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