1 /*
2 * Things to sort out:
3 *
4 * o tbusy handling
5 * o allow users to set the parameters
6 * o sync/async switching ?
7 *
8 * Note: This does _not_ implement CCITT X.25 asynchronous framing
9 * recommendations. Its primarily for testing purposes. If you wanted
10 * to do CCITT then in theory all you need is to nick the HDLC async
11 * checksum routines from ppp.c
12 * Changes:
13 *
14 * 2000-10-29 Henner Eisen lapb_data_indication() return status.
15 */
16
17 #include <linux/module.h>
18
19 #include <asm/system.h>
20 #include <asm/uaccess.h>
21 #include <asm/bitops.h>
22 #include <linux/string.h>
23 #include <linux/mm.h>
24 #include <linux/interrupt.h>
25 #include <linux/in.h>
26 #include <linux/tty.h>
27 #include <linux/errno.h>
28 #include <linux/netdevice.h>
29 #include <linux/etherdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/if_arp.h>
32 #include <linux/x25.h>
33 #include <linux/lapb.h>
34 #include <linux/init.h>
35 #include "x25_asy.h"
36
37 typedef struct x25_ctrl {
38 struct x25_asy ctrl; /* X.25 things */
39 struct net_device dev; /* the device */
40 } x25_asy_ctrl_t;
41
42 static x25_asy_ctrl_t **x25_asy_ctrls = NULL;
43
44 int x25_asy_maxdev = SL_NRUNIT; /* Can be overridden with insmod! */
45
46 MODULE_PARM(x25_asy_maxdev, "i");
47 MODULE_LICENSE("GPL");
48
49 static struct tty_ldisc x25_ldisc;
50
51 static int x25_asy_esc(unsigned char *p, unsigned char *d, int len);
52 static void x25_asy_unesc(struct x25_asy *sl, unsigned char c);
53
54 /* Find a free X.25 channel, and link in this `tty' line. */
x25_asy_alloc(void)55 static inline struct x25_asy *x25_asy_alloc(void)
56 {
57 x25_asy_ctrl_t *slp = NULL;
58 int i;
59
60 if (x25_asy_ctrls == NULL)
61 return NULL; /* Master array missing ! */
62
63 for (i = 0; i < x25_asy_maxdev; i++)
64 {
65 slp = x25_asy_ctrls[i];
66 /* Not allocated ? */
67 if (slp == NULL)
68 break;
69 /* Not in use ? */
70 if (!test_and_set_bit(SLF_INUSE, &slp->ctrl.flags))
71 break;
72 }
73 /* SLP is set.. */
74
75 /* Sorry, too many, all slots in use */
76 if (i >= x25_asy_maxdev)
77 return NULL;
78
79 /* If no channels are available, allocate one */
80 if (!slp &&
81 (x25_asy_ctrls[i] = (x25_asy_ctrl_t *)kmalloc(sizeof(x25_asy_ctrl_t),
82 GFP_KERNEL)) != NULL) {
83 slp = x25_asy_ctrls[i];
84 memset(slp, 0, sizeof(x25_asy_ctrl_t));
85
86 /* Initialize channel control data */
87 set_bit(SLF_INUSE, &slp->ctrl.flags);
88 slp->ctrl.tty = NULL;
89 sprintf(slp->dev.name, "x25asy%d", i);
90 slp->dev.base_addr = i;
91 slp->dev.priv = (void*)&(slp->ctrl);
92 slp->dev.next = NULL;
93 slp->dev.init = x25_asy_init;
94 }
95 if (slp != NULL)
96 {
97
98 /* register device so that it can be ifconfig'ed */
99 /* x25_asy_init() will be called as a side-effect */
100 /* SIDE-EFFECT WARNING: x25_asy_init() CLEARS slp->ctrl ! */
101
102 if (register_netdev(&(slp->dev)) == 0)
103 {
104 /* (Re-)Set the INUSE bit. Very Important! */
105 set_bit(SLF_INUSE, &slp->ctrl.flags);
106 slp->ctrl.dev = &(slp->dev);
107 slp->dev.priv = (void*)&(slp->ctrl);
108 return (&(slp->ctrl));
109 }
110 else
111 {
112 clear_bit(SLF_INUSE,&(slp->ctrl.flags));
113 printk("x25_asy_alloc() - register_netdev() failure.\n");
114 }
115 }
116 return NULL;
117 }
118
119
120 /* Free an X.25 channel. */
121
x25_asy_free(struct x25_asy * sl)122 static inline void x25_asy_free(struct x25_asy *sl)
123 {
124 /* Free all X.25 frame buffers. */
125 if (sl->rbuff) {
126 kfree(sl->rbuff);
127 }
128 sl->rbuff = NULL;
129 if (sl->xbuff) {
130 kfree(sl->xbuff);
131 }
132 sl->xbuff = NULL;
133
134 if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
135 printk("%s: x25_asy_free for already free unit.\n", sl->dev->name);
136 }
137 }
138
139 /* MTU has been changed by the IP layer. Unfortunately we are not told
140 about this, but we spot it ourselves and fix things up. We could be
141 in an upcall from the tty driver, or in an ip packet queue. */
142
x25_asy_changed_mtu(struct x25_asy * sl)143 static void x25_asy_changed_mtu(struct x25_asy *sl)
144 {
145 struct net_device *dev = sl->dev;
146 unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
147 int len;
148 unsigned long flags;
149
150 len = dev->mtu * 2;
151
152 xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
153 rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC);
154
155 if (xbuff == NULL || rbuff == NULL)
156 {
157 printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
158 sl->dev->name);
159 dev->mtu = sl->mtu;
160 if (xbuff != NULL)
161 kfree(xbuff);
162 if (rbuff != NULL)
163 kfree(rbuff);
164 return;
165 }
166
167 save_flags(flags);
168 cli();
169
170 oxbuff = sl->xbuff;
171 sl->xbuff = xbuff;
172 orbuff = sl->rbuff;
173 sl->rbuff = rbuff;
174
175 if (sl->xleft) {
176 if (sl->xleft <= len) {
177 memcpy(sl->xbuff, sl->xhead, sl->xleft);
178 } else {
179 sl->xleft = 0;
180 sl->tx_dropped++;
181 }
182 }
183 sl->xhead = sl->xbuff;
184
185 if (sl->rcount) {
186 if (sl->rcount <= len) {
187 memcpy(sl->rbuff, orbuff, sl->rcount);
188 } else {
189 sl->rcount = 0;
190 sl->rx_over_errors++;
191 set_bit(SLF_ERROR, &sl->flags);
192 }
193 }
194 sl->mtu = dev->mtu;
195
196 sl->buffsize = len;
197
198 restore_flags(flags);
199
200 if (oxbuff != NULL)
201 kfree(oxbuff);
202 if (orbuff != NULL)
203 kfree(orbuff);
204 }
205
206
207 /* Set the "sending" flag. This must be atomic, hence the ASM. */
208
x25_asy_lock(struct x25_asy * sl)209 static inline void x25_asy_lock(struct x25_asy *sl)
210 {
211 netif_stop_queue(sl->dev);
212 }
213
214
215 /* Clear the "sending" flag. This must be atomic, hence the ASM. */
216
x25_asy_unlock(struct x25_asy * sl)217 static inline void x25_asy_unlock(struct x25_asy *sl)
218 {
219 netif_wake_queue(sl->dev);
220 }
221
222 /* Send one completely decapsulated IP datagram to the IP layer. */
223
x25_asy_bump(struct x25_asy * sl)224 static void x25_asy_bump(struct x25_asy *sl)
225 {
226 struct sk_buff *skb;
227 int count;
228 int err;
229
230 count = sl->rcount;
231 sl->rx_bytes+=count;
232
233 skb = dev_alloc_skb(count+1);
234 if (skb == NULL)
235 {
236 printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
237 sl->rx_dropped++;
238 return;
239 }
240 skb_push(skb,1); /* LAPB internal control */
241 skb->dev = sl->dev;
242 memcpy(skb_put(skb,count), sl->rbuff, count);
243 skb->mac.raw=skb->data;
244 skb->protocol=htons(ETH_P_X25);
245 if((err=lapb_data_received(sl,skb))!=LAPB_OK)
246 {
247 kfree_skb(skb);
248 printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
249 }
250 else
251 {
252 netif_rx(skb);
253 sl->rx_packets++;
254 }
255 }
256
257 /* Encapsulate one IP datagram and stuff into a TTY queue. */
x25_asy_encaps(struct x25_asy * sl,unsigned char * icp,int len)258 static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
259 {
260 unsigned char *p;
261 int actual, count;
262
263
264 if (sl->mtu != sl->dev->mtu) { /* Someone has been ifconfigging */
265
266 x25_asy_changed_mtu(sl);
267 }
268
269 if (len > sl->mtu)
270 { /* Sigh, shouldn't occur BUT ... */
271 len = sl->mtu;
272 printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
273 sl->tx_dropped++;
274 x25_asy_unlock(sl);
275 return;
276 }
277
278 p = icp;
279 count = x25_asy_esc(p, (unsigned char *) sl->xbuff, len);
280
281 /* Order of next two lines is *very* important.
282 * When we are sending a little amount of data,
283 * the transfer may be completed inside driver.write()
284 * routine, because it's running with interrupts enabled.
285 * In this case we *never* got WRITE_WAKEUP event,
286 * if we did not request it before write operation.
287 * 14 Oct 1994 Dmitry Gorodchanin.
288 */
289 sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
290 actual = sl->tty->driver.write(sl->tty, 0, sl->xbuff, count);
291 sl->xleft = count - actual;
292 sl->xhead = sl->xbuff + actual;
293 /* VSV */
294 clear_bit(SLF_OUTWAIT, &sl->flags); /* reset outfill flag */
295 }
296
297 /*
298 * Called by the driver when there's room for more data. If we have
299 * more packets to send, we send them here.
300 */
x25_asy_write_wakeup(struct tty_struct * tty)301 static void x25_asy_write_wakeup(struct tty_struct *tty)
302 {
303 int actual;
304 struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
305
306 /* First make sure we're connected. */
307 if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
308 return;
309
310 if (sl->xleft <= 0)
311 {
312 /* Now serial buffer is almost free & we can start
313 * transmission of another packet */
314 sl->tx_packets++;
315 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
316 x25_asy_unlock(sl);
317 return;
318 }
319
320 actual = tty->driver.write(tty, 0, sl->xhead, sl->xleft);
321 sl->xleft -= actual;
322 sl->xhead += actual;
323 }
324
x25_asy_timeout(struct net_device * dev)325 static void x25_asy_timeout(struct net_device *dev)
326 {
327 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
328 /* May be we must check transmitter timeout here ?
329 * 14 Oct 1994 Dmitry Gorodchanin.
330 */
331 printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
332 (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
333 "bad line quality" : "driver error");
334 sl->xleft = 0;
335 sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
336 x25_asy_unlock(sl);
337 }
338
339 /* Encapsulate an IP datagram and kick it into a TTY queue. */
340
x25_asy_xmit(struct sk_buff * skb,struct net_device * dev)341 static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
342 {
343 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
344 int err;
345
346 if (!netif_running(sl->dev))
347 {
348 printk("%s: xmit call when iface is down\n", dev->name);
349 return 1;
350 }
351
352 switch(skb->data[0])
353 {
354 case 0x00:break;
355 case 0x01: /* Connection request .. do nothing */
356 if((err=lapb_connect_request(sl))!=LAPB_OK)
357 printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
358 kfree_skb(skb);
359 return 0;
360 case 0x02: /* Disconnect request .. do nothing - hang up ?? */
361 if((err=lapb_disconnect_request(sl))!=LAPB_OK)
362 printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
363 default:
364 kfree_skb(skb);
365 return 0;
366 }
367 skb_pull(skb,1); /* Remove control byte */
368 /*
369 * If we are busy already- too bad. We ought to be able
370 * to queue things at this point, to allow for a little
371 * frame buffer. Oh well...
372 * -----------------------------------------------------
373 * I hate queues in X.25 driver. May be it's efficient,
374 * but for me latency is more important. ;)
375 * So, no queues !
376 * 14 Oct 1994 Dmitry Gorodchanin.
377 */
378
379 if((err=lapb_data_request(sl,skb))!=LAPB_OK)
380 {
381 printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
382 kfree_skb(skb);
383 return 0;
384 }
385 return 0;
386 }
387
388
389 /*
390 * LAPB interface boilerplate
391 */
392
393 /*
394 * Called when I frame data arrives. We did the work above - throw it
395 * at the net layer.
396 */
397
x25_asy_data_indication(void * token,struct sk_buff * skb)398 static int x25_asy_data_indication(void *token, struct sk_buff *skb)
399 {
400 return netif_rx(skb);
401 }
402
403 /*
404 * Data has emerged from the LAPB protocol machine. We don't handle
405 * busy cases too well. Its tricky to see how to do this nicely -
406 * perhaps lapb should allow us to bounce this ?
407 */
408
x25_asy_data_transmit(void * token,struct sk_buff * skb)409 static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
410 {
411 struct x25_asy *sl=token;
412 if (netif_queue_stopped(sl->dev))
413 {
414 printk(KERN_ERR "x25_asy: tbusy drop\n");
415 kfree_skb(skb);
416 return;
417 }
418 /* We were not busy, so we are now... :-) */
419 if (skb != NULL)
420 {
421 x25_asy_lock(sl);
422 sl->tx_bytes+=skb->len;
423 x25_asy_encaps(sl, skb->data, skb->len);
424 dev_kfree_skb(skb);
425 }
426 }
427
428 /*
429 * LAPB connection establish/down information.
430 */
431
x25_asy_connected(void * token,int reason)432 static void x25_asy_connected(void *token, int reason)
433 {
434 struct x25_asy *sl = token;
435 struct sk_buff *skb;
436 unsigned char *ptr;
437
438 if ((skb = dev_alloc_skb(1)) == NULL) {
439 printk(KERN_ERR "lapbeth: out of memory\n");
440 return;
441 }
442
443 ptr = skb_put(skb, 1);
444 *ptr = 0x01;
445
446 skb->dev = sl->dev;
447 skb->protocol = htons(ETH_P_X25);
448 skb->mac.raw = skb->data;
449 skb->pkt_type = PACKET_HOST;
450
451 netif_rx(skb);
452 }
453
x25_asy_disconnected(void * token,int reason)454 static void x25_asy_disconnected(void *token, int reason)
455 {
456 struct x25_asy *sl = token;
457 struct sk_buff *skb;
458 unsigned char *ptr;
459
460 if ((skb = dev_alloc_skb(1)) == NULL) {
461 printk(KERN_ERR "x25_asy: out of memory\n");
462 return;
463 }
464
465 ptr = skb_put(skb, 1);
466 *ptr = 0x02;
467
468 skb->dev = sl->dev;
469 skb->protocol = htons(ETH_P_X25);
470 skb->mac.raw = skb->data;
471 skb->pkt_type = PACKET_HOST;
472
473 netif_rx(skb);
474 }
475
476
477 /* Open the low-level part of the X.25 channel. Easy! */
478
x25_asy_open(struct net_device * dev)479 static int x25_asy_open(struct net_device *dev)
480 {
481 struct lapb_register_struct x25_asy_callbacks;
482 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
483 unsigned long len;
484 int err;
485
486 if (sl->tty == NULL)
487 return -ENODEV;
488
489 /*
490 * Allocate the X.25 frame buffers:
491 *
492 * rbuff Receive buffer.
493 * xbuff Transmit buffer.
494 */
495
496 len = dev->mtu * 2;
497
498 sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
499 if (sl->rbuff == NULL) {
500 goto norbuff;
501 }
502 sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
503 if (sl->xbuff == NULL) {
504 goto noxbuff;
505 }
506 sl->mtu = dev->mtu;
507 sl->buffsize = len;
508 sl->rcount = 0;
509 sl->xleft = 0;
510 sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
511
512 netif_start_queue(dev);
513
514 /*
515 * Now attach LAPB
516 */
517
518 x25_asy_callbacks.connect_confirmation=x25_asy_connected;
519 x25_asy_callbacks.connect_indication=x25_asy_connected;
520 x25_asy_callbacks.disconnect_confirmation=x25_asy_disconnected;
521 x25_asy_callbacks.disconnect_indication=x25_asy_disconnected;
522 x25_asy_callbacks.data_indication=x25_asy_data_indication;
523 x25_asy_callbacks.data_transmit=x25_asy_data_transmit;
524
525 if((err=lapb_register(sl, &x25_asy_callbacks))==LAPB_OK)
526 return 0;
527
528 /* Cleanup */
529 kfree(sl->xbuff);
530 noxbuff:
531 kfree(sl->rbuff);
532 norbuff:
533 return -ENOMEM;
534 }
535
536
537 /* Close the low-level part of the X.25 channel. Easy! */
x25_asy_close(struct net_device * dev)538 static int x25_asy_close(struct net_device *dev)
539 {
540 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
541 int err;
542
543 if (sl->tty == NULL)
544 return -EBUSY;
545
546 sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
547 netif_stop_queue(dev);
548 if((err=lapb_unregister(sl))!=LAPB_OK)
549 printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
550 return 0;
551 }
552
x25_asy_receive_room(struct tty_struct * tty)553 static int x25_asy_receive_room(struct tty_struct *tty)
554 {
555 return 65536; /* We can handle an infinite amount of data. :-) */
556 }
557
558 /*
559 * Handle the 'receiver data ready' interrupt.
560 * This function is called by the 'tty_io' module in the kernel when
561 * a block of X.25 data has been received, which can now be decapsulated
562 * and sent on to some IP layer for further processing.
563 */
564
x25_asy_receive_buf(struct tty_struct * tty,const unsigned char * cp,char * fp,int count)565 static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
566 {
567 struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
568
569 if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
570 return;
571
572 /*
573 * Argh! mtu change time! - costs us the packet part received
574 * at the change
575 */
576 if (sl->mtu != sl->dev->mtu) {
577
578 x25_asy_changed_mtu(sl);
579 }
580
581 /* Read the characters out of the buffer */
582 while (count--) {
583 if (fp && *fp++) {
584 if (!test_and_set_bit(SLF_ERROR, &sl->flags)) {
585 sl->rx_errors++;
586 }
587 cp++;
588 continue;
589 }
590 x25_asy_unesc(sl, *cp++);
591 }
592 }
593
594 /*
595 * Open the high-level part of the X.25 channel.
596 * This function is called by the TTY module when the
597 * X.25 line discipline is called for. Because we are
598 * sure the tty line exists, we only have to link it to
599 * a free X.25 channel...
600 */
601
x25_asy_open_tty(struct tty_struct * tty)602 static int x25_asy_open_tty(struct tty_struct *tty)
603 {
604 struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
605 int err;
606
607 /* First make sure we're not already connected. */
608 if (sl && sl->magic == X25_ASY_MAGIC) {
609 return -EEXIST;
610 }
611
612 /* OK. Find a free X.25 channel to use. */
613 if ((sl = x25_asy_alloc()) == NULL) {
614 return -ENFILE;
615 }
616
617 sl->tty = tty;
618 tty->disc_data = sl;
619 if (tty->driver.flush_buffer) {
620 tty->driver.flush_buffer(tty);
621 }
622 tty_ldisc_flush(tty);
623
624 /* Restore default settings */
625 sl->dev->type = ARPHRD_X25;
626
627 /* Perform the low-level X.25 async init */
628 if ((err = x25_asy_open(sl->dev)))
629 return err;
630
631 MOD_INC_USE_COUNT;
632
633 /* Done. We have linked the TTY line to a channel. */
634 return sl->dev->base_addr;
635 }
636
637
638 /*
639 * Close down an X.25 channel.
640 * This means flushing out any pending queues, and then restoring the
641 * TTY line discipline to what it was before it got hooked to X.25
642 * (which usually is TTY again).
643 */
x25_asy_close_tty(struct tty_struct * tty)644 static void x25_asy_close_tty(struct tty_struct *tty)
645 {
646 struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
647
648 /* First make sure we're connected. */
649 if (!sl || sl->magic != X25_ASY_MAGIC)
650 return;
651
652 if (sl->dev->flags & IFF_UP)
653 {
654 (void) dev_close(sl->dev);
655 }
656
657 tty->disc_data = 0;
658 sl->tty = NULL;
659 x25_asy_free(sl);
660 unregister_netdev(sl->dev);
661 MOD_DEC_USE_COUNT;
662 }
663
664
x25_asy_get_stats(struct net_device * dev)665 static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
666 {
667 static struct net_device_stats stats;
668 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
669
670 memset(&stats, 0, sizeof(struct net_device_stats));
671
672 stats.rx_packets = sl->rx_packets;
673 stats.tx_packets = sl->tx_packets;
674 stats.rx_bytes = sl->rx_bytes;
675 stats.tx_bytes = sl->tx_bytes;
676 stats.rx_dropped = sl->rx_dropped;
677 stats.tx_dropped = sl->tx_dropped;
678 stats.tx_errors = sl->tx_errors;
679 stats.rx_errors = sl->rx_errors;
680 stats.rx_over_errors = sl->rx_over_errors;
681 return (&stats);
682 }
683
684
685 /************************************************************************
686 * STANDARD X.25 ENCAPSULATION *
687 ************************************************************************/
688
x25_asy_esc(unsigned char * s,unsigned char * d,int len)689 int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
690 {
691 unsigned char *ptr = d;
692 unsigned char c;
693
694 /*
695 * Send an initial END character to flush out any
696 * data that may have accumulated in the receiver
697 * due to line noise.
698 */
699
700 *ptr++ = X25_END; /* Send 10111110 bit seq */
701
702 /*
703 * For each byte in the packet, send the appropriate
704 * character sequence, according to the X.25 protocol.
705 */
706
707 while (len-- > 0)
708 {
709 switch(c = *s++)
710 {
711 case X25_END:
712 *ptr++ = X25_ESC;
713 *ptr++ = X25_ESCAPE(X25_END);
714 break;
715 case X25_ESC:
716 *ptr++ = X25_ESC;
717 *ptr++ = X25_ESCAPE(X25_ESC);
718 break;
719 default:
720 *ptr++ = c;
721 break;
722 }
723 }
724 *ptr++ = X25_END;
725 return (ptr - d);
726 }
727
x25_asy_unesc(struct x25_asy * sl,unsigned char s)728 static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
729 {
730
731 switch(s)
732 {
733 case X25_END:
734 if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))
735 {
736 x25_asy_bump(sl);
737 }
738 clear_bit(SLF_ESCAPE, &sl->flags);
739 sl->rcount = 0;
740 return;
741
742 case X25_ESC:
743 set_bit(SLF_ESCAPE, &sl->flags);
744 return;
745
746 case X25_ESCAPE(X25_ESC):
747 case X25_ESCAPE(X25_END):
748 if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
749 s = X25_UNESCAPE(s);
750 break;
751 }
752 if (!test_bit(SLF_ERROR, &sl->flags))
753 {
754 if (sl->rcount < sl->buffsize)
755 {
756 sl->rbuff[sl->rcount++] = s;
757 return;
758 }
759 sl->rx_over_errors++;
760 set_bit(SLF_ERROR, &sl->flags);
761 }
762 }
763
764
765 /* Perform I/O control on an active X.25 channel. */
x25_asy_ioctl(struct tty_struct * tty,void * file,int cmd,void * arg)766 static int x25_asy_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
767 {
768 struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
769
770 /* First make sure we're connected. */
771 if (!sl || sl->magic != X25_ASY_MAGIC) {
772 return -EINVAL;
773 }
774
775 switch(cmd)
776 {
777 case SIOCGIFNAME:
778 if(copy_to_user(arg, sl->dev->name, strlen(sl->dev->name) + 1))
779 return -EFAULT;
780 return 0;
781
782 case SIOCSIFHWADDR:
783 return -EINVAL;
784
785 /* Allow stty to read, but not set, the serial port */
786 case TCGETS:
787 case TCGETA:
788 return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
789
790 default:
791 return -ENOIOCTLCMD;
792 }
793 }
794
x25_asy_open_dev(struct net_device * dev)795 static int x25_asy_open_dev(struct net_device *dev)
796 {
797 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
798 if(sl->tty==NULL)
799 return -ENODEV;
800 return 0;
801 }
802
803 /* Initialize X.25 control device -- register X.25 line discipline */
804
x25_asy_init_ctrl_dev(void)805 int __init x25_asy_init_ctrl_dev(void)
806 {
807 int status;
808
809 if (x25_asy_maxdev < 4) x25_asy_maxdev = 4; /* Sanity */
810
811 printk(KERN_INFO "X.25 async: version 0.00 ALPHA (dynamic channels, max=%d).\n",
812 x25_asy_maxdev );
813 x25_asy_ctrls = (x25_asy_ctrl_t **) kmalloc(sizeof(void*)*x25_asy_maxdev, GFP_KERNEL);
814 if (x25_asy_ctrls == NULL)
815 {
816 printk("X25 async: Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n");
817 return -ENOMEM;
818 }
819
820 /* Clear the pointer array, we allocate devices when we need them */
821 memset(x25_asy_ctrls, 0, sizeof(void*)*x25_asy_maxdev); /* Pointers */
822
823 /* Fill in our line protocol discipline, and register it */
824 memset(&x25_ldisc, 0, sizeof(x25_ldisc));
825 x25_ldisc.magic = TTY_LDISC_MAGIC;
826 x25_ldisc.name = "X.25";
827 x25_ldisc.flags = 0;
828 x25_ldisc.open = x25_asy_open_tty;
829 x25_ldisc.close = x25_asy_close_tty;
830 x25_ldisc.read = NULL;
831 x25_ldisc.write = NULL;
832 x25_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
833 unsigned int, unsigned long)) x25_asy_ioctl;
834 x25_ldisc.poll = NULL;
835 x25_ldisc.receive_buf = x25_asy_receive_buf;
836 x25_ldisc.receive_room = x25_asy_receive_room;
837 x25_ldisc.write_wakeup = x25_asy_write_wakeup;
838 if ((status = tty_register_ldisc(N_X25, &x25_ldisc)) != 0) {
839 printk("X.25 async: can't register line discipline (err = %d)\n", status);
840 }
841
842 return status;
843 }
844
845
846 /* Initialise the X.25 driver. Called by the device init code */
847
x25_asy_init(struct net_device * dev)848 int x25_asy_init(struct net_device *dev)
849 {
850 struct x25_asy *sl = (struct x25_asy*)(dev->priv);
851
852 if (sl == NULL) /* Allocation failed ?? */
853 return -ENODEV;
854
855 /* Set up the control block. (And clear statistics) */
856
857 memset(sl, 0, sizeof (struct x25_asy));
858 sl->magic = X25_ASY_MAGIC;
859 sl->dev = dev;
860
861 /*
862 * Finish setting up the DEVICE info.
863 */
864
865 dev->mtu = SL_MTU;
866 dev->hard_start_xmit = x25_asy_xmit;
867 dev->tx_timeout = x25_asy_timeout;
868 dev->watchdog_timeo = HZ*20;
869 dev->open = x25_asy_open_dev;
870 dev->stop = x25_asy_close;
871 dev->get_stats = x25_asy_get_stats;
872 dev->hard_header_len = 0;
873 dev->addr_len = 0;
874 dev->type = ARPHRD_X25;
875 dev->tx_queue_len = 10;
876
877 /* New-style flags. */
878 dev->flags = IFF_NOARP;
879
880 return 0;
881 }
882 #ifdef MODULE
883
884 int
init_module(void)885 init_module(void)
886 {
887 return x25_asy_init_ctrl_dev();
888 }
889
890 void
cleanup_module(void)891 cleanup_module(void)
892 {
893 int i;
894
895 if (x25_asy_ctrls != NULL)
896 {
897 for (i = 0; i < x25_asy_maxdev; i++)
898 {
899 if (x25_asy_ctrls[i])
900 {
901 /*
902 * VSV = if dev->start==0, then device
903 * unregistered while close proc.
904 */
905 if (netif_running(&(x25_asy_ctrls[i]->dev)))
906 unregister_netdev(&(x25_asy_ctrls[i]->dev));
907
908 kfree(x25_asy_ctrls[i]);
909 x25_asy_ctrls[i] = NULL;
910 }
911 }
912 kfree(x25_asy_ctrls);
913 x25_asy_ctrls = NULL;
914 }
915 if ((i = tty_register_ldisc(N_X25, NULL)))
916 {
917 printk("X.25 async: can't unregister line discipline (err = %d)\n", i);
918 }
919 }
920 #endif /* MODULE */
921
922