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