Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / iwic_bchan.c
blob9d9804f1377f81a28640852ca8c9e6809c190456
1 /* $NetBSD: iwic_bchan.c,v 1.6 2007/10/19 12:00:50 ad Exp $ */
3 /*
4 * Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
6 * Copyright (c) 2000, 2001 Hellmuth Michaelis. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 *---------------------------------------------------------------------------
31 * i4b_iwic - isdn4bsd Winbond W6692 driver
32 * ----------------------------------------
34 * $FreeBSD$
36 * last edit-date: [Tue Jan 16 13:21:24 2001]
38 *---------------------------------------------------------------------------*/
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: iwic_bchan.c,v 1.6 2007/10/19 12:00:50 ad Exp $");
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/callout.h>
48 #include <sys/socket.h>
49 #include <sys/device.h>
50 #include <net/if.h>
52 #include <sys/bus.h>
54 #include <dev/pci/pcireg.h>
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/iwicreg.h>
59 #include <dev/pci/iwicvar.h>
61 #include <netisdn/i4b_debug.h>
62 #include <netisdn/i4b_ioctl.h>
63 #include <netisdn/i4b_trace.h>
65 #include <netisdn/i4b_l2.h>
66 #include <netisdn/i4b_l1l2.h>
67 #include <netisdn/i4b_mbuf.h>
68 #include <netisdn/i4b_global.h>
70 static void iwic_bchan_init(struct iwic_softc *sc, int chan_no, int activate);
72 /*---------------------------------------------------------------------------*
73 * B-channel interrupt handler
74 *---------------------------------------------------------------------------*/
75 void
76 iwic_bchan_xirq(struct iwic_softc *sc, int chan_no)
78 int irq_stat;
79 struct iwic_bchan *chan;
80 int cmd = 0;
81 int activity = 0;
83 chan = &sc->sc_bchan[chan_no];
85 irq_stat = IWIC_READ(sc, chan->offset + B_EXIR);
87 NDBGL1(L1_H_IRQ, "irq_stat = 0x%x", irq_stat);
89 if((irq_stat & (B_EXIR_RMR | B_EXIR_RME | B_EXIR_RDOV | B_EXIR_XFR | B_EXIR_XDUN)) == 0)
91 NDBGL1(L1_H_XFRERR, "spurious IRQ!");
92 return;
95 if (irq_stat & B_EXIR_RDOV)
97 NDBGL1(L1_H_XFRERR, "%s: EXIR B-channel Receive Data Overflow", device_xname(&sc->sc_dev));
100 if (irq_stat & B_EXIR_XDUN)
102 NDBGL1(L1_H_XFRERR, "%s: EXIR B-channel Transmit Data Underrun", device_xname(&sc->sc_dev));
103 cmd |= (B_CMDR_XRST); /*XXX must retransmit frame ! */
106 /* RX message end interrupt */
108 if(irq_stat & B_EXIR_RME)
110 int error;
112 NDBGL1(L1_H_IRQ, "B_EXIR_RME");
114 error = (IWIC_READ(sc,chan->offset+B_STAR) &
115 (B_STAR_RDOV | B_STAR_CRCE | B_STAR_RMB));
117 if(error)
119 if(error & B_STAR_RDOV)
120 NDBGL1(L1_H_XFRERR, "%s: B-channel Receive Data Overflow", device_xname(&sc->sc_dev));
121 if(error & B_STAR_CRCE)
122 NDBGL1(L1_H_XFRERR, "%s: B-channel CRC Error", device_xname(&sc->sc_dev));
123 if(error & B_STAR_RMB)
124 NDBGL1(L1_H_XFRERR, "%s: B-channel Receive Message Aborted", device_xname(&sc->sc_dev));
127 /* all error conditions checked, now decide and take action */
129 if(error == 0)
131 register int fifo_data_len;
132 fifo_data_len = ((IWIC_READ(sc,chan->offset+B_RBCL)) &
133 ((IWIC_BCHAN_FIFO_LEN)-1));
135 if(fifo_data_len == 0)
136 fifo_data_len = IWIC_BCHAN_FIFO_LEN;
139 if(chan->in_mbuf == NULL)
141 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
142 panic("L1 iwic_bchan_irq: RME, cannot allocate mbuf!");
143 chan->in_cbptr = chan->in_mbuf->m_data;
144 chan->in_len = 0;
147 if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
149 /* read data from fifo */
151 NDBGL1(L1_H_IRQ, "B_EXIR_RME, rd fifo, len = %d", fifo_data_len);
153 IWIC_RDBFIFO(sc, chan, chan->in_cbptr, fifo_data_len);
155 cmd |= (B_CMDR_RACK | B_CMDR_RACT);
156 IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
157 cmd = 0;
159 chan->in_len += fifo_data_len;
160 chan->rxcount += fifo_data_len;
162 /* setup mbuf data length */
164 chan->in_mbuf->m_len = chan->in_len;
165 chan->in_mbuf->m_pkthdr.len = chan->in_len;
167 if(sc->sc_trace & TRACE_B_RX)
169 i4b_trace_hdr hdr;
170 hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
171 hdr.dir = FROM_NT;
172 hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
173 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
176 (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
179 activity = ACT_RX;
181 /* mark buffer ptr as unused */
183 chan->in_mbuf = NULL;
184 chan->in_cbptr = NULL;
185 chan->in_len = 0;
187 else
189 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
190 chan->in_cbptr = chan->in_mbuf->m_data;
191 chan->in_len = 0;
192 cmd |= (B_CMDR_RRST | B_CMDR_RACK);
195 else
197 if (chan->in_mbuf != NULL)
199 i4b_Bfreembuf(chan->in_mbuf);
200 chan->in_mbuf = NULL;
201 chan->in_cbptr = NULL;
202 chan->in_len = 0;
204 cmd |= (B_CMDR_RRST | B_CMDR_RACK);
208 /* RX fifo full interrupt */
210 if(irq_stat & B_EXIR_RMR)
212 NDBGL1(L1_H_IRQ, "B_EXIR_RMR");
214 if(chan->in_mbuf == NULL)
216 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
217 panic("L1 iwic_bchan_irq: RMR, cannot allocate mbuf!");
218 chan->in_cbptr = chan->in_mbuf->m_data;
219 chan->in_len = 0;
222 chan->rxcount += IWIC_BCHAN_FIFO_LEN;
224 if((chan->in_len + IWIC_BCHAN_FIFO_LEN) <= BCH_MAX_DATALEN)
226 /* read data from fifo */
228 NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo, len = max (64)");
230 IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);
232 chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
233 chan->in_len += IWIC_BCHAN_FIFO_LEN;
235 else
237 if(chan->bprot == BPROT_NONE)
239 /* setup mbuf data length */
241 chan->in_mbuf->m_len = chan->in_len;
242 chan->in_mbuf->m_pkthdr.len = chan->in_len;
244 if(sc->sc_trace & TRACE_B_RX)
246 i4b_trace_hdr hdr;
247 hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
248 hdr.dir = FROM_NT;
249 hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
250 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
253 /* silence detection */
255 if(!(isdn_bchan_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
256 activity = ACT_RX;
258 #if defined (__FreeBSD__) && __FreeBSD__ > 4
259 (void) IF_HANDOFF(&chan->rx_queue, chan->in_mbuf, NULL);
260 #else
261 if(!(IF_QFULL(&chan->rx_queue)))
263 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
265 else
267 i4b_Bfreembuf(chan->in_mbuf);
269 #endif
270 /* signal upper driver that data is available */
272 (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
274 /* alloc new buffer */
276 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
277 panic("L1 iwic_bchan_irq: RMR, cannot allocate new mbuf!");
279 /* setup new data ptr */
281 chan->in_cbptr = chan->in_mbuf->m_data;
283 /* read data from fifo */
285 NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo1, len = max (64)");
287 IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);
289 chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
290 chan->in_len = IWIC_BCHAN_FIFO_LEN;
292 chan->rxcount += IWIC_BCHAN_FIFO_LEN;
294 else
296 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
297 chan->in_cbptr = chan->in_mbuf->m_data;
298 chan->in_len = 0;
299 cmd |= (B_CMDR_RRST | B_CMDR_RACK);
303 /* command to release fifo space */
305 cmd |= B_CMDR_RACK;
308 /* TX interrupt */
310 if (irq_stat & B_EXIR_XFR)
312 /* transmit fifo empty, new data can be written to fifo */
314 int activity1 = -1;
315 int len;
316 int nextlen;
318 NDBGL1(L1_H_IRQ, "B_EXIR_XFR");
320 if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
322 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
324 if(chan->out_mbuf_head == NULL)
326 chan->state &= ~ST_TX_ACTIVE;
327 (*chan->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc);
329 else
331 chan->state |= ST_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;
336 if(sc->sc_trace & TRACE_B_TX)
338 i4b_trace_hdr hdr;
339 hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
340 hdr.dir = FROM_TE;
341 hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
342 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
345 if(chan->bprot == BPROT_NONE)
347 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
348 activity1 = ACT_TX;
350 else
352 activity1 = ACT_TX;
357 len = 0;
359 while(chan->out_mbuf_cur && len != IWIC_BCHAN_FIFO_LEN)
361 nextlen = min(chan->out_mbuf_cur_len, IWIC_BCHAN_FIFO_LEN - len);
363 NDBGL1(L1_H_IRQ, "B_EXIR_XFR, wr fifo, len = %d", nextlen);
365 IWIC_WRBFIFO(sc, chan, chan->out_mbuf_cur_ptr, nextlen);
367 cmd |= B_CMDR_XMS;
369 len += nextlen;
370 chan->txcount += nextlen;
372 chan->out_mbuf_cur_ptr += nextlen;
373 chan->out_mbuf_cur_len -= nextlen;
375 if(chan->out_mbuf_cur_len == 0)
377 if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
379 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
380 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
382 if(sc->sc_trace & TRACE_B_TX)
384 i4b_trace_hdr hdr;
385 hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
386 hdr.dir = FROM_TE;
387 hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
388 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
391 else
393 if (chan->bprot != BPROT_NONE)
394 cmd |= B_CMDR_XME;
395 i4b_Bfreembuf(chan->out_mbuf_head);
396 chan->out_mbuf_head = NULL;
401 if(cmd)
403 cmd |= B_CMDR_RACT;
404 IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
408 /*---------------------------------------------------------------------------*
409 * initialize one B channels rx/tx data structures
410 *---------------------------------------------------------------------------*/
411 void
412 iwic_bchannel_setup(isdn_layer1token t, int chan_no, int bprot, int activate)
414 struct iwic_softc *sc = t;
415 struct iwic_bchan *chan = &sc->sc_bchan[chan_no];
417 int s = splnet();
419 NDBGL1(L1_BCHAN, "%s: chan %d, bprot %d, activate %d",
420 device_xname(&sc->sc_dev), chan_no, bprot, activate);
422 /* general part */
424 chan->bprot = bprot; /* B channel protocol */
425 chan->state = ST_IDLE; /* B channel state */
427 if(activate == 0)
429 /* deactivation */
430 iwic_bchan_init(sc, chan_no, activate);
433 /* receiver part */
435 chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
437 #if defined (__FreeBSD__) && __FreeBSD__ > 4
438 if(!mtx_initialized(&chan->rx_queue.ifq_mtx))
439 mtx_init(&chan->rx_queue.ifq_mtx, "i4b_iwic_rx", NULL, MTX_DEF);
440 #endif
442 i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
444 chan->rxcount = 0; /* reset rx counter */
446 i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
448 chan->in_mbuf = NULL; /* reset mbuf ptr */
449 chan->in_cbptr = NULL; /* reset mbuf curr ptr */
450 chan->in_len = 0; /* reset mbuf data len */
452 /* transmitter part */
454 chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
456 #if defined (__FreeBSD__) && __FreeBSD__ > 4
457 if(!mtx_initialized(&chan->tx_queue.ifq_mtx))
458 mtx_init(&chan->tx_queue.ifq_mtx, "i4b_iwic_tx", NULL, MTX_DEF);
459 #endif
461 i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
463 chan->txcount = 0; /* reset tx counter */
465 i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
467 chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
468 chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
469 chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
470 chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
472 if(activate != 0)
474 /* activation */
475 iwic_bchan_init(sc, chan_no, activate);
478 splx(s);
481 /*---------------------------------------------------------------------------*
482 * initalize / deinitialize B-channel hardware
483 *---------------------------------------------------------------------------*/
484 static void
485 iwic_bchan_init(struct iwic_softc *sc, int chan_no, int activate)
487 struct iwic_bchan *bchan = &sc->sc_bchan[chan_no];
489 NDBGL1(L1_BCHAN, "chan %d, activate %d", chan_no, activate);
491 if(activate)
493 if(bchan->bprot == BPROT_NONE)
495 /* Extended transparent mode */
496 IWIC_WRITE(sc, bchan->offset + B_MODE, B_MODE_MMS);
498 else
500 /* Transparent mode */
501 IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
502 /* disable address comparation */
503 IWIC_WRITE (sc, bchan->offset+B_ADM1, 0xff);
504 IWIC_WRITE (sc, bchan->offset+B_ADM2, 0xff);
507 /* reset & start receiver */
508 IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST|B_CMDR_RACT);
510 /* clear irq mask */
511 IWIC_WRITE(sc, bchan->offset + B_EXIM, 0);
513 else
515 /* mask all irqs */
516 IWIC_WRITE(sc, bchan->offset + B_EXIM, 0xff);
518 /* reset mode */
519 IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
521 /* Bring interface down */
522 IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST | B_CMDR_XRST);
524 /* Flush pending interrupts */
525 IWIC_READ(sc, bchan->offset + B_EXIR);
529 /*---------------------------------------------------------------------------*
530 * start transmission on a b channel
531 *---------------------------------------------------------------------------*/
532 static void
533 iwic_bchannel_start(isdn_layer1token t,int h_chan)
535 struct iwic_softc *sc = (void *)t;
536 struct iwic_bchan *chan = &sc->sc_bchan[h_chan];
537 register int len;
538 register int next_len;
540 int s;
541 int activity = -1;
542 int cmd = 0;
544 s = splnet(); /* enter critical section */
546 NDBGL1(L1_BCHAN, "%s: channel %d", device_xname(&sc->sc_dev), h_chan);
548 if(chan->state & ST_TX_ACTIVE) /* already running ? */
550 splx(s);
551 return; /* yes, leave */
554 /* get next mbuf from queue */
556 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
558 if(chan->out_mbuf_head == NULL) /* queue empty ? */
560 splx(s); /* leave critical section */
561 return; /* yes, exit */
564 /* init current mbuf values */
566 chan->out_mbuf_cur = chan->out_mbuf_head;
567 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
568 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
570 /* activity indicator for timeout handling */
572 if(chan->bprot == BPROT_NONE)
574 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
575 activity = ACT_TX;
577 else
579 activity = ACT_TX;
582 chan->state |= ST_TX_ACTIVE; /* we start transmitting */
584 if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */
586 i4b_trace_hdr hdr;
587 hdr.type = (h_chan == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
588 hdr.dir = FROM_TE;
589 hdr.count = ++sc->sc_bchan[h_chan].sc_trace_bcount;
590 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
593 len = 0; /* # of chars put into tx fifo this time */
596 * fill the tx fifo with data from the current mbuf. if
597 * current mbuf holds less data than fifo length, try to
598 * get the next mbuf from (a possible) mbuf chain. if there is
599 * not enough data in a single mbuf or in a chain, then this
600 * is the last mbuf and we tell the chip that it has to send
601 * CRC and closing flag
604 while((len < IWIC_BCHAN_FIFO_LEN) && chan->out_mbuf_cur)
607 * put as much data into the fifo as is
608 * available from the current mbuf
611 if((len + chan->out_mbuf_cur_len) >= IWIC_BCHAN_FIFO_LEN)
612 next_len = IWIC_BCHAN_FIFO_LEN - len;
613 else
614 next_len = chan->out_mbuf_cur_len;
616 /* write what we have from current mbuf to fifo */
618 IWIC_WRBFIFO(sc, chan, chan->out_mbuf_cur_ptr, next_len);
620 len += next_len; /* update # of bytes written */
621 chan->txcount += next_len; /* statistics */
622 chan->out_mbuf_cur_ptr += next_len; /* data ptr */
623 chan->out_mbuf_cur_len -= next_len; /* data len */
626 * in case the current mbuf (of a possible chain) data
627 * has been put into the fifo, check if there is a next
628 * mbuf in the chain. If there is one, get ptr to it
629 * and update the data ptr and the length
632 if((chan->out_mbuf_cur_len <= 0) &&
633 ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
635 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
636 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
638 if(sc->sc_trace & TRACE_B_TX)
640 i4b_trace_hdr hdr;
641 hdr.type = (h_chan == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
642 hdr.dir = FROM_TE;
643 hdr.count = ++sc->sc_bchan[h_chan].sc_trace_bcount;
644 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
650 * if there is either still data in the current mbuf and/or
651 * there is a successor on the chain available issue just
652 * a XTF (transmit) command to the chip. if there is no more
653 * data available from the current mbuf (-chain), issue
654 * an XTF and an XME (message end) command which will then
655 * send the CRC and the closing HDLC flag sequence
658 if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
661 * more data available, send current fifo out.
662 * next xfer to tx fifo is done in the
663 * interrupt routine.
666 cmd |= B_CMDR_XMS;
668 else
670 /* end of mbuf chain */
672 if(chan->bprot == BPROT_NONE)
673 cmd |= B_CMDR_XMS;
674 else
675 cmd |= (B_CMDR_XMS | B_CMDR_XME);
677 i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */
679 chan->out_mbuf_head = NULL;
680 chan->out_mbuf_cur = NULL;
681 chan->out_mbuf_cur_ptr = NULL;
682 chan->out_mbuf_cur_len = 0;
685 /* call timeout handling routine */
687 if(activity == ACT_RX || activity == ACT_TX)
688 (*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
690 if(cmd)
692 cmd |= B_CMDR_RACT;
693 IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
696 splx(s);
699 /*---------------------------------------------------------------------------*
700 * return B-channel statistics
701 *---------------------------------------------------------------------------*/
702 static void
703 iwic_bchannel_stat(isdn_layer1token t, int h_chan, bchan_statistics_t *bsp)
705 struct iwic_softc *sc = t;
706 struct iwic_bchan *bchan = &sc->sc_bchan[h_chan];
708 int s = splnet();
710 bsp->outbytes = bchan->txcount;
711 bsp->inbytes = bchan->rxcount;
713 bchan->txcount = 0;
714 bchan->rxcount = 0;
716 splx(s);
719 /*---------------------------------------------------------------------------*
720 * initialize our local linktab
721 *---------------------------------------------------------------------------*/
722 static const struct isdn_l4_bchannel_functions iwic_bchan_driver = {
723 iwic_bchannel_setup,
724 iwic_bchannel_start,
725 iwic_bchannel_stat
728 void
729 iwic_init_linktab(struct iwic_softc *sc)
731 struct iwic_bchan *chan;
732 isdn_link_t *lt;
734 /* channel A */
736 chan = &sc->sc_bchan[IWIC_BCH_A];
737 lt = &chan->iwic_isdn_linktab;
739 lt->l1token = sc;
740 lt->channel = IWIC_BCH_A;
741 lt->bchannel_driver = &iwic_bchan_driver;
742 lt->tx_queue = &chan->tx_queue;
744 /* used by non-HDLC data transfers, i.e. telephony drivers */
745 lt->rx_queue = &chan->rx_queue;
747 /* used by HDLC data transfers, i.e. ipr and isp drivers */
748 lt->rx_mbuf = &chan->in_mbuf;
750 /* channel B */
752 chan = &sc->sc_bchan[IWIC_BCH_B];
753 lt = &chan->iwic_isdn_linktab;
755 lt->l1token = sc;
756 lt->channel = IWIC_BCH_B;
757 lt->bchannel_driver = &iwic_bchan_driver;
758 lt->tx_queue = &chan->tx_queue;
760 /* used by non-HDLC data transfers, i.e. telephony drivers */
761 lt->rx_queue = &chan->rx_queue;
763 /* used by HDLC data transfers, i.e. ipr and isp drivers */
764 lt->rx_mbuf = &chan->in_mbuf;