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