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