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