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