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