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 /* 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. */
167 sp_bump(struct sixpack
*sp
, char cmd
)
173 count
= sp
->rcount
+1;
177 skb
= dev_alloc_skb(count
);
180 printk(KERN_DEBUG
"%s: memory squeeze, dropping packet.\n", sp
->dev
->name
);
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
);
197 /* ----------------------------------------------------------------------- */
199 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
201 sp_encaps(struct sixpack
*sp
, unsigned char *icp
, int len
)
206 if (len
> sp
->mtu
) /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
209 printk(KERN_DEBUG
"%s: truncating oversized transmit packet!\n", sp
->dev
->name
);
211 netif_start_queue(sp
->dev
);
219 printk(KERN_DEBUG
"%s: invalid KISS command -- dropped\n", sp
->dev
->name
);
220 netif_start_queue(sp
->dev
);
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
);
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
);
239 count
= encode_sixpack(p
, (unsigned char *) sp
->xbuff
, len
, sp
->tx_delay
);
240 sp
->tty
->flags
|= (1 << TTY_DO_WRITE_WAKEUP
);
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;
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);
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);
268 sp
->xhead
= sp
->xbuff
;
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
)
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
)) {
290 if (sp
->xleft
<= 0) {
291 /* Now serial buffer is almost free & we can start
292 * transmission of another packet */
294 tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
296 netif_wake_queue(sp
->dev
);
300 if (sp
->tx_enable
== 1) {
301 actual
= tty
->driver
.write(tty
, 0, sp
->xhead
, sp
->xleft
);
307 /* ----------------------------------------------------------------------- */
309 /* Encapsulate an IP datagram and kick it into a TTY queue. */
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... :-) */
318 netif_stop_queue(dev
);
319 sp
->tx_bytes
+=skb
->len
; /*---2.1.x---*/
320 sp_encaps(sp
, skb
->data
, skb
->len
);
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. */
333 void sp_xmit_on_air(unsigned long channel
)
335 struct sixpack
*sp
= (struct sixpack
*) channel
;
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);
345 actual
= sp
->tty
->driver
.write(sp
->tty
, 0, sp
->xbuff
, sp
->status2
);
348 sp
->led_state
= 0x60;
349 sp
->tty
->driver
.write(sp
->tty
, 0, &(sp
->led_state
),1);
352 sp_start_tx_timer(sp
);
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
)
362 if (type
!= htons(ETH_P_AX25
))
363 return ax25_encapsulate(skb
, dev
, type
, daddr
, saddr
, len
);
369 static int sp_rebuild_header(struct sk_buff
*skb
)
372 return ax25_rebuild_header(skb
);
378 /* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
380 /* Open the low-level part of the 6pack channel. */
382 sp_open(struct net_device
*dev
)
384 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
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!
403 sp
->rbuff
= (unsigned char *) kmalloc(len
+ 4, GFP_KERNEL
);
404 if (sp
->rbuff
== NULL
)
407 sp
->xbuff
= (unsigned char *) kmalloc(len
+ 4, GFP_KERNEL
);
408 if (sp
->xbuff
== NULL
)
414 sp
->mtu
= AX25_MTU
+ 73;
418 sp
->rx_count_cooked
= 0;
421 sp
->flags
&= (1 << SIXPF_INUSE
); /* Clear ESCAPE & ERROR flags */
424 sp
->tx_delay
= SIXP_TXDELAY
;
425 sp
->persistance
= SIXP_PERSIST
;
426 sp
->slottime
= SIXP_SLOTTIME
;
427 sp
->led_state
= 0x60;
434 netif_start_queue(dev
);
436 init_timer(&sp
->tx_t
);
437 init_timer(&sp
->resync_t
);
442 /* Close the low-level part of the 6pack channel. */
444 sp_close(struct net_device
*dev
)
446 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
448 if (sp
->tty
== NULL
) {
451 sp
->tty
->flags
&= ~(1 << TTY_DO_WRITE_WAKEUP
);
453 netif_stop_queue(dev
);
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.
472 sixpack_receive_buf(struct tty_struct
*tty
, const unsigned char *cp
, char *fp
, int count
)
474 unsigned char buf
[512];
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
)
485 memcpy(buf
, cp
, count
<sizeof(buf
)? count
:sizeof(buf
));
486 restore_flags(flags
);
488 /* Read the characters out of the buffer */
496 if (!test_and_set_bit(SIXPF_ERROR
, &sp
->flags
)) {
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...
513 sixpack_open(struct tty_struct
*tty
)
515 struct sixpack
*sp
= (struct sixpack
*) tty
->disc_data
;
518 /* First make sure we're not already connected. */
520 if (sp
&& sp
->magic
== SIXPACK_MAGIC
)
523 /* OK. Find a free 6pack channel to use. */
524 if ((sp
= sp_alloc()) == NULL
)
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
)))
544 /* Done. We have linked the TTY line to a channel. */
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).
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
)
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
));
576 /* VSV = very important to remove timers */
579 unregister_netdev(sp
->dev
);
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
;
607 sp_set_mac_address(struct net_device
*dev
, void *addr
)
611 err
= verify_area(VERIFY_READ
, addr
, AX25_ADDR_LEN
);
616 copy_from_user(dev
->dev_addr
, addr
, AX25_ADDR_LEN
); /* addr is an AX.25 shifted ASCII mac address */
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
);
630 /* Perform I/O control on an active 6pack channel. */
632 sixpack_ioctl(struct tty_struct
*tty
, void *file
, int cmd
, void *arg
)
634 struct sixpack
*sp
= (struct sixpack
*) tty
->disc_data
;
638 /* First make sure we're connected. */
639 if (!sp
|| sp
->magic
!= SIXPACK_MAGIC
) {
645 err
= verify_area(VERIFY_WRITE
, arg
, strlen(sp
->dev
->name
) + 1);
649 copy_to_user(arg
, sp
->dev
->name
, strlen(sp
->dev
->name
) + 1);
653 err
= verify_area(VERIFY_WRITE
, arg
, sizeof(int));
657 put_user(0, (int *)arg
);
661 err
= verify_area(VERIFY_READ
, arg
, sizeof(int));
665 get_user(tmp
,(int *)arg
);
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
;
675 return sp_set_mac_address(sp
->dev
, arg
);
677 /* Allow stty to read, but not set, the serial port */
680 return n_tty_ioctl(tty
, (struct file
*) file
, cmd
, (unsigned long) arg
);
687 static int sp_open_dev(struct net_device
*dev
)
689 struct sixpack
*sp
= (struct sixpack
*)(dev
->priv
);
695 /* Initialize 6pack control device -- register 6pack line discipline */
697 static int __init
sixpack_init_ctrl_dev(void)
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");
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";
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
);
739 static void __exit
sixpack_cleanup_driver(void)
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 ?? */
784 /* Set up the "6pack Control Block". (And clear statistics) */
786 memset(sp
, 0, sizeof (struct sixpack
));
787 sp
->magic
= SIXPACK_MAGIC
;
790 /* Finish setting up the DEVICE info. */
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. */
819 /* ----> 6pack timer interrupt handler and friends. <---- */
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
)
838 byte checksum
= 0, buf
[400];
841 tx_buf_raw
[raw_count
++] = SIXP_PRIO_CMD_MASK
| SIXP_TX_MASK
;
842 tx_buf_raw
[raw_count
++] = SIXP_SEOF
;
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);
862 tx_buf_raw
[raw_count
++] |= (buf
[count
] & 0x03);
863 tx_buf_raw
[raw_count
++] =
867 if ((length
% 3) != 2)
869 tx_buf_raw
[raw_count
++] = SIXP_SEOF
;
874 /* decode a 6pack packet */
877 sixpack_decode(struct sixpack
*sp
, unsigned char pre_rbuff
[], int count
)
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");
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
);
894 if ((sp
->status
& SIXP_RX_DCD_MASK
) == SIXP_RX_DCD_MASK
)
895 decode_data(inbyte
, sp
);
901 tnc_init(struct sixpack
*sp
)
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
));
918 /* identify and execute a 6pack priority command byte */
920 void decode_prio_command(byte cmd
, struct sixpack
*sp
)
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
)) {
938 printk(KERN_DEBUG
"6pack: protocol violation\n");
941 cmd
&= !SIXP_RX_DCD_MASK
;
943 sp
->status
= cmd
& SIXP_PRIO_DATA_MASK
;
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);
950 actual
= sp
->tty
->driver
.write(sp
->tty
, 0, sp
->xbuff
, sp
->status2
);
953 sp
->led_state
= 0x60;
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 */
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 */
990 sp
->rx_count_cooked
= 0;
992 /* reset state machine */
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
;
1024 channel
= cmd
& SIXP_CHN_MASK
;
1025 switch(cmd
& SIXP_CMD_MASK
) { /* normal command */
1027 if ((sp
->rx_count
== 0) && (sp
->rx_count_cooked
== 0)) {
1028 if ((sp
->status
& SIXP_RX_DCD_MASK
) ==
1030 sp
->led_state
= 0x68;
1031 sp
->tty
->driver
.write(sp
->tty
, 0, &(sp
->led_state
), 1);
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
;
1039 for(i
=rest
; i
<=3; i
++)
1042 sp
->rx_count_cooked
-= 2;
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
);
1050 sp
->rcount
= sp
->rx_count_cooked
-2;
1053 sp
->rx_count_cooked
= 0;
1056 case SIXP_TX_URUN
: printk(KERN_DEBUG
"6pack: TX underrun\n");
1058 case SIXP_RX_ORUN
: printk(KERN_DEBUG
"6pack: RX overrun\n");
1060 case SIXP_RX_BUF_OVL
:
1061 printk(KERN_DEBUG
"6pack: RX buffer overflow\n");
1065 /* decode 4 sixpack-encoded bytes into 3 data bytes */
1067 void decode_data(byte inbyte
, struct sixpack
*sp
)
1072 if (sp
->rx_count
!= 3)
1073 sp
->raw_buf
[sp
->rx_count
++] = inbyte
;
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);
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
);