1 /* $NetBSD: iwic_bchan.c,v 1.6 2007/10/19 12:00:50 ad Exp $ */
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
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
29 *---------------------------------------------------------------------------
31 * i4b_iwic - isdn4bsd Winbond W6692 driver
32 * ----------------------------------------
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>
47 #include <sys/callout.h>
48 #include <sys/socket.h>
49 #include <sys/device.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 *---------------------------------------------------------------------------*/
76 iwic_bchan_xirq(struct iwic_softc
*sc
, int chan_no
)
79 struct iwic_bchan
*chan
;
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!");
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
)
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
));
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 */
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
;
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
);
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
)
170 hdr
.type
= (chan_no
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
);
181 /* mark buffer ptr as unused */
183 chan
->in_mbuf
= NULL
;
184 chan
->in_cbptr
= NULL
;
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
;
192 cmd
|= (B_CMDR_RRST
| B_CMDR_RACK
);
197 if (chan
->in_mbuf
!= NULL
)
199 i4b_Bfreembuf(chan
->in_mbuf
);
200 chan
->in_mbuf
= NULL
;
201 chan
->in_cbptr
= NULL
;
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
;
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
;
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
)
247 hdr
.type
= (chan_no
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
)))
258 #if defined (__FreeBSD__) && __FreeBSD__ > 4
259 (void) IF_HANDOFF(&chan
->rx_queue
, chan
->in_mbuf
, NULL
);
261 if(!(IF_QFULL(&chan
->rx_queue
)))
263 IF_ENQUEUE(&chan
->rx_queue
, chan
->in_mbuf
);
267 i4b_Bfreembuf(chan
->in_mbuf
);
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
;
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
;
299 cmd
|= (B_CMDR_RRST
| B_CMDR_RACK
);
303 /* command to release fifo space */
310 if (irq_stat
& B_EXIR_XFR
)
312 /* transmit fifo empty, new data can be written to fifo */
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
);
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
)
339 hdr
.type
= (chan_no
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
)))
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
);
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
)
385 hdr
.type
= (chan_no
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
);
393 if (chan
->bprot
!= BPROT_NONE
)
395 i4b_Bfreembuf(chan
->out_mbuf_head
);
396 chan
->out_mbuf_head
= NULL
;
404 IWIC_WRITE(sc
, chan
->offset
+ B_CMDR
, cmd
);
408 /*---------------------------------------------------------------------------*
409 * initialize one B channels rx/tx data structures
410 *---------------------------------------------------------------------------*/
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
];
419 NDBGL1(L1_BCHAN
, "%s: chan %d, bprot %d, activate %d",
420 device_xname(&sc
->sc_dev
), chan_no
, bprot
, activate
);
424 chan
->bprot
= bprot
; /* B channel protocol */
425 chan
->state
= ST_IDLE
; /* B channel state */
430 iwic_bchan_init(sc
, chan_no
, activate
);
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
);
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
);
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 */
475 iwic_bchan_init(sc
, chan_no
, activate
);
481 /*---------------------------------------------------------------------------*
482 * initalize / deinitialize B-channel hardware
483 *---------------------------------------------------------------------------*/
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
);
493 if(bchan
->bprot
== BPROT_NONE
)
495 /* Extended transparent mode */
496 IWIC_WRITE(sc
, bchan
->offset
+ B_MODE
, B_MODE_MMS
);
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
);
511 IWIC_WRITE(sc
, bchan
->offset
+ B_EXIM
, 0);
516 IWIC_WRITE(sc
, bchan
->offset
+ B_EXIM
, 0xff);
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 *---------------------------------------------------------------------------*/
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
];
538 register int next_len
;
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 ? */
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
)))
582 chan
->state
|= ST_TX_ACTIVE
; /* we start transmitting */
584 if(sc
->sc_trace
& TRACE_B_TX
) /* if trace, send mbuf to trace dev */
587 hdr
.type
= (h_chan
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
;
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
)
641 hdr
.type
= (h_chan
== IWIC_BCH_A
? TRC_CH_B1
: TRC_CH_B2
);
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
670 /* end of mbuf chain */
672 if(chan
->bprot
== BPROT_NONE
)
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
);
693 IWIC_WRITE(sc
, chan
->offset
+ B_CMDR
, cmd
);
699 /*---------------------------------------------------------------------------*
700 * return B-channel statistics
701 *---------------------------------------------------------------------------*/
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
];
710 bsp
->outbytes
= bchan
->txcount
;
711 bsp
->inbytes
= bchan
->rxcount
;
719 /*---------------------------------------------------------------------------*
720 * initialize our local linktab
721 *---------------------------------------------------------------------------*/
722 static const struct isdn_l4_bchannel_functions iwic_bchan_driver
= {
729 iwic_init_linktab(struct iwic_softc
*sc
)
731 struct iwic_bchan
*chan
;
736 chan
= &sc
->sc_bchan
[IWIC_BCH_A
];
737 lt
= &chan
->iwic_isdn_linktab
;
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
;
752 chan
= &sc
->sc_bchan
[IWIC_BCH_B
];
753 lt
= &chan
->iwic_isdn_linktab
;
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
;