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