* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / net / hamradio / 6pack.c
blob16dc8a976c7770a0dd7b6d8c714eff4fa944c862
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 /* Set the "sending" flag. */
162 static inline void
163 sp_lock(struct sixpack *sp)
165 if (test_and_set_bit(0, (void *) &sp->dev->tbusy))
166 printk(KERN_WARNING "%s: trying to lock already locked device!\n", sp->dev->name);
170 /* Clear the "sending" flag. */
171 static inline void
172 sp_unlock(struct sixpack *sp)
174 if (!test_and_clear_bit(0, (void *)&sp->dev->tbusy))
175 printk(KERN_WARNING "%s: trying to unlock already unlocked device!\n", sp->dev->name);
179 /* Send one completely decapsulated IP datagram to the IP layer. */
181 /* This is the routine that sends the received data to the kernel AX.25.
182 'cmd' is the KISS command. For AX.25 data, it is zero. */
184 static void
185 sp_bump(struct sixpack *sp, char cmd)
187 struct sk_buff *skb;
188 int count;
189 unsigned char *ptr;
191 count = sp->rcount+1;
193 sp->rx_bytes+=count;
195 skb = dev_alloc_skb(count);
196 if (skb == NULL)
198 printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
199 sp->rx_dropped++;
200 return;
203 skb->dev = sp->dev;
204 ptr = skb_put(skb, count);
205 *ptr++ = cmd; /* KISS command */
207 memcpy(ptr, (sp->cooked_buf)+1, count);
208 skb->mac.raw=skb->data;
209 skb->protocol=htons(ETH_P_AX25);
210 netif_rx(skb);
211 sp->rx_packets++;
215 /* ----------------------------------------------------------------------- */
217 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
218 static void
219 sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
221 unsigned char *p;
222 int actual, count;
224 if (len > sp->mtu) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
226 len = sp->mtu;
227 printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
228 sp->tx_dropped++;
229 sp_unlock(sp);
230 return;
233 p = icp;
235 if (p[0] > 5)
237 printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
238 sp_unlock(sp);
239 return;
242 if ((p[0] != 0) && (len > 2))
244 printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
245 sp_unlock(sp);
246 return;
249 if ((p[0] == 0) && (len < 15))
251 printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
252 sp_unlock(sp);
253 sp->tx_dropped++;
254 return;
257 count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
258 sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
260 switch(p[0])
262 case 1: sp->tx_delay = p[1]; return;
263 case 2: sp->persistance = p[1]; return;
264 case 3: sp->slottime = p[1]; return;
265 case 4: /* ignored */ return;
266 case 5: sp->duplex = p[1]; return;
269 if (p[0] == 0) {
270 /* in case of fullduplex or DAMA operation, we don't take care
271 about the state of the DCD or of any timers, as the determination
272 of the correct time to send is the job of the AX.25 layer. We send
273 immediately after data has arrived. */
274 if (sp->duplex == 1){
275 sp->led_state = 0x70;
276 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
277 sp->tx_enable = 1;
278 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, count);
279 sp->xleft = count - actual;
280 sp->xhead = sp->xbuff + actual;
281 sp->led_state = 0x60;
282 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
284 else {
285 sp->xleft = count;
286 sp->xhead = sp->xbuff;
287 sp->status2 = count;
288 if (sp->duplex == 0)
289 sp_start_tx_timer(sp);
295 * Called by the TTY driver when there's room for more data. If we have
296 * more packets to send, we send them here.
298 static void sixpack_write_wakeup(struct tty_struct *tty)
300 int actual;
301 struct sixpack *sp = (struct sixpack *) tty->disc_data;
303 /* First make sure we're connected. */
304 if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start) {
305 return;
307 if (sp->xleft <= 0) {
308 /* Now serial buffer is almost free & we can start
309 * transmission of another packet */
310 sp->tx_packets++;
311 tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
312 sp_unlock(sp);
313 sp->tx_enable = 0;
314 mark_bh(NET_BH);
315 return;
318 if (sp->tx_enable == 1) {
319 actual = tty->driver.write(tty, 0, sp->xhead, sp->xleft);
320 sp->xleft -= actual;
321 sp->xhead += actual;
325 /* ----------------------------------------------------------------------- */
327 /* Encapsulate an IP datagram and kick it into a TTY queue. */
329 static int
330 sp_xmit(struct sk_buff *skb, struct net_device *dev)
332 struct sixpack *sp = (struct sixpack*)(dev->priv);
334 if (!dev->start)
336 printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
337 return 1;
340 if (dev->tbusy)
341 return 1;
343 /* We were not busy, so we are now... :-) */
344 if (skb != NULL) {
345 sp_lock(sp);
346 sp->tx_bytes+=skb->len; /*---2.1.x---*/
347 sp_encaps(sp, skb->data, skb->len);
348 dev_kfree_skb(skb);
350 return 0;
352 /* #endif */
355 /* perform the persistence/slottime algorithm for CSMA access. If the persistence
356 check was successful, write the data to the serial driver. Note that in case
357 of DAMA operation, the data is not sent here. */
359 static
360 void sp_xmit_on_air(unsigned long channel)
362 struct sixpack *sp = (struct sixpack *) channel;
363 int actual;
364 static unsigned char random;
366 random = random * 17 + 41;
368 if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistance)) {
369 sp->led_state = 0x70;
370 sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
371 sp->tx_enable = 1;
372 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
373 sp->xleft -= actual;
374 sp->xhead += actual;
375 sp->led_state = 0x60;
376 sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
377 sp->status2 = 0;
378 } else
379 sp_start_tx_timer(sp);
380 } /* sp_xmit */
382 /* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
384 /* Return the frame type ID */
385 static int sp_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
386 void *daddr, void *saddr, unsigned len)
388 #ifdef CONFIG_INET
389 if (type != htons(ETH_P_AX25))
390 return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
391 #endif
392 return 0;
396 static int sp_rebuild_header(struct sk_buff *skb)
398 #ifdef CONFIG_INET
399 return ax25_rebuild_header(skb);
400 #else
401 return 0;
402 #endif
405 /* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
407 /* Open the low-level part of the 6pack channel. */
408 static int
409 sp_open(struct net_device *dev)
411 struct sixpack *sp = (struct sixpack*)(dev->priv);
412 unsigned long len;
414 if (sp->tty == NULL)
415 return -ENODEV;
418 * Allocate the 6pack frame buffers:
420 * rbuff Receive buffer.
421 * xbuff Transmit buffer.
422 * cbuff Temporary compression buffer.
425 /* !!! length of the buffers. MTU is IP MTU, not PACLEN!
428 len = dev->mtu * 2;
430 sp->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
431 if (sp->rbuff == NULL)
432 return -ENOMEM;
434 sp->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
435 if (sp->xbuff == NULL)
437 kfree(sp->rbuff);
438 return -ENOMEM;
441 sp->mtu = AX25_MTU + 73;
442 sp->buffsize = len;
443 sp->rcount = 0;
444 sp->rx_count = 0;
445 sp->rx_count_cooked = 0;
446 sp->xleft = 0;
448 sp->flags &= (1 << SIXPF_INUSE); /* Clear ESCAPE & ERROR flags */
450 sp->duplex = 0;
451 sp->tx_delay = SIXP_TXDELAY;
452 sp->persistance = SIXP_PERSIST;
453 sp->slottime = SIXP_SLOTTIME;
454 sp->led_state = 0x60;
455 sp->status = 1;
456 sp->status1 = 1;
457 sp->status2 = 0;
458 sp->tnc_ok = 0;
459 sp->tx_enable = 0;
461 dev->tbusy = 0;
462 dev->start = 1;
464 init_timer(&sp->tx_t);
465 init_timer(&sp->resync_t);
466 return 0;
470 /* Close the low-level part of the 6pack channel. */
471 static int
472 sp_close(struct net_device *dev)
474 struct sixpack *sp = (struct sixpack*)(dev->priv);
476 if (sp->tty == NULL) {
477 return -EBUSY;
479 sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
480 dev->tbusy = 1;
481 dev->start = 0;
483 return 0;
486 static int
487 sixpack_receive_room(struct tty_struct *tty)
489 return 65536; /* We can handle an infinite amount of data. :-) */
492 /* !!! receive state machine */
495 * Handle the 'receiver data ready' interrupt.
496 * This function is called by the 'tty_io' module in the kernel when
497 * a block of 6pack data has been received, which can now be decapsulated
498 * and sent on to some IP layer for further processing.
500 static void
501 sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
503 unsigned char buf[512];
504 unsigned long flags;
505 int count1;
507 struct sixpack *sp = (struct sixpack *) tty->disc_data;
509 if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start || !count)
510 return;
512 save_flags(flags);
513 cli();
514 memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
515 restore_flags(flags);
517 /* Read the characters out of the buffer */
519 count1 = count;
520 while(count)
522 count--;
523 if (fp && *fp++)
525 if (!test_and_set_bit(SIXPF_ERROR, &sp->flags)) {
526 sp->rx_errors++;
528 continue;
531 sixpack_decode(sp, buf, count1);
535 * Open the high-level part of the 6pack channel.
536 * This function is called by the TTY module when the
537 * 6pack line discipline is called for. Because we are
538 * sure the tty line exists, we only have to link it to
539 * a free 6pcack channel...
541 static int
542 sixpack_open(struct tty_struct *tty)
544 struct sixpack *sp = (struct sixpack *) tty->disc_data;
545 int err;
547 /* First make sure we're not already connected. */
549 if (sp && sp->magic == SIXPACK_MAGIC)
550 return -EEXIST;
552 /* OK. Find a free 6pack channel to use. */
553 if ((sp = sp_alloc()) == NULL)
554 return -ENFILE;
555 sp->tty = tty;
556 tty->disc_data = sp;
557 if (tty->driver.flush_buffer)
558 tty->driver.flush_buffer(tty);
560 if (tty->ldisc.flush_buffer)
561 tty->ldisc.flush_buffer(tty);
564 /* Restore default settings */
565 sp->dev->type = ARPHRD_AX25;
567 /* Perform the low-level 6pack initialization. */
568 if ((err = sp_open(sp->dev)))
569 return err;
571 MOD_INC_USE_COUNT;
573 /* Done. We have linked the TTY line to a channel. */
575 tnc_init(sp);
577 return sp->dev->base_addr;
582 * Close down a 6pack channel.
583 * This means flushing out any pending queues, and then restoring the
584 * TTY line discipline to what it was before it got hooked to 6pack
585 * (which usually is TTY again).
587 static void
588 sixpack_close(struct tty_struct *tty)
590 struct sixpack *sp = (struct sixpack *) tty->disc_data;
592 /* First make sure we're connected. */
593 if (!sp || sp->magic != SIXPACK_MAGIC)
594 return;
596 rtnl_lock();
597 if (sp->dev->flags & IFF_UP)
598 (void) dev_close(sp->dev);
600 del_timer(&(sp->tx_t));
601 del_timer(&(sp->resync_t));
603 tty->disc_data = 0;
604 sp->tty = NULL;
605 /* VSV = very important to remove timers */
607 sp_free(sp);
608 unregister_netdev(sp->dev);
609 rtnl_unlock();
610 MOD_DEC_USE_COUNT;
614 static struct net_device_stats *
615 sp_get_stats(struct net_device *dev)
617 static struct net_device_stats stats;
618 struct sixpack *sp = (struct sixpack*)(dev->priv);
620 memset(&stats, 0, sizeof(struct net_device_stats));
622 stats.rx_packets = sp->rx_packets;
623 stats.tx_packets = sp->tx_packets;
624 stats.rx_bytes = sp->rx_bytes;
625 stats.tx_bytes = sp->tx_bytes;
626 stats.rx_dropped = sp->rx_dropped;
627 stats.tx_dropped = sp->tx_dropped;
628 stats.tx_errors = sp->tx_errors;
629 stats.rx_errors = sp->rx_errors;
630 stats.rx_over_errors = sp->rx_over_errors;
631 return (&stats);
636 sp_set_mac_address(struct net_device *dev, void *addr)
638 int err;
640 err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
641 if (err) {
642 return err;
645 copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN); /* addr is an AX.25 shifted ASCII mac address */
647 return 0;
650 static int
651 sp_set_dev_mac_address(struct net_device *dev, void *addr)
653 struct sockaddr *sa=addr;
654 memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
655 return 0;
659 /* Perform I/O control on an active 6pack channel. */
660 static int
661 sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
663 struct sixpack *sp = (struct sixpack *) tty->disc_data;
664 int err;
665 unsigned int tmp;
667 /* First make sure we're connected. */
668 if (!sp || sp->magic != SIXPACK_MAGIC) {
669 return -EINVAL;
672 switch(cmd) {
673 case SIOCGIFNAME:
674 err = verify_area(VERIFY_WRITE, arg, strlen(sp->dev->name) + 1);
675 if (err) {
676 return err;
678 copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1);
679 return 0;
681 case SIOCGIFENCAP:
682 err = verify_area(VERIFY_WRITE, arg, sizeof(int));
683 if (err) {
684 return err;
686 put_user(0, (int *)arg);
687 return 0;
689 case SIOCSIFENCAP:
690 err = verify_area(VERIFY_READ, arg, sizeof(int));
691 if (err) {
692 return err;
694 get_user(tmp,(int *)arg);
696 sp->mode = tmp;
697 sp->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
698 sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
699 sp->dev->type = ARPHRD_AX25;
701 return 0;
703 case SIOCSIFHWADDR:
704 return sp_set_mac_address(sp->dev, arg);
706 /* Allow stty to read, but not set, the serial port */
707 case TCGETS:
708 case TCGETA:
709 return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
711 default:
712 return -ENOIOCTLCMD;
716 static int sp_open_dev(struct net_device *dev)
718 struct sixpack *sp = (struct sixpack*)(dev->priv);
719 if(sp->tty==NULL)
720 return -ENODEV;
721 return 0;
724 /* Initialize 6pack control device -- register 6pack line discipline */
726 #ifdef MODULE
727 static int sixpack_init_ctrl_dev(void)
728 #else /* !MODULE */
729 int __init sixpack_init_ctrl_dev(struct net_device *dummy)
730 #endif /* !MODULE */
732 int status;
734 if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
736 printk(KERN_INFO "6pack: %s (dynamic channels, max=%d)\n",
737 SIXPACK_VERSION, sixpack_maxdev);
739 sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
740 if (sixpack_ctrls == NULL)
742 printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array! Uaargh! (-> No 6pack available)\n");
743 return -ENOMEM;
746 /* Clear the pointer array, we allocate devices when we need them */
747 memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
750 /* Fill in our line protocol discipline, and register it */
751 memset(&sp_ldisc, 0, sizeof(sp_ldisc));
752 sp_ldisc.magic = TTY_LDISC_MAGIC;
753 sp_ldisc.name = "6pack";
754 sp_ldisc.flags = 0;
755 sp_ldisc.open = sixpack_open;
756 sp_ldisc.close = sixpack_close;
757 sp_ldisc.read = NULL;
758 sp_ldisc.write = NULL;
759 sp_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
760 unsigned int, unsigned long)) sixpack_ioctl;
761 sp_ldisc.poll = NULL;
762 sp_ldisc.receive_buf = sixpack_receive_buf;
763 sp_ldisc.receive_room = sixpack_receive_room;
764 sp_ldisc.write_wakeup = sixpack_write_wakeup;
765 if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
766 printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
769 #ifdef MODULE
770 return status;
771 #else
772 /* Return "not found", so that dev_init() will unlink
773 * the placeholder device entry for us.
775 return ENODEV;
776 #endif
779 /* Initialize the 6pack driver. Called by DDI. */
781 sixpack_init(struct net_device *dev)
783 struct sixpack *sp = (struct sixpack*)(dev->priv);
785 static char ax25_bcast[AX25_ADDR_LEN] =
786 {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
787 static char ax25_test[AX25_ADDR_LEN] =
788 {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
790 if (sp == NULL) /* Allocation failed ?? */
791 return -ENODEV;
793 /* Set up the "6pack Control Block". (And clear statistics) */
795 memset(sp, 0, sizeof (struct sixpack));
796 sp->magic = SIXPACK_MAGIC;
797 sp->dev = dev;
799 /* Finish setting up the DEVICE info. */
800 dev->mtu = SIXP_MTU;
801 dev->hard_start_xmit = sp_xmit;
802 dev->open = sp_open_dev;
803 dev->stop = sp_close;
804 dev->hard_header = sp_header;
805 dev->get_stats = sp_get_stats;
806 dev->set_mac_address = sp_set_dev_mac_address;
807 dev->hard_header_len = AX25_MAX_HEADER_LEN;
808 dev->addr_len = AX25_ADDR_LEN;
809 dev->type = ARPHRD_AX25;
810 dev->tx_queue_len = 10;
811 dev->rebuild_header = sp_rebuild_header;
813 memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); /* Only activated in AX.25 mode */
814 memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); /* "" "" "" "" */
816 dev_init_buffers(dev);
818 /* New-style flags. */
819 dev->flags = 0;
821 return 0;
824 #ifdef MODULE
827 init_module(void)
829 return sixpack_init_ctrl_dev();
832 void
833 cleanup_module(void)
835 int i;
837 if (sixpack_ctrls != NULL)
839 for (i = 0; i < sixpack_maxdev; i++)
841 if (sixpack_ctrls[i])
844 * VSV = if dev->start==0, then device
845 * unregistered while close proc.
847 if (sixpack_ctrls[i]->dev.start)
848 unregister_netdev(&(sixpack_ctrls[i]->dev));
850 kfree(sixpack_ctrls[i]);
851 sixpack_ctrls[i] = NULL;
854 kfree(sixpack_ctrls);
855 sixpack_ctrls = NULL;
857 if ((i = tty_register_ldisc(N_6PACK, NULL)))
859 printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
862 #endif /* MODULE */
864 /* ----> 6pack timer interrupt handler and friends. <---- */
865 static void
866 sp_start_tx_timer(struct sixpack *sp)
868 int when = sp->slottime;
870 del_timer(&(sp->tx_t));
871 sp->tx_t.data = (unsigned long) sp;
872 sp->tx_t.function = sp_xmit_on_air;
873 sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
874 add_timer(&(sp->tx_t));
878 /* encode an AX.25 packet into 6pack */
880 int encode_sixpack(byte *tx_buf, byte *tx_buf_raw, int length, byte tx_delay)
882 int count = 0;
883 byte checksum = 0, buf[400];
884 int raw_count = 0;
886 tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
887 tx_buf_raw[raw_count++] = SIXP_SEOF;
889 buf[0] = tx_delay;
890 for(count = 1; count < length; count++)
891 buf[count] = tx_buf[count];
893 for(count = 0; count < length; count++)
894 checksum += buf[count];
895 buf[length] = (byte)0xff - checksum;
897 for(count = 0; count <= length; count++) {
898 if((count % 3) == 0) {
899 tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
900 tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
902 else if((count % 3) == 1) {
903 tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
904 tx_buf_raw[raw_count] =
905 ((buf[count] >> 2) & 0x3c);
906 } else {
907 tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
908 tx_buf_raw[raw_count++] =
909 (buf[count] >> 2);
910 } /* else */
911 } /* for */
912 if ((length % 3) != 2)
913 raw_count++;
914 tx_buf_raw[raw_count++] = SIXP_SEOF;
915 return(raw_count);
919 /* decode a 6pack packet */
921 void
922 sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
924 byte inbyte;
925 int count1;
927 for (count1 = 0; count1 < count; count1++) {
928 inbyte = pre_rbuff[count1];
929 if (inbyte == SIXP_FOUND_TNC) {
930 printk(KERN_INFO "6pack: TNC found.\n");
931 sp->tnc_ok = 1;
932 del_timer(&(sp->resync_t));
934 if((inbyte & SIXP_PRIO_CMD_MASK) != 0)
935 decode_prio_command(inbyte, sp);
936 else if((inbyte & SIXP_STD_CMD_MASK) != 0)
937 decode_std_command(inbyte, sp);
938 else {
939 if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
940 decode_data(inbyte, sp);
941 } /* else */
942 } /* for */
945 static int
946 tnc_init(struct sixpack *sp)
948 static byte inbyte;
950 inbyte = 0xe8;
951 sp->tty->driver.write(sp->tty, 0, &inbyte, 1);
953 del_timer(&(sp->resync_t));
954 sp->resync_t.data = (unsigned long) sp;
955 sp->resync_t.function = resync_tnc;
956 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
957 add_timer(&(sp->resync_t));
959 return 0;
963 /* identify and execute a 6pack priority command byte */
965 void decode_prio_command(byte cmd, struct sixpack *sp)
967 byte channel;
968 int actual;
970 channel = cmd & SIXP_CHN_MASK;
971 if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
973 /* RX and DCD flags can only be set in the same prio command,
974 if the DCD flag has been set without the RX flag in the previous
975 prio command. If DCD has not been set before, something in the
976 transmission has gone wrong. In this case, RX and DCD are
977 cleared in order to prevent the decode_data routine from
978 reading further data that might be corrupt. */
980 if (((sp->status & SIXP_DCD_MASK) == 0) &&
981 ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
982 if (sp->status != 1)
983 printk(KERN_DEBUG "6pack: protocol violation\n");
984 else
985 sp->status = 0;
986 cmd &= !SIXP_RX_DCD_MASK;
988 sp->status = cmd & SIXP_PRIO_DATA_MASK;
989 } /* if */
990 else { /* output watchdog char if idle */
991 if ((sp->status2 != 0) && (sp->duplex == 1)) {
992 sp->led_state = 0x70;
993 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
994 sp->tx_enable = 1;
995 actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
996 sp->xleft -= actual;
997 sp->xhead += actual;
998 sp->led_state = 0x60;
999 sp->status2 = 0;
1001 } /* if */
1002 } /* else */
1004 /* needed to trigger the TNC watchdog */
1005 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1007 /* if the state byte has been received, the TNC is present,
1008 so the resync timer can be reset. */
1010 if (sp->tnc_ok == 1) {
1011 del_timer(&(sp->resync_t));
1012 sp->resync_t.data = (unsigned long) sp;
1013 sp->resync_t.function = resync_tnc;
1014 sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
1015 add_timer(&(sp->resync_t));
1018 sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
1021 /* try to resync the TNC. Called by the resync timer defined in
1022 decode_prio_command */
1024 static void
1025 resync_tnc(unsigned long channel)
1027 static char resync_cmd = 0xe8;
1028 struct sixpack *sp = (struct sixpack *) channel;
1030 printk(KERN_INFO "6pack: resyncing TNC\n");
1032 /* clear any data that might have been received */
1034 sp->rx_count = 0;
1035 sp->rx_count_cooked = 0;
1037 /* reset state machine */
1039 sp->status = 1;
1040 sp->status1 = 1;
1041 sp->status2 = 0;
1042 sp->tnc_ok = 0;
1044 /* resync the TNC */
1046 sp->led_state = 0x60;
1047 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1048 sp->tty->driver.write(sp->tty, 0, &resync_cmd, 1);
1051 /* Start resync timer again -- the TNC might be still absent */
1053 del_timer(&(sp->resync_t));
1054 sp->resync_t.data = (unsigned long) sp;
1055 sp->resync_t.function = resync_tnc;
1056 sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
1057 add_timer(&(sp->resync_t));
1062 /* identify and execute a standard 6pack command byte */
1064 void decode_std_command(byte cmd, struct sixpack *sp)
1066 byte checksum = 0, rest = 0, channel;
1067 short i;
1069 channel = cmd & SIXP_CHN_MASK;
1070 switch(cmd & SIXP_CMD_MASK) { /* normal command */
1071 case SIXP_SEOF:
1072 if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
1073 if ((sp->status & SIXP_RX_DCD_MASK) ==
1074 SIXP_RX_DCD_MASK) {
1075 sp->led_state = 0x68;
1076 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1077 } /* if */
1078 } else {
1079 sp->led_state = 0x60;
1080 /* fill trailing bytes with zeroes */
1081 sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
1082 rest = sp->rx_count;
1083 if (rest != 0)
1084 for(i=rest; i<=3; i++)
1085 decode_data(0, sp);
1086 if (rest == 2)
1087 sp->rx_count_cooked -= 2;
1088 else if (rest == 3)
1089 sp->rx_count_cooked -= 1;
1090 for (i=0; i<sp->rx_count_cooked; i++)
1091 checksum+=sp->cooked_buf[i];
1092 if (checksum != SIXP_CHKSUM) {
1093 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
1094 } else {
1095 sp->rcount = sp->rx_count_cooked-2;
1096 sp_bump(sp, 0);
1097 } /* else */
1098 sp->rx_count_cooked = 0;
1099 } /* else */
1100 break;
1101 case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
1102 break;
1103 case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
1104 break;
1105 case SIXP_RX_BUF_OVL:
1106 printk(KERN_DEBUG "6pack: RX buffer overflow\n");
1107 } /* switch */
1108 } /* function */
1110 /* decode 4 sixpack-encoded bytes into 3 data bytes */
1112 void decode_data(byte inbyte, struct sixpack *sp)
1115 unsigned char *buf;
1117 if (sp->rx_count != 3)
1118 sp->raw_buf[sp->rx_count++] = inbyte;
1119 else {
1120 buf = sp->raw_buf;
1121 sp->cooked_buf[sp->rx_count_cooked++] =
1122 buf[0] | ((buf[1] << 2) & 0xc0);
1123 sp->cooked_buf[sp->rx_count_cooked++] =
1124 (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
1125 sp->cooked_buf[sp->rx_count_cooked++] =
1126 (buf[2] & 0x03) | (inbyte << 2);
1127 sp->rx_count = 0;