0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
0043 #define SIXP_SEOF 0x40
0044 #define SIXP_TX_URUN 0x48
0045 #define SIXP_RX_ORUN 0x50
0046 #define SIXP_RX_BUF_OVL 0x58
0047
0048 #define SIXP_CHKSUM 0xFF
0049
0050
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
0071 #define SIXP_TXDELAY 25
0072 #define SIXP_PERSIST 50
0073 #define SIXP_SLOTTIME 10
0074 #define SIXP_INIT_RESYNC_TIMEOUT (3*HZ/2)
0075 #define SIXP_RESYNC_TIMEOUT 5*HZ
0076
0077
0078 #define SIXP_NRUNIT 31
0079 #define SIXP_MTU 256
0080
0081 enum sixpack_flags {
0082 SIXPF_ERROR,
0083 };
0084
0085 struct sixpack {
0086
0087 struct tty_struct *tty;
0088 struct net_device *dev;
0089
0090
0091 unsigned char *rbuff;
0092 int rcount;
0093 unsigned char *xbuff;
0094 unsigned char *xhead;
0095 int xleft;
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;
0105 int buffsize;
0106
0107 unsigned long flags;
0108 unsigned char mode;
0109
0110
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
0136
0137
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
0163
0164
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) {
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:
0201 return;
0202 case 5: sp->duplex = p[1];
0203 return;
0204 }
0205
0206 if (p[0] != 0)
0207 return;
0208
0209
0210
0211
0212
0213
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
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
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
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
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
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
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
0326
0327
0328
0329
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;
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
0364
0365
0366
0367
0368
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
0393
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
0404
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
0426
0427
0428
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
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
0461
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:
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
0504
0505 sp->rx_count = 0;
0506 sp->rx_count_cooked = 0;
0507
0508
0509
0510 sp->status = 1;
0511 sp->status1 = 1;
0512 sp->status2 = 0;
0513
0514
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
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
0540
0541
0542
0543
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
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;
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
0620 tty->disc_data = sp;
0621 tty->receive_room = 65536;
0622
0623
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
0645
0646
0647
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
0662
0663
0664 if (!refcount_dec_and_test(&sp->refcnt))
0665 wait_for_completion(&sp->dead);
0666
0667
0668
0669
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
0679 kfree(sp->rbuff);
0680 kfree(sp->xbuff);
0681
0682 free_netdev(sp->dev);
0683 }
0684
0685
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
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
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
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
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
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) {
0856
0857
0858
0859
0860
0861
0862
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 {
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
0888 sp->tty->ops->write(sp->tty, &sp->led_state, 1);
0889
0890
0891
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
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) {
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
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
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);