ALPHA-pl15i
diff --git a/Makefile b/Makefile
index 8b40870..0fea62b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 15
-ALPHA = h
+ALPHA = i
 
 all:	Version zImage
 
diff --git a/README b/README
index c8d3523..4e73bed 100644
--- a/README
+++ b/README
@@ -1,18 +1,18 @@
 
-	Linux kernel release 0.99 patchlevel 14
+	Linux kernel release 0.99 patchlevel 15
 
-These are the release notes for linux version 0.99.14.  Read them
+These are the release notes for linux version 0.99.15.  Read them
 carefully, as they tell you what's new, explain how to install the
 kernel, and what to do if something goes wrong. 
 
 INSTALLING the kernel:
 
- - if you install by patching, you need a *clean* 0.99.13 source tree,
+ - if you install by patching, you need a *clean* 0.99.14 source tree,
    which presumably exists in /usr/src/linux.  If so, to get the kernel
    patched, just do a
 
 		cd /usr/src
-		patch -p0 < linux-0.99.patch14
+		patch -p0 < linux-0.99.patch15
 
    and you should be ok.  You may want to remove the backup files (xxx~
    or xxx.orig), and make sure that there are no failed patches (xxx# or
@@ -21,7 +21,7 @@
  - If you install the full sources, do a
 
 		cd /usr/src
-		tar xvf linux-0.99.14.tar
+		tar xvf linux-0.99.15.tar
 
    to get it all put in place.
 
diff --git a/drivers/FPU-emu/errors.c b/drivers/FPU-emu/errors.c
index 787f4e8..f8f9554 100644
--- a/drivers/FPU-emu/errors.c
+++ b/drivers/FPU-emu/errors.c
@@ -97,9 +97,19 @@
       printk(" [%02x]", byte1);
       address++;
     }
-  if ( i == MAX_PRINTED_BYTES ) printk(" [more..]");
-  printk("\n");
-  FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+  if ( i == MAX_PRINTED_BYTES )
+    printk(" [more..]\n");
+  else
+    {
+      FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+
+      if (FPU_modrm >= 0300)
+	printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
+      else
+	printk(" /%d, mod=%d rm=%d\n",
+	       (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
+    }
+
   partial_status = status_word();
 
 #ifdef DEBUGGING
@@ -118,12 +128,6 @@
 if ( partial_status & SW_Invalid )     printk("SW: invalid operation\n");
 #endif DEBUGGING
 
-  if (FPU_modrm >= 0300)
-    printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
-  else
-    printk("/%d, mod=%d rm=%d\n",
-	   (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
-
   printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
 	 partial_status & 0x8000 ? 1 : 0,   /* busy */
 	 (partial_status & 0x3800) >> 11,   /* stack top pointer */
diff --git a/drivers/FPU-emu/reg_mul.c b/drivers/FPU-emu/reg_mul.c
index cd21beb..7524618 100644
--- a/drivers/FPU-emu/reg_mul.c
+++ b/drivers/FPU-emu/reg_mul.c
@@ -51,11 +51,10 @@
 	 one valid and the other zero.
 	 The result is therefore zero. */
       reg_move(&CONST_Z, dest);
-#ifdef PECULIAR_486
       /* The 80486 book says that the answer is +0, but a real
-	 80486 appears to behave this way... */
+	 80486 behaves this way.
+	 IEEE-754 apparently says it should be this way. */
       dest->sign = sign;
-#endif PECULIAR_486
       return 0;
     }
   else
diff --git a/drivers/char/console.c b/drivers/char/console.c
index 4b43d69..e412241 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -1828,6 +1828,14 @@
 
 /*
  * PIO_FONT support.
+ *
+ * The font loading code goes back to the codepage package by
+ * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
+ * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
+ * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
+ *
+ * Change for certain monochrome monitors by Yury Shevchuck
+ * (sizif@botik.yaroslavl.su).
  */
 
 #define colourmap ((char *)0xa0000)
@@ -1843,14 +1851,17 @@
 #ifdef CAN_LOAD_EGA_FONTS
 	int i;
 	char *charmap;
+	int beg;
 
 	/* no use to "load" CGA... */
 
-	if (video_type == VIDEO_TYPE_EGAC)
+	if (video_type == VIDEO_TYPE_EGAC) {
 		charmap = colourmap;
-	else if (video_type == VIDEO_TYPE_EGAM)
+		beg = 0x0e;
+	} else if (video_type == VIDEO_TYPE_EGAM) {
 		charmap = blackwmap;
-	else
+		beg = 0x0a;
+	} else
 		return -EINVAL;
 
 	i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
@@ -1897,7 +1908,7 @@
 	outb_p( 0x05, gr_port_reg );
 	outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
 	outb_p( 0x06, gr_port_reg );
-	outb_p( 0x0e, gr_port_val );    /* map starts at b800:0000 */
+	outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
 	sti();
 
 	return 0;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index dc35531..d9f227a 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -930,10 +930,7 @@
 static inline int input_available_p(struct tty_struct *tty)
 {
 	/* Avoid calling TTY_READ_FLUSH unnecessarily. */
-	if (L_ICANON(tty)) {
-		if (tty->canon_data || FULL(&tty->read_q))
-			return 1;
-	} else if (!EMPTY(&tty->secondary))
+	if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
 		return 1;
 
 	/* Shuffle any pending data down the queues. */
@@ -941,10 +938,7 @@
 	if (tty->link)
 		TTY_WRITE_FLUSH(tty->link);
 
-	if (L_ICANON(tty)) {
-		if (tty->canon_data || FULL(&tty->read_q))
-			return 1;
-	} else if (!EMPTY(&tty->secondary))
+	if (L_ICANON(tty) ? tty->canon_data : !EMPTY(&tty->secondary))
 		return 1;
 	return 0;
 }
@@ -1036,7 +1030,7 @@
 			nr--;
 		}
 
-		while (nr > 0) {
+		while (1) {
 			int eol;
 
 			cli();
@@ -1047,6 +1041,24 @@
 			eol = clear_bit(tty->secondary.tail,
 					&tty->secondary_flags);
 			c = tty->secondary.buf[tty->secondary.tail];
+			if (!nr) {
+				/* Gobble up an immediately following EOF if
+				   there is no more room in buf (this can
+				   happen if the user "pushes" some characters
+				   using ^D).  This prevents the next read()
+				   from falsely returning EOF. */
+				if (eol) {
+					if (c == __DISABLED_CHAR) {
+						tty->canon_data--;
+						INC(tty->secondary.tail);
+					} else {
+						set_bit(tty->secondary.tail,
+							&tty->secondary_flags);
+					}
+				}
+				sti();
+				break;
+			}
 			INC(tty->secondary.tail);
 			sti();
 			if (eol) {
@@ -1067,10 +1079,9 @@
 		/* If there is enough space in the secondary queue now, let the
 		   low-level driver know. */
 		if (tty->throttle && (LEFT(&tty->secondary) >= SQ_THRESHOLD_HW)
-		    && !clear_bit(TTY_SQ_THROTTLED, &tty->flags))
+		    && clear_bit(TTY_SQ_THROTTLED, &tty->flags))
 			tty->throttle(tty, TTY_THROTTLE_SQ_AVAIL);
 
-		/* XXX packet mode's status byte is mistakenly counted */
 		if (b - buf >= minimum || !nr)
 			break;
 		if (time)
@@ -1121,6 +1132,10 @@
 			break;
 		if (EMPTY(&tty->write_q) && !need_resched)
 			continue;
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			break;
+		}
 		schedule();
 	}
 	current->state = TASK_RUNNING;
@@ -1594,7 +1609,7 @@
 			select_wait(&tty->secondary.proc_list, wait);
 			return 0;
 		case SEL_OUT:
-			if (!FULL(&tty->write_q))
+			if (LEFT(&tty->write_q) > WAKEUP_CHARS)
 				return 1;
 			select_wait(&tty->write_q.proc_list, wait);
 			return 0;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 1aec5ba..046012d 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -487,6 +487,8 @@
 					     sizeof (pid_t));
 			if (retval)
 				return retval;
+			if (current->tty != termios_dev)
+				return -ENOTTY;
 			put_fs_long(termios_tty->pgrp, (pid_t *) arg);
 			return 0;
 		case TIOCSPGRP:
@@ -526,7 +528,7 @@
 			return 0;
 		case TIOCSTI:
 			if ((current->tty != dev) && !suser())
-				return -EACCES;
+				return -EPERM;
 			retval = verify_area(VERIFY_READ, (void *) arg, 1);
 			if (retval)
 				return retval;
@@ -580,7 +582,7 @@
 			else if (IS_A_PTY_SLAVE(dev))
 				redirect = tty;
 			else
-				return -EINVAL;
+				return -ENOTTY;
 			return 0;
 		case FIONBIO:
 			arg = get_fs_long((unsigned long *) arg);
@@ -590,8 +592,8 @@
 				file->f_flags &= ~O_NONBLOCK;
 			return 0;
 		case TIOCNOTTY:
-			if (MINOR(file->f_rdev) != current->tty)
-				return -EINVAL;
+			if (current->tty != dev)
+				return -ENOTTY;
 			if (current->leader)
 				disassociate_ctty(0);
 			current->tty = -1;
@@ -629,7 +631,7 @@
 			return 0;
 		case TIOCPKT:
 			if (!IS_A_PTY_MASTER(dev))
-				return -EINVAL;
+				return -ENOTTY;
 			retval = verify_area(VERIFY_READ, (void *) arg,
 					     sizeof (unsigned long));
 			if (retval)
@@ -637,7 +639,7 @@
 			if (get_fs_long(arg)) {
 				if (!tty->packet) {
 					tty->packet = 1;
-					tty->ctrl_status = 0;
+					tty->link->ctrl_status = 0;
 				}
 			} else
 				tty->packet = 0;
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 148d91b..f7077d5 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -13,7 +13,7 @@
 	C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
 */
 
-static char *version = "3c509.c:pl13t 11/24/93 becker@super.org\n";
+static char *version = "3c509.c:pl15i 2/23/94 becker@super.org\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -549,19 +549,19 @@
 			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
 	while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
 		if (rx_status & 0x4000) { /* Error, update stats. */
-			short error = rx_status & 0x3C00;
+			short error = rx_status & 0x3800;
 			lp->stats.rx_errors++;
 			switch (error) {
-			case 0x2000:		lp->stats.rx_over_errors++; break;
-			case 0x2C00:		lp->stats.rx_length_errors++; break;
-			case 0x3400:		lp->stats.rx_crc_errors++; break;
-			case 0x2400:		lp->stats.rx_length_errors++; break;
-			case 0x3000:		lp->stats.rx_frame_errors++; break;
-			case 0x0800:		lp->stats.rx_frame_errors++; break;
+			case 0x0000:		lp->stats.rx_over_errors++; break;
+			case 0x0800:		lp->stats.rx_length_errors++; break;
+			case 0x1000:		lp->stats.rx_frame_errors++; break;
+			case 0x1800:		lp->stats.rx_length_errors++; break;
+			case 0x2000:		lp->stats.rx_frame_errors++; break;
+			case 0x2800:		lp->stats.rx_crc_errors++; break;
 			}
 		}
 		if ( (! (rx_status & 0x4000))
-			|| ! (rx_status & 0x2000)) { /* Dribble bits are OK. */
+			|| ! (rx_status & 0x1000)) { /* Dribble bits are OK. */
 			short pkt_len = rx_status & 0x7ff;
 			int sksize = sizeof(struct sk_buff) + pkt_len + 3;
 			struct sk_buff *skb;
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index e99d024..ac66503 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -12,7 +12,7 @@
 */
 
 static char *version =
-	"atp.c:v0.03 1/19/94 Donald Becker (becker@super.org)\n";
+	"atp.c:v0.04 2/25/94 Donald Becker (becker@super.org)\n";
 
 /*
 	This file is a device driver for the RealTek (aka AT-Lan-Tec) pocket
@@ -477,7 +477,7 @@
 
 	/* For ethernet, fill in the header.  This should really be done by a
 	   higher level, rather than duplicated for each ethernet adaptor. */
-	if (!skb->arp  &&  dev->rebuild_header(skb+1, dev)) {
+	if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
 		skb->dev = dev;
 		arp_queue (skb);
 		return 0;
@@ -490,7 +490,7 @@
 		printk("%s: Transmitter access conflict.\n", dev->name);
 	else {
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned char *buf = (void *)(skb+1);
+		unsigned char *buf = skb->data;
 		int flags;
 
 		/* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
@@ -611,7 +611,7 @@
 		} else if (num_tx_since_rx > 8
 				   && jiffies > dev->last_rx + 100) {
 			if (net_debug > 2)
-				printk("%s: Missed packet? No Rx after %d Tx and %d jiffies"
+				printk("%s: Missed packet? No Rx after %d Tx and %ld jiffies"
 					   " status %02x  CMR1 %02x.\n", dev->name,
 					   num_tx_since_rx, jiffies - dev->last_rx, status,
 					   (read_nibble(ioaddr, CMR1) >> 3) & 15);
@@ -623,6 +623,8 @@
 			break;
     }
 
+	/* This following code fixes a rare (and very difficult to track down)
+	   problem where the adaptor forgets its ethernet address. */
 	{
 		int i;
 		for (i = 0; i < 6; i++)
@@ -686,12 +688,12 @@
 		skb->len = pkt_len;
 		skb->dev = dev;
 		
-		/* 'skb+1' points to the start of sk_buff data area. */
-		read_block(ioaddr, pkt_len, (unsigned char *)(skb + 1), dev->if_port);
+		read_block(ioaddr, pkt_len, skb->data, dev->if_port);
 
 		if (net_debug > 6) {
-			unsigned char *data = (unsigned char *)(skb + 1);
-			printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x%02x %02x%02x..",
+			unsigned char *data = skb->data;
+			printk(" data %02x%02x%02x %02x%02x%02x %02x%02x%02x"
+				   "%02x%02x%02x %02x%02x..",
 				   data[0], data[1], data[2], data[3], data[4], data[5],
 				   data[6], data[7], data[8], data[9], data[10], data[11],
 				   data[12], data[13]);
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 50efe69..38c779a 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -135,8 +135,6 @@
 #include "arp.h"
 #include "depca.h"
 
-extern int vsprintf(char *buf, const char *fmt, ...);
-
 #ifdef DEPCA_DEBUG
 int depca_debug = DEPCA_DEBUG;
 #else
@@ -344,7 +342,7 @@
 		(num_eth > 0) && (num_eth < 9999)) {
 	      dev = dev->next;         /* point to the new device */
 	      dev->name = (char *)(dev + sizeof(struct device));
-	      vsprintf(dev->name,"eth%d", num_eth); /* New device name */
+	      sprintf(dev->name,"eth%d", num_eth); /* New device name */
 	      dev->base_addr = ioaddr; /* assign the io address */
 	      dev->next = (struct device *)NULL; /* mark the end of list */
 	      dev->init = &depca_probe;/* initialisation routine */
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 4eac67b..39e6339 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -562,9 +562,9 @@
 	    (int)(lp->tx_bounce_buffs + entry) | 0x83000000;
 	if (skb->free)
 	    kfree_skb (skb, FREE_WRITE);
-    } else
-    {
-    	/* Gimme!!! */
+    } else {
+    	/* We can't free the packet yet, so we inform the memory management
+	   code that we are still using it. */
     	if(skb->free==0)
     		skb_kept_by_device(skb);
 	lp->tx_ring[entry].base = (int)(skb+1) | 0x83000000;
@@ -655,7 +655,8 @@
 		    kfree_skb(skb, FREE_WRITE);
 		else
 		    skb_device_release(skb,FREE_WRITE);
-		/* Warning: skb may well vanish at the point you call device_release! */
+		/* Warning: skb may well vanish at the point you call
+		   device_release! */
 	    }
 	    dirty_tx++;
 	}
@@ -705,8 +706,13 @@
     while (lp->rx_ring[entry].base >= 0) {
 	int status = lp->rx_ring[entry].base >> 24;
 
-	if (status & 0x40) {	/* There was an error. */
-	    lp->stats.rx_errors++;
+	if (status != 0x03) {		/* There was an error. */
+	    /* There is an tricky error noted by John Murphy,
+	       <murf@perftech.com> to Russ Nelson: Even with full-sized
+	       buffers it's possible for a jabber packet to use two
+	       buffers, with only the last correctly noting the error. */
+	    if (status & 0x01)	/* Only count a general error at the */
+		lp->stats.rx_errors++; /* end of a packet.*/
 	    if (status & 0x20) lp->stats.rx_frame_errors++;
 	    if (status & 0x10) lp->stats.rx_over_errors++;
 	    if (status & 0x08) lp->stats.rx_crc_errors++;
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 07dc5ce..2a8dc3e 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -14,7 +14,7 @@
 */
 
 static char *version =
-    "smc-ultra.c:v0.06 2/9/94 Donald Becker (becker@super.org)\n";
+    "smc-ultra.c:v0.07 3/1/94 Donald Becker (becker@super.org)\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -63,7 +63,7 @@
     unsigned short ioaddr = dev->base_addr;
 
     if (ioaddr > 0x1ff)
-	return ! ultraprobe1(ioaddr, dev);
+	return ultraprobe1(ioaddr, dev);
     else if (ioaddr > 0)
 	return ENXIO;		/* Don't probe at all. */
 
@@ -158,7 +158,7 @@
   dev->mem_end = dev->rmem_end
       = dev->mem_start + (ei_status.stop_page - START_PG)*256;
 
-  printk(",%s IRQ %d memory %#x-%#x.\n", eeprom_irq ? "" : "assigned ",
+  printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
 	 dev->irq, dev->mem_start, dev->mem_end-1);
   if (ei_debug > 0)
       printk(version);
@@ -193,7 +193,7 @@
     int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
 
     outb(ULTRA_RESET, cmd_port);
-    if (ei_debug > 1) printk("resetting Ultra, t=%d...", jiffies);
+    if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
     ei_status.txing = 0;
 
     outb(ULTRA_MEMENB, cmd_port);
diff --git a/fs/hpfs/README b/fs/hpfs/README
new file mode 100644
index 0000000..7e4fe88
--- /dev/null
+++ b/fs/hpfs/README
@@ -0,0 +1,25 @@
+Linux can read, but not write, OS/2 HPFS partitions.
+
+Mount options are the same as for msdos partitions.
+
+  uid=nnn	All files in the partition will be owned by user id nnn.
+  gid=nnn	All files in the partition will be in group nnn.
+  umask=nnn	The permission mask (see umask(1)) for the partition.
+  conv=binary   Data is returned exactly as is, with CRLF's.  [default]
+  conv=text     (Carriage return, line feed) is replaced with newline.
+  conv=auto     Chooses, file by file, conv=binary or conv=text (by guessing)
+
+There is one mount option unique to HPFS.
+
+  case=lower	Convert file names to lower case.  [default]
+  case=asis     Return file names as is, in mixed case.
+
+Case is not significant in filename matching, like real HPFS.
+
+
+Command line example
+    mkdir -p /os2/c
+    mount -t hpfs -o uid=100,gid=100 /dev/sda6 /os2/c
+
+/etc/fstab example
+    /dev/sdb5	/d/f    hpfs    ro,uid=402,gid=402,umask=002
diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h
index b01e8d7..cfd5ef6 100644
--- a/fs/hpfs/hpfs.h
+++ b/fs/hpfs/hpfs.h
@@ -131,7 +131,7 @@
 
 /* The code page info pointed to by the spare block consists of an index
    block and blocks containing character maps.  The following is pretty
-   sketchy, but Linux is Latin-1 so it doesn't matter. */
+   sketchy, but Linux doesn't use code pages so it doesn't matter. */
 
 /* block pointed to by spareblock->code_page_dir */
 
diff --git a/fs/hpfs/hpfs_fs.c b/fs/hpfs/hpfs_fs.c
index 9498f5a..f2abf2c 100644
--- a/fs/hpfs/hpfs_fs.c
+++ b/fs/hpfs/hpfs_fs.c
@@ -6,7 +6,7 @@
  *  Chris Smith 1993
  *
  *  Sources & references:
- *   Duncan, _Design ... of HPFS_, MSSJ 4(5)   (C) 1989 Microsoft Corp
+ *   Duncan, _Design ... of HPFS_, MSJ 4(5)   (C) 1989 Microsoft Corp
  *   linux/fs/minix  Copyright (C) 1991, 1992, 1993  Linus Torvalds
  *   linux/fs/msdos  Written 1992, 1993 by Werner Almesberger
  *   linux/fs/isofs  Copyright (C) 1991  Eric Youngdale
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index ed5884a..1aebbb1 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -191,6 +191,8 @@
 			    for (i = 0; i < dlen && i < NAME_MAX; i++) {
 			      if (!(c = dpnt[i])) break;
 			      if (c >= 'A' && c <= 'Z') c |= 0x20;  /* lower case */
+			      if (c == '.' && i == dlen-3 && de->name[i+1] == ';' && de->name[i+2] == '1')
+				break;  /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
 			      if (c == ';' && i == dlen-2 && de->name[i+1] == '1') 
 				break;  /* Drop trailing ';1' */
 			      if (c == ';') c = '.';  /* Convert remaining ';' to '.' */
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index ebbb449..f62faf1 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -316,6 +316,7 @@
 	 struct SL_component * slp;
 	 slen = rr->len - 5;
 	 slp = &rr->u.SL.link;
+	 inode->i_size = 0;
 	 while (slen > 1){
 	   rootflag = 0;
 	   switch(slp->flags &~1){
diff --git a/fs/nfs/sock.c b/fs/nfs/sock.c
index f355b0c..801fdc5 100644
--- a/fs/nfs/sock.c
+++ b/fs/nfs/sock.c
@@ -108,7 +108,7 @@
 					continue;
 				if (server->flags & NFS_MOUNT_SOFT) {
 					printk("NFS server %s not responding, "
-						"timed out", server_name);
+						"timed out\n", server_name);
 					result = -EIO;
 					break;
 				}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 4f102df..3a9260a 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -84,7 +84,8 @@
 	inode->i_nlink = 1;
 	inode->i_size = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	inode->i_blocks = inode->i_blksize = 0;
+	inode->i_blocks = 0;
+	inode->i_blksize = 1024;
 	ino = inode->i_ino;
 	pid = ino >> 16;
 	p = task[0];
diff --git a/fs/select.c b/fs/select.c
index cfa62cd..3d89701 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -223,11 +223,10 @@
 		i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
 		if (i)
 			return i;
-		timeout = jiffies;
-		timeout += ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
+		timeout = ROUND_UP(get_fs_long((unsigned long *)&tvp->tv_usec),(1000000/HZ));
 		timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
-		if (timeout <= jiffies)
-			timeout = 0;
+		if (timeout)
+			timeout += jiffies + 1;
 	}
 	current->timeout = timeout;
 	i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 36f302d..92aa261 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -166,7 +166,7 @@
 
 struct task_struct {
 /* these are hardcoded - don't touch */
-	long state;		/* -1 unrunnable, 0 runnable, >0 stopped */
+	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	long counter;
 	long priority;
 	unsigned long signal;
diff --git a/include/linux/termios.h b/include/linux/termios.h
index a2528bd..3864136 100644
--- a/include/linux/termios.h
+++ b/include/linux/termios.h
@@ -150,9 +150,9 @@
 #define VTDLY	0040000
 #define   VT0	0000000
 #define   VT1	0040000
-#define FFDLY	0040000
+#define FFDLY	0100000
 #define   FF0	0000000
-#define   FF1	0040000
+#define   FF1	0100000
 
 /* c_cflag bit meaning */
 #define CBAUD	0000017
diff --git a/ipc/shm.c b/ipc/shm.c
index b486e62..ac249ec 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -462,6 +462,8 @@
 	shp->attaches = shmd;
 	shp->shm_lpid = current->pid;
 	shp->shm_atime = CURRENT_TIME;
+	if (!raddr)
+		return addr;
 	put_fs_long (addr, raddr);
 	return 0;
 }
diff --git a/kernel/traps.c b/kernel/traps.c
index 7321836..1303a25 100644
--- a/kernel/traps.c
+++ b/kernel/traps.c
@@ -80,23 +80,33 @@
 /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
 	int i;
+	unsigned long esp;
+	unsigned short ss;
 
+	esp = (unsigned long) &regs->esp;
+	ss = KERNEL_DS;
 	if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
 		return;
-
+	if (regs->cs & 3) {
+		esp = regs->esp;
+		ss = regs->ss;
+	}
 	console_verbose();
 	printk("%s: %04lx\n", str, err & 0xffff);
 	printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
-	printk("esi: %08lx   edi: %08lx   ebp: %08lx\n",
-		regs->esi, regs->edi, regs->ebp);
-	printk("ds: %04x   es: %04x   fs: %04x   gs: %04x\n",
-		regs->ds, regs->es, regs->fs, regs->gs);
+	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+		regs->esi, regs->edi, regs->ebp, esp);
+	printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
+		regs->ds, regs->es, regs->fs, regs->gs, ss);
 	store_TR(i);
-	printk("Pid: %d, process nr: %d (%s)\n", current->pid, 0xffff & i, current->comm);
+	printk("Pid: %d, process nr: %d (%s)\nCode: ", current->pid, 0xffff & i, current->comm);
 	for(i=0;i<20;i++)
 		printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
+	printk("\nStack: ");
+	for(i=0;i<5;i++)
+		printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
 	printk("\n");
 	do_exit(SIGSEGV);
 }
diff --git a/mm/memory.c b/mm/memory.c
index 0168a8d..9ffd165 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -304,9 +304,9 @@
 			if ((page = *page_table) != 0) {
 				*page_table = 0;
 				if (1 & page) {
-					if (!(mem_map[MAP_NR(page)]
-					      & MAP_PAGE_RESERVED))
-						--current->rss;
+					if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
+						if (current->rss > 0)
+							--current->rss;
 					free_page(PAGE_MASK & page);
 				} else
 					swap_free(page);
@@ -364,9 +364,9 @@
 			if ((page = *page_table) != 0) {
 				*page_table = 0;
 				if (page & PAGE_PRESENT) {
-					if (!(mem_map[MAP_NR(page)]
-					      & MAP_PAGE_RESERVED))
-						--current->rss;
+					if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
+						if (current->rss > 0)
+							--current->rss;
 					free_page(PAGE_MASK & page);
 				} else
 					swap_free(page);
@@ -426,9 +426,9 @@
 			if ((page = *page_table) != 0) {
 				*page_table = 0;
 				if (PAGE_PRESENT & page) {
-					if (!(mem_map[MAP_NR(page)]
-					      & MAP_PAGE_RESERVED))
-						--current->rss;
+					if (!(mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED))
+						if (current->rss > 0)
+							--current->rss;
 					free_page(PAGE_MASK & page);
 				} else
 					swap_free(page);
diff --git a/net/inet/icmp.c b/net/inet/icmp.c
index f6ae64c..51e6a05 100644
--- a/net/inet/icmp.c
+++ b/net/inet/icmp.c
@@ -210,9 +210,11 @@
   ip = iph->daddr;
   switch(icmph->code & 7) {
 	case ICMP_REDIR_NET:
+#ifdef not_a_good_idea
 		rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY),
 			ip, 0, icmph->un.gateway, dev);
 		break;
+#endif
 	case ICMP_REDIR_HOST:
 		rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_HOST | RTF_GATEWAY),
 			ip, 0, icmph->un.gateway, dev);
diff --git a/net/inet/skbuff.c b/net/inet/skbuff.c
index 7886e5c..7de68d9 100644
--- a/net/inet/skbuff.c
+++ b/net/inet/skbuff.c
@@ -394,8 +394,8 @@
 	skb->magic = 0;
 	if (skb->sk)
 	{
-	      if(skb->sk->prot!=NULL)
-	{
+		if(skb->sk->prot!=NULL)
+		{
 			if (rw)
 				skb->sk->prot->rfree(skb->sk, skb->mem_addr, skb->mem_len);
 			else
diff --git a/net/inet/sock.c b/net/inet/sock.c
index c605eac..e45dd7f 100644
--- a/net/inet/sock.c
+++ b/net/inet/sock.c
@@ -1578,10 +1578,13 @@
 {
   if (sk) {
 	if (sk->wmem_alloc + size < sk->sndbuf || force) {
-		cli();
-		sk->wmem_alloc+= size;
-		sti();
-		return(alloc_skb(size, priority));
+		struct sk_buff * c = alloc_skb(size, priority);
+		if (c) {
+			cli();
+			sk->wmem_alloc+= size;
+			sti();
+		}
+		return c;
 	}
 	DPRINTF((DBG_INET, "sock_wmalloc(%X,%d,%d,%d) returning NULL\n",
 						sk, size, force, priority));
@@ -1597,9 +1600,11 @@
   if (sk) {
 	if (sk->rmem_alloc + size < sk->rcvbuf || force) {
 		struct sk_buff *c = alloc_skb(size, priority);
-		cli();
-		if (c) sk->rmem_alloc += size;
-		sti();
+		if (c) {
+			cli();
+			sk->rmem_alloc += size;
+			sti();
+		}
 		return(c);
 	}
 	DPRINTF((DBG_INET, "sock_rmalloc(%X,%d,%d,%d) returning NULL\n",
diff --git a/net/inet/tcp.c b/net/inet/tcp.c
index 30c48e2..9880c99 100644
--- a/net/inet/tcp.c
+++ b/net/inet/tcp.c
@@ -117,28 +117,29 @@
 }
 
 
-void
-print_th(struct tcphdr *th)
+static void __print_th(struct tcphdr *th)
 {
-  unsigned char *ptr;
+	unsigned char *ptr;
 
-  if (inet_debug != DBG_TCP) return;
+	printk("TCP header:\n");
+	printk("    source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
+		ntohs(th->source), ntohs(th->dest),
+		ntohl(th->seq), ntohl(th->ack_seq));
+	printk("    fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
+		th->fin, th->syn, th->rst, th->psh, th->ack,
+		th->urg, th->res1, th->res2);
+	printk("    window = %d, check = %d urg_ptr = %d\n",
+		ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
+	printk("    doff = %d\n", th->doff);
+	ptr =(unsigned char *)(th + 1);
+	printk("    options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
+}
 
-  printk("TCP header:\n");
-  ptr =(unsigned char *)(th + 1);
-  printk("    source=%d, dest=%d, seq =%ld, ack_seq = %ld\n",
-	ntohs(th->source), ntohs(th->dest),
-	ntohl(th->seq), ntohl(th->ack_seq));
-  printk("    fin=%d, syn=%d, rst=%d, psh=%d, ack=%d, urg=%d res1=%d res2=%d\n",
-	th->fin, th->syn, th->rst, th->psh, th->ack,
-	th->urg, th->res1, th->res2);
-  printk("    window = %d, check = %d urg_ptr = %d\n",
-	ntohs(th->window), ntohs(th->check), ntohs(th->urg_ptr));
-  printk("    doff = %d\n", th->doff);
-  printk("    options = %d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
- }
-
-
+static inline void print_th(struct tcphdr *th)
+{
+	if (inet_debug == DBG_TCP)
+		__print_th(th);
+}
 
 /* This routine grabs the first thing off of a rcv queue. */
 static struct sk_buff *
@@ -616,6 +617,13 @@
 	/* We need to complete and send the packet. */
 	tcp_send_check(skb->h.th, sk->saddr, sk->daddr, size, sk);
 
+	size -= 4*skb->h.th->doff;
+	if (skb->h.th->syn)
+		size++;
+	if (skb->h.th->fin)
+		size++;
+
+	sk->send_seq += size;
 	skb->h.seq = sk->send_seq;
 	if (after(sk->send_seq , sk->window_seq) ||
 	    (sk->retransmits && sk->timeout == TIME_WRITE) ||
@@ -737,6 +745,10 @@
   /* FIXME: */
   memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
 
+  /* hack-around */
+  if (after(sequence, sk->window_seq))
+	sequence = sk->window_seq;
+
   /* swap the send and the receive. */
   t1->dest = th->source;
   t1->source = th->dest;
@@ -920,7 +932,6 @@
 			from += copy;
 			copied += copy;
 			len -= copy;
-			sk->send_seq += copy;
 		      }
 		if ((skb->len - hdrlen) >= sk->mss ||
 		    (flags & MSG_OOB) ||
@@ -943,14 +954,11 @@
 	 *   be queued for later rather than sent.
 	 */
 
-	copy = diff(sk->window_seq, sk->send_seq);
-	/* what if max_window == 1?  In that case max_window >> 1 is 0.
-	 * however in that case copy == max_window, so it's OK to use 
-	 * the window */
-	if (copy < (sk->max_window >> 1))
-	  copy = sk->mss;
-	copy = min(copy, sk->mss);
-	copy = min(copy, len);
+	copy = sk->window_seq - sk->send_seq;
+	if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
+		copy = sk->mss;
+	if (copy > len)
+		copy = len;
 
   /* We should really check the window here also. */
 	send_tmp = NULL;
@@ -1043,7 +1051,6 @@
 	len -= copy;
 	skb->len += copy;
 	skb->free = 0;
-	sk->send_seq += copy;
 
 	if (send_tmp != NULL && sk->packets_out) {
 		tcp_enqueue_partial(send_tmp, sk);
@@ -1136,7 +1143,10 @@
   t1 =(struct tcphdr *)(buff->data +tmp);
 
   memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
-  t1->seq = ntohl(sk->send_seq);
+  if (after(sk->send_seq, sk->window_seq))
+	t1->seq = ntohl(sk->window_seq);
+  else
+	t1->seq = ntohl(sk->send_seq);
   t1->ack = 1;
   t1->res1 = 0;
   t1->res2 = 0;
@@ -1613,13 +1623,13 @@
   
   if(th->ack)
   {
-  	t1->ack=0;
-  	t1->seq=th->ack_seq;
-  	t1->ack_seq=0;
+  	t1->ack = 0;
+  	t1->seq = th->ack_seq;
+  	t1->ack_seq = 0;
   }
   else
   {
-  	t1->ack=1;
+  	t1->ack = 1;
   	if(!th->syn)
   		t1->ack_seq=htonl(th->seq);
   	else
@@ -3049,77 +3059,62 @@
 }
 
 
-/* This functions checks to see if the tcp header is actually acceptible. */
+/* This functions checks to see if the tcp header is actually acceptable. */
 static int
 tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
 	     struct options *opt, unsigned long saddr, struct device *dev)
 {
-  /*
-   * This isn't quite right.  sk->acked_seq could be more recent
-   * than sk->window.  This is however close enough.  We will accept
-   * slightly more packets than we should, but it should not cause
-   * problems unless someone is trying to forge packets.
-   */
-  DPRINTF((DBG_TCP, "tcp_sequence(sk=%X, th=%X, len = %d, opt=%d, saddr=%X)\n",
-	  sk, th, len, opt, saddr));
+	unsigned long next_seq;
 
-  if (between(th->seq, sk->acked_seq, sk->acked_seq + sk->window)||
-      between(th->seq + len-(th->doff*4), sk->acked_seq + 1,
-	      sk->acked_seq + sk->window) ||
-     (before(th->seq, sk->acked_seq) &&
-       after(th->seq + len -(th->doff*4), sk->acked_seq + sk->window))) {
-       return(1);
-   }
-  DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
+	next_seq = len - 4*th->doff;
+	/* if we have a zero window, we can't have any data in the packet.. */
+	if (next_seq && !sk->window)
+		goto ignore_it;
+	next_seq += th->seq;
+	if (th->syn)
+		next_seq++;
 
-  /*
-   *	Send a reset if we get something not ours and we are
-   *	unsynchronized. Note: We don't do anything to our end. We
-   *	are just killing the bogus remote connection then we will
-   *	connect again and it will work (with luck).
-   */
+	/*
+	 * This isn't quite right.  sk->acked_seq could be more recent
+	 * than sk->window.  This is however close enough.  We will accept
+	 * slightly more packets than we should, but it should not cause
+	 * problems unless someone is trying to forge packets.
+	 */
+
+	/* have we already seen all of this packet? */
+	if (!after(next_seq+1, sk->acked_seq))
+		goto ignore_it;
+	/* or does it start beyond the window? */
+	if (!before(th->seq, sk->acked_seq + sk->window + 1))
+		goto ignore_it;
+
+	/* ok, at least part of this packet would seem interesting.. */
+	return 1;
+
+ignore_it:
+	DPRINTF((DBG_TCP, "tcp_sequence: rejecting packet.\n"));
+
+	/*
+	 *	Send a reset if we get something not ours and we are
+	 *	unsynchronized. Note: We don't do anything to our end. We
+	 *	are just killing the bogus remote connection then we will
+	 *	connect again and it will work (with luck).
+	 */
   	 
-  if(sk->state==TCP_SYN_SENT||sk->state==TCP_SYN_RECV)
-  {
-  	tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
-  	return(1);
-  }
+	if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV) {
+		tcp_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
+		return 1;
+	}
 
-  /*
-   * If it's too far ahead, send an ack to let the
-   * other end know what we expect.
-   */
-  if (after(th->seq, sk->acked_seq + sk->window)) {
-	if(!th->rst)
-		tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-	return(0);
-  }
+	if (th->rst)
+		return 0;
 
-#ifdef undef
-/*
- * if we do this, we won't respond to keepalive packets, since those
- * are slightly out of window, and we have to generate an ack
- * a late ack out still not to have a sequence number less than
- * one we've seen before.  Berkeley doesn't seem to do this, but it's
- * always hard to be sure.
- */
-  /* In case it's just a late ack, let it through. */
-  if (th->ack && len == (th->doff * 4) &&
-      after(th->seq, sk->acked_seq - 32767) &&
-      !th->fin && !th->syn) return(1);
-#endif
-
-  if (!th->rst) {
 	/* Try to resync things. */
 	tcp_send_ack(sk->send_seq, sk->acked_seq, sk, th, saddr);
-  }
-  return(0);
+	return 0;
 }
 
 
-
-
-
 int
 tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
 	unsigned long daddr, unsigned short len,
@@ -3175,14 +3170,12 @@
 		return(0);
 	}
 
+	th->seq = ntohl(th->seq);
+
 	/* See if we know about the socket. */
 	if (sk == NULL) {
-		if (!th->rst) 
-		{	
-			th->seq = ntohl(th->seq);
-			/* So reset is always called with th->seq in host order */
+		if (!th->rst)
 			tcp_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
-		}
 		skb->sk = NULL;
 		kfree_skb(skb, FREE_READ);
 		return(0);
@@ -3196,8 +3189,6 @@
 	skb->saddr = daddr;
 	skb->daddr = saddr;
 
-	th->seq = ntohl(th->seq);
-
 	/* We may need to add it to the backlog here. */
 	cli();
 	if (sk->inuse) {
@@ -3317,12 +3308,11 @@
 			release_sock(sk);
 			return(0);
 		}
-		if (th->ack) {
-			if (!tcp_ack(sk, th, saddr, len)) {
-				kfree_skb(skb, FREE_READ);
-				release_sock(sk);
-				return(0);
-			}
+
+		if (th->ack && !tcp_ack(sk, th, saddr, len)) {
+			kfree_skb(skb, FREE_READ);
+			release_sock(sk);
+			return(0);
 		}
 
 		if (tcp_urg(sk, th, saddr, len)) {
@@ -3684,10 +3674,8 @@
  * sends fin in a separate packet
  * syn, rst, had better be zero in original */
   t1->ack = 1;
-  t1->urg = 0;  /* urgent pointer might be beyond this fragment */
   t1->res2 = 0;
   t1->window = ntohs(tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
-  t1->urg_ptr = 0;
   tcp_send_check(t1, sk->saddr, sk->daddr, len - hlen, sk);
   /* Send it and free it.
    * This will prevent the timer from automatically being restarted.
diff --git a/net/inet/tcp.h b/net/inet/tcp.h
index 5cbe0ea..1dd91ad 100644
--- a/net/inet/tcp.h
+++ b/net/inet/tcp.h
@@ -80,10 +80,7 @@
  */
 static inline int before(unsigned long seq1, unsigned long seq2)
 {
-	/* this inequality is strict. */
-	if (seq1 == seq2)
-		return 0;
-	seq2 -= seq1;
+	seq2 -= seq1+1;
 	return (seq2 < 65536);
 }
 
@@ -118,7 +115,6 @@
 extern struct proto tcp_prot;
 
 
-extern void	print_th(struct tcphdr *);
 extern void	tcp_err(int err, unsigned char *header, unsigned long daddr,
 			unsigned long saddr, struct inet_protocol *protocol);
 extern void	tcp_shutdown (struct sock *sk, int how);