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