[PATCH] e1000:Fix computation of netdev stats from controller stats counters
[linux-2.6] / drivers / net / hamradio / 6pack.c
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.
5  *
6  * Authors:     Andreas Könsgen <ajk@iehk.rwth-aachen.de>
7  *              Ralf Baechle DL5RB <ralf@linux-mips.org>
8  *
9  * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
10  *
11  *              Laurence Culhane, <loz@holmes.demon.co.uk>
12  *              Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
13  */
14
15 #include <linux/config.h>
16 #include <linux/module.h>
17 #include <asm/system.h>
18 #include <asm/uaccess.h>
19 #include <linux/bitops.h>
20 #include <linux/string.h>
21 #include <linux/mm.h>
22 #include <linux/interrupt.h>
23 #include <linux/in.h>
24 #include <linux/tty.h>
25 #include <linux/errno.h>
26 #include <linux/netdevice.h>
27 #include <linux/timer.h>
28 #include <net/ax25.h>
29 #include <linux/etherdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/rtnetlink.h>
32 #include <linux/spinlock.h>
33 #include <linux/if_arp.h>
34 #include <linux/init.h>
35 #include <linux/ip.h>
36 #include <linux/tcp.h>
37 #include <asm/semaphore.h>
38 #include <asm/atomic.h>
39
40 #define SIXPACK_VERSION    "Revision: 0.3.0"
41
42 /* sixpack priority commands */
43 #define SIXP_SEOF               0x40    /* start and end of a 6pack frame */
44 #define SIXP_TX_URUN            0x48    /* transmit overrun */
45 #define SIXP_RX_ORUN            0x50    /* receive overrun */
46 #define SIXP_RX_BUF_OVL         0x58    /* receive buffer overflow */
47
48 #define SIXP_CHKSUM             0xFF    /* valid checksum of a 6pack frame */
49
50 /* masks to get certain bits out of the status bytes sent by the TNC */
51
52 #define SIXP_CMD_MASK           0xC0
53 #define SIXP_CHN_MASK           0x07
54 #define SIXP_PRIO_CMD_MASK      0x80
55 #define SIXP_STD_CMD_MASK       0x40
56 #define SIXP_PRIO_DATA_MASK     0x38
57 #define SIXP_TX_MASK            0x20
58 #define SIXP_RX_MASK            0x10
59 #define SIXP_RX_DCD_MASK        0x18
60 #define SIXP_LEDS_ON            0x78
61 #define SIXP_LEDS_OFF           0x60
62 #define SIXP_CON                0x08
63 #define SIXP_STA                0x10
64
65 #define SIXP_FOUND_TNC          0xe9
66 #define SIXP_CON_ON             0x68
67 #define SIXP_DCD_MASK           0x08
68 #define SIXP_DAMA_OFF           0
69
70 /* default level 2 parameters */
71 #define SIXP_TXDELAY                    (HZ/4)  /* in 1 s */
72 #define SIXP_PERSIST                    50      /* in 256ths */
73 #define SIXP_SLOTTIME                   (HZ/10) /* in 1 s */
74 #define SIXP_INIT_RESYNC_TIMEOUT        (3*HZ/2) /* in 1 s */
75 #define SIXP_RESYNC_TIMEOUT             5*HZ    /* in 1 s */
76
77 /* 6pack configuration. */
78 #define SIXP_NRUNIT                     31      /* MAX number of 6pack channels */
79 #define SIXP_MTU                        256     /* Default MTU */
80
81 enum sixpack_flags {
82         SIXPF_ERROR,    /* Parity, etc. error   */
83 };
84
85 struct sixpack {
86         /* Various fields. */
87         struct tty_struct       *tty;           /* ptr to TTY structure */
88         struct net_device       *dev;           /* easy for intr handling  */
89
90         /* These are pointers to the malloc()ed frame buffers. */
91         unsigned char           *rbuff;         /* receiver buffer      */
92         int                     rcount;         /* received chars counter  */
93         unsigned char           *xbuff;         /* transmitter buffer   */
94         unsigned char           *xhead;         /* next byte to XMIT */
95         int                     xleft;          /* bytes left in XMIT queue  */
96
97         unsigned char           raw_buf[4];
98         unsigned char           cooked_buf[400];
99
100         unsigned int            rx_count;
101         unsigned int            rx_count_cooked;
102
103         /* 6pack interface statistics. */
104         struct net_device_stats stats;
105
106         int                     mtu;            /* Our mtu (to spot changes!) */
107         int                     buffsize;       /* Max buffers sizes */
108
109         unsigned long           flags;          /* Flag values/ mode etc */
110         unsigned char           mode;           /* 6pack mode */
111
112         /* 6pack stuff */
113         unsigned char           tx_delay;
114         unsigned char           persistence;
115         unsigned char           slottime;
116         unsigned char           duplex;
117         unsigned char           led_state;
118         unsigned char           status;
119         unsigned char           status1;
120         unsigned char           status2;
121         unsigned char           tx_enable;
122         unsigned char           tnc_state;
123
124         struct timer_list       tx_t;
125         struct timer_list       resync_t;
126         atomic_t                refcnt;
127         struct semaphore        dead_sem;
128         spinlock_t              lock;
129 };
130
131 #define AX25_6PACK_HEADER_LEN 0
132
133 static void sp_start_tx_timer(struct sixpack *);
134 static void sixpack_decode(struct sixpack *, unsigned char[], int);
135 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
136
137 /*
138  * perform the persistence/slottime algorithm for CSMA access. If the
139  * persistence check was successful, write the data to the serial driver.
140  * Note that in case of DAMA operation, the data is not sent here.
141  */
142
143 static void sp_xmit_on_air(unsigned long channel)
144 {
145         struct sixpack *sp = (struct sixpack *) channel;
146         int actual;
147         static unsigned char random;
148
149         random = random * 17 + 41;
150
151         if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
152                 sp->led_state = 0x70;
153                 sp->tty->driver->write(sp->tty, &sp->led_state, 1);
154                 sp->tx_enable = 1;
155                 actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
156                 sp->xleft -= actual;
157                 sp->xhead += actual;
158                 sp->led_state = 0x60;
159                 sp->tty->driver->write(sp->tty, &sp->led_state, 1);
160                 sp->status2 = 0;
161         } else
162                 sp_start_tx_timer(sp);
163 }
164
165 /* ----> 6pack timer interrupt handler and friends. <---- */
166 static void sp_start_tx_timer(struct sixpack *sp)
167 {
168         int when = sp->slottime;
169
170         del_timer(&sp->tx_t);
171         sp->tx_t.data = (unsigned long) sp;
172         sp->tx_t.function = sp_xmit_on_air;
173         sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
174         add_timer(&sp->tx_t);
175 }
176
177 /* Encapsulate one AX.25 frame and stuff into a TTY queue. */
178 static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
179 {
180         unsigned char *msg, *p = icp;
181         int actual, count;
182
183         if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
184                 msg = "oversized transmit packet!";
185                 goto out_drop;
186         }
187
188         if (len > sp->mtu) {    /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
189                 msg = "oversized transmit packet!";
190                 goto out_drop;
191         }
192
193         if (p[0] > 5) {
194                 msg = "invalid KISS command";
195                 goto out_drop;
196         }
197
198         if ((p[0] != 0) && (len > 2)) {
199                 msg = "KISS control packet too long";
200                 goto out_drop;
201         }
202
203         if ((p[0] == 0) && (len < 15)) {
204                 msg = "bad AX.25 packet to transmit";
205                 goto out_drop;
206         }
207
208         count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
209         set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
210
211         switch (p[0]) {
212         case 1: sp->tx_delay = p[1];
213                 return;
214         case 2: sp->persistence = p[1];
215                 return;
216         case 3: sp->slottime = p[1];
217                 return;
218         case 4: /* ignored */
219                 return;
220         case 5: sp->duplex = p[1];
221                 return;
222         }
223
224         if (p[0] != 0)
225                 return;
226
227         /*
228          * In case of fullduplex or DAMA operation, we don't take care about the
229          * state of the DCD or of any timers, as the determination of the
230          * correct time to send is the job of the AX.25 layer. We send
231          * immediately after data has arrived.
232          */
233         if (sp->duplex == 1) {
234                 sp->led_state = 0x70;
235                 sp->tty->driver->write(sp->tty, &sp->led_state, 1);
236                 sp->tx_enable = 1;
237                 actual = sp->tty->driver->write(sp->tty, sp->xbuff, count);
238                 sp->xleft = count - actual;
239                 sp->xhead = sp->xbuff + actual;
240                 sp->led_state = 0x60;
241                 sp->tty->driver->write(sp->tty, &sp->led_state, 1);
242         } else {
243                 sp->xleft = count;
244                 sp->xhead = sp->xbuff;
245                 sp->status2 = count;
246                 if (sp->duplex == 0)
247                         sp_start_tx_timer(sp);
248         }
249
250         return;
251
252 out_drop:
253         sp->stats.tx_dropped++;
254         netif_start_queue(sp->dev);
255         if (net_ratelimit())
256                 printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
257 }
258
259 /* Encapsulate an IP datagram and kick it into a TTY queue. */
260
261 static int sp_xmit(struct sk_buff *skb, struct net_device *dev)
262 {
263         struct sixpack *sp = netdev_priv(dev);
264
265         spin_lock_bh(&sp->lock);
266         /* We were not busy, so we are now... :-) */
267         netif_stop_queue(dev);
268         sp->stats.tx_bytes += skb->len;
269         sp_encaps(sp, skb->data, skb->len);
270         spin_unlock_bh(&sp->lock);
271
272         dev_kfree_skb(skb);
273
274         return 0;
275 }
276
277 static int sp_open_dev(struct net_device *dev)
278 {
279         struct sixpack *sp = netdev_priv(dev);
280
281         if (sp->tty == NULL)
282                 return -ENODEV;
283         return 0;
284 }
285
286 /* Close the low-level part of the 6pack channel. */
287 static int sp_close(struct net_device *dev)
288 {
289         struct sixpack *sp = netdev_priv(dev);
290
291         spin_lock_bh(&sp->lock);
292         if (sp->tty) {
293                 /* TTY discipline is running. */
294                 clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
295         }
296         netif_stop_queue(dev);
297         spin_unlock_bh(&sp->lock);
298
299         return 0;
300 }
301
302 /* Return the frame type ID */
303 static int sp_header(struct sk_buff *skb, struct net_device *dev,
304         unsigned short type, void *daddr, void *saddr, unsigned len)
305 {
306 #ifdef CONFIG_INET
307         if (type != htons(ETH_P_AX25))
308                 return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
309 #endif
310         return 0;
311 }
312
313 static struct net_device_stats *sp_get_stats(struct net_device *dev)
314 {
315         struct sixpack *sp = netdev_priv(dev);
316         return &sp->stats;
317 }
318
319 static int sp_set_mac_address(struct net_device *dev, void *addr)
320 {
321         struct sockaddr_ax25 *sa = addr;
322
323         if (sa->sax25_family != AF_AX25)
324                 return -EINVAL;
325
326         if (!sa->sax25_ndigis)
327                 return -EINVAL;
328
329         spin_lock_irq(&dev->xmit_lock);
330         memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
331         spin_unlock_irq(&dev->xmit_lock);
332
333         return 0;
334 }
335
336 static int sp_rebuild_header(struct sk_buff *skb)
337 {
338 #ifdef CONFIG_INET
339         return ax25_rebuild_header(skb);
340 #else
341         return 0;
342 #endif
343 }
344
345 static void sp_setup(struct net_device *dev)
346 {
347         static char ax25_bcast[AX25_ADDR_LEN] =
348                 {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
349         static char ax25_test[AX25_ADDR_LEN] =
350                 {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
351
352         /* Finish setting up the DEVICE info. */
353         dev->mtu                = SIXP_MTU;
354         dev->hard_start_xmit    = sp_xmit;
355         dev->open               = sp_open_dev;
356         dev->destructor         = free_netdev;
357         dev->stop               = sp_close;
358         dev->hard_header        = sp_header;
359         dev->get_stats          = sp_get_stats;
360         dev->set_mac_address    = sp_set_mac_address;
361         dev->hard_header_len    = AX25_MAX_HEADER_LEN;
362         dev->addr_len           = AX25_ADDR_LEN;
363         dev->type               = ARPHRD_AX25;
364         dev->tx_queue_len       = 10;
365         dev->rebuild_header     = sp_rebuild_header;
366         dev->tx_timeout         = NULL;
367
368         /* Only activated in AX.25 mode */
369         memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
370         memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
371
372         SET_MODULE_OWNER(dev);
373
374         dev->flags              = 0;
375 }
376
377 /* Send one completely decapsulated IP datagram to the IP layer. */
378
379 /*
380  * This is the routine that sends the received data to the kernel AX.25.
381  * 'cmd' is the KISS command. For AX.25 data, it is zero.
382  */
383
384 static void sp_bump(struct sixpack *sp, char cmd)
385 {
386         struct sk_buff *skb;
387         int count;
388         unsigned char *ptr;
389
390         count = sp->rcount + 1;
391
392         sp->stats.rx_bytes += count;
393
394         if ((skb = dev_alloc_skb(count)) == NULL)
395                 goto out_mem;
396
397         ptr = skb_put(skb, count);
398         *ptr++ = cmd;   /* KISS command */
399
400         memcpy(ptr, sp->cooked_buf + 1, count);
401         skb->protocol = ax25_type_trans(skb, sp->dev);
402         netif_rx(skb);
403         sp->dev->last_rx = jiffies;
404         sp->stats.rx_packets++;
405
406         return;
407
408 out_mem:
409         sp->stats.rx_dropped++;
410 }
411
412
413 /* ----------------------------------------------------------------------- */
414
415 /*
416  * We have a potential race on dereferencing tty->disc_data, because the tty
417  * layer provides no locking at all - thus one cpu could be running
418  * sixpack_receive_buf while another calls sixpack_close, which zeroes
419  * tty->disc_data and frees the memory that sixpack_receive_buf is using.  The
420  * best way to fix this is to use a rwlock in the tty struct, but for now we
421  * use a single global rwlock for all ttys in ppp line discipline.
422  */
423 static DEFINE_RWLOCK(disc_data_lock);
424                                                                                 
425 static struct sixpack *sp_get(struct tty_struct *tty)
426 {
427         struct sixpack *sp;
428
429         read_lock(&disc_data_lock);
430         sp = tty->disc_data;
431         if (sp)
432                 atomic_inc(&sp->refcnt);
433         read_unlock(&disc_data_lock);
434
435         return sp;
436 }
437
438 static void sp_put(struct sixpack *sp)
439 {
440         if (atomic_dec_and_test(&sp->refcnt))
441                 up(&sp->dead_sem);
442 }
443
444 /*
445  * Called by the TTY driver when there's room for more data.  If we have
446  * more packets to send, we send them here.
447  */
448 static void sixpack_write_wakeup(struct tty_struct *tty)
449 {
450         struct sixpack *sp = sp_get(tty);
451         int actual;
452
453         if (!sp)
454                 return;
455         if (sp->xleft <= 0)  {
456                 /* Now serial buffer is almost free & we can start
457                  * transmission of another packet */
458                 sp->stats.tx_packets++;
459                 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
460                 sp->tx_enable = 0;
461                 netif_wake_queue(sp->dev);
462                 goto out;
463         }
464
465         if (sp->tx_enable) {
466                 actual = tty->driver->write(tty, sp->xhead, sp->xleft);
467                 sp->xleft -= actual;
468                 sp->xhead += actual;
469         }
470
471 out:
472         sp_put(sp);
473 }
474
475 /* ----------------------------------------------------------------------- */
476
477 static int sixpack_receive_room(struct tty_struct *tty)
478 {
479         return 65536;  /* We can handle an infinite amount of data. :-) */
480 }
481
482 /*
483  * Handle the 'receiver data ready' interrupt.
484  * This function is called by the 'tty_io' module in the kernel when
485  * a block of 6pack data has been received, which can now be decapsulated
486  * and sent on to some IP layer for further processing.
487  */
488 static void sixpack_receive_buf(struct tty_struct *tty,
489         const unsigned char *cp, char *fp, int count)
490 {
491         struct sixpack *sp;
492         unsigned char buf[512];
493         int count1;
494
495         if (!count)
496                 return;
497
498         sp = sp_get(tty);
499         if (!sp)
500                 return;
501
502         memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf));
503
504         /* Read the characters out of the buffer */
505
506         count1 = count;
507         while (count) {
508                 count--;
509                 if (fp && *fp++) {
510                         if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))
511                                 sp->stats.rx_errors++;
512                         continue;
513                 }
514         }
515         sixpack_decode(sp, buf, count1);
516
517         sp_put(sp);
518         if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
519             && tty->driver->unthrottle)
520                 tty->driver->unthrottle(tty);
521 }
522
523 /*
524  * Try to resync the TNC. Called by the resync timer defined in
525  * decode_prio_command
526  */
527
528 #define TNC_UNINITIALIZED       0
529 #define TNC_UNSYNC_STARTUP      1
530 #define TNC_UNSYNCED            2
531 #define TNC_IN_SYNC             3
532
533 static void __tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
534 {
535         char *msg;
536
537         switch (new_tnc_state) {
538         default:                        /* gcc oh piece-o-crap ... */
539         case TNC_UNSYNC_STARTUP:
540                 msg = "Synchronizing with TNC";
541                 break;
542         case TNC_UNSYNCED:
543                 msg = "Lost synchronization with TNC\n";
544                 break;
545         case TNC_IN_SYNC:
546                 msg = "Found TNC";
547                 break;
548         }
549
550         sp->tnc_state = new_tnc_state;
551         printk(KERN_INFO "%s: %s\n", sp->dev->name, msg);
552 }
553
554 static inline void tnc_set_sync_state(struct sixpack *sp, int new_tnc_state)
555 {
556         int old_tnc_state = sp->tnc_state;
557
558         if (old_tnc_state != new_tnc_state)
559                 __tnc_set_sync_state(sp, new_tnc_state);
560 }
561
562 static void resync_tnc(unsigned long channel)
563 {
564         struct sixpack *sp = (struct sixpack *) channel;
565         static char resync_cmd = 0xe8;
566
567         /* clear any data that might have been received */
568
569         sp->rx_count = 0;
570         sp->rx_count_cooked = 0;
571
572         /* reset state machine */
573
574         sp->status = 1;
575         sp->status1 = 1;
576         sp->status2 = 0;
577
578         /* resync the TNC */
579
580         sp->led_state = 0x60;
581         sp->tty->driver->write(sp->tty, &sp->led_state, 1);
582         sp->tty->driver->write(sp->tty, &resync_cmd, 1);
583
584
585         /* Start resync timer again -- the TNC might be still absent */
586
587         del_timer(&sp->resync_t);
588         sp->resync_t.data       = (unsigned long) sp;
589         sp->resync_t.function   = resync_tnc;
590         sp->resync_t.expires    = jiffies + SIXP_RESYNC_TIMEOUT;
591         add_timer(&sp->resync_t);
592 }
593
594 static inline int tnc_init(struct sixpack *sp)
595 {
596         unsigned char inbyte = 0xe8;
597
598         tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
599
600         sp->tty->driver->write(sp->tty, &inbyte, 1);
601
602         del_timer(&sp->resync_t);
603         sp->resync_t.data = (unsigned long) sp;
604         sp->resync_t.function = resync_tnc;
605         sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
606         add_timer(&sp->resync_t);
607
608         return 0;
609 }
610
611 /*
612  * Open the high-level part of the 6pack channel.
613  * This function is called by the TTY module when the
614  * 6pack line discipline is called for.  Because we are
615  * sure the tty line exists, we only have to link it to
616  * a free 6pcack channel...
617  */
618 static int sixpack_open(struct tty_struct *tty)
619 {
620         char *rbuff = NULL, *xbuff = NULL;
621         struct net_device *dev;
622         struct sixpack *sp;
623         unsigned long len;
624         int err = 0;
625
626         if (!capable(CAP_NET_ADMIN))
627                 return -EPERM;
628
629         dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
630         if (!dev) {
631                 err = -ENOMEM;
632                 goto out;
633         }
634
635         sp = netdev_priv(dev);
636         sp->dev = dev;
637
638         spin_lock_init(&sp->lock);
639         atomic_set(&sp->refcnt, 1);
640         init_MUTEX_LOCKED(&sp->dead_sem);
641
642         /* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
643
644         len = dev->mtu * 2;
645
646         rbuff = kmalloc(len + 4, GFP_KERNEL);
647         xbuff = kmalloc(len + 4, GFP_KERNEL);
648
649         if (rbuff == NULL || xbuff == NULL) {
650                 err = -ENOBUFS;
651                 goto out_free;
652         }
653
654         spin_lock_bh(&sp->lock);
655
656         sp->tty = tty;
657
658         sp->rbuff       = rbuff;
659         sp->xbuff       = xbuff;
660
661         sp->mtu         = AX25_MTU + 73;
662         sp->buffsize    = len;
663         sp->rcount      = 0;
664         sp->rx_count    = 0;
665         sp->rx_count_cooked = 0;
666         sp->xleft       = 0;
667
668         sp->flags       = 0;            /* Clear ESCAPE & ERROR flags */
669
670         sp->duplex      = 0;
671         sp->tx_delay    = SIXP_TXDELAY;
672         sp->persistence = SIXP_PERSIST;
673         sp->slottime    = SIXP_SLOTTIME;
674         sp->led_state   = 0x60;
675         sp->status      = 1;
676         sp->status1     = 1;
677         sp->status2     = 0;
678         sp->tx_enable   = 0;
679
680         netif_start_queue(dev);
681
682         init_timer(&sp->tx_t);
683         init_timer(&sp->resync_t);
684
685         spin_unlock_bh(&sp->lock);
686
687         /* Done.  We have linked the TTY line to a channel. */
688         tty->disc_data = sp;
689
690         /* Now we're ready to register. */
691         if (register_netdev(dev))
692                 goto out_free;
693
694         tnc_init(sp);
695
696         return 0;
697
698 out_free:
699         kfree(xbuff);
700         kfree(rbuff);
701
702         if (dev)
703                 free_netdev(dev);
704
705 out:
706         return err;
707 }
708
709
710 /*
711  * Close down a 6pack channel.
712  * This means flushing out any pending queues, and then restoring the
713  * TTY line discipline to what it was before it got hooked to 6pack
714  * (which usually is TTY again).
715  */
716 static void sixpack_close(struct tty_struct *tty)
717 {
718         struct sixpack *sp;
719
720         write_lock(&disc_data_lock);
721         sp = tty->disc_data;
722         tty->disc_data = NULL;
723         write_unlock(&disc_data_lock);
724         if (sp == 0)
725                 return;
726
727         /*
728          * We have now ensured that nobody can start using ap from now on, but
729          * we have to wait for all existing users to finish.
730          */
731         if (!atomic_dec_and_test(&sp->refcnt))
732                 down(&sp->dead_sem);
733
734         unregister_netdev(sp->dev);
735
736         del_timer(&sp->tx_t);
737         del_timer(&sp->resync_t);
738
739         /* Free all 6pack frame buffers. */
740         kfree(sp->rbuff);
741         kfree(sp->xbuff);
742 }
743
744 /* Perform I/O control on an active 6pack channel. */
745 static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
746         unsigned int cmd, unsigned long arg)
747 {
748         struct sixpack *sp = sp_get(tty);
749         struct net_device *dev = sp->dev;
750         unsigned int tmp, err;
751
752         if (!sp)
753                 return -ENXIO;
754
755         switch(cmd) {
756         case SIOCGIFNAME:
757                 err = copy_to_user((void __user *) arg, dev->name,
758                                    strlen(dev->name) + 1) ? -EFAULT : 0;
759                 break;
760
761         case SIOCGIFENCAP:
762                 err = put_user(0, (int __user *) arg);
763                 break;
764
765         case SIOCSIFENCAP:
766                 if (get_user(tmp, (int __user *) arg)) {
767                         err = -EFAULT;
768                         break;
769                 }
770
771                 sp->mode = tmp;
772                 dev->addr_len        = AX25_ADDR_LEN;
773                 dev->hard_header_len = AX25_KISS_HEADER_LEN +
774                                        AX25_MAX_HEADER_LEN + 3;
775                 dev->type            = ARPHRD_AX25;
776
777                 err = 0;
778                 break;
779
780          case SIOCSIFHWADDR: {
781                 char addr[AX25_ADDR_LEN];
782
783                 if (copy_from_user(&addr,
784                                    (void __user *) arg, AX25_ADDR_LEN)) {
785                         err = -EFAULT;
786                         break;
787                 }
788
789                 spin_lock_irq(&dev->xmit_lock);
790                 memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
791                 spin_unlock_irq(&dev->xmit_lock);
792
793                 err = 0;
794                 break;
795         }
796
797         /* Allow stty to read, but not set, the serial port */
798         case TCGETS:
799         case TCGETA:
800                 err = n_tty_ioctl(tty, (struct file *) file, cmd, arg);
801                 break;
802
803         default:
804                 err = -ENOIOCTLCMD;
805         }
806
807         sp_put(sp);
808
809         return err;
810 }
811
812 static struct tty_ldisc sp_ldisc = {
813         .owner          = THIS_MODULE,
814         .magic          = TTY_LDISC_MAGIC,
815         .name           = "6pack",
816         .open           = sixpack_open,
817         .close          = sixpack_close,
818         .ioctl          = sixpack_ioctl,
819         .receive_buf    = sixpack_receive_buf,
820         .receive_room   = sixpack_receive_room,
821         .write_wakeup   = sixpack_write_wakeup,
822 };
823
824 /* Initialize 6pack control device -- register 6pack line discipline */
825
826 static char msg_banner[]  __initdata = KERN_INFO \
827         "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
828 static char msg_regfail[] __initdata = KERN_ERR  \
829         "6pack: can't register line discipline (err = %d)\n";
830
831 static int __init sixpack_init_driver(void)
832 {
833         int status;
834
835         printk(msg_banner);
836
837         /* Register the provided line protocol discipline */
838         if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)
839                 printk(msg_regfail, status);
840
841         return status;
842 }
843
844 static const char msg_unregfail[] __exitdata = KERN_ERR \
845         "6pack: can't unregister line discipline (err = %d)\n";
846
847 static void __exit sixpack_exit_driver(void)
848 {
849         int ret;
850
851         if ((ret = tty_register_ldisc(N_6PACK, NULL)))
852                 printk(msg_unregfail, ret);
853 }
854
855 /* encode an AX.25 packet into 6pack */
856
857 static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
858         int length, unsigned char tx_delay)
859 {
860         int count = 0;
861         unsigned char checksum = 0, buf[400];
862         int raw_count = 0;
863
864         tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
865         tx_buf_raw[raw_count++] = SIXP_SEOF;
866
867         buf[0] = tx_delay;
868         for (count = 1; count < length; count++)
869                 buf[count] = tx_buf[count];
870
871         for (count = 0; count < length; count++)
872                 checksum += buf[count];
873         buf[length] = (unsigned char) 0xff - checksum;
874
875         for (count = 0; count <= length; count++) {
876                 if ((count % 3) == 0) {
877                         tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
878                         tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
879                 } else if ((count % 3) == 1) {
880                         tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
881                         tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x3c);
882                 } else {
883                         tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
884                         tx_buf_raw[raw_count++] = (buf[count] >> 2);
885                 }
886         }
887         if ((length % 3) != 2)
888                 raw_count++;
889         tx_buf_raw[raw_count++] = SIXP_SEOF;
890         return raw_count;
891 }
892
893 /* decode 4 sixpack-encoded bytes into 3 data bytes */
894
895 static void decode_data(struct sixpack *sp, unsigned char inbyte)
896 {
897         unsigned char *buf;
898
899         if (sp->rx_count != 3) {
900                 sp->raw_buf[sp->rx_count++] = inbyte;
901
902                 return;
903         }
904
905         buf = sp->raw_buf;
906         sp->cooked_buf[sp->rx_count_cooked++] =
907                 buf[0] | ((buf[1] << 2) & 0xc0);
908         sp->cooked_buf[sp->rx_count_cooked++] =
909                 (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
910         sp->cooked_buf[sp->rx_count_cooked++] =
911                 (buf[2] & 0x03) | (inbyte << 2);
912         sp->rx_count = 0;
913 }
914
915 /* identify and execute a 6pack priority command byte */
916
917 static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
918 {
919         unsigned char channel;
920         int actual;
921
922         channel = cmd & SIXP_CHN_MASK;
923         if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {     /* idle ? */
924
925         /* RX and DCD flags can only be set in the same prio command,
926            if the DCD flag has been set without the RX flag in the previous
927            prio command. If DCD has not been set before, something in the
928            transmission has gone wrong. In this case, RX and DCD are
929            cleared in order to prevent the decode_data routine from
930            reading further data that might be corrupt. */
931
932                 if (((sp->status & SIXP_DCD_MASK) == 0) &&
933                         ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
934                                 if (sp->status != 1)
935                                         printk(KERN_DEBUG "6pack: protocol violation\n");
936                                 else
937                                         sp->status = 0;
938                                 cmd &= !SIXP_RX_DCD_MASK;
939                 }
940                 sp->status = cmd & SIXP_PRIO_DATA_MASK;
941         } else { /* output watchdog char if idle */
942                 if ((sp->status2 != 0) && (sp->duplex == 1)) {
943                         sp->led_state = 0x70;
944                         sp->tty->driver->write(sp->tty, &sp->led_state, 1);
945                         sp->tx_enable = 1;
946                         actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
947                         sp->xleft -= actual;
948                         sp->xhead += actual;
949                         sp->led_state = 0x60;
950                         sp->status2 = 0;
951
952                 }
953         }
954
955         /* needed to trigger the TNC watchdog */
956         sp->tty->driver->write(sp->tty, &sp->led_state, 1);
957
958         /* if the state byte has been received, the TNC is present,
959            so the resync timer can be reset. */
960
961         if (sp->tnc_state == TNC_IN_SYNC) {
962                 del_timer(&sp->resync_t);
963                 sp->resync_t.data       = (unsigned long) sp;
964                 sp->resync_t.function   = resync_tnc;
965                 sp->resync_t.expires    = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
966                 add_timer(&sp->resync_t);
967         }
968
969         sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
970 }
971
972 /* identify and execute a standard 6pack command byte */
973
974 static void decode_std_command(struct sixpack *sp, unsigned char cmd)
975 {
976         unsigned char checksum = 0, rest = 0, channel;
977         short i;
978
979         channel = cmd & SIXP_CHN_MASK;
980         switch (cmd & SIXP_CMD_MASK) {     /* normal command */
981         case SIXP_SEOF:
982                 if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
983                         if ((sp->status & SIXP_RX_DCD_MASK) ==
984                                 SIXP_RX_DCD_MASK) {
985                                 sp->led_state = 0x68;
986                                 sp->tty->driver->write(sp->tty, &sp->led_state, 1);
987                         }
988                 } else {
989                         sp->led_state = 0x60;
990                         /* fill trailing bytes with zeroes */
991                         sp->tty->driver->write(sp->tty, &sp->led_state, 1);
992                         rest = sp->rx_count;
993                         if (rest != 0)
994                                  for (i = rest; i <= 3; i++)
995                                         decode_data(sp, 0);
996                         if (rest == 2)
997                                 sp->rx_count_cooked -= 2;
998                         else if (rest == 3)
999                                 sp->rx_count_cooked -= 1;
1000                         for (i = 0; i < sp->rx_count_cooked; i++)
1001                                 checksum += sp->cooked_buf[i];
1002                         if (checksum != SIXP_CHKSUM) {
1003                                 printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
1004                         } else {
1005                                 sp->rcount = sp->rx_count_cooked-2;
1006                                 sp_bump(sp, 0);
1007                         }
1008                         sp->rx_count_cooked = 0;
1009                 }
1010                 break;
1011         case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
1012                 break;
1013         case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
1014                 break;
1015         case SIXP_RX_BUF_OVL:
1016                 printk(KERN_DEBUG "6pack: RX buffer overflow\n");
1017         }
1018 }
1019
1020 /* decode a 6pack packet */
1021
1022 static void
1023 sixpack_decode(struct sixpack *sp, unsigned char *pre_rbuff, int count)
1024 {
1025         unsigned char inbyte;
1026         int count1;
1027
1028         for (count1 = 0; count1 < count; count1++) {
1029                 inbyte = pre_rbuff[count1];
1030                 if (inbyte == SIXP_FOUND_TNC) {
1031                         tnc_set_sync_state(sp, TNC_IN_SYNC);
1032                         del_timer(&sp->resync_t);
1033                 }
1034                 if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
1035                         decode_prio_command(sp, inbyte);
1036                 else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
1037                         decode_std_command(sp, inbyte);
1038                 else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
1039                         decode_data(sp, inbyte);
1040         }
1041 }
1042
1043 MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
1044 MODULE_DESCRIPTION("6pack driver for AX.25");
1045 MODULE_LICENSE("GPL");
1046 MODULE_ALIAS_LDISC(N_6PACK);
1047
1048 module_init(sixpack_init_driver);
1049 module_exit(sixpack_exit_driver);