aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/hamradio/Kconfig1
-rw-r--r--drivers/net/hamradio/mkiss.c178
2 files changed, 148 insertions, 31 deletions
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index de087cd609d9..896aa02000d7 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -1,6 +1,7 @@
1config MKISS 1config MKISS
2 tristate "Serial port KISS driver" 2 tristate "Serial port KISS driver"
3 depends on AX25 3 depends on AX25
4 select CRC16
4 ---help--- 5 ---help---
5 KISS is a protocol used for the exchange of data between a computer 6 KISS is a protocol used for the exchange of data between a computer
6 and a Terminal Node Controller (a small embedded system commonly 7 and a Terminal Node Controller (a small embedded system commonly
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 331a75c8aee2..7961f5b41c4b 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);
@@ -417,20 +455,69 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
417 p = icp; 455 p = icp;
418 456
419 spin_lock_bh(&ax->buflock); 457 spin_lock_bh(&ax->buflock);
420 switch (ax->crcmode) { 458 if ((*p & 0x0f) != 0) {
421 unsigned short crc; 459 /* Configuration Command (kissparms(1).
460 * Protocol spec says: never append CRC.
461 * This fixes a very old bug in the linux
462 * kiss driver. -- dl9sau */
463 switch (*p & 0xff) {
464 case 0x85:
465 /* command from userspace especially for us,
466 * not for delivery to the tnc */
467 if (len > 1) {
468 int cmd = (p[1] & 0xff);
469 switch(cmd) {
470 case 3:
471 ax->crcmode = CRC_MODE_SMACK;
472 break;
473 case 2:
474 ax->crcmode = CRC_MODE_FLEX;
475 break;
476 case 1:
477 ax->crcmode = CRC_MODE_NONE;
478 break;
479 case 0:
480 default:
481 ax->crcmode = CRC_MODE_SMACK_TEST;
482 cmd = 0;
483 }
484 ax->crcauto = (cmd ? 0 : 1);
485 printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
486 }
487 spin_unlock_bh(&ax->buflock);
488 netif_start_queue(dev);
422 489
423 case CRC_MODE_FLEX: 490 return;
424 *p |= 0x20; 491 default:
425 crc = calc_crc_flex(p, len); 492 count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
426 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2); 493 }
427 break; 494 } else {
495 unsigned short crc;
496 switch (ax->crcmode) {
497 case CRC_MODE_SMACK_TEST:
498 ax->crcmode = CRC_MODE_FLEX_TEST;
499 printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
500 // fall through
501 case CRC_MODE_SMACK:
502 *p |= 0x80;
503 crc = swab16(crc16(0, p, len));
504 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
505 break;
506 case CRC_MODE_FLEX_TEST:
507 ax->crcmode = CRC_MODE_NONE;
508 printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
509 // fall through
510 case CRC_MODE_FLEX:
511 *p |= 0x20;
512 crc = calc_crc_flex(p, len);
513 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
514 break;
515
516 default:
517 count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
518 }
519 }
428 520
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); 521 set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
435 actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); 522 actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
436 ax->stats.tx_packets++; 523 ax->stats.tx_packets++;
@@ -439,8 +526,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
439 ax->dev->trans_start = jiffies; 526 ax->dev->trans_start = jiffies;
440 ax->xleft = count - actual; 527 ax->xleft = count - actual;
441 ax->xhead = ax->xbuff + actual; 528 ax->xhead = ax->xbuff + actual;
442
443 spin_unlock_bh(&ax->buflock);
444} 529}
445 530
446/* Encapsulate an AX.25 packet and kick it into a TTY queue. */ 531/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
@@ -643,6 +728,8 @@ static void mkiss_put(struct mkiss *ax)
643 up(&ax->dead_sem); 728 up(&ax->dead_sem);
644} 729}
645 730
731static int crc_force = 0; /* Can be overridden with insmod */
732
646static int mkiss_open(struct tty_struct *tty) 733static int mkiss_open(struct tty_struct *tty)
647{ 734{
648 struct net_device *dev; 735 struct net_device *dev;
@@ -682,6 +769,33 @@ static int mkiss_open(struct tty_struct *tty)
682 if (register_netdev(dev)) 769 if (register_netdev(dev))
683 goto out_free_buffers; 770 goto out_free_buffers;
684 771
772 /* after register_netdev() - because else printk smashes the kernel */
773 switch (crc_force) {
774 case 3:
775 ax->crcmode = CRC_MODE_SMACK;
776 printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n",
777 ax->dev->name);
778 break;
779 case 2:
780 ax->crcmode = CRC_MODE_FLEX;
781 printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n",
782 ax->dev->name);
783 break;
784 case 1:
785 ax->crcmode = CRC_MODE_NONE;
786 printk(KERN_INFO "mkiss: %s: crc mode disabled.\n",
787 ax->dev->name);
788 break;
789 case 0:
790 /* fall through */
791 default:
792 crc_force = 0;
793 printk(KERN_INFO "mkiss: %s: crc mode is auto.\n",
794 ax->dev->name);
795 ax->crcmode = CRC_MODE_SMACK_TEST;
796 }
797 ax->crcauto = (crc_force ? 0 : 1);
798
685 netif_start_queue(dev); 799 netif_start_queue(dev);
686 800
687 /* Done. We have linked the TTY line to a channel. */ 801 /* Done. We have linked the TTY line to a channel. */
@@ -903,6 +1017,8 @@ static void __exit mkiss_exit_driver(void)
903 1017
904MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>"); 1018MODULE_AUTHOR("Ralf Baechle DL5RB <ralf@linux-mips.org>");
905MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs"); 1019MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
1020MODULE_PARM(crc_force, "i");
1021MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
906MODULE_LICENSE("GPL"); 1022MODULE_LICENSE("GPL");
907MODULE_ALIAS_LDISC(N_AX25); 1023MODULE_ALIAS_LDISC(N_AX25);
908 1024