aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hamradio/mkiss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hamradio/mkiss.c')
-rw-r--r--drivers/net/hamradio/mkiss.c188
1 files changed, 151 insertions, 37 deletions
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d9fe64b46f4b..3e9accf137e7 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -14,13 +14,14 @@
14 * 14 *
15 * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl> 15 * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
16 * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org> 16 * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
17 * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
17 */ 18 */
18
19#include <linux/config.h> 19#include <linux/config.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <asm/system.h> 21#include <asm/system.h>
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23#include <asm/uaccess.h> 23#include <asm/uaccess.h>
24#include <linux/crc16.h>
24#include <linux/string.h> 25#include <linux/string.h>
25#include <linux/mm.h> 26#include <linux/mm.h>
26#include <linux/interrupt.h> 27#include <linux/interrupt.h>
@@ -39,11 +40,6 @@
39 40
40#include <net/ax25.h> 41#include <net/ax25.h>
41 42
42#ifdef CONFIG_INET
43#include <linux/ip.h>
44#include <linux/tcp.h>
45#endif
46
47#define AX_MTU 236 43#define AX_MTU 236
48 44
49/* SLIP/KISS protocol characters. */ 45/* SLIP/KISS protocol characters. */
@@ -80,9 +76,13 @@ struct mkiss {
80 76
81 int mode; 77 int mode;
82 int crcmode; /* MW: for FlexNet, SMACK etc. */ 78 int crcmode; /* MW: for FlexNet, SMACK etc. */
83#define CRC_MODE_NONE 0 79 int crcauto; /* CRC auto mode */
84#define CRC_MODE_FLEX 1 80
85#define CRC_MODE_SMACK 2 81#define CRC_MODE_NONE 0
82#define CRC_MODE_FLEX 1
83#define CRC_MODE_SMACK 2
84#define CRC_MODE_FLEX_TEST 3
85#define CRC_MODE_SMACK_TEST 4
86 86
87 atomic_t refcnt; 87 atomic_t refcnt;
88 struct semaphore dead_sem; 88 struct semaphore dead_sem;
@@ -151,6 +151,21 @@ static int check_crc_flex(unsigned char *cp, int size)
151 return 0; 151 return 0;
152} 152}
153 153
154static int check_crc_16(unsigned char *cp, int size)
155{
156 unsigned short crc = 0x0000;
157
158 if (size < 3)
159 return -1;
160
161 crc = crc16(0, cp, size);
162
163 if (crc != 0x0000)
164 return -1;
165
166 return 0;
167}
168
154/* 169/*
155 * Standard encapsulation 170 * Standard encapsulation
156 */ 171 */
@@ -237,19 +252,42 @@ static void ax_bump(struct mkiss *ax)
237 252
238 spin_lock_bh(&ax->buflock); 253 spin_lock_bh(&ax->buflock);
239 if (ax->rbuff[0] > 0x0f) { 254 if (ax->rbuff[0] > 0x0f) {
240 if (ax->rbuff[0] & 0x20) { 255 if (ax->rbuff[0] & 0x80) {
241 ax->crcmode = CRC_MODE_FLEX; 256 if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
257 ax->stats.rx_errors++;
258 spin_unlock_bh(&ax->buflock);
259
260 return;
261 }
262 if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
263 printk(KERN_INFO
264 "mkiss: %s: Switchting to crc-smack\n",
265 ax->dev->name);
266 ax->crcmode = CRC_MODE_SMACK;
267 }
268 ax->rcount -= 2;
269 *ax->rbuff &= ~0x80;
270 } else if (ax->rbuff[0] & 0x20) {
242 if (check_crc_flex(ax->rbuff, ax->rcount) < 0) { 271 if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
243 ax->stats.rx_errors++; 272 ax->stats.rx_errors++;
273 spin_unlock_bh(&ax->buflock);
244 return; 274 return;
245 } 275 }
276 if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
277 printk(KERN_INFO
278 "mkiss: %s: Switchting to crc-flexnet\n",
279 ax->dev->name);
280 ax->crcmode = CRC_MODE_FLEX;
281 }
246 ax->rcount -= 2; 282 ax->rcount -= 2;
247 /* dl9sau bugfix: the trailling two bytes flexnet crc 283
248 * will not be passed to the kernel. thus we have 284 /*
249 * to correct the kissparm signature, because it 285 * dl9sau bugfix: the trailling two bytes flexnet crc
250 * indicates a crc but there's none 286 * will not be passed to the kernel. thus we have to
287 * correct the kissparm signature, because it indicates
288 * a crc but there's none
251 */ 289 */
252 *ax->rbuff &= ~0x20; 290 *ax->rbuff &= ~0x20;
253 } 291 }
254 } 292 }
255 spin_unlock_bh(&ax->buflock); 293 spin_unlock_bh(&ax->buflock);
@@ -352,10 +390,8 @@ static void ax_changedmtu(struct mkiss *ax)
352 "MTU change cancelled.\n", 390 "MTU change cancelled.\n",
353 ax->dev->name); 391 ax->dev->name);
354 dev->mtu = ax->mtu; 392 dev->mtu = ax->mtu;
355 if (xbuff != NULL) 393 kfree(xbuff);
356 kfree(xbuff); 394 kfree(rbuff);
357 if (rbuff != NULL)
358 kfree(rbuff);
359 return; 395 return;
360 } 396 }
361 397
@@ -417,20 +453,69 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
417 p = icp; 453 p = icp;
418 454
419 spin_lock_bh(&ax->buflock); 455 spin_lock_bh(&ax->buflock);
420 switch (ax->crcmode) { 456 if ((*p & 0x0f) != 0) {
421 unsigned short crc; 457 /* Configuration Command (kissparms(1).
458 * Protocol spec says: never append CRC.
459 * This fixes a very old bug in the linux
460 * kiss driver. -- dl9sau */
461 switch (*p & 0xff) {
462 case 0x85:
463 /* command from userspace especially for us,
464 * not for delivery to the tnc */
465 if (len > 1) {
466 int cmd = (p[1] & 0xff);
467 switch(cmd) {
468 case 3:
469 ax->crcmode = CRC_MODE_SMACK;
470 break;
471 case 2:
472 ax->crcmode = CRC_MODE_FLEX;
473 break;
474 case 1:
475 ax->crcmode = CRC_MODE_NONE;
476 break;
477 case 0:
478 default:
479 ax->crcmode = CRC_MODE_SMACK_TEST;
480 cmd = 0;
481 }
482 ax->crcauto = (cmd ? 0 : 1);
483 printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
484 }
485 spin_unlock_bh(&ax->buflock);
486 netif_start_queue(dev);
422 487
423 case CRC_MODE_FLEX: 488 return;
424 *p |= 0x20; 489 default:
425 crc = calc_crc_flex(p, len); 490 count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
426 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2); 491 }
427 break; 492 } else {
493 unsigned short crc;
494 switch (ax->crcmode) {
495 case CRC_MODE_SMACK_TEST:
496 ax->crcmode = CRC_MODE_FLEX_TEST;
497 printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
498 // fall through
499 case CRC_MODE_SMACK:
500 *p |= 0x80;
501 crc = swab16(crc16(0, p, len));
502 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
503 break;
504 case CRC_MODE_FLEX_TEST:
505 ax->crcmode = CRC_MODE_NONE;
506 printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
507 // fall through
508 case CRC_MODE_FLEX:
509 *p |= 0x20;
510 crc = calc_crc_flex(p, len);
511 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
512 break;
513
514 default:
515 count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
516 }
517 }
428 518
429 default:
430 count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
431 break;
432 }
433
434 set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); 519 set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
435 actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); 520 actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
436 ax->stats.tx_packets++; 521 ax->stats.tx_packets++;
@@ -439,8 +524,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
439 ax->dev->trans_start = jiffies; 524 ax->dev->trans_start = jiffies;
440 ax->xleft = count - actual; 525 ax->xleft = count - actual;
441 ax->xhead = ax->xbuff + actual; 526 ax->xhead = ax->xbuff + actual;
442
443 spin_unlock_bh(&ax->buflock);
444} 527}
445 528
446/* Encapsulate an AX.25 packet and kick it into a TTY queue. */ 529/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -622,7 +705,7 @@ static void ax_setup(struct net_device *dev)
622 * best way to fix this is to use a rwlock in the tty struct, but for now we 705 * best way to fix this is to use a rwlock in the tty struct, but for now we
623 * use a single global rwlock for all ttys in ppp line discipline. 706 * use a single global rwlock for all ttys in ppp line discipline.
624 */ 707 */
625static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED; 708static DEFINE_RWLOCK(disc_data_lock);
626 709
627static struct mkiss *mkiss_get(struct tty_struct *tty) 710static struct mkiss *mkiss_get(struct tty_struct *tty)
628{ 711{
@@ -643,6 +726,8 @@ static void mkiss_put(struct mkiss *ax)
643 up(&ax->dead_sem); 726 up(&ax->dead_sem);
644} 727}
645 728
729static int crc_force = 0; /* Can be overridden with insmod */
730
646static int mkiss_open(struct tty_struct *tty) 731static int mkiss_open(struct tty_struct *tty)
647{ 732{
648 struct net_device *dev; 733 struct net_device *dev;
@@ -682,6 +767,33 @@ static int mkiss_open(struct tty_struct *tty)
682 if (register_netdev(dev)) 767 if (register_netdev(dev))
683 goto out_free_buffers; 768 goto out_free_buffers;
684 769
770 /* after register_netdev() - because else printk smashes the kernel */
771 switch (crc_force) {
772 case 3:
773 ax->crcmode = CRC_MODE_SMACK;
774 printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
775 ax->dev->name);
776 break;
777 case 2:
778 ax->crcmode = CRC_MODE_FLEX;
779 printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
780 ax->dev->name);
781 break;
782 case 1:
783 ax->crcmode = CRC_MODE_NONE;
784 printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
785 ax->dev->name);
786 break;
787 case 0:
788 /* fall through */
789 default:
790 crc_force = 0;
791 printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
792 ax->dev->name);
793 ax->crcmode = CRC_MODE_SMACK_TEST;
794 }
795 ax->crcauto = (crc_force ? 0 : 1);
796
685 netif_start_queue(dev); 797 netif_start_queue(dev);
686 798
687 /* Done. We have linked the TTY line to a channel. */ 799 /* Done. We have linked the TTY line to a channel. */
@@ -765,7 +877,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
765 877
766 case SIOCSIFHWADDR: { 878 case SIOCSIFHWADDR: {
767 char addr[AX25_ADDR_LEN]; 879 char addr[AX25_ADDR_LEN];
768printk(KERN_INFO "In SIOCSIFHWADDR");
769 880
770 if (copy_from_user(&addr, 881 if (copy_from_user(&addr,
771 (void __user *) arg, AX25_ADDR_LEN)) { 882 (void __user *) arg, AX25_ADDR_LEN)) {
@@ -864,6 +975,7 @@ out:
864} 975}
865 976
866static struct tty_ldisc ax_ldisc = { 977static struct tty_ldisc ax_ldisc = {
978 .owner = THIS_MODULE,
867 .magic = TTY_LDISC_MAGIC, 979 .magic = TTY_LDISC_MAGIC,
868 .name = "mkiss", 980 .name = "mkiss",
869 .open = mkiss_open, 981 .open = mkiss_open,
@@ -904,6 +1016,8 @@ static void __exit mkiss_exit_driver(void)
904 1016
905MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>"); 1017MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
906MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); 1018MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
1019MODULE_PARM(crc_force, "i");
1020MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
907MODULE_LICENSE("GPL"); 1021MODULE_LICENSE("GPL");
908MODULE_ALIAS_LDISC(N_AX25); 1022MODULE_ALIAS_LDISC(N_AX25);
909 1023