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