1 /* ISDN4BSD code */
2 /* $NetBSD: isacsx.c,v 1.2 2003/05/08 21:16:19 martin Exp $ */
3 /*
4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
5 * Copyright (c) 2001 Gary Jennejohn. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 *---------------------------------------------------------------------------
29 *
30 * i4b_ifpi2_isac.c - i4b Fritz PCI Version 2 ISACSX handler
31 * --------------------------------------------
32 *
33 * $Id: isacsx.c,v 1.3 2003/09/01 22:37:13 tg Stab $
34 *
35 * $FreeBSD: src/sys/i4b/layer1/ifpi2/i4b_ifpi2_isacsx.c,v 1.3 2002/09/02 00:52:07 brooks Exp $
36 *
37 *
38 *---------------------------------------------------------------------------*/
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: isacsx.c,v 1.2 2003/05/08 21:16:19 martin Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <sys/device.h>
48
49 #include <net/if.h>
50
51 #include <sys/timeout.h>
52
53 #ifdef __FreeBSD__
54 #include <machine/i4b_debug.h>
55 #include <machine/i4b_ioctl.h>
56 #include <machine/i4b_trace.h>
57
58 #include <i4b/layer1/i4b_l1.h>
59
60 #include <i4b/layer1/isic/i4b_isic.h>
61 #include <i4b/layer1/isic/i4b_hscx.h>
62
63 #include <i4b/layer1/ifpi2/i4b_ifpi2_ext.h>
64 #include <i4b/layer1/ifpi2/i4b_ifpi2_isacsx.h>
65
66 #include <i4b/include/i4b_global.h>
67 #include <i4b/include/i4b_mbuf.h>
68 #else
69 #include <machine/bus.h>
70
71 #include <netisdn/i4b_debug.h>
72 #include <netisdn/i4b_ioctl.h>
73 #include <netisdn/i4b_trace.h>
74
75 #include <netisdn/i4b_global.h>
76 #include <netisdn/i4b_l2.h>
77 #include <netisdn/i4b_l1l2.h>
78 #include <netisdn/i4b_mbuf.h>
79
80 #include <dev/ic/isacsx.h>
81 #include <dev/ic/isic_l1.h>
82 #include <dev/ic/hscx.h>
83
84 #endif
85
86 static u_char isic_isacsx_exir_hdlr(register struct isic_softc *sc, u_char exir);
87 static void isic_isacsx_ind_hdlr(register struct isic_softc *sc, int ind);
88
89 /* the ISACSX has 2 mask registers of interest - cannot use ISAC_IMASK */
90 unsigned char isacsx_imaskd;
91 unsigned char isacsx_imask;
92
93 /*---------------------------------------------------------------------------*
94 * ISACSX interrupt service routine
95 *---------------------------------------------------------------------------*/
96 void
isic_isacsx_irq(struct isic_softc * sc,int ista)97 isic_isacsx_irq(struct isic_softc *sc, int ista)
98 {
99 register u_char c = 0;
100 register u_char istad = 0;
101
102 NDBGL1(L1_F_MSG, "%s: ista = 0x%02x", sc->sc_dev.dv_xname, ista);
103
104 /* was it an HDLC interrupt ? */
105 if (ista & ISACSX_ISTA_ICD)
106 {
107 istad = ISAC_READ(I_ISTAD);
108 NDBGL1(L1_F_MSG, "%s: istad = 0x%02x", sc->sc_dev.dv_xname, istad);
109
110 if(istad & (ISACSX_ISTAD_RFO|ISACSX_ISTAD_XMR|ISACSX_ISTAD_XDU))
111 {
112 /* not really EXIR, but very similar */
113 c |= isic_isacsx_exir_hdlr(sc, istad);
114 }
115 }
116
117 if(istad & ISACSX_ISTAD_RME) /* receive message end */
118 {
119 register int rest;
120 u_char rsta;
121
122 /* get rx status register */
123
124 rsta = ISAC_READ(I_RSTAD);
125
126 /* Check for Frame and CRC valid */
127 if((rsta & ISACSX_RSTAD_MASK) != (ISACSX_RSTAD_VFR|ISACSX_RSTAD_CRC))
128 {
129 int error = 0;
130
131 if(!(rsta & ISACSX_RSTAD_VFR)) /* VFR error */
132 {
133 error++;
134 NDBGL1(L1_I_ERR, "%s: Frame not valid error", sc->sc_dev.dv_xname);
135 }
136
137 if(!(rsta & ISACSX_RSTAD_CRC)) /* CRC error */
138 {
139 error++;
140 NDBGL1(L1_I_ERR, "%s: CRC error", sc->sc_dev.dv_xname);
141 }
142
143 if(rsta & ISACSX_RSTAD_RDO) /* ReceiveDataOverflow */
144 {
145 error++;
146 NDBGL1(L1_I_ERR, "%s: Data Overrun error", sc->sc_dev.dv_xname);
147 }
148
149 if(rsta & ISACSX_RSTAD_RAB) /* ReceiveABorted */
150 {
151 error++;
152 NDBGL1(L1_I_ERR, "%s: Receive Aborted error", sc->sc_dev.dv_xname);
153 }
154
155 if(error == 0)
156 NDBGL1(L1_I_ERR, "%s: RME unknown error, RSTAD = 0x%02x!", sc->sc_dev.dv_xname, rsta);
157
158 i4b_Dfreembuf(sc->sc_ibuf);
159
160 c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;
161
162 sc->sc_ibuf = NULL;
163 sc->sc_ib = NULL;
164 sc->sc_ilen = 0;
165
166 ISAC_WRITE(I_CMDRD, ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES);
167
168 return;
169 }
170
171 rest = (ISAC_READ(I_RBCLD) & (ISACSX_FIFO_LEN-1));
172
173 if(rest == 0)
174 rest = ISACSX_FIFO_LEN;
175
176 if(sc->sc_ibuf == NULL)
177 {
178 if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
179 sc->sc_ib = sc->sc_ibuf->m_data;
180 else
181 panic("isic_isacsx_irq: RME, i4b_Dgetmbuf returns NULL!\n");
182 sc->sc_ilen = 0;
183 }
184
185 if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
186 {
187 ISAC_RDFIFO(sc->sc_ib, rest);
188 /* the last byte contains status, strip it */
189 sc->sc_ilen += rest - 1;
190
191 sc->sc_ibuf->m_pkthdr.len =
192 sc->sc_ibuf->m_len = sc->sc_ilen;
193
194 if(sc->sc_trace & TRACE_D_RX)
195 {
196 i4b_trace_hdr hdr;
197
198 memset(&hdr, 0, sizeof hdr);
199 hdr.type = TRC_CH_D;
200 hdr.dir = FROM_NT;
201 hdr.count = ++sc->sc_trace_dcount;
202 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
203 }
204
205 c |= ISACSX_CMDRD_RMC;
206
207 if(sc->sc_intr_valid == ISIC_INTR_VALID &&
208 (((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S))
209 {
210 isdn_layer2_data_ind(&sc->sc_l2, sc->sc_l3token, sc->sc_ibuf);
211 }
212 else
213 {
214 i4b_Dfreembuf(sc->sc_ibuf);
215 }
216 }
217 else
218 {
219 NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
220 i4b_Dfreembuf(sc->sc_ibuf);
221 c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;
222 }
223
224 sc->sc_ibuf = NULL;
225 sc->sc_ib = NULL;
226 sc->sc_ilen = 0;
227 }
228
229 if(istad & ISACSX_ISTAD_RPF) /* receive fifo full */
230 {
231 if(sc->sc_ibuf == NULL)
232 {
233 if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
234 sc->sc_ib= sc->sc_ibuf->m_data;
235 else
236 panic("isic_isacsx_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
237 sc->sc_ilen = 0;
238 }
239
240 if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISACSX_FIFO_LEN))
241 {
242 ISAC_RDFIFO(sc->sc_ib, ISACSX_FIFO_LEN);
243 sc->sc_ilen += ISACSX_FIFO_LEN;
244 sc->sc_ib += ISACSX_FIFO_LEN;
245 c |= ISACSX_CMDRD_RMC;
246 }
247 else
248 {
249 NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
250 i4b_Dfreembuf(sc->sc_ibuf);
251 sc->sc_ibuf = NULL;
252 sc->sc_ib = NULL;
253 sc->sc_ilen = 0;
254 c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;
255 }
256 }
257
258 if(istad & ISACSX_ISTAD_XPR) /* transmit fifo empty (XPR bit set) */
259 {
260 if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
261 {
262 sc->sc_freeflag = sc->sc_freeflag2;
263 sc->sc_obuf = sc->sc_obuf2;
264 sc->sc_op = sc->sc_obuf->m_data;
265 sc->sc_ol = sc->sc_obuf->m_len;
266 sc->sc_obuf2 = NULL;
267 #ifdef NOTDEF
268 printf("ob2=%x, op=%x, ol=%d, f=%d #",
269 sc->sc_obuf,
270 sc->sc_op,
271 sc->sc_ol,
272 sc->sc_state);
273 #endif
274 }
275 else
276 {
277 #ifdef NOTDEF
278 printf("ob=%x, op=%x, ol=%d, f=%d #",
279 sc->sc_obuf,
280 sc->sc_op,
281 sc->sc_ol,
282 sc->sc_state);
283 #endif
284 }
285
286 if(sc->sc_obuf)
287 {
288 ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISACSX_FIFO_LEN));
289
290 if(sc->sc_ol > ISACSX_FIFO_LEN) /* length > 32 ? */
291 {
292 sc->sc_op += ISACSX_FIFO_LEN; /* bufferptr+32 */
293 sc->sc_ol -= ISACSX_FIFO_LEN; /* length - 32 */
294 c |= ISACSX_CMDRD_XTF; /* set XTF bit */
295 }
296 else
297 {
298 if(sc->sc_freeflag)
299 {
300 i4b_Dfreembuf(sc->sc_obuf);
301 sc->sc_freeflag = 0;
302 }
303 sc->sc_obuf = NULL;
304 sc->sc_op = NULL;
305 sc->sc_ol = 0;
306
307 c |= ISACSX_CMDRD_XTF | ISACSX_CMDRD_XME;
308 }
309 }
310 else
311 {
312 sc->sc_state &= ~ISAC_TX_ACTIVE;
313 }
314 }
315
316 if(ista & ISACSX_ISTA_CIC) /* channel status change CISQ */
317 {
318 register u_char ci;
319
320 /* get command/indication rx register*/
321
322 ci = ISAC_READ(I_CIR0);
323
324 /* C/I code change IRQ (flag already cleared by CIR0 read) */
325
326 if(ci & ISACSX_CIR0_CIC0)
327 isic_isacsx_ind_hdlr(sc, (ci >> 4) & 0xf);
328 }
329
330 if(c)
331 {
332 ISAC_WRITE(I_CMDRD, c);
333 }
334 }
335
336 /*---------------------------------------------------------------------------*
337 * ISACSX L1 Extended IRQ handler
338 *---------------------------------------------------------------------------*/
339 static u_char
isic_isacsx_exir_hdlr(register struct isic_softc * sc,u_char exir)340 isic_isacsx_exir_hdlr(register struct isic_softc *sc, u_char exir)
341 {
342 u_char c = 0;
343
344 if(exir & ISACSX_ISTAD_XMR)
345 {
346 NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
347
348 c |= ISACSX_CMDRD_XRES;
349 }
350
351 if(exir & ISACSX_ISTAD_XDU)
352 {
353 NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
354
355 c |= ISACSX_CMDRD_XRES;
356 }
357
358 if(exir & ISACSX_ISTAD_RFO)
359 {
360 NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
361
362 c |= ISACSX_CMDRD_RMC;
363 }
364
365 #if 0 /* all blocked per default */
366 if(exir & ISACSX_EXIR_SOV)
367 {
368 NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
369 }
370
371 if(exir & ISACSX_EXIR_MOS)
372 {
373 NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
374 }
375
376 if(exir & ISACSX_EXIR_SAW)
377 {
378 /* cannot happen, STCR:TSF is set to 0 */
379
380 NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
381 }
382
383 if(exir & ISACSX_EXIR_WOV)
384 {
385 /* cannot happen, STCR:TSF is set to 0 */
386
387 NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
388 }
389 #endif
390
391 return(c);
392 }
393
394 /*---------------------------------------------------------------------------*
395 * ISACSX L1 Indication handler
396 *---------------------------------------------------------------------------*/
397 static void
isic_isacsx_ind_hdlr(register struct isic_softc * sc,int ind)398 isic_isacsx_ind_hdlr(register struct isic_softc *sc, int ind)
399 {
400 register int event;
401
402 switch(ind)
403 {
404 case ISACSX_CIR0_IAI8:
405 NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc));
406 if(sc->sc_bustyp == BUS_TYPE_IOM2)
407 isic_isacsx_l1_cmd(sc, CMD_AR8);
408 event = EV_INFO48;
409 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
410 break;
411
412 case ISACSX_CIR0_IAI10:
413 NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc));
414 if(sc->sc_bustyp == BUS_TYPE_IOM2)
415 isic_isacsx_l1_cmd(sc, CMD_AR10);
416 event = EV_INFO410;
417 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
418 break;
419
420 case ISACSX_CIR0_IRSY:
421 NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc));
422 event = EV_RSY;
423 break;
424
425 case ISACSX_CIR0_IPU:
426 NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc));
427 event = EV_PU;
428 break;
429
430 case ISACSX_CIR0_IDR:
431 NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc));
432 isic_isacsx_l1_cmd(sc, CMD_DIU);
433 event = EV_DR;
434 break;
435
436 case ISACSX_CIR0_IDID:
437 NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc));
438 event = EV_INFO0;
439 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE);
440 break;
441
442 case ISACSX_CIR0_IDIS:
443 NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc));
444 event = EV_DIS;
445 break;
446
447 case ISACSX_CIR0_IEI:
448 NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc));
449 isic_isacsx_l1_cmd(sc, CMD_DIU);
450 event = EV_EI;
451 break;
452
453 case ISACSX_CIR0_IARD:
454 NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc));
455 event = EV_INFO2;
456 break;
457
458 case ISACSX_CIR0_ITI:
459 NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc));
460 event = EV_INFO0;
461 break;
462
463 case ISACSX_CIR0_IATI:
464 NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc));
465 event = EV_INFO0;
466 break;
467
468 case ISACSX_CIR0_ISD:
469 NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc));
470 event = EV_INFO0;
471 break;
472
473 default:
474 NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc));
475 event = EV_INFO0;
476 break;
477 }
478 isic_next_state(sc, event);
479 }
480
481 /*---------------------------------------------------------------------------*
482 * execute a layer 1 command
483 *---------------------------------------------------------------------------*/
484 void
isic_isacsx_l1_cmd(struct isic_softc * sc,int command)485 isic_isacsx_l1_cmd(struct isic_softc *sc, int command)
486 {
487 u_char cmd;
488
489 #ifdef I4B_SMP_WORKAROUND
490
491 /* XXXXXXXXXXXXXXXXXXX */
492
493 /*
494 * patch from Wolfgang Helbig:
495 *
496 * Here is a patch that makes i4b work on an SMP:
497 * The card (TELES 16.3) didn't interrupt on an SMP machine.
498 * This is a gross workaround, but anyway it works *and* provides
499 * some information as how to finally fix this problem.
500 */
501
502 HSCX_WRITE(0, H_MASK, 0xff);
503 HSCX_WRITE(1, H_MASK, 0xff);
504 ISAC_WRITE(I_MASKD, 0xff);
505 ISAC_WRITE(I_MASK, 0xff);
506 DELAY(100);
507 HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
508 HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
509 ISAC_WRITE(I_MASKD, isacsx_imaskd);
510 ISAC_WRITE(I_MASK, isacsx_imask);
511
512 /* XXXXXXXXXXXXXXXXXXX */
513
514 #endif /* I4B_SMP_WORKAROUND */
515
516 if(command < 0 || command > CMD_ILL)
517 {
518 NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc));
519 return;
520 }
521
522 cmd = ISACSX_CIX0_LOW;
523
524 switch(command)
525 {
526 case CMD_TIM:
527 NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc));
528 cmd |= (ISACSX_CIX0_CTIM << 4);
529 break;
530
531 case CMD_RS:
532 NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc));
533 cmd |= (ISACSX_CIX0_CRS << 4);
534 break;
535
536 case CMD_AR8:
537 NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc));
538 cmd |= (ISACSX_CIX0_CAR8 << 4);
539 break;
540
541 case CMD_AR10:
542 NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc));
543 cmd |= (ISACSX_CIX0_CAR10 << 4);
544 break;
545
546 case CMD_DIU:
547 NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc));
548 cmd |= (ISACSX_CIX0_CDIU << 4);
549 break;
550 }
551 ISAC_WRITE(I_CIX0, cmd);
552 }
553
554 /*---------------------------------------------------------------------------*
555 * L1 ISACSX initialization
556 *---------------------------------------------------------------------------*/
557 int
isic_isacsx_init(struct isic_softc * sc)558 isic_isacsx_init(struct isic_softc *sc)
559 {
560 isacsx_imaskd = 0xff; /* disable all irqs */
561 isacsx_imask = 0xff; /* disable all irqs */
562
563 ISAC_WRITE(I_MASKD, isacsx_imaskd);
564 ISAC_WRITE(I_MASK, isacsx_imask);
565
566 /* the ISACSX only runs in IOM-2 mode */
567 NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
568
569 /* TR_CONF0: Transceiver Configuration Register 0:
570 * DIS_TR - transceiver enabled
571 * EN_ICV - normal operation
572 * EXLP - no external loop
573 * LDD - automatic clock generation
574 */
575 ISAC_WRITE(I_WTR_CONF0, 0);
576
577 /* TR_CONF2: Transceiver Configuration Register 1:
578 * DIS_TX - transmitter enabled
579 * PDS - phase deviation 2 S-bits
580 * RLP - remote line loop open
581 */
582 ISAC_WRITE(I_WTR_CONF2, 0);
583
584 /* MODED: Mode Register:
585 * MDSx - transparent mode 0
586 * TMD - timer mode = external
587 * RAC - Receiver enabled
588 * DIMx - digital i/f mode
589 */
590 ISAC_WRITE(I_WMODED, ISACSX_MODED_MDS2|ISACSX_MODED_MDS1|ISACSX_MODED_RAC|ISACSX_MODED_DIM0);
591
592 /* enabled interrupts:
593 * ===================
594 * RME - receive message end
595 * RPF - receive pool full
596 * RPO - receive pool overflow
597 * XPR - transmit pool ready
598 * XMR - transmit message repeat
599 * XDU - transmit data underrun
600 */
601
602 isacsx_imaskd = ISACSX_MASKD_LOW;
603 ISAC_WRITE(I_MASKD, isacsx_imaskd);
604
605 /* enabled interrupts:
606 * ===================
607 * ICD - HDLC interrupt from D-channel
608 * CIC - C/I channel change
609 */
610
611 isacsx_imask = ~(ISACSX_MASK_ICD | ISACSX_MASK_CIC);
612
613 ISAC_WRITE(I_MASK, isacsx_imask);
614
615 return(0);
616 }
617
618 /*---------------------------------------------------------------------------*
619 * L1 ISACSX disable interrupts
620 *---------------------------------------------------------------------------*/
621 void
isic_isacsx_disable_intr(struct isic_softc * sc)622 isic_isacsx_disable_intr(struct isic_softc *sc)
623 {
624 ISAC_WRITE(I_WMODED, ISACSX_MODED_MDS2|ISACSX_MODED_MDS1|ISACSX_MODED_DIM0);
625 isacsx_imaskd = 0xff; /* disable all irqs */
626 isacsx_imask = 0xff; /* disable all irqs */
627
628 ISAC_WRITE(I_MASKD, isacsx_imaskd);
629 ISAC_WRITE(I_MASK, isacsx_imask);
630 }
631
632 /*---------------------------------------------------------------------------*
633 * ISACSX recover - try to recover from irq lockup
634 *---------------------------------------------------------------------------*/
635 void
isic_isacsx_recover(struct isic_softc * sc)636 isic_isacsx_recover(struct isic_softc *sc)
637 {
638 u_char byte, istad;
639
640
641 /*
642 * XXX
643 * Leo: Unknown if this function does anything good... At least it
644 * prints some stuff that might be helpful.
645 */
646
647 printf("%s: isic_isacsx_recover\n", sc->sc_dev.dv_xname);
648 /* get isac irq status */
649
650 byte = ISAC_READ(I_ISTAD);
651
652 NDBGL1(L1_ERROR, " ISAC: ISTAD = 0x%x", byte);
653
654 if(byte & ISACSX_ISTA_ICD) {
655 istad = ISAC_READ(I_ISTAD);
656 NDBGL1(L1_ERROR, " ISACSX: istad = 0x%02x", istad);
657 }
658
659 if(byte & ISACSX_ISTA_CIC)
660 {
661 byte = ISAC_READ(I_CIR0);
662
663 NDBGL1(L1_ERROR, " ISACSX: CIR0 = 0x%x", byte);
664 }
665
666 NDBGL1(L1_ERROR, " ISACSX: IMASKD/IMASK = 0x%02x/%02x", isacsx_imaskd,
667 isacsx_imask);
668
669 ISAC_WRITE(I_MASKD, 0xff);
670 ISAC_WRITE(I_MASK, 0xff);
671 DELAY(100);
672 ISAC_WRITE(I_MASKD, isacsx_imaskd);
673 ISAC_WRITE(I_MASK, isacsx_imask);
674 }
675