#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <asm/system.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <linux/string.h>
#define SLLIN_MAGIC 0x53CA
/* #define BREAK_BY_BAUD */
-static int master = true;
+static bool master = true;
static int baudrate; /* Use LIN_DEFAULT_BAUDRATE when not set */
module_param(master, bool, 0);
static struct net_device **sllin_devs;
static int sllin_configure_frame_cache(struct sllin *sl, struct can_frame *cf);
+static void sllin_slave_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count);
+static void sllin_master_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count);
/* Values of two parity bits in LIN Protected
} while (unlikely(test_bit(SLF_TXBUFF_RQ, &sl->flags)));
if ((remains > 0) && (actual >= 0)) {
- pr_debug("sllin: sllin_write_wakeup sent %d, "
- "remains %d, waiting\n",
+ pr_debug("sllin: sllin_write_wakeup sent %d, remains %d, waiting\n",
sl->tx_cnt, sl->tx_lim - sl->tx_cnt);
return;
}
spin_lock(&sl->lock);
if (!netif_running(dev)) {
- printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
+ pr_warn("%s: xmit: iface is down\n", dev->name);
goto err_out_unlock;
}
if (sl->tty == NULL) {
- printk(KERN_WARNING "%s: xmit: no tty device connected\n", dev->name);
+ pr_warn("%s: xmit: no tty device connected\n", dev->name);
goto err_out_unlock;
}
/* New-style flags. */
dev->flags = IFF_NOARP;
- dev->features = NETIF_F_NO_CSUM;
+ dev->features = NETIF_F_HW_CSUM; /* NETIF_F_NO_CSUM;*/
}
/******************************************
Routines looking at TTY side.
******************************************/
-#define SLL_RESPONSE_RECEIVED ((sl->header_received == true) && \
- ((sl->rx_cnt >= sl->rx_expect) || \
- ((sl->rx_len_unknown == true) && (count == 0))))
-
-#define SLL_HEADER_RECEIVED ((sl->header_received == false) && \
- (sl->rx_cnt >= (SLLIN_BUFF_ID + 1)))
-
-static void sllin_receive_buf(struct tty_struct *tty,
+static void sllin_master_receive_buf(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
{
struct sllin *sl = (struct sllin *) tty->disc_data;
- pr_debug("sllin: sllin_receive_buf invoked, count = %u\n", count);
-
- if (!sl || sl->magic != SLLIN_MAGIC || !netif_running(sl->dev))
- return;
/* Read the characters out of the buffer */
while (count--) {
"due marker 0x%02x, flags 0x%lx\n",
*cp, *(fp-1), sl->flags);
- if (sl->lin_master == true) { /* Report error */
+ /* i.e. Real error -- not Break */
+ if (sl->rx_cnt > SLLIN_BUFF_BREAK) {
set_bit(SLF_ERROR, &sl->flags);
wake_up(&sl->kwt_wq);
return;
- } else { /* Received Break */
- sl->rx_cnt = 0;
- sl->rx_expect = SLLIN_BUFF_ID + 1;
- sl->rx_len_unknown = false; /* We do know exact length of the header */
- sl->header_received = false;
}
}
pr_debug("sllin: LIN_RX[%d]: 0x00\n", sl->rx_cnt);
sl->rx_buff[sl->rx_cnt++] = 0x00;
}
-#endif
+#endif /* BREAK_BY_BAUD */
+
if (sl->rx_cnt < SLLIN_BUFF_LEN) {
pr_debug("sllin: LIN_RX[%d]: 0x%02x\n", sl->rx_cnt, *cp);
sl->rx_buff[sl->rx_cnt++] = *cp++;
}
+ }
- if (sl->lin_master == true) {
- if (SLL_RESPONSE_RECEIVED) {
- set_bit(SLF_RXEVENT, &sl->flags);
- wake_up(&sl->kwt_wq);
- pr_debug("sllin: sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
- } else {
- pr_debug("sllin: sllin_receive_buf count %d, waiting\n", sl->rx_cnt);
- }
- } else { /* LIN slave */
- int lin_id;
- struct sllin_conf_entry *sce;
- pr_debug("sllin: rx_cnt = %u; header_received = %u\n",
- sl->rx_cnt, sl->header_received);
+ if (sl->rx_cnt >= sl->rx_expect) {
+ set_bit(SLF_RXEVENT, &sl->flags);
+ wake_up(&sl->kwt_wq);
+ pr_debug("sllin: sllin_receive_buf count %d, wakeup\n", sl->rx_cnt);
+ } else {
+ pr_debug("sllin: sllin_receive_buf count %d, waiting\n", sl->rx_cnt);
+ }
+}
+
- if (SLL_HEADER_RECEIVED) {
- unsigned long flags;
+static void sllin_slave_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct sllin *sl = (struct sllin *) tty->disc_data;
+ int lin_id;
+ struct sllin_conf_entry *sce;
- lin_id = sl->rx_buff[SLLIN_BUFF_ID] & LIN_ID_MASK;
- sce = &sl->linfr_cache[lin_id];
- spin_lock_irqsave(&sl->linfr_lock, flags);
- /* Is the length of data set in frame cache? */
- if (sce->frame_fl & LIN_LOC_SLAVE_CACHE) {
- sl->rx_expect += sce->dlc;
- sl->rx_len_unknown = false;
- } else {
- sl->rx_expect += SLLIN_DATA_MAX + 1; /* + checksum */
- sl->rx_len_unknown = true;
+ /* Read the characters out of the buffer */
+ while (count--) {
+ if (fp && *fp++) {
+ pr_debug("sllin: sllin_receive_buf char 0x%02x ignored "
+ "due marker 0x%02x, flags 0x%lx\n",
+ *cp, *(fp-1), sl->flags);
+
+ /* Received Break */
+ sl->rx_cnt = 0;
+ sl->rx_expect = SLLIN_BUFF_ID + 1;
+ sl->rx_len_unknown = false; /* We do know exact length of the header */
+ sl->header_received = false;
+ }
+
+ if (sl->rx_cnt < SLLIN_BUFF_LEN) {
+ pr_debug("sllin: LIN_RX[%d]: 0x%02x\n", sl->rx_cnt, *cp);
+
+ /* We did not receive break (0x00) character */
+ if ((sl->rx_cnt == SLLIN_BUFF_BREAK) && (*cp == 0x55)) {
+ sl->rx_buff[sl->rx_cnt++] = 0x00;
+ }
+
+ if (sl->rx_cnt == SLLIN_BUFF_SYNC) {
+ /* 'Duplicated' break character -- ignore */
+ if (*cp == 0x00) {
+ cp++;
+ continue;
}
- spin_unlock_irqrestore(&sl->linfr_lock, flags);
- sl->header_received = true;
- sll_send_rtr(sl);
- continue;
+ /* Wrong sync character */
+ if (*cp != 0x55)
+ break;
}
- if (SLL_RESPONSE_RECEIVED) {
- sll_bump(sl);
- pr_debug("sllin: Received LIN header & LIN response. "
- "rx_cnt = %u, rx_expect = %u\n", sl->rx_cnt,
- sl->rx_expect);
-
- /* Prepare for reception of new header */
- sl->rx_cnt = 0;
- sl->rx_expect = SLLIN_BUFF_ID + 1;
- sl->rx_len_unknown = false; /* We do know exact length of the header */
- sl->header_received = false;
+ sl->rx_buff[sl->rx_cnt++] = *cp++;
+ }
+
+ /* Header received */
+ if ((sl->header_received == false) && (sl->rx_cnt >= (SLLIN_BUFF_ID + 1))) {
+ unsigned long flags;
+
+ lin_id = sl->rx_buff[SLLIN_BUFF_ID] & LIN_ID_MASK;
+ sce = &sl->linfr_cache[lin_id];
+
+ spin_lock_irqsave(&sl->linfr_lock, flags);
+ /* Is the length of data set in frame cache? */
+ if (sce->frame_fl & LIN_CACHE_RESPONSE) {
+ sl->rx_expect += sce->dlc;
+ sl->rx_len_unknown = false;
+ } else {
+ sl->rx_expect += SLLIN_DATA_MAX + 1; /* + checksum */
+ sl->rx_len_unknown = true;
}
+ spin_unlock_irqrestore(&sl->linfr_lock, flags);
+
+ sl->header_received = true;
+ sll_send_rtr(sl);
+ continue;
+ }
+
+ /* Response received */
+ if ((sl->header_received == true) &&
+ ((sl->rx_cnt >= sl->rx_expect) ||
+ ((sl->rx_len_unknown == true) && (count == 0)))) {
+
+ sll_bump(sl);
+ pr_debug("sllin: Received LIN header & LIN response. "
+ "rx_cnt = %u, rx_expect = %u\n", sl->rx_cnt,
+ sl->rx_expect);
+
+ /* Prepare for reception of new header */
+ sl->rx_cnt = 0;
+ sl->rx_expect = SLLIN_BUFF_ID + 1;
+ sl->rx_len_unknown = false; /* We do know exact length of the header */
+ sl->header_received = false;
}
}
}
+static void sllin_receive_buf(struct tty_struct *tty,
+ const unsigned char *cp, char *fp, int count)
+{
+ struct sllin *sl = (struct sllin *) tty->disc_data;
+ pr_debug("sllin: sllin_receive_buf invoked, count = %u\n", count);
+
+ if (!sl || sl->magic != SLLIN_MAGIC || !netif_running(sl->dev))
+ return;
+
+ if (sl->lin_master)
+ sllin_master_receive_buf(tty, cp, fp, count);
+ else
+ sllin_slave_receive_buf(tty, cp, fp, count);
+
+}
+
/*****************************************
* sllin message helper routines
*****************************************/
unsigned long flags;
struct sllin_conf_entry *sce;
- if (!(cf->can_id & LIN_ID_CONF))
+ if (!(cf->can_id & LIN_CTRL_FRAME))
return -1;
sce = &sl->linfr_cache[cf->can_id & LIN_ID_MASK];
- pr_debug("sllin: Setting frame cache with EFF CAN frame. "
- "LIN ID = %d\n", cf->can_id & LIN_ID_MASK);
+ pr_debug("sllin: Setting frame cache with EFF CAN frame. LIN ID = %d\n",
+ cf->can_id & LIN_ID_MASK);
spin_lock_irqsave(&sl->linfr_lock, flags);
if ((data != NULL) && len) {
sl->tx_lim += len;
memcpy(sl->tx_buff + SLLIN_BUFF_DATA, data, len);
- sl->tx_buff[sl->tx_lim++] = sllin_checksum(sl->tx_buff,
+ sl->tx_buff[sl->tx_lim] = sllin_checksum(sl->tx_buff,
sl->tx_lim, mode & SLLIN_STPMSG_CHCKSUM_ENH);
+ sl->tx_lim++;
}
if (len != 0)
sl->rx_lim = SLLIN_BUFF_DATA + len + 1;
spin_lock_irqsave(&sl->linfr_lock, flags);
/* Is there Slave response in linfr_cache to be sent? */
- if ((sce->frame_fl & LIN_LOC_SLAVE_CACHE)
+ if ((sce->frame_fl & LIN_CACHE_RESPONSE)
&& (sce->dlc > 0)) {
pr_debug("sllin: Sending LIN response from linfr_cache\n");
sllin_report_error(sl, LIN_ERR_CHECKSUM);
} else {
/* Send CAN non-RTR frame with data */
- pr_debug("sllin: sending NON-RTR CAN"
- "frame with LIN payload.");
+ pr_debug("sllin: sending NON-RTR CAN frame with LIN payload.");
sll_bump(sl); /* send packet to the network layer */
}
sllin_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL);
if (!sllin_devs) {
- printk(KERN_ERR "sllin: can't allocate sllin device array!\n");
+ pr_err("sllin: can't allocate sllin device array!\n");
return -ENOMEM;
}
/* Fill in our line protocol discipline, and register it */
status = tty_register_ldisc(N_SLLIN, &sll_ldisc);
if (status) {
- printk(KERN_ERR "sllin: can't register line discipline\n");
+ pr_err("sllin: can't register line discipline\n");
kfree(sllin_devs);
}
sl = netdev_priv(dev);
if (sl->tty) {
- printk(KERN_ERR "%s: tty discipline still running\n",
+ pr_err("%s: tty discipline still running\n",
dev->name);
/* Intentionally leak the control block. */
dev->destructor = NULL;
i = tty_unregister_ldisc(N_SLLIN);
if (i)
- printk(KERN_ERR "sllin: can't unregister ldisc (err %d)\n", i);
+ pr_err("sllin: can't unregister ldisc (err %d)\n", i);
}
module_init(sllin_init);