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