Merge branch 'vendor/LIBARCHIVE'
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_isic.c
1 /*
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_isic.c - global isic stuff
28  *      ==============================
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_isic.c,v 1.4.2.1 2001/08/10 14:08:38 obrien Exp $
31  * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_isic.c,v 1.6 2006/12/22 23:44:56 swildner Exp $
32  *
33  *      last edit-date: [Wed Jan 24 09:29:42 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_isic.h"
38 #include "opt_i4b.h"
39
40 #if NISIC > 0
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/socket.h>
45 #include <net/if.h>
46
47 #include <net/i4b/include/machine/i4b_debug.h>
48 #include <net/i4b/include/machine/i4b_ioctl.h>
49 #include <net/i4b/include/machine/i4b_trace.h>
50
51 #include "../i4b_l1.h"
52
53 #include "i4b_isic.h"
54 #include "i4b_isic_ext.h"
55 #include "i4b_ipac.h"
56 #include "i4b_isac.h"
57 #include "i4b_hscx.h"
58
59 #include "../../include/i4b_global.h"
60
61 static char *ISACversion[] = {
62         "2085 Version A1/A2 or 2086/2186 Version 1.1",
63         "2085 Version B1",
64         "2085 Version B2",
65         "2085 Version V2.3 (B3)",
66         "Unknown Version"
67 };
68
69 static char *HSCXversion[] = {
70         "82525 Version A1",
71         "Unknown (0x01)",
72         "82525 Version A2",
73         "Unknown (0x03)",
74         "82525 Version A3",
75         "82525 or 21525 Version 2.1",
76         "Unknown Version"
77 };
78
79 /* jump table for multiplex routines */
80 struct i4b_l1mux_func isic_l1mux_func = {
81         isic_ret_linktab,
82         isic_set_linktab,
83         isic_mph_command_req,
84         isic_ph_data_req,
85         isic_ph_activate_req,
86 };
87
88 /*---------------------------------------------------------------------------*
89  *      isic - device driver interrupt routine
90  *---------------------------------------------------------------------------*/
91 void
92 isicintr(struct l1_softc *sc)
93 {
94         if(sc->sc_ipac == 0)    /* HSCX/ISAC interupt routine */
95         {
96                 u_char was_hscx_irq = 0;
97                 u_char was_isac_irq = 0;
98
99                 u_char hscx_irq_stat;
100                 u_char isac_irq_stat;
101
102                 for(;;)
103                 {
104                         /* get hscx irq status from hscx b ista */
105                         hscx_irq_stat =
106                             HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
107         
108                         /* get isac irq status */
109                         isac_irq_stat = ISAC_READ(I_ISTA);
110         
111                         /* do as long as there are pending irqs in the chips */
112                         if(!hscx_irq_stat && !isac_irq_stat)
113                                 break;
114         
115                         if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
116                                             HSCX_ISTA_RSC | HSCX_ISTA_XPR |
117                                             HSCX_ISTA_TIN | HSCX_ISTA_EXB))
118                         {
119                                 isic_hscx_irq(sc, hscx_irq_stat,
120                                                 HSCX_CH_B,
121                                                 hscx_irq_stat & HSCX_ISTA_EXB);
122                                 was_hscx_irq = 1;                       
123                         }
124                         
125                         if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
126                         {
127                                 isic_hscx_irq(sc,
128                                     HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
129                                     HSCX_CH_A,
130                                     hscx_irq_stat & HSCX_ISTA_EXA);
131                                 was_hscx_irq = 1;
132                         }
133         
134                         if(isac_irq_stat)
135                         {
136                                 isic_isac_irq(sc, isac_irq_stat); /* isac handler */
137                                 was_isac_irq = 1;
138                         }
139                 }
140
141                 HSCX_WRITE(0, H_MASK, 0xff);
142                 ISAC_WRITE(I_MASK, 0xff);
143                 HSCX_WRITE(1, H_MASK, 0xff);
144         
145 #ifdef ELSA_QS1ISA
146                 DELAY(80);
147                 
148                 if((sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA) && (sc->clearirq))
149                 {
150                         sc->clearirq(sc);
151                 }
152 #else
153                 DELAY(100);
154 #endif  
155         
156                 HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
157                 ISAC_WRITE(I_MASK, ISAC_IMASK);
158                 HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
159         }
160         else    /* IPAC interrupt routine */
161         {
162                 u_char ipac_irq_stat;
163                 u_char was_ipac_irq = 0;
164
165                 for(;;)
166                 {
167                         /* get global irq status */
168                         
169                         ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
170                         
171                         /* check hscx a */
172                         
173                         if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
174                         {
175                                 /* HSCX A interrupt */
176                                 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
177                                                 HSCX_CH_A,
178                                                 ipac_irq_stat & IPAC_ISTA_EXA);
179                                 was_ipac_irq = 1;                       
180                         }
181                         if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
182                         {
183                                 /* HSCX B interrupt */
184                                 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
185                                                 HSCX_CH_B,
186                                                 ipac_irq_stat & IPAC_ISTA_EXB);
187                                 was_ipac_irq = 1;                       
188                         }
189                         if(ipac_irq_stat & IPAC_ISTA_ICD)
190                         {
191                                 /* ISAC interrupt */
192                                 isic_isac_irq(sc, ISAC_READ(I_ISTA));
193                                 was_ipac_irq = 1;
194                         }
195                         if(ipac_irq_stat & IPAC_ISTA_EXD)
196                         {
197                                 /* force ISAC interrupt handling */
198                                 isic_isac_irq(sc, ISAC_ISTA_EXI);
199                                 was_ipac_irq = 1;
200                         }
201         
202                         /* do as long as there are pending irqs in the chip */
203                         if(!ipac_irq_stat)
204                                 break;
205                 }
206
207                 IPAC_WRITE(IPAC_MASK, 0xff);
208                 DELAY(50);
209                 IPAC_WRITE(IPAC_MASK, 0xc0);
210         }               
211 }
212
213 /*---------------------------------------------------------------------------*
214  *      isic_recover - try to recover from irq lockup
215  *---------------------------------------------------------------------------*/
216 void
217 isic_recover(struct l1_softc *sc)
218 {
219         u_char byte;
220         
221         /* get hscx irq status from hscx b ista */
222
223         byte = HSCX_READ(HSCX_CH_B, H_ISTA);
224
225         NDBGL1(L1_ERROR, "HSCX B: ISTA = 0x%x", byte);
226
227         if(byte & HSCX_ISTA_ICA)
228                 NDBGL1(L1_ERROR, "HSCX A: ISTA = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA));
229
230         if(byte & HSCX_ISTA_EXB)
231                 NDBGL1(L1_ERROR, "HSCX B: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR));
232
233         if(byte & HSCX_ISTA_EXA)
234                 NDBGL1(L1_ERROR, "HSCX A: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR));
235
236         /* get isac irq status */
237
238         byte = ISAC_READ(I_ISTA);
239
240         NDBGL1(L1_ERROR, "  ISAC: ISTA = 0x%x", byte);
241         
242         if(byte & ISAC_ISTA_EXI)
243                 NDBGL1(L1_ERROR, "  ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR));
244
245         if(byte & ISAC_ISTA_CISQ)
246         {
247                 byte = ISAC_READ(I_CIRR);
248         
249                 NDBGL1(L1_ERROR, "  ISAC: CISQ = 0x%x", byte);
250                 
251                 if(byte & ISAC_CIRR_SQC)
252                         NDBGL1(L1_ERROR, "  ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR));
253         }
254
255         NDBGL1(L1_ERROR, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK);
256         NDBGL1(L1_ERROR, "HSCX A: IMASK = 0x%x", HSCX_A_IMASK);
257
258         HSCX_WRITE(0, H_MASK, 0xff);
259         HSCX_WRITE(1, H_MASK, 0xff);
260         DELAY(100);     
261         HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
262         HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
263         DELAY(100);
264
265         NDBGL1(L1_ERROR, "  ISAC: IMASK = 0x%x", ISAC_IMASK);
266
267         ISAC_WRITE(I_MASK, 0xff);       
268         DELAY(100);
269         ISAC_WRITE(I_MASK, ISAC_IMASK);
270 }
271
272 /*---------------------------------------------------------------------------*
273  *      isic_attach_common - common attach routine for all busses
274  *---------------------------------------------------------------------------*/
275 int
276 isic_attach_common(device_t dev)
277 {
278         char *drvid = NULL;
279         int unit = device_get_unit(dev);
280         struct l1_softc *sc = &l1_sc[unit];
281         
282         sc->sc_unit = unit;
283         
284         sc->sc_isac_version = 0;
285         sc->sc_hscx_version = 0;
286
287         if(sc->sc_ipac)
288         {
289                 sc->sc_ipac_version = IPAC_READ(IPAC_ID);
290
291                 switch(sc->sc_ipac_version)
292                 {
293                         case IPAC_V11:
294                         case IPAC_V12:
295                                 break;
296
297                         default:
298                                 kprintf("isic%d: Error, IPAC version %d unknown!\n",
299                                         unit, sc->sc_ipac_version);
300                                 return(0);
301                                 break;
302                 }
303         }
304         else
305         {
306                 sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
307         
308                 switch(sc->sc_isac_version)
309                 {
310                         case ISAC_VA:
311                         case ISAC_VB1:
312                         case ISAC_VB2:
313                         case ISAC_VB3:
314                                 break;
315         
316                         default:
317                                 kprintf("isic%d: Error, ISAC version %d unknown!\n",
318                                         unit, sc->sc_isac_version);
319                                 return ENXIO;
320                                 break;
321                 }
322
323                 sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
324
325                 switch(sc->sc_hscx_version)
326                 {
327                         case HSCX_VA1:
328                         case HSCX_VA2:
329                         case HSCX_VA3:
330                         case HSCX_V21:
331                                 break;
332                                 
333                         default:
334                                 kprintf("isic%d: Error, HSCX version %d unknown!\n",
335                                         unit, sc->sc_hscx_version);
336                                 return ENXIO;
337                                 break;
338                 }
339         }
340         
341         isic_isac_init(sc);             /* ISAC setup */
342
343         /* HSCX setup */
344
345         isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
346         
347         isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
348
349         isic_init_linktab(sc);          /* setup linktab */
350
351         sc->sc_trace = TRACE_OFF;       /* set trace level */
352
353         sc->sc_state = ISAC_IDLE;       /* set state */
354
355         sc->sc_ibuf = NULL;             /* input buffering */
356         sc->sc_ib = NULL;
357         sc->sc_ilen = 0;
358
359         sc->sc_obuf = NULL;             /* output buffering */
360         sc->sc_op = NULL;
361         sc->sc_ol = 0;
362         sc->sc_freeflag = 0;
363
364         sc->sc_obuf2 = NULL;            /* second output buffer */
365         sc->sc_freeflag2 = 0;
366
367         /* timer setup */
368         
369         callout_init(&sc->sc_T3_timeout);
370         callout_init(&sc->sc_T4_timeout);       
371         
372         /* init higher protocol layers */
373         
374         i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &isic_l1mux_func);
375
376         /* announce manufacturer and card type for ISA cards */
377         
378         switch(sc->sc_cardtyp)
379         {
380                 case CARD_TYPEP_8:
381                         drvid = "Teles S0/8 (or compatible)";
382                         break;
383
384                 case CARD_TYPEP_16:
385                         drvid = "Teles S0/16 (or compatible)";
386                         break;
387
388                 case CARD_TYPEP_16_3:
389                         drvid = "Teles S0/16.3";
390                         break;
391
392                 case CARD_TYPEP_AVMA1:
393                         drvid = "AVM A1 or Fritz!Card Classic";
394                         break;
395
396                 case CARD_TYPEP_PCFRITZ:
397                         drvid = "AVM Fritz!Card PCMCIA";
398                         break;
399
400                 case CARD_TYPEP_USRTA:
401                         drvid = "USRobotics Sportster ISDN TA intern";
402                         break;
403
404                 case CARD_TYPEP_ITKIX1:
405                         drvid = "ITK ix1 micro";
406                         break;
407
408                 case CARD_TYPEP_PCC16:
409                         drvid = "ELSA MicroLink ISDN/PCC-16";
410                         break;
411
412                 default:
413                         drvid = NULL;   /* pnp/pci cards announce themselves */
414                         break;
415         }
416
417         if(drvid)
418                 kprintf("isic%d: %s\n", unit, drvid);
419         
420         if(bootverbose)
421         {
422                 /* announce chip versions */
423                 
424                 if(sc->sc_ipac)
425                 {
426                         if(sc->sc_ipac_version == IPAC_V11)
427                                 kprintf("isic%d: IPAC PSB2115 Version 1.1\n", unit);
428                         else
429                                 kprintf("isic%d: IPAC PSB2115 Version 1.2\n", unit);
430                 }
431                 else
432                 {
433                         kprintf("isic%d: ISAC %s (IOM-%c)\n",
434                                 unit,
435                                 ISACversion[sc->sc_isac_version],
436                                 sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
437
438                         kprintf("isic%d: HSCX %s\n",
439                                 unit,
440                                 HSCXversion[sc->sc_hscx_version]);
441                 }
442         }
443         return 0;
444 }
445
446 /*---------------------------------------------------------------------------*
447  *      isic_detach_common - common detach routine for all busses
448  *---------------------------------------------------------------------------*/
449 void
450 isic_detach_common(device_t dev)
451 {
452         struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
453         int i;
454
455         sc->sc_cardtyp = CARD_TYPEP_UNK;
456
457         /* free interrupt resources */
458         
459         if(sc->sc_resources.irq)
460         {
461                 /* tear down interupt handler */
462                 bus_teardown_intr(dev, sc->sc_resources.irq,
463                                         (void(*)(void *))isicintr);
464
465                 /* free irq */
466                 bus_release_resource(dev, SYS_RES_IRQ,
467                                         sc->sc_resources.irq_rid,
468                                         sc->sc_resources.irq);
469                 sc->sc_resources.irq_rid = 0;
470                 sc->sc_resources.irq = 0;
471         }
472
473         /* free memory resource */
474         
475         if(sc->sc_resources.mem)
476         {
477                 bus_release_resource(dev,SYS_RES_MEMORY,
478                                         sc->sc_resources.mem_rid,
479                                         sc->sc_resources.mem);
480                 sc->sc_resources.mem_rid = 0;
481                 sc->sc_resources.mem = 0;
482         }
483
484         /* free iobases */
485
486         for(i=0; i < INFO_IO_BASES ; i++)
487         {
488                 if(sc->sc_resources.io_base[i])
489                 {
490                         bus_release_resource(dev, SYS_RES_IOPORT,
491                                                 sc->sc_resources.io_rid[i],
492                                                 sc->sc_resources.io_base[i]);
493                         sc->sc_resources.io_rid[i] = 0;
494                         sc->sc_resources.io_base[i] = 0;                        
495                 }
496         }
497 }
498
499 #endif /* NISIC > 0 */
500