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