diff -u --recursive --new-file v1.1.1/linux/CREDITS linux/CREDITS
--- v1.1.1/linux/CREDITS	Thu Apr  7 11:57:28 1994
+++ linux/CREDITS	Sun Apr 10 22:46:28 1994
@@ -351,6 +351,13 @@
 S: Syracuse, New York 13206
 S: USA
 
+N: Dirk Melchers
+E: dirk@merlin.nbg.sub.org
+D: 8 bit XT hard disk driver for OMTI5520
+S: Branderweg 4
+S: D-91058 Erlangen
+S: Germany
+
 N: Craig Metz
 E: cmetz@tjhsst.edu
 D: Some of PAS 16 mixer & PCM support
diff -u --recursive --new-file v1.1.1/linux/Makefile linux/Makefile
--- v1.1.1/linux/Makefile	Thu Apr  7 11:57:29 1994
+++ linux/Makefile	Fri Apr  8 08:57:19 1994
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 1
+SUBLEVEL = 2
 
 all:	Version zImage
 
@@ -9,7 +9,7 @@
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
 	  else echo sh; fi ; fi)
-ROOT	:= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
+TOPDIR	:= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 
 #
 # Make "config" the default target if there is no configuration file or
@@ -77,7 +77,7 @@
 LD	=ld
 LDFLAGS	=#-qmagic
 HOSTCC	=gcc
-CC	=gcc -D__KERNEL__ -I$(ROOT)/include
+CC	=gcc -D__KERNEL__ -I$(TOPDIR)/include
 MAKE	=make
 CPP	=$(CC) -E
 AR	=ar
diff -u --recursive --new-file v1.1.1/linux/README linux/README
--- v1.1.1/linux/README	Mon Mar 14 00:11:20 1994
+++ linux/README	Mon Apr 11 11:00:55 1994
@@ -81,9 +81,6 @@
 	  should probably answer 'n' to the questions for a "production"
 	  kernel. 
 
- - edit drivers/net/CONFIG to configure the networking parts of the
-   kernel.  The comments should hopefully clarify it all. 
-
  - Check the top Makefile for further site-dependent configuration
    (default SVGA mode etc). 
 
diff -u --recursive --new-file v1.1.1/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v1.1.1/linux/drivers/block/hd.c	Fri Jan 21 14:50:11 1994
+++ linux/drivers/block/hd.c	Mon Apr 11 13:44:13 1994
@@ -542,6 +542,12 @@
 			put_fs_long(hd[MINOR(inode->i_rdev)].start_sect,
 				(long *) &loc->start);
 			return 0;
+		case BLKRASET:
+			if(!suser())  return -EACCES;
+			if(!inode->i_rdev) return -EINVAL;
+			if(arg > 0xff) return -EINVAL;
+			read_ahead[MAJOR(inode->i_rdev)] = arg;
+			return 0;
          	case BLKGETSIZE:   /* Return device size */
 			if (!arg)  return -EINVAL;
 			err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
diff -u --recursive --new-file v1.1.1/linux/drivers/block/ramdisk.c linux/drivers/block/ramdisk.c
--- v1.1.1/linux/drivers/block/ramdisk.c	Wed Dec  1 14:44:15 1993
+++ linux/drivers/block/ramdisk.c	Mon Apr 11 13:44:13 1994
@@ -126,7 +126,7 @@
 	 */
 	for (tries = 0; tries < 1000; tries += 512) {
 		block = tries;
-		bh = breada(ROOT_DEV,block+1,block,block+2,-1);
+		bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0,  PAGE_SIZE);
 		if (!bh) {
 			printk("RAMDISK: I/O error while looking for super block!\n");
 			return;
@@ -154,7 +154,7 @@
 		cp = rd_start;
 		while (nblocks) {
 			if (nblocks > 2) 
-				bh = breada(ROOT_DEV, block, block+1, block+2, -1);
+			        bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0,  PAGE_SIZE);
 			else
 				bh = bread(ROOT_DEV, block, BLOCK_SIZE);
 			if (!bh) {
diff -u --recursive --new-file v1.1.1/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v1.1.1/linux/drivers/block/xd.c	Tue Apr  5 07:24:51 1994
+++ linux/drivers/block/xd.c	Mon Apr 11 13:44:12 1994
@@ -252,6 +252,12 @@
 					return (0);
 				}
 				break;
+			case BLKRASET:
+			  if(!suser())  return -EACCES;
+			  if(!inode->i_rdev) return -EINVAL;
+			  if(arg > 0xff) return -EINVAL;
+			  read_ahead[MAJOR(inode->i_rdev)] = arg;
+			  return 0;
 			case BLKGETSIZE:
 				if (arg) {
 					if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
diff -u --recursive --new-file v1.1.1/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.1/linux/drivers/char/keyboard.c	Thu Mar  3 08:05:22 1994
+++ linux/drivers/char/keyboard.c	Mon Apr 11 14:39:55 1994
@@ -85,7 +85,7 @@
 static int last_console = 0;		/* last used VC */
 static int dead_key_next = 0;
 static int shift_state = 0;
-static int npadch = -1;		        /* -1 or number assembled on pad */
+static int npadch = -1;			/* -1 or number assembled on pad */
 static unsigned char diacr = 0;
 static char rep = 0;			/* flag telling character repeat */
 struct kbd_struct kbd_table[NR_CONSOLES];
@@ -100,7 +100,7 @@
 typedef void (k_handfn)(unsigned char value, char up_flag);
 
 static k_handfn
-        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
+	do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 	do_meta, do_ascii, do_lock, do_lowercase;
 
 static k_hand key_handler[] = {
@@ -196,7 +196,7 @@
 {
 	unsigned char scancode;
 	static unsigned int prev_scancode = 0;   /* remember E0, E1 */
-	char up_flag;		                 /* 0 or 0200 */
+	char up_flag;				 /* 0 or 0200 */
 	char raw_mode;
 
 	pt_regs = (struct pt_regs *) int_pt_regs;
@@ -214,15 +214,15 @@
 		goto end_kbd_intr;
 	} else if (scancode == 0) {
 #ifdef KBD_REPORT_ERR
-	        printk("keyboard buffer overflow\n");
+		printk("keyboard buffer overflow\n");
 #endif
 		goto end_kbd_intr;
 	} else if (scancode == 0xff) {
 #ifdef KBD_REPORT_ERR
-	        printk("keyboard error\n");
+		printk("keyboard error\n");
 #endif
-	        prev_scancode = 0;
-	        goto end_kbd_intr;
+		prev_scancode = 0;
+		goto end_kbd_intr;
 	}
 	tty = TTY_TABLE(0);
  	kbd = kbd_table + fg_console;
@@ -242,7 +242,7 @@
  	 */
 	up_flag = (scancode & 0200);
  	scancode &= 0x7f;
-  
+
 	if (prev_scancode) {
 	  /*
 	   * usually it will be 0xe0, but a Pause key generates
@@ -294,7 +294,7 @@
 #endif
 	  goto end_kbd_intr;
  	}
-  
+
 	/*
 	 * At this point the variable `scancode' contains the keysym.
 	 * We keep track of the up/down status of the key, and
@@ -308,15 +308,15 @@
 		rep = 0;
 	} else
  		rep = set_bit(scancode, key_down);
-  
+
 	if (raw_mode)
-	        goto end_kbd_intr;
+		goto end_kbd_intr;
 
  	if (vc_kbd_mode(kbd, VC_MEDIUMRAW)) {
  		put_queue(scancode + up_flag);
 		goto end_kbd_intr;
  	}
-  
+
  	/*
 	 * Small change in philosophy: earlier we defined repetition by
 	 *	 rep = scancode == prev_keysym;
@@ -330,7 +330,7 @@
  	 *  characters get echoed locally. This makes key repeat usable
  	 *  with slow applications and under heavy loads.
 	 */
-	if (!rep || 
+	if (!rep ||
 	    (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 	     (L_ECHO(tty) || (EMPTY(&tty->secondary) && EMPTY(&tty->read_q)))))
 	{
@@ -499,7 +499,7 @@
 
 static void compose(void)
 {
-        dead_key_next = 1;
+	dead_key_next = 1;
 }
 
 static void do_spec(unsigned char value, char up_flag)
@@ -523,22 +523,22 @@
 
 static void do_lowercase(unsigned char value, char up_flag)
 {
-        printk("keyboard.c: do_lowercase was called - impossible\n");
+	printk("keyboard.c: do_lowercase was called - impossible\n");
 }
-  
+
 static void do_self(unsigned char value, char up_flag)
 {
 	if (up_flag)
 		return;		/* no action, if this is a key release */
 
-        if (diacr)
-                value = handle_diacr(value);
+	if (diacr)
+		value = handle_diacr(value);
 
-        if (dead_key_next) {
-                dead_key_next = 0;
-                diacr = value;
-                return;
-        }
+	if (dead_key_next) {
+		dead_key_next = 0;
+		diacr = value;
+		return;
+	}
 
 	put_queue(value);
 }
@@ -549,7 +549,7 @@
 #define A_TILDE  '~'
 #define A_DIAER  '"'
 static unsigned char ret_diacr[] =
-        {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
+	{A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 
 /* If a dead key pressed twice, output a character corresponding to it,	*/
 /* otherwise just remember the dead key.				*/
@@ -559,12 +559,12 @@
 	if (up_flag)
 		return;
 
-        value = ret_diacr[value];
-        if (diacr == value) {   /* pressed twice */
-                diacr = 0;
-                put_queue(value);
-                return;
-        }
+	value = ret_diacr[value];
+	if (diacr == value) {   /* pressed twice */
+		diacr = 0;
+		put_queue(value);
+		return;
+	}
 	diacr = value;
 }
 
@@ -574,19 +574,20 @@
 
 unsigned char handle_diacr(unsigned char ch)
 {
-        int d = diacr;
-        int i;
+	int d = diacr;
+	int i;
 
-        diacr = 0;
-        if (ch == ' ')
-                return d;
-
-        for (i = 0; i < accent_table_size; i++)
-          if(accent_table[i].diacr == d && accent_table[i].base == ch)
-            return accent_table[i].result;
+	diacr = 0;
+	if (ch == ' ')
+		return d;
+
+	for (i = 0; i < accent_table_size; i++) {
+		if (accent_table[i].diacr == d && accent_table[i].base == ch)
+			return accent_table[i].result;
+	}
 
-        put_queue(d);
-        return ch;
+	put_queue(d);
+	return ch;
 }
 
 static void do_cons(unsigned char value, char up_flag)
@@ -601,9 +602,9 @@
 	if (up_flag)
 		return;
 	if (value < SIZE(func_table))
-	        puts_queue(func_table[value]);
+		puts_queue(func_table[value]);
 	else
-	        printk("do_fn called with value=%d\n", value);
+		printk("do_fn called with value=%d\n", value);
 }
 
 static void do_pad(unsigned char value, char up_flag)
@@ -686,7 +687,7 @@
 	}
 
 	if (up_flag) {
-	        /* handle the case that two shift or control
+		/* handle the case that two shift or control
 		   keys are depressed simultaneously */
 		if (k_down[value])
 			k_down[value]--;
@@ -709,9 +710,9 @@
    recompute k_down[] and shift_state from key_down[] */
 void compute_shiftstate(void)
 {
-        int i, j, k, sym, val;
+	int i, j, k, sym, val;
 
-        shift_state = 0;
+	shift_state = 0;
 	for(i=0; i < SIZE(k_down); i++)
 	  k_down[i] = 0;
 
@@ -725,7 +726,7 @@
 		  val = KVAL(sym);
 		  k_down[val]++;
 		  shift_state |= (1<<val);
-	        }
+		}
 	      }
 	  }
 }
@@ -748,9 +749,9 @@
 		return;
 
 	if (npadch == -1)
-	        npadch = value;
+		npadch = value;
 	else
-	        npadch = (npadch * 10 + value) % 1000;
+		npadch = (npadch * 10 + value) % 1000;
 }
 
 static void do_lock(unsigned char value, char up_flag)
diff -u --recursive --new-file v1.1.1/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v1.1.1/linux/drivers/net/3c503.c	Sun Mar  6 16:12:04 1994
+++ linux/drivers/net/3c503.c	Mon Apr 11 11:30:19 1994
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/string.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
diff -u --recursive --new-file v1.1.1/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v1.1.1/linux/drivers/net/3c507.c	Sun Mar  6 16:12:05 1994
+++ linux/drivers/net/3c507.c	Mon Apr 11 11:30:19 1994
@@ -44,12 +44,12 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
+#include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <errno.h>
-#include <memory.h>
+#include <linux/errno.h>
 
 #include "dev.h"
 #include "eth.h"
diff -u --recursive --new-file v1.1.1/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.1.1/linux/drivers/net/depca.c	Fri Mar  4 09:20:19 1994
+++ linux/drivers/net/depca.c	Mon Apr 11 13:25:49 1994
@@ -1,24 +1,34 @@
-/*  depca.c: A DIGITAL DEPCA ethernet driver for linux.
+/*  depca.c: A DIGITAL DEPCA  & EtherWORKS ethernet driver for linux.
 
     Written 1994 by David C. Davies.
 
-    Copyright 1994 David C. Davies and United States Government as
-    represented by the Director, National Security Agency.  This software
-    may be used and distributed according to the terms of the GNU Public
-    License, incorporated herein by reference.
 
+                      Copyright 1994 David C. Davies
+		                   and 
+			 United States Government
+	 (as represented by the Director, National Security Agency).  
+
+
+    This software may be used and distributed according to the terms of
+    the GNU Public License, incorporated herein by reference.
+
     This driver is written for the Digital Equipment Corporation series
-    of DEPCA ethernet cards:
+    of DEPCA and EtherWORKS ethernet cards:
 
-    	DE100 DEPCA
-	DE200 DEPCA Turbo
-	DE202 DEPCA Turbo (TP BNC)
-	DE210 DEPCA
+        DEPCA       (the original)
+    	DE100
+	DE200 Turbo
+	DE201 Turbo
+	DE202 Turbo (TP BNC)
+	DE210
 
-    The driver has been tested on DE100 and DE20x cards in a relatively busy 
-    network.
+    The  driver has been tested on DE100, DE200 and DE202 cards  in  a
+    relatively busy network.
 
-    The author may be reached as davies@wanton.enet.dec.com or
+    This driver  will  not work  for the DE203,  DE204  and DE205 series  of
+    cards, since they have a new custom ASIC in place of the AMD LANCE chip.
+
+    The author may be reached as davies@wanton.lkg.dec.com or
     Digital Equipment Corporation, 146 Main Street, Maynard MA 01754.
 
     =========================================================================
@@ -49,10 +59,20 @@
     the   filter bit   positions  correctly.  Hash   filtering  is  not  yet
     implemented in the current driver set.
 
-    The  DE200 series boards have   on-board 64kB RAM  for  use as a  shared
-    memory network buffer. Only  the DE100 cards  make  use of a  2kB buffer
-    mode  which has not  been implemented in  this driver (only the 32kB and
-    64kB modes are supported).
+    The original DEPCA  card requires that  the ethernet ROM address counter
+    be enabled to count and has an 8 bit NICSR.  The ROM counter enabling is
+    only done when  a 0x08 is read as  the first address octet  (to minimise
+    the chances of  writing over some other hardware's  I/O  register).  The
+    size of the NICSR is tested by a word read: if  both bytes are the same,
+    the register  is 8 bits wide.   Also,  there is a   maximum of only 48kB
+    network  RAM for   this card.  My   thanks  to Torbjorn Lindh   for help
+    debugging all this  (and holding  my  feet to the   fire until I got  it
+    right).
+
+    The DE200  series  boards have  on-board 64kB  RAM for  use  as a shared
+    memory network  buffer. Only the DE100  cards make use  of a  2kB buffer
+    mode which has not  been implemented in  this driver (only the 32kB  and
+    64kB modes are supported [16kB/48kB for the original DEPCA]).
 
     At the  most only 2 DEPCA  cards can be supported  because there is only
     provision for two I/O base addresses on the cards (0x300 and 0x200). The
@@ -73,26 +93,20 @@
     this unambiguously at the moment, since there is nothing on the cards to
     tie I/O and memory information together.
 
-    I   am unable to test    2 DEPCAs together for   now,   so this code  is
+    I am unable  to  test  2 cards   together for now,    so this  code   is
     unchecked. All reports, good or bad, are welcome.
 
     ************************************************************************
 
-    The board IRQ  setting must be  at  an unused  IRQ  which is auto-probed
-    using   Donald Becker's   autoprobe   routines. DE100   board IRQs   are
-    {2,3,4,5,7}, whereas  the DE200 is at  {5,9,10,11,15}. Note that IRQ2 is
+    The board IRQ   setting must be  at an  unused IRQ which  is auto-probed
+    using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
+    {2,3,4,5,7}, whereas the  DE200 is at {5,9,10,11,15}.  Note that IRQ2 is
     really IRQ9 in machines with 16 IRQ lines.
 
     No 16MB memory  limitation should exist with this  driver as DMA is  not
     used and the common memory area is in low memory on the network card (my
     current system has 20MB and I've not had problems yet).
 
-    The DE203,  DE204  and DE205 cards  may  also work  with this driver  (I
-    haven't tested  them so I don't  know). If you have  one of these cards,
-    place the name in the DEPCA_SIGNATURE string  around line 160, recompile
-    the kernel and reboot. Check if the card  is recognised and works - mail
-    me if so, so that I can add it into the list of supported cards!
-
     TO DO:
     ------
 
@@ -103,16 +117,21 @@
 
     Version   Date        Description
   
-      0.1   25-jan-94     Initial writing
-      0.2   27-jan-94     Added LANCE TX buffer chaining
-      0.3    1-feb-94     Added multiple DEPCA support
-      0.31   4-feb-94     Added DE202 recognition
+      0.1   25-jan-94     Initial writing.
+      0.2   27-jan-94     Added LANCE TX buffer chaining.
+      0.3    1-feb-94     Added multiple DEPCA support.
+      0.31   4-feb-94     Added DE202 recognition.
       0.32  19-feb-94     Tidy up. Improve multi-DEPCA support.
+      0.33  25-feb-94     Fix DEPCA ethernet ROM counter enable.
+                          Add jabber packet fix from murf@perftech.com
+			  and becker@super.org
+      0.34   7-mar-94     Fix DEPCA max network memory RAM & NICSR access.
+      0.35   8-mar-94     Added DE201 recognition.
 
     =========================================================================
 */
 
-static char *version = "depca.c:v0.32 2/19/94 davies@wanton.enet.dec.com\n";
+static char *version = "depca.c:v0.35 3/8/94 davies@wanton.lkg.dec.com\n";
 
 #include <stdarg.h>
 #include <linux/config.h>
@@ -129,7 +148,7 @@
 #include <asm/dma.h>
 
 #include "dev.h"
-#include "iow.h"
+#include "iow.h"                    /* left in for pl13/14 compatibility... */
 #include "eth.h"
 #include "skbuff.h"
 #include "arp.h"
@@ -155,7 +174,7 @@
 #endif
 
 #ifndef DEPCA_SIGNATURE
-#define DEPCA_SIGNATURE {"DEPCA","DE100","DE200","DE202","DE210",""}
+#define DEPCA_SIGNATURE {"DEPCA","DE100","DE200","DE201","DE202","DE210",""}
 #define DEPCA_NAME_LENGTH 8
 #endif
 
@@ -241,7 +260,7 @@
     int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
     int dma;
     struct enet_statistics stats;
-    char old_depca;
+    char depca_na;              /* NICSR access width: 0=>byte, 1=>word */
     short ringSize;             /* ring size based on available memory */
     short rmask;                /* modulus mask based on ring size */
     long rlen;                  /* log2(ringSize) for the descriptors */
@@ -275,6 +294,7 @@
 static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table);
 #endif
 
+static int depca_na;
 static int num_depcas = 0, num_eth = 0;;
 
 /*
@@ -284,6 +304,21 @@
     outw(CSR0, DEPCA_ADDR);\
     outw(STOP, DEPCA_DATA)
 
+#define GET_NICSR(a,b) \
+    if (depca_na) { \
+      (a) = inw((b)); \
+    } else { \
+      (a) = inb((b)); \
+    }
+
+#define PUT_NICSR(a,b) \
+    if (depca_na) { \
+      outw((a), (b)); \
+    } else { \
+      outb((a), (b)); \
+    }
+
+
 
 
 int depca_probe(struct device *dev)
@@ -294,7 +329,10 @@
     struct device *eth0 = (struct device *) NULL;
 
     if (base_addr > 0x1ff) {	      /* Check a single specified location. */
-		status = depca_probe1(dev, base_addr);
+      status = -ENODEV;
+      if (DevicePresent(base_addr) == 0) { /* Is DEPCA really here? */
+	status = depca_probe1(dev, base_addr);
+      }
     } else if (base_addr > 0) {	      /* Don't probe at all. */
 		status = -ENXIO;
     } else {                          /* First probe for the DEPCA test */
@@ -308,7 +346,7 @@
 	if (check_region(ioaddr, DEPCA_TOTAL_SIZE))
 	    continue;
 #endif
-	if (DevicePresent(DEPCA_PROM) == 0) {
+	if (DevicePresent(ioaddr) == 0) {
 	  if (num_depcas > 0) {        /* only gets here in autoprobe */
 
 	    /*
@@ -370,17 +408,18 @@
     int i,j, status=0;
     unsigned long mem_start, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
     char *name=(char *)NULL;
-    int nicsr, offset;
+    unsigned int nicsr, offset, netRAM;
 
 
     /*
-    ** Stop the DEPCA. Enable the DBR ROM. Disable interrupts and remote boot
+    ** Stop the DEPCA. Enable the DBR ROM and the ethernet ROM address counter
+    ** (for the really old DEPCAs). Disable interrupts and remote boot.
     */
     STOP_DEPCA;
 
-    nicsr = inw(DEPCA_NICSR);
-    nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
-    outw(nicsr, DEPCA_NICSR);
+    GET_NICSR(nicsr, DEPCA_NICSR);
+    nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | AAC | IM);
+    PUT_NICSR(nicsr, DEPCA_NICSR);
 
     if (inw(DEPCA_DATA) == STOP) {
 
@@ -438,18 +477,27 @@
 	snarf_region(ioaddr, DEPCA_TOTAL_SIZE);
 #endif
 
+	/*
+	** Set up the maximum amount of network RAM(kB)
+	*/
+	if (strstr(name,"DEPCA")==(char *)NULL) {
+	  netRAM=64;
+	} else {
+	  netRAM=48;
+	}
+
 	/* 
 	 ** Determine the base address for the DEPCA RAM from the NI-CSR
 	 ** and make up a DEPCA-specific-data structure. 
         */
 
 	if (nicsr & BUF) {
-	  offset = 0x8000;              /* 32kbyte RAM */
+	  offset = 0x8000;              /* 32kbyte RAM offset*/
 	  nicsr &= ~BS;                 /* DEPCA RAM in top 32k */
-	  printk(",\n      with 32kB RAM");
+	  printk(",\n      with %dkB RAM", netRAM-(offset >> 10));
 	} else {
-	  offset = 0x0000;              /* 64kbyte RAM */
-	  printk(",\n      with 64kB RAM");
+	  offset = 0x0000;              /* 64k/48k bytes RAM */
+	  printk(",\n      with %dkB RAM", netRAM);
 	}
 
 	mem_start += offset;
@@ -459,17 +507,19 @@
 	 ** Enable the shadow RAM.
 	*/
 	nicsr |= SHE;
-	outw(nicsr, DEPCA_NICSR);
+	PUT_NICSR(nicsr, DEPCA_NICSR);
  
 	/*
 	** Calculate the ring size based on the available RAM
 	** found above. Allocate an equal number of buffers, each
-	** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx. Make sure
+	** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx, allowing one
+	** descriptor entry (8 bytes) for each buffer. Make sure
 	** that this ring size is <= RING_SIZE. The ring size must be
 	** a power of 2.
 	*/
 
-	j = ((0x10000 - offset) / PKT_BUF_SZ) >> 1;
+	j = (((netRAM << 10) - offset - sizeof(struct depca_private)) / 
+	                                               (PKT_BUF_SZ + 8)) >> 1;
 	for (i=0;j>1;i++) {
 	  j >>= 1;
 	}
@@ -549,10 +599,15 @@
 	LoadCSRs(dev);
 
 	/*
+	** Store the NICSR width for this DEPCA
+	*/
+	lp->depca_na = depca_na;
+
+	/*
 	** Enable DEPCA board interrupts for autoprobing
 	*/
 	nicsr = ((nicsr & ~IM)|IEN);
-	outw(nicsr, DEPCA_NICSR);
+	PUT_NICSR(nicsr, DEPCA_NICSR);
 
 	/* The DMA channel may be passed in on this parameter. */
 	dev->dma = 0;
@@ -646,8 +701,9 @@
     /*
     ** Stop the DEPCA & get the board status information.  
     */
+    depca_na=lp->depca_na;
     STOP_DEPCA;
-    nicsr = inw(DEPCA_NICSR);
+    GET_NICSR(nicsr, DEPCA_NICSR);
 
     /* 
     ** Re-initialize the DEPCA... 
@@ -698,7 +754,7 @@
     ** Enable DEPCA board interrupts
     */
     nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN);
-    outw(nicsr, DEPCA_NICSR);
+    PUT_NICSR(nicsr, DEPCA_NICSR);
     outw(CSR0,DEPCA_ADDR);
 
     dev->tbusy = 0;                         
@@ -709,7 +765,8 @@
 
     if (depca_debug > 1){
       printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA));
-      printk("nicsr: 0x%4.4x\n",inw(DEPCA_NICSR));
+      GET_NICSR(nicsr, DEPCA_NICSR);
+      printk("nicsr: 0x%4.4x\n",nicsr);
     }
 
     return 0;			          /* Always succeed */
@@ -760,7 +817,7 @@
     /* Transmitter timeout, serious problems. */
     if (dev->tbusy) {
       int tickssofar = jiffies - dev->trans_start;
-      if (tickssofar < 5) {
+      if (tickssofar < 10) {
 	status = -1;
       } else {
 	STOP_DEPCA;
@@ -921,6 +978,7 @@
     } else {
       lp = (struct depca_private *)dev->priv;
       ioaddr = dev->base_addr;
+      depca_na = lp->depca_na;
     }
 
     if (dev->interrupt)
@@ -929,9 +987,9 @@
     dev->interrupt = MASK_INTERRUPTS;
 
     /* mask the DEPCA board interrupts and turn on the LED */
-    nicsr = inw(DEPCA_NICSR);
+    GET_NICSR(nicsr, DEPCA_NICSR);
     nicsr |= (IM|LED);
-    outw(nicsr, DEPCA_NICSR);
+    PUT_NICSR(nicsr, DEPCA_NICSR);
 
     outw(CSR0, DEPCA_ADDR);
     csr0 = inw(DEPCA_DATA);
@@ -961,7 +1019,7 @@
 
     /* Unmask the DEPCA board interrupts and turn off the LED */
     nicsr = (nicsr & ~IM & ~LED);
-    outw(nicsr, DEPCA_NICSR);
+    PUT_NICSR(nicsr, DEPCA_NICSR);
 
     dev->interrupt = UNMASK_INTERRUPTS;
     return;
@@ -976,9 +1034,32 @@
     /* If we own the next entry, it's a new packet. Send it up. */
     for (; lp->rx_ring[entry].base >= 0; entry = (++lp->cur_rx) & lp->rmask) {
 	int status = lp->rx_ring[entry].base >> 16 ;
+	int chained;
 
-	if (status & R_ERR) {	       /* There was an error. */
-	    lp->stats.rx_errors++;     /* Update the error stats. */
+	/*
+	** There is a 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 one correctly
+	** noting the error.
+	*/
+
+	/* Check for a chaining buffer */
+	chained = 0;
+	if (status == R_STP) { 
+	  chained = 1;
+
+	  /* 
+	  ** Wait for next buffer to complete to check for errors. This
+	  ** is slow but infrequent and allows for correct hardware buffer
+	  ** chaining (whilst defeating the chaining's purpose).
+	  */
+	  while ((status=(lp->rx_ring[(entry+1)&lp->rmask].base >> 16)) < 0);
+
+	  /* NB: 'status' now comes from the buffer following 'entry'. */
+	}
+	  
+	if (status & R_ERR) {	               /* There was an error. */
+	    lp->stats.rx_errors++;             /* Update the error stats. */
 	    if (status & R_FRAM) lp->stats.rx_frame_errors++;
 	    if (status & R_OFLO) lp->stats.rx_over_errors++;
 	    if (status & R_CRC)  lp->stats.rx_crc_errors++;
@@ -1020,6 +1101,10 @@
 
 	/* turn over ownership of the current entry back to the LANCE */
 	lp->rx_ring[entry].base |= R_OWN;
+	if (chained && (status & R_ERR)) {          /* next entry also bad */
+	  entry = (++lp->cur_rx) & lp->rmask;
+	  lp->rx_ring[entry].base |= R_OWN;
+	}
     }
 
     /* 
@@ -1277,7 +1362,15 @@
 
 /*
 ** Look for a special sequence in the Ethernet station address PROM that
-** is common across all DEPCA products.
+** is common across all DEPCA products. Note that the original DEPCA needs
+** its ROM address counter to be initialized and enabled. Only enable
+** if the first address octet is a 0x08 - this minimises the chances of
+** messing around with some other hardware, but it assumes that this DEPCA
+** card initialized itself correctly. It also assumes that all past and
+** future DEPCA/EtherWORKS cards will have ethernet addresses beginning with
+** a 0x08. The choice of byte or word addressing is made here based on whether
+** word read of the NICSR returns two identical lower and upper bytes: if so
+** the register is 8 bits wide.
 */
 
 static int DevicePresent(short ioaddr)
@@ -1285,9 +1378,40 @@
   static short fp=1,sigLength=0;
   static char devSig[] = PROBE_SEQUENCE;
   char data;
-  int i, j, status = 0;
+  unsigned char LSB,MSB;
+  int i, j, nicsr, status = 0;
   static char asc2hex(char value);
 
+/*
+** Initialize the counter on a DEPCA card. Two reads to ensure DEPCA ethernet
+** address counter is a) cleared and b) the correct data read.
+*/
+  data = inb(DEPCA_PROM);                /* clear counter */
+  data = inb(DEPCA_PROM);                /* read data */
+
+/*
+** Determine whether a byte or word access should be made on the NICSR.
+** Since the I/O 'functions' are actually in-line code, the choice not to use
+** pointers to functions vs. just set a conditional, is made for us. This code
+** assumes that the NICSR has an asymmetric bit pattern already in it.
+*/
+  nicsr = inw(DEPCA_NICSR);
+  LSB = nicsr & 0xff;
+  MSB = (((unsigned) nicsr) >> 8) & 0xff;
+  if (MSB == LSB) {
+    depca_na = 0;        /* byte accesses */
+  } else {
+    depca_na = 1;        /* word accesses */
+  }
+
+/*
+** Enable counter
+*/
+  if (data == 0x08) {
+    nicsr |= AAC;
+    PUT_NICSR(nicsr, DEPCA_NICSR);
+  }
+  
 /* 
 ** Convert the ascii signature to a hex equivalent & pack in place 
 */
@@ -1318,7 +1442,7 @@
 */
   if (!status) {
     for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
-      data = inb(ioaddr);
+      data = inb(DEPCA_PROM);
       if (devSig[j] == data) {    /* track signature */
 	j++;
       } else {                    /* lost signature; begin search again */
diff -u --recursive --new-file v1.1.1/linux/drivers/net/depca.h linux/drivers/net/depca.h
--- v1.1.1/linux/drivers/net/depca.h	Tue Feb 22 08:35:15 1994
+++ linux/drivers/net/depca.h	Mon Apr 11 13:18:36 1994
@@ -34,7 +34,7 @@
 #define BS       	0x0040  /* Bank Select */
 #define BUF      	0x0020	/* BUFfer size (1->32k, 0->64k) */
 #define RBE      	0x0010	/* Remote Boot Enable (1->net boot) */
-#define AAC      	0x0008  /* for DEPCA family compatability */
+#define AAC      	0x0008  /* Address ROM Address Counter (1->enable) */
 #define IM       	0x0004	/* Interrupt Mask (1->mask) */
 #define IEN      	0x0002	/* Interrupt tristate ENable (1->enable) */
 #define LED      	0x0001	/* LED control */
diff -u --recursive --new-file v1.1.1/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v1.1.1/linux/drivers/net/eexpress.c	Sun Mar  6 16:12:05 1994
+++ linux/drivers/net/eexpress.c	Mon Apr 11 11:30:20 1994
@@ -42,12 +42,12 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
+#include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <errno.h>
-#include <memory.h>
+#include <linux/errno.h>
 
 #include "dev.h"
 #include "eth.h"
diff -u --recursive --new-file v1.1.1/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v1.1.1/linux/drivers/net/net_init.c	Wed Dec  1 14:44:15 1993
+++ linux/drivers/net/net_init.c	Mon Apr 11 11:30:20 1994
@@ -23,7 +23,7 @@
 #include <linux/fs.h>
 #include <linux/malloc.h>
 #include <linux/if_ether.h>
-#include <memory.h>
+#include <linux/string.h>
 #include "dev.h"
 #include "eth.h"
 
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.1.1/linux/drivers/scsi/scsi.c	Thu Mar 17 09:31:18 1994
+++ linux/drivers/scsi/scsi.c	Mon Apr 11 15:32:05 1994
@@ -127,6 +127,7 @@
 static struct blist blacklist[] = 
 {
    {"CHINON","CD-ROM CDS-431","H42"},  /* Locks up if polled for lun != 0 */
+   {"CHINON","CD-ROM CDS-535","Q14"}, /* Lockup if polled for lun != 0 */
    {"DENON","DRD-25X","V"},   /* A cdrom that locks up when probed at lun != 0 */
    {"IMS", "CDD521/10","2.06"},   /* Locks-up when LUN>0 polled. */
    {"MAXTOR","XT-3280","PR02"},   /* Locks-up when LUN>0 polled. */
@@ -533,7 +534,7 @@
 {
   Scsi_Cmnd * SCpnt = NULL;
   int tablesize;
-  struct buffer_head * bh;
+  struct buffer_head * bh, *bhp;
 
   if ((index < 0) ||  (index > NR_SCSI_DEVICES))
     panic ("Index number in allocate_device() is out of range.\n");
@@ -557,16 +558,17 @@
   if (req) {
     memcpy(&SCpnt->request, req, sizeof(struct request));
     tablesize = scsi_devices[index].host->sg_tablesize;
-    bh = req->bh;
+    bhp = bh = req->bh;
     if(!tablesize) bh = NULL;
     /* Take a quick look through the table to see how big it is.  We already
        have our copy of req, so we can mess with that if we want to.  */
     while(req->nr_sectors && bh){
-	    tablesize--;
+	    bhp = bhp->b_reqnext;
+	    if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--;
 	    req->nr_sectors -= bh->b_size >> 9;
 	    req->sector += bh->b_size >> 9;
 	    if(!tablesize) break;
-	    bh = bh->b_reqnext;
+	    bh = bhp;
     };
     if(req->nr_sectors && bh && bh->b_reqnext){  /* Any leftovers? */
       SCpnt->request.bhtail = bh;
@@ -579,9 +581,10 @@
       req->current_nr_sectors = bh->b_size >> 9;
       req->buffer = bh->b_data;
       SCpnt->request.waiting = NULL; /* Wait until whole thing done */
-    } else
+    } else {
       req->dev = -1;
-      
+      wake_up(&wait_for_request);
+    };      
   } else {
     SCpnt->request.dev = 0xffff; /* Busy, but no request */
     SCpnt->request.waiting = NULL;  /* And no one is waiting for the device either */
@@ -608,7 +611,7 @@
   int dev = -1;
   struct request * req = NULL;
   int tablesize;
-  struct buffer_head * bh;
+  struct buffer_head * bh, *bhp;
   struct Scsi_Host * host;
   Scsi_Cmnd * SCpnt = NULL;
   Scsi_Cmnd * SCwait = NULL;
@@ -654,16 +657,17 @@
 	if (req) {
 	  memcpy(&SCpnt->request, req, sizeof(struct request));
 	  tablesize = scsi_devices[index].host->sg_tablesize;
-	  bh = req->bh;
+	  bhp = bh = req->bh;
 	  if(!tablesize) bh = NULL;
 	  /* Take a quick look through the table to see how big it is.  We already
 	     have our copy of req, so we can mess with that if we want to.  */
 	  while(req->nr_sectors && bh){
-	    tablesize--;
+	    bhp = bhp->b_reqnext;
+	    if(!bhp || !CONTIGUOUS_BUFFERS(bh,bhp)) tablesize--;
 	    req->nr_sectors -= bh->b_size >> 9;
 	    req->sector += bh->b_size >> 9;
 	    if(!tablesize) break;
-	    bh = bh->b_reqnext;
+	    bh = bhp;
 	  };
 	  if(req->nr_sectors && bh && bh->b_reqnext){  /* Any leftovers? */
 	    SCpnt->request.bhtail = bh;
@@ -680,6 +684,7 @@
 	    {
 	      req->dev = -1;
 	      *reqp = req->next;
+	      wake_up(&wait_for_request);
 	    };
 	} else {
 	  SCpnt->request.dev = 0xffff; /* Busy */
@@ -1503,8 +1508,8 @@
 {
   unsigned int nbits, mask;
   int i, j;
-  if((len & 0x1ff) || len > 4096)
-    panic("Inappropriate buffer size requested");
+  if((len & 0x1ff) || len > 8192)
+    return NULL;
   
   cli();
   nbits = len >> 9;
@@ -1593,6 +1598,7 @@
 
 	for (i=0; i< NR_SCSI_DEVICES; i++) {
 	  int j;
+	  scsi_devices[i].scsi_request_fn = NULL;
 	  switch (scsi_devices[i].type)
 	    {
 	    case TYPE_TAPE :
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.1.1/linux/drivers/scsi/scsi.h	Thu Dec 30 11:39:04 1993
+++ linux/drivers/scsi/scsi.h	Mon Apr 11 13:44:16 1994
@@ -262,6 +262,7 @@
 	int access_count;	/* Count of open channels/mounts */
 	struct wait_queue * device_wait;  /* Used to wait if device is busy */
 	struct Scsi_Host * host;
+	void (*scsi_request_fn)(void); /* Used to jumpstart things after an ioctl */
 	char type;
 	char scsi_level;
 	unsigned writeable:1;
@@ -307,11 +308,13 @@
      char *  address; /* Location data is to be transferred to */
      char * alt_address; /* Location of actual if address is a 
 			    dma indirect buffer.  NULL otherwise */
-     unsigned short length;
+     unsigned int length;
      };
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
+#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data)
 
+
 void *   scsi_malloc(unsigned int);
 int      scsi_free(void *, unsigned int);
 extern unsigned int dma_free_sectors;   /* How much room do we have left */
@@ -389,7 +392,6 @@
 	/* Low-level done function - can be used by low-level driver to point
 	 to completion function.  Not used by mid/upper level code. */
 	void (*scsi_done)(struct scsi_cmnd *);  
-
 	void (*done)(struct scsi_cmnd *);  /* Mid-level done function */
 
 /* The following fields can be written to by the host specific code. 
@@ -426,7 +428,6 @@
 extern Scsi_Cmnd * allocate_device(struct request **, int, int);
 
 extern Scsi_Cmnd * request_queueable(struct request *, int);
-
 extern int scsi_reset (Scsi_Cmnd *);
 
 extern int max_scsi_hosts;
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- v1.1.1/linux/drivers/scsi/scsi_debug.c	Wed Dec  1 14:44:16 1993
+++ linux/drivers/scsi/scsi_debug.c	Mon Apr 11 13:44:13 1994
@@ -18,15 +18,26 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-
 #include "../block/blk.h"
 #include "scsi.h"
 #include "hosts.h"
 
+/* A few options that we want selected */
+
+/* Do not attempt to use a timer to simulate a real disk with latency */
+/* Only use this in the actual kernel, not in the simulator. */
+#define IMMEDIATE
+
+/* Skip some consistency checking.  Good for benchmarking */
+#define SPEEDY
+
 /* Number of real scsi disks that will be detected ahead of time */
 static int NR_REAL=-1;
 
-#define MAJOR_NR SCSI_DISK_MAJOR
+#define NR_BLK_DEV	12
+#ifndef MAJOR_NR
+#define MAJOR_NR 8
+#endif
 #define START_PARTITION 4
 #define SCSI_DEBUG_TIMER 20
 /* Number of jiffies to wait before completing a command */
@@ -43,6 +54,11 @@
 #define DEB(x)
 #endif
 
+#ifdef SPEEDY
+#define VERIFY1_DEBUG(RW) 1
+#define VERIFY_DEBUG(RW) 1
+#else
+
 #define VERIFY1_DEBUG(RW)			       			\
       if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");};			\
       start = 0;							\
@@ -79,6 +95,7 @@
 	  panic ("Wrong bh block#");};  \
 	if (SCpnt->request.bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
       };
+#endif
 
 static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
 static int scsi_debug_host = 0;
@@ -154,7 +171,7 @@
     
     buff = (unsigned char *) SCpnt->request_buffer;
 
-    if(target>=2 || SCpnt->lun != 0) {
+    if(target>=1 || SCpnt->lun != 0) {
       SCpnt->result =  DID_NO_CONNECT << 16;
       done(SCpnt);
       return 0;
@@ -187,6 +204,7 @@
       buff[0] = TYPE_DISK;
       buff[1] = 0x80;  /* Removable disk */
       buff[2] = 1;
+      buff[4] = 33 - 5;
       memcpy(&buff[8],"Foo Inc",7);
       memcpy(&buff[16],"XYZZY",5);
       memcpy(&buff[32],"1",1);
@@ -219,7 +237,21 @@
       else 
 	block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
       VERIFY_DEBUG(READ);
+#if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
+      {
+	int delay = SCSI_SETUP_LATENCY;
+	double usec;
+
+	usec = 0.0;
+	usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
+	delay += usec;
+	if(delay) usleep(delay);
+      };
+#endif
+
+#ifdef DEBUG
       printk("(r%d)",SCpnt->request.nr_sectors);
+#endif
       nbytes = bufflen;
       if(SCpnt->use_sg){
 	sgcount = 0;
@@ -231,7 +263,10 @@
       scsi_debug_errsts = 0;
       do{
 	VERIFY1_DEBUG(READ);
+/* For the speedy test, we do not even want to fill the buffer with anything */
+#ifndef SPEEDY
 	memset(buff, 0, bufflen);
+#endif
 /* If this is block 0, then we want to read the partition table for this
    device.  Let's make one up */
 	if(block == 0 && target == 0) {
@@ -252,6 +287,8 @@
 	if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
 	       SCpnt->request.current_nr_sectors);
 #endif
+
+#if 0
 	/* Simulate a disk change */
 	if(block == 0xfff0) {
 	  sense_buffer[0] = 0x70;
@@ -270,14 +307,19 @@
 	  scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
 	  break;
 	} /* End phony disk change code */
-	memset(buff, 0, bufflen);
+#endif
+
+#ifndef SPEEDY
 	memcpy(buff, &target, sizeof(target));
 	memcpy(buff+sizeof(target), cmd, 24);
 	memcpy(buff+60, &block, sizeof(block));
 	memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
+#endif
 	nbytes -= bufflen;
 	if(SCpnt->use_sg){
+#ifndef SPEEDY
 	  memcpy(buff+128, bh, sizeof(struct buffer_head));
+#endif
 	  block += bufflen >> 9;
 	  bh = bh->b_reqnext;
 	  sgcount++;
@@ -288,6 +330,11 @@
 	  };
 	}
       } while(nbytes);
+
+      SCpnt->result = 0;
+      (done)(SCpnt);
+      return;
+
       if (SCpnt->use_sg && !scsi_debug_errsts)
 	if(bh) scsi_dump(SCpnt, 0);
       break;
@@ -301,7 +348,7 @@
       else 
 	block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
       VERIFY_DEBUG(WRITE);
-      printk("(w%d)",SCpnt->request.nr_sectors);
+/*      printk("(w%d)",SCpnt->request.nr_sectors); */
       if (SCpnt->use_sg){
 	if ((bufflen >> 9) != SCpnt->request.nr_sectors)
 	  panic ("Trying to write wrong number of blocks\n");
@@ -344,6 +391,10 @@
     else
       printk("scsi_debug_queuecommand: done cant be NULL\n");
 
+#ifdef IMMEDIATE
+    SCpnt->result = scsi_debug_errsts;
+    scsi_debug_intr_handle();  /* No timer - do this one right away */
+#else
     timeout[i] = jiffies+DISK_SPEED;
 
 /* If no timers active, then set this one */
@@ -358,6 +409,7 @@
 #if 0
     printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
 #endif
+#endif
 
     return 0;
 }
@@ -390,18 +442,25 @@
     void (*my_done)(Scsi_Cmnd *); 
    int to;
 
+#ifndef IMMEDIATE
     timer_table[SCSI_DEBUG_TIMER].expires = 0;
     timer_active &= ~(1 << SCSI_DEBUG_TIMER);
+#endif
 
   repeat:
     cli();
     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
       if (SCint[i] == 0) continue;
+#ifndef IMMEDIATE
       if (timeout[i] == 0) continue;
       if (timeout[i] <= jiffies) break;
+#else
+      break;
+#endif
     };
 
     if(i == SCSI_DEBUG_MAILBOXES){
+#ifndef IMMEDIATE
       pending = INT_MAX;
       for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
 	if (SCint[i] == 0) continue;
@@ -418,6 +477,7 @@
 	timer_active |= 1 << SCSI_DEBUG_TIMER;
       };
       sti();
+#endif
       return;
     };
 
@@ -454,8 +514,10 @@
 int scsi_debug_detect(int hostnum)
 {
     scsi_debug_host = hostnum;
+#ifndef IMMEDIATE
     timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
     timer_table[SCSI_DEBUG_TIMER].expires = 0;
+#endif
     return 1;
 }
 
@@ -479,7 +541,7 @@
     return 0;
 }
 
-int scsi_debug_biosparam(int size, int* info){
+int scsi_debug_biosparam(int size, int dev, int* info){
   info[0] = 32;
   info[1] = 64;
   info[2] = (size + 2047) >> 11;
@@ -506,7 +568,7 @@
     return 0;
 }
 
-char *scsi_debug_info(void)
+const char *scsi_debug_info(void)
 {
     static char buffer[] = " ";			/* looks nicer without anything here */
     return buffer;
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi_debug.h linux/drivers/scsi/scsi_debug.h
--- v1.1.1/linux/drivers/scsi/scsi_debug.h	Wed Dec  1 14:44:16 1993
+++ linux/drivers/scsi/scsi_debug.h	Mon Apr 11 13:44:13 1994
@@ -6,8 +6,8 @@
 int scsi_debug_command(Scsi_Cmnd *);
 int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int scsi_debug_abort(Scsi_Cmnd *, int);
-int scsi_debug_biosparam(int, int*);
-char *scsi_debug_info(void);
+int scsi_debug_biosparam(int, int, int[]);
+const char *scsi_debug_info(void);
 int scsi_debug_reset(Scsi_Cmnd *);
 
 #ifndef NULL
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v1.1.1/linux/drivers/scsi/scsi_ioctl.c	Wed Mar 16 19:12:10 1994
+++ linux/drivers/scsi/scsi_ioctl.c	Mon Apr 11 13:44:14 1994
@@ -134,7 +134,7 @@
 	  };
 
 	result = SCpnt->result;
-	SCpnt->request.dev = -1;  /* Mark as not busy */
+	SCpnt->request.dev = -1;
 	wake_up(&scsi_devices[SCpnt->index].device_wait);
 	return result;
 }
@@ -203,6 +203,10 @@
 	result = SCpnt->result;
 	SCpnt->request.dev = -1;  /* Mark as not busy */
 	if (buf) scsi_free(buf, needed);
+
+	if(scsi_devices[SCpnt->index].scsi_request_fn)
+	  (*scsi_devices[SCpnt->index].scsi_request_fn)();
+
 	wake_up(&scsi_devices[SCpnt->index].device_wait);
 	return result;
 #else
@@ -223,8 +227,6 @@
 #endif
 }
 
-	
-
 /*
 	the scsi_ioctl() function differs from most ioctls in that it does
 	not take a major/minor number as the dev filed.  Rather, it takes
@@ -302,4 +304,3 @@
   set_fs(oldfs);
   return tmp;
 }
-
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/scsi_ioctl.h linux/drivers/scsi/scsi_ioctl.h
--- v1.1.1/linux/drivers/scsi/scsi_ioctl.h	Wed Dec  1 14:44:16 1993
+++ linux/drivers/scsi/scsi_ioctl.h	Mon Apr 11 13:44:14 1994
@@ -4,6 +4,7 @@
 #define SCSI_IOCTL_PROBE_HOST 0
 #define SCSI_IOCTL_SEND_COMMAND 1
 #define SCSI_IOCTL_TEST_UNIT_READY 2
+#define SCSI_IOCTL_BENCHMARK_COMMAND 3
 /* The door lock/unlock constants are compatible with Sun constants for
    the cdrom */
 #define SCSI_IOCTL_DOORLOCK 0x5380		/* lock the eject mechanism */
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.1.1/linux/drivers/scsi/sd.c	Wed Mar 16 19:12:09 1994
+++ linux/drivers/scsi/sd.c	Mon Apr 11 13:44:14 1994
@@ -34,11 +34,15 @@
 #define MAX_RETRIES 5
 
 /*
- *	Time out in seconds
+ *	Time out in seconds for disks and Magneto-opticals (which are slower).
  */
 
 #define SD_TIMEOUT 300
+#define SD_MOD_TIMEOUT 750
 
+#define CLUSTERABLE_DEVICE(SC) (SC->host->sg_tablesize < 64 && \
+			    scsi_devices[SC->index].type != TYPE_MOD)
+
 struct hd_struct * sd;
 
 int NR_SD=0;
@@ -369,9 +373,7 @@
     };
     
     if (!SCpnt) return; /* Could not find anything to do */
-    
-    wake_up(&wait_for_request);
-    
+        
     /* Queue command */
     requeue_sd_request(SCpnt);
   };  /* While */
@@ -381,7 +383,10 @@
 {
 	int dev, block, this_count;
 	unsigned char cmd[10];
-	char * buff;
+	int bounce_size, contiguous;
+	int max_sg;
+	struct buffer_head * bh, *bhp;
+	char * buff, *bounce_buffer;
 
 repeat:
 
@@ -440,8 +445,35 @@
 
 	SCpnt->this_count = 0;
 
-	if (!SCpnt->request.bh || 
-	    (SCpnt->request.nr_sectors == SCpnt->request.current_nr_sectors)) {
+	/* If the host adapter can deal with very large scatter-gather
+	   requests, it is a waste of time to cluster */
+	contiguous = (!CLUSTERABLE_DEVICE(SCpnt) ? 0 :1);
+	bounce_buffer = NULL;
+	bounce_size = (SCpnt->request.nr_sectors << 9);
+
+	/* First see if we need a bounce buffer for this request.  If we do, make sure
+	   that we can allocate a buffer.  Do not waste space by allocating a bounce
+	   buffer if we are straddling the 16Mb line */
+
+	
+	if (contiguous && SCpnt->request.bh &&
+	    ((int) SCpnt->request.bh->b_data) + (SCpnt->request.nr_sectors << 9) - 1 > 
+	    ISA_DMA_THRESHOLD && SCpnt->host->unchecked_isa_dma) {
+	  if(((int) SCpnt->request.bh->b_data) > ISA_DMA_THRESHOLD)
+	    bounce_buffer = scsi_malloc(bounce_size);
+	  if(!bounce_buffer) contiguous = 0;
+	};
+
+	if(contiguous && SCpnt->request.bh && SCpnt->request.bh->b_reqnext)
+	  for(bh = SCpnt->request.bh, bhp = bh->b_reqnext; bhp; bh = bhp, 
+	      bhp = bhp->b_reqnext) {
+	    if(!CONTIGUOUS_BUFFERS(bh,bhp)) { 
+	      if(bounce_buffer) scsi_free(bounce_buffer, bounce_size);
+	      contiguous = 0;
+	      break;
+	    } 
+	  };
+	if (!SCpnt->request.bh || contiguous) {
 
 	  /* case of page request (i.e. raw device), or unlinked buffer */
 	  this_count = SCpnt->request.nr_sectors;
@@ -450,7 +482,7 @@
 
 	} else if (SCpnt->host->sg_tablesize == 0 ||
 		   (need_isa_buffer && 
-		    dma_free_sectors < 10)) {
+		    dma_free_sectors <= 10)) {
 
 	  /* Case of host adapter that cannot scatter-gather.  We also
 	   come here if we are running low on DMA buffer memory.  We set
@@ -461,7 +493,7 @@
 
 	  if (SCpnt->host->sg_tablesize != 0 &&
 	      need_isa_buffer && 
-	      dma_free_sectors < 10)
+	      dma_free_sectors <= 10)
 	    printk("Warning: SCSI DMA buffer space running low.  Using non scatter-gather I/O.\n");
 
 	  this_count = SCpnt->request.current_nr_sectors;
@@ -471,25 +503,41 @@
 	} else {
 
 	  /* Scatter-gather capable host adapter */
-	  struct buffer_head * bh;
 	  struct scatterlist * sgpnt;
 	  int count, this_count_max;
+	  int counted;
+
 	  bh = SCpnt->request.bh;
 	  this_count = 0;
 	  this_count_max = (rscsi_disks[dev].ten ? 0xffff : 0xff);
 	  count = 0;
-	  while(bh && count < SCpnt->host->sg_tablesize) {
+	  bhp = NULL;
+	  while(bh) {
 	    if ((this_count + (bh->b_size >> 9)) > this_count_max) break;
+	    if(!bhp || !CONTIGUOUS_BUFFERS(bhp,bh) ||
+	       !CLUSTERABLE_DEVICE(SCpnt) ||
+	       (SCpnt->host->unchecked_isa_dma &&
+	       ((unsigned int) bh->b_data-1) == ISA_DMA_THRESHOLD)) {
+	      if (count < SCpnt->host->sg_tablesize) count++;
+	      else break;
+	    };
 	    this_count += (bh->b_size >> 9);
-	    count++;
+	    bhp = bh;
 	    bh = bh->b_reqnext;
 	  };
+#if 0
+	  if(SCpnt->host->unchecked_isa_dma &&
+	     ((unsigned int) SCpnt->request.bh->b_data-1) == ISA_DMA_THRESHOLD) count--;
+#endif
 	  SCpnt->use_sg = count;  /* Number of chains */
 	  count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/
 	  while( count < (SCpnt->use_sg * sizeof(struct scatterlist))) 
 	    count = count << 1;
 	  SCpnt->sglist_len = count;
+	  max_sg = count / sizeof(struct scatterlist);
+	  if(SCpnt->host->sg_tablesize < max_sg) max_sg = SCpnt->host->sg_tablesize;
 	  sgpnt = (struct scatterlist * ) scsi_malloc(count);
+	  memset(sgpnt, 0, count);  /* Zero so it is easy to fill */
 	  if (!sgpnt) {
 	    printk("Warning - running *really* short on DMA buffers\n");
 	    SCpnt->use_sg = 0;  /* No memory left - bail out */
@@ -497,20 +545,25 @@
 	    buff = SCpnt->request.buffer;
 	  } else {
 	    buff = (char *) sgpnt;
-	    count = 0;
-	    bh = SCpnt->request.bh;
-	    for(count = 0, bh = SCpnt->request.bh; count < SCpnt->use_sg; 
-		count++, bh = bh->b_reqnext) {
-	      sgpnt[count].address = bh->b_data;
-	      sgpnt[count].alt_address = NULL;
-	      sgpnt[count].length = bh->b_size;
-	      if (((int) sgpnt[count].address) + sgpnt[count].length > 
-		  ISA_DMA_THRESHOLD & (SCpnt->host->unchecked_isa_dma)) {
+	    counted = 0;
+	    for(count = 0, bh = SCpnt->request.bh, bhp = bh->b_reqnext;
+		count < SCpnt->use_sg && bh; 
+		count++, bh = bhp) {
+
+	      bhp = bh->b_reqnext;
+
+	      if(!sgpnt[count].address) sgpnt[count].address = bh->b_data;
+	      sgpnt[count].length += bh->b_size;
+	      counted += bh->b_size >> 9;
+
+	      if (((int) sgpnt[count].address) + sgpnt[count].length - 1 > 
+		  ISA_DMA_THRESHOLD && (SCpnt->host->unchecked_isa_dma) &&
+		  !sgpnt[count].alt_address) {
 		sgpnt[count].alt_address = sgpnt[count].address;
 		/* We try and avoid exhausting the DMA pool, since it is easier
 		   to control usage here.  In other places we might have a more
 		   pressing need, and we would be screwed if we ran out */
-		if(dma_free_sectors < (bh->b_size >> 9) + 5) {
+		if(dma_free_sectors < (sgpnt[count].length >> 9) + 10) {
 		  sgpnt[count].address = NULL;
 		} else {
 		  sgpnt[count].address = (char *) scsi_malloc(sgpnt[count].length);
@@ -520,6 +573,7 @@
    ensure that all scsi operations are able to do at least a non-scatter/gather
    operation */
 		if(sgpnt[count].address == NULL){ /* Out of dma memory */
+#if 0
 		  printk("Warning: Running low on SCSI DMA buffers");
 		  /* Try switching back to a non scatter-gather operation. */
 		  while(--count >= 0){
@@ -529,30 +583,93 @@
 		  this_count = SCpnt->request.current_nr_sectors;
 		  buff = SCpnt->request.buffer;
 		  SCpnt->use_sg = 0;
-		  scsi_free(buff, SCpnt->sglist_len);
+		  scsi_free(sgpnt, SCpnt->sglist_len);
+#endif
+		  SCpnt->use_sg = count;
+		  this_count = counted -= bh->b_size >> 9;
 		  break;
 		};
 
-		if (SCpnt->request.cmd == WRITE)
-		  memcpy(sgpnt[count].address, sgpnt[count].alt_address, 
-			 sgpnt[count].length);
 	      };
+
+	      /* Only cluster buffers if we know that we can supply DMA buffers
+		 large enough to satisfy the request.  Do not cluster a new
+		 request if this would mean that we suddenly need to start
+		 using DMA bounce buffers */
+	      if(bhp && CONTIGUOUS_BUFFERS(bh,bhp) && CLUSTERABLE_DEVICE(SCpnt)) {
+		char * tmp;
+
+		if (((int) sgpnt[count].address) + sgpnt[count].length +
+		    bhp->b_size - 1 > ISA_DMA_THRESHOLD && 
+		    (SCpnt->host->unchecked_isa_dma) &&
+		    !sgpnt[count].alt_address) continue;
+
+		if(!sgpnt[count].alt_address) {count--; continue; }
+		if(dma_free_sectors > 10)
+		  tmp = scsi_malloc(sgpnt[count].length + bhp->b_size);
+		else {
+		  tmp = NULL;
+		  max_sg = SCpnt->use_sg;
+		};
+		if(tmp){
+		  scsi_free(sgpnt[count].address, sgpnt[count].length);
+		  sgpnt[count].address = tmp;
+		  count--;
+		  continue;
+		};
+
+		/* If we are allowed another sg chain, then increment counter so we
+		   can insert it.  Otherwise we will end up truncating */
+
+		if (SCpnt->use_sg < max_sg) SCpnt->use_sg++;
+	      };  /* contiguous buffers */
 	    }; /* for loop */
+
+	    this_count = counted; /* This is actually how many we are going to transfer */
+
+	    if(count < SCpnt->use_sg || SCpnt->use_sg > SCpnt->host->sg_tablesize){
+	      bh = SCpnt->request.bh;
+	      printk("Use sg, count %d %x %d\n", SCpnt->use_sg, count, dma_free_sectors);
+	      printk("maxsg = %x, counted = %d this_count = %d\n", max_sg, counted, this_count);
+	      while(bh){
+		printk("[%8.8x %x] ", bh->b_data, bh->b_size);
+		bh = bh->b_reqnext;
+	      };
+	      if(SCpnt->use_sg < 16)
+		for(count=0; count<SCpnt->use_sg; count++)
+		  printk("{%d:%8.8x %8.8x %d}  ", count,
+			 sgpnt[count].address,
+			 sgpnt[count].alt_address,
+			 sgpnt[count].length);
+	      panic("Ooops");
+	    };
+
+	    if (SCpnt->request.cmd == WRITE)
+	      for(count=0; count<SCpnt->use_sg; count++)
+		if(sgpnt[count].alt_address)
+		  memcpy(sgpnt[count].address, sgpnt[count].alt_address, 
+			 sgpnt[count].length);
 	  };  /* Able to malloc sgpnt */
 	};  /* Host adapter capable of scatter-gather */
 
 /* Now handle the possibility of DMA to addresses > 16Mb */
 
 	if(SCpnt->use_sg == 0){
-	  if (((int) buff) + (this_count << 9) > ISA_DMA_THRESHOLD && 
+	  if (((int) buff) + (this_count << 9) - 1 > ISA_DMA_THRESHOLD && 
 	    (SCpnt->host->unchecked_isa_dma)) {
-	    buff = (char *) scsi_malloc(this_count << 9);
-	    if(buff == NULL) panic("Ran out of DMA buffers.");
+	    if(bounce_buffer)
+	      buff = bounce_buffer;
+	    else
+	      buff = (char *) scsi_malloc(this_count << 9);
+	    if(buff == NULL) {  /* Try backing off a bit if we are low on mem*/
+	      this_count = SCpnt->request.current_nr_sectors;
+	      buff = (char *) scsi_malloc(this_count << 9);
+	      if(!buff) panic("Ran out of DMA buffers.");
+	    };
 	    if (SCpnt->request.cmd == WRITE)
 	      memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9);
 	  };
 	};
-
 #ifdef DEBUG
 	printk("sd%d : %s %d/%d 512 byte blocks.\n", MINOR(SCpnt->request.dev),
 		(SCpnt->request.cmd == WRITE) ? "writing" : "reading",
@@ -607,10 +724,12 @@
 
         SCpnt->transfersize = rscsi_disks[dev].sector_size;
         SCpnt->underflow = this_count << 9; 
-
 	scsi_do_cmd (SCpnt, (void *) cmd, buff, 
 		     this_count * rscsi_disks[dev].sector_size,
-		     rw_intr, SD_TIMEOUT, MAX_RETRIES);
+		     rw_intr, 
+		     (scsi_devices[SCpnt->index].type == TYPE_DISK ? 
+		                     SD_TIMEOUT : SD_MOD_TIMEOUT),
+		     MAX_RETRIES);
 }
 
 int check_scsidisk_media_change(int full_dev, int flag){
@@ -857,6 +976,7 @@
 	their size, and reads partition	table entries for them.
 */
 
+
 unsigned long sd_init(unsigned long memory_start, unsigned long memory_end)
 {
 	int i;
@@ -893,7 +1013,7 @@
 	   the read-ahead to 16 blocks (32 sectors).  If not, we use
 	   a two block (4 sector) read ahead. */
 	if(rscsi_disks[0].device->host->sg_tablesize)
-	  read_ahead[MAJOR_NR] = 32;
+	  read_ahead[MAJOR_NR] = 120;
 	/* 64 sector read-ahead */
 	else
 	  read_ahead[MAJOR_NR] = 4;  /* 4 sector read-ahead */
@@ -910,6 +1030,7 @@
 };
 
 void sd_attach(Scsi_Device * SDp){
+  SDp->scsi_request_fn = do_sd_request;
   rscsi_disks[NR_SD++].device = SDp;
   if(NR_SD > MAX_SD) panic ("scsi_devices corrupt (sd)");
 };
@@ -968,3 +1089,4 @@
 	  DEVICE_BUSY = 0;
 	  return 0;
 }
+
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v1.1.1/linux/drivers/scsi/sd_ioctl.c	Wed Dec  1 14:44:16 1993
+++ linux/drivers/scsi/sd_ioctl.c	Mon Apr 11 13:44:15 1994
@@ -53,6 +53,12 @@
 			put_fs_long(sd[MINOR(inode->i_rdev)].nr_sects,
 				(long *) arg);
 			return 0;
+		case BLKRASET:
+			if(!suser())  return -EACCES;
+			if(!inode->i_rdev) return -EINVAL;
+			if(arg > 0xff) return -EINVAL;
+			read_ahead[MAJOR(inode->i_rdev)] = arg;
+			return 0;
 		case BLKFLSBUF:
 			if(!suser())  return -EACCES;
 			if(!inode->i_rdev) return -EINVAL;
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.1/linux/drivers/scsi/sr.c	Wed Mar 16 19:12:09 1994
+++ linux/drivers/scsi/sr.c	Mon Apr 11 13:44:15 1994
@@ -624,6 +624,7 @@
 };
 
 void sr_attach(Scsi_Device * SDp){
+  SDp->scsi_request_fn = do_sr_request;
   scsi_CDs[NR_SR++].device = SDp;
   if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");
 };
diff -u --recursive --new-file v1.1.1/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v1.1.1/linux/drivers/scsi/sr_ioctl.c	Mon Mar 21 16:13:13 1994
+++ linux/drivers/scsi/sr_ioctl.c	Mon Apr 11 13:44:15 1994
@@ -385,6 +385,12 @@
 		case CDROMREADMODE1:
 			return -EINVAL;
 
+		case BLKRASET:
+			if(!suser())  return -EACCES;
+			if(!inode->i_rdev) return -EINVAL;
+			if(arg > 0xff) return -EINVAL;
+			read_ahead[MAJOR(inode->i_rdev)] = arg;
+			return 0;
 		RO_IOCTLS(dev,arg);
 		default:
 			return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
diff -u --recursive --new-file v1.1.1/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v1.1.1/linux/drivers/sound/os.h	Fri Feb 11 13:07:33 1994
+++ linux/drivers/sound/os.h	Mon Apr 11 11:30:20 1994
@@ -37,6 +37,7 @@
 #include <linux/timer.h>
 #include <linux/tty.h>
 #include <linux/ctype.h>
+#include <linux/string.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
diff -u --recursive --new-file v1.1.1/linux/fs/block_dev.c linux/fs/block_dev.c
--- v1.1.1/linux/fs/block_dev.c	Sun Dec  5 12:30:12 1993
+++ linux/fs/block_dev.c	Mon Apr 11 15:22:11 1994
@@ -54,7 +54,8 @@
 		if (chars == blocksize)
 			bh = getblk(dev, block, blocksize);
 		else
-			bh = breada(dev,block,block+1,block+2,-1);
+			bh = breada(dev, block, blocksize, offset, 
+				    size << blocksize_bits);
 		block++;
 		if (!bh)
 			return written?written:-EIO;
@@ -67,7 +68,7 @@
 		p += chars;
 		buf += chars;
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse(bh);
 	}
 	return written;
diff -u --recursive --new-file v1.1.1/linux/fs/buffer.c linux/fs/buffer.c
--- v1.1.1/linux/fs/buffer.c	Thu Mar 10 14:20:55 1994
+++ linux/fs/buffer.c	Mon Apr 11 13:52:14 1994
@@ -46,6 +46,10 @@
 extern int check_mcd_media_change(int, int);
 #endif
 
+static char buffersize_index[9] = {-1,  0,  1, -1,  2, -1, -1, -1, 3};
+
+#define BUFSIZE_INDEX(X) (buffersize_index[(X)>>9])
+
 static int grow_buffers(int pri, int size);
 
 static struct buffer_head * hash_table[NR_HASH];
@@ -556,42 +560,62 @@
 
 /*
  * Ok, breada can be used as bread, but additionally to mark other
- * blocks for reading as well. End the argument list with a negative
- * number.
+ * blocks for reading as well.
  */
-struct buffer_head * breada(dev_t dev,int first, ...)
-{
-	va_list args;
-	unsigned int blocksize;
-	struct buffer_head * bh, *tmp;
 
-	va_start(args,first);
+#define NBUF 16
+
+struct buffer_head * breada(dev_t dev, int block, int bufsize,
+	unsigned int pos, unsigned int filesize)
+{
+	struct buffer_head * bhlist[NBUF];
+	unsigned int blocks;
+	struct buffer_head * bh;
+	int index;
+	int i, j;
 
-	blocksize = BLOCK_SIZE;
-	if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
-		blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
+	if (pos >= filesize)
+		return NULL;
 
-	if (!(bh = getblk(dev, first, blocksize))) {
-		printk("VFS: breada: READ error on device %d/%d\n",
-						MAJOR(dev), MINOR(dev));
+	if (block < 0 || !(bh = getblk(dev,block,bufsize)))
 		return NULL;
-	}
-	if (!bh->b_uptodate)
-		ll_rw_block(READ, 1, &bh);
-	while ((first=va_arg(args,int))>=0) {
-		tmp = getblk(dev, first, blocksize);
-		if (tmp) {
-			if (!tmp->b_uptodate)
-				ll_rw_block(READA, 1, &tmp);
-			tmp->b_count--;
+
+	index = BUFSIZE_INDEX(bh->b_size);
+
+	if (bh->b_uptodate)
+		return bh;
+
+	blocks = ((filesize & (bufsize - 1)) - (pos & (bufsize - 1))) >> (9+index);
+
+	if (blocks > (read_ahead[MAJOR(dev)] >> index))
+		blocks = read_ahead[MAJOR(dev)] >> index;
+	if (blocks > NBUF)
+		blocks = NBUF;
+	
+	bhlist[0] = bh;
+	j = 1;
+	for(i=1; i<blocks; i++) {
+		bh = getblk(dev,block+i,bufsize);
+		if (bh->b_uptodate) {
+			brelse(bh);
+			break;
 		}
+		bhlist[j++] = bh;
 	}
-	va_end(args);
+
+	/* Request the read for these buffers, and then release them */
+	ll_rw_block(READ, j, bhlist);
+
+	for(i=1; i<j; i++)
+		brelse(bhlist[i]);
+
+	/* Wait for this buffer, and then continue on */
+	bh = bhlist[0];
 	wait_on_buffer(bh);
 	if (bh->b_uptodate)
 		return bh;
 	brelse(bh);
-	return (NULL);
+	return NULL;
 }
 
 /*
@@ -616,7 +640,7 @@
 	if (unused_list)
 		return;
 
-	if(! (bh = (struct buffer_head*) get_free_page(GFP_BUFFER)))
+	if (!(bh = (struct buffer_head*) get_free_page(GFP_BUFFER)))
 		return;
 
 	for (nr_buffer_heads+=i=PAGE_SIZE/sizeof*bh ; i>0; i--) {
@@ -870,7 +894,7 @@
 		printk("VFS: grow_buffers: size = %d\n",size);
 		return 0;
 	}
-	if(!(page = __get_free_page(pri)))
+	if (!(page = __get_free_page(pri)))
 		return 0;
 	bh = create_buffers(page, size);
 	if (!bh) {
diff -u --recursive --new-file v1.1.1/linux/fs/ext/file.c linux/fs/ext/file.c
--- v1.1.1/linux/fs/ext/file.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/ext/file.c	Mon Apr 11 13:35:31 1994
@@ -104,7 +104,8 @@
 	blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
 	bhb = bhe = buflist;
 	if (filp->f_reada) {
-		blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+	        if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
+		  blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
 		if (block + blocks > size)
 			blocks = size - block;
 	}
@@ -247,7 +248,7 @@
 		memcpy_fromfs(p,buf,c);
 		buf += c;
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse(bh);
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v1.1.1/linux/fs/ext/freelists.c linux/fs/ext/freelists.c
--- v1.1.1/linux/fs/ext/freelists.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/ext/freelists.c	Mon Apr 11 13:35:30 1994
@@ -83,7 +83,7 @@
 	}
 	sb->u.ext_sb.s_freeblockscount ++;
 	sb->s_dirt = 1;
-	sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
+	dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
 	unlock_super (sb);
 	return;
 }
@@ -104,7 +104,7 @@
 	efb = (struct ext_free_block *) sb->u.ext_sb.s_firstfreeblock->b_data;
 	if (efb->count) {
 		j = efb->free[--efb->count];
-		sb->u.ext_sb.s_firstfreeblock->b_dirt = 1;
+		dirtify_buffer(sb->u.ext_sb.s_firstfreeblock, 1);
 	} else {
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: block empty, skipping to %d\n", efb->next);
@@ -135,7 +135,7 @@
 	}
 	clear_block(bh->b_data);
 	bh->b_uptodate = 1;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 #ifdef EXTFS_DEBUG
 printk("ext_new_block: allocating block %d\n", j);
@@ -239,7 +239,7 @@
 	}
 	sb->u.ext_sb.s_freeinodescount ++;
 	sb->s_dirt = 1;
-	sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
+	dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
 	unlock_super (sb);
 }
 
@@ -263,7 +263,7 @@
 		(sb->u.ext_sb.s_firstfreeinodenumber-1)%EXT_INODES_PER_BLOCK;
 	if (efi->count) {
 		j = efi->free[--efi->count];
-		sb->u.ext_sb.s_firstfreeinodeblock->b_dirt = 1;
+		dirtify_buffer(sb->u.ext_sb.s_firstfreeinodeblock, 1);
 	} else {
 #ifdef EXTFS_DEBUG
 printk("ext_free_inode: inode empty, skipping to %d\n", efi->next);
diff -u --recursive --new-file v1.1.1/linux/fs/ext/inode.c linux/fs/ext/inode.c
--- v1.1.1/linux/fs/ext/inode.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/ext/inode.c	Mon Apr 11 13:35:31 1994
@@ -139,7 +139,7 @@
 	es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
 	es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
 	es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse (bh);
 	sb->s_dirt = 0;
 }
@@ -296,7 +296,7 @@
 		goto repeat;
 	}
 	*p = tmp;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	return result;
 }
@@ -407,7 +407,7 @@
 		raw_inode->i_zone[0] = inode->i_rdev;
 	else for (block = 0; block < 12; block++)
 		raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
-	bh->b_dirt=1;
+	dirtify_buffer(bh, 1);
 	inode->i_dirt=0;
 	return bh;
 }
diff -u --recursive --new-file v1.1.1/linux/fs/ext/namei.c linux/fs/ext/namei.c
--- v1.1.1/linux/fs/ext/namei.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/ext/namei.c	Mon Apr 11 13:35:31 1994
@@ -249,7 +249,7 @@
 #if 0
 					dir->i_ctime = CURRENT_TIME;
 #endif
-					bh->b_dirt = 1;
+					dirtify_buffer(bh, 1);
 				}
 				brelse (bh);
 				bh = NULL;
@@ -296,7 +296,7 @@
 			de->name_len = namelen;
 			for (i=0; i < namelen ; i++)
 				de->name[i] = name[i];
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 			*res_dir = de;
 			return bh;
 		}
@@ -334,7 +334,7 @@
 		return -ENOSPC;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	*result = inode;
@@ -393,7 +393,7 @@
 		return -ENOSPC;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -445,7 +445,7 @@
 	de->name_len=2;
 	strcpy(de->name,"..");
 	inode->i_nlink = 2;
-	dir_block->b_dirt = 1;
+	dirtify_buffer(dir_block, 1);
 	brelse(dir_block);
 	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
 	if (dir->i_mode & S_ISGID)
@@ -459,7 +459,7 @@
 		return -ENOSPC;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	dir->i_nlink++;
 	dir->i_dirt = 1;
 	iput(dir);
@@ -567,7 +567,7 @@
 	de->inode = 0;
 	de->name_len = 0;
 	ext_merge_entries (de, pde, nde);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	inode->i_nlink=0;
 	inode->i_dirt=1;
 	dir->i_nlink--;
@@ -610,7 +610,7 @@
 	de->inode = 0;
 	de->name_len = 0;
 	ext_merge_entries (de, pde, nde);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	inode->i_nlink--;
 	inode->i_dirt = 1;
 	inode->i_ctime = CURRENT_TIME;
@@ -650,7 +650,7 @@
 	while (i < 1023 && (c = *(symname++)))
 		name_block->b_data[i++] = c;
 	name_block->b_data[i] = 0;
-	name_block->b_dirt = 1;
+	dirtify_buffer(name_block, 1);
 	brelse(name_block);
 	inode->i_size = i;
 	inode->i_dirt = 1;
@@ -672,7 +672,7 @@
 		return -ENOSPC;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -708,7 +708,7 @@
 		return -ENOSPC;
 	}
 	de->inode = oldinode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	oldinode->i_nlink++;
@@ -851,11 +851,11 @@
 		new_inode->i_nlink--;
 		new_inode->i_dirt = 1;
 	}
-	old_bh->b_dirt = 1;
-	new_bh->b_dirt = 1;
+	dirtify_buffer(old_bh, 1);
+	dirtify_buffer(new_bh, 1);
 	if (dir_bh) {
 		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-		dir_bh->b_dirt = 1;
+		dirtify_buffer(dir_bh, 1);
 		old_dir->i_nlink--;
 		new_dir->i_nlink++;
 		old_dir->i_dirt = 1;
diff -u --recursive --new-file v1.1.1/linux/fs/ext/truncate.c linux/fs/ext/truncate.c
--- v1.1.1/linux/fs/ext/truncate.c	Mon Dec 27 07:36:07 1993
+++ linux/fs/ext/truncate.c	Mon Apr 11 13:35:31 1994
@@ -102,7 +102,7 @@
 			continue;
 		}
 		*ind = 0;
-		ind_bh->b_dirt = 1;
+		dirtify_buffer(ind_bh, 1);
 		brelse(bh);
 		ext_free_block(inode->i_sb,tmp);
 	}
@@ -154,7 +154,7 @@
 		if (!tmp)
 			continue;
 		retry |= trunc_indirect(inode,offset+(i<<8),dind);
-		dind_bh->b_dirt = 1;
+		dirtify_buffer(dind_bh, 1);
 	}
 	dind = (unsigned long *) dind_bh->b_data;
 	for (i = 0; i < 256; i++)
@@ -201,7 +201,7 @@
 			goto repeat;
 		tind = i+(unsigned long *) tind_bh->b_data;
 		retry |= trunc_dindirect(inode,9+256+256*256+(i<<16),tind);
-		tind_bh->b_dirt = 1;
+		dirtify_buffer(tind_bh, 1);
 	}
 	tind = (unsigned long *) tind_bh->b_data;
 	for (i = 0; i < 256; i++)
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v1.1.1/linux/fs/ext2/balloc.c	Tue Feb 22 08:15:49 1994
+++ linux/fs/ext2/balloc.c	Mon Apr 11 13:35:36 1994
@@ -310,10 +310,10 @@
 		}
 	}
 	
-	bh2->b_dirt = 1;
-	sb->u.ext2_sb.s_sbh->b_dirt = 1;
+	dirtify_buffer(bh2, 1);
+	dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (sb->s_flags & MS_SYNC) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -524,7 +524,7 @@
 
 	j = tmp;
 
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (sb->s_flags & MS_SYNC) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -544,16 +544,16 @@
 	}
 	clear_block (bh->b_data, sb->s_blocksize);
 	bh->b_uptodate = 1;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse (bh);
 
 	ext2_debug ("allocating block %d. "
 		    "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
 
 	gdp->bg_free_blocks_count--;
-	bh2->b_dirt = 1;
+	dirtify_buffer(bh2, 1);
 	es->s_free_blocks_count--;
-	sb->u.ext2_sb.s_sbh->b_dirt = 1;
+	dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 	sb->s_dirt = 1;
 	unlock_super (sb);
 	return j;
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v1.1.1/linux/fs/ext2/file.c	Thu Mar 31 10:26:28 1994
+++ linux/fs/ext2/file.c	Mon Apr 11 13:35:36 1994
@@ -112,8 +112,8 @@
 	blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb);
 	bhb = bhe = buflist;
 	if (filp->f_reada) {
-		blocks += read_ahead[MAJOR(inode->i_dev)] >>
-			(EXT2_BLOCK_SIZE_BITS(sb) - 9);
+	        if (blocks < read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9))
+	            blocks = read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9);
 		if (block + blocks > size)
 			blocks = size - block;
 	}
@@ -277,7 +277,7 @@
 		memcpy_fromfs (p, buf, c);
 		buf += c;
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse (bh);
 	}
 	up(&inode->i_sem);
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v1.1.1/linux/fs/ext2/ialloc.c	Sat Jan  8 14:35:10 1994
+++ linux/fs/ext2/ialloc.c	Mon Apr 11 13:35:34 1994
@@ -202,7 +202,7 @@
 			EXT2_INODES_PER_BLOCK(inode->i_sb));
 	raw_inode->i_links_count = 0;
 	raw_inode->i_dtime = CURRENT_TIME;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(inode)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -266,12 +266,12 @@
 		gdp->bg_free_inodes_count++;
 		if (S_ISDIR(inode->i_mode))
 			gdp->bg_used_dirs_count--;
-		bh2->b_dirt = 1;
+		dirtify_buffer(bh2, 1);
 		es->s_free_inodes_count++;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 		set_inode_dtime (inode, gdp);
 	}
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (sb->s_flags & MS_SYNC) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -313,7 +313,7 @@
 			EXT2_INODES_PER_BLOCK(inode->i_sb));
 	raw_inode->i_version++;
 	inode->u.ext2_i.i_version = raw_inode->i_version;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse (bh);
 }
 
@@ -438,7 +438,7 @@
 				      "bit already set for inode %d", j);
 			goto repeat;
 		}
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		if (sb->s_flags & MS_SYNC) {
 			ll_rw_block (WRITE, 1, &bh);
 			wait_on_buffer (bh);
@@ -466,9 +466,9 @@
 	gdp->bg_free_inodes_count--;
 	if (S_ISDIR(mode))
 		gdp->bg_used_dirs_count++;
-	bh2->b_dirt = 1;
+	dirtify_buffer(bh2, 1);
 	es->s_free_inodes_count--;
-	sb->u.ext2_sb.s_sbh->b_dirt = 1;
+	dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 	sb->s_dirt = 1;
 	inode->i_mode = mode;
 	inode->i_sb = sb;
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v1.1.1/linux/fs/ext2/inode.c	Mon Feb  7 15:32:00 1994
+++ linux/fs/ext2/inode.c	Mon Apr 11 13:35:35 1994
@@ -109,7 +109,7 @@
 		}
 		clear_block (bh->b_data, inode->i_sb->s_blocksize);
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		brelse (bh);
 	} else {
 		ext2_discard_prealloc (inode);
@@ -314,7 +314,7 @@
 		goto repeat;
 	}
 	*p = tmp;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(inode)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -549,7 +549,7 @@
 		raw_inode->i_block[0] = inode->i_rdev;
 	else for (block = 0; block < EXT2_N_BLOCKS; block++)
 		raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	inode->i_dirt = 0;
 	return bh;
 }
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v1.1.1/linux/fs/ext2/namei.c	Fri Feb 11 14:55:41 1994
+++ linux/fs/ext2/namei.c	Mon Apr 11 15:23:22 1994
@@ -275,9 +275,6 @@
 				de->rec_len = sb->s_blocksize;
 				dir->i_size = offset + sb->s_blocksize;
 				dir->i_dirt = 1;
-#if 0 /* XXX don't update any times until successful completion of syscall */
-				dir->i_ctime = CURRENT_TIME;
-#endif
 			} else {
 
 				ext2_debug ("skipping to next block\n");
@@ -323,7 +320,7 @@
 			 */
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			dir->i_dirt = 1;
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 			*res_dir = de;
 			*err = 0;
 			return bh;
@@ -397,7 +394,7 @@
 	ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 			 de->inode);
 #endif
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -449,14 +446,6 @@
 		init_fifo(inode);
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		inode->i_rdev = rdev;
-#if 0
-	/*
-	 * XXX we may as well use the times set by ext2_new_inode().  The
-	 * following usually does nothing, but sometimes it invalidates
-	 * inode->i_ctime.
-	 */
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
 	inode->i_dirt = 1;
 	bh = ext2_add_entry (dir, name, len, &de, &err);
 	if (!bh) {
@@ -471,7 +460,7 @@
 	ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 			 de->inode);
 #endif
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -508,9 +497,6 @@
 	}
 	inode->i_op = &ext2_dir_inode_operations;
 	inode->i_size = inode->i_sb->s_blocksize;
-#if 0 /* XXX as above */
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-#endif
 	dir_block = ext2_bread (inode, 0, 1, &err);
 	if (!dir_block) {
 		iput (dir);
@@ -531,7 +517,7 @@
 	de->name_len = 2;
 	strcpy (de->name, "..");
 	inode->i_nlink = 2;
-	dir_block->b_dirt = 1;
+	dirtify_buffer(dir_block, 1);
 	brelse (dir_block);
 	inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
 	if (dir->i_mode & S_ISGID)
@@ -550,7 +536,7 @@
 	ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 			 de->inode);
 #endif
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -674,7 +660,7 @@
 	up(&inode->i_sem);
 	if (retval)
 		goto end_rmdir;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -742,7 +728,7 @@
 	retval = ext2_delete_entry (de, bh);
 	if (retval)
 		goto end_unlink;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -807,7 +793,7 @@
 		link[i++] = c;
 	link[i] = 0;
 	if (name_block) {
-		name_block->b_dirt = 1;
+		dirtify_buffer(name_block, 1);
 		brelse (name_block);
 	}
 	inode->i_size = i;
@@ -834,7 +820,7 @@
 	ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 			 de->inode);
 #endif
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -880,7 +866,7 @@
 	ext2_dcache_add (dir->i_dev, dir->i_ino, de->name, de->name_len,
 			 de->inode);
 #endif
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if (IS_SYNC(dir)) {
 		ll_rw_block (WRITE, 1, &bh);
 		wait_on_buffer (bh);
@@ -1056,19 +1042,19 @@
 	}
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
 	old_dir->i_dirt = 1;
-	old_bh->b_dirt = 1;
+	dirtify_buffer(old_bh,  1);
 	if (IS_SYNC(old_dir)) {
 		ll_rw_block (WRITE, 1, &old_bh);
 		wait_on_buffer (old_bh);
 	}
-	new_bh->b_dirt = 1;
+	dirtify_buffer(new_bh, 1);
 	if (IS_SYNC(new_dir)) {
 		ll_rw_block (WRITE, 1, &new_bh);
 		wait_on_buffer (new_bh);
 	}
 	if (dir_bh) {
 		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-		dir_bh->b_dirt = 1;
+		dirtify_buffer(dir_bh, 1);
 		old_dir->i_nlink--;
 		old_dir->i_dirt = 1;
 		if (new_inode) {
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v1.1.1/linux/fs/ext2/super.c	Thu Mar 10 18:48:35 1994
+++ linux/fs/ext2/super.c	Mon Apr 11 13:35:35 1994
@@ -36,7 +36,7 @@
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
 		sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 	}
 	va_start (args, fmt);
@@ -66,7 +66,7 @@
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
 		sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 	}
 	va_start (args, fmt);
@@ -96,7 +96,7 @@
 	lock_super (sb);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 	}
 #ifndef DONT_USE_DCACHE
 	ext2_dcache_invalidate (sb->s_dev);
@@ -159,10 +159,10 @@
 		gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
 		gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
 	}
-	bh2->b_dirt = 1;
+	dirtify_buffer(bh2, 1);
 	brelse (bh2);
 	es->s_magic = EXT2_SUPER_MAGIC;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	sb->s_magic = EXT2_SUPER_MAGIC;
 	return 1;
 }
@@ -287,7 +287,7 @@
 			es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
 		es->s_mnt_count++;
 		es->s_mtime = CURRENT_TIME;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 		if (test_opt (sb, DEBUG))
 			printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
@@ -570,7 +570,7 @@
 #ifdef EXT2FS_PRE_02B_COMPAT
 	if (fs_converted) {
 		for (i = 0; i < bh_count; i++)
-			sb->u.ext2_sb.s_group_desc[i]->b_dirt = 1;
+			dirtify_buffer(sb->u.ext2_sb.s_group_desc[i], 1);
 		sb->s_dirt = 1;
 	}
 #endif
@@ -582,7 +582,7 @@
 			       struct ext2_super_block * es)
 {
 	es->s_wtime = CURRENT_TIME;
-	sb->u.ext2_sb.s_sbh->b_dirt = 1;
+	dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 	sb->s_dirt = 0;
 }
 
@@ -639,7 +639,7 @@
 		 */
 		es->s_state = sb->u.ext2_sb.s_mount_state;
 		es->s_mtime = CURRENT_TIME;
-		sb->u.ext2_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.ext2_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 		ext2_commit_super (sb, es);
 	}
diff -u --recursive --new-file v1.1.1/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c
--- v1.1.1/linux/fs/ext2/truncate.c	Thu Mar 31 10:27:50 1994
+++ linux/fs/ext2/truncate.c	Mon Apr 11 13:35:34 1994
@@ -90,7 +90,7 @@
 		if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
 			clear_block (bh->b_data, inode->i_sb->s_blocksize,
 				     RANDOM_INT);
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 		}
 		brelse (bh);
 		if (free_count == 0) {
@@ -162,11 +162,11 @@
 			continue;
 		}
 		*ind = 0;
-		ind_bh->b_dirt = 1;
+		dirtify_buffer(ind_bh, 1);
 		if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
 			clear_block (bh->b_data, inode->i_sb->s_blocksize,
 				     RANDOM_INT);
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 		}
 		brelse (bh);
 		if (free_count == 0) {
@@ -243,7 +243,7 @@
 			continue;
 		retry |= trunc_indirect (inode, offset + (i * addr_per_block),
 					  dind);
-		dind_bh->b_dirt = 1;
+		dirtify_buffer(dind_bh, 1);
 	}
 	dind = (unsigned long *) dind_bh->b_data;
 	for (i = 0; i < addr_per_block; i++)
@@ -302,7 +302,7 @@
 		retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
 			addr_per_block + (i + 1) * addr_per_block * addr_per_block,
 			tind);
-		tind_bh->b_dirt = 1;
+		dirtify_buffer(tind_bh, 1);
 	}
 	tind = (unsigned long *) tind_bh->b_data;
 	for (i = 0; i < addr_per_block; i++)
diff -u --recursive --new-file v1.1.1/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v1.1.1/linux/fs/hpfs/hpfs_fs.c	Wed Feb 23 09:45:40 1994
+++ linux/fs/hpfs/hpfs_fs.c	Mon Apr 11 15:24:52 1994
@@ -16,6 +16,7 @@
 #include <linux/hpfs_fs.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
+#include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/locks.h>
 #include <linux/stat.h>
@@ -1676,8 +1677,7 @@
 	if (!data)
 		goto bail;
 
-	qbh->bh[0] = bh = breada(dev,
-				 secno, secno + 1, secno + 2, secno + 3, -1);
+	qbh->bh[0] = bh = breada(dev, secno, 512, 0, UINT_MAX);
 	if (!bh)
 		goto bail0;
 	memcpy(data, bh->b_data, 512);
diff -u --recursive --new-file v1.1.1/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v1.1.1/linux/fs/isofs/dir.c	Tue Mar  1 18:47:38 1994
+++ linux/fs/isofs/dir.c	Mon Apr 11 13:44:10 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/isofs/dir.c
  *
- *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
+ *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
  *
@@ -19,6 +19,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/locks.h>
 
 static int isofs_readdir(struct inode *, struct file *, struct dirent *, int);
 
@@ -81,9 +83,12 @@
 	
 	offset = filp->f_pos & (bufsize - 1);
 	block = isofs_bmap(inode,filp->f_pos>>bufbits);
-	if (!block || !(bh = bread(inode->i_dev,block,bufsize)))
-		return 0;
-	
+
+	if(!block) return 0;
+
+	if(!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
+	  return 0;
+
 	while (filp->f_pos < inode->i_size) {
 #ifdef DEBUG
 		printk("Block, offset: %x %x %x\n",
@@ -103,7 +108,8 @@
 				       + ISOFS_BLOCK_SIZE);
 			block = isofs_bmap(inode,(filp->f_pos)>>bufbits);
 			if (!block
-			    || !(bh = bread(inode->i_dev,block,bufsize)))
+			    || !(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, 
+					     inode->i_size)))
 				return 0;
 			continue;
 		}
@@ -126,7 +132,8 @@
 			offset = filp->f_pos & (bufsize - 1);
 			block = isofs_bmap(inode,(filp->f_pos)>> bufbits);
 			if (!block
-			    || !(bh = bread(inode->i_dev,block,bufsize))) {
+			    || !(bh = breada(inode->i_dev, block, bufsize,
+					     filp->f_pos, inode->i_size))) {
 			        kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
 				return 0;
 			};
diff -u --recursive --new-file v1.1.1/linux/fs/isofs/file.c linux/fs/isofs/file.c
--- v1.1.1/linux/fs/isofs/file.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/isofs/file.c	Mon Apr 11 13:44:11 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/isofs/file.c
  *
- *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
+ *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
  *
@@ -146,6 +146,8 @@
 	bhb = bhe = buflist;
 
 	ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+	if(ra_blocks > blocks) blocks = ra_blocks;
+
 	max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
 	nextblock = -1;
 
@@ -169,7 +171,6 @@
 			if (*bhb && !(*bhb)->b_uptodate) {
 			        uptodate = 0;
 			        bhreq[bhrequest++] = *bhb;
-				nextblock = (*bhb)->b_blocknr + 1;
 			      };
 
 			if (++bhb == &buflist[NBUF])
@@ -177,37 +178,12 @@
 
 			/* If the block we have on hand is uptodate, go ahead
 			   and complete processing. */
-			if(bhrequest == 0 && uptodate) break;
+			if(uptodate) break;
 
 			if (bhb == bhe)
 				break;
 		      }
 
-		if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { 
-		  /* If we are going to read something anyways, add in the
-		     read-ahead blocks */
-		  while(ra_blocks){
-		    if (block >= max_block) break;
-		    if(bhrequest == NBUF) break;  /* Block full */
-		    --ra_blocks;
-		    *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
-
-		    if (*bhb && !(*bhb)->b_uptodate) {
-		      if((*bhb)->b_blocknr != nextblock) {
-			brelse(*bhb);
-			break;
-		      };
-		      nextblock = (*bhb)->b_blocknr + 1;
-		      bhreq[bhrequest++] = *bhb;
-		    };
-		    
-		    if (++bhb == &buflist[NBUF])
-		      bhb = buflist;
-		    
-		    if (bhb == bhe)
-		      break;
-		  };
-		};
 		/* Now request them all */
 		if (bhrequest)
 		  ll_rw_block(READ, bhrequest, bhreq);
diff -u --recursive --new-file v1.1.1/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.1.1/linux/fs/isofs/inode.c	Sun Mar 13 20:39:14 1994
+++ linux/fs/isofs/inode.c	Mon Apr 11 13:44:11 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/isofs/inode.c
  * 
- *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
+ *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
  *
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
@@ -354,7 +354,7 @@
 	if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
 		cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
 		if (cpnt == NULL) {
-			printk(KERN_INFO "NoMem ISO inode %d\n",inode->i_ino);
+			printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
 			brelse(bh);
 			goto fail;
 		}
@@ -600,7 +600,8 @@
 			brelse(bh);
 			offset = 0;
 			block++;
-			if(block & 1) return -1;
+			if((block & 1) && (ISOFS_BLOCK_BITS - bufbits))
+			  return -1;
 			if (!block
 			    || !(bh = bread(parent->i_dev,block, bufsize)))
 				return -1;
diff -u --recursive --new-file v1.1.1/linux/fs/isofs/rock.c linux/fs/isofs/rock.c
--- v1.1.1/linux/fs/isofs/rock.c	Tue Mar  1 18:45:15 1994
+++ linux/fs/isofs/rock.c	Mon Apr 11 13:44:11 1994
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/isofs/rock.c
  *
- *  (C) 1992  Eric Youngdale
+ *  (C) 1992, 1993  Eric Youngdale
  *
  *  Rock Ridge Extensions to iso9660
  */
diff -u --recursive --new-file v1.1.1/linux/fs/minix/bitmap.c linux/fs/minix/bitmap.c
--- v1.1.1/linux/fs/minix/bitmap.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/minix/bitmap.c	Mon Apr 11 13:35:33 1994
@@ -93,7 +93,7 @@
 	}
 	if (!clear_bit(bit,bh->b_data))
 		printk("free_block (%04x:%d): bit already cleared\n",sb->s_dev,block);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	return;
 }
 
@@ -118,7 +118,7 @@
 		printk("new_block: bit already set");
 		goto repeat;
 	}
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
 	if (j < sb->u.minix_sb.s_firstdatazone ||
 	    j >= sb->u.minix_sb.s_nzones)
@@ -129,7 +129,7 @@
 	}
 	clear_block(bh->b_data);
 	bh->b_uptodate = 1;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	return j;
 }
@@ -175,7 +175,7 @@
 	clear_inode(inode);
 	if (!clear_bit(ino & 8191, bh->b_data))
 		printk("free_inode: bit %lu already cleared.\n",ino);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 }
 
 struct inode * minix_new_inode(const struct inode * dir)
@@ -204,7 +204,7 @@
 		iput(inode);
 		return NULL;
 	}
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	j += i*8192;
 	if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) {
 		iput(inode);
diff -u --recursive --new-file v1.1.1/linux/fs/minix/file.c linux/fs/minix/file.c
--- v1.1.1/linux/fs/minix/file.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/minix/file.c	Mon Apr 11 13:35:33 1994
@@ -98,7 +98,8 @@
 	blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
 	bhb = bhe = buflist;
 	if (filp->f_reada) {
-		blocks += read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
+	        if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
+		  blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
 		if (block + blocks > size)
 			blocks = size - block;
 	}
@@ -239,7 +240,7 @@
 		memcpy_fromfs(p,buf,c);
 		buf += c;
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse(bh);
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v1.1.1/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v1.1.1/linux/fs/minix/inode.c	Mon Jan  3 10:40:56 1994
+++ linux/fs/minix/inode.c	Mon Apr 11 13:35:33 1994
@@ -28,7 +28,7 @@
 static void minix_commit_super (struct super_block * sb,
 			       struct minix_super_block * ms)
 {
-	sb->u.minix_sb.s_sbh->b_dirt = 1;
+	dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
 	sb->s_dirt = 0;
 }
 
@@ -54,7 +54,7 @@
 	lock_super(sb);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
-		sb->u.minix_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
 	}
 	sb->s_dev = 0;
 	for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
@@ -90,7 +90,7 @@
 			return 0;
 		/* Mounting a rw partition read-only. */
 		ms->s_state = sb->u.minix_sb.s_mount_state;
-		sb->u.minix_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 		minix_commit_super (sb, ms);
 	}
@@ -98,7 +98,7 @@
 	  	/* Mount a partition which is read-only, read-write. */
 		sb->u.minix_sb.s_mount_state = ms->s_state;
 		ms->s_state &= ~MINIX_VALID_FS;
-		sb->u.minix_sb.s_sbh->b_dirt = 1;
+		dirtify_buffer(sb->u.minix_sb.s_sbh, 1);
 		sb->s_dirt = 1;
 
 		if (!(sb->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -197,7 +197,7 @@
 	}
 	if (!(s->s_flags & MS_RDONLY)) {
 		ms->s_state &= ~MINIX_VALID_FS;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		s->s_dirt = 1;
 	}
 	if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
@@ -349,7 +349,7 @@
 		goto repeat;
 	}
 	*p = tmp;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	return result;
 }
@@ -477,7 +477,7 @@
 	else for (block = 0; block < 9; block++)
 		raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
 	inode->i_dirt=0;
-	bh->b_dirt=1;
+	dirtify_buffer(bh, 1);
 	return bh;
 }
 
diff -u --recursive --new-file v1.1.1/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v1.1.1/linux/fs/minix/namei.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/minix/namei.c	Mon Apr 11 13:35:34 1994
@@ -195,7 +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;
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 			*res_dir = de;
 			break;
 		}
@@ -238,7 +238,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	*result = inode;
@@ -295,7 +295,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -347,7 +347,7 @@
 	de->inode = dir->i_ino;
 	strcpy(de->name,"..");
 	inode->i_nlink = 2;
-	dir_block->b_dirt = 1;
+	dirtify_buffer(dir_block, 1);
 	brelse(dir_block);
 	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
 	if (dir->i_mode & S_ISGID)
@@ -361,7 +361,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	dir->i_nlink++;
 	dir->i_dirt = 1;
 	iput(dir);
@@ -469,7 +469,7 @@
 	if (inode->i_nlink != 2)
 		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
 	de->inode = 0;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	inode->i_nlink=0;
 	inode->i_dirt=1;
 	dir->i_nlink--;
@@ -522,7 +522,7 @@
 		inode->i_nlink=1;
 	}
 	de->inode = 0;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_dirt = 1;
 	inode->i_nlink--;
@@ -562,7 +562,7 @@
 	while (i < 1023 && (c=*(symname++)))
 		name_block->b_data[i++] = c;
 	name_block->b_data[i] = 0;
-	name_block->b_dirt = 1;
+	dirtify_buffer(name_block, 1);
 	brelse(name_block);
 	inode->i_size = i;
 	inode->i_dirt = 1;
@@ -584,7 +584,7 @@
 		return i;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -621,7 +621,7 @@
 		return error;
 	}
 	de->inode = oldinode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	oldinode->i_nlink++;
@@ -774,11 +774,11 @@
 		new_inode->i_ctime = CURRENT_TIME;
 		new_inode->i_dirt = 1;
 	}
-	old_bh->b_dirt = 1;
-	new_bh->b_dirt = 1;
+	dirtify_buffer(old_bh, 1);
+	dirtify_buffer(new_bh, 1);
 	if (dir_bh) {
 		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-		dir_bh->b_dirt = 1;
+		dirtify_buffer(dir_bh, 1);
 		old_dir->i_nlink--;
 		old_dir->i_dirt = 1;
 		if (new_inode) {
diff -u --recursive --new-file v1.1.1/linux/fs/minix/truncate.c linux/fs/minix/truncate.c
--- v1.1.1/linux/fs/minix/truncate.c	Mon Dec 27 07:37:23 1993
+++ linux/fs/minix/truncate.c	Mon Apr 11 13:35:33 1994
@@ -96,7 +96,7 @@
 			continue;
 		}
 		*ind = 0;
-		ind_bh->b_dirt = 1;
+		dirtify_buffer(ind_bh, 1);
 		brelse(bh);
 		minix_free_block(inode->i_sb,tmp);
 	}
@@ -144,7 +144,7 @@
 			goto repeat;
 		dind = i+(unsigned short *) dind_bh->b_data;
 		retry |= trunc_indirect(inode,7+512+(i<<9),dind);
-		dind_bh->b_dirt = 1;
+		dirtify_buffer(dind_bh, 1);
 	}
 	dind = (unsigned short *) dind_bh->b_data;
 	for (i = 0; i < 512; i++)
diff -u --recursive --new-file v1.1.1/linux/fs/msdos/fat.c linux/fs/msdos/fat.c
--- v1.1.1/linux/fs/msdos/fat.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/msdos/fat.c	Mon Apr 11 13:35:32 1994
@@ -72,15 +72,15 @@
 				*p_first = new_value & 0xff;
 				*p_last = (*p_last & 0xf0) | (new_value >> 8);
 			}
-			bh2->b_dirt = 1;
+			dirtify_buffer(bh2, 1);
 		}
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
 			if (!(c_bh = msdos_sread(sb->s_dev,MSDOS_SB(sb)->
 			    fat_start+(first >> SECTOR_BITS)+MSDOS_SB(sb)->
 			    fat_length*copy,&c_data))) break;
 			memcpy(c_data,data,SECTOR_SIZE);
-			c_bh->b_dirt = 1;
+			dirtify_buffer(c_bh, 1);
 			if (data != data2 || bh != bh2) {
 				if (!(c_bh2 = msdos_sread(sb->s_dev,
 				    MSDOS_SB(sb)->fat_start+(first >>
diff -u --recursive --new-file v1.1.1/linux/fs/msdos/file.c linux/fs/msdos/file.c
--- v1.1.1/linux/fs/msdos/file.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/msdos/file.c	Mon Apr 11 13:35:33 1994
@@ -200,7 +200,7 @@
 			inode->i_size = filp->f_pos;
 			inode->i_dirt = 1;
 		}
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse(bh);
 	}
 	if (start == buf)
diff -u --recursive --new-file v1.1.1/linux/fs/msdos/inode.c linux/fs/msdos/inode.c
--- v1.1.1/linux/fs/msdos/inode.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/msdos/inode.c	Mon Apr 11 13:35:32 1994
@@ -415,7 +415,7 @@
 	date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
 	raw_entry->time = CT_LE_W(raw_entry->time);
 	raw_entry->date = CT_LE_W(raw_entry->date);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 }
 
diff -u --recursive --new-file v1.1.1/linux/fs/msdos/misc.c linux/fs/msdos/misc.c
--- v1.1.1/linux/fs/msdos/misc.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/msdos/misc.c	Mon Apr 11 13:35:32 1994
@@ -185,7 +185,7 @@
 			else memset(data,0,SECTOR_SIZE);
 		}
 		if (bh) {
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 			brelse(bh);
 		}
 	}
diff -u --recursive --new-file v1.1.1/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v1.1.1/linux/fs/msdos/namei.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/msdos/namei.c	Mon Apr 11 13:35:32 1994
@@ -181,7 +181,7 @@
 	de->start = 0;
 	date_unix2dos(dir->i_mtime,&de->time,&de->date);
 	de->size = 0;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	if ((*result = iget(dir->i_sb,ino)) != NULL)
 		msdos_read_inode(*result);
 	brelse(bh);
@@ -350,7 +350,7 @@
 	dir->i_nlink--;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	res = 0;
 rmdir_done:
 	brelse(bh);
@@ -384,7 +384,7 @@
 	MSDOS_I(inode)->i_busy = 1;
 	inode->i_dirt = dir->i_dirt = 1;
 	de->name[0] = DELETED_FLAG;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 unlink_done:
 	brelse(bh);
 	iput(inode);
@@ -429,12 +429,12 @@
 		MSDOS_I(new_inode)->i_busy = 1;
 		new_inode->i_dirt = 1;
 		new_de->name[0] = DELETED_FLAG;
-		new_bh->b_dirt = 1;
+		dirtify_buffer(new_bh, 1);
 		iput(new_inode);
 		brelse(new_bh);
 	}
 	memcpy(old_de->name,new_name,MSDOS_NAME);
-	old_bh->b_dirt = 1;
+	dirtify_buffer(old_bh, 1);
 	if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */
 		if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
 			msdos_read_inode(old_inode);
@@ -503,7 +503,7 @@
 		MSDOS_I(new_inode)->i_busy = 1;
 		new_inode->i_dirt = 1;
 		new_de->name[0] = DELETED_FLAG;
-		new_bh->b_dirt = 1;
+		dirtify_buffer(new_bh, 1);
 	}
 	memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
 	memcpy(free_de->name,new_name,MSDOS_NAME);
@@ -526,8 +526,8 @@
 	cache_inval_inode(old_inode);
 	old_inode->i_dirt = 1;
 	old_de->name[0] = DELETED_FLAG;
-	old_bh->b_dirt = 1;
-	free_bh->b_dirt = 1;
+	dirtify_buffer(old_bh, 1);
+	dirtify_buffer(free_bh, 1);
 	if (!exists) iput(free_inode);
 	else {
 		MSDOS_I(new_inode)->i_depend = free_inode;
@@ -547,7 +547,7 @@
 		dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
 		    MSDOS_I(new_dir)->i_start;
 		dotdot_inode->i_dirt = 1;
-		dotdot_bh->b_dirt = 1;
+		dirtify_buffer(dotdot_bh, 1);
 		old_dir->i_nlink--;
 		new_dir->i_nlink++;
 		/* no need to mark them dirty */
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/balloc.c linux/fs/sysv/balloc.c
--- v1.1.1/linux/fs/sysv/balloc.c	Wed Jul 21 21:26:29 1993
+++ linux/fs/sysv/balloc.c	Mon Apr 11 13:35:39 1994
@@ -96,7 +96,7 @@
 		}
 		*flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */
 		memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		bh->b_uptodate = 1;
 		brelse(bh);
 		*sb->sv_sb_flc_count = 0;
@@ -117,7 +117,7 @@
 		bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
 		memzero(bh_data, sb->sv_block_size);
 		/* this implies ((struct ..._freelist_chunk *) bh_data)->flc_count = 0; */
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		bh->b_uptodate = 1;
 		brelse(bh);
 		/* still *sb->sv_sb_flc_count = 0 */
@@ -138,7 +138,7 @@
 		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
 	else
 		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
-	sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+	dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 	sb->s_dirt = 1; /* and needs time stamp */
 	unlock_super(sb);
 }
@@ -229,7 +229,7 @@
 			return 0;
 		}
 	memzero(bh_data,sb->sv_block_size);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	bh->b_uptodate = 1;
 	brelse(bh);
 	if (sb->sv_convert)
@@ -237,7 +237,7 @@
 		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
 	else
 		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
-	sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+	dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 	sb->s_dirt = 1; /* and needs time stamp */
 	unlock_super(sb);
 	return block;
@@ -331,7 +331,7 @@
 		printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
 		if (!(sb->s_flags & MS_RDONLY)) {
 			*sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
-			sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+			dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 			sb->s_dirt = 1; /* and needs time stamp */
 		}
 	}
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v1.1.1/linux/fs/sysv/file.c	Sun Nov 28 21:01:02 1993
+++ linux/fs/sysv/file.c	Mon Apr 11 13:35:39 1994
@@ -301,7 +301,7 @@
 		memcpy_fromfs(p,buf,c);
 		buf += c;
 		bh->b_uptodate = 1;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 0);
 		brelse(bh);
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/ialloc.c linux/fs/sysv/ialloc.c
--- v1.1.1/linux/fs/sysv/ialloc.c	Thu Jan 13 20:26:21 1994
+++ linux/fs/sysv/ialloc.c	Mon Apr 11 13:35:39 1994
@@ -74,10 +74,10 @@
 	if (*sb->sv_sb_fic_count < sb->sv_fic_size)
 		sb->sv_sb_fic_inodes[(*sb->sv_sb_fic_count)++] = ino;
 	(*sb->sv_sb_total_free_inodes)++;
-	sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+	dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 	sb->s_dirt = 1; /* and needs time stamp */
 	memset(raw_inode, 0, sizeof(struct sysv_inode));
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	unlock_super(sb);
 	brelse(bh);
 	clear_inode(inode);
@@ -130,7 +130,7 @@
 	}
 	/* Now *sb->sv_sb_fic_count > 0. */
 	ino = sb->sv_sb_fic_inodes[--(*sb->sv_sb_fic_count)];
-	sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+	dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 	sb->s_dirt = 1; /* and needs time stamp */
 	inode->i_count = 1;
 	inode->i_nlink = 1;
@@ -152,7 +152,7 @@
 	inode->i_dirt = 1;		/* cleared by sysv_write_inode() */
 	/* That's it. */
 	(*sb->sv_sb_total_free_inodes)--;
-	sb->sv_bh->b_dirt = 1; /* super-block has been modified again */
+	dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified again */
 	sb->s_dirt = 1; /* and needs time stamp again */
 	unlock_super(sb);
 	return inode;
@@ -191,7 +191,7 @@
 		printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
 		if (!(sb->s_flags & MS_RDONLY)) {
 			*sb->sv_sb_total_free_inodes = count;
-			sb->sv_bh->b_dirt = 1; /* super-block has been modified */
+			dirtify_buffer(sb->sv_bh, 1); /* super-block has been modified */
 			sb->s_dirt = 1; /* and needs time stamp */
 		}
 	}
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v1.1.1/linux/fs/sysv/inode.c	Thu Jan 13 20:26:21 1994
+++ linux/fs/sysv/inode.c	Mon Apr 11 13:35:39 1994
@@ -557,7 +557,7 @@
 		goto repeat;
 	}
 	*p = (sb->sv_convert ? to_coh_ulong(block) : block);
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	*start = result->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
 	return result;
@@ -773,7 +773,7 @@
 		for (block = 0; block < 10+1+1+1; block++)
 			write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
 	inode->i_dirt=0;
-	bh->b_dirt=1;
+	dirtify_buffer(bh, 1);
 	return bh;
 }
 
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v1.1.1/linux/fs/sysv/namei.c	Tue Nov 30 05:00:53 1993
+++ linux/fs/sysv/namei.c	Mon Apr 11 13:35:38 1994
@@ -193,7 +193,7 @@
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			for (i = 0; i < SYSV_NAMELEN ; i++)
 				de->name[i] = (i < namelen) ? name[i] : 0;
-			bh->b_dirt = 1;
+			dirtify_buffer(bh, 1);
 			*res_dir = de;
 			break;
 		}
@@ -238,7 +238,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	*result = inode;
@@ -298,7 +298,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -349,7 +349,7 @@
 	de->inode = dir->i_ino;
 	strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
 	inode->i_nlink = 2;
-	dir_block->b_dirt = 1;
+	dirtify_buffer(dir_block, 1);
 	brelse(dir_block);
 	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
 	if (dir->i_mode & S_ISGID)
@@ -363,7 +363,7 @@
 		return error;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	dir->i_nlink++;
 	dir->i_dirt = 1;
 	iput(dir);
@@ -473,7 +473,7 @@
 	if (inode->i_nlink != 2)
 		printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
 	de->inode = 0;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	inode->i_nlink=0;
 	inode->i_dirt=1;
 	dir->i_nlink--;
@@ -526,7 +526,7 @@
 		inode->i_nlink=1;
 	}
 	de->inode = 0;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_dirt = 1;
 	inode->i_nlink--;
@@ -570,7 +570,7 @@
 	while (i < sb->sv_block_size_1 && (c = *(symname++)))
 		name_block_data[i++] = c;
 	name_block_data[i] = 0;
-	name_block->b_dirt = 1;
+	dirtify_buffer(name_block, 1);
 	brelse(name_block);
 	inode->i_size = i;
 	inode->i_dirt = 1;
@@ -592,7 +592,7 @@
 		return i;
 	}
 	de->inode = inode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	iput(inode);
@@ -629,7 +629,7 @@
 		return error;
 	}
 	de->inode = oldinode->i_ino;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 1);
 	brelse(bh);
 	iput(dir);
 	oldinode->i_nlink++;
@@ -782,11 +782,11 @@
 		new_inode->i_ctime = CURRENT_TIME;
 		new_inode->i_dirt = 1;
 	}
-	old_bh->b_dirt = 1;
-	new_bh->b_dirt = 1;
+	dirtify_buffer(old_bh, 1);
+	dirtify_buffer(new_bh, 1);
 	if (dir_bh) {
 		PARENT_INO(dir_bh_data) = new_dir->i_ino;
-		dir_bh->b_dirt = 1;
+		dirtify_buffer(dir_bh, 1);
 		old_dir->i_nlink--;
 		old_dir->i_dirt = 1;
 		if (new_inode) {
diff -u --recursive --new-file v1.1.1/linux/fs/sysv/truncate.c linux/fs/sysv/truncate.c
--- v1.1.1/linux/fs/sysv/truncate.c	Wed Jul 21 14:53:18 1993
+++ linux/fs/sysv/truncate.c	Mon Apr 11 13:35:38 1994
@@ -84,7 +84,7 @@
 		if (!indblock)
 			continue;
 		*ind = 0;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		sysv_free_block(sb,indblock);
 	}
 	for (i = 0; i < sb->sv_ind_per_block; i++)
@@ -338,7 +338,7 @@
 			continue;
 		}
 		*ind = 0;
-		indbh->b_dirt = 1;
+		dirtify_buffer(indbh, 1);
 		brelse(bh);
 		sysv_free_block(sb,block);
 	}
diff -u --recursive --new-file v1.1.1/linux/fs/xiafs/bitmap.c linux/fs/xiafs/bitmap.c
--- v1.1.1/linux/fs/xiafs/bitmap.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/xiafs/bitmap.c	Mon Apr 11 13:35:37 1994
@@ -65,7 +65,7 @@
         start_bit=j + (i << 5) + 1;
 	goto repeat;
     }
-    bh->b_dirt=1;
+    dirtify_buffer(bh, 1);
     return j + (i << 5);
 }
 
@@ -245,7 +245,7 @@
         printk("XIA-FS: dev %04x"
 	       " block bit %u (0x%x) already cleared (%s %d)\n",
 	       sb->s_dev, bit, bit, WHERE_ERR);
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     xiafs_unlock_super(sb, sb->u.xiafs_sb.s_zmap_cached);
 }
 
@@ -277,7 +277,7 @@
     }
     clear_buf(bh);
     bh->b_uptodate = 1;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     return tmp;
 }
@@ -305,7 +305,7 @@
         printk("XIA-FS: dev %04x"
 	       "inode bit %ld (0x%lx) already cleared (%s %d)\n",
 	       inode->i_dev, ino, ino, WHERE_ERR);
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     xiafs_unlock_super(sb, sb->u.xiafs_sb.s_imap_cached);
 }
 
diff -u --recursive --new-file v1.1.1/linux/fs/xiafs/file.c linux/fs/xiafs/file.c
--- v1.1.1/linux/fs/xiafs/file.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/xiafs/file.c	Mon Apr 11 13:35:37 1994
@@ -97,7 +97,8 @@
     zones = (left+offset+XIAFS_ZSIZE(inode->i_sb)-1) >> XIAFS_ZSIZE_BITS(inode->i_sb);
     bhb = bhe = buflist;
     if (filp->f_reada) {
-        zones += read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
+        if(zones < read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb)))
+	  zones = read_ahead[MAJOR(inode->i_dev)] >> (1+XIAFS_ZSHIFT(inode->i_sb));
 	if (zone_nr + zones > f_zones)
 	    zones = f_zones - zone_nr;
     }
@@ -240,7 +241,7 @@
 	memcpy_fromfs(cp,buf,c);
 	buf += c;
 	bh->b_uptodate = 1;
-	bh->b_dirt = 1;
+	dirtify_buffer(bh, 0);
 	brelse(bh);
     }
     inode->i_mtime = inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v1.1.1/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v1.1.1/linux/fs/xiafs/inode.c	Tue Feb  1 07:59:53 1994
+++ linux/fs/xiafs/inode.c	Mon Apr 11 13:35:37 1994
@@ -306,7 +306,7 @@
     }
     *lp = tmp;
     inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     return result;
 }
@@ -466,7 +466,7 @@
 	                             | (inode->u.xiafs_i.i_dind_zone  & 0xffffff);
     }
     inode->i_dirt=0;
-    bh->b_dirt=1;
+    dirtify_buffer(bh, 1);
     return bh;
 }
 
diff -u --recursive --new-file v1.1.1/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c
--- v1.1.1/linux/fs/xiafs/namei.c	Wed Dec  1 14:44:15 1993
+++ linux/fs/xiafs/namei.c	Mon Apr 11 13:35:36 1994
@@ -221,7 +221,7 @@
 		memcpy(de->d_name, name, namelen);
 		de->d_name[namelen]=0;
 		de->d_name_len=namelen;
-		bh->b_dirt = 1;
+		dirtify_buffer(bh, 1);
 		*res_dir = de;
 		if (res_pre)
 		    *res_pre = de_pre;
@@ -268,7 +268,7 @@
 	return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     iput(dir);
     *result = inode;
@@ -325,7 +325,7 @@
 	return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     iput(dir);
     iput(inode);
@@ -375,7 +375,7 @@
     de->d_name_len=2;
     de->d_rec_len=XIAFS_ZSIZE(dir->i_sb)-12;
     inode->i_nlink = 2;
-    dir_block->b_dirt = 1;
+    dirtify_buffer(dir_block, 1);
     brelse(dir_block);
     inode->i_mode = S_IFDIR | (mode & S_IRWXUGO & ~current->umask);
     if (dir->i_mode & S_ISGID)
@@ -389,7 +389,7 @@
 	return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     dir->i_nlink++;
     dir->i_dirt = 1;
     iput(dir);
@@ -518,7 +518,7 @@
     if (inode->i_nlink != 2)
         printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR);
     xiafs_rm_entry(de, de_pre);
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     inode->i_nlink=0;
     inode->i_dirt=1;
     dir->i_nlink--;
@@ -566,7 +566,7 @@
 	inode->i_nlink=1;
     }
     xiafs_rm_entry(de, de_pre);
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
     dir->i_dirt = 1;
     inode->i_nlink--;
@@ -611,7 +611,7 @@
     for (i = 0; i < BLOCK_SIZE-1 && (c=*symname++); i++)
         name_block->b_data[i] = c;
     name_block->b_data[i] = 0;
-    name_block->b_dirt = 1;
+    dirtify_buffer(name_block, 1);
     brelse(name_block);
     inode->i_size = i;
     inode->i_dirt = 1;
@@ -624,7 +624,7 @@
 	return -ENOSPC;
     }
     de->d_ino = inode->i_ino;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     iput(dir);
     iput(inode);
@@ -661,7 +661,7 @@
 	return -ENOSPC;
     }
     de->d_ino = oldinode->i_ino;
-    bh->b_dirt = 1;
+    dirtify_buffer(bh, 1);
     brelse(bh);
     iput(dir);
     oldinode->i_nlink++;
@@ -798,11 +798,11 @@
         new_inode->i_nlink--;
 	new_inode->i_dirt = 1;
     }
-    old_bh->b_dirt = 1;
-    new_bh->b_dirt = 1;
+    dirtify_buffer(old_bh, 1);
+    dirtify_buffer(new_bh, 1);
     if (dir_bh) {
         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-	dir_bh->b_dirt = 1;
+	dirtify_buffer(dir_bh, 1);
 	old_dir->i_nlink--;
 	new_dir->i_nlink++;
 	old_dir->i_dirt = 1;
diff -u --recursive --new-file v1.1.1/linux/fs/xiafs/truncate.c linux/fs/xiafs/truncate.c
--- v1.1.1/linux/fs/xiafs/truncate.c	Mon Dec 27 07:37:23 1993
+++ linux/fs/xiafs/truncate.c	Mon Apr 11 13:35:37 1994
@@ -104,7 +104,7 @@
 	    retry = 1;
 	else {
 	    *indp = 0;
-	    ind_bh->b_dirt = 1;
+	    dirtify_buffer(ind_bh, 1);
 	    inode->i_blocks-= 2 << XIAFS_ZSHIFT(inode->i_sb);
 	    xiafs_free_zone(inode->i_sb, tmp);
 	}
@@ -157,7 +157,7 @@
 	retry |= trunc_indirect(inode, 
 				8+((1+i)<<XIAFS_ADDRS_PER_Z_BITS(inode->i_sb)), 
 				dindp);
-	dind_bh->b_dirt = 1;
+	dirtify_buffer(dind_bh, 1);
     }
     dindp = (u_long *) dind_bh->b_data;
     for (i = 0; i < XIAFS_ADDRS_PER_Z(inode->i_sb) && !(*dindp++); i++);
diff -u --recursive --new-file v1.1.1/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.1.1/linux/include/linux/fs.h	Sat Mar 26 14:44:57 1994
+++ linux/include/linux/fs.h	Mon Apr 11 13:44:12 1994
@@ -103,6 +103,7 @@
 #define BLKRRPART 4703 /* re-read partition table */
 #define BLKGETSIZE 4704 /* return device size */
 #define BLKFLSBUF 4705 /* flush buffer cache */
+#define BLKRASET 4706 /* Set read ahead for block device */
 
 /* These are a few other constants  only used by scsi  devices */
 
@@ -210,7 +211,7 @@
 	off_t f_pos;
 	unsigned short f_flags;
 	unsigned short f_count;
-	unsigned short f_reada;
+	off_t f_reada;
 	struct file *f_next, *f_prev;
 	struct inode * f_inode;
 	struct file_operations * f_op;
@@ -359,6 +360,12 @@
 extern int buffermem;
 extern int nr_buffer_heads;
 
+/* Once the full cluster diffs are in place, this will be filled out a bit. */
+extern inline void dirtify_buffer(struct buffer_head * bh, int flag)
+{
+  bh->b_dirt = 1;
+}
+
 extern void check_disk_change(dev_t dev);
 extern void invalidate_inodes(dev_t dev);
 extern void invalidate_buffers(dev_t dev);
@@ -392,7 +399,8 @@
 extern void set_blocksize(dev_t dev, int size);
 extern struct buffer_head * bread(dev_t dev, int block, int size);
 extern unsigned long bread_page(unsigned long addr,dev_t dev,int b[],int size,int prot);
-extern struct buffer_head * breada(dev_t dev,int block,...);
+extern struct buffer_head * breada(dev_t dev,int block, int size, 
+				   unsigned int pos, unsigned int filesize);
 extern void put_super(dev_t dev);
 extern dev_t ROOT_DEV;
 
diff -u --recursive --new-file v1.1.1/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.1.1/linux/kernel/ksyms.c	Thu Apr  7 11:57:32 1994
+++ linux/kernel/ksyms.c	Fri Apr  8 09:18:59 1994
@@ -11,6 +11,11 @@
 
 #define X(name)	{ (void *) &name, "_" #name }
 
+#ifdef CONFIG_FTAPE
+extern char * ftape_big_buffer;
+extern void (*do_floppy)(void);
+#endif
+
 struct {
 	void *addr;
 	const char *name;
diff -u --recursive --new-file v1.1.1/linux/mm/memory.c linux/mm/memory.c
--- v1.1.1/linux/mm/memory.c	Wed Apr  6 11:47:17 1994
+++ linux/mm/memory.c	Mon Apr 11 14:01:16 1994
@@ -902,7 +902,7 @@
 			} else 
 				user_esp = regs->esp;
 		}
-		if (error_code & 1)
+		if (error_code & PAGE_PRESENT)
 			do_wp_page(error_code, address, current, user_esp);
 		else
 			do_no_page(error_code, address, current, user_esp);
@@ -1084,10 +1084,17 @@
 	/* mark usable pages in the mem_map[] */
 	start_low_mem = PAGE_ALIGN(start_low_mem);
 	start_mem = PAGE_ALIGN(start_mem);
-	while (start_low_mem < 0xA0000) {
+
+	/*
+	 * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
+	 * They seem to have done something stupid with the floppy
+	 * controller as well..
+	 */
+	while (start_low_mem < 0x9f000) {
 		mem_map[MAP_NR(start_low_mem)] = 0;
 		start_low_mem += PAGE_SIZE;
 	}
+
 	while (start_mem < high_memory) {
 		mem_map[MAP_NR(start_mem)] = 0;
 		start_mem += PAGE_SIZE;
@@ -1133,21 +1140,18 @@
 
 	i = high_memory >> PAGE_SHIFT;
 	val->totalram = 0;
-	val->freeram = 0;
 	val->sharedram = 0;
+	val->freeram = nr_free_pages << PAGE_SHIFT;
 	val->bufferram = buffermem;
 	while (i-- > 0)  {
 		if (mem_map[i] & MAP_PAGE_RESERVED)
 			continue;
 		val->totalram++;
-		if (!mem_map[i]) {
-			val->freeram++;
+		if (!mem_map[i])
 			continue;
-		}
 		val->sharedram += mem_map[i]-1;
 	}
 	val->totalram <<= PAGE_SHIFT;
-	val->freeram <<= PAGE_SHIFT;
 	val->sharedram <<= PAGE_SHIFT;
 	return;
 }
diff -u --recursive --new-file v1.1.1/linux/net/inet/icmp.c linux/net/inet/icmp.c
--- v1.1.1/linux/net/inet/icmp.c	Thu Apr  7 11:57:32 1994
+++ linux/net/inet/icmp.c	Mon Apr 11 11:30:21 1994
@@ -28,6 +28,7 @@
 #include <linux/fcntl.h>
 #include <linux/socket.h>
 #include <linux/in.h>
+#include <linux/string.h>
 #include "inet.h"
 #include "dev.h"
 #include "ip.h"
diff -u --recursive --new-file v1.1.1/linux/net/inet/ip.c linux/net/inet/ip.c
--- v1.1.1/linux/net/inet/ip.c	Mon Mar 21 19:45:35 1994
+++ linux/net/inet/ip.c	Sun Apr 10 22:28:58 1994
@@ -44,6 +44,7 @@
  *		Linus Torvalds/ :	Memory leakage on fragmentation	
  *		Alan Cox	:	handling.
  *		Gerhard Koerting:	Forwarding uses IP priority hints
+ *		Teemu Rantanen	:	Fragment problems.
  *
  * To Fix:
  *		IP option processing is mostly not needed. ip_forward needs to know about routing rules
@@ -774,6 +775,7 @@
    	skb->len = (len - qp->maclen);
    	skb->h.raw = skb->data;
    	skb->free = 1;
+   	skb->dev = qp->dev;
  
    	/* Copy the original MAC and IP headers into the new buffer. */
    	ptr = (unsigned char *) skb->h.raw;
diff -u --recursive --new-file v1.1.1/linux/net/inet/skbuff.c linux/net/inet/skbuff.c
--- v1.1.1/linux/net/inet/skbuff.c	Tue Apr  5 07:37:25 1994
+++ linux/net/inet/skbuff.c	Mon Apr 11 11:30:21 1994
@@ -23,6 +23,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
+#include <linux/string.h>
 #include "inet.h"
 #include "dev.h"
 #include "ip.h"
