Import 2.3.46pre3
[davej-history.git] / drivers / net / hamradio / 6pack.c
blobe8708a28fa810cfb7260f8b8db477752077bbc45
1 /*
2 * 6pack.c This module implements the 6pack protocol for kernel-based
3 * devices like TTY. It interfaces between a raw TTY and the
4 * kernel's AX.25 protocol layers.
6 * Version: @(#)6pack.c 0.3.0 04/07/98
8 * Authors: Andreas Könsgen <ajk@iehk.rwth-aachen.de>
10 * Quite a lot of stuff "stolen" by Jörg Reuter from slip.c, written by
12 * Laurence Culhane, <loz@holmes.demon.co.uk>
13 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
17 #include <linux/config.h>
18 #include <linux/module.h>
20 #include <asm/system.h>
21 #include <asm/uaccess.h>
22 #include <asm/bitops.h>
23 #include <linux/string.h>
24 #include <linux/mm.h>
25 #include <linux/interrupt.h>
26 #include <linux/in.h>
27 #include <linux/tty.h>
28 #include <linux/errno.h>
29 #include <linux/netdevice.h>
30 #include <linux/timer.h>
31 #include <net/ax25.h>
32 #include <linux/etherdevice.h>
33 #include <linux/skbuff.h>
34 #include <linux/rtnetlink.h>
35 #include <linux/if_arp.h>
36 #include <linux/if_slip.h>
37 #include <linux/init.h>
38 #include <linux/ip.h>
39 #include <linux/tcp.h>
40 /*
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <unistd.h>
48 #include "6pack.h"
50 typedef unsigned char byte;
53 typedef struct sixpack_ctrl {
54 char if_name[8]; /* "sp0\0" .. "sp99999\0" */
55 struct sixpack ctrl; /* 6pack things */
56 struct net_device dev; /* the device */
57 } sixpack_ctrl_t;
58 static sixpack_ctrl_t **sixpack_ctrls = NULL;
59 int sixpack_maxdev = SIXP_NRUNIT; /* Can be overridden with insmod! */
61 static struct tty_ldisc sp_ldisc;
63 static void sp_start_tx_timer(struct sixpack *);
64 static void sp_xmit_on_air(unsigned long);
65 static void resync_tnc(unsigned long);
66 void sixpack_decode(struct sixpack *, unsigned char[], int);
67 int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
69 void decode_prio_command(byte, struct sixpack *);
70 void decode_std_command(byte, struct sixpack *);
71 void decode_data(byte, struct sixpack *);
73 static int tnc_init(struct sixpack *);
75 /* Find a free 6pack channel, and link in this `tty' line. */
76 static inline struct sixpack *
77 sp_alloc(void)
79 sixpack_ctrl_t *spp = NULL;
80 int i;
82 if (sixpack_ctrls == NULL) return NULL; /* Master array missing ! */
84 for (i = 0; i < sixpack_maxdev; i++)
86 spp = sixpack_ctrls[i];
88 if (spp == NULL)
89 break;
91 if (!test_and_set_bit(SIXPF_INUSE, &spp->ctrl.flags))
92 break;
95 /* Too many devices... */
96 if (i >= sixpack_maxdev)
97 return NULL;
99 /* If no channels are available, allocate one */
100 if (!spp &&
101 (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
102 GFP_KERNEL)) != NULL)
104 spp = sixpack_ctrls[i];
105 memset(spp, 0, sizeof(sixpack_ctrl_t));
107 /* Initialize channel control data */
108 set_bit(SIXPF_INUSE, &spp->ctrl.flags);
109 spp->ctrl.tty = NULL;
110 sprintf(spp->if_name, "sp%d", i);
111 spp->dev.name = spp->if_name;
112 spp->dev.base_addr = i;
113 spp->dev.priv = (void*)&(spp->ctrl);
114 spp->dev.next = NULL;
115 spp->dev.init = sixpack_init;
118 if (spp != NULL)
120 /* register device so that it can be ifconfig'ed */
121 /* sixpack_init() will be called as a side-effect */
122 /* SIDE-EFFECT WARNING: sixpack_init() CLEARS spp->ctrl ! */
124 if (register_netdev(&(spp->dev)) == 0)
126 set_bit(SIXPF_INUSE, &spp->ctrl.flags);
127 spp->ctrl.dev = &(spp->dev);
128 spp->dev.priv = (void*)&(spp->ctrl);
130 return (&(spp->ctrl));
131 } else {
132 clear_bit(SIXPF_INUSE,&(spp->ctrl.flags));
133 printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
137 return NULL;
141 /* Free a 6pack channel. */
142 static inline void
143 sp_free(struct sixpack *sp)
145 /* Free all 6pack frame buffers. */
146 if (sp->rbuff)
147 kfree(sp->rbuff);
148 sp->rbuff = NULL;
149 if (sp->xbuff) {
150 kfree(sp->xbuff);
152 sp->xbuff = NULL;
154 if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags))
156 printk(KERN_WARNING "%s: sp_free for already free unit.\n", sp->dev->name);
161 /* Send one completely decapsulated IP datagram to the IP layer. */
163 /* This is the routine that sends the received data to the kernel AX.25.
164 'cmd' is the KISS command. For AX.25 data, it is zero. */
166 static void
167 sp_bump(struct sixpack *sp, char cmd)
169 struct sk_buff *skb;
170 int count;
171 unsigned char *ptr;
173 count = sp->rcount+1;
175 sp->rx_bytes+=count;
177 skb = dev_alloc_skb(count);
178 if (skb == NULL)
180 printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
181 sp->rx_dropped++;
182 return;
185 skb->dev = sp->dev;
186 ptr = skb_put(skb, count);
187 *ptr++ = cmd; /* KISS command */
189 memcpy(ptr, (sp->cooked_buf)+1, count);
190 skb->mac.raw=skb->data;
191 skb->protocol=htons(ETH_P_AX25);
192 netif_rx(skb);
193 sp->rx_packets++;
197 /* ----------------------------------------------------------------------- */
199 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
200 static void
201 sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
203 unsigned char *p;
204 int actual, count;
206 if (len > sp->mtu) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
208 len = sp->mtu;
209 printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
210 sp->tx_dropped++;
211 netif_start_queue(sp->dev);
212 return;
215 p = icp;
217 if (p[0] > 5)
219 printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
220 netif_start_queue(sp->dev);
221 return;
224 if ((p[0] != 0) && (len > 2))
226 printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
227 netif_start_queue(sp->dev);
228 return;
231 if ((p[0] == 0) && (len < 15))
233 printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
234 netif_start_queue(sp->dev);
235 sp->tx_dropped++;
236 return;
239 count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
240 sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
242 switch(p[0])
244 case 1: sp->tx_delay = p[1]; return;
245 case 2: sp->persistance = p[1]; return;
246 case 3: sp->slottime = p[1]; return;
247 case 4: /* ignored */ return;
248 case 5: sp->duplex = p[1]; return;
251 if (p[0] == 0) {
252 /* in case of fullduplex or DAMA operation, we don't take care
253 about the state of the DCD or of any timers, as the determination
254 of the correct time to send is the job of the AX.25 layer. We send
255 immediately after data has arrived. */
256 if (sp->duplex == 1){
257 sp->led_state = 0x70;
258 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
259 sp->tx_enable = 1;
260 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, count);
261 sp->xleft = count - actual;
262 sp->xhead = sp->xbuff + actual;
263 sp->led_state = 0x60;
264 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
266 else {
267 sp->xleft = count;
268 sp->xhead = sp->xbuff;
269 sp->status2 = count;
270 if (sp->duplex == 0)
271 sp_start_tx_timer(sp);
277 * Called by the TTY driver when there's room for more data. If we have
278 * more packets to send, we send them here.
280 static void sixpack_write_wakeup(struct tty_struct *tty)
282 int actual;
283 struct sixpack *sp = (struct sixpack *) tty->disc_data;
285 /* First make sure we're connected. */
286 if (!sp || sp->magic != SIXPACK_MAGIC || !test_bit(LINK_STATE_START, &sp->dev->state)) {
287 return;
290 if (sp->xleft <= 0) {
291 /* Now serial buffer is almost free & we can start
292 * transmission of another packet */
293 sp->tx_packets++;
294 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
295 sp->tx_enable = 0;
296 netif_wake_queue(sp->dev);
297 return;
300 if (sp->tx_enable == 1) {
301 actual = tty->driver.write(tty, 0, sp->xhead, sp->xleft);
302 sp->xleft -= actual;
303 sp->xhead += actual;
307 /* ----------------------------------------------------------------------- */
309 /* Encapsulate an IP datagram and kick it into a TTY queue. */
311 static int
312 sp_xmit(struct sk_buff *skb, struct net_device *dev)
314 struct sixpack *sp = (struct sixpack*)(dev->priv);
316 /* We were not busy, so we are now... :-) */
317 if (skb != NULL) {
318 netif_stop_queue(dev);
319 sp->tx_bytes+=skb->len; /*---2.1.x---*/
320 sp_encaps(sp, skb->data, skb->len);
321 dev_kfree_skb(skb);
323 return 0;
325 /* #endif */
328 /* perform the persistence/slottime algorithm for CSMA access. If the persistence
329 check was successful, write the data to the serial driver. Note that in case
330 of DAMA operation, the data is not sent here. */
332 static
333 void sp_xmit_on_air(unsigned long channel)
335 struct sixpack *sp = (struct sixpack *) channel;
336 int actual;
337 static unsigned char random;
339 random = random * 17 + 41;
341 if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistance)) {
342 sp->led_state = 0x70;
343 sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
344 sp->tx_enable = 1;
345 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
346 sp->xleft -= actual;
347 sp->xhead += actual;
348 sp->led_state = 0x60;
349 sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
350 sp->status2 = 0;
351 } else
352 sp_start_tx_timer(sp);
353 } /* sp_xmit */
355 /* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
357 /* Return the frame type ID */
358 static int sp_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
359 void *daddr, void *saddr, unsigned len)
361 #ifdef CONFIG_INET
362 if (type != htons(ETH_P_AX25))
363 return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
364 #endif
365 return 0;
369 static int sp_rebuild_header(struct sk_buff *skb)
371 #ifdef CONFIG_INET
372 return ax25_rebuild_header(skb);
373 #else
374 return 0;
375 #endif
378 /* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
380 /* Open the low-level part of the 6pack channel. */
381 static int
382 sp_open(struct net_device *dev)
384 struct sixpack *sp = (struct sixpack*)(dev->priv);
385 unsigned long len;
387 if (sp->tty == NULL)
388 return -ENODEV;
391 * Allocate the 6pack frame buffers:
393 * rbuff Receive buffer.
394 * xbuff Transmit buffer.
395 * cbuff Temporary compression buffer.
398 /* !!! length of the buffers. MTU is IP MTU, not PACLEN!
401 len = dev->mtu * 2;
403 sp->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
404 if (sp->rbuff == NULL)
405 return -ENOMEM;
407 sp->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
408 if (sp->xbuff == NULL)
410 kfree(sp->rbuff);
411 return -ENOMEM;
414 sp->mtu = AX25_MTU + 73;
415 sp->buffsize = len;
416 sp->rcount = 0;
417 sp->rx_count = 0;
418 sp->rx_count_cooked = 0;
419 sp->xleft = 0;
421 sp->flags &= (1 << SIXPF_INUSE); /* Clear ESCAPE & ERROR flags */
423 sp->duplex = 0;
424 sp->tx_delay = SIXP_TXDELAY;
425 sp->persistance = SIXP_PERSIST;
426 sp->slottime = SIXP_SLOTTIME;
427 sp->led_state = 0x60;
428 sp->status = 1;
429 sp->status1 = 1;
430 sp->status2 = 0;
431 sp->tnc_ok = 0;
432 sp->tx_enable = 0;
434 netif_start_queue(dev);
436 init_timer(&sp->tx_t);
437 init_timer(&sp->resync_t);
438 return 0;
442 /* Close the low-level part of the 6pack channel. */
443 static int
444 sp_close(struct net_device *dev)
446 struct sixpack *sp = (struct sixpack*)(dev->priv);
448 if (sp->tty == NULL) {
449 return -EBUSY;
451 sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
453 netif_stop_queue(dev);
454 return 0;
457 static int
458 sixpack_receive_room(struct tty_struct *tty)
460 return 65536; /* We can handle an infinite amount of data. :-) */
463 /* !!! receive state machine */
466 * Handle the 'receiver data ready' interrupt.
467 * This function is called by the 'tty_io' module in the kernel when
468 * a block of 6pack data has been received, which can now be decapsulated
469 * and sent on to some IP layer for further processing.
471 static void
472 sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
474 unsigned char buf[512];
475 unsigned long flags;
476 int count1;
478 struct sixpack *sp = (struct sixpack *) tty->disc_data;
480 if (!sp || sp->magic != SIXPACK_MAGIC || !test_bit(LINK_STATE_START, &sp->dev->state) || !count)
481 return;
483 save_flags(flags);
484 cli();
485 memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
486 restore_flags(flags);
488 /* Read the characters out of the buffer */
490 count1 = count;
491 while(count)
493 count--;
494 if (fp && *fp++)
496 if (!test_and_set_bit(SIXPF_ERROR, &sp->flags)) {
497 sp->rx_errors++;
499 continue;
502 sixpack_decode(sp, buf, count1);
506 * Open the high-level part of the 6pack channel.
507 * This function is called by the TTY module when the
508 * 6pack line discipline is called for. Because we are
509 * sure the tty line exists, we only have to link it to
510 * a free 6pcack channel...
512 static int
513 sixpack_open(struct tty_struct *tty)
515 struct sixpack *sp = (struct sixpack *) tty->disc_data;
516 int err;
518 /* First make sure we're not already connected. */
520 if (sp && sp->magic == SIXPACK_MAGIC)
521 return -EEXIST;
523 /* OK. Find a free 6pack channel to use. */
524 if ((sp = sp_alloc()) == NULL)
525 return -ENFILE;
526 sp->tty = tty;
527 tty->disc_data = sp;
528 if (tty->driver.flush_buffer)
529 tty->driver.flush_buffer(tty);
531 if (tty->ldisc.flush_buffer)
532 tty->ldisc.flush_buffer(tty);
535 /* Restore default settings */
536 sp->dev->type = ARPHRD_AX25;
538 /* Perform the low-level 6pack initialization. */
539 if ((err = sp_open(sp->dev)))
540 return err;
542 MOD_INC_USE_COUNT;
544 /* Done. We have linked the TTY line to a channel. */
546 tnc_init(sp);
548 return sp->dev->base_addr;
553 * Close down a 6pack channel.
554 * This means flushing out any pending queues, and then restoring the
555 * TTY line discipline to what it was before it got hooked to 6pack
556 * (which usually is TTY again).
558 static void
559 sixpack_close(struct tty_struct *tty)
561 struct sixpack *sp = (struct sixpack *) tty->disc_data;
563 /* First make sure we're connected. */
564 if (!sp || sp->magic != SIXPACK_MAGIC)
565 return;
567 rtnl_lock();
568 if (sp->dev->flags & IFF_UP)
569 (void) dev_close(sp->dev);
571 del_timer(&(sp->tx_t));
572 del_timer(&(sp->resync_t));
574 tty->disc_data = 0;
575 sp->tty = NULL;
576 /* VSV = very important to remove timers */
578 sp_free(sp);
579 unregister_netdev(sp->dev);
580 rtnl_unlock();
581 MOD_DEC_USE_COUNT;
585 static struct net_device_stats *
586 sp_get_stats(struct net_device *dev)
588 static struct net_device_stats stats;
589 struct sixpack *sp = (struct sixpack*)(dev->priv);
591 memset(&stats, 0, sizeof(struct net_device_stats));
593 stats.rx_packets = sp->rx_packets;
594 stats.tx_packets = sp->tx_packets;
595 stats.rx_bytes = sp->rx_bytes;
596 stats.tx_bytes = sp->tx_bytes;
597 stats.rx_dropped = sp->rx_dropped;
598 stats.tx_dropped = sp->tx_dropped;
599 stats.tx_errors = sp->tx_errors;
600 stats.rx_errors = sp->rx_errors;
601 stats.rx_over_errors = sp->rx_over_errors;
602 return (&stats);
607 sp_set_mac_address(struct net_device *dev, void *addr)
609 int err;
611 err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
612 if (err) {
613 return err;
616 copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN); /* addr is an AX.25 shifted ASCII mac address */
618 return 0;
621 static int
622 sp_set_dev_mac_address(struct net_device *dev, void *addr)
624 struct sockaddr *sa=addr;
625 memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
626 return 0;
630 /* Perform I/O control on an active 6pack channel. */
631 static int
632 sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
634 struct sixpack *sp = (struct sixpack *) tty->disc_data;
635 int err;
636 unsigned int tmp;
638 /* First make sure we're connected. */
639 if (!sp || sp->magic != SIXPACK_MAGIC) {
640 return -EINVAL;
643 switch(cmd) {
644 case SIOCGIFNAME:
645 err = verify_area(VERIFY_WRITE, arg, strlen(sp->dev->name) + 1);
646 if (err) {
647 return err;
649 copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1);
650 return 0;
652 case SIOCGIFENCAP:
653 err = verify_area(VERIFY_WRITE, arg, sizeof(int));
654 if (err) {
655 return err;
657 put_user(0, (int *)arg);
658 return 0;
660 case SIOCSIFENCAP:
661 err = verify_area(VERIFY_READ, arg, sizeof(int));
662 if (err) {
663 return err;
665 get_user(tmp,(int *)arg);
667 sp->mode = tmp;
668 sp->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
669 sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
670 sp->dev->type = ARPHRD_AX25;
672 return 0;
674 case SIOCSIFHWADDR:
675 return sp_set_mac_address(sp->dev, arg);
677 /* Allow stty to read, but not set, the serial port */
678 case TCGETS:
679 case TCGETA:
680 return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
682 default:
683 return -ENOIOCTLCMD;
687 static int sp_open_dev(struct net_device *dev)
689 struct sixpack *sp = (struct sixpack*)(dev->priv);
690 if(sp->tty==NULL)
691 return -ENODEV;
692 return 0;
695 /* Initialize 6pack control device -- register 6pack line discipline */
697 static int __init sixpack_init_ctrl_dev(void)
699 int status;
701 if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
703 printk(KERN_INFO "AX.25: 6pack driver, %s (dynamic channels, max=%d)\n",
704 SIXPACK_VERSION, sixpack_maxdev);
706 sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
707 if (sixpack_ctrls == NULL)
709 printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array! Uaargh! (-> No 6pack available)\n");
710 return -ENOMEM;
713 /* Clear the pointer array, we allocate devices when we need them */
714 memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
717 /* Fill in our line protocol discipline, and register it */
718 memset(&sp_ldisc, 0, sizeof(sp_ldisc));
719 sp_ldisc.magic = TTY_LDISC_MAGIC;
720 sp_ldisc.name = "6pack";
721 sp_ldisc.flags = 0;
722 sp_ldisc.open = sixpack_open;
723 sp_ldisc.close = sixpack_close;
724 sp_ldisc.read = NULL;
725 sp_ldisc.write = NULL;
726 sp_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
727 unsigned int, unsigned long)) sixpack_ioctl;
728 sp_ldisc.poll = NULL;
729 sp_ldisc.receive_buf = sixpack_receive_buf;
730 sp_ldisc.receive_room = sixpack_receive_room;
731 sp_ldisc.write_wakeup = sixpack_write_wakeup;
732 if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
733 printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
736 return status;
739 static void __exit sixpack_cleanup_driver(void)
741 int i;
743 if (sixpack_ctrls != NULL)
745 for (i = 0; i < sixpack_maxdev; i++)
747 if (sixpack_ctrls[i])
750 * VSV = if dev->start==0, then device
751 * unregistered while close proc.
753 if (test_bit(LINK_STATE_START, &sixpack_ctrls[i]->dev.state))
754 unregister_netdev(&(sixpack_ctrls[i]->dev));
756 kfree(sixpack_ctrls[i]);
757 sixpack_ctrls[i] = NULL;
760 kfree(sixpack_ctrls);
761 sixpack_ctrls = NULL;
763 if ((i = tty_register_ldisc(N_6PACK, NULL)))
765 printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
770 /* Initialize the 6pack driver. Called by DDI. */
772 sixpack_init(struct net_device *dev)
774 struct sixpack *sp = (struct sixpack*)(dev->priv);
776 static char ax25_bcast[AX25_ADDR_LEN] =
777 {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
778 static char ax25_test[AX25_ADDR_LEN] =
779 {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
781 if (sp == NULL) /* Allocation failed ?? */
782 return -ENODEV;
784 /* Set up the "6pack Control Block". (And clear statistics) */
786 memset(sp, 0, sizeof (struct sixpack));
787 sp->magic = SIXPACK_MAGIC;
788 sp->dev = dev;
790 /* Finish setting up the DEVICE info. */
791 dev->mtu = SIXP_MTU;
792 dev->hard_start_xmit = sp_xmit;
793 dev->open = sp_open_dev;
794 dev->stop = sp_close;
795 dev->hard_header = sp_header;
796 dev->get_stats = sp_get_stats;
797 dev->set_mac_address = sp_set_dev_mac_address;
798 dev->hard_header_len = AX25_MAX_HEADER_LEN;
799 dev->addr_len = AX25_ADDR_LEN;
800 dev->type = ARPHRD_AX25;
801 dev->tx_queue_len = 10;
802 dev->rebuild_header = sp_rebuild_header;
803 dev->tx_timeout = NULL;
805 memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); /* Only activated in AX.25 mode */
806 memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); /* "" "" "" "" */
808 dev_init_buffers(dev);
810 /* New-style flags. */
811 dev->flags = 0;
813 return 0;
819 /* ----> 6pack timer interrupt handler and friends. <---- */
820 static void
821 sp_start_tx_timer(struct sixpack *sp)
823 int when = sp->slottime;
825 del_timer(&(sp->tx_t));
826 sp->tx_t.data = (unsigned long) sp;
827 sp->tx_t.function = sp_xmit_on_air;
828 sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
829 add_timer(&(sp->tx_t));
833 /* encode an AX.25 packet into 6pack */
835 int encode_sixpack(byte *tx_buf, byte *tx_buf_raw, int length, byte tx_delay)
837 int count = 0;
838 byte checksum = 0, buf[400];
839 int raw_count = 0;
841 tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
842 tx_buf_raw[raw_count++] = SIXP_SEOF;
844 buf[0] = tx_delay;
845 for(count = 1; count < length; count++)
846 buf[count] = tx_buf[count];
848 for(count = 0; count < length; count++)
849 checksum += buf[count];
850 buf[length] = (byte)0xff - checksum;
852 for(count = 0; count <= length; count++) {
853 if((count % 3) == 0) {
854 tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
855 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
857 else if((count % 3) == 1) {
858 tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
859 tx_buf_raw[raw_count] =
860 ((buf[count] >> 2) & 0x3c);
861 } else {
862 tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
863 tx_buf_raw[raw_count++] =
864 (buf[count] >> 2);
865 } /* else */
866 } /* for */
867 if ((length % 3) != 2)
868 raw_count++;
869 tx_buf_raw[raw_count++] = SIXP_SEOF;
870 return(raw_count);
874 /* decode a 6pack packet */
876 void
877 sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
879 byte inbyte;
880 int count1;
882 for (count1 = 0; count1 < count; count1++) {
883 inbyte = pre_rbuff[count1];
884 if (inbyte == SIXP_FOUND_TNC) {
885 printk(KERN_INFO "6pack: TNC found.\n");
886 sp->tnc_ok = 1;
887 del_timer(&(sp->resync_t));
889 if((inbyte & SIXP_PRIO_CMD_MASK) != 0)
890 decode_prio_command(inbyte, sp);
891 else if((inbyte & SIXP_STD_CMD_MASK) != 0)
892 decode_std_command(inbyte, sp);
893 else {
894 if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
895 decode_data(inbyte, sp);
896 } /* else */
897 } /* for */
900 static int
901 tnc_init(struct sixpack *sp)
903 static byte inbyte;
905 inbyte = 0xe8;
906 sp->tty->driver.write(sp->tty, 0, &inbyte, 1);
908 del_timer(&(sp->resync_t));
909 sp->resync_t.data = (unsigned long) sp;
910 sp->resync_t.function = resync_tnc;
911 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
912 add_timer(&(sp->resync_t));
914 return 0;
918 /* identify and execute a 6pack priority command byte */
920 void decode_prio_command(byte cmd, struct sixpack *sp)
922 byte channel;
923 int actual;
925 channel = cmd & SIXP_CHN_MASK;
926 if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
928 /* RX and DCD flags can only be set in the same prio command,
929 if the DCD flag has been set without the RX flag in the previous
930 prio command. If DCD has not been set before, something in the
931 transmission has gone wrong. In this case, RX and DCD are
932 cleared in order to prevent the decode_data routine from
933 reading further data that might be corrupt. */
935 if (((sp->status & SIXP_DCD_MASK) == 0) &&
936 ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
937 if (sp->status != 1)
938 printk(KERN_DEBUG "6pack: protocol violation\n");
939 else
940 sp->status = 0;
941 cmd &= !SIXP_RX_DCD_MASK;
943 sp->status = cmd & SIXP_PRIO_DATA_MASK;
944 } /* if */
945 else { /* output watchdog char if idle */
946 if ((sp->status2 != 0) && (sp->duplex == 1)) {
947 sp->led_state = 0x70;
948 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
949 sp->tx_enable = 1;
950 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
951 sp->xleft -= actual;
952 sp->xhead += actual;
953 sp->led_state = 0x60;
954 sp->status2 = 0;
956 } /* if */
957 } /* else */
959 /* needed to trigger the TNC watchdog */
960 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
962 /* if the state byte has been received, the TNC is present,
963 so the resync timer can be reset. */
965 if (sp->tnc_ok == 1) {
966 del_timer(&(sp->resync_t));
967 sp->resync_t.data = (unsigned long) sp;
968 sp->resync_t.function = resync_tnc;
969 sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
970 add_timer(&(sp->resync_t));
973 sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
976 /* try to resync the TNC. Called by the resync timer defined in
977 decode_prio_command */
979 static void
980 resync_tnc(unsigned long channel)
982 static char resync_cmd = 0xe8;
983 struct sixpack *sp = (struct sixpack *) channel;
985 printk(KERN_INFO "6pack: resyncing TNC\n");
987 /* clear any data that might have been received */
989 sp->rx_count = 0;
990 sp->rx_count_cooked = 0;
992 /* reset state machine */
994 sp->status = 1;
995 sp->status1 = 1;
996 sp->status2 = 0;
997 sp->tnc_ok = 0;
999 /* resync the TNC */
1001 sp->led_state = 0x60;
1002 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1003 sp->tty->driver.write(sp->tty, 0, &resync_cmd, 1);
1006 /* Start resync timer again -- the TNC might be still absent */
1008 del_timer(&(sp->resync_t));
1009 sp->resync_t.data = (unsigned long) sp;
1010 sp->resync_t.function = resync_tnc;
1011 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
1012 add_timer(&(sp->resync_t));
1017 /* identify and execute a standard 6pack command byte */
1019 void decode_std_command(byte cmd, struct sixpack *sp)
1021 byte checksum = 0, rest = 0, channel;
1022 short i;
1024 channel = cmd & SIXP_CHN_MASK;
1025 switch(cmd & SIXP_CMD_MASK) { /* normal command */
1026 case SIXP_SEOF:
1027 if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
1028 if ((sp->status & SIXP_RX_DCD_MASK) ==
1029 SIXP_RX_DCD_MASK) {
1030 sp->led_state = 0x68;
1031 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1032 } /* if */
1033 } else {
1034 sp->led_state = 0x60;
1035 /* fill trailing bytes with zeroes */
1036 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1037 rest = sp->rx_count;
1038 if (rest != 0)
1039 for(i=rest; i<=3; i++)
1040 decode_data(0, sp);
1041 if (rest == 2)
1042 sp->rx_count_cooked -= 2;
1043 else if (rest == 3)
1044 sp->rx_count_cooked -= 1;
1045 for (i=0; i<sp->rx_count_cooked; i++)
1046 checksum+=sp->cooked_buf[i];
1047 if (checksum != SIXP_CHKSUM) {
1048 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
1049 } else {
1050 sp->rcount = sp->rx_count_cooked-2;
1051 sp_bump(sp, 0);
1052 } /* else */
1053 sp->rx_count_cooked = 0;
1054 } /* else */
1055 break;
1056 case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
1057 break;
1058 case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
1059 break;
1060 case SIXP_RX_BUF_OVL:
1061 printk(KERN_DEBUG "6pack: RX buffer overflow\n");
1062 } /* switch */
1063 } /* function */
1065 /* decode 4 sixpack-encoded bytes into 3 data bytes */
1067 void decode_data(byte inbyte, struct sixpack *sp)
1070 unsigned char *buf;
1072 if (sp->rx_count != 3)
1073 sp->raw_buf[sp->rx_count++] = inbyte;
1074 else {
1075 buf = sp->raw_buf;
1076 sp->cooked_buf[sp->rx_count_cooked++] =
1077 buf[0] | ((buf[1] << 2) & 0xc0);
1078 sp->cooked_buf[sp->rx_count_cooked++] =
1079 (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
1080 sp->cooked_buf[sp->rx_count_cooked++] =
1081 (buf[2] & 0x03) | (inbyte << 2);
1082 sp->rx_count = 0;
1087 MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
1088 MODULE_DESCRIPTION("6pack driver for AX.25");
1089 module_init(sixpack_init_ctrl_dev);
1090 module_exit(sixpack_cleanup_driver);