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