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>
25 #include <linux/interrupt.h>
27 #include <linux/tty.h>
28 #include <linux/errno.h>
29 #include <linux/netdevice.h>
30 #include <linux/timer.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>
39 #include <linux/tcp.h>
41 #include <sys/types.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 */
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
*
79 sixpack_ctrl_t
*spp
= NULL
;
82 if (sixpack_ctrls
== NULL
) return NULL
; /* Master array missing ! */
84 for (i
= 0; i
< sixpack_maxdev
; i
++)
86 spp
= sixpack_ctrls
[i
];
91 if (!test_and_set_bit(SIXPF_INUSE
, &spp
->ctrl
.flags
))
95 /* Too many devices... */
96 if (i
>= sixpack_maxdev
)
99 /* If no channels are available, allocate one */
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
;
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
));
132 clear_bit(SIXPF_INUSE
,&(spp
->ctrl
.flags
));
133 printk(KERN_WARNING
"sp_alloc() - register_netdev() failure.\n");
141 /* Free a 6pack channel. */
143 sp_free(struct sixpack
*sp
)
145 /* Free all 6pack frame buffers. */
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. */
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. */
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. */
185 sp_bump(struct sixpack
*sp
, char cmd
)
191 count
= sp
->rcount
+1;
195 skb
= dev_alloc_skb(count
);
198 printk(KERN_DEBUG
"%s: memory squeeze, dropping packet.\n", sp
->dev
->name
);
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
);
215 /* ----------------------------------------------------------------------- */
217 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
219 sp_encaps(struct sixpack
*sp
, unsigned char *icp
, int len
)
224 if (len
> sp
->mtu
) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
227 printk(KERN_DEBUG
"%s: truncating oversized transmit packet!\n", sp
->dev
->name
);
237 printk(KERN_DEBUG
"%s: invalid KISS command -- dropped\n", sp
->dev
->name
);
242 if ((p
[0] != 0) && (len
> 2))
244 printk(KERN_DEBUG
"%s: KISS control packet too long -- dropped\n", sp
->dev
->name
);
249 if ((p
[0] == 0) && (len
< 15))
251 printk(KERN_DEBUG
"%s: bad AX.25 packet to transmit -- dropped\n", sp
->dev
->name
);
257 count
= encode_sixpack(p
, (unsigned char *) sp
->xbuff
, len
, sp
->tx_delay
);
258 sp
->tty
->flags
|= (1 << TTY_DO_WRITE_WAKEUP
);
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;
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);
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);
286 sp
->xhead
= sp
->xbuff
;
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
)
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
) {
307 if (sp
->xleft
<= 0) {
308 /* Now serial buffer is almost free & we can start
309 * transmission of another packet */
311 tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
318 if (sp
->tx_enable
== 1) {
319 actual
= tty
->driver
.write(tty
, 0, sp
->xhead
, sp
->xleft
);
325 /* ----------------------------------------------------------------------- */
327 /* Encapsulate an IP datagram and kick it into a TTY queue. */
330 sp_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
332 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
336 printk(KERN_WARNING
"%s: xmit call when iface is down\n", dev
->name
);
343 /* We were not busy, so we are now... :-) */
346 sp
->tx_bytes
+=skb
->len
; /*---2.1.x---*/
347 sp_encaps(sp
, skb
->data
, skb
->len
);
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. */
360 void sp_xmit_on_air(unsigned long channel
)
362 struct sixpack
*sp
= (struct sixpack
*) channel
;
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);
372 actual
= sp
->tty
->driver
.write(sp
->tty
, 0, sp
->xbuff
, sp
->status2
);
375 sp
->led_state
= 0x60;
376 sp
->tty
->driver
.write(sp
->tty
, 0, &(sp
->led_state
),1);
379 sp_start_tx_timer(sp
);
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
)
389 if (type
!= htons(ETH_P_AX25
))
390 return ax25_encapsulate(skb
, dev
, type
, daddr
, saddr
, len
);
396 static int sp_rebuild_header(struct sk_buff
*skb
)
399 return ax25_rebuild_header(skb
);
405 /* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
407 /* Open the low-level part of the 6pack channel. */
409 sp_open(struct net_device
*dev
)
411 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
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!
430 sp
->rbuff
= (unsigned char *) kmalloc(len
+ 4, GFP_KERNEL
);
431 if (sp
->rbuff
== NULL
)
434 sp
->xbuff
= (unsigned char *) kmalloc(len
+ 4, GFP_KERNEL
);
435 if (sp
->xbuff
== NULL
)
441 sp
->mtu
= AX25_MTU
+ 73;
445 sp
->rx_count_cooked
= 0;
448 sp
->flags
&= (1 << SIXPF_INUSE
); /* Clear ESCAPE & ERROR flags */
451 sp
->tx_delay
= SIXP_TXDELAY
;
452 sp
->persistance
= SIXP_PERSIST
;
453 sp
->slottime
= SIXP_SLOTTIME
;
454 sp
->led_state
= 0x60;
464 init_timer(&sp
->tx_t
);
465 init_timer(&sp
->resync_t
);
470 /* Close the low-level part of the 6pack channel. */
472 sp_close(struct net_device
*dev
)
474 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
476 if (sp
->tty
== NULL
) {
479 sp
->tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
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.
501 sixpack_receive_buf(struct tty_struct
*tty
, const unsigned char *cp
, char *fp
, int count
)
503 unsigned char buf
[512];
507 struct sixpack
*sp
= (struct sixpack
*) tty
->disc_data
;
509 if (!sp
|| sp
->magic
!= SIXPACK_MAGIC
|| !sp
->dev
->start
|| !count
)
514 memcpy(buf
, cp
, count
<sizeof(buf
)? count
:sizeof(buf
));
515 restore_flags(flags
);
517 /* Read the characters out of the buffer */
525 if (!test_and_set_bit(SIXPF_ERROR
, &sp
->flags
)) {
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...
542 sixpack_open(struct tty_struct
*tty
)
544 struct sixpack
*sp
= (struct sixpack
*) tty
->disc_data
;
547 /* First make sure we're not already connected. */
549 if (sp
&& sp
->magic
== SIXPACK_MAGIC
)
552 /* OK. Find a free 6pack channel to use. */
553 if ((sp
= sp_alloc()) == NULL
)
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
)))
573 /* Done. We have linked the TTY line to a channel. */
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).
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
)
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
));
605 /* VSV = very important to remove timers */
608 unregister_netdev(sp
->dev
);
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
;
636 sp_set_mac_address(struct net_device
*dev
, void *addr
)
640 err
= verify_area(VERIFY_READ
, addr
, AX25_ADDR_LEN
);
645 copy_from_user(dev
->dev_addr
, addr
, AX25_ADDR_LEN
); /* addr is an AX.25 shifted ASCII mac address */
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
);
659 /* Perform I/O control on an active 6pack channel. */
661 sixpack_ioctl(struct tty_struct
*tty
, void *file
, int cmd
, void *arg
)
663 struct sixpack
*sp
= (struct sixpack
*) tty
->disc_data
;
667 /* First make sure we're connected. */
668 if (!sp
|| sp
->magic
!= SIXPACK_MAGIC
) {
674 err
= verify_area(VERIFY_WRITE
, arg
, strlen(sp
->dev
->name
) + 1);
678 copy_to_user(arg
, sp
->dev
->name
, strlen(sp
->dev
->name
) + 1);
682 err
= verify_area(VERIFY_WRITE
, arg
, sizeof(int));
686 put_user(0, (int *)arg
);
690 err
= verify_area(VERIFY_READ
, arg
, sizeof(int));
694 get_user(tmp
,(int *)arg
);
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
;
704 return sp_set_mac_address(sp
->dev
, arg
);
706 /* Allow stty to read, but not set, the serial port */
709 return n_tty_ioctl(tty
, (struct file
*) file
, cmd
, (unsigned long) arg
);
716 static int sp_open_dev(struct net_device
*dev
)
718 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
724 /* Initialize 6pack control device -- register 6pack line discipline */
727 static int sixpack_init_ctrl_dev(void)
729 int __init
sixpack_init_ctrl_dev(struct net_device
*dummy
)
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");
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";
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
);
772 /* Return "not found", so that dev_init() will unlink
773 * the placeholder device entry for us.
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 ?? */
793 /* Set up the "6pack Control Block". (And clear statistics) */
795 memset(sp
, 0, sizeof (struct sixpack
));
796 sp
->magic
= SIXPACK_MAGIC
;
799 /* Finish setting up the DEVICE info. */
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. */
829 return sixpack_init_ctrl_dev();
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
);
864 /* ----> 6pack timer interrupt handler and friends. <---- */
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
)
883 byte checksum
= 0, buf
[400];
886 tx_buf_raw
[raw_count
++] = SIXP_PRIO_CMD_MASK
| SIXP_TX_MASK
;
887 tx_buf_raw
[raw_count
++] = SIXP_SEOF
;
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);
907 tx_buf_raw
[raw_count
++] |= (buf
[count
] & 0x03);
908 tx_buf_raw
[raw_count
++] =
912 if ((length
% 3) != 2)
914 tx_buf_raw
[raw_count
++] = SIXP_SEOF
;
919 /* decode a 6pack packet */
922 sixpack_decode(struct sixpack
*sp
, unsigned char pre_rbuff
[], int count
)
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");
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
);
939 if ((sp
->status
& SIXP_RX_DCD_MASK
) == SIXP_RX_DCD_MASK
)
940 decode_data(inbyte
, sp
);
946 tnc_init(struct sixpack
*sp
)
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
));
963 /* identify and execute a 6pack priority command byte */
965 void decode_prio_command(byte cmd
, struct sixpack
*sp
)
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
)) {
983 printk(KERN_DEBUG
"6pack: protocol violation\n");
986 cmd
&= !SIXP_RX_DCD_MASK
;
988 sp
->status
= cmd
& SIXP_PRIO_DATA_MASK
;
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);
995 actual
= sp
->tty
->driver
.write(sp
->tty
, 0, sp
->xbuff
, sp
->status2
);
998 sp
->led_state
= 0x60;
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 */
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 */
1035 sp
->rx_count_cooked
= 0;
1037 /* reset state machine */
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
;
1069 channel
= cmd
& SIXP_CHN_MASK
;
1070 switch(cmd
& SIXP_CMD_MASK
) { /* normal command */
1072 if ((sp
->rx_count
== 0) && (sp
->rx_count_cooked
== 0)) {
1073 if ((sp
->status
& SIXP_RX_DCD_MASK
) ==
1075 sp
->led_state
= 0x68;
1076 sp
->tty
->driver
.write(sp
->tty
, 0, &(sp
->led_state
), 1);
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
;
1084 for(i
=rest
; i
<=3; i
++)
1087 sp
->rx_count_cooked
-= 2;
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
);
1095 sp
->rcount
= sp
->rx_count_cooked
-2;
1098 sp
->rx_count_cooked
= 0;
1101 case SIXP_TX_URUN
: printk(KERN_DEBUG
"6pack: TX underrun\n");
1103 case SIXP_RX_ORUN
: printk(KERN_DEBUG
"6pack: RX overrun\n");
1105 case SIXP_RX_BUF_OVL
:
1106 printk(KERN_DEBUG
"6pack: RX buffer overflow\n");
1110 /* decode 4 sixpack-encoded bytes into 3 data bytes */
1112 void decode_data(byte inbyte
, struct sixpack
*sp
)
1117 if (sp
->rx_count
!= 3)
1118 sp
->raw_buf
[sp
->rx_count
++] = inbyte
;
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);