linux/drivers/net/hamradio/6pack.c
<<
>>
Prefs
   1/*
   2 * 6pack.c      This module implements the 6pack protocol for kernel-based
   3 *              devices like TTY. It interfaces between a raw TTY and the
   4 *              kernel's AX.25 protocol layers.
   5 *
   6 * Authors:     Andreas Könsgen <ajk@comnets.uni-bremen.de>
   7 *              Ralf Baechle DL5RB <ralf@linux-mips.org>
   8 *
   9 * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
  10 *
  11 *              Laurence Culhane, <loz@holmes.demon.co.uk>
  12 *              Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  13 */
  14
  15#include <linux/module.h>
  16#include <asm/uaccess.h>
  17#include <linux/bitops.h>
  18#include <linux/string.h>
  19#include <linux/mm.h>
  20#include <linux/interrupt.h>
  21#include <linux/in.h>
  22#include <linux/tty.h>
  23#include <linux/errno.h>
  24#include <linux/netdevice.h>
  25#include <linux/timer.h>
  26#include <linux/slab.h>
  27#include <net/ax25.h>
  28#include <linux/etherdevice.h>
  29#include <linux/skbuff.h>
  30#include <linux/rtnetlink.h>
  31#include <linux/spinlock.h>
  32#include <linux/if_arp.h>
  33#include <linux/init.h>
  34#include <linux/ip.h>
  35#include <linux/tcp.h>
  36#include <linux/semaphore.h>
  37#include <linux/compat.h>
  38#include <linux/atomic.h>
  39
  40#define SIXPACK_VERSION    "Revision: 0.3.0"
  41
  42/* sixpack priority commands */
  43#define SIXP_SEOF               0x40    /* start and end of a 6pack frame */
  44#define SIXP_TX_URUN            0x48    /* transmit overrun */
  45#define SIXP_RX_ORUN            0x50    /* receive overrun */
  46#define SIXP_RX_BUF_OVL         0x58    /* receive buffer overflow */
  47
  48#define SIXP_CHKSUM             0xFF    /* valid checksum of a 6pack frame */
  49
  50/* masks to get certain bits out of the status bytes sent by the TNC */
  51
  52#define SIXP_CMD_MASK           0xC0
  53#define SIXP_CHN_MASK           0x07
  54#define SIXP_PRIO_CMD_MASK      0x80
  55#define SIXP_STD_CMD_MASK       0x40
  56#define SIXP_PRIO_DATA_MASK     0x38
  57#define SIXP_TX_MASK            0x20
  58#define SIXP_RX_MASK            0x10
  59#define SIXP_RX_DCD_MASK        0x18
  60#define SIXP_LEDS_ON            0x78
  61#define SIXP_LEDS_OFF           0x60
  62#define SIXP_CON                0x08
  63#define SIXP_STA                0x10
  64
  65#define SIXP_FOUND_TNC          0xe9
  66#define SIXP_CON_ON             0x68
  67#define SIXP_DCD_MASK           0x08
  68#define SIXP_DAMA_OFF           0
  69
  70/* default level 2 parameters */
  71#define SIXP_TXDELAY                    (HZ/4)  /* in 1 s */
  72#define SIXP_PERSIST                    50      /* in 256ths */
  73#define SIXP_SLOTTIME                   (HZ/10) /* in 1 s */
  74#define SIXP_INIT_RESYNC_TIMEOUT        (3*HZ/2) /* in 1 s */
  75#define SIXP_RESYNC_TIMEOUT             5*HZ    /* in 1 s */
  76
  77/* 6pack configuration. */
  78#define SIXP_NRUNIT                     31      /* MAX number of 6pack channels */
  79#define SIXP_MTU                        256     /* Default MTU */
  80
  81enum sixpack_flags {
  82        SIXPF_ERROR,    /* Parity, etc. error   */
  83};
  84
  85struct sixpack {
  86        /* Various fields. */
  87        struct tty_struct       *tty;           /* ptr to TTY structure */
  88        struct net_device       *dev;           /* easy for intr handling  */
  89
  90        /* These are pointers to the malloc()ed frame buffers. */
  91        unsigned char           *rbuff;         /* receiver buffer      */
  92        int                     rcount;         /* received chars counter  */
  93        unsigned char           *xbuff;         /* transmitter buffer   */
  94        unsigned char           *xhead;         /* next byte to XMIT */
  95        int                     xleft;          /* bytes left in XMIT queue  */
  96
  97        unsigned char           raw_buf[4];
  98        unsigned char           cooked_buf[400];
  99
 100        unsigned int            rx_count;
 101        unsigned int            rx_count_cooked;
 102
 103        int                     mtu;            /* Our mtu (to spot changes!) */
 104        int                     buffsize;       /* Max buffers sizes */
 105
 106        unsigned long           flags;          /* Flag values/ mode etc */
 107        unsigned char           mode;           /* 6pack mode */
 108
 109        /* 6pack stuff */
 110        unsigned char           tx_delay;
 111        unsigned char           persistence;
 112        unsigned char           slottime;
 113        unsigned char           duplex;
 114        unsigned char           led_state;
 115        unsigned char           status;
 116        unsigned char           status1;
 117        unsigned char           status2;
 118        unsigned char           tx_enable;
 119        unsigned char           tnc_state;
 120
 121        struct timer_list       tx_t;
 122        struct timer_list       resync_t;
 123        atomic_t                refcnt;
 124        struct semaphore        dead_sem;
 125        spinlock_t              lock;
 126};
 127
 128#define AX25_6PACK_HEADER_LEN 0
 129
 130static void sixpack_decode(struct sixpack *, unsigned char[], int);
 131static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
 132
 133/*
 134 * Perform the persistence/slottime algorithm for CSMA access. If the
 135 * persistence check was successful, write the data to the serial driver.
 136 * Note that in case of DAMA operation, the data is not sent here.
 137 */
 138
 139static void sp_xmit_on_air(unsigned long channel)
 140{
 141        struct sixpack *sp = (struct sixpack *) channel;
 142        int actual, when = sp->slottime;
 143        static unsigned char random;
 144
 145        random = random * 17 + 41;
 146
 147        if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
 148                sp->led_state = 0x70;
 149                sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 150                sp->tx_enable = 1;
 151                actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
 152                sp->xleft -= actual;
 153                sp->xhead += actual;
 154                sp->led_state = 0x60;
 155                sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 156                sp->status2 = 0;
 157        } else
 158                mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
 159}
 160
 161/* ----> 6pack timer interrupt handler and friends. <---- */
 162
 163/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
 164static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
 165{
 166        unsigned char *msg, *p = icp;
 167        int actual, count;
 168
 169        if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
 170                msg = "oversized transmit packet!";
 171                goto out_drop;
 172        }
 173
 174        if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
 175                msg = "oversized transmit packet!";
 176                goto out_drop;
 177        }
 178
 179        if (p[0] > 5) {
 180                msg = "invalid KISS command";
 181                goto out_drop;
 182        }
 183
 184        if ((p[0] != 0) && (len > 2)) {
 185                msg = "KISS control packet too long";
 186                goto out_drop;
 187        }
 188
 189        if ((p[0] == 0) && (len < 15)) {
 190                msg = "bad AX.25 packet to transmit";
 191                goto out_drop;
 192        }
 193
 194        count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
 195        set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
 196
 197        switch (p[0]) {
 198        case 1: sp->tx_delay = p[1];
 199                return;
 200        case 2: sp->persistence = p[1];
 201                return;
 202        case 3: sp->slottime = p[1];
 203                return;
 204        case 4: /* ignored */
 205                return;
 206        case 5: sp->duplex = p[1];
 207                return;
 208        }
 209
 210        if (p[0] != 0)
 211                return;
 212
 213        /*
 214         * In case of fullduplex or DAMA operation, we don't take care about the
 215         * state of the DCD or of any timers, as the determination of the
 216         * correct time to send is the job of the AX.25 layer. We send
 217         * immediately after data has arrived.
 218         */
 219        if (sp->duplex == 1) {
 220                sp->led_state = 0x70;
 221                sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 222                sp->tx_enable = 1;
 223                actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
 224                sp->xleft = count - actual;
 225                sp->xhead = sp->xbuff + actual;
 226                sp->led_state = 0x60;
 227                sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 228        } else {
 229                sp->xleft = count;
 230                sp->xhead = sp->xbuff;
 231                sp->status2 = count;
 232                sp_xmit_on_air((unsigned long)sp);
 233        }
 234
 235        return;
 236
 237out_drop:
 238        sp->dev->stats.tx_dropped++;
 239        netif_start_queue(sp->dev);
 240        if (net_ratelimit())
 241                printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
 242}
 243
 244/* Encapsulate an IP datagram and kick it into a TTY queue. */
 245
 246static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev)
 247{
 248        struct sixpack *sp = netdev_priv(dev);
 249
 250        spin_lock_bh(&sp->lock);
 251        /* We were not busy, so we are now... :-) */
 252        netif_stop_queue(dev);
 253        dev->stats.tx_bytes += skb->len;
 254        sp_encaps(sp, skb->data, skb->len);
 255        spin_unlock_bh(&sp->lock);
 256
 257        dev_kfree_skb(skb);
 258
 259        return NETDEV_TX_OK;
 260}
 261
 262static int sp_open_dev(struct net_device *dev)
 263{
 264        struct sixpack *sp = netdev_priv(dev);
 265
 266        if (sp->tty == NULL)
 267                return -ENODEV;
 268        return 0;
 269}
 270
 271/* Close the low-level part of the 6pack channel. */
 272static int sp_close(struct net_device *dev)
 273{
 274        struct sixpack *sp = netdev_priv(dev);
 275
 276        spin_lock_bh(&sp->lock);
 277        if (sp->tty) {
 278                /* TTY discipline is running. */
 279                clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
 280        }
 281        netif_stop_queue(dev);
 282        spin_unlock_bh(&sp->lock);
 283
 284        return 0;
 285}
 286
 287/* Return the frame type ID */
 288static int sp_header(struct sk_buff *skb, struct net_device *dev,
 289                     unsigned short type, const void *daddr,
 290                     const void *saddr, unsigned len)
 291{
 292#ifdef CONFIG_INET
 293        if (type != ETH_P_AX25)
 294                return ax25_hard_header(skb, dev, type, daddr, saddr, len);
 295#endif
 296        return 0;
 297}
 298
 299static int sp_set_mac_address(struct net_device *dev, void *addr)
 300{
 301        struct sockaddr_ax25 *sa = addr;
 302
 303        netif_tx_lock_bh(dev);
 304        netif_addr_lock(dev);
 305        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
 306        netif_addr_unlock(dev);
 307        netif_tx_unlock_bh(dev);
 308
 309        return 0;
 310}
 311
 312static int sp_rebuild_header(struct sk_buff *skb)
 313{
 314#ifdef CONFIG_INET
 315        return ax25_rebuild_header(skb);
 316#else
 317        return 0;
 318#endif
 319}
 320
 321static const struct header_ops sp_header_ops = {
 322        .create         = sp_header,
 323        .rebuild        = sp_rebuild_header,
 324};
 325
 326static const struct net_device_ops sp_netdev_ops = {
 327        .ndo_open               = sp_open_dev,
 328        .ndo_stop               = sp_close,
 329        .ndo_start_xmit         = sp_xmit,
 330        .ndo_set_mac_address    = sp_set_mac_address,
 331};
 332
 333static void sp_setup(struct net_device *dev)
 334{
 335        /* Finish setting up the DEVICE info. */
 336        dev->netdev_ops         = &sp_netdev_ops;
 337        dev->destructor         = free_netdev;
 338        dev->mtu                = SIXP_MTU;
 339        dev->hard_header_len    = AX25_MAX_HEADER_LEN;
 340        dev->header_ops         = &sp_header_ops;
 341
 342        dev->addr_len           = AX25_ADDR_LEN;
 343        dev->type               = ARPHRD_AX25;
 344        dev->tx_queue_len       = 10;
 345
 346        /* Only activated in AX.25 mode */
 347        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
 348        memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 349
 350        dev->flags              = 0;
 351}
 352
 353/* Send one completely decapsulated IP datagram to the IP layer. */
 354
 355/*
 356 * This is the routine that sends the received data to the kernel AX.25.
 357 * 'cmd' is the KISS command. For AX.25 data, it is zero.
 358 */
 359
 360static void sp_bump(struct sixpack *sp, char cmd)
 361{
 362        struct sk_buff *skb;
 363        int count;
 364        unsigned char *ptr;
 365
 366        count = sp->rcount + 1;
 367
 368        sp->dev->stats.rx_bytes += count;
 369
 370        if ((skb = dev_alloc_skb(count)) == NULL)
 371                goto out_mem;
 372
 373        ptr = skb_put(skb, count);
 374        *ptr++ = cmd;   /* KISS command */
 375
 376        memcpy(ptr, sp->cooked_buf + 1, count);
 377        skb->protocol = ax25_type_trans(skb, sp->dev);
 378        netif_rx(skb);
 379        sp->dev->stats.rx_packets++;
 380
 381        return;
 382
 383out_mem:
 384        sp->dev->stats.rx_dropped++;
 385}
 386
 387
 388/* ----------------------------------------------------------------------- */
 389
 390/*
 391 * We have a potential race on dereferencing tty->disc_data, because the tty
 392 * layer provides no locking at all - thus one cpu could be running
 393 * sixpack_receive_buf while another calls sixpack_close, which zeroes
 394 * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
 395 * best way to fix this is to use a rwlock in the tty struct, but for now we
 396 * use a single global rwlock for all ttys in ppp line discipline.
 397 */
 398static DEFINE_RWLOCK(disc_data_lock);
 399                                                                                
 400static struct sixpack *sp_get(struct tty_struct *tty)
 401{
 402        struct sixpack *sp;
 403
 404        read_lock(&disc_data_lock);
 405        sp = tty->disc_data;
 406        if (sp)
 407                atomic_inc(&sp->refcnt);
 408        read_unlock(&disc_data_lock);
 409
 410        return sp;
 411}
 412
 413static void sp_put(struct sixpack *sp)
 414{
 415        if (atomic_dec_and_test(&sp->refcnt))
 416                up(&sp->dead_sem);
 417}
 418
 419/*
 420 * Called by the TTY driver when there's room for more data.  If we have
 421 * more packets to send, we send them here.
 422 */
 423static void sixpack_write_wakeup(struct tty_struct *tty)
 424{
 425        struct sixpack *sp = sp_get(tty);
 426        int actual;
 427
 428        if (!sp)
 429                return;
 430        if (sp->xleft <= 0)  {
 431                /* Now serial buffer is almost free & we can start
 432                 * transmission of another packet */
 433                sp->dev->stats.tx_packets++;
 434                clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 435                sp->tx_enable = 0;
 436                netif_wake_queue(sp->dev);
 437                goto out;
 438        }
 439
 440        if (sp->tx_enable) {
 441                actual = tty->ops->write(tty, sp->xhead, sp->xleft);
 442                sp->xleft -= actual;
 443                sp->xhead += actual;
 444        }
 445
 446out:
 447        sp_put(sp);
 448}
 449
 450/* ----------------------------------------------------------------------- */
 451
 452/*
 453 * Handle the 'receiver data ready' interrupt.
 454 * This function is called by the 'tty_io' module in the kernel when
 455 * a block of 6pack data has been received, which can now be decapsulated
 456 * and sent on to some IP layer for further processing.
 457 */
 458static void sixpack_receive_buf(struct tty_struct *tty,
 459        const unsigned char *cp, char *fp, int count)
 460{
 461        struct sixpack *sp;
 462        unsigned char buf[512];
 463        int count1;
 464
 465        if (!count)
 466                return;
 467
 468        sp = sp_get(tty);
 469        if (!sp)
 470                return;
 471
 472        memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf));
 473
 474        /* Read the characters out of the buffer */
 475
 476        count1 = count;
 477        while (count) {
 478                count--;
 479                if (fp && *fp++) {
 480                        if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
 481                                sp->dev->stats.rx_errors++;
 482                        continue;
 483                }
 484        }
 485        sixpack_decode(sp, buf, count1);
 486
 487        sp_put(sp);
 488        tty_unthrottle(tty);
 489}
 490
 491/*
 492 * Try to resync the TNC. Called by the resync timer defined in
 493 * decode_prio_command
 494 */
 495
 496#define TNC_UNINITIALIZED       0
 497#define TNC_UNSYNC_STARTUP      1
 498#define TNC_UNSYNCED            2
 499#define TNC_IN_SYNC             3
 500
 501static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
 502{
 503        char *msg;
 504
 505        switch (new_tnc_state) {
 506        default:                        /* gcc oh piece-o-crap ... */
 507        case TNC_UNSYNC_STARTUP:
 508                msg = "Synchronizing with TNC";
 509                break;
 510        case TNC_UNSYNCED:
 511                msg = "Lost synchronization with TNC\n";
 512                break;
 513        case TNC_IN_SYNC:
 514                msg = "Found TNC";
 515                break;
 516        }
 517
 518        sp->tnc_state = new_tnc_state;
 519        printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);
 520}
 521
 522static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
 523{
 524        int old_tnc_state = sp->tnc_state;
 525
 526        if (old_tnc_state != new_tnc_state)
 527                __tnc_set_sync_state(sp, new_tnc_state);
 528}
 529
 530static void resync_tnc(unsigned long channel)
 531{
 532        struct sixpack *sp = (struct sixpack *) channel;
 533        static char resync_cmd = 0xe8;
 534
 535        /* clear any data that might have been received */
 536
 537        sp->rx_count = 0;
 538        sp->rx_count_cooked = 0;
 539
 540        /* reset state machine */
 541
 542        sp->status = 1;
 543        sp->status1 = 1;
 544        sp->status2 = 0;
 545
 546        /* resync the TNC */
 547
 548        sp->led_state = 0x60;
 549        sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 550        sp->tty->ops->write(sp->tty, &resync_cmd, 1);
 551
 552
 553        /* Start resync timer again -- the TNC might be still absent */
 554
 555        del_timer(&sp->resync_t);
 556        sp->resync_t.data       = (unsigned long) sp;
 557        sp->resync_t.function   = resync_tnc;
 558        sp->resync_t.expires    = jiffies + SIXP_RESYNC_TIMEOUT;
 559        add_timer(&sp->resync_t);
 560}
 561
 562static inline int tnc_init(struct sixpack *sp)
 563{
 564        unsigned char inbyte = 0xe8;
 565
 566        tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
 567
 568        sp->tty->ops->write(sp->tty, &inbyte, 1);
 569
 570        del_timer(&sp->resync_t);
 571        sp->resync_t.data = (unsigned long) sp;
 572        sp->resync_t.function = resync_tnc;
 573        sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
 574        add_timer(&sp->resync_t);
 575
 576        return 0;
 577}
 578
 579/*
 580 * Open the high-level part of the 6pack channel.
 581 * This function is called by the TTY module when the
 582 * 6pack line discipline is called for.  Because we are
 583 * sure the tty line exists, we only have to link it to
 584 * a free 6pcack channel...
 585 */
 586static int sixpack_open(struct tty_struct *tty)
 587{
 588        char *rbuff = NULL, *xbuff = NULL;
 589        struct net_device *dev;
 590        struct sixpack *sp;
 591        unsigned long len;
 592        int err = 0;
 593
 594        if (!capable(CAP_NET_ADMIN))
 595                return -EPERM;
 596        if (tty->ops->write == NULL)
 597                return -EOPNOTSUPP;
 598
 599        dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
 600        if (!dev) {
 601                err = -ENOMEM;
 602                goto out;
 603        }
 604
 605        sp = netdev_priv(dev);
 606        sp->dev = dev;
 607
 608        spin_lock_init(&sp->lock);
 609        atomic_set(&sp->refcnt, 1);
 610        sema_init(&sp->dead_sem, 0);
 611
 612        /* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
 613
 614        len = dev->mtu * 2;
 615
 616        rbuff = kmalloc(len + 4, GFP_KERNEL);
 617        xbuff = kmalloc(len + 4, GFP_KERNEL);
 618
 619        if (rbuff == NULL || xbuff == NULL) {
 620                err = -ENOBUFS;
 621                goto out_free;
 622        }
 623
 624        spin_lock_bh(&sp->lock);
 625
 626        sp->tty = tty;
 627
 628        sp->rbuff       = rbuff;
 629        sp->xbuff       = xbuff;
 630
 631        sp->mtu         = AX25_MTU + 73;
 632        sp->buffsize    = len;
 633        sp->rcount      = 0;
 634        sp->rx_count    = 0;
 635        sp->rx_count_cooked = 0;
 636        sp->xleft       = 0;
 637
 638        sp->flags       = 0;            /* Clear ESCAPE & ERROR flags */
 639
 640        sp->duplex      = 0;
 641        sp->tx_delay    = SIXP_TXDELAY;
 642        sp->persistence = SIXP_PERSIST;
 643        sp->slottime    = SIXP_SLOTTIME;
 644        sp->led_state   = 0x60;
 645        sp->status      = 1;
 646        sp->status1     = 1;
 647        sp->status2     = 0;
 648        sp->tx_enable   = 0;
 649
 650        netif_start_queue(dev);
 651
 652        init_timer(&sp->tx_t);
 653        sp->tx_t.function = sp_xmit_on_air;
 654        sp->tx_t.data = (unsigned long) sp;
 655
 656        init_timer(&sp->resync_t);
 657
 658        spin_unlock_bh(&sp->lock);
 659
 660        /* Done.  We have linked the TTY line to a channel. */
 661        tty->disc_data = sp;
 662        tty->receive_room = 65536;
 663
 664        /* Now we're ready to register. */
 665        if (register_netdev(dev))
 666                goto out_free;
 667
 668        tnc_init(sp);
 669
 670        return 0;
 671
 672out_free:
 673        kfree(xbuff);
 674        kfree(rbuff);
 675
 676        if (dev)
 677                free_netdev(dev);
 678
 679out:
 680        return err;
 681}
 682
 683
 684/*
 685 * Close down a 6pack channel.
 686 * This means flushing out any pending queues, and then restoring the
 687 * TTY line discipline to what it was before it got hooked to 6pack
 688 * (which usually is TTY again).
 689 */
 690static void sixpack_close(struct tty_struct *tty)
 691{
 692        struct sixpack *sp;
 693
 694        write_lock_bh(&disc_data_lock);
 695        sp = tty->disc_data;
 696        tty->disc_data = NULL;
 697        write_unlock_bh(&disc_data_lock);
 698        if (!sp)
 699                return;
 700
 701        /*
 702         * We have now ensured that nobody can start using ap from now on, but
 703         * we have to wait for all existing users to finish.
 704         */
 705        if (!atomic_dec_and_test(&sp->refcnt))
 706                down(&sp->dead_sem);
 707
 708        unregister_netdev(sp->dev);
 709
 710        del_timer(&sp->tx_t);
 711        del_timer(&sp->resync_t);
 712
 713        /* Free all 6pack frame buffers. */
 714        kfree(sp->rbuff);
 715        kfree(sp->xbuff);
 716}
 717
 718/* Perform I/O control on an active 6pack channel. */
 719static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
 720        unsigned int cmd, unsigned long arg)
 721{
 722        struct sixpack *sp = sp_get(tty);
 723        struct net_device *dev;
 724        unsigned int tmp, err;
 725
 726        if (!sp)
 727                return -ENXIO;
 728        dev = sp->dev;
 729
 730        switch(cmd) {
 731        case SIOCGIFNAME:
 732                err = copy_to_user((void __user *) arg, dev->name,
 733                                   strlen(dev->name) + 1) ? -EFAULT : 0;
 734                break;
 735
 736        case SIOCGIFENCAP:
 737                err = put_user(0, (int __user *) arg);
 738                break;
 739
 740        case SIOCSIFENCAP:
 741                if (get_user(tmp, (int __user *) arg)) {
 742                        err = -EFAULT;
 743                        break;
 744                }
 745
 746                sp->mode = tmp;
 747                dev->addr_len        = AX25_ADDR_LEN;
 748                dev->hard_header_len = AX25_KISS_HEADER_LEN +
 749                                       AX25_MAX_HEADER_LEN + 3;
 750                dev->type            = ARPHRD_AX25;
 751
 752                err = 0;
 753                break;
 754
 755         case SIOCSIFHWADDR: {
 756                char addr[AX25_ADDR_LEN];
 757
 758                if (copy_from_user(&addr,
 759                                   (void __user *) arg, AX25_ADDR_LEN)) {
 760                                err = -EFAULT;
 761                                break;
 762                        }
 763
 764                        netif_tx_lock_bh(dev);
 765                        memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
 766                        netif_tx_unlock_bh(dev);
 767
 768                        err = 0;
 769                        break;
 770                }
 771
 772        default:
 773                err = tty_mode_ioctl(tty, file, cmd, arg);
 774        }
 775
 776        sp_put(sp);
 777
 778        return err;
 779}
 780
 781#ifdef CONFIG_COMPAT
 782static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file,
 783                                unsigned int cmd, unsigned long arg)
 784{
 785        switch (cmd) {
 786        case SIOCGIFNAME:
 787        case SIOCGIFENCAP:
 788        case SIOCSIFENCAP:
 789        case SIOCSIFHWADDR:
 790                return sixpack_ioctl(tty, file, cmd,
 791                                (unsigned long)compat_ptr(arg));
 792        }
 793
 794        return -ENOIOCTLCMD;
 795}
 796#endif
 797
 798static struct tty_ldisc_ops sp_ldisc = {
 799        .owner          = THIS_MODULE,
 800        .magic          = TTY_LDISC_MAGIC,
 801        .name           = "6pack",
 802        .open           = sixpack_open,
 803        .close          = sixpack_close,
 804        .ioctl          = sixpack_ioctl,
 805#ifdef CONFIG_COMPAT
 806        .compat_ioctl   = sixpack_compat_ioctl,
 807#endif
 808        .receive_buf    = sixpack_receive_buf,
 809        .write_wakeup   = sixpack_write_wakeup,
 810};
 811
 812/* Initialize 6pack control device -- register 6pack line discipline */
 813
 814static const char msg_banner[]  __initconst = KERN_INFO \
 815        "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
 816static const char msg_regfail[] __initconst = KERN_ERR  \
 817        "6pack: can't register line discipline (err = %d)\n";
 818
 819static int __init sixpack_init_driver(void)
 820{
 821        int status;
 822
 823        printk(msg_banner);
 824
 825        /* Register the provided line protocol discipline */
 826        if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)
 827                printk(msg_regfail, status);
 828
 829        return status;
 830}
 831
 832static const char msg_unregfail[] = KERN_ERR \
 833        "6pack: can't unregister line discipline (err = %d)\n";
 834
 835static void __exit sixpack_exit_driver(void)
 836{
 837        int ret;
 838
 839        if ((ret = tty_unregister_ldisc(N_6PACK)))
 840                printk(msg_unregfail, ret);
 841}
 842
 843/* encode an AX.25 packet into 6pack */
 844
 845static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
 846        int length, unsigned char tx_delay)
 847{
 848        int count = 0;
 849        unsigned char checksum = 0, buf[400];
 850        int raw_count = 0;
 851
 852        tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
 853        tx_buf_raw[raw_count++] = SIXP_SEOF;
 854
 855        buf[0] = tx_delay;
 856        for (count = 1; count < length; count++)
 857                buf[count] = tx_buf[count];
 858
 859        for (count = 0; count < length; count++)
 860                checksum += buf[count];
 861        buf[length] = (unsigned char) 0xff - checksum;
 862
 863        for (count = 0; count <= length; count++) {
 864                if ((count % 3) == 0) {
 865                        tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
 866                        tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
 867                } else if ((count % 3) == 1) {
 868                        tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
 869                        tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
 870                } else {
 871                        tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
 872                        tx_buf_raw[raw_count++] = (buf[count] >> 2);
 873                }
 874        }
 875        if ((length % 3) != 2)
 876                raw_count++;
 877        tx_buf_raw[raw_count++] = SIXP_SEOF;
 878        return raw_count;
 879}
 880
 881/* decode 4 sixpack-encoded bytes into 3 data bytes */
 882
 883static void decode_data(struct sixpack *sp, unsigned char inbyte)
 884{
 885        unsigned char *buf;
 886
 887        if (sp->rx_count != 3) {
 888                sp->raw_buf[sp->rx_count++] = inbyte;
 889
 890                return;
 891        }
 892
 893        buf = sp->raw_buf;
 894        sp->cooked_buf[sp->rx_count_cooked++] =
 895                buf[0] | ((buf[1] << 2) & 0xc0);
 896        sp->cooked_buf[sp->rx_count_cooked++] =
 897                (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
 898        sp->cooked_buf[sp->rx_count_cooked++] =
 899                (buf[2] & 0x03) | (inbyte << 2);
 900        sp->rx_count = 0;
 901}
 902
 903/* identify and execute a 6pack priority command byte */
 904
 905static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
 906{
 907        unsigned char channel;
 908        int actual;
 909
 910        channel = cmd & SIXP_CHN_MASK;
 911        if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {     /* idle ? */
 912
 913        /* RX and DCD flags can only be set in the same prio command,
 914           if the DCD flag has been set without the RX flag in the previous
 915           prio command. If DCD has not been set before, something in the
 916           transmission has gone wrong. In this case, RX and DCD are
 917           cleared in order to prevent the decode_data routine from
 918           reading further data that might be corrupt. */
 919
 920                if (((sp->status & SIXP_DCD_MASK) == 0) &&
 921                        ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
 922                                if (sp->status != 1)
 923                                        printk(KERN_DEBUG "6pack: protocol violation\n");
 924                                else
 925                                        sp->status = 0;
 926                                cmd &= ~SIXP_RX_DCD_MASK;
 927                }
 928                sp->status = cmd & SIXP_PRIO_DATA_MASK;
 929        } else { /* output watchdog char if idle */
 930                if ((sp->status2 != 0) && (sp->duplex == 1)) {
 931                        sp->led_state = 0x70;
 932                        sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 933                        sp->tx_enable = 1;
 934                        actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
 935                        sp->xleft -= actual;
 936                        sp->xhead += actual;
 937                        sp->led_state = 0x60;
 938                        sp->status2 = 0;
 939
 940                }
 941        }
 942
 943        /* needed to trigger the TNC watchdog */
 944        sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 945
 946        /* if the state byte has been received, the TNC is present,
 947           so the resync timer can be reset. */
 948
 949        if (sp->tnc_state == TNC_IN_SYNC) {
 950                del_timer(&sp->resync_t);
 951                sp->resync_t.data       = (unsigned long) sp;
 952                sp->resync_t.function   = resync_tnc;
 953                sp->resync_t.expires    = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
 954                add_timer(&sp->resync_t);
 955        }
 956
 957        sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
 958}
 959
 960/* identify and execute a standard 6pack command byte */
 961
 962static void decode_std_command(struct sixpack *sp, unsigned char cmd)
 963{
 964        unsigned char checksum = 0, rest = 0, channel;
 965        short i;
 966
 967        channel = cmd & SIXP_CHN_MASK;
 968        switch (cmd & SIXP_CMD_MASK) {     /* normal command */
 969        case SIXP_SEOF:
 970                if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
 971                        if ((sp->status & SIXP_RX_DCD_MASK) ==
 972                                SIXP_RX_DCD_MASK) {
 973                                sp->led_state = 0x68;
 974                                sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 975                        }
 976                } else {
 977                        sp->led_state = 0x60;
 978                        /* fill trailing bytes with zeroes */
 979                        sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 980                        rest = sp->rx_count;
 981                        if (rest != 0)
 982                                 for (i = rest; i <= 3; i++)
 983                                        decode_data(sp, 0);
 984                        if (rest == 2)
 985                                sp->rx_count_cooked -= 2;
 986                        else if (rest == 3)
 987                                sp->rx_count_cooked -= 1;
 988                        for (i = 0; i < sp->rx_count_cooked; i++)
 989                                checksum += sp->cooked_buf[i];
 990                        if (checksum != SIXP_CHKSUM) {
 991                                printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
 992                        } else {
 993                                sp->rcount = sp->rx_count_cooked-2;
 994                                sp_bump(sp, 0);
 995                        }
 996                        sp->rx_count_cooked = 0;
 997                }
 998                break;
 999        case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
1000                break;
1001        case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
1002                break;
1003        case SIXP_RX_BUF_OVL:
1004                printk(KERN_DEBUG "6pack: RX buffer overflow\n");
1005        }
1006}
1007
1008/* decode a 6pack packet */
1009
1010static void
1011sixpack_decode(struct sixpack *sp, unsigned char *pre_rbuff, int count)
1012{
1013        unsigned char inbyte;
1014        int count1;
1015
1016        for (count1 = 0; count1 < count; count1++) {
1017                inbyte = pre_rbuff[count1];
1018                if (inbyte == SIXP_FOUND_TNC) {
1019                        tnc_set_sync_state(sp, TNC_IN_SYNC);
1020                        del_timer(&sp->resync_t);
1021                }
1022                if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
1023                        decode_prio_command(sp, inbyte);
1024                else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
1025                        decode_std_command(sp, inbyte);
1026                else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
1027                        decode_data(sp, inbyte);
1028        }
1029}
1030
1031MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
1032MODULE_DESCRIPTION("6pack driver for AX.25");
1033MODULE_LICENSE("GPL");
1034MODULE_ALIAS_LDISC(N_6PACK);
1035
1036module_init(sixpack_init_driver);
1037module_exit(sixpack_exit_driver);
1038