diff -u --recursive --new-file v1.1.54/linux/Makefile linux/Makefile
--- v1.1.54/linux/Makefile	Thu Oct 20 09:37:27 1994
+++ linux/Makefile	Tue Oct 18 10:08:37 1994
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 54
+SUBLEVEL = 55
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.54/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.1.54/linux/drivers/block/floppy.c	Thu Oct 20 09:37:28 1994
+++ linux/drivers/block/floppy.c	Wed Oct 19 11:48:42 1994
@@ -25,9 +25,9 @@
 
 
 /* Define the following if you don't like that your drives seek audibly
- * after a disk change
+ * after a disk change (but it may not work correctly for everybody)
  */
-#define SILENT_DC_CLEAR
+/* #define SILENT_DC_CLEAR */
 
 
 /* End of configuration */
@@ -304,7 +304,7 @@
 	{ 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"CompaQ"},	/*  9 2.88MB 3.5"   */
 
 	{ 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25"  */
-	{ 3360,21,2,80,0,0x1C,0x00,0xCF,0x6C,"H1680" }, /* 11 1.68MB 3.5"   */
+	{ 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5"   */
 	{  820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410"  },	/* 12 410KB 5.25"   */
 	{ 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820"  },	/* 13 820KB 3.5"    */
 	{ 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" },	/* 14 1.48MB 5.25"  */
@@ -317,8 +317,8 @@
 	{ 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"h880"  }, /* 20 880KB 5.25"   */
 	{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5"   */
 	{ 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5"   */
-	{ 3200,20,2,80,0,0x1C,0x20,0xCF,0x6C,"h1600" }, /* 23 1.6MB 5.25"   */
-	{ 3520,22,2,80,0,0x1C,0x08,0xCF,0x6C,"H1760" }, /* 24 1.76MB 3.5"   */
+	{ 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25"   */
+	{ 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5"   */
 	{ 3840,24,2,80,0,0x1C,0x20,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5"   */
 	{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5"   */
 	{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5"   */
@@ -326,7 +326,7 @@
 
 	{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x6C,"H1840" }, /* 29 1.84MB 3.5"   */
 	{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800"  },	/* 30 800KB 3.5"    */
-	{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x6C,"H1600" }, /* 31 1.6MB 3.5"    */
+	{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */
 };
 
 #define	NUMBER(x)	(sizeof(x) / sizeof(*(x)))
@@ -1278,9 +1278,10 @@
 			debugt("recal interrupt need 1 recal:");
 #endif
 			/* after a second recalibrate, we still haven't
-			 * reached track 0. Probably no drive */
-			DRS->track = PROVEN_ABSENT;
-			cont->done(0);
+			 * reached track 0. Probably no drive. Raise an
+			 * error, as failing immediately might upset 
+			 * computers possessed by the Devil :-) */
+			cont->error();
 			cont->redo();
 			return;
 		case NEED_2_RECAL:
@@ -1691,7 +1692,7 @@
 	int count,head_shift,track_shift;
 
 	raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-		FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
+		/*FD_RAW_NEED_DISK |*/ FD_RAW_NEED_SEEK;
 	raw_cmd.rate = floppy->rate & 0x3;
 	raw_cmd.cmd_count = NR_F;
 	COMMAND = FM_MODE(floppy,FD_FORMAT);
diff -u --recursive --new-file v1.1.54/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v1.1.54/linux/drivers/block/hd.c	Thu Oct 20 09:37:28 1994
+++ linux/drivers/block/hd.c	Tue Oct 18 10:08:06 1994
@@ -15,10 +15,8 @@
  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
  *  in the early extended-partition checks and added DM partitions
  *
- *  IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord.
- *
- *  Support for BIOS drive geometry translation added by Mark Lord.
- *   -- hd.c no longer chokes on drives with "more than 16 heads".
+ *  IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ *  and general streamlining by mlord@bnr.ca (Mark Lord).
  */
 
 #define DEFAULT_MULT_COUNT  0	/* set to 0 to disable multiple mode at boot */
@@ -62,6 +60,9 @@
 #define RECAL_FREQ      4	/* Recalibrate every 4th retry */
 #define MAX_HD		2
 
+#define STAT_OK		(READY_STAT|SEEK_STAT)
+#define OK_STATUS(s)	(((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
+
 static void recal_intr(void);
 static void bad_rw_intr(void);
 
@@ -135,12 +136,12 @@
 static void dump_status (char *msg, unsigned int stat)
 {
 	unsigned long flags;
-	char dev;
+	char devc;
 
-	dev  = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?';
+	devc = CURRENT ? 'a' + DEVICE_NR(CURRENT->dev) : '?';
 	save_flags (flags);
 	sti();
-	printk("hd%c: %s: status=0x%02x { ", dev, msg, stat & 0xff);
+	printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
 	if (stat & BUSY_STAT)	printk("Busy ");
 	if (stat & READY_STAT)	printk("DriveReady ");
 	if (stat & WRERR_STAT)	printk("WriteFault ");
@@ -150,55 +151,48 @@
 	if (stat & INDEX_STAT)	printk("Index ");
 	if (stat & ERR_STAT)	printk("Error ");
 	printk("}\n");
-	if (stat & ERR_STAT) {
-		unsigned int err = inb(HD_ERROR);
-		printk("hd%c: %s: error=0x%02x { ", dev, msg, err & 0xff);
-		if (err & BBD_ERR)	printk("BadSector ");
-		if (err & ECC_ERR)	printk("UncorrectableError ");
-		if (err & ID_ERR)	printk("SectorIdNotFound ");
-		if (err & ABRT_ERR)	printk("DriveStatusError ");
-		if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
-		if (err & MARK_ERR)	printk("AddrMarkNotFound ");
+	if ((stat & ERR_STAT) == 0) {
+		hd_error = 0;
+	} else {
+		hd_error = inb(HD_ERROR);
+		printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff);
+		if (hd_error & BBD_ERR)		printk("BadSector ");
+		if (hd_error & ECC_ERR)		printk("UncorrectableError ");
+		if (hd_error & ID_ERR)		printk("SectorIdNotFound ");
+		if (hd_error & ABRT_ERR)	printk("DriveStatusError ");
+		if (hd_error & TRK0_ERR)	printk("TrackZeroNotFound ");
+		if (hd_error & MARK_ERR)	printk("AddrMarkNotFound ");
 		printk("}");
-		if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
-			if (CURRENT)
-				printk(", sector=%ld", CURRENT->sector);
+		if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
 			printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
 				inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
+			if (CURRENT)
+				printk(", sector=%ld", CURRENT->sector);
 		}
 		printk("\n");
 	}
 	restore_flags (flags);
 }
 
-static int win_result(void)
+void check_status(void)
 {
-	int i=inb_p(HD_STATUS);
+	int i = inb_p(HD_STATUS);
 
-	if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
-		== (READY_STAT | SEEK_STAT)) {
-	        hd_error = 0;
-		return 0; /* ok */
+	if (!OK_STATUS(i)) {
+		dump_status("check_status", i);
+		bad_rw_intr();
 	}
-	dump_status("win_result", i);
-	return 1;
 }
 
-static int controller_busy(void);
-static int status_ok(void);
-
-static int controller_ready(unsigned int drive, unsigned int head)
+static int controller_busy(void)
 {
-	int retry = 100;
+	int retries = 100000;
+	unsigned char status;
 
 	do {
-		if (controller_busy() & BUSY_STAT)
-			return 0;
-		outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
-		if (status_ok())
-			return 1;
-	} while (--retry);
-	return 0;
+		status = inb_p(HD_STATUS);
+	} while ((status & BUSY_STAT) && --retries);
+	return status;
 }
 
 static int status_ok(void)
@@ -206,7 +200,7 @@
 	unsigned char status = inb_p(HD_STATUS);
 
 	if (status & BUSY_STAT)
-		return 1;
+		return 1;	/* Ancient, but does it make sense??? */
 	if (status & WRERR_STAT)
 		return 0;
 	if (!(status & READY_STAT))
@@ -216,15 +210,18 @@
 	return 1;
 }
 
-static int controller_busy(void)
+static int controller_ready(unsigned int drive, unsigned int head)
 {
-	int retries = 100000;
-	unsigned char status;
+	int retry = 100;
 
 	do {
-		status = inb_p(HD_STATUS);
-	} while ((status & BUSY_STAT) && --retries);
-	return status;
+		if (controller_busy() & BUSY_STAT)
+			return 0;
+		outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
+		if (status_ok())
+			return 1;
+	} while (--retry);
+	return 0;
 }
 
 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
@@ -233,13 +230,6 @@
 {
 	unsigned short port;
 
-#ifdef DEBUG
-	if (drive>1 || head>15) {
-		printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
-			drive, cyl, head, sect);
-		panic("harddisk driver problem");
-	}
-#endif
 #if (HD_DELAY > 0)
 	while (read_timer() - last_req < HD_DELAY)
 		/* nothing */;
@@ -346,7 +336,7 @@
 		/*
 		 * Early model Quantum drives go weird at this point,
 		 *   but doing a recalibrate seems to "fix" them.
-		 * (Doing a full reset confuses some newer model Quantums)
+		 * (Doing a full reset confuses some other model Quantums)
 		 */
 		if (!strncmp(id->model, "QUANTUM", 7))
 			special_op[dev] = recalibrate[dev] = 1;
@@ -366,7 +356,7 @@
 		sti();
 	if (stat & (BUSY_STAT|ERR_STAT)) {
 		mult_req[dev] = mult_count[dev] = 0;
-		dump_status("set multiple mode failed", stat);
+		dump_status("set multmode failed", stat);
 	} else {
 		if ((mult_count[dev] = mult_req[dev]))
 			printk ("  hd%c: enabled %d-sector multiple mode\n",
@@ -388,8 +378,7 @@
 
 	for (i = 0; i < 500000 ; i++) {
 		c = inb_p(HD_STATUS);
-		c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
-		if (c == (READY_STAT | SEEK_STAT))
+		if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
 			return 0;
 	}
 	dump_status("reset timed out", c);
@@ -405,9 +394,9 @@
 	outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
 	for(i = 0; i < 1000; i++) nop();
 	if (drive_busy())
-		printk("HD-controller still busy\n");
-	if ((hd_error = inb(HD_ERROR)) != 1)
-		printk("HD-controller reset failed: %02x\n",hd_error);
+		printk("hd: controller still busy\n");
+	else if ((hd_error = inb(HD_ERROR)) != 1)
+		printk("hd: controller reset failed: %02x\n",hd_error);
 }
 
 static void reset_hd(void)
@@ -419,12 +408,13 @@
 		reset = 0;
 		i = -1;
 		reset_controller();
-	} else if (win_result()) {
-		bad_rw_intr();
+	} else {
+		check_status();
 		if (reset)
 			goto repeat;
 	}
 	if (++i < NR_HD) {
+		special_op[i] = recalibrate[i] = 1;
 		if (unmask_intr[i]) {
 			unmask_intr[i] = DEFAULT_UNMASK_INTR;
 			printk("hd%c: reset irq-unmasking to %d\n",i+'a',
@@ -444,7 +434,6 @@
 		hd_request();
 }
 
-
 /*
  * Ok, don't know what to do with the unexpected interrupts: on some machines
  * doing a reset and a retry seems to result in an eternal loop. Right now I
@@ -478,11 +467,11 @@
 	dev = DEVICE_NR(CURRENT->dev);
 	if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
 		end_request(0);
-		special_op[dev] += recalibrate[dev] = 1;
+		special_op[dev] = recalibrate[dev] = 1;
 	} else if (CURRENT->errors % RESET_FREQ == 0)
 		reset = 1;
 	else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
-		special_op[dev] += recalibrate[dev] = 1;
+		special_op[dev] = recalibrate[dev] = 1;
 	/* Otherwise just retry */
 }
 
@@ -497,9 +486,6 @@
 	return -1;
 }
 
-#define STAT_MASK (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT)
-#define STAT_OK (READY_STAT | SEEK_STAT)
-
 static void read_intr(void)
 {
 	unsigned int dev = DEVICE_NR(CURRENT->dev);
@@ -511,7 +497,7 @@
 		i = (unsigned) inb_p(HD_STATUS);
 		if (i & BUSY_STAT)
 			continue;
-		if ((i & STAT_MASK) != STAT_OK)
+		if (!OK_STATUS(i))
 			break;
 		if (i & DRQ_STAT)
 			goto ok_to_read;
@@ -534,9 +520,9 @@
 	i = (CURRENT->nr_sectors -= nsect);
 
 #ifdef DEBUG
-	printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=%08lx\n",
+	printk("hd%c: read: sectors(%ld-%ld), remaining=%ld, buffer=0x%08lx\n",
 		dev+'a', CURRENT->sector, CURRENT->sector+nsect,
-		CURRENT->nr_sectors, (long) CURRENT->buffer+(nsect<<9));
+		CURRENT->nr_sectors, (unsigned long) CURRENT->buffer+(nsect<<9));
 #endif
 	if ((CURRENT->current_nr_sectors -= nsect) <= 0)
 		end_request(1);
@@ -581,7 +567,7 @@
 
 	if (unmask_intr[dev])
 		sti();
-	if (((i = inb_p(HD_STATUS)) & STAT_MASK) == STAT_OK) {
+	if (OK_STATUS(i=inb_p(HD_STATUS))) {
 		if (i & DRQ_STAT) {
 			if (WCURRENT.nr_sectors) {
 				multwrite(dev);
@@ -619,7 +605,7 @@
 		i = (unsigned) inb_p(HD_STATUS);
 		if (i & BUSY_STAT)
 			continue;
-		if ((i & STAT_MASK) != STAT_OK)
+		if (!OK_STATUS(i))
 			break;
 		if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT))
 			goto ok_to_write;
@@ -650,8 +636,7 @@
 
 static void recal_intr(void)
 {
-	if (win_result())
-		bad_rw_intr();
+	check_status();
 #if (HD_DELAY > 0)
 	last_req = read_timer();
 #endif
@@ -664,116 +649,118 @@
  */
 static void hd_times_out(void)
 {
+	unsigned int dev;
+
 	DEVICE_INTR = NULL;
-	sti();
 	if (!CURRENT)
 		return;
+	disable_irq(HD_IRQ);
+	sti();
 	reset = 1;
-	printk(KERN_DEBUG "HD timeout\n");
+	dev = DEVICE_NR(CURRENT->dev);
+	printk("hd%c: timeout\n", dev+'a');
 	if (++CURRENT->errors >= MAX_ERRORS) {
 #ifdef DEBUG
-		printk("hd : too many errors.\n");
+		printk("hd%c: too many errors\n", dev+'a');
 #endif
 		end_request(0);
 	}
 	cli();
-
 	hd_request();
+	enable_irq(HD_IRQ);
+}
+
+int do_special_op (unsigned int dev)
+{
+	if (recalibrate[dev]) {
+		recalibrate[dev] = 0;
+		hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+		return reset;
+	}
+	if (!identified[dev]) {
+		identified[dev]  = 1;
+		unmask_intr[dev] = DEFAULT_UNMASK_INTR;
+		mult_req[dev]    = DEFAULT_MULT_COUNT;
+		hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
+		return reset;
+	}
+	if (mult_req[dev] != mult_count[dev]) {
+		hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
+		return reset;
+	}
+	if (hd_info[dev].head > 16) {
+		printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
+		end_request(0);
+	}
+	special_op[dev] = 0;
+	return 1;
 }
 
 /*
- * The driver has been modified to enable interrupts a bit more: in order to
- * do this we first (a) disable the timeout-interrupt and (b) clear the
- * device-interrupt. This way the interrupts won't mess with out code (the
- * worst that can happen is that an unexpected HD-interrupt comes in and
- * sets the "reset" variable and starts the timer)
+ * The driver enables interrupts as much as possible.  In order to do this,
+ * (a) the device-interrupt is disabled before entering hd_request(),
+ * and (b) the timeout-interrupt is disabled before the sti().
+ *
+ * Interrupts are still masked (by default) whenever we are exchanging
+ * data/cmds with a drive, because some drives seem to have very poor
+ * tolerance for latency during I/O.  For devices which don't suffer from
+ * that problem (most don't), the unmask_intr[] flag can be set to unmask
+ * other interrupts during data/cmd transfers (by defining DEFAULT_UNMASK_INTR
+ * to 1, or by using "hdparm -u1 /dev/hd?" from the shell).
  */
 static void hd_request(void)
 {
-	unsigned int block,dev;
-	unsigned int sec,head,cyl,track;
-	unsigned int nsect;
+	unsigned int dev, block, nsect, sec, track, head, cyl;
 
 	if (CURRENT && CURRENT->dev < 0) return;
-
 	if (DEVICE_INTR)
 		return;
 repeat:
 	timer_active &= ~(1<<HD_TIMER);
 	sti();
 	INIT_REQUEST;
+	if (reset) {
+		cli();
+		reset_hd();
+		return;
+	}
 	dev = MINOR(CURRENT->dev);
 	block = CURRENT->sector;
 	nsect = CURRENT->nr_sectors;
-	if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
+	if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
 #ifdef DEBUG
-		printk("hd : attempted read for sector %d past end of device at sector %d.\n",
-		   	block, hd[dev].nr_sects);
+		if (dev >= (NR_HD<<6))
+			printk("hd: bad minor number: device=0x%04x\n", CURRENT->dev);
+		else
+			printk("hd%c: bad access: block=%d, count=%d\n",
+				(CURRENT->dev>>6)+'a', block, nsect);
 #endif
 		end_request(0);
 		goto repeat;
 	}
 	block += hd[dev].start_sect;
 	dev >>= 6;
-	sec = block % hd_info[dev].sect + 1;
+	if (special_op[dev]) {
+		if (do_special_op(dev))
+			goto repeat;
+		return;
+	}
+	sec   = block % hd_info[dev].sect + 1;
 	track = block / hd_info[dev].sect;
-	head = track % hd_info[dev].head;
-	cyl = track / hd_info[dev].head;
+	head  = track % hd_info[dev].head;
+	cyl   = track / hd_info[dev].head;
 #ifdef DEBUG
-	printk("hd%c : cyl = %d, head = %d, sector = %d, buffer = %08x\n",
-		dev+'a', cyl, head, sec, CURRENT->buffer);
+	printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n",
+		dev+'a', (CURRENT->cmd == READ)?"read":"writ",
+		cyl, head, sec, nsect, (unsigned long) CURRENT->buffer);
 #endif
 	if (!unmask_intr[dev])
 		cli();
-	if (reset) {
-		int i;
-
-		for (i=0; i < NR_HD; i++)
-			special_op[i] = recalibrate[i] = 1;
-		cli(); /* better play it safe, as resets are the last resort */
-		reset_hd();
-		return;
-	}
-	if (special_op[dev]) {	/* we use "special_op" to reduce overhead on r/w */
-		if (recalibrate[dev]) {
-			recalibrate[dev] = 0;
-			hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
-			if (reset)
-				goto repeat;
-			return;
-		}	
-		if (!identified[dev]) {
-			identified[dev]  = 1;
-			unmask_intr[dev] = DEFAULT_UNMASK_INTR;
-			mult_req[dev]    = DEFAULT_MULT_COUNT;
-			hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
-			if (reset)
-				goto repeat;
-			return;
-		}
-		if (mult_req[dev] != mult_count[dev]) {
-			hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
-			if (reset)
-				goto repeat;
-			return;
-		}
-		if (hd_info[dev].head > 16) {
-			printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
-			end_request(0);
-			goto repeat;
-		}
-		--special_op[dev];
-	} /* special_op[dev] */
 	if (CURRENT->cmd == READ) {
 		unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
 		hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
 		if (reset)
 			goto repeat;
-#ifdef DEBUG
-		printk("hd%c: reading %d sectors(%ld-%ld), buffer=%08lx\n",
-			dev+'a', nsect, CURRENT->sector,
-			CURRENT->sector+nsect-1, (long) CURRENT->buffer);
-#endif
 		return;
 	}
 	if (CURRENT->cmd == WRITE) {
@@ -783,11 +770,6 @@
 			hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
 		if (reset)
 			goto repeat;
-#ifdef DEBUG
-		printk("hd%c: writing %d sectors(%ld-%ld), buffer=%08lx\n",
-			dev+'a', nsect, CURRENT->sector,
-			CURRENT->sector+nsect-1, (long) CURRENT->buffer);
-#endif
 		if (wait_DRQ()) {
 			bad_rw_intr();
 			goto repeat;
@@ -795,9 +777,8 @@
 		if (mult_count[dev]) {
 			WCURRENT = *CURRENT;
 			multwrite(dev);
-		} else {
+		} else
 			outsw(HD_DATA,CURRENT->buffer,256);
-		}
 		return;
 	}
 	panic("unknown hd-command");
@@ -905,11 +886,11 @@
 			if (arg > max_mult[dev])
 				err = -EINVAL;	/* out of range for device */
 			else if (mult_req[dev] != mult_count[dev]) {
-				++special_op[dev];
+				special_op[dev] = 1;
 				err = -EBUSY;	/* busy, try again */
 			} else {
 				mult_req[dev] = arg;
-				++special_op[dev];
+				special_op[dev] = 1;
 				err = 0;
 			}
 			restore_flags(flags);
@@ -1045,22 +1026,14 @@
 	}
 	i = NR_HD;
 	while (i-- > 0) {
-		hd[i<<6].nr_sects = 0;
-		if (bios_info[i].head > 16) {
-			/*
-			 * The newer E-IDE BIOSs handle drives larger than 1024
-			 * cylinders by increasing the number of logical heads
-			 * to keep the number of logical cylinders below the
-			 * sacred INT13 limit of 1024 (10 bits).  If that is
-			 * what's happening here, we'll find out and correct
-			 * it later when "identifying" the drive.
-			 */
-			printk("hd.c: IDE/ST-506 disk with more than 16 heads detected.\n");
-			printk("  (hd%c: cyl=%d, sect=%d, head=%d)\n", i+'a',
-				bios_info[i].cyl,
-				bios_info[i].sect,
-				bios_info[i].head);
-		}
+		/*
+		 * The newer E-IDE BIOSs handle drives larger than 1024
+		 * cylinders by increasing the number of logical heads
+		 * to keep the number of logical cylinders below the
+		 * sacred INT13 limit of 1024 (10 bits).  If that is
+		 * what's happening here, we'll find out and correct
+		 * it later when "identifying" the drive.
+		 */
 		hd[i<<6].nr_sects = bios_info[i].head *
 				bios_info[i].sect * bios_info[i].cyl;
 		hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
@@ -1068,7 +1041,7 @@
 	}
 	if (NR_HD) {
 		if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
-			printk("hd.c: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
+			printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
 			NR_HD = 0;
 		}
 	}
@@ -1094,7 +1067,7 @@
 unsigned long hd_init(unsigned long mem_start, unsigned long mem_end)
 {
 	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-		printk("Unable to get major %d for harddisk\n",MAJOR_NR);
+		printk("hd: unable to get major %d for harddisk\n",MAJOR_NR);
 		return mem_start;
 	}
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
diff -u --recursive --new-file v1.1.54/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v1.1.54/linux/drivers/char/lp.c	Sun Oct  9 12:00:24 1994
+++ linux/drivers/char/lp.c	Tue Oct 18 10:07:53 1994
@@ -514,4 +514,12 @@
 	return 0;
 }
 
+void cleanup_module(void)
+{
+       if(MOD_IN_USE)
+               printk("lp: busy - remove delayed\n");
+       else
+               unregister_chrdev(LP_MAJOR,"lp");
+}
+
 #endif
diff -u --recursive --new-file v1.1.54/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v1.1.54/linux/drivers/sound/Makefile	Thu Jul 21 08:18:12 1994
+++ linux/drivers/sound/Makefile	Tue Oct 18 10:07:28 1994
@@ -54,7 +54,11 @@
 	@echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
 	@echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
 	@echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h
-	@echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\" >> local.h
+	@if [ -x /bin/dnsdomainname ]; then \
+           echo \#define SOUND_CONFIG_DOMAIN \"`dnsdomainname`\"; \
+         else \
+           echo \#define SOUND_CONFIG_DOMAIN \"`domainname`\"; \
+         fi >> local.h
 
 clrconf:
 	rm -f local.h .depend
diff -u --recursive --new-file v1.1.54/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v1.1.54/linux/fs/binfmt_elf.c	Thu Oct 20 09:37:35 1994
+++ linux/fs/binfmt_elf.c	Tue Oct 18 10:07:47 1994
@@ -612,8 +612,8 @@
 	current->mm->start_code = start_code;
 	current->mm->end_data = end_data;
 	current->mm->start_stack = bprm->p;
-	current->suid = current->euid = bprm->e_uid;
-	current->sgid = current->egid = bprm->e_gid;
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
 
 	/* Calling sys_brk effectively mmaps the pages that we need for the bss and break
 	   sections */
diff -u --recursive --new-file v1.1.54/linux/fs/ext/dir.c linux/fs/ext/dir.c
--- v1.1.54/linux/fs/ext/dir.c	Sun Oct  9 12:00:25 1994
+++ linux/fs/ext/dir.c	Wed Oct 19 10:23:03 1994
@@ -20,6 +20,9 @@
 #include <linux/ext_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int ext_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
 	return -EISDIR;
@@ -65,6 +68,7 @@
 	struct dirent * dirent, int count)
 {
 	unsigned int i;
+	unsigned int ret;
 	off_t offset;
 	char c;
 	struct buffer_head * bh;
@@ -74,15 +78,23 @@
 		return -EBADF;
 	if ((filp->f_pos & 7) != 0)
 		return -EBADF;
-	while (filp->f_pos < inode->i_size) {
+	ret = 0;
+	while (!ret && filp->f_pos < inode->i_size) {
 		offset = filp->f_pos & 1023;
 		bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
 		if (!bh) {
 			filp->f_pos += 1024-offset;
 			continue;
 		}
+		for (i = 0; i < 1024 && i < offset; ) {
+			de = (struct ext_dir_entry *) (bh->b_data + i);
+			if (!de->rec_len)
+				break;
+			i += de->rec_len;
+		}
+		offset = i;
 		de = (struct ext_dir_entry *) (offset + bh->b_data);
-		while (offset < 1024 && filp->f_pos < inode->i_size) {
+		while (!ret && offset < 1024 && filp->f_pos < inode->i_size) {
 			if (de->rec_len < 8 || de->rec_len % 8 != 0 ||
 			    de->rec_len < de->name_len + 8 ||
 			    (de->rec_len + (off_t) filp->f_pos - 1) / 1024 > ((off_t) filp->f_pos / 1024)) {
@@ -106,8 +118,8 @@
 					put_fs_long(de->inode,&dirent->d_ino);
 					put_fs_byte(0,i+dirent->d_name);
 					put_fs_word(i,&dirent->d_reclen);
-					brelse(bh);
-					return i;
+					ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
+					break;
 				}
 			}
 			de = (struct ext_dir_entry *) ((char *) de 
@@ -115,5 +127,5 @@
 		}
 		brelse(bh);
 	}
-	return 0;
+	return ret;
 }
diff -u --recursive --new-file v1.1.54/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v1.1.54/linux/fs/ext2/dir.c	Sun Aug 21 17:48:35 1994
+++ linux/fs/ext2/dir.c	Wed Oct 19 10:23:17 1994
@@ -22,6 +22,9 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int ext2_dir_read (struct inode * inode, struct file * filp,
 			    char * buf, int count)
 {
@@ -98,17 +101,21 @@
 			 struct dirent * dirent, int count)
 {
 	unsigned long offset, blk;
-	int i, num;
+	int i, num, stored, dlen;
 	struct buffer_head * bh, * tmp, * bha[16];
 	struct ext2_dir_entry * de;
 	struct super_block * sb;
-	int err;
-	
+	int err, version;
+
 	if (!inode || !S_ISDIR(inode->i_mode))
 		return -EBADF;
 	sb = inode->i_sb;
-	while (filp->f_pos < inode->i_size) {
-		offset = filp->f_pos & (sb->s_blocksize - 1);
+
+	stored = 0;
+	bh = NULL;
+	offset = filp->f_pos & (sb->s_blocksize - 1);
+
+	while (count > 0 && !stored && filp->f_pos < inode->i_size) {
 		blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb);
 		bh = ext2_bread (inode, blk, 0, &err);
 		if (!bh) {
@@ -135,39 +142,78 @@
 			}
 		}
 		
-		de = (struct ext2_dir_entry *) (offset + bh->b_data);
-		while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) {
+revalidate:
+		/* If the dir block has changed since the last call to
+		   readdir(2), then we might be pointing to an invalid dirent
+		   right now.  Scan from the start of the block to make
+		   sure. */
+		for (i = 0; i < sb->s_blocksize && i < offset; ) {
+			de = (struct ext2_dir_entry *) (bh->b_data + i);
+			/* It's too expensive to do a full dirent test
+			 * each time round this loop, but we do have
+			 * to test at least that it is non-zero.  A
+			 * failure will be detected in the dirent test
+			 * below. */
+			if (de->rec_len < EXT2_DIR_REC_LEN(1))
+				break;
+			i += de->rec_len;
+		}
+		offset = i;
+		filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset;
+		
+		while (count > 0 && filp->f_pos < inode->i_size 
+		       && offset < sb->s_blocksize) {
+			de = (struct ext2_dir_entry *) (bh->b_data + offset);
 			if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
 						   bh, offset)) {
+				/* On error, skip the f_pos to the next block. */
+				filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
+					      + sb->s_blocksize;
 				brelse (bh);
-				return 0;
+				return stored;
 			}
-			offset += de->rec_len;
-			filp->f_pos += de->rec_len;
 			if (de->inode) {
-				memcpy_tofs (dirent->d_name, de->name,
-					     de->name_len);
+				dlen = ROUND_UP(NAME_OFFSET(dirent) 
+						+ de->name_len + 1);
+				/* Old libc libraries always use a count of 1. */
+				if (count == 1 && !stored)
+					count = dlen;
+				if (count < dlen) {
+					count = 0;
+					break;
+				}
+
+				/* We might block in the next section
+                               * if the data destination is
+                               * currently swapped out.  So, use a
+                               * version stamp to detect whether or
+                               * not the directory has been modified
+                               * during the copy operation. */
+				version = inode->i_version;
+				i = de->name_len;
+				memcpy_tofs (dirent->d_name, de->name, i);
 				put_fs_long (de->inode, &dirent->d_ino);
-				put_fs_byte (0, de->name_len + dirent->d_name);
-				put_fs_word (de->name_len, &dirent->d_reclen);
+				put_fs_byte (0, dirent->d_name + i);
+				put_fs_word (i, &dirent->d_reclen);
+				put_fs_long (dlen, &dirent->d_off);
+				if (version != inode->i_version)
+					goto revalidate;
 				dcache_add(inode, de->name, de->name_len,
 						 de->inode);
-				i = de->name_len;
-				brelse (bh);
-				if (!IS_RDONLY(inode)) {
-					inode->i_atime = CURRENT_TIME;
-					inode->i_dirt = 1;
-				}
-				return i;
+
+				stored += dlen;
+				count -= dlen;
+				((char *) dirent) += dlen;
 			}
-			de = (struct ext2_dir_entry *) ((char *) de +
-							de->rec_len);
+			offset += de->rec_len;
+			filp->f_pos += de->rec_len;
 		}
+		offset = 0;
 		brelse (bh);
 	}
 	if (!IS_RDONLY(inode)) {
 		inode->i_atime = CURRENT_TIME;
 		inode->i_dirt = 1;
 	}
-	return 0;
+	return stored;
 }
diff -u --recursive --new-file v1.1.54/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v1.1.54/linux/fs/ext2/namei.c	Sun Aug 21 17:48:36 1994
+++ linux/fs/ext2/namei.c	Wed Oct 19 10:23:17 1994
@@ -318,6 +318,7 @@
 			 */
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			dir->i_dirt = 1;
+			dir->i_version = ++event;
 			mark_buffer_dirty(bh, 1);
 			*res_dir = de;
 			*err = 0;
@@ -923,8 +924,10 @@
 
 	goto start_up;
 try_again:
-	if (new_bh && new_de)
+	if (new_bh && new_de) {
 		ext2_delete_entry(new_de, new_bh);
+		new_dir->i_version = ++event;
+	}
 	brelse (old_bh);
 	brelse (new_bh);
 	brelse (dir_bh);
@@ -1002,6 +1005,7 @@
 					 &retval);
 	if (!new_bh)
 		goto end_rename;
+	new_dir->i_version = ++event;
 	/*
 	 * sanity checking before doing the rename - avoid races
 	 */
@@ -1015,7 +1019,6 @@
 	 * ok, that's it
 	 */
 	new_de->inode = old_inode->i_ino;
-	new_dir->i_version = ++event;
 	dcache_add(new_dir, new_de->name, new_de->name_len, new_de->inode);
 	retval = ext2_delete_entry (old_de, old_bh);
 	if (retval == -ENOENT)
diff -u --recursive --new-file v1.1.54/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v1.1.54/linux/fs/hpfs/hpfs_fs.c	Sun Aug 21 17:48:36 1994
+++ linux/fs/hpfs/hpfs_fs.c	Wed Oct 19 10:23:18 1994
@@ -117,6 +117,9 @@
 
 /* notation */
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 #define little_ushort(x) (*(unsigned short *) &(x))
 typedef void nonconst;
 
@@ -1345,13 +1348,13 @@
 	case 0:
 		write_one_dirent(dirent, ".", 1, inode->i_ino, lc);
 		filp->f_pos = -1;
-		return 1;
+		return ROUND_UP(NAME_OFFSET(dirent) + 2);
 
 	case -1:
 		write_one_dirent(dirent, "..", 2,
 				 inode->i_hpfs_parent_dir, lc);
 		filp->f_pos = 1;
-		return 2;
+		return ROUND_UP(NAME_OFFSET(dirent) + 3);
 
 	case -2:
 		return 0;
@@ -1371,7 +1374,7 @@
 		write_one_dirent(dirent, de->name, namelen, ino, lc);
 		brelse4(&qbh);
 
-		return namelen;
+		return ROUND_UP(NAME_OFFSET(dirent) + namelen + 1);
 	}
 }
 
diff -u --recursive --new-file v1.1.54/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v1.1.54/linux/fs/isofs/dir.c	Sun Aug  7 03:30:41 1994
+++ linux/fs/isofs/dir.c	Wed Oct 19 10:23:18 1994
@@ -22,6 +22,9 @@
 #include <linux/sched.h>
 #include <linux/locks.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
 
 static struct file_operations isofs_dir_operations = {
@@ -228,7 +231,7 @@
 			put_fs_byte(0,i+dirent->d_name);
 			put_fs_word(i,&dirent->d_reclen);
 			brelse(bh);
-			return i;
+			return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
 		}
 	      }
 	/* We go here for any condition we cannot handle.  We also drop through
diff -u --recursive --new-file v1.1.54/linux/fs/minix/dir.c linux/fs/minix/dir.c
--- v1.1.54/linux/fs/minix/dir.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/minix/dir.c	Wed Oct 19 10:23:18 1994
@@ -13,6 +13,9 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int minix_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
 	return -EISDIR;
@@ -57,7 +60,8 @@
 static int minix_readdir(struct inode * inode, struct file * filp,
 	struct dirent * dirent, int count)
 {
-	unsigned int offset,i;
+	unsigned int offset,i,ret;
+	int version;
 	char c;
 	struct buffer_head * bh;
 	struct minix_dir_entry * de;
@@ -68,17 +72,19 @@
 	info = &inode->i_sb->u.minix_sb;
 	if (filp->f_pos & (info->s_dirsize - 1))
 		return -EBADF;
-	while (filp->f_pos < inode->i_size) {
+	ret = 0;
+	while (!ret && filp->f_pos < inode->i_size) {
 		offset = filp->f_pos & 1023;
 		bh = minix_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0);
 		if (!bh) {
 			filp->f_pos += 1024-offset;
 			continue;
 		}
-		while (offset < 1024 && filp->f_pos < inode->i_size) {
+		while (!ret && offset < 1024 && filp->f_pos < inode->i_size) {
 			de = (struct minix_dir_entry *) (offset + bh->b_data);
 			offset += info->s_dirsize;
 			filp->f_pos += info->s_dirsize;
+retry:
 			if (de->inode) {
 				for (i = 0; i < info->s_namelen; i++)
 					if ((c = de->name[i]) != 0)
@@ -86,15 +92,17 @@
 					else
 						break;
 				if (i) {
+					version = inode->i_version;
 					put_fs_long(de->inode,&dirent->d_ino);
 					put_fs_byte(0,i+dirent->d_name);
 					put_fs_word(i,&dirent->d_reclen);
-					brelse(bh);
-					return i;
+					if (version != inode->i_version)
+						goto retry;
+					ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
 				}
 			}
 		}
 		brelse(bh);
 	}
-	return 0;
+	return ret;
 }
diff -u --recursive --new-file v1.1.54/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v1.1.54/linux/fs/minix/namei.c	Mon Aug 15 11:47:10 1994
+++ linux/fs/minix/namei.c	Wed Oct 19 10:23:18 1994
@@ -195,6 +195,7 @@
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			for (i = 0; i < info->s_namelen ; i++)
 				de->name[i] = (i < namelen) ? name[i] : 0;
+			dir->i_version = ++event;
 			mark_buffer_dirty(bh, 1);
 			*res_dir = de;
 			break;
@@ -470,11 +471,12 @@
 	if (inode->i_nlink != 2)
 		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
 	de->inode = 0;
+	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	inode->i_nlink=0;
 	inode->i_dirt=1;
-	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	dir->i_nlink--;
 	dir->i_dirt=1;
 	retval = 0;
 end_rmdir:
@@ -523,6 +525,7 @@
 		inode->i_nlink=1;
 	}
 	de->inode = 0;
+	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_dirt = 1;
@@ -768,8 +771,10 @@
 	new_de->inode = old_inode->i_ino;
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
 	old_dir->i_dirt = 1;
+	old_dir->i_version = ++event;
 	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
 	new_dir->i_dirt = 1;
+	new_dir->i_version = ++event;
 	if (new_inode) {
 		new_inode->i_nlink--;
 		new_inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v1.1.54/linux/fs/msdos/dir.c linux/fs/msdos/dir.c
--- v1.1.54/linux/fs/msdos/dir.c	Wed Aug 31 10:14:11 1994
+++ linux/fs/msdos/dir.c	Wed Oct 19 10:23:18 1994
@@ -14,7 +14,10 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
 
+
 static int msdos_dir_read(struct inode * inode,struct file * filp, char * buf,int count)
 {
 	return -EISDIR;
@@ -73,7 +76,7 @@
 			put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
 			put_fs_byte(0,dirent->d_name+i);
 			put_fs_word(i,&dirent->d_reclen);
-			return i;
+			return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
 		}
 	}
 	if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT;
@@ -110,7 +113,7 @@
 				memcpy_tofs(dirent->d_name,bufname,i+1);
 				put_fs_word(i,&dirent->d_reclen);
 				brelse(bh);
-				return i;
+				return ROUND_UP(NAME_OFFSET(dirent) + i + 1);
 			}
 		}
 	}
diff -u --recursive --new-file v1.1.54/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v1.1.54/linux/fs/nfs/dir.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/nfs/dir.c	Wed Oct 19 10:23:18 1994
@@ -18,6 +18,9 @@
 
 #include <asm/segment.h>	/* for fs functions */
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int nfs_dir_read(struct inode *, struct file *filp, char *buf,
 			int count);
 static int nfs_readdir(struct inode *, struct file *, struct dirent *, int);
@@ -153,7 +156,7 @@
 		put_fs_long(entry->fileid, &dirent->d_ino);
 		put_fs_word(i, &dirent->d_reclen);
 		filp->f_pos = entry->cookie;
-		return i;
+		return ROUND_UP(NAME_OFFSET(dirent)+i+1);
 	}
 	return 0;
 }
diff -u --recursive --new-file v1.1.54/linux/fs/proc/link.c linux/fs/proc/link.c
--- v1.1.54/linux/fs/proc/link.c	Thu Oct 20 09:37:35 1994
+++ linux/fs/proc/link.c	Thu Oct 20 09:54:33 1994
@@ -92,7 +92,8 @@
 
 	new_f->f_count++;
 	current->files->fd[fd] = new_f;
-	f->f_count--;
+	if (!--f->f_count)
+		iput(f->f_inode);
 	return 0;
 }
 
diff -u --recursive --new-file v1.1.54/linux/fs/read_write.c linux/fs/read_write.c
--- v1.1.54/linux/fs/read_write.c	Sun Aug 21 17:48:37 1994
+++ linux/fs/read_write.c	Wed Oct 19 10:23:18 1994
@@ -13,8 +13,14 @@
 #include <asm/segment.h>
 
 /*
- * Count is not yet used: but we'll probably support reading several entries
- * at once in the future. Use count=1 in the library for future expansions.
+ * Count is now a supported feature, but currently only the ext2fs
+ * uses it.  A count value of 1 is supported for compatibility with
+ * earlier libraries, but larger values are supported: count should
+ * indicate the total buffer space available for filling with dirents.
+ * The d_off entry in the dirents will then indicate the offset from
+ * each dirent to the next, and the return value will indicate the
+ * number of bytes written.  All dirents will be written at
+ * word-aligned addresses.  [sct Oct 1994]
  */
 asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
 {
@@ -62,8 +68,10 @@
 	}
 	if (tmp < 0)
 		return -EINVAL;
-	file->f_pos = tmp;
-	file->f_reada = 0;
+	if (tmp != file->f_pos) {
+		file->f_pos = tmp;
+		file->f_reada = 0;
+	}
 	return file->f_pos;
 }
 
diff -u --recursive --new-file v1.1.54/linux/fs/sysv/dir.c linux/fs/sysv/dir.c
--- v1.1.54/linux/fs/sysv/dir.c	Sun Aug 21 17:48:37 1994
+++ linux/fs/sysv/dir.c	Wed Oct 19 10:23:18 1994
@@ -20,6 +20,9 @@
 #include <linux/sysv_fs.h>
 #include <linux/stat.h>
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
 	return -EISDIR;
@@ -100,7 +103,7 @@
 					put_fs_byte(0,i+dirent->d_name);
 					put_fs_word(i,&dirent->d_reclen);
 					brelse(bh);
-					return i;
+					return ROUND_UP(NAME_OFFSET(dirent)+i+1);
 				}
 			}
 		}
diff -u --recursive --new-file v1.1.54/linux/fs/xiafs/dir.c linux/fs/xiafs/dir.c
--- v1.1.54/linux/fs/xiafs/dir.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/xiafs/dir.c	Wed Oct 19 10:23:19 1994
@@ -19,6 +19,9 @@
 
 #include "xiafs_mac.h"
 
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+3) & ~3)
+
 static int xiafs_dir_read(struct inode *, struct file *, char *, int);
 static int xiafs_readdir(struct inode *, struct file *, struct dirent *, int);
 
@@ -65,7 +68,7 @@
 static int xiafs_readdir(struct inode * inode, 
 		       struct file * filp, struct dirent * dirent, int count)
 {
-    u_int offset, i;
+    u_int offset, i,ret;
     struct buffer_head * bh;
     struct xiafs_direct * de;
 
@@ -73,15 +76,24 @@
         return -EBADF;
     if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
         return -EBADF;
-    while (filp->f_pos < inode->i_size) {
+    ret = 0;
+    while (!ret && filp->f_pos < inode->i_size) {
         offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
 	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
 	if (!bh) {
 	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
 	    continue;
 	}
+	for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
+	    de = (struct xiafs_direct *) (bh->b_data + i);
+	    if (!de->d_rec_len)
+		break;
+	    i += de->d_rec_len;
+	}
+	offset = i;
 	de = (struct xiafs_direct *) (offset + bh->b_data);
-	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
+	
+	while (!ret && offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
 	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
 		de->d_rec_len < 12 || 
 		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
@@ -100,12 +112,12 @@
 		put_fs_byte(0,i+dirent->d_name);
 		put_fs_long(de->d_ino,&dirent->d_ino);
 		put_fs_word(i,&dirent->d_reclen);
-		brelse(bh);
 		if (!IS_RDONLY (inode)) {
 		    inode->i_atime=CURRENT_TIME;		    
 		    inode->i_dirt=1;
 		}
-		return i;
+		ret = ROUND_UP(NAME_OFFSET(dirent)+i+1);
+		break;
 	    }
 	    de = (struct xiafs_direct *) (offset + bh->b_data);
 	}
diff -u --recursive --new-file v1.1.54/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v1.1.54/linux/include/linux/hdreg.h	Sun Oct  9 12:00:27 1994
+++ linux/include/linux/hdreg.h	Tue Oct 18 10:08:05 1994
@@ -71,7 +71,6 @@
 #define HDIO_SETUNMASKINTR	0x303
 #define HDIO_GETMULTCOUNT	0x304
 #define HDIO_SETMULTCOUNT	0x305
-#define HDIO_SETFEATURE  	0x306
 #define HDIO_GETIDENTITY 	0x307
 #endif
 
diff -u --recursive --new-file v1.1.54/linux/include/linux/tty.h linux/include/linux/tty.h
--- v1.1.54/linux/include/linux/tty.h	Thu Oct 20 09:37:36 1994
+++ linux/include/linux/tty.h	Tue Oct 18 10:07:59 1994
@@ -289,6 +289,7 @@
 extern void start_tty(struct tty_struct * tty);
 extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
 extern int tty_register_driver(struct tty_driver *driver);
+extern int tty_unregister_driver(struct tty_driver *driver);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 			     int buflen);
 
diff -u --recursive --new-file v1.1.54/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.1.54/linux/kernel/ksyms.c	Wed Aug 31 10:14:11 1994
+++ linux/kernel/ksyms.c	Tue Oct 18 10:08:05 1994
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/termios.h>
 #include <linux/tqueue.h>
+#include <linux/tty.h>
 #include <linux/serial.h>
 #ifdef CONFIG_INET
 #include <linux/netdevice.h>
@@ -91,6 +92,9 @@
 	X(unregister_chrdev),
 	X(register_blkdev),
 	X(unregister_blkdev),
+	X(tty_register_driver),
+	X(tty_unregister_driver),
+	X(tty_std_termios),
 
 	/* block device driver support */
 	X(block_read),
diff -u --recursive --new-file v1.1.54/linux/net/inet/tcp.c linux/net/inet/tcp.c
--- v1.1.54/linux/net/inet/tcp.c	Wed Oct  5 15:17:23 1994
+++ linux/net/inet/tcp.c	Wed Oct 19 10:44:34 1994
@@ -83,6 +83,7 @@
  *		Matt Dillon	:	Yet more small nasties remove from the TCP code
  *					(Be very nice to this man if tcp finally works 100%) 8)
  *		Alan Cox	:	BSD accept semantics. 
+ *	Peter De Schrijver	:	ENOTCONN check missing in tcp_sendto().
  *
  *
  * To Fix:
@@ -1221,15 +1222,17 @@
 {
 	if (flags & ~(MSG_OOB|MSG_DONTROUTE))
 		return -EINVAL;
-	if (addr_len < sizeof(*addr)) 
-		return(-EINVAL);
+	if (!tcp_connected(sk->state))
+		return -ENOTCONN;
+	if (addr_len < sizeof(*addr))
+		return -EINVAL;
 	if (addr->sin_family && addr->sin_family != AF_INET) 
-		return(-EINVAL);
+		return -EINVAL;
 	if (addr->sin_port != sk->dummy_th.dest) 
-		return(-EISCONN);
+		return -EISCONN;
 	if (addr->sin_addr.s_addr != sk->daddr) 
-		return(-EISCONN);
-	return(tcp_write(sk, from, len, nonblock, flags));
+		return -EISCONN;
+	return tcp_write(sk, from, len, nonblock, flags);
 }
 
 
@@ -2238,7 +2241,7 @@
 				/* The +1 is not needed because the FIN takes up seq
 				   is not read!!! */
 				if(skb->len > 0 && after(skb->h.th->seq + skb->len , sk->copied_seq))
-					need_reset = 1;
+					need_reset = 0;
 				kfree_skb(skb, FREE_READ);
 			}
 			if(sk->debug)
