Initial import from FreeBSD RELENG_4:
[games.git] / sys / net / i4b / layer1 / isic / i4b_hscx.c
1 /*
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b - Siemens HSCX chip (B-channel) handling
28  *      --------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_hscx.c,v 1.7.2.1 2001/08/10 14:08:38 obrien Exp $
31  *
32  *      last edit-date: [Wed Jan 24 09:09:42 2001]
33  *
34  *---------------------------------------------------------------------------*/
35
36 #include "isic.h"
37
38 #if NISIC > 0
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44
45 #include <net/if.h>
46
47 #include <machine/i4b_debug.h>
48 #include <machine/i4b_ioctl.h>
49 #include <machine/i4b_trace.h>
50
51 #include <i4b/layer1/isic/i4b_isic.h>
52 #include <i4b/layer1/isic/i4b_hscx.h>
53
54 #include <i4b/layer1/i4b_l1.h>
55
56 #include <i4b/include/i4b_global.h>
57 #include <i4b/include/i4b_mbuf.h>
58
59 /*---------------------------------------------------------------------------*
60  *      HSCX IRQ Handler
61  *---------------------------------------------------------------------------*/
62 void
63 isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq)
64 {
65         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
66         u_char exir = 0;
67         int activity = -1;
68         u_char cmd = 0;
69
70         NDBGL1(L1_H_IRQ, "%#x", ista);
71
72         if(ex_irq)
73         {
74                 /* get channel extended irq reg */
75
76                 exir = HSCX_READ(h_chan, H_EXIR);
77
78                 if(exir & HSCX_EXIR_RFO)
79                 {
80                         chan->stat_RFO++;
81                         NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
82                 }
83
84                 if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
85                 {
86                         chan->stat_XDU++;                       
87                         NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
88                         isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
89
90                         if (chan->out_mbuf_head != NULL)  /* don't continue to transmit this buffer */
91                         {
92                                 i4b_Bfreembuf(chan->out_mbuf_head);
93                                 chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
94                         }
95                 }
96
97         }
98
99         /* rx message end, end of frame */
100         
101         if(ista & HSCX_ISTA_RME)
102         {
103                 register int fifo_data_len;
104                 u_char rsta;            
105                 int error = 0;
106
107                 rsta = HSCX_READ(h_chan, H_RSTA);
108
109                 if((rsta & 0xf0) != 0xa0)
110                 {
111                         if((rsta & HSCX_RSTA_VFR) == 0)
112                         {
113                                 chan->stat_VFR++;
114                                 cmd |= (HSCX_CMDR_RHR);
115                                 NDBGL1(L1_H_XFRERR, "received invalid Frame");
116                                 error++;
117                         }
118         
119                         if(rsta & HSCX_RSTA_RDO)
120                         {
121                                 chan->stat_RDO++;
122                                 NDBGL1(L1_H_XFRERR, "receive data overflow");
123                                 error++;                                
124                         }
125                         
126                         if((rsta & HSCX_RSTA_CRC) == 0)
127                         {
128                                 chan->stat_CRC++;
129                                 cmd |= (HSCX_CMDR_RHR);
130                                 NDBGL1(L1_H_XFRERR, "CRC check failed");
131                                 error++;
132                         }
133                         
134                         if(rsta & HSCX_RSTA_RAB)
135                         {
136                                 chan->stat_RAB++;                               
137                                 NDBGL1(L1_H_XFRERR, "Receive message aborted");
138                                 error++;
139                         }
140                 }
141
142                 fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
143                                                 ((sc->sc_bfifolen)-1));
144                 
145                 if(fifo_data_len == 0)
146                         fifo_data_len = sc->sc_bfifolen;
147
148                 /* all error conditions checked, now decide and take action */
149                 
150                 if(error == 0)
151                 {
152                         if(chan->in_mbuf == NULL)
153                         {
154                                 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
155                                         panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
156                                 chan->in_cbptr = chan->in_mbuf->m_data;
157                                 chan->in_len = 0;
158                         }
159
160                         fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
161                         
162                         if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
163                         {
164                                 /* read data from HSCX fifo */
165         
166                                 HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
167
168                                 cmd |= (HSCX_CMDR_RMC);
169                                 isic_hscx_cmd(sc, h_chan, cmd);
170                                 cmd = 0;
171                                 
172                                 chan->in_len += fifo_data_len;
173                                 chan->rxcount += fifo_data_len;
174
175                                 /* setup mbuf data length */
176                                         
177                                 chan->in_mbuf->m_len = chan->in_len;
178                                 chan->in_mbuf->m_pkthdr.len = chan->in_len;
179                 
180                                 if(sc->sc_trace & TRACE_B_RX)
181                                 {
182                                         i4b_trace_hdr_t hdr;
183                                         hdr.unit = L0ISICUNIT(sc->sc_unit);
184                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
185                                         hdr.dir = FROM_NT;
186                                         hdr.count = ++sc->sc_trace_bcount;
187                                         MICROTIME(hdr.time);
188                                         i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
189                                 }
190
191                                 (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
192
193                                 activity = ACT_RX;
194                                 
195                                 /* mark buffer ptr as unused */
196                                         
197                                 chan->in_mbuf = NULL;
198                                 chan->in_cbptr = NULL;
199                                 chan->in_len = 0;
200                         }
201                         else
202                         {
203                                 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
204                                 chan->in_cbptr = chan->in_mbuf->m_data;
205                                 chan->in_len = 0;
206                                 cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC); 
207                         }
208                 }
209                 else
210                 {
211                         if (chan->in_mbuf != NULL)
212                         {
213                                 i4b_Bfreembuf(chan->in_mbuf);
214                                 chan->in_mbuf = NULL;
215                                 chan->in_cbptr = NULL;
216                                 chan->in_len = 0;
217                         }
218                         cmd |= (HSCX_CMDR_RMC);
219                 }
220         }
221
222         /* rx fifo full */
223
224         if(ista & HSCX_ISTA_RPF)
225         {
226                 if(chan->in_mbuf == NULL)
227                 {
228                         if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
229                                 panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
230                         chan->in_cbptr = chan->in_mbuf->m_data;
231                         chan->in_len = 0;
232                 }
233
234                 chan->rxcount += sc->sc_bfifolen;
235                 
236                 if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
237                 {
238                         /* read data from HSCX fifo */
239
240                         HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
241
242                         chan->in_cbptr += sc->sc_bfifolen;
243                         chan->in_len += sc->sc_bfifolen;
244                 }
245                 else
246                 {
247                         if(chan->bprot == BPROT_NONE)
248                         {
249                                 /* setup mbuf data length */
250                                 
251                                 chan->in_mbuf->m_len = chan->in_len;
252                                 chan->in_mbuf->m_pkthdr.len = chan->in_len;
253
254                                 if(sc->sc_trace & TRACE_B_RX)
255                                 {
256                                         i4b_trace_hdr_t hdr;
257                                         hdr.unit = L0ISICUNIT(sc->sc_unit);
258                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
259                                         hdr.dir = FROM_NT;
260                                         hdr.count = ++sc->sc_trace_bcount;
261                                         MICROTIME(hdr.time);
262                                         i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
263                                 }
264
265                                 /* silence detection */
266                                 
267                                 if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
268                                         activity = ACT_RX;
269
270 #if defined (__FreeBSD__) && __FreeBSD__ > 4
271                                 (void) IF_HANDOFF(&chan->rx_queue, chan->in_mbuf, NULL);
272 #else
273                                 if(!(IF_QFULL(&chan->rx_queue)))
274                                 {
275                                         IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
276                                 }
277                                 else
278                                 {
279                                         i4b_Bfreembuf(chan->in_mbuf);
280                                 }
281 #endif
282                                 /* signal upper driver that data is available */
283
284                                 (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
285                                 
286                                 /* alloc new buffer */
287                                 
288                                 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
289                                         panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
290         
291                                 /* setup new data ptr */
292                                 
293                                 chan->in_cbptr = chan->in_mbuf->m_data;
294         
295                                 /* read data from HSCX fifo */
296         
297                                 HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
298
299                                 chan->in_cbptr += sc->sc_bfifolen;
300                                 chan->in_len = sc->sc_bfifolen;
301
302                                 chan->rxcount += sc->sc_bfifolen;
303                         }
304                         else
305                         {
306                                 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
307                                 chan->in_cbptr = chan->in_mbuf->m_data;
308                                 chan->in_len = 0;
309                                 cmd |= (HSCX_CMDR_RHR);
310                         }
311                 }
312                 
313                 /* command to release fifo space */
314                 
315                 cmd |= HSCX_CMDR_RMC;
316         }
317
318         /* transmit fifo empty, new data can be written to fifo */
319         
320         if(ista & HSCX_ISTA_XPR)
321         {
322                 /*
323                  * for a description what is going on here, please have
324                  * a look at isic_bchannel_start() in i4b_bchan.c !
325                  */
326                  
327                 int activity = -1;
328                 int len;
329                 int nextlen;
330
331                 NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan);
332
333                 if(chan->out_mbuf_cur == NULL)  /* last frame is transmitted */
334                 {
335                         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
336
337                         if(chan->out_mbuf_head == NULL)
338                         {
339                                 chan->state &= ~HSCX_TX_ACTIVE;
340                                 (*chan->isic_drvr_linktab->bch_tx_queue_empty)(chan->isic_drvr_linktab->unit);
341                         }
342                         else
343                         {
344                                 chan->state |= HSCX_TX_ACTIVE;
345                                 chan->out_mbuf_cur = chan->out_mbuf_head;
346                                 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
347                                 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
348
349                                 if(sc->sc_trace & TRACE_B_TX)
350                                 {
351                                         i4b_trace_hdr_t hdr;
352                                         hdr.unit = L0ISICUNIT(sc->sc_unit);
353                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
354                                         hdr.dir = FROM_TE;
355                                         hdr.count = ++sc->sc_trace_bcount;
356                                         MICROTIME(hdr.time);
357                                         i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
358                                 }
359                                 
360                                 if(chan->bprot == BPROT_NONE)
361                                 {
362                                         if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
363                                                 activity = ACT_TX;
364                                 }
365                                 else
366                                 {
367                                         activity = ACT_TX;
368                                 }
369                         }
370                 }
371                         
372                 len = 0;
373
374                 while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
375                 {
376                         nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
377
378 #ifdef NOTDEF                   
379                         printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
380                                 chan->out_mbuf_head,
381                                 chan->out_mbuf_cur,                     
382                                 chan->out_mbuf_cur_ptr,
383                                 chan->out_mbuf_cur_len,
384                                 len,
385                                 next_len);
386 #endif
387
388                         isic_hscx_waitxfw(sc, h_chan);  /* necessary !!! */
389                         
390                         HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
391                         cmd |= HSCX_CMDR_XTF;
392         
393                         len += nextlen;
394                         chan->txcount += nextlen;
395         
396                         chan->out_mbuf_cur_ptr += nextlen;
397                         chan->out_mbuf_cur_len -= nextlen;
398                         
399                         if(chan->out_mbuf_cur_len == 0) 
400                         {
401                                 if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
402                                 {
403                                         chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
404                                         chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
405         
406                                         if(sc->sc_trace & TRACE_B_TX)
407                                         {
408                                                 i4b_trace_hdr_t hdr;
409                                                 hdr.unit = L0ISICUNIT(sc->sc_unit);
410                                                 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
411                                                 hdr.dir = FROM_TE;
412                                                 hdr.count = ++sc->sc_trace_bcount;
413                                                 MICROTIME(hdr.time);
414                                                 i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
415                                         }
416                                 }
417                                 else
418                                 {
419                                         if (chan->bprot != BPROT_NONE)
420                                                 cmd |= HSCX_CMDR_XME;
421                                         i4b_Bfreembuf(chan->out_mbuf_head);
422                                         chan->out_mbuf_head = NULL;
423                                 }
424
425                         }
426                 }
427         }
428
429         if(cmd)         /* is there a command for the HSCX ? */
430         {
431                 isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
432         }
433
434         /* call timeout handling routine */
435         
436         if(activity == ACT_RX || activity == ACT_TX)
437                 (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);
438 }
439
440 /*---------------------------------------------------------------------------*
441  *      HSCX initialization
442  *
443  *      for telephony: extended transparent mode 1
444  *      for raw hdlc:  transparent mode 0
445  *---------------------------------------------------------------------------*/
446 void
447 isic_hscx_init(struct l1_softc *sc, int h_chan, int activate)
448 {       
449         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
450
451         HSCX_WRITE(h_chan, H_MASK, 0xff);               /* mask irq's */
452
453         if(sc->sc_ipac)
454         {
455                 /* CCR1: Power Up, Clock Mode 5 */
456                 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |      /* power up */
457                               HSCX_CCR1_CM1);   /* IPAC clock mode 5 */
458         }
459         else
460         {
461                 /* CCR1: Power Up, Clock Mode 5 */
462                 HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |      /* power up */
463                               HSCX_CCR1_CM2 |   /* HSCX clock mode 5 */
464                               HSCX_CCR1_CM0);
465         }
466                 
467         /* XAD1: Transmit Address Byte 1 */
468         HSCX_WRITE(h_chan, H_XAD1, 0xff);
469         
470         /* XAD2: Transmit Address Byte 2 */
471         HSCX_WRITE(h_chan, H_XAD2, 0xff);
472
473         /* RAH2: Receive Address Byte High Reg. 2 */
474         HSCX_WRITE(h_chan, H_RAH2, 0xff);
475         
476         /* XBCH: reset Transmit Byte Count High */
477         HSCX_WRITE(h_chan, H_XBCH, 0x00);
478         
479         /* RLCR: reset Receive Length Check Register */
480         HSCX_WRITE(h_chan, H_RLCR, 0x00);
481         
482         /* CCR2: set tx/rx clock shift bit 0    */
483         /*       disable CTS irq, disable RIE irq*/
484         HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
485
486         /* XCCR: tx bit count per time slot */
487         HSCX_WRITE(h_chan, H_XCCR, 0x07);
488
489         /* RCCR: rx bit count per time slot */
490         HSCX_WRITE(h_chan, H_RCCR, 0x07);
491         
492         if(sc->sc_bustyp == BUS_TYPE_IOM2)
493         {
494                 switch(h_chan) 
495                 {
496                         case HSCX_CH_A: /* Prepare HSCX channel A */
497                                 /* TSAX: tx clock shift bits 1 & 2      */
498                                 /*       tx time slot number            */
499                                 HSCX_WRITE(h_chan, H_TSAX, 0x2f);
500
501                                 /* TSAR: rx clock shift bits 1 & 2      */
502                                 /*       rx time slot number            */
503                                 HSCX_WRITE(h_chan, H_TSAR, 0x2f);
504                                 break;
505
506                         case HSCX_CH_B: /* Prepare HSCX channel B */
507                                 /* TSAX: tx clock shift bits 1 & 2      */
508                                 /*       tx time slot number            */
509                                 HSCX_WRITE(h_chan, H_TSAX, 0x03);
510
511                                 /* TSAR: rx clock shift bits 1 & 2      */
512                                 /*       rx time slot number            */
513                                 HSCX_WRITE(h_chan, H_TSAR, 0x03);
514                                 break;
515                 }
516         }
517         else    /* IOM 1 setup */
518         {
519                 /* TSAX: tx clock shift bits 1 & 2      */
520                 /*       tx time slot number            */
521                 HSCX_WRITE(h_chan, H_TSAX, 0x07);
522
523                 /* TSAR: rx clock shift bits 1 & 2      */
524                 /*       rx time slot number            */
525                 HSCX_WRITE(h_chan, H_TSAR, 0x07);
526         }
527
528         if(activate)
529         {
530                 if(chan->bprot == BPROT_RHDLC)
531                 {
532                   /* HDLC Frames, transparent mode 0 */
533                   HSCX_WRITE(h_chan, H_MODE,
534                      HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
535                 }
536                 else
537                 {
538                   /* Raw Telephony, extended transparent mode 1 */
539                   HSCX_WRITE(h_chan, H_MODE,
540                      HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
541                 }
542 #if 0
543                 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
544 #else
545                 isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR);
546 #endif
547         }
548         else
549         {
550                 /* TSAX: tx time slot */
551                 HSCX_WRITE(h_chan, H_TSAX, 0xff);
552
553                 /* TSAR: rx time slot */
554                 HSCX_WRITE(h_chan, H_TSAR, 0xff);
555
556                 /* Raw Telephony, extended transparent mode 1 */
557                 HSCX_WRITE(h_chan, H_MODE,
558                    HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
559         }
560
561         /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */        
562         /* always disable RSC and TIN */
563
564         chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
565
566         if(activate)
567         {
568                 /* enable */
569                 chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
570         }
571         else
572         {
573                 /* disable */
574                 chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
575         }
576
577         /* handle ICA, EXA, and EXB via interrupt mask of channel b */
578
579         if (h_chan == HSCX_CH_A)
580         {
581                 if (activate) 
582                         HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
583                 else
584                         HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
585                 HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
586                 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
587         }
588         else
589         {
590                 if (activate)
591                         HSCX_B_IMASK &= ~HSCX_MASK_EXB;
592                 else
593                         HSCX_B_IMASK |= HSCX_MASK_EXB;
594                 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
595         }
596
597         /* clear spurious interrupts left over */
598
599         if(h_chan == HSCX_CH_A)
600         {
601                 HSCX_READ(h_chan, H_EXIR);
602                 HSCX_READ(h_chan, H_ISTA);
603         }
604         else  /* mask ICA, because it must not be cleared by reading ISTA */
605         {
606                 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
607                 HSCX_READ(h_chan, H_EXIR);
608                 HSCX_READ(h_chan, H_ISTA);
609                 HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
610         }
611 }
612
613 /*---------------------------------------------------------------------------*
614  *      write command to HSCX command register
615  *---------------------------------------------------------------------------*/
616 void
617 isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd)
618 {       
619         int timeout = 20;
620
621         while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
622         {
623                 DELAY(10);
624                 timeout--;
625         }
626
627         if(timeout == 0)
628         {
629                 NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
630         }
631
632         HSCX_WRITE(h_chan, H_CMDR, cmd);        
633 }
634
635 /*---------------------------------------------------------------------------*
636  *      wait for HSCX transmit FIFO write enable
637  *---------------------------------------------------------------------------*/
638 void
639 isic_hscx_waitxfw(struct l1_softc *sc, int h_chan)
640 {       
641 #define WAITVAL 50
642 #define WAITTO  200
643
644         int timeout = WAITTO;
645
646         while((!(((HSCX_READ(h_chan, H_STAR)) &
647                 (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
648         {
649                 DELAY(WAITVAL);
650                 timeout--;
651         }
652
653         if(timeout == 0)
654         {
655                 NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
656         }
657         else if (timeout != WAITTO)
658         {
659                 NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
660         }
661 }
662                 
663 #endif /* NISIC > 0 */