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