Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * 6pack.c  This module implements the 6pack protocol for kernel-based
0004  *      devices like TTY. It interfaces between a raw TTY and the
0005  *      kernel's AX.25 protocol layers.
0006  *
0007  * Authors: Andreas Könsgen <ajk@comnets.uni-bremen.de>
0008  *              Ralf Baechle DL5RB <ralf@linux-mips.org>
0009  *
0010  * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
0011  *
0012  *      Laurence Culhane, <loz@holmes.demon.co.uk>
0013  *      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
0014  */
0015 
0016 #include <linux/module.h>
0017 #include <linux/uaccess.h>
0018 #include <linux/bitops.h>
0019 #include <linux/string.h>
0020 #include <linux/mm.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/in.h>
0023 #include <linux/tty.h>
0024 #include <linux/errno.h>
0025 #include <linux/netdevice.h>
0026 #include <linux/timer.h>
0027 #include <linux/slab.h>
0028 #include <net/ax25.h>
0029 #include <linux/etherdevice.h>
0030 #include <linux/skbuff.h>
0031 #include <linux/rtnetlink.h>
0032 #include <linux/spinlock.h>
0033 #include <linux/if_arp.h>
0034 #include <linux/init.h>
0035 #include <linux/ip.h>
0036 #include <linux/tcp.h>
0037 #include <linux/semaphore.h>
0038 #include <linux/refcount.h>
0039 
0040 #define SIXPACK_VERSION    "Revision: 0.3.0"
0041 
0042 /* sixpack priority commands */
0043 #define SIXP_SEOF       0x40    /* start and end of a 6pack frame */
0044 #define SIXP_TX_URUN        0x48    /* transmit overrun */
0045 #define SIXP_RX_ORUN        0x50    /* receive overrun */
0046 #define SIXP_RX_BUF_OVL     0x58    /* receive buffer overflow */
0047 
0048 #define SIXP_CHKSUM     0xFF    /* valid checksum of a 6pack frame */
0049 
0050 /* masks to get certain bits out of the status bytes sent by the TNC */
0051 
0052 #define SIXP_CMD_MASK       0xC0
0053 #define SIXP_CHN_MASK       0x07
0054 #define SIXP_PRIO_CMD_MASK  0x80
0055 #define SIXP_STD_CMD_MASK   0x40
0056 #define SIXP_PRIO_DATA_MASK 0x38
0057 #define SIXP_TX_MASK        0x20
0058 #define SIXP_RX_MASK        0x10
0059 #define SIXP_RX_DCD_MASK    0x18
0060 #define SIXP_LEDS_ON        0x78
0061 #define SIXP_LEDS_OFF       0x60
0062 #define SIXP_CON        0x08
0063 #define SIXP_STA        0x10
0064 
0065 #define SIXP_FOUND_TNC      0xe9
0066 #define SIXP_CON_ON     0x68
0067 #define SIXP_DCD_MASK       0x08
0068 #define SIXP_DAMA_OFF       0
0069 
0070 /* default level 2 parameters */
0071 #define SIXP_TXDELAY            25  /* 250 ms */
0072 #define SIXP_PERSIST            50  /* in 256ths */
0073 #define SIXP_SLOTTIME           10  /* 100 ms */
0074 #define SIXP_INIT_RESYNC_TIMEOUT    (3*HZ/2) /* in 1 s */
0075 #define SIXP_RESYNC_TIMEOUT     5*HZ    /* in 1 s */
0076 
0077 /* 6pack configuration. */
0078 #define SIXP_NRUNIT         31      /* MAX number of 6pack channels */
0079 #define SIXP_MTU            256 /* Default MTU */
0080 
0081 enum sixpack_flags {
0082     SIXPF_ERROR,    /* Parity, etc. error   */
0083 };
0084 
0085 struct sixpack {
0086     /* Various fields. */
0087     struct tty_struct   *tty;       /* ptr to TTY structure */
0088     struct net_device   *dev;       /* easy for intr handling  */
0089 
0090     /* These are pointers to the malloc()ed frame buffers. */
0091     unsigned char       *rbuff;     /* receiver buffer  */
0092     int         rcount;         /* received chars counter  */
0093     unsigned char       *xbuff;     /* transmitter buffer   */
0094     unsigned char       *xhead;         /* next byte to XMIT */
0095     int         xleft;          /* bytes left in XMIT queue  */
0096 
0097     unsigned char       raw_buf[4];
0098     unsigned char       cooked_buf[400];
0099 
0100     unsigned int        rx_count;
0101     unsigned int        rx_count_cooked;
0102     spinlock_t      rxlock;
0103 
0104     int         mtu;        /* Our mtu (to spot changes!) */
0105     int         buffsize;       /* Max buffers sizes */
0106 
0107     unsigned long       flags;      /* Flag values/ mode etc */
0108     unsigned char       mode;       /* 6pack mode */
0109 
0110     /* 6pack stuff */
0111     unsigned char       tx_delay;
0112     unsigned char       persistence;
0113     unsigned char       slottime;
0114     unsigned char       duplex;
0115     unsigned char       led_state;
0116     unsigned char       status;
0117     unsigned char       status1;
0118     unsigned char       status2;
0119     unsigned char       tx_enable;
0120     unsigned char       tnc_state;
0121 
0122     struct timer_list   tx_t;
0123     struct timer_list   resync_t;
0124     refcount_t      refcnt;
0125     struct completion   dead;
0126     spinlock_t      lock;
0127 };
0128 
0129 #define AX25_6PACK_HEADER_LEN 0
0130 
0131 static void sixpack_decode(struct sixpack *, const unsigned char[], int);
0132 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
0133 
0134 /*
0135  * Perform the persistence/slottime algorithm for CSMA access. If the
0136  * persistence check was successful, write the data to the serial driver.
0137  * Note that in case of DAMA operation, the data is not sent here.
0138  */
0139 
0140 static void sp_xmit_on_air(struct timer_list *t)
0141 {
0142     struct sixpack *sp = from_timer(sp, t, tx_t);
0143     int actual, when = sp->slottime;
0144     static unsigned char random;
0145 
0146     random = random * 17 + 41;
0147 
0148     if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
0149         sp->led_state = 0x70;
0150         sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0151         sp->tx_enable = 1;
0152         actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
0153         sp->xleft -= actual;
0154         sp->xhead += actual;
0155         sp->led_state = 0x60;
0156         sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0157         sp->status2 = 0;
0158     } else
0159         mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
0160 }
0161 
0162 /* ----> 6pack timer interrupt handler and friends. <---- */
0163 
0164 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
0165 static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
0166 {
0167     unsigned char *msg, *p = icp;
0168     int actual, count;
0169 
0170     if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
0171         msg = "oversized transmit packet!";
0172         goto out_drop;
0173     }
0174 
0175     if (p[0] > 5) {
0176         msg = "invalid KISS command";
0177         goto out_drop;
0178     }
0179 
0180     if ((p[0] != 0) && (len > 2)) {
0181         msg = "KISS control packet too long";
0182         goto out_drop;
0183     }
0184 
0185     if ((p[0] == 0) && (len < 15)) {
0186         msg = "bad AX.25 packet to transmit";
0187         goto out_drop;
0188     }
0189 
0190     count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
0191     set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
0192 
0193     switch (p[0]) {
0194     case 1: sp->tx_delay = p[1];
0195         return;
0196     case 2: sp->persistence = p[1];
0197         return;
0198     case 3: sp->slottime = p[1];
0199         return;
0200     case 4: /* ignored */
0201         return;
0202     case 5: sp->duplex = p[1];
0203         return;
0204     }
0205 
0206     if (p[0] != 0)
0207         return;
0208 
0209     /*
0210      * In case of fullduplex or DAMA operation, we don't take care about the
0211      * state of the DCD or of any timers, as the determination of the
0212      * correct time to send is the job of the AX.25 layer. We send
0213      * immediately after data has arrived.
0214      */
0215     if (sp->duplex == 1) {
0216         sp->led_state = 0x70;
0217         sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0218         sp->tx_enable = 1;
0219         actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
0220         sp->xleft = count - actual;
0221         sp->xhead = sp->xbuff + actual;
0222         sp->led_state = 0x60;
0223         sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0224     } else {
0225         sp->xleft = count;
0226         sp->xhead = sp->xbuff;
0227         sp->status2 = count;
0228         sp_xmit_on_air(&sp->tx_t);
0229     }
0230 
0231     return;
0232 
0233 out_drop:
0234     sp->dev->stats.tx_dropped++;
0235     netif_start_queue(sp->dev);
0236     if (net_ratelimit())
0237         printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
0238 }
0239 
0240 /* Encapsulate an IP datagram and kick it into a TTY queue. */
0241 
0242 static netdev_tx_t sp_xmit(struct sk_buff *skb, struct net_device *dev)
0243 {
0244     struct sixpack *sp = netdev_priv(dev);
0245 
0246     if (skb->protocol == htons(ETH_P_IP))
0247         return ax25_ip_xmit(skb);
0248 
0249     spin_lock_bh(&sp->lock);
0250     /* We were not busy, so we are now... :-) */
0251     netif_stop_queue(dev);
0252     dev->stats.tx_bytes += skb->len;
0253     sp_encaps(sp, skb->data, skb->len);
0254     spin_unlock_bh(&sp->lock);
0255 
0256     dev_kfree_skb(skb);
0257 
0258     return NETDEV_TX_OK;
0259 }
0260 
0261 static int sp_open_dev(struct net_device *dev)
0262 {
0263     struct sixpack *sp = netdev_priv(dev);
0264 
0265     if (sp->tty == NULL)
0266         return -ENODEV;
0267     return 0;
0268 }
0269 
0270 /* Close the low-level part of the 6pack channel. */
0271 static int sp_close(struct net_device *dev)
0272 {
0273     struct sixpack *sp = netdev_priv(dev);
0274 
0275     spin_lock_bh(&sp->lock);
0276     if (sp->tty) {
0277         /* TTY discipline is running. */
0278         clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
0279     }
0280     netif_stop_queue(dev);
0281     spin_unlock_bh(&sp->lock);
0282 
0283     return 0;
0284 }
0285 
0286 static int sp_set_mac_address(struct net_device *dev, void *addr)
0287 {
0288     struct sockaddr_ax25 *sa = addr;
0289 
0290     netif_tx_lock_bh(dev);
0291     netif_addr_lock(dev);
0292     __dev_addr_set(dev, &sa->sax25_call, AX25_ADDR_LEN);
0293     netif_addr_unlock(dev);
0294     netif_tx_unlock_bh(dev);
0295 
0296     return 0;
0297 }
0298 
0299 static const struct net_device_ops sp_netdev_ops = {
0300     .ndo_open       = sp_open_dev,
0301     .ndo_stop       = sp_close,
0302     .ndo_start_xmit     = sp_xmit,
0303     .ndo_set_mac_address    = sp_set_mac_address,
0304 };
0305 
0306 static void sp_setup(struct net_device *dev)
0307 {
0308     /* Finish setting up the DEVICE info. */
0309     dev->netdev_ops     = &sp_netdev_ops;
0310     dev->mtu        = SIXP_MTU;
0311     dev->hard_header_len    = AX25_MAX_HEADER_LEN;
0312     dev->header_ops     = &ax25_header_ops;
0313 
0314     dev->addr_len       = AX25_ADDR_LEN;
0315     dev->type       = ARPHRD_AX25;
0316     dev->tx_queue_len   = 10;
0317 
0318     /* Only activated in AX.25 mode */
0319     memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
0320     dev_addr_set(dev, (u8 *)&ax25_defaddr);
0321 
0322     dev->flags      = 0;
0323 }
0324 
0325 /* Send one completely decapsulated IP datagram to the IP layer. */
0326 
0327 /*
0328  * This is the routine that sends the received data to the kernel AX.25.
0329  * 'cmd' is the KISS command. For AX.25 data, it is zero.
0330  */
0331 
0332 static void sp_bump(struct sixpack *sp, char cmd)
0333 {
0334     struct sk_buff *skb;
0335     int count;
0336     unsigned char *ptr;
0337 
0338     count = sp->rcount + 1;
0339 
0340     sp->dev->stats.rx_bytes += count;
0341 
0342     if ((skb = dev_alloc_skb(count + 1)) == NULL)
0343         goto out_mem;
0344 
0345     ptr = skb_put(skb, count + 1);
0346     *ptr++ = cmd;   /* KISS command */
0347 
0348     memcpy(ptr, sp->cooked_buf + 1, count);
0349     skb->protocol = ax25_type_trans(skb, sp->dev);
0350     netif_rx(skb);
0351     sp->dev->stats.rx_packets++;
0352 
0353     return;
0354 
0355 out_mem:
0356     sp->dev->stats.rx_dropped++;
0357 }
0358 
0359 
0360 /* ----------------------------------------------------------------------- */
0361 
0362 /*
0363  * We have a potential race on dereferencing tty->disc_data, because the tty
0364  * layer provides no locking at all - thus one cpu could be running
0365  * sixpack_receive_buf while another calls sixpack_close, which zeroes
0366  * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
0367  * best way to fix this is to use a rwlock in the tty struct, but for now we
0368  * use a single global rwlock for all ttys in ppp line discipline.
0369  */
0370 static DEFINE_RWLOCK(disc_data_lock);
0371                                                                                 
0372 static struct sixpack *sp_get(struct tty_struct *tty)
0373 {
0374     struct sixpack *sp;
0375 
0376     read_lock(&disc_data_lock);
0377     sp = tty->disc_data;
0378     if (sp)
0379         refcount_inc(&sp->refcnt);
0380     read_unlock(&disc_data_lock);
0381 
0382     return sp;
0383 }
0384 
0385 static void sp_put(struct sixpack *sp)
0386 {
0387     if (refcount_dec_and_test(&sp->refcnt))
0388         complete(&sp->dead);
0389 }
0390 
0391 /*
0392  * Called by the TTY driver when there's room for more data.  If we have
0393  * more packets to send, we send them here.
0394  */
0395 static void sixpack_write_wakeup(struct tty_struct *tty)
0396 {
0397     struct sixpack *sp = sp_get(tty);
0398     int actual;
0399 
0400     if (!sp)
0401         return;
0402     if (sp->xleft <= 0)  {
0403         /* Now serial buffer is almost free & we can start
0404          * transmission of another packet */
0405         sp->dev->stats.tx_packets++;
0406         clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
0407         sp->tx_enable = 0;
0408         netif_wake_queue(sp->dev);
0409         goto out;
0410     }
0411 
0412     if (sp->tx_enable) {
0413         actual = tty->ops->write(tty, sp->xhead, sp->xleft);
0414         sp->xleft -= actual;
0415         sp->xhead += actual;
0416     }
0417 
0418 out:
0419     sp_put(sp);
0420 }
0421 
0422 /* ----------------------------------------------------------------------- */
0423 
0424 /*
0425  * Handle the 'receiver data ready' interrupt.
0426  * This function is called by the tty module in the kernel when
0427  * a block of 6pack data has been received, which can now be decapsulated
0428  * and sent on to some IP layer for further processing.
0429  */
0430 static void sixpack_receive_buf(struct tty_struct *tty,
0431     const unsigned char *cp, const char *fp, int count)
0432 {
0433     struct sixpack *sp;
0434     int count1;
0435 
0436     if (!count)
0437         return;
0438 
0439     sp = sp_get(tty);
0440     if (!sp)
0441         return;
0442 
0443     /* Read the characters out of the buffer */
0444     count1 = count;
0445     while (count) {
0446         count--;
0447         if (fp && *fp++) {
0448             if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
0449                 sp->dev->stats.rx_errors++;
0450             continue;
0451         }
0452     }
0453     sixpack_decode(sp, cp, count1);
0454 
0455     sp_put(sp);
0456     tty_unthrottle(tty);
0457 }
0458 
0459 /*
0460  * Try to resync the TNC. Called by the resync timer defined in
0461  * decode_prio_command
0462  */
0463 
0464 #define TNC_UNINITIALIZED   0
0465 #define TNC_UNSYNC_STARTUP  1
0466 #define TNC_UNSYNCED        2
0467 #define TNC_IN_SYNC     3
0468 
0469 static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
0470 {
0471     char *msg;
0472 
0473     switch (new_tnc_state) {
0474     default:            /* gcc oh piece-o-crap ... */
0475     case TNC_UNSYNC_STARTUP:
0476         msg = "Synchronizing with TNC";
0477         break;
0478     case TNC_UNSYNCED:
0479         msg = "Lost synchronization with TNC\n";
0480         break;
0481     case TNC_IN_SYNC:
0482         msg = "Found TNC";
0483         break;
0484     }
0485 
0486     sp->tnc_state = new_tnc_state;
0487     printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);
0488 }
0489 
0490 static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
0491 {
0492     int old_tnc_state = sp->tnc_state;
0493 
0494     if (old_tnc_state != new_tnc_state)
0495         __tnc_set_sync_state(sp, new_tnc_state);
0496 }
0497 
0498 static void resync_tnc(struct timer_list *t)
0499 {
0500     struct sixpack *sp = from_timer(sp, t, resync_t);
0501     static char resync_cmd = 0xe8;
0502 
0503     /* clear any data that might have been received */
0504 
0505     sp->rx_count = 0;
0506     sp->rx_count_cooked = 0;
0507 
0508     /* reset state machine */
0509 
0510     sp->status = 1;
0511     sp->status1 = 1;
0512     sp->status2 = 0;
0513 
0514     /* resync the TNC */
0515 
0516     sp->led_state = 0x60;
0517     sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0518     sp->tty->ops->write(sp->tty, &resync_cmd, 1);
0519 
0520 
0521     /* Start resync timer again -- the TNC might be still absent */
0522     mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);
0523 }
0524 
0525 static inline int tnc_init(struct sixpack *sp)
0526 {
0527     unsigned char inbyte = 0xe8;
0528 
0529     tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
0530 
0531     sp->tty->ops->write(sp->tty, &inbyte, 1);
0532 
0533     mod_timer(&sp->resync_t, jiffies + SIXP_RESYNC_TIMEOUT);
0534 
0535     return 0;
0536 }
0537 
0538 /*
0539  * Open the high-level part of the 6pack channel.
0540  * This function is called by the TTY module when the
0541  * 6pack line discipline is called for.  Because we are
0542  * sure the tty line exists, we only have to link it to
0543  * a free 6pcack channel...
0544  */
0545 static int sixpack_open(struct tty_struct *tty)
0546 {
0547     char *rbuff = NULL, *xbuff = NULL;
0548     struct net_device *dev;
0549     struct sixpack *sp;
0550     unsigned long len;
0551     int err = 0;
0552 
0553     if (!capable(CAP_NET_ADMIN))
0554         return -EPERM;
0555     if (tty->ops->write == NULL)
0556         return -EOPNOTSUPP;
0557 
0558     dev = alloc_netdev(sizeof(struct sixpack), "sp%d", NET_NAME_UNKNOWN,
0559                sp_setup);
0560     if (!dev) {
0561         err = -ENOMEM;
0562         goto out;
0563     }
0564 
0565     sp = netdev_priv(dev);
0566     sp->dev = dev;
0567 
0568     spin_lock_init(&sp->lock);
0569     spin_lock_init(&sp->rxlock);
0570     refcount_set(&sp->refcnt, 1);
0571     init_completion(&sp->dead);
0572 
0573     /* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
0574 
0575     len = dev->mtu * 2;
0576 
0577     rbuff = kmalloc(len + 4, GFP_KERNEL);
0578     xbuff = kmalloc(len + 4, GFP_KERNEL);
0579 
0580     if (rbuff == NULL || xbuff == NULL) {
0581         err = -ENOBUFS;
0582         goto out_free;
0583     }
0584 
0585     spin_lock_bh(&sp->lock);
0586 
0587     sp->tty = tty;
0588 
0589     sp->rbuff   = rbuff;
0590     sp->xbuff   = xbuff;
0591 
0592     sp->mtu     = AX25_MTU + 73;
0593     sp->buffsize    = len;
0594     sp->rcount  = 0;
0595     sp->rx_count    = 0;
0596     sp->rx_count_cooked = 0;
0597     sp->xleft   = 0;
0598 
0599     sp->flags   = 0;        /* Clear ESCAPE & ERROR flags */
0600 
0601     sp->duplex  = 0;
0602     sp->tx_delay    = SIXP_TXDELAY;
0603     sp->persistence = SIXP_PERSIST;
0604     sp->slottime    = SIXP_SLOTTIME;
0605     sp->led_state   = 0x60;
0606     sp->status      = 1;
0607     sp->status1     = 1;
0608     sp->status2     = 0;
0609     sp->tx_enable   = 0;
0610 
0611     netif_start_queue(dev);
0612 
0613     timer_setup(&sp->tx_t, sp_xmit_on_air, 0);
0614 
0615     timer_setup(&sp->resync_t, resync_tnc, 0);
0616 
0617     spin_unlock_bh(&sp->lock);
0618 
0619     /* Done.  We have linked the TTY line to a channel. */
0620     tty->disc_data = sp;
0621     tty->receive_room = 65536;
0622 
0623     /* Now we're ready to register. */
0624     err = register_netdev(dev);
0625     if (err)
0626         goto out_free;
0627 
0628     tnc_init(sp);
0629 
0630     return 0;
0631 
0632 out_free:
0633     kfree(xbuff);
0634     kfree(rbuff);
0635 
0636     free_netdev(dev);
0637 
0638 out:
0639     return err;
0640 }
0641 
0642 
0643 /*
0644  * Close down a 6pack channel.
0645  * This means flushing out any pending queues, and then restoring the
0646  * TTY line discipline to what it was before it got hooked to 6pack
0647  * (which usually is TTY again).
0648  */
0649 static void sixpack_close(struct tty_struct *tty)
0650 {
0651     struct sixpack *sp;
0652 
0653     write_lock_irq(&disc_data_lock);
0654     sp = tty->disc_data;
0655     tty->disc_data = NULL;
0656     write_unlock_irq(&disc_data_lock);
0657     if (!sp)
0658         return;
0659 
0660     /*
0661      * We have now ensured that nobody can start using ap from now on, but
0662      * we have to wait for all existing users to finish.
0663      */
0664     if (!refcount_dec_and_test(&sp->refcnt))
0665         wait_for_completion(&sp->dead);
0666 
0667     /* We must stop the queue to avoid potentially scribbling
0668      * on the free buffers. The sp->dead completion is not sufficient
0669      * to protect us from sp->xbuff access.
0670      */
0671     netif_stop_queue(sp->dev);
0672 
0673     unregister_netdev(sp->dev);
0674 
0675     del_timer_sync(&sp->tx_t);
0676     del_timer_sync(&sp->resync_t);
0677 
0678     /* Free all 6pack frame buffers after unreg. */
0679     kfree(sp->rbuff);
0680     kfree(sp->xbuff);
0681 
0682     free_netdev(sp->dev);
0683 }
0684 
0685 /* Perform I/O control on an active 6pack channel. */
0686 static int sixpack_ioctl(struct tty_struct *tty, unsigned int cmd,
0687         unsigned long arg)
0688 {
0689     struct sixpack *sp = sp_get(tty);
0690     struct net_device *dev;
0691     unsigned int tmp, err;
0692 
0693     if (!sp)
0694         return -ENXIO;
0695     dev = sp->dev;
0696 
0697     switch(cmd) {
0698     case SIOCGIFNAME:
0699         err = copy_to_user((void __user *) arg, dev->name,
0700                            strlen(dev->name) + 1) ? -EFAULT : 0;
0701         break;
0702 
0703     case SIOCGIFENCAP:
0704         err = put_user(0, (int __user *) arg);
0705         break;
0706 
0707     case SIOCSIFENCAP:
0708         if (get_user(tmp, (int __user *) arg)) {
0709             err = -EFAULT;
0710             break;
0711         }
0712 
0713         sp->mode = tmp;
0714         dev->addr_len        = AX25_ADDR_LEN;
0715         dev->hard_header_len = AX25_KISS_HEADER_LEN +
0716                                AX25_MAX_HEADER_LEN + 3;
0717         dev->type            = ARPHRD_AX25;
0718 
0719         err = 0;
0720         break;
0721 
0722     case SIOCSIFHWADDR: {
0723             char addr[AX25_ADDR_LEN];
0724 
0725             if (copy_from_user(&addr,
0726                        (void __user *)arg, AX25_ADDR_LEN)) {
0727                 err = -EFAULT;
0728                 break;
0729             }
0730 
0731             netif_tx_lock_bh(dev);
0732             __dev_addr_set(dev, &addr, AX25_ADDR_LEN);
0733             netif_tx_unlock_bh(dev);
0734             err = 0;
0735             break;
0736         }
0737     default:
0738         err = tty_mode_ioctl(tty, cmd, arg);
0739     }
0740 
0741     sp_put(sp);
0742 
0743     return err;
0744 }
0745 
0746 static struct tty_ldisc_ops sp_ldisc = {
0747     .owner      = THIS_MODULE,
0748     .num        = N_6PACK,
0749     .name       = "6pack",
0750     .open       = sixpack_open,
0751     .close      = sixpack_close,
0752     .ioctl      = sixpack_ioctl,
0753     .receive_buf    = sixpack_receive_buf,
0754     .write_wakeup   = sixpack_write_wakeup,
0755 };
0756 
0757 /* Initialize 6pack control device -- register 6pack line discipline */
0758 
0759 static const char msg_banner[]  __initconst = KERN_INFO \
0760     "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
0761 static const char msg_regfail[] __initconst = KERN_ERR  \
0762     "6pack: can't register line discipline (err = %d)\n";
0763 
0764 static int __init sixpack_init_driver(void)
0765 {
0766     int status;
0767 
0768     printk(msg_banner);
0769 
0770     /* Register the provided line protocol discipline */
0771     status = tty_register_ldisc(&sp_ldisc);
0772     if (status)
0773         printk(msg_regfail, status);
0774 
0775     return status;
0776 }
0777 
0778 static void __exit sixpack_exit_driver(void)
0779 {
0780     tty_unregister_ldisc(&sp_ldisc);
0781 }
0782 
0783 /* encode an AX.25 packet into 6pack */
0784 
0785 static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
0786     int length, unsigned char tx_delay)
0787 {
0788     int count = 0;
0789     unsigned char checksum = 0, buf[400];
0790     int raw_count = 0;
0791 
0792     tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
0793     tx_buf_raw[raw_count++] = SIXP_SEOF;
0794 
0795     buf[0] = tx_delay;
0796     for (count = 1; count < length; count++)
0797         buf[count] = tx_buf[count];
0798 
0799     for (count = 0; count < length; count++)
0800         checksum += buf[count];
0801     buf[length] = (unsigned char) 0xff - checksum;
0802 
0803     for (count = 0; count <= length; count++) {
0804         if ((count % 3) == 0) {
0805             tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
0806             tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
0807         } else if ((count % 3) == 1) {
0808             tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
0809             tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
0810         } else {
0811             tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
0812             tx_buf_raw[raw_count++] = (buf[count] >> 2);
0813         }
0814     }
0815     if ((length % 3) != 2)
0816         raw_count++;
0817     tx_buf_raw[raw_count++] = SIXP_SEOF;
0818     return raw_count;
0819 }
0820 
0821 /* decode 4 sixpack-encoded bytes into 3 data bytes */
0822 
0823 static void decode_data(struct sixpack *sp, unsigned char inbyte)
0824 {
0825     unsigned char *buf;
0826 
0827     if (sp->rx_count != 3) {
0828         sp->raw_buf[sp->rx_count++] = inbyte;
0829 
0830         return;
0831     }
0832 
0833     if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {
0834         pr_err("6pack: cooked buffer overrun, data loss\n");
0835         sp->rx_count = 0;
0836         return;
0837     }
0838 
0839     buf = sp->raw_buf;
0840     sp->cooked_buf[sp->rx_count_cooked++] =
0841         buf[0] | ((buf[1] << 2) & 0xc0);
0842     sp->cooked_buf[sp->rx_count_cooked++] =
0843         (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
0844     sp->cooked_buf[sp->rx_count_cooked++] =
0845         (buf[2] & 0x03) | (inbyte << 2);
0846     sp->rx_count = 0;
0847 }
0848 
0849 /* identify and execute a 6pack priority command byte */
0850 
0851 static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
0852 {
0853     int actual;
0854 
0855     if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {     /* idle ? */
0856 
0857     /* RX and DCD flags can only be set in the same prio command,
0858        if the DCD flag has been set without the RX flag in the previous
0859        prio command. If DCD has not been set before, something in the
0860        transmission has gone wrong. In this case, RX and DCD are
0861        cleared in order to prevent the decode_data routine from
0862        reading further data that might be corrupt. */
0863 
0864         if (((sp->status & SIXP_DCD_MASK) == 0) &&
0865             ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
0866                 if (sp->status != 1)
0867                     printk(KERN_DEBUG "6pack: protocol violation\n");
0868                 else
0869                     sp->status = 0;
0870                 cmd &= ~SIXP_RX_DCD_MASK;
0871         }
0872         sp->status = cmd & SIXP_PRIO_DATA_MASK;
0873     } else { /* output watchdog char if idle */
0874         if ((sp->status2 != 0) && (sp->duplex == 1)) {
0875             sp->led_state = 0x70;
0876             sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0877             sp->tx_enable = 1;
0878             actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
0879             sp->xleft -= actual;
0880             sp->xhead += actual;
0881             sp->led_state = 0x60;
0882             sp->status2 = 0;
0883 
0884         }
0885     }
0886 
0887     /* needed to trigger the TNC watchdog */
0888     sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0889 
0890         /* if the state byte has been received, the TNC is present,
0891            so the resync timer can be reset. */
0892 
0893     if (sp->tnc_state == TNC_IN_SYNC)
0894         mod_timer(&sp->resync_t, jiffies + SIXP_INIT_RESYNC_TIMEOUT);
0895 
0896     sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
0897 }
0898 
0899 /* identify and execute a standard 6pack command byte */
0900 
0901 static void decode_std_command(struct sixpack *sp, unsigned char cmd)
0902 {
0903     unsigned char checksum = 0, rest = 0;
0904     short i;
0905 
0906     switch (cmd & SIXP_CMD_MASK) {     /* normal command */
0907     case SIXP_SEOF:
0908         if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
0909             if ((sp->status & SIXP_RX_DCD_MASK) ==
0910                 SIXP_RX_DCD_MASK) {
0911                 sp->led_state = 0x68;
0912                 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0913             }
0914         } else {
0915             sp->led_state = 0x60;
0916             /* fill trailing bytes with zeroes */
0917             sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0918             spin_lock_bh(&sp->rxlock);
0919             rest = sp->rx_count;
0920             if (rest != 0)
0921                  for (i = rest; i <= 3; i++)
0922                     decode_data(sp, 0);
0923             if (rest == 2)
0924                 sp->rx_count_cooked -= 2;
0925             else if (rest == 3)
0926                 sp->rx_count_cooked -= 1;
0927             for (i = 0; i < sp->rx_count_cooked; i++)
0928                 checksum += sp->cooked_buf[i];
0929             if (checksum != SIXP_CHKSUM) {
0930                 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
0931             } else {
0932                 sp->rcount = sp->rx_count_cooked-2;
0933                 sp_bump(sp, 0);
0934             }
0935             sp->rx_count_cooked = 0;
0936             spin_unlock_bh(&sp->rxlock);
0937         }
0938         break;
0939     case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
0940         break;
0941     case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
0942         break;
0943     case SIXP_RX_BUF_OVL:
0944         printk(KERN_DEBUG "6pack: RX buffer overflow\n");
0945     }
0946 }
0947 
0948 /* decode a 6pack packet */
0949 
0950 static void
0951 sixpack_decode(struct sixpack *sp, const unsigned char *pre_rbuff, int count)
0952 {
0953     unsigned char inbyte;
0954     int count1;
0955 
0956     for (count1 = 0; count1 < count; count1++) {
0957         inbyte = pre_rbuff[count1];
0958         if (inbyte == SIXP_FOUND_TNC) {
0959             tnc_set_sync_state(sp, TNC_IN_SYNC);
0960             del_timer(&sp->resync_t);
0961         }
0962         if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
0963             decode_prio_command(sp, inbyte);
0964         else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
0965             decode_std_command(sp, inbyte);
0966         else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) {
0967             spin_lock_bh(&sp->rxlock);
0968             decode_data(sp, inbyte);
0969             spin_unlock_bh(&sp->rxlock);
0970         }
0971     }
0972 }
0973 
0974 MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
0975 MODULE_DESCRIPTION("6pack driver for AX.25");
0976 MODULE_LICENSE("GPL");
0977 MODULE_ALIAS_LDISC(N_6PACK);
0978 
0979 module_init(sixpack_init_driver);
0980 module_exit(sixpack_exit_driver);