1 /*****************************************************************************/
2 /*
3  *      auerisdn_b.c  --  Auerswald PBX/System Telephone ISDN B-channel interface.
4  *
5  *      Copyright (C) 2002  Wolfgang M�es (wolfgang@iksw-muees.de)
6  *
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation; either version 2 of the License, or
10  *      (at your option) any later version.
11  *
12  *      This program is distributed in the hope that it will be useful,
13  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *      GNU General Public License for more details.
16  *
17  *      You should have received a copy of the GNU General Public License
18  *      along with this program; if not, write to the Free Software
19  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21  /*****************************************************************************/
22 
23 #include <linux/isdnif.h>	/* ISDN constants */
24 #include <linux/netdevice.h>	/* skb functions */
25 
26 #undef DEBUG			/* include debug macros until it's done */
27 #include <linux/usb.h>		/* standard usb header */
28 
29 #include "auerisdn.h"
30 #include "auermain.h"
31 
32 /*-------------------------------------------------------------------*/
33 /* ISDN B channel support defines                                    */
34 #define AUISDN_BC_1MS		8	/* Bytes per channel and ms */
35 #define AUISDN_BC_INC		4	/* change INT OUT size increment */
36 #define AUISDN_BCDATATHRESHOLD	48	/* for unsymmetric 2-B-channels */
37 #define AUISDN_TOGGLETIME	6	/* Timeout for unsymmetric serve */
38 
39 /*-------------------------------------------------------------------*/
40 /* Debug support 						     */
41 #ifdef DEBUG
42 #define dump( desc, adr, len) \
43 do {			\
44 	unsigned int u;	\
45 	printk (KERN_DEBUG); \
46 	printk (desc); \
47 	for (u = 0; u < len; u++) \
48 		printk (" %02X", adr[u] & 0xFF); \
49 	printk ("\n"); \
50 } while (0)
51 #else
52 #define dump( desc, adr, len)
53 #endif
54 
55 /*-------------------------------------------------------------------*/
56 
57 /* Callback to L2 for HISAX */
58 /* This callback can be called from 3 sources:
59    a) from hisax context (answer from a l2l1 function)
60    b) from interrupt context (a B channel paket arrived, a B channel paket was sent)
61    c) from kernel daemon context (probe/disconnecting)
62 */
auerisdn_b_l1l2(struct auerisdnbc * bc,int pr,void * arg)63 void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg)
64 {
65 	struct auerhisax *ahp;
66 	struct sk_buff *skb;
67 
68 	/* do the callback */
69 	ahp = bc->cp->isdn.ahp;
70 	if (ahp) {
71 		ahp->hisax_b_if[bc->channel].ifc.l1l2(&ahp->
72 						      hisax_b_if[bc->
73 								 channel].
74 						      ifc, pr, arg);
75 	} else {
76 		dbg("auerisdn_b_l1l2 called without ahp");
77 		if (pr == (PH_DATA | INDICATION)) {
78 			skb = (struct sk_buff *) arg;
79 			if (skb) {
80 				skb_pull(skb, skb->len);
81 				dev_kfree_skb_any(skb);
82 			}
83 		}
84 	}
85 }
86 
87 /* fill the INT OUT data buffer with new data */
88 /* Transfer buffer size to fill is in urbp->transfer_buffer_length */
auerisdn_bintbo_newdata(struct auerisdn * ip)89 static void auerisdn_bintbo_newdata(struct auerisdn *ip)
90 {
91 	unsigned long flags;
92 	struct urb *urbp = ip->intbo_urbp;
93 	struct auerisdnbc *bc = &ip->bc[0];	/* start with B-channel 0 */
94 	struct sk_buff *skb;
95 	unsigned char *ucp;
96 	int buf_size;
97 	int len;
98 	int bytes_sent;
99 	int i;
100 
101 	/* FIXME: this algorithm is fixed to 2 B-channels */
102 	/* Which B channel should we serve? */
103 	if (ip->bc[1].mode != L1_MODE_NULL) {
104 		/* B channel 1 is used */
105 		if (bc->mode != L1_MODE_NULL) {
106 			/* both B-channels are used */
107 			if (ip->intbo_toggletimer) {
108 				/* simply toggling */
109 				ip->intbo_toggletimer--;
110 				i = ip->intbo_index ^ 1;	/* serve both channels equal */
111 			} else {
112 				/* search the B channel with the most demand of data */
113 				i = bc->txfree - ip->bc[1].txfree;
114 				if (i < -AUISDN_BCDATATHRESHOLD)
115 					i = 1;	/* B channel 1 needs more data */
116 				else if (i > AUISDN_BCDATATHRESHOLD)
117 					i = 0;	/* B channel 0 needs more data */
118 				else
119 					i = ip->intbo_index ^ 1;	/* serve both channels equal */
120 				if (i == ip->intbo_index)
121 					ip->intbo_toggletimer =
122 					    AUISDN_TOGGLETIME;
123 			}
124 			bc = &ip->bc[i];
125 			ip->intbo_index = i;
126 		} else {
127 			bc = &ip->bc[1];
128 		}
129 	}
130 	dbg("INTBO: Fill B%d with %d Bytes, %d Bytes free",
131 	    bc->channel + 1, urbp->transfer_buffer_length - AUH_SIZE,
132 	    bc->txfree);
133 
134 	/* Fill the buffer with data */
135 	ucp = ip->intbo_bufp;
136 	*ucp++ = AUH_B1CHANNEL + bc->channel;	/* First byte is channel nr. */
137 	buf_size = urbp->transfer_buffer_length - AUH_SIZE;
138 	len = 0;
139 	while (len < buf_size) {
140 		spin_lock_irqsave(&bc->txskb_lock, flags);
141 		if ((skb = bc->txskb)) {
142 			/* dump ("raw tx data:", skb->data, skb->len); */
143 			if (bc->mode == L1_MODE_TRANS) {
144 				bytes_sent = buf_size - len;
145 				if (skb->len < bytes_sent)
146 					bytes_sent = skb->len;
147 				{	/* swap tx bytes */
148 					register unsigned char *src =
149 					    skb->data;
150 					unsigned int count;
151 					for (count = 0; count < bytes_sent;
152 					     count++)
153 						*ucp++ =
154 						    isdnhdlc_bit_rev_tab
155 						    [*src++];
156 				}
157 				len += bytes_sent;
158 				bc->lastbyte = skb->data[bytes_sent - 1];
159 			} else {
160 				int bs =
161 				    isdnhdlc_encode(&bc->outp_hdlc_state,
162 						    skb->data, skb->len,
163 						    &bytes_sent,
164 						    ucp, buf_size - len);
165 				/* dump ("hdlc data:", ucp, bs); */
166 				len += bs;
167 				ucp += bs;
168 			}
169 			skb_pull(skb, bytes_sent);
170 
171 			if (!skb->len) {
172 				// Frame sent
173 				bc->txskb = NULL;
174 				spin_unlock_irqrestore(&bc->txskb_lock,
175 						       flags);
176 				auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
177 						(void *) skb->truesize);
178 				dev_kfree_skb_any(skb);
179 				continue;	//while
180 			}
181 		} else {
182 			if (bc->mode == L1_MODE_TRANS) {
183 				memset(ucp, bc->lastbyte, buf_size - len);
184 				ucp += buf_size - len;
185 				len = buf_size;
186 				/* dbg ("fill = 0xFF"); */
187 			} else {
188 				// Send flags
189 				int bs =
190 				    isdnhdlc_encode(&bc->outp_hdlc_state,
191 						    NULL, 0, &bytes_sent,
192 						    ucp, buf_size - len);
193 				/* dbg ("fill = 0x%02X", (int)*ucp); */
194 				len += bs;
195 				ucp += bs;
196 			}
197 		}
198 		spin_unlock_irqrestore(&bc->txskb_lock, flags);
199 	}
200 	/* dbg ("%d Bytes to TX buffer", len); */
201 }
202 
203 
204 /* INT OUT completion handler */
auerisdn_bintbo_complete(struct urb * urbp)205 static void auerisdn_bintbo_complete(struct urb *urbp)
206 {
207 	struct auerisdn *ip = urbp->context;
208 
209 	/* unlink completion? */
210 	if ((urbp->status == -ENOENT) || (urbp->status == -ECONNRESET)) {
211 		/* should we restart with another size? */
212 		if (ip->intbo_state == INTBOS_CHANGE) {
213 			dbg("state => RESTART");
214 			ip->intbo_state = INTBOS_RESTART;
215 		} else {
216 			/* set up variables for later restart */
217 			dbg("INTBO stopped");
218 			ip->intbo_state = INTBOS_IDLE;
219 		}
220 		/* nothing more to do */
221 		return;
222 	}
223 
224 	/* other state != 0? */
225 	if (urbp->status) {
226 		warn("auerisdn_bintbo_complete: status = %d",
227 		     urbp->status);
228 		return;
229 	}
230 
231 	/* Should we fill in new data? */
232 	if (ip->intbo_state == INTBOS_CHANGE) {
233 		dbg("state == INTBOS_CHANGE, no new data");
234 		return;
235 	}
236 
237 	/* fill in new data */
238 	auerisdn_bintbo_newdata(ip);
239 }
240 
241 /* set up the INT OUT URB the first time */
242 /* Don't start the URB */
auerisdn_bintbo_setup(struct auerisdn * ip,unsigned int len)243 static void auerisdn_bintbo_setup(struct auerisdn *ip, unsigned int len)
244 {
245 	ip->intbo_state = INTBOS_IDLE;
246 	FILL_INT_URB(ip->intbo_urbp, ip->usbdev,
247 		     usb_sndintpipe(ip->usbdev, ip->intbo_endp),
248 		     ip->intbo_bufp, len, auerisdn_bintbo_complete, ip,
249 		     ip->outInterval);
250 	ip->intbo_urbp->transfer_flags |= USB_ASYNC_UNLINK;
251 	ip->intbo_urbp->status = 0;
252 }
253 
254 /* restart the INT OUT endpoint */
auerisdn_bintbo_restart(struct auerisdn * ip)255 static void auerisdn_bintbo_restart(struct auerisdn *ip)
256 {
257 	struct urb *urbp = ip->intbo_urbp;
258 	int status;
259 
260 	/* dbg ("auerisdn_intbo_restart"); */
261 
262 	/* fresh restart */
263 	auerisdn_bintbo_setup(ip, ip->paketsize + AUH_SIZE);
264 
265 	/* Fill in new data */
266 	auerisdn_bintbo_newdata(ip);
267 
268 	/* restart the urb */
269 	ip->intbo_state = INTBOS_RUNNING;
270 	status = usb_submit_urb(urbp);
271 	if (status < 0) {
272 		err("can't submit INT OUT urb, status = %d", status);
273 		urbp->status = status;
274 		urbp->complete(urbp);
275 	}
276 }
277 
278 /* change the size of the INT OUT endpoint */
auerisdn_bchange(struct auerisdn * ip,unsigned int paketsize)279 static void auerisdn_bchange(struct auerisdn *ip, unsigned int paketsize)
280 {
281 	/* changing... */
282 	dbg("txfree[0] = %d, txfree[1] = %d, old size = %d, new size = %d",
283 	    ip->bc[0].txfree, ip->bc[1].txfree, ip->paketsize, paketsize);
284 	ip->paketsize = paketsize;
285 
286 	if (paketsize == 0) {
287 		/* stop the INT OUT endpoint */
288 		dbg("stop unlinking INT out urb");
289 		ip->intbo_state = INTBOS_IDLE;
290 		usb_unlink_urb(ip->intbo_urbp);
291 		return;
292 	}
293 	if (ip->intbo_state != INTBOS_IDLE) {
294 		/* dbg ("unlinking INT out urb"); */
295 		ip->intbo_state = INTBOS_CHANGE;
296 		usb_unlink_urb(ip->intbo_urbp);
297 	} else {
298 		/* dbg ("restart immediately"); */
299 		auerisdn_bintbo_restart(ip);
300 	}
301 }
302 
303 /* serve the outgoing B channel interrupt */
304 /* Called from the INT IN completion handler */
auerisdn_bserv(struct auerisdn * ip)305 static void auerisdn_bserv(struct auerisdn *ip)
306 {
307 	struct auerisdnbc *bc;
308 	unsigned int u;
309 	unsigned int paketsize;
310 
311 	/* should we start the INT OUT endpoint again? */
312 	if (ip->intbo_state == INTBOS_RESTART) {
313 		/* dbg ("Restart INT OUT from INT IN"); */
314 		auerisdn_bintbo_restart(ip);
315 		return;
316 	}
317 	/* no new calculation if change already in progress */
318 	if (ip->intbo_state == INTBOS_CHANGE)
319 		return;
320 
321 	/* calculation of transfer parameters for INT OUT endpoint */
322 	paketsize = 0;
323 	for (u = 0; u < AUISDN_BCHANNELS; u++) {
324 		bc = &ip->bc[u];
325 		if (bc->mode != L1_MODE_NULL) {	/* B channel is active */
326 			unsigned int bpp = AUISDN_BC_1MS * ip->outInterval;
327 			if (bc->txfree < bpp) {	/* buffer is full, throttle */
328 				bc->txsize = bpp - AUISDN_BC_INC;
329 				paketsize += bpp - AUISDN_BC_INC;
330 			} else if (bc->txfree < bpp * 2) {
331 				paketsize += bc->txsize;	/* schmidt-trigger, continue */
332 			} else if (bc->txfree < bpp * 4) {	/* we are in synch */
333 				bc->txsize = bpp;
334 				paketsize += bpp;
335 			} else if (bc->txfree > bc->ofsize / 2) {/* we have to fill the buffer */
336 				bc->txsize = bpp + AUISDN_BC_INC;
337 				paketsize += bpp + AUISDN_BC_INC;
338 			} else {
339 				paketsize += bc->txsize;	/* schmidt-trigger, continue */
340 			}
341 		}
342 	}
343 
344 	/* check if we have to change the paket size */
345 	if (paketsize != ip->paketsize)
346 		auerisdn_bchange(ip, paketsize);
347 }
348 
349 /* Send activation/deactivation state to L2 */
auerisdn_bconf(struct auerisdnbc * bc)350 static void auerisdn_bconf(struct auerisdnbc *bc)
351 {
352 	unsigned long flags;
353 	struct sk_buff *skb;
354 
355 	if (bc->mode == L1_MODE_NULL) {
356 		auerisdn_b_l1l2(bc, PH_DEACTIVATE | INDICATION, NULL);
357 		/* recycle old txskb */
358 		spin_lock_irqsave(&bc->txskb_lock, flags);
359 		skb = bc->txskb;
360 		bc->txskb = NULL;
361 		spin_unlock_irqrestore(&bc->txskb_lock, flags);
362 		if (skb) {
363 			skb_pull(skb, skb->len);
364 			auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
365 					(void *) skb->truesize);
366 			dev_kfree_skb_any(skb);
367 		}
368 	} else {
369 		auerisdn_b_l1l2(bc, PH_ACTIVATE | INDICATION, NULL);
370 	}
371 }
372 
373 /* B channel setup completion handler */
auerisdn_bmode_complete(struct urb * urb)374 static void auerisdn_bmode_complete(struct urb *urb)
375 {
376 	struct auerswald *cp;
377 	struct auerbuf *bp = (struct auerbuf *) urb->context;
378 	struct auerisdnbc *bc;
379 	int channel;
380 
381 	dbg("auerisdn_bmode_complete called");
382 	cp = ((struct auerswald *) ((char *) (bp->list) -
383 				    (unsigned
384 				     long) (&((struct auerswald *) 0)->
385 					    bufctl)));
386 
387 	/* select the B-channel */
388 	channel = le16_to_cpu(bp->dr->wIndex);
389 	channel -= AUH_B1CHANNEL;
390 	if (channel < 0)
391 		goto rel;
392 	if (channel >= AUISDN_BCHANNELS)
393 		goto rel;
394 	bc = &cp->isdn.bc[channel];
395 
396 	/* Check for success */
397 	if (urb->status) {
398 		err("complete with non-zero status: %d", urb->status);
399 	} else {
400 		bc->mode = *bp->bufp;
401 	}
402 	/* Signal current mode to L2 */
403 	auerisdn_bconf(bc);
404 
405 	/* reuse the buffer */
406       rel:auerbuf_releasebuf(bp);
407 
408 	/* Wake up all processes waiting for a buffer */
409 	wake_up(&cp->bufferwait);
410 }
411 
412 /* Setup a B channel transfer mode */
auerisdn_bmode(struct auerisdnbc * bc,unsigned int mode)413 static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode)
414 {
415 	struct auerswald *cp = bc->cp;
416 	struct auerbuf *bp;
417 	int ret;
418 
419 	/* don't allow activation on disconnect */
420 	if (cp->disconnecting) {
421 		mode = L1_MODE_NULL;
422 
423 		/* Else check if something changed */
424 	} else if (bc->mode != mode) {
425 		if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) {
426 			/* init RX hdlc decoder */
427 			dbg("rcv init");
428 			isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0);
429 			/* init TX hdlc decoder */
430 			dbg("out init");
431 			isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0);
432 		}
433 		/* stop ASAP */
434 		if (mode == L1_MODE_NULL)
435 			bc->mode = mode;
436 		if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) {
437 			/* Activation or deactivation required */
438 
439 			/* get a buffer for the command */
440 			bp = auerbuf_getbuf(&cp->bufctl);
441 			/* if no buffer available: can't change the mode */
442 			if (!bp) {
443 				err("auerisdn_bmode: no data buffer available");
444 				return;
445 			}
446 
447 			/* fill the control message */
448 			bp->dr->bRequestType = AUT_WREQ;
449 			bp->dr->bRequest = AUV_CHANNELCTL;
450 			if (mode != L1_MODE_NULL)
451 				bp->dr->wValue = cpu_to_le16(1);
452 			else
453 				bp->dr->wValue = cpu_to_le16(0);
454 			bp->dr->wIndex =
455 			    cpu_to_le16(AUH_B1CHANNEL + bc->channel);
456 			bp->dr->wLength = cpu_to_le16(0);
457 			*bp->bufp = mode;
458 			FILL_CONTROL_URB(bp->urbp, cp->usbdev,
459 					 usb_sndctrlpipe(cp->usbdev, 0),
460 					 (unsigned char *) bp->dr,
461 					 bp->bufp, 0,
462 					 (usb_complete_t)
463 					 auerisdn_bmode_complete, bp);
464 
465 			/* submit the control msg */
466 			ret =
467 			    auerchain_submit_urb(&cp->controlchain,
468 						 bp->urbp);
469 			if (ret) {
470 				bp->urbp->status = ret;
471 				auerisdn_bmode_complete(bp->urbp);
472 			}
473 			return;
474 		}
475 	}
476 	/* new mode is set */
477 	bc->mode = mode;
478 
479 	/* send confirmation to L2 */
480 	auerisdn_bconf(bc);
481 }
482 
483 /* B-channel transfer function L2->L1 */
auerisdn_b_l2l1(struct hisax_if * ifc,int pr,void * arg,unsigned int channel)484 void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg,
485 		     unsigned int channel)
486 {
487 	struct auerhisax *ahp;
488 	struct auerisdnbc *bc;
489 	struct auerswald *cp;
490 	struct sk_buff *skb;
491 	unsigned long flags;
492 	int mode;
493 
494 	cp = NULL;
495 	ahp = (struct auerhisax *) ifc->priv;
496 	if (ahp)
497 		cp = ahp->cp;
498 	if (cp && !cp->disconnecting) {
499 		/* normal execution */
500 		bc = &cp->isdn.bc[channel];
501 		switch (pr) {
502 		case PH_ACTIVATE | REQUEST:	/* activation request */
503 			mode = (int) arg;	/* one of the L1_MODE constants */
504 			dbg("B%d, PH_ACTIVATE_REQUEST Mode = %d",
505 			    bc->channel + 1, mode);
506 			auerisdn_bmode(bc, mode);
507 			break;
508 		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
509 			dbg("B%d, PH_DEACTIVATE_REQUEST", bc->channel + 1);
510 			auerisdn_bmode(bc, L1_MODE_NULL);
511 			break;
512 		case PH_DATA | REQUEST:	/* Transmit data request */
513 			skb = (struct sk_buff *) arg;
514 			spin_lock_irqsave(&bc->txskb_lock, flags);
515 			if (bc->txskb) {
516 				err("Overflow in B channel TX");
517 				skb_pull(skb, skb->len);
518 				dev_kfree_skb_any(skb);
519 			} else {
520 				if (cp->disconnecting
521 				    || (bc->mode == L1_MODE_NULL)) {
522 					skb_pull(skb, skb->len);
523 					spin_unlock_irqrestore(&bc->
524 							       txskb_lock,
525 							       flags);
526 					auerisdn_b_l1l2(bc,
527 							PH_DATA | CONFIRM,
528 							(void *) skb->
529 							truesize);
530 					dev_kfree_skb_any(skb);
531 					goto next;
532 				} else
533 					bc->txskb = skb;
534 			}
535 			spin_unlock_irqrestore(&bc->txskb_lock, flags);
536 		      next:break;
537 		default:
538 			warn("pr %#x\n", pr);
539 			break;
540 		}
541 	} else {
542 		/* hisax interface is down */
543 		switch (pr) {
544 		case PH_ACTIVATE | REQUEST:	/* activation request */
545 			dbg("B channel: PH_ACTIVATE | REQUEST with interface down");
546 			/* don't answer this request! Endless... */
547 			break;
548 		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
549 			dbg("B channel: PH_DEACTIVATE | REQUEST with interface down");
550 			ifc->l1l2(ifc, PH_DEACTIVATE | INDICATION, NULL);
551 			break;
552 		case PH_DATA | REQUEST:	/* Transmit data request */
553 			dbg("B channel: PH_DATA | REQUEST with interface down");
554 			skb = (struct sk_buff *) arg;
555 			/* free data buffer */
556 			if (skb) {
557 				skb_pull(skb, skb->len);
558 				dev_kfree_skb_any(skb);
559 			}
560 			/* send confirmation back to layer 2 */
561 			ifc->l1l2(ifc, PH_DATA | CONFIRM, NULL);
562 			break;
563 		default:
564 			warn("pr %#x\n", pr);
565 			break;
566 		}
567 	}
568 }
569 
570 /* Completion handler for B channel input endpoint */
auerisdn_intbi_complete(struct urb * urb)571 void auerisdn_intbi_complete(struct urb *urb)
572 {
573 	unsigned int bytecount;
574 	unsigned char *ucp;
575 	int channel;
576 	unsigned int syncbit;
577 	unsigned int syncdata;
578 	struct auerisdnbc *bc;
579 	struct sk_buff *skb;
580 	int count;
581 	int status;
582 	struct auerswald *cp = (struct auerswald *) urb->context;
583 	/* do not respond to an error condition */
584 	if (urb->status != 0) {
585 		dbg("nonzero URB status = %d", urb->status);
586 		return;
587 	}
588 	if (cp->disconnecting)
589 		return;
590 
591 	/* Parse and extract the header information */
592 	bytecount = urb->actual_length;
593 	ucp = cp->isdn.intbi_bufp;
594 	if (!bytecount)
595 		return;		/* no data */
596 	channel = *ucp & AUH_TYPEMASK;
597 	syncbit = *ucp & AUH_SYNC;
598 	ucp++;
599 	bytecount--;
600 	channel -= AUH_B1CHANNEL;
601 	if (channel < 0)
602 		return;		/* unknown data channel, no B1,B2 */
603 	if (channel >= AUISDN_BCHANNELS)
604 		return;		/* unknown data channel, no B1,B2 */
605 	bc = &cp->isdn.bc[channel];
606 	if (!bytecount)
607 		return;
608 	/* Calculate amount of bytes which are free in tx device buffer */
609 	bc->txfree = ((255 - *ucp++) * bc->ofsize) / 256;
610 	/* dbg ("%d Bytes free in TX buffer", bc->txfree); */
611 	bytecount--;
612 
613 	/* Next Byte: TX sync information */
614 	if (syncbit) {
615 		if (!bytecount)
616 			goto int_tx;
617 		syncdata = *ucp++;
618 		dbg("Sync data = %d", syncdata);
619 		bytecount--;
620 	}
621 	/* The rest of the paket is plain data */
622 	if (!bytecount)
623 		goto int_tx;
624 	/* dump ("RX Data is:", ucp, bytecount); */
625 
626 	/* Send B channel data to upper layers */
627 	while (bytecount > 0) {
628 		if (bc->mode == L1_MODE_NULL) {
629 			/* skip the data. Nobody needs them */
630 			status = 0;
631 			bytecount = 0;
632 		} else if (bc->mode == L1_MODE_TRANS) {
633 			{	/* swap rx bytes */
634 				register unsigned char *dest = bc->rxbuf;
635 				status = bytecount;
636 				for (; bytecount; bytecount--)
637 					*dest++ =
638 					    isdnhdlc_bit_rev_tab[*ucp++];
639 			}
640 
641 		} else {
642 			status = isdnhdlc_decode(&bc->inp_hdlc_state, ucp,
643 						 bytecount, &count,
644 						 bc->rxbuf, AUISDN_RXSIZE);
645 			ucp += count;
646 			bytecount -= count;
647 		}
648 		if (status > 0) {
649 			/* Good frame received */
650 			if (!(skb = dev_alloc_skb(status))) {
651 				warn("receive out of memory");
652 				break;
653 			}
654 			memcpy(skb_put(skb, status), bc->rxbuf, status);
655 			/* dump ("HDLC Paket", bc->rxbuf, status); */
656 			auerisdn_b_l1l2(bc, PH_DATA | INDICATION, skb);
657 			/* these errors may actually happen at the start of a connection! */
658 		} else if (status == -HDLC_CRC_ERROR) {
659 			dbg("CRC error");
660 		} else if (status == -HDLC_FRAMING_ERROR) {
661 			dbg("framing error");
662 		} else if (status == -HDLC_LENGTH_ERROR) {
663 			dbg("length error");
664 		}
665 	}
666 
667       int_tx:			/* serve the outgoing B channel */
668 	auerisdn_bserv(&cp->isdn);
669 }
670 
671 /* Stop the B channel activity. The device is disconnecting */
672 /* This function is called after cp->disconnecting is true */
auerisdn_b_disconnect(struct auerswald * cp)673 unsigned int auerisdn_b_disconnect(struct auerswald *cp)
674 {
675 	unsigned int u;
676 	struct auerisdnbc *bc;
677 	unsigned int result = 0;
678 
679 	/* Close the B channels */
680 	for (u = 0; u < AUISDN_BCHANNELS; u++) {
681 		bc = &cp->isdn.bc[u];
682 		if (bc->mode != L1_MODE_NULL) {	/* B channel is active */
683 			auerisdn_bmode(bc, L1_MODE_NULL);
684 			result = 1;
685 		}
686 	}
687 	/* return 1 if there is B channel traffic */
688 	return result;
689 }
690