patch-1.3.61 linux/drivers/net/slip.c
Next file: linux/drivers/net/slip.h
Previous file: linux/drivers/net/loopback.c
Back to the patch index
Back to the overall index
- Lines: 318
- Date:
Fri Feb 9 16:59:04 1996
- Orig file:
v1.3.60/linux/drivers/net/slip.c
- Orig date:
Wed Feb 7 15:11:26 1996
diff -u --recursive --new-file v1.3.60/linux/drivers/net/slip.c linux/drivers/net/slip.c
@@ -46,7 +46,10 @@
* With MODULE-loading ``insmod'', user can
* issue parameter: slip_maxdev=1024
* (Or how much he/she wants.. Default is 256)
- *
+ * * Stanislav Voronyi : Slip line checking, with ideas taken
+ * from multislip BSDI driver which was written
+ * by Igor Chechik, RELCOM Corp. Only algorithms
+ * have been ported to Linux SLIP driver.
*/
#define SL_CHECK_TRANSMIT
@@ -81,9 +84,9 @@
#endif
#ifdef MODULE
-#define SLIP_VERSION "0.8.3-NET3.019-NEWTTY-MODULAR"
+#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY-MODULAR"
#else
-#define SLIP_VERSION "0.8.3-NET3.019-NEWTTY"
+#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY"
#endif
@@ -103,7 +106,10 @@
static int slip_esc6(unsigned char *p, unsigned char *d, int len);
static void slip_unesc6(struct slip *sl, unsigned char c);
#endif
-
+#ifdef CONFIG_SLIP_SMART
+static void sl_keepalive(unsigned long sls);
+static void sl_outfill(unsigned long sls);
+#endif
/* Find a free SLIP channel, and link in this `tty' line. */
static inline struct slip *
@@ -442,6 +448,8 @@
#endif
sl->xleft = count - actual;
sl->xhead = sl->xbuff + actual;
+ /* VSV */
+ clear_bit(SLF_OUTWAIT, &sl->flags); /* reset outfill flag */
}
/*
@@ -457,13 +465,13 @@
if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start) {
return;
}
-
if (sl->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sl->tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- sl_unlock(sl);
+ if (test_bit(0, (void *) &sl->dev->tbusy)) /* add by VSV */
+ sl_unlock(sl);
mark_bh(NET_BH);
return;
}
@@ -620,7 +628,16 @@
sl->xbits = 0;
#endif
sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
-
+#ifdef CONFIG_SLIP_SMART
+ sl->keepalive=0; /* no keepalive by default = VSV */
+ init_timer(&sl->keepalive_timer); /* initialize timer_list struct */
+ sl->keepalive_timer.data=(unsigned long)sl;
+ sl->keepalive_timer.function=sl_keepalive;
+ sl->outfill=0; /* & outfill too */
+ init_timer(&sl->outfill_timer);
+ sl->outfill_timer.data=(unsigned long)sl;
+ sl->outfill_timer.function=sl_outfill;
+#endif
/* Needed because address '0' is special */
if (dev->pa_addr == 0) {
dev->pa_addr=ntohl(0xC0A80001);
@@ -873,6 +890,10 @@
switch(s) {
case END:
+ /* drop keeptest bit = VSV */
+ if (test_bit(SLF_KEEPTEST, &sl->flags))
+ clear_bit(SLF_KEEPTEST, &sl->flags);
+
if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2)) {
sl_bump(sl);
}
@@ -954,6 +975,10 @@
unsigned char c;
if (s == 0x70) {
+ /* drop keeptest bit = VSV */
+ if (test_bit(SLF_KEEPTEST, &sl->flags))
+ clear_bit(SLF_KEEPTEST, &sl->flags);
+
if (!clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2)) {
sl_bump(sl);
}
@@ -1086,6 +1111,60 @@
return -EINVAL;
#endif
+#ifdef CONFIG_SLIP_SMART
+ /* VSV changes start here */
+ case SIOCSKEEPALIVE:
+ if (sl->keepalive)
+ del_timer (&sl->keepalive_timer);
+ err = verify_area(VERIFY_READ, arg, sizeof(int));
+ if (err) {
+ return -err;
+ }
+ tmp = get_user((int *)arg);
+ if (tmp > 255) /* max for unchar */
+ return -EINVAL;
+ if ((sl->keepalive = (unchar) tmp) != 0) {
+ sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
+ add_timer(&sl->keepalive_timer);
+ set_bit(SLF_KEEPTEST, &sl->flags);
+ }
+ return 0;
+
+ case SIOCGKEEPALIVE:
+ err = verify_area(VERIFY_WRITE, arg, sizeof(int));
+ if (err) {
+ return -err;
+ }
+ put_user(sl->keepalive, (int *)arg);
+ return 0;
+
+ case SIOCSOUTFILL:
+ if (sl->outfill)
+ (void)del_timer (&sl->outfill_timer);
+ err = verify_area(VERIFY_READ, arg, sizeof(int));
+ if (err) {
+ return -err;
+ }
+ tmp = get_user((int *)arg);
+ if (tmp > 255) /* max for unchar */
+ return -EINVAL;
+ if ((sl->outfill = (unchar) tmp) != 0){
+ sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
+ add_timer(&sl->outfill_timer);
+ set_bit(SLF_OUTWAIT, &sl->flags);
+ }
+ return 0;
+
+ case SIOCGOUTFILL:
+ err = verify_area(VERIFY_WRITE, arg, sizeof(int));
+ if (err) {
+ return -err;
+ }
+ put_user(sl->outfill, (int *)arg);
+ return 0;
+ /* VSV changes end */
+#endif
+
/* Allow stty to read, but not set, the serial port */
case TCGETS:
case TCGETA:
@@ -1108,8 +1187,7 @@
#ifdef MODULE
static int slip_init_ctrl_dev(void)
#else /* !MODULE */
-int
-slip_init_ctrl_dev(struct device *dummy)
+int slip_init_ctrl_dev(struct device *dummy)
#endif /* !MODULE */
{
int status;
@@ -1120,19 +1198,23 @@
#ifdef CONFIG_SLIP_MODE_SLIP6
" (6 bit encapsulation enabled)"
#endif
- "\n",
+ ".\n",
SLIP_VERSION, slip_maxdev );
#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
- printk("CSLIP: code copyright 1989 Regents of the University of California\n");
+ printk("CSLIP: code copyright 1989 Regents of the University of California.\n");
#endif
#ifdef CONFIG_AX25
- printk("AX25: KISS encapsulation enabled\n");
+ printk("AX25: KISS encapsulation enabled.\n");
#endif
+#ifdef CONFIG_SLIP_SMART
+ printk("SLIP linefill/keepalive option.\n");
+#endif
slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL);
- if (slip_ctrls == NULL) {
- printk("SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n");
- return -ENOMEM;
+ if (slip_ctrls == NULL)
+ {
+ printk("SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n");
+ return -ENOMEM;
}
/* Clear the pointer array, we allocate devices when we need them */
@@ -1153,7 +1235,7 @@
sl_ldisc.receive_room = slip_receive_room;
sl_ldisc.write_wakeup = slip_write_wakeup;
if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) {
- printk("SLIP: can't register line discipline (err = %d)\n", status);
+ printk("SLIP: can't register line discipline (err = %d)\n", status);
}
@@ -1242,18 +1324,95 @@
{
int i;
- if (slip_ctrls != NULL) {
- for (i = 0; i < slip_maxdev; i++) {
- if (slip_ctrls[i] != NULL) {
- unregister_netdev(&(slip_ctrls[i]->dev));
- kfree(slip_ctrls[i]);
- }
- }
- kfree(slip_ctrls);
- slip_ctrls = NULL;
+ if (slip_ctrls != NULL)
+ {
+ for (i = 0; i < slip_maxdev; i++)
+ {
+ if (slip_ctrls[i] != NULL)
+ {
+ unregister_netdev(&(slip_ctrls[i]->dev));
+ kfree(slip_ctrls[i]);
+ }
+ }
+ kfree(slip_ctrls);
+ slip_ctrls = NULL;
}
- if ((i = tty_register_ldisc(N_SLIP, NULL))) {
- printk("SLIP: can't unregister line discipline (err = %d)\n", i);
+ if ((i = tty_register_ldisc(N_SLIP, NULL)))
+ {
+ printk("SLIP: can't unregister line discipline (err = %d)\n", i);
}
}
#endif /* MODULE */
+
+#ifdef CONFIG_SLIP_SMART
+/*
+ * This is start of the code for multislip style line checking
+ * added by Stanislav Voronyi. All changes before marked VSV
+ */
+
+static void sl_outfill(unsigned long sls)
+{
+ struct slip *sl=(struct slip *)sls;
+
+ if(sls==NULL)
+ return;
+
+ if(sl->outfill)
+ {
+ if( test_bit(SLF_OUTWAIT, &sl->flags) )
+ {
+ /* no packets was transmited, do outfill */
+#ifdef CONFIG_SLIP_MODE_SLIP6
+ unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;
+#else
+ unsigned char s = END;
+#endif
+ /* put END into tty queue. Is it right ??? */
+ if (!test_bit(0, (void *) &sl->dev->tbusy))
+ {
+ /* if device busy no outfill */
+ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ sl->tty->driver.write(sl->tty, 0, &s, 1);
+ }
+ }
+ else
+ set_bit(SLF_OUTWAIT, &sl->flags);
+ (void)del_timer(&sl->outfill_timer);
+ sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
+ add_timer(&sl->outfill_timer);
+ }
+ else
+ del_timer(&sl->outfill_timer);
+}
+
+static void sl_keepalive(unsigned long sls)
+{
+ struct slip *sl=(struct slip *)sls;
+
+ if(sls==NULL)
+ return;
+
+ if( sl->keepalive)
+ {
+ if(test_bit(SLF_KEEPTEST, &sl->flags))
+ {
+ /* keepalive still high :(, we must hangup */
+ (void)del_timer(&sl->keepalive_timer);
+ if( sl->outfill ) /* outfill timer must be deleted too */
+ (void)del_timer(&sl->outfill_timer);
+ printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
+ tty_hangup(sl->tty); /* this must hangup tty & close slip */
+ /* I think we need not something else */
+ return;
+ }
+ else
+ set_bit(SLF_KEEPTEST, &sl->flags);
+ (void)del_timer(&sl->keepalive_timer);
+ sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
+ add_timer(&sl->keepalive_timer);
+ }
+ else
+ (void)del_timer(&sl->keepalive_timer);
+}
+
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this