diff -u --recursive --new-file v1.2.4/linux/Makefile linux/Makefile
--- v1.2.4/linux/Makefile	Sun Apr  9 11:59:55 1995
+++ linux/Makefile	Wed Apr 12 15:25:52 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 2
-SUBLEVEL = 4
+SUBLEVEL = 5
 
 ARCH = i386
 
diff -u --recursive --new-file v1.2.4/linux/README linux/README
--- v1.2.4/linux/README	Sun Apr  9 11:59:55 1995
+++ linux/README	Wed Apr 12 08:12:14 1995
@@ -124,15 +124,15 @@
    floppy. 
 
    If you boot Linux from the hard drive, chances are you use LILO which
-   uses the kernel image as specified in the file /etc/lilo/config.  The
+   uses the kernel image as specified in the file /etc/lilo.conf.  The
    kernel image file is usually /vmlinuz, or /zImage, or /etc/zImage. 
    To use the new kernel, copy the new image over the old one (save a
    backup of the original!).  Then, you MUST RERUN LILO to update the
    loading map!! If you don't, you won't be able to boot the new kernel
    image. 
 
-   Reinstalling LILO is usually a matter of running /etc/lilo/install. 
-   You may wish to edit /etc/lilo/config to specify an entry for your
+   Reinstalling LILO is usually a matter of running /sbin/lilo. 
+   You may wish to edit /etc/lilo.conf to specify an entry for your
    old kernel image (say, /vmlinux.old) in case the new one does not
    work.  See the LILO docs for more information. 
 
diff -u --recursive --new-file v1.2.4/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.2.4/linux/drivers/block/ll_rw_blk.c	Sun Apr  9 11:59:56 1995
+++ linux/drivers/block/ll_rw_blk.c	Mon Apr 10 11:22:45 1995
@@ -169,20 +169,40 @@
 
 /*
  * wait until a free request in the first N entries is available.
- * NOTE: interrupts must be disabled on the way in, and will still
- *       be disabled on the way out.
  */
-static inline struct request * get_request_wait(int n, int dev)
+static struct request * __get_request_wait(int n, int dev)
 {
 	register struct request *req;
+	struct wait_queue wait = { current, NULL };
 
-	while ((req = get_request(n, dev)) == NULL) {
+	add_wait_queue(&wait_for_request, &wait);
+	for (;;) {
 		unplug_device(MAJOR(dev)+blk_dev);
-		sleep_on(&wait_for_request);
+		current->state = TASK_UNINTERRUPTIBLE;
+		cli();
+		req = get_request(n, dev);
+		sti();
+		if (req)
+			break;
+		schedule();
 	}
+	remove_wait_queue(&wait_for_request, &wait);
+	current->state = TASK_RUNNING;
 	return req;
 }
 
+static inline struct request * get_request_wait(int n, int dev)
+{
+	register struct request *req;
+
+	cli();
+	req = get_request(n, dev);
+	sti();
+	if (req)
+		return req;
+	return __get_request_wait(n, dev);
+}
+
 /* RO fail safe mechanism */
 
 static long ro_bits[MAX_BLKDEV][8];
@@ -303,9 +323,7 @@
  */
 	max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3);
 
-/* big loop: look for a free request. */
-
-repeat:
+/* look for a free request. */
 	cli();
 
 /* The scsi disk drivers and the IDE driver completely remove the request
@@ -363,23 +381,17 @@
 
 /* find an unused request. */
 	req = get_request(max_req, bh->b_dev);
+	sti();
 
-/* if no request available: if rw_ahead, forget it; otherwise try again. */
-	if (! req) {
+/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
+	if (!req) {
 		if (rw_ahead) {
-			sti();
 			unlock_buffer(bh);
 			return;
 		}
-		unplug_device(major+blk_dev);
-		sleep_on(&wait_for_request);
-		sti();
-		goto repeat;
+		req = __get_request_wait(max_req, bh->b_dev);
 	}
 
-/* we found a request. */
-	sti();
-
 /* fill up the request-info, and add it to the queue */
 	req->cmd = rw;
 	req->errors = 0;
@@ -410,9 +422,7 @@
 		printk("Can't page to read-only device 0x%X\n",dev);
 		return;
 	}
-	cli();
 	req = get_request_wait(NR_REQUEST, dev);
-	sti();
 /* fill up the request-info, and add it to the queue */
 	req->cmd = rw;
 	req->errors = 0;
@@ -533,9 +543,7 @@
 
 	for (i=0; i<nb; i++, buf += buffersize)
 	{
-		cli();
 		req = get_request_wait(NR_REQUEST, dev);
-		sti();
 		req->cmd = rw;
 		req->errors = 0;
 		req->sector = (b[i] * buffersize) >> 9;
diff -u --recursive --new-file v1.2.4/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.2.4/linux/drivers/char/ChangeLog	Thu Mar  9 20:37:34 1995
+++ linux/drivers/char/ChangeLog	Wed Apr 12 21:24:17 1995
@@ -1,3 +1,11 @@
+Wed Apr 12 08:06:16 1995  Theodore Y. Ts'o  <tytso@localhost>
+
+	* serial.c (do_serial_hangup, do_softint, check_modem_status,
+		rs_init):  Hangups are now scheduled via a separate tqueue
+		structure in the async_struct structure, tqueue_hangup.
+		This task is pushed on to the tq_schedule queue, so that
+		it is processed syncronously by the scheduler.
+
 Sat Feb 18 12:13:51 1995  Theodore Y. Ts'o  (tytso@rt-11)
 
 	* tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear
diff -u --recursive --new-file v1.2.4/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.2.4/linux/drivers/char/serial.c	Thu Feb 23 13:31:40 1995
+++ linux/drivers/char/serial.c	Wed Apr 12 21:24:17 1995
@@ -468,7 +468,8 @@
 #ifdef SERIAL_DEBUG_OPEN
 			printk("scheduling hangup...");
 #endif
-			rs_sched_event(info, RS_EVENT_HANGUP);
+			queue_task_irq_off(&info->tqueue_hangup,
+					   &tq_scheduler);
 		}
 	}
 	if (info->flags & ASYNC_CTS_FLOW) {
@@ -722,12 +723,6 @@
 	if (!tty)
 		return;
 
-	if (clear_bit(RS_EVENT_HANGUP, &info->event)) {
-		tty_hangup(tty);
-		wake_up_interruptible(&info->open_wait);
-		info->flags &= ~(ASYNC_NORMAL_ACTIVE|
-				 ASYNC_CALLOUT_ACTIVE);
-	}
 	if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
 		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 		    tty->ldisc.write_wakeup)
@@ -737,6 +732,28 @@
 }
 
 /*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occured.  The path of
+ * hangup processing is:
+ *
+ * 	serial interrupt routine -> (scheduler tqueue) ->
+ * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ * 
+ */
+static void do_serial_hangup(void *private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	tty_hangup(tty);
+}
+
+
+/*
  * This subroutine is called when the RS_TIMER goes off.  It is used
  * by the serial driver to handle ports that do not have an interrupt
  * (irq=0).  This doesn't work very well for 16450's, but gives barely
@@ -2615,6 +2632,8 @@
 		info->blocked_open = 0;
 		info->tqueue.routine = do_softint;
 		info->tqueue.data = info;
+		info->tqueue_hangup.routine = do_serial_hangup;
+		info->tqueue_hangup.data = info;
 		info->callout_termios =callout_driver.init_termios;
 		info->normal_termios = serial_driver.init_termios;
 		info->open_wait = 0;
diff -u --recursive --new-file v1.2.4/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v1.2.4/linux/drivers/net/lance.c	Fri Jan 20 11:34:39 1995
+++ linux/drivers/net/lance.c	Sun Apr  9 10:38:29 1995
@@ -913,7 +913,7 @@
 			lp->rx_ring[entry].base &= 0x03ffffff;
 		} else {
 			/* Malloc up new buffer, compatible with net-2e. */
-			short pkt_len = lp->rx_ring[entry].msg_length;
+			short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4;
 			struct sk_buff *skb;
 
 			skb = alloc_skb(pkt_len, GFP_ATOMIC);
diff -u --recursive --new-file v1.2.4/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v1.2.4/linux/drivers/net/ne.c	Sun Apr  9 11:59:56 1995
+++ linux/drivers/net/ne.c	Wed Apr 12 13:16:11 1995
@@ -1,3 +1,4 @@
+#define rw_bugfix
 /* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
 /*
     Written 1992-94 by Donald Becker.
@@ -375,6 +376,7 @@
 {
     int retries = 0;
     int nic_base = NE_BASE;
+    unsigned long flags;
 
     /* Round the count up for word writes.  Do we need to do this?
        What effect will an odd byte count have on the 8390?
@@ -415,8 +417,13 @@
 	race condition will munge the remote byte count values, and then
 	the ne2k will hang the machine by holding I/O CH RDY because it
 	expects more data. Hopefully fixes the lockups. -- Paul Gortmaker.
+
+	Use save_flags/cli/restore_flags rather than cli/sti to avoid risk
+	of accidentally enabling interrupts which were disabled when we
+	were entered.   Dave Platt <dplatt@3do.com>
     */
 
+    save_flags(flags);
     cli();
     outb_p(count & 0xff, nic_base + EN0_RCNTLO);
     outb_p(count >> 8,   nic_base + EN0_RCNTHI);
@@ -429,7 +436,7 @@
     } else {
 	outsb(NE_BASE + NE_DATAPORT, buf, count);
     }
-    sti();
+    restore_flags(flags);
 
 #ifdef CONFIG_NE_SANITY
     /* This was for the ALPHA version only, but enough people have
diff -u --recursive --new-file v1.2.4/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v1.2.4/linux/drivers/net/wavelan.c	Wed Feb 22 16:25:04 1995
+++ linux/drivers/net/wavelan.c	Tue Apr 11 07:45:38 1995
@@ -71,7 +71,7 @@
 
 extern int		wavelan_probe(device *);	/* See Space.c */
 
-static char		*version	= "wavelan.c:v6 22/2/95\n";
+static char		*version	= "wavelan.c:v7 95/4/8\n";
 
 /*
  * Entry point forward declarations.
@@ -508,6 +508,9 @@
 	ac_cfg_t	cfg;
 	ac_ias_t	ias;
 
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_hardware_reset(dev=0x%x)\n", dev->name, (unsigned int)dev);
+
 	ioaddr = dev->base_addr;
 	lp = (net_local *)dev->priv;
 
@@ -565,7 +568,12 @@
 	}
 
 	if (i <= 0)
+	{
 		printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name);
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
+		return -1;
+	}
 
 	for (i = 15; i > 0; i--)
 	{
@@ -578,7 +586,12 @@
 	}
 
 	if (i <= 0)
+	{
 		printk("%s: wavelan_hardware_reset(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
+		return -1;
+	}
 
 	wavelan_ack(dev);
 
@@ -588,12 +601,18 @@
 	obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
 
 	if (wavelan_synchronous_cmd(dev, "diag()") == -1)
+	{
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
 		return -1;
+	}
 
 	obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
 	if (cb.ac_status & AC_SFLD_FAIL)
 	{
 		printk("%s: wavelan_hardware_reset(): i82586 Self Test failed.\n", dev->name);
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
 		return -1;
 	}
 
@@ -654,7 +673,12 @@
 	obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cfg, sizeof(cfg));
 
 	if (wavelan_synchronous_cmd(dev, "reset()-configure") == -1)
+	{
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
+
 		return -1;
+	}
 
 	memset(&ias, 0x00, sizeof(ias));
 	ias.ias_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_ia_setup);
@@ -663,19 +687,24 @@
 	obram_write(ioaddr, OFFSET_CU, (unsigned char *)&ias, sizeof(ias));
 
 	if (wavelan_synchronous_cmd(dev, "reset()-address") == -1)
+	{
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_hardware_reset(): -1\n", dev->name);
+
 		return -1;
+	}
 
 	wavelan_ints_on(dev);
 
 	if (wavelan_debug > 4)
-	{
 		wavelan_scb_show(ioaddr);
-		printk("%s: Initialized WaveLAN.\n", dev->name);
-	}
 
 	wavelan_ru_start(dev);
 	wavelan_cu_start(dev);
 
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_hardware_reset(): 0\n", dev->name);
+
 	return 0;
 }
 
@@ -708,6 +737,7 @@
 wavelan_probe(device *dev)
 {
 	int			i;
+	int			r;
 	short			base_addr;
 	static unsigned short	iobase[]	=
 	{
@@ -721,10 +751,17 @@
 		0x390,
 	};
 
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n", dev->name, (unsigned int)dev, (unsigned int)dev->base_addr);
+
 #if	STRUCT_CHECK == 1
 	if (wavelan_struct_check() != (char *)0)
 	{
 		printk("%s: structure/compiler botch: \"%s\"\n", dev->name, wavelan_struct_check());
+
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_probe(): ENODEV\n", dev->name);
+
 		return ENODEV;
 	}
 #endif	/* STRUCT_CHECK == 1 */
@@ -732,16 +769,25 @@
 	base_addr = dev->base_addr;
 
 	if (base_addr < 0)
+	{
 		/*
 		 * Don't probe at all.
 		 */
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_probe(): ENXIO\n", dev->name);
 		return ENXIO;
+	}
 
 	if (base_addr > 0x100)
+	{
 		/*
 		 * Check a single specified location.
 		 */
-		return wavelan_probe1(dev, base_addr);
+		r = wavelan_probe1(dev, base_addr);
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_probe(): %d\n", dev->name, r);
+		return r;
+	}
 
 	for (i = 0; i < nels(iobase); i++)
 	{
@@ -749,9 +795,16 @@
 			continue;
 
 		if (wavelan_probe1(dev, iobase[i]) == 0)
+		{
+			if (wavelan_debug > 0)
+				printk("%s: <-wavelan_probe(): 0\n", dev->name);
 			return 0;
+		}
 	}
 
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_probe(): ENODEV\n", dev->name);
+
 	return ENODEV;
 }
 
@@ -764,6 +817,9 @@
 	int		i;
 	net_local	*lp;
 
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_probe1(dev=0x%x, ioaddr=0x%x)\n", dev->name, (unsigned int)dev, ioaddr);
+
 	wavelan_reset(ioaddr);
 
 	psa_read(ioaddr, HACR_DEFAULT, 0, (unsigned char *)&psa, sizeof(psa));
@@ -780,13 +836,19 @@
 		||
 		psa.psa_univ_mac_addr[2] != SA_ADDR2
 	)
+	{
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_probe1(): ENODEV\n", dev->name);
 		return ENODEV;
+	}
 
 	printk("%s: WaveLAN at %#x,", dev->name, ioaddr);
 
 	if ((irq = wavelan_map_irq(ioaddr, psa.psa_int_req_no)) == -1)
 	{
 		printk(" could not wavelan_map_irq(0x%x, %d).\n", ioaddr, psa.psa_int_req_no);
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_probe1(): EAGAIN\n", dev->name);
 		return EAGAIN;
 	}
 
@@ -871,7 +933,7 @@
 
 	printk("\n");
 
-	if (wavelan_debug)
+	if (wavelan_debug > 0)
 		printk(version);
 
 	dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
@@ -915,6 +977,9 @@
 
 	dev->mtu = WAVELAN_MTU;
 
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_probe1(): 0\n", dev->name);
+
 	return 0;
 }
 
@@ -1074,12 +1139,21 @@
 {
 	unsigned short	ioaddr;
 	net_local	*lp;
+	unsigned long	x;
+	int		r;
+
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_open(dev=0x%x)\n", dev->name, (unsigned int)dev);
 
 	ioaddr = dev->base_addr;
 	lp = (net_local *)dev->priv;
 
 	if (dev->irq == 0)
+	{
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_open(): -ENXIO\n", dev->name);
 		return -ENXIO;
+	}
 
 	if
 	(
@@ -1092,23 +1166,35 @@
 	)
 	{
 		irq2dev_map[dev->irq] = (device *)0;
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_open(): -EAGAIN\n", dev->name);
 		return -EAGAIN;
 	}
 
-	if (wavelan_hardware_reset(dev) == -1)
+	x = wavelan_splhi();
+	if ((r = wavelan_hardware_reset(dev)) != -1)
+	{
+		dev->interrupt = 0;
+		dev->start = 1;
+	}
+	wavelan_splx(x);
+
+	if (r == -1)
 	{
 		free_irq(dev->irq);
 		irq2dev_map[dev->irq] = (device *)0;
+		if (wavelan_debug > 0)
+			printk("%s: <-wavelan_open(): -EAGAIN(2)\n", dev->name);
 		return -EAGAIN;
 	}
 
-	dev->interrupt = 0;
-	dev->start = 1;
-
 #if	defined(MODULE)
 	MOD_INC_USE_COUNT;
 #endif	/* defined(MODULE) */
 
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_open(): 0\n", dev->name);
+
 	return 0;
 }
 
@@ -1438,7 +1524,7 @@
 			}
 #endif	/* 0 */
 
-			if (wavelan_debug > 0)
+			if (wavelan_debug > 5)
 			{
 				unsigned char	addr[WAVELAN_ADDR_SIZE];
 				unsigned short	ltype;
@@ -1723,14 +1809,14 @@
 		 * This will clear it -- ignored for now.
 		 */
 		mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status));
-		if (wavelan_debug > 4)
+		if (wavelan_debug > 0)
 			printk("%s: warning: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", dev->name, dce_status);
 	}
 
 	if ((hasr & HASR_82586_INTR) == 0)
 	{
 		dev->interrupt = 0;
-		if (wavelan_debug > 4)
+		if (wavelan_debug > 0)
 			printk("%s: warning: wavelan_interrupt() but (hasr & HASR_82586_INTR) == 0.\n", dev->name);
 		return;
 	}
@@ -1746,7 +1832,7 @@
 
 	set_chan_attn(ioaddr, lp->hacr);
 
-	if (wavelan_debug > 4)
+	if (wavelan_debug > 5)
 		printk("%s: interrupt, status 0x%04x.\n", dev->name, status);
 
 	if ((status & SCB_ST_CX) == SCB_ST_CX)
@@ -1804,6 +1890,9 @@
 	net_local	*lp;
 	unsigned short	scb_cmd;
 
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_close(dev=0x%x)\n", dev->name, (unsigned int)dev);
+
 	ioaddr = dev->base_addr;
 	lp = (net_local *)dev->priv;
 
@@ -1831,6 +1920,9 @@
 	MOD_DEC_USE_COUNT;
 #endif	/* defined(MODULE) */
 
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_close(): 0\n", dev->name);
+
 	return 0;
 }
 
@@ -1856,6 +1948,9 @@
 	net_local	*lp;
 	unsigned long	x;
 
+	if (wavelan_debug > 0)
+		printk("%s: ->wavelan_set_multicast_list(dev=0x%x, num_addrs=%d, addrs=0x%x)\n", dev->name, (unsigned int)dev, num_addrs, (unsigned int)addrs);
+
 	lp = (net_local *)dev->priv;
 
 	switch (num_addrs)
@@ -1888,6 +1983,9 @@
 		 */
 		break;
 	}
+
+	if (wavelan_debug > 0)
+		printk("%s: <-wavelan_set_multicast_list()\n", dev->name);
 }
 
 /*
@@ -2330,6 +2428,7 @@
  *	Matthew Geier (matthew@cs.usyd.edu.au),
  *	Remo di Giovanni (remo@cs.usyd.edu.au),
  *	Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de),
+ *	Vipul Gupta (vgupta@cs.binghamton.edu),
  *	Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM),
  *	Tim Nicholson (tim@cs.usyd.edu.au),
  *	Ian Parkin (ian@cs.usyd.edu.au),
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.2.4/linux/drivers/scsi/Makefile	Tue Apr  4 09:05:34 1995
+++ linux/drivers/scsi/Makefile	Tue Apr 11 07:56:24 1995
@@ -86,9 +86,11 @@
 SCSI_SRCS := $(SCSI_SRCS) buslogic.c
 endif
 
+SCSI_SRCS := $(SCSI_SRCS) eata_dma.c
 ifdef CONFIG_SCSI_EATA_DMA
 SCSI_OBJS := $(SCSI_OBJS) eata_dma.o
-SCSI_SRCS := $(SCSI_SRCS) eata_dma.c
+else
+SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) eata_dma.o
 endif
 
 ifdef CONFIG_SCSI_U14_34F
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c
--- v1.2.4/linux/drivers/scsi/buslogic.c	Mon Jan 23 10:38:29 1995
+++ linux/drivers/scsi/buslogic.c	Wed Apr 12 08:12:14 1995
@@ -56,16 +56,18 @@
  *	BT-747D - 747S + differential termination.
  *	BT-757S - 747S + WIDE SCSI.
  *	BT-757D - 747D + WIDE SCSI.
- *	BT-445S - VESA bus-master FAST SCSI with active termination and floppy
- *		  support.
+ *	BT-445S - VESA bus-master FAST SCSI with active termination
+ *		  and floppy support.
  *	BT-445C - 445S + enhanced BIOS & firmware options.
- *	BT-946C - PCI bus-master FAST SCSI. (??? Nothing else known.)
+ *	BT-946C - PCI bus-master FAST SCSI.
+ *	BT-956C - PCI bus-master FAST/WIDE SCSI.
  *
  *    ??? I believe other boards besides the 445 now have a "C" model, but I
  *    have no facts on them.
  *
  *    This driver SHOULD support all of these boards.  It has only been tested
- *    with a 747S and 445S.
+ *    with a 747S, 445S, 946C, and 956C; there is no PCI-specific support as
+ *    yet.
  *
  *    Should you require further information on any of these boards, BusLogic
  *    can be reached at (408)492-9090.  Their BBS # is (408)492-1984 (maybe BBS
@@ -118,7 +120,7 @@
    The test is believed to fail on at least some AMI BusLogic clones. */
 /* #define BIOS_TRANSLATION_OVERRIDE BIOS_TRANSLATION_BIG */
 
-#define BUSLOGIC_VERSION "1.14"
+#define BUSLOGIC_VERSION "1.15"
 
 /* Not a random value - if this is too large, the system hangs for a long time
    waiting for something to happen if a board is not installed. */
@@ -137,11 +139,13 @@
 /* Since the SG list is malloced, we have to limit the length. */
 #define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain))
 
-/* ??? Arbitrary.  If we can dynamically allocate the mailbox arrays, I may
-   bump up this number. */
-#define BUSLOGIC_MAILBOXES 16
+/* Since the host adapters have room to buffer 32 commands internally, there
+   is some virtue in setting BUSLOGIC_MAILBOXES to 32.  The maximum value
+   appears to be 255, since the Count parameter to the Initialize Extended
+   Mailbox command is limited to one byte. */
+#define BUSLOGIC_MAILBOXES 32
 
-#define BUSLOGIC_CMDLUN 4		/* ??? Arbitrary */
+#define BUSLOGIC_CMDLUN 4	/* Arbitrary, but seems to work well. */
 
 /* BusLogic boards can be configured for quite a number of port addresses (six
    to be exact), but I generally do not want the driver poking around at
@@ -165,8 +169,8 @@
 struct hostdata {
     unsigned int bus_type;
     unsigned int bios_translation: 1;	/* BIOS mapping (for compatibility) */
-    size_t last_mbi_used;
-    size_t last_mbo_used;
+    int last_mbi_used;
+    int last_mbo_used;
     char model[7];
     char firmware_rev[6];
     Scsi_Cmnd *sc[BUSLOGIC_MAILBOXES];
@@ -425,174 +429,131 @@
     return "BusLogic SCSI driver " BUSLOGIC_VERSION;
 }
 
-/* A "high" level interrupt handler. */
+/*
+  This is a major rewrite of the interrupt handler to support the newer
+  and faster PCI cards.  While the previous interrupt handler was supposed
+  to handle multiple incoming becoming available mailboxes during the same
+  interrupt, my testing showed that in practice only a single mailbox was
+  ever made available.  With the 946C and 956C, multiple incoming mailboxes
+  being ready for processing during a single interrupt occurs much more
+  frequently, and so care must be taken to avoid race conditions managing
+  the Host Adapter Interrupt Register, which can lead to lost interrupts.
+
+  Leonard N. Zubkoff, 23-Mar-95
+*/
+
 static void buslogic_interrupt(int irq, struct pt_regs * regs)
 {
-    void (*my_done)(Scsi_Cmnd *) = NULL;
-    int errstatus, mbistatus = MBX_NOT_IN_USE, number_serviced, found;
-    size_t mbi, mbo = 0;
+    int mbi, saved_mbo[BUSLOGIC_MAILBOXES];
+    int base, interrupt_flags, found, i;
     struct Scsi_Host *shpnt;
     Scsi_Cmnd *sctmp;
-    unsigned long flags;
-    int base, flag;
-    int needs_restart;
     struct mailbox *mb;
     struct ccb *ccb;
 
     shpnt = host[irq - 9];
-    if (!shpnt)
-	panic("buslogic_interrupt: NULL SCSI host entry");
+    if (shpnt == NULL)
+      panic("buslogic_interrupt: NULL SCSI host entry");
 
     mb = HOSTDATA(shpnt)->mb;
     ccb = HOSTDATA(shpnt)->ccbs;
     base = shpnt->io_port;
 
-#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
-    flag = inb(INTERRUPT(base));
+    /*
+      This interrupt handler is now specified to use the SA_INTERRUPT
+      protocol, so interrupts are inhibited on entry until explicitly
+      allowed again.  Read the Host Adapter Interrupt Register, and
+      complain if there is no pending interrupt being signaled.
+    */
+
+    interrupt_flags = inb(INTERRUPT(base));
+
+    if (!(interrupt_flags & INTV))
+      {
+	buslogic_printk("interrupt received, but INTV not set\n");
+	return;
+      }
+
+    /*
+      Reset the Host Adapter Interrupt Register.  It appears to be
+      important that this is only done once per interrupt to avoid
+      losing interrupts under heavy loads.
+    */
 
-    buslogic_printk("");
-    if (!(flag & INTV))
-	printk("no interrupt? ");
-    if (flag & IMBL)
-	printk("IMBL ");
-    if (flag & MBOR)
-	printk("MBOR ");
-    if (flag & CMDC)
-	printk("CMDC ");
-    if (flag & RSTS)
-	printk("RSTS ");
-    printk("status %02X\n", inb(STATUS(base)));
-#endif
-
-    number_serviced = 0;
-    needs_restart = 0;
-
-    for (;;) {
-	flag = inb(INTERRUPT(base));
-
-	/* Check for unusual interrupts.  If any of these happen, we should
-	   probably do something special, but for now just printing a message
-	   is sufficient.  A SCSI reset detected is something that we really
-	   need to deal with in some way. */
-	if (flag & (MBOR | CMDC | RSTS)) {
-	    buslogic_printk("unusual flag:");
-	    if (flag & MBOR)
-		printk(" MBOR");
-	    if (flag & CMDC)
-		printk(" CMDC");
-	    if (flag & RSTS) {
-		needs_restart = 1;
-		printk(" RSTS");
-	    }
-	    printk("\n");
-	}
-
-	INTR_RESET(base);
-
-	save_flags(flags);
-	cli();
-
-	mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
-	if (mbi >= 2 * BUSLOGIC_MAILBOXES)
-	    mbi = BUSLOGIC_MAILBOXES;
-
-	/* I use the "found" variable as I like to keep cli/sti pairs at the
-	   same block level.  Debugging dropped sti's is no fun... */
-
-	found = FALSE;
-	do {
-	    if (mb[mbi].status != MBX_NOT_IN_USE) {
-		found = TRUE;
-		break;
-	    }
-	    mbi++;
-	    if (mbi >= 2 * BUSLOGIC_MAILBOXES)
-		mbi = BUSLOGIC_MAILBOXES;
-	} while (mbi != HOSTDATA(shpnt)->last_mbi_used);
-
-	if (found) {
-	    mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
-	    mbistatus = mb[mbi].status;
-	    mb[mbi].status = MBX_NOT_IN_USE;
-	    HOSTDATA(shpnt)->last_mbi_used = mbi;
-	}
-
-	restore_flags(flags);
-
-	if (!found) {
-	    /* Hmm, no mail.  Must have read it the last time around. */
-	    if (!number_serviced && !needs_restart)
-		buslogic_printk("interrupt received, but no mail.\n");
-	    /* We detected a reset.  Restart all pending commands for devices
-	       that use the hard reset option. */
-	    if (needs_restart)
-		restart(shpnt);
-	    return;
-	}
-
-#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
-	if (ccb[mbo].tarstat || ccb[mbo].hastat)
-	    buslogic_printk("returning %08X (status %d).\n",
-			    ((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat,
-			    mb[mbi].status);
-#endif
-
-	if (mbistatus == MBX_COMPLETION_NOT_FOUND)
-	    continue;
-
-#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
-	buslogic_printk("...done %u %u\n", mbo, mbi);
-#endif
+    INTR_RESET(base);
 
+    if (interrupt_flags & RSTS)
+      {
+	restart(shpnt);
+	return;
+      }
+
+    /*
+      With interrupts still inhibited, scan through the incoming mailboxes
+      in strict round robin fashion saving the status information and
+      then freeing the mailbox.  A second pass over the completed commands
+      will be made separately to complete their processing.
+    */
+
+    mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
+    if (mbi >= 2*BUSLOGIC_MAILBOXES)
+      mbi = BUSLOGIC_MAILBOXES;
+
+    found = 0;
+
+    while (mb[mbi].status != MBX_NOT_IN_USE && found < BUSLOGIC_MAILBOXES)
+      {
+	int mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
+	int result = 0;
+
+	saved_mbo[found++] = mbo;
+
+	if (mb[mbi].status != MBX_COMPLETION_OK)
+	  result = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
+
+	HOSTDATA(shpnt)->sc[mbo]->result = result;
+
+	mb[mbi].status = MBX_NOT_IN_USE;
+
+	HOSTDATA(shpnt)->last_mbi_used = mbi;
+
+	if (++mbi >= 2*BUSLOGIC_MAILBOXES)
+	  mbi = BUSLOGIC_MAILBOXES;
+      }
+
+    /*
+      With interrupts no longer inhibited, iterate over the completed
+      commands freeing resources and calling the completion routines.
+      Since we exit upon completion of this loop, there is no need to
+      inhibit interrupts before exit, as this will be handled by the
+      fast interrupt assembly code we return to.
+    */
+
+    sti();
+
+    for (i = 0; i < found; i++)
+      {
+	int mbo = saved_mbo[i];
 	sctmp = HOSTDATA(shpnt)->sc[mbo];
-
-	if (!sctmp || !sctmp->scsi_done) {
-	    buslogic_printk("unexpected interrupt.\n");
-	    buslogic_printk("tarstat=%02X, hastat=%02X id=%d lun=%d ccb#=%u\n",
-			    ccb[mbo].tarstat, ccb[mbo].hastat,
-			    ccb[mbo].id, ccb[mbo].lun, mbo);
-	    return;
-	}
-
-	my_done = sctmp->scsi_done;
+	/*
+	  First, free any storage allocated for a scatter/gather
+	  data segment list.
+	*/
 	if (sctmp->host_scribble)
-	    scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
-
-	/* ??? more error checking left out here */
-	if (mbistatus != MBX_COMPLETION_OK) {
-	    /* ??? This is surely wrong, but I don't know what's right. */
-	    errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
-	} else
-	    errstatus = 0;
-
-#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
-	if (errstatus)
-	    buslogic_printk("error: %04X %04X\n",
-			    ccb[mbo].hastat, ccb[mbo].tarstat);
-
-	if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) {
-	    size_t i;
-
-	    buslogic_printk("sense:");
-	    for (i = 0; i < sizeof sctmp->sense_buffer; i++)
-		printk(" %02X", sctmp->sense_buffer[i]);
-	    printk("\n");
-	}
-
-	if (errstatus)
-	    buslogic_printk("returning %08X.\n", errstatus);
-#endif
-
-	sctmp->result = errstatus;
-	HOSTDATA(shpnt)->sc[mbo] = NULL;	/* This effectively frees up
-						   the mailbox slot, as far as
-						   queuecommand is
-						   concerned. */
-	my_done(sctmp);
-	number_serviced++;
-    }
+	  scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
+	/*
+	  Next, call the SCSI command completion handler.
+	*/
+	sctmp->scsi_done(sctmp);
+	/*
+	  Finally, mark the SCSI Command as completed so it may be reused
+	  for another command by buslogic_queuecommand.
+	*/
+	HOSTDATA(shpnt)->sc[mbo] = NULL;
+      }
 }
 
+
 /* ??? Why does queuecommand return a value?  scsi.c never looks at it... */
 int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
 {
@@ -605,9 +566,10 @@
     int bufflen = scpnt->request_bufflen;
     int mbo;
     unsigned long flags;
-    struct mailbox *mb;
-    struct ccb *ccb;
     struct Scsi_Host *shpnt = scpnt->host;
+    struct mailbox *mb = HOSTDATA(shpnt)->mb;
+    struct ccb *ccb;
+
 
 #if (BUSLOGIC_DEBUG & BD_COMMAND)
     if (target > 1) {
@@ -651,9 +613,6 @@
     }
 #endif
 
-    mb = HOSTDATA(shpnt)->mb;
-    ccb = HOSTDATA(shpnt)->ccbs;
-
     /* Use the outgoing mailboxes in a round-robin fashion, because this
        is how the host adapter will scan for them. */
 
@@ -693,12 +652,14 @@
     buslogic_printk("sending command (%d %08X)...", mbo, done);
 #endif
 
+    ccb = &HOSTDATA(shpnt)->ccbs[mbo];
+
     /* This gets trashed for some reason */
-    mb[mbo].ccbptr = &ccb[mbo];
+    mb[mbo].ccbptr = ccb;
 
-    memset(&ccb[mbo], 0, sizeof (struct ccb));
+    memset(ccb, 0, sizeof (struct ccb));
 
-    ccb[mbo].cdblen = scpnt->cmd_len;		/* SCSI Command Descriptor
+    ccb->cdblen = scpnt->cmd_len;		/* SCSI Command Descriptor
 						   Block Length */
 
     direction = 0;
@@ -707,14 +668,14 @@
     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 	direction = 16;
 
-    memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
+    memcpy(ccb->cdb, cmd, ccb->cdblen);
 
     if (scpnt->use_sg) {
 	struct scatterlist *sgpnt;
 	struct chain *cptr;
 	size_t i;
 
-	ccb[mbo].op = CCB_OP_INIT_SG;	/* SCSI Initiator Command
+	ccb->op = CCB_OP_INIT_SG;	/* SCSI Initiator Command
 					   w/scatter-gather */
 	scpnt->host_scribble
 	    = (unsigned char *)scsi_malloc(BUSLOGIC_SG_MALLOC);
@@ -735,8 +696,8 @@
 	    cptr[i].dataptr = sgpnt[i].address;
 	    cptr[i].datalen = sgpnt[i].length;
 	}
-	ccb[mbo].datalen = scpnt->use_sg * sizeof (struct chain);
-	ccb[mbo].dataptr = cptr;
+	ccb->datalen = scpnt->use_sg * sizeof (struct chain);
+	ccb->dataptr = cptr;
 #if (BUSLOGIC_DEBUG & BD_COMMAND)
 	{
 	    unsigned char *ptr;
@@ -749,27 +710,26 @@
 	}
 #endif
     } else {
-	ccb[mbo].op = CCB_OP_INIT;	/* SCSI Initiator Command */
+	ccb->op = CCB_OP_INIT;	/* SCSI Initiator Command */
 	scpnt->host_scribble = NULL;
 	CHECK_DMA_ADDR(shpnt->unchecked_isa_dma, buff, goto baddma);
-	ccb[mbo].datalen = bufflen;
-	ccb[mbo].dataptr = buff;
+	ccb->datalen = bufflen;
+	ccb->dataptr = buff;
     }
-    ccb[mbo].id = target;
-    ccb[mbo].lun = lun;
-    ccb[mbo].dir = direction;
-    ccb[mbo].rsalen = sizeof scpnt->sense_buffer;
-    ccb[mbo].senseptr = scpnt->sense_buffer;
-    ccb[mbo].linkptr = NULL;
-    ccb[mbo].commlinkid = 0;
+    ccb->id = target;
+    ccb->lun = lun;
+    ccb->dir = direction;
+    ccb->rsalen = sizeof scpnt->sense_buffer;
+    ccb->senseptr = scpnt->sense_buffer;
+    /* ccbcontrol, commlinkid, and linkptr are 0 due to above memset. */
 
 #if (BUSLOGIC_DEBUG & BD_COMMAND)
     {
 	size_t i;
 
 	buslogic_printk("sending...");
-	for (i = 0; i < sizeof ccb[mbo] - 10; i++)
-	    printk(" %02X", ((unsigned char *)&ccb[mbo])[i]);
+	for (i = 0; i < sizeof(struct ccb) - 10; i++)
+	    printk(" %02X", ((unsigned char *)ccb)[i]);
 	printk("\n");
     }
 #endif
@@ -1255,7 +1215,8 @@
 
 	    save_flags(flags);
 	    cli();
-	    if (request_irq(irq, buslogic_interrupt, 0, "buslogic")) {
+	    if (request_irq(irq, buslogic_interrupt,
+			    SA_INTERRUPT, "buslogic")) {
 		buslogic_printk("unable to allocate IRQ for "
 				"BusLogic controller.\n");
 		restore_flags(flags);
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v1.2.4/linux/drivers/scsi/eata_dma.c	Tue Feb 14 08:02:58 1995
+++ linux/drivers/scsi/eata_dma.c	Wed Apr 12 21:03:23 1995
@@ -44,13 +44,14 @@
  * Thanks also to Greg Hosler who did a lot of testing and  *
  * found quite a number of bugs during the development.     *
  ************************************************************
- *  last change: 95/02/13       OS: Linux 1.1.91 or higher  *
+ *  last change: 95/04/10       OS: Linux 1.2.00 or higher  *
  ************************************************************/
 
 /* Look in eata_dma.h for configuration and revision information */
 
 #ifdef MODULE
 #include <linux/module.h>
+#include <linux/version.h>
 #endif
  
 #include <linux/kernel.h>
@@ -61,6 +62,7 @@
 #include <linux/in.h>
 #include <linux/bios32.h>
 #include <linux/pci.h>
+#include <asm/types.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include "../block/blk.h"
@@ -87,10 +89,13 @@
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static unchar reg_IRQL[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static struct eata_sp status[MAXIRQ];	/* Statuspacket array   */
+static struct eata_sp *status = 0;   /* Statuspacket array   */
+static void *dma_scratch = 0;
 
 static uint internal_command_finished = TRUE;
 static unchar HBA_interpret = FALSE;
+static u32 fake_int_base;
+static u32 fake_int_result;
 static struct geom_emul geometry;	/* Drive 1 & 2 geometry */
 
 static ulong int_counter = 0;
@@ -101,6 +106,14 @@
     return;
 }	
 
+void eata_fake_int_handler(s32 irq, struct pt_regs * regs)
+{
+    fake_int_result = inb(fake_int_base + HA_RSTATUS);
+    DBG(DBG_INTR3, printk("eata_fake_int_handler called irq%ld base %#lx res %#lx\n", 
+			  irq, fake_int_base, fake_int_result));
+    return;
+}
+
 #if EATA_DMA_PROC 
 #include "eata_dma_proc.c"
 #endif
@@ -109,6 +122,9 @@
 {
   if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
   else reg_IRQ[sh->irq]--;
+    
+    scsi_init_free((void *)status, 512);
+    
   if (SD(sh)->channel == 0) {
       if (sh->dma_channel != 0xff) free_dma(sh->dma_channel);
       if (sh->io_port && sh->n_io_port)
@@ -125,7 +141,7 @@
 
 void eata_int_handler(int irq, struct pt_regs * regs)
 {
-    uint i, result;
+    uint i, result = 0;
     uint hba_stat, scsi_stat, eata_stat;
     Scsi_Cmnd *cmd;
     struct eata_ccb *cp;
@@ -183,21 +199,25 @@
 			     eata_stat, hba_stat));
 
 	switch (hba_stat) {
-	case 0x00:		/* NO Error */
+	case HA_NO_ERROR:       /* NO Error */
 	    if (scsi_stat == CONDITION_GOOD
 		&& cmd->device->type == TYPE_DISK
 		&& (HD(cmd)->t_state[cmd->target] == RESET))
 	        result = DID_BUS_BUSY << 16;	    
+            else if (scsi_stat == GOOD)
+	      HD(cmd)->t_state[cmd->target] = FALSE;
+	    else if (scsi_stat == CHECK_CONDITION
+                     && cmd->device->type == TYPE_DISK
+                     && (cmd->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
+	      result = DID_BUS_BUSY << 16;
 	    else
 	        result = DID_OK << 16;
-	    if (scsi_stat == GOOD)
-		HD(cmd)->t_state[cmd->target] = FALSE;
-	    HD(cmd)->t_timeout[cmd->target] = 0;
+	    HD(cmd)->t_timeout[cmd->target] = FALSE;
 	    break;
-	case 0x01:		/* Selection Timeout */
+	case HA_ERR_SEL_TO:		/* Selection Timeout */
 	    result = DID_BAD_TARGET << 16;  
 	    break;
-	case 0x02:		/* Command Timeout   */
+	case HA_ERR_CMD_TO:		/* Command Timeout   */
 	    if (HD(cmd)->t_timeout[cmd->target] > 1)
 		result = DID_ERROR << 16;
 	    else {
@@ -205,7 +225,8 @@
 		HD(cmd)->t_timeout[cmd->target]++;
 	    }
 	    break;
-	case 0x03:		/* SCSI Bus Reset Received */
+        case HA_ERR_RESET:              /* SCSI Bus Reset Received */
+        case HA_INIT_POWERUP:           /* Initial Controller Power-up */
 	    if (cmd->device->type != TYPE_TAPE)
 		result = DID_BUS_BUSY << 16;
 	    else
@@ -214,23 +235,19 @@
 	    for (i = 0; i < MAXTARGET; i++)
 		HD(cmd)->t_state[i] = RESET;
 	    break;
-	case 0x07:		/* Bus Parity Error */
-	case 0x0c:		/* Controller Ram Parity */
-	case 0x04:		/* Initial Controller Power-up */
-	case 0x05:		/* Unexpected Bus Phase */
-	case 0x06:		/* Unexpected Bus Free */
-	case 0x08:		/* SCSI Hung */
-	case 0x09:		/* Unexpected Message Reject */
-	case 0x0a:		/* SCSI Bus Reset Stuck */
-	case 0x0b:		/* Auto Request-Sense Failed */
+        case HA_UNX_BUSPHASE:       /* Unexpected Bus Phase */
+        case HA_UNX_BUS_FREE:       /* Unexpected Bus Free */
+        case HA_BUS_PARITY:         /* Bus Parity Error */
+        case HA_SCSI_HUNG:          /* SCSI Hung */
+        case HA_UNX_MSGRJCT:        /* Unexpected Message Reject */
+        case HA_RESET_STUCK:        /* SCSI Bus Reset Stuck */
+        case HA_RSENSE_FAIL:        /* Auto Request-Sense Failed */
+        case HA_PARITY_ERR:         /* Controller Ram Parity */
 	default:
 	    result = DID_ERROR << 16;
 	    break;
 	}
-	cmd->result = result | scsi_stat; 
-        if (in_scan_scsis && scsi_stat == CHECK_CONDITION && 
-	    (cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION) 
-	    cmd->result |= (DRIVER_SENSE << 24);
+	cmd->result = result | (scsi_stat << 1); 
 
 #if DBG_INTR2
 	if (scsi_stat || result || hba_stat || eata_stat != 0x50) 
@@ -262,14 +279,14 @@
 
     while (inb(base + HA_RAUXSTAT) & HA_ABUSY)
         if (--loop == 0)
-            return(TRUE);
+            return(FALSE);
 
     outb(addr & 0x000000ff, base + HA_WDMAADDR);
     outb((addr & 0x0000ff00) >> 8, base + HA_WDMAADDR + 1);
     outb((addr & 0x00ff0000) >> 16, base + HA_WDMAADDR + 2);
     outb((addr & 0xff000000) >> 24, base + HA_WDMAADDR + 3);
     outb(command, base + HA_WCOMMAND);
-    return(FALSE);
+    return(TRUE);
 }
 
 int eata_queue(Scsi_Cmnd * cmd, void *(done) (Scsi_Cmnd *))
@@ -337,10 +354,10 @@
     case FORMAT_UNIT:       case REASSIGN_BLOCKS: case RESERVE:
     case SEARCH_EQUAL:      case SEARCH_HIGH:     case SEARCH_LOW:
     case WRITE_6:           case WRITE_10:        case WRITE_VERIFY:
-    case 0x3f:              case 0x41:            case 0xb1:
-    case 0xb0:              case 0xb2:            case 0xaa:
-    case 0xae:              case 0x24:            case 0x38:
-    case 0x3d:              case 0xb6:            
+    case UPDATE_BLOCK:      case WRITE_LONG:      case WRITE_SAME:      
+    case SEARCH_HIGH_12:    case SEARCH_EQUAL_12: case SEARCH_LOW_12:
+    case WRITE_12:          case WRITE_VERIFY_12: case SET_WINDOW: 
+    case MEDIUM_SCAN:       case SEND_VOLUME_TAG:            
     case 0xea:		/* alternate number for WRITE LONG */
 	cp->DataOut = TRUE;	/* Output mode */
         break;
@@ -376,7 +393,7 @@
     cp->cp_lun = cmd->lun;
     cp->cp_dispri = TRUE;
     cp->cp_identify = TRUE;
-    memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+    memcpy(cp->cp_cdb, cmd->cmnd, cmd->cmd_len);
 
     cp->cp_statDMA = htonl((ulong) &(hd->sp));
 
@@ -384,7 +401,7 @@
     cp->cmd = cmd;
     cmd->host_scribble = (char *)&hd->ccb[y];	
 
-    if(eata_send_command((ulong) cp, (uint) sh->base, EATA_CMD_DMA_SEND_CP)) {
+    if(eata_send_command((ulong) cp, (uint) sh->base, EATA_CMD_DMA_SEND_CP) == FALSE) {
       cmd->result = DID_ERROR << 16;
       printk("eata_queue target %d, pid %ld, HBA busy, returning DID_ERROR, done.\n",
               cmd->target, cmd->pid);
@@ -494,8 +511,10 @@
 	    DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
 	    return (SCSI_RESET_ERROR);
 	}
-    for (z = 0; z < MAXTARGET; z++)
+    for (z = 0; z < MAXTARGET; z++) {
 	HD(cmd)->t_state[z] = RESET;
+	HD(cmd)->t_timeout[z] = FALSE;
+    }
 
     for (x = 0; x < cmd->host->can_queue; x++) {
 
@@ -577,16 +596,21 @@
 {
     struct eata_ccb cp;
     struct eata_sp  sp;
-    static char buff[256];
+    static char *buff;
+    u32 i;
+
+    buff = dma_scratch;
 
     memset(&cp, 0, sizeof(struct eata_ccb));
-    memset(buff, 0, sizeof(buff));
+    memset(&sp, 0, sizeof(struct eata_sp));
+    memset(buff, 0, 256);
 
     cp.DataIn = TRUE;     
     cp.Interpret = TRUE;   /* Interpret command */
  
     cp.cp_datalen = htonl(255);  
-    cp.cp_dataDMA = htonl((long)buff);
+    cp.cp_dataDMA = htonl((s32)buff);
+    cp.cp_viraddr = &cp;
 
     cp.cp_id = id;
     cp.cp_lun = 0;
@@ -600,9 +624,21 @@
 
     cp.cp_statDMA = htonl((ulong) &sp);
 
-    eata_send_command((ulong) &cp, (uint) base, EATA_CMD_DMA_SEND_CP);
-    while (!(inb(base + HA_RAUXSTAT) & HA_AIRQ));
-    if(inb((uint) base + HA_RSTATUS) & 1)
+    fake_int_base = base;
+    fake_int_result = 0;
+
+    eata_send_command((u32) &cp, (u32) base, EATA_CMD_DMA_SEND_CP);
+    
+    i = jiffies + 300;
+    while (!fake_int_result && jiffies <= i) 
+        /* nothing */;
+    
+    DBG(DBG_INTR3, printk("fake_int_result: %#lx hbastat %#lx scsistat %#lx,"
+			  " buff %p sp %p\n",
+                          fake_int_result, (u32) (sp.hba_stat & 0x7f), 
+			  (u32) sp.scsi_stat, buff, &sp));
+    
+    if (jiffies > i || (fake_int_result & 1))
         return (NULL);
     else
         return (buff);
@@ -610,7 +646,6 @@
     
 int check_blink_state(long base)
 {
-    uint ret = 0;
     uint loops = 10;
     ulong blinkindicator = 0x42445054;
     ulong state = 0x12345678;
@@ -621,10 +656,13 @@
 	state = inl((uint) base + 1);
     }
 
+    DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n",
+			  (state == oldstate) && (state == blinkindicator)));
+
     if ((state == oldstate) && (state == blinkindicator))
-	ret = 1;
-    DBG(DBG_BLINK, printk("Did Blink check. Status: %d\n", ret));
-    return (ret);
+        return(TRUE);
+    else
+        return (FALSE);
 }
 
 int get_conf_PIO(struct eata_register *base, struct get_conf *buf)
@@ -632,8 +670,14 @@
     ulong loop = R_LIMIT;
     ushort *p;
 
-    if(check_region((uint)base, 9)) 
+    u8  warning = FALSE;
+    
+    if(check_region((int) base, 9)) {
+        if ((int)base == 0x1f0 || (int)base == 0x170) {
+            warning = 1;
+        } else
         return (FALSE);
+    }
  
     memset(buf, 0, sizeof(struct get_conf));
 
@@ -665,11 +709,15 @@
 	
 	    while (inb((uint) base + HA_RSTATUS) & HA_SDRQ) 
 	        inw((uint) base + HA_RDATA);
+            if (warning == TRUE)
+                printk("Warning: HBA with IO on 0x%p dectected,\n"
+                       "         this IO space is already allocated, probably by the IDE driver.\n"
+                       "         This might lead to problems.", base);
  	    return (TRUE);
 	} 
     } else {
-        printk("eata_dma: get_conf_PIO, error during transfer for HBA at %lx",
-	       (long)base);
+        DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer "
+			      "for HBA at %lx\n", (long)base));
     }
     return (FALSE);
 }
@@ -701,42 +749,14 @@
     
     DBG(DBG_REGISTER, print_config(gc));
 
-    if (!gc->DMA_support) {
-	printk("HBA at %#.8lx doesn't support DMA. Sorry\n",base);
-	return (FALSE);
-    }
-
-    if ((buff = get_board_data((uint)base, gc->IRQ, gc->scsi_id[3])) == NULL){
-        printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base);
-	return (FALSE);
-    }
-
-    if(gc->HAA_valid == FALSE || ntohl(gc->len) <= 0x1e) 
-        gc->MAX_CHAN = 0;
-
-    if(strncmp("PM2322", &buff[16], 6) && strncmp("PM3021", &buff[16], 6)
-         && strncmp("PM3222", &buff[16], 6) && strncmp("PM3224", &buff[16], 6))
+    if(gc->HAA_valid == FALSE || ntohl(gc->len) < 0x22) 
         gc->MAX_CHAN = 0;
 
-    /* if gc->DMA_valid it must be a PM2011 and we have to register it */
-    dma_channel = 0xff;
-    if (gc->DMA_valid) {
-	if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "DPT_PM2011")) {
-	    printk("Unable to allocate DMA channel %d for HBA PM2011.\n",
-		dma_channel);
-	    return (FALSE);
-	}
-    } 
-    
     if (!reg_IRQ[gc->IRQ]) {	/* Interrupt already registered ? */
-	if (!request_irq(gc->IRQ, eata_int_handler, SA_INTERRUPT, "EATA-DMA")){
+        if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT, "eata_dma")){
 	    reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
 	    if (!gc->IRQ_TR)
 		reg_IRQL[gc->IRQ] = TRUE;	/* IRQ is edge triggered */
-
-	    /* We free it again so we can do a get_conf_dma and 
-	     * allocate the interrupt again later */
-	    free_irq(gc->IRQ);	
 	} else {
 	    printk("Couldn't allocate IRQ %d, Sorry.", gc->IRQ);
 	    return (FALSE);
@@ -750,7 +770,47 @@
 	    reg_IRQ[gc->IRQ] += (gc->MAX_CHAN+1);
     }
 
-    request_region(base, 9, "eata_dma");
+    /* if gc->DMA_valid it must be an ISA HBA and we have to register it */
+    dma_channel = 0xff;
+    if (gc->DMA_valid) {
+        if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "eata_dma")) {
+            printk("Unable to allocate DMA channel %d for ISA HBA at %#.4lx.\n",
+                   dma_channel, base);
+            reg_IRQ[gc->IRQ] -= (gc->MAX_CHAN+1);
+            if (reg_IRQ[gc->IRQ] == 0)
+                free_irq(gc->IRQ);
+            if (!gc->IRQ_TR)
+                reg_IRQL[gc->IRQ] = FALSE; 
+            return (FALSE);
+        }
+    } 
+    
+    buff = get_board_data(base, gc->IRQ, gc->scsi_id[3]);
+
+    if (buff == NULL) {
+        if (gc->DMA_support == FALSE)
+            printk("HBA at %#.4lx doesn't support DMA. Sorry\n", base);
+        else
+            printk("HBA at %#.4lx didn't react on INQUIRY. Sorry.\n", base);
+        if (gc->DMA_valid) 
+            free_dma(dma_channel);
+        reg_IRQ[gc->IRQ] -= (gc->MAX_CHAN+1);
+        if (reg_IRQ[gc->IRQ] == 0)
+            free_irq(gc->IRQ);
+        if (!gc->IRQ_TR)
+            reg_IRQL[gc->IRQ] = FALSE; 
+        return (FALSE);
+    }
+    
+    if (gc->DMA_support == FALSE && buff != NULL)  
+        printk("HBA %.12sat %#.4lx doesn't set the DMA_support flag correctly.\n",
+               &buff[16], base);
+    
+    request_region(base, 9, "eata_dma"); /* We already checked the 
+                                          * availability, so this could 
+                                          * only fail if we're on 
+					  * 0x1f0 or 0x170.
+                                          */
 
     if(ntohs(gc->queuesiz) == 0) {
         gc->queuesiz = ntohs(64);
@@ -769,6 +829,18 @@
     for (i = 0; i <= gc->MAX_CHAN; i++) {
 
 	sh = scsi_register(tpnt, size);
+
+	if(sh == NULL) {
+	    if (gc->DMA_valid) 
+	        free_dma(dma_channel);
+	    reg_IRQ[gc->IRQ] -= 1;
+	    if (reg_IRQ[gc->IRQ] == 0)
+	        free_irq(gc->IRQ);
+	    if (!gc->IRQ_TR)
+	        reg_IRQL[gc->IRQ] = FALSE; 
+	    return (FALSE);
+	}
+
 	hd = SD(sh);                   
 
 	memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)) / 
@@ -808,8 +880,10 @@
 
 	if (gc->OCS_enabled == TRUE) {
 	    sh->cmd_per_lun = sh->can_queue/C_P_L_DIV; 
+#if 0   /* The memory management seems to be more stable now */
 	    if (sh->cmd_per_lun > C_P_L_CURRENT_MAX)
 	        sh->cmd_per_lun = C_P_L_CURRENT_MAX;
+#endif
 	} else {
 	    sh->cmd_per_lun = 1;
 	}
@@ -940,7 +1014,7 @@
 {
 
 #ifndef CONFIG_PCI
-    printk("Kernel PCI support not enabled. Skipping.\n");
+    printk("Kernel PCI support not enabled. Skipping scan for PCI HBAs.\n");
 #else
 
     unchar pci_bus, pci_device_fn;
@@ -1041,14 +1115,12 @@
  
     geometry.drv[0].trans = geometry.drv[1].trans = 0;
 
-    printk("EATA (Extended Attachment) driver version: %d.%d%s\n"
-	   "developed in co-operation with DPT\n"             
-	   "(c) 1993-95 Michael Neuffer  neuffer@goofy.zdv.uni-mainz.de\n",
-	   VER_MAJOR, VER_MINOR, VER_SUB);
- 
     DBG((DBG_PROBE && DBG_DELAY)|| DPT_DEBUG,
 	printk("Using lots of delays to let you read the debugging output\n"));
 
+    status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
+    dma_scratch = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
+
     find_PCI(&gc, tpnt);
 
     for (i = 0; i < MAXEISA; i++) {
@@ -1064,23 +1136,40 @@
     }
 
     for (i = 0; i <= MAXIRQ; i++)
-	if (reg_IRQ[i])
+	if (reg_IRQ[i]){
+	    free_irq(i);
 	    request_irq(i, eata_int_handler, SA_INTERRUPT, "EATA-DMA");
+	}
 
     HBA_ptr = first_HBA;
 
+    if (registered_HBAs != 0) {
+        printk("EATA (Extended Attachment) driver version: %d.%d%s\n"
+	       "developed in co-operation with DPT\n"             
+	       "(c) 1993-95 Michael Neuffer  neuffer@goofy.zdv.uni-mainz.de\n",
+	       VER_MAJOR, VER_MINOR, VER_SUB);
     printk("Registered HBAs:\n");
     printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: DMA: Ch: ID: Pr: QS: SG: CPL:\n");
     for (i = 1; i <= registered_HBAs; i++) {
-        printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4x   %2d   %2x   %d   %d   %d  %2d  %2d   %2d\n", 
+	    printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4lx   %2d",
 	       HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
 	       SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? 
 	       "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
-	       (uint) HBA_ptr->base, HBA_ptr->irq, HBA_ptr->dma_channel, 
-	       SD(HBA_ptr)->channel, HBA_ptr->this_id, SD(HBA_ptr)->primary, 
+                   (u32) HBA_ptr->base, HBA_ptr->irq);
+            if(HBA_ptr->dma_channel != 0xff)
+	        printk("   %2x ", HBA_ptr->dma_channel);
+            else
+                printk("  %s", "BMST");
+            printk("  %d   %d   %c  %2d  %2d   %2d\n", SD(HBA_ptr)->channel, 
+                   HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', 
 	       HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
         HBA_ptr = SD(HBA_ptr)->next;
     }
+    } else 
+        scsi_init_free((void *)status, 512);
+    
+    scsi_init_free((void *)dma_scratch, 512);
+
     DBG(DPT_DEBUG,DELAY(1200));
 
     return (registered_HBAs);
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/eata_dma.h linux/drivers/scsi/eata_dma.h
--- v1.2.4/linux/drivers/scsi/eata_dma.h	Tue Feb 14 08:02:58 1995
+++ linux/drivers/scsi/eata_dma.h	Tue Apr 11 07:56:25 1995
@@ -2,7 +2,7 @@
 * Header file for eata_dma.c Linux EATA-DMA SCSI driver *
 * (c) 1993,94,95 Michael Neuffer                        *
 *********************************************************
-* last change: 95/02/13                                 *
+* last change: 95/04/10                                 *
 ********************************************************/
 
 
@@ -11,7 +11,7 @@
 
 #define VER_MAJOR 2
 #define VER_MINOR 3
-#define VER_SUB   "1a"
+#define VER_SUB   "5r"
 
 /************************************************************************
  * Here you can configure your drives that are using a non-standard     *
@@ -61,6 +61,7 @@
 #define DBG_QUEUE	0	/* Trace command queueing. 		*/
 #define DBG_INTR	0       /* Trace interrupt service routine. 	*/
 #define DBG_INTR2	0       /* Trace interrupt service routine. 	*/
+#define DBG_INTR3       0       /* Trace interrupt service routine.     */
 #define DBG_PROC        0       /* Debug proc-fs related statistics     */
 #define DBG_REGISTER    0       /* */
 #define DBG_ABNORM	1	/* Debug abnormal actions (reset, abort)*/
@@ -125,13 +126,15 @@
 
 #define SG_SIZE           64 
 
-#define C_P_L_CURRENT_MAX 10  /* Until this limit in the mm is removed    
+#define C_P_L_CURRENT_MAX 16  /* Until this limit in the mm is removed    
 			       * Kernels < 1.1.86 died horrible deaths
 			       * if you used values >2. The memory management
 			       * since pl1.1.86 seems to cope with up to 10
 			       * queued commands per device. 
+                               * Since 1.2.0 the memory management seems to 
+                               * have no more problems......
 			       */
-#define C_P_L_DIV          4  /* 1 <= C_P_L_DIV <= 8            
+#define C_P_L_DIV          3  /* 1 <= C_P_L_DIV <= 8            
 			       * You can use this parameter to fine-tune
 			       * the driver. Depending on the number of 
 			       * devices and their speed and ability to queue 
@@ -200,6 +203,24 @@
 #define HA_SREADY   0x40        /* drive ready               */
 #define HA_SBUSY    0x80        /* drive busy                */
 #define HA_SDRDY    HA_SSC+HA_SREADY+HA_SDRQ 
+
+#define HA_NO_ERROR      0x00
+#define HA_ERR_SEL_TO    0x01
+#define HA_ERR_CMD_TO    0x02
+#define HA_ERR_RESET     0x03
+#define HA_INIT_POWERUP  0x04
+#define HA_UNX_BUSPHASE  0x05
+#define HA_UNX_BUS_FREE  0x06
+#define HA_BUS_PARITY    0x07
+#define HA_SCSI_HUNG     0x08
+#define HA_UNX_MSGRJCT   0x09
+#define HA_RESET_STUCK   0x0a
+#define HA_RSENSE_FAIL   0x0b
+#define HA_PARITY_ERR    0x0c
+#define HA_CP_ABORT_NA   0x0d
+#define HA_CP_ABORTED    0x0e
+#define HA_CP_RESET_NA   0x0f
+#define HA_CP_RESET      0x10
 
 /**********************************************
  * Message definitions                        *
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.2.4/linux/drivers/scsi/scsi.c	Wed Mar 29 06:52:58 1995
+++ linux/drivers/scsi/scsi.c	Wed Apr 12 21:03:23 1995
@@ -387,7 +387,8 @@
 
 
 	  if(SCpnt->result) {
-	    if ((driver_byte(SCpnt->result)  & DRIVER_SENSE) &&
+	    if (((driver_byte(SCpnt->result) & DRIVER_SENSE) ||
+		 (status_byte(SCpnt->result) & CHECK_CONDITION)) &&
 		((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
 	      if (SCpnt->sense_buffer[2] &0xe0)
 		continue; /* No devices here... */
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.2.4/linux/drivers/scsi/scsi.h	Wed Mar 29 06:52:59 1995
+++ linux/drivers/scsi/scsi.h	Tue Apr 11 07:56:25 1995
@@ -50,6 +50,7 @@
 #define SEND_DIAGNOSTIC		0x1d
 #define ALLOW_MEDIUM_REMOVAL	0x1e
 
+#define SET_WINDOW              0x24
 #define READ_CAPACITY		0x25
 #define READ_10			0x28
 #define WRITE_10		0x2a
@@ -65,16 +66,26 @@
 #define SYNCHRONIZE_CACHE	0x35
 #define LOCK_UNLOCK_CACHE	0x36
 #define READ_DEFECT_DATA	0x37
+#define MEDIUM_SCAN             0x38
 #define COMPARE			0x39
 #define COPY_VERIFY		0x3a
 #define WRITE_BUFFER		0x3b
 #define READ_BUFFER		0x3c
+#define UPDATE_BLOCK            0x3d
 #define READ_LONG		0x3e
+#define WRITE_LONG              0x3f
 #define CHANGE_DEFINITION	0x40
+#define WRITE_SAME             0x41
 #define LOG_SELECT		0x4c
 #define LOG_SENSE		0x4d
 #define MODE_SELECT_10		0x55
 #define MODE_SENSE_10		0x5a
+#define WRITE_12                0xaa
+#define WRITE_VERIFY_12         0xae
+#define SEARCH_HIGH_12          0xb0
+#define SEARCH_EQUAL_12         0xb1
+#define SEARCH_LOW_12           0xb2
+#define SEND_VOLUME_TAG         0xb6
 
 extern void scsi_make_blocked_list(void);
 extern volatile int in_scan_scsis;
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.2.4/linux/drivers/scsi/sd.c	Sun Feb 19 11:33:13 1995
+++ linux/drivers/scsi/sd.c	Mon Apr 10 08:31:51 1995
@@ -358,8 +358,8 @@
   unsigned long flags;
   int flag = 0;
 
+  save_flags(flags);
   while (1==1){
-    save_flags(flags);
     cli();
     if (CURRENT != NULL && CURRENT->dev == -1) {
       restore_flags(flags);
@@ -387,12 +387,10 @@
 
     /*
      * The following restore_flags leads to latency problems.  FIXME.
+     * Using a "sti()" gets rid of the latency problems but causes
+     * race conditions and crashes.
      */
-#if 0
     restore_flags(flags);
-#else
-    sti();
-#endif
 
 /* This is a performance enhancement.  We dig down into the request list and
    try and find a queueable request (i.e. device not busy, and host able to
@@ -404,7 +402,6 @@
     if (!SCpnt && sd_template.nr_dev > 1){
       struct request *req1;
       req1 = NULL;
-      save_flags(flags);
       cli();
       req = CURRENT;
       while(req){
diff -u --recursive --new-file v1.2.4/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.2.4/linux/drivers/scsi/st.c	Sun Apr  9 11:59:57 1995
+++ linux/drivers/scsi/st.c	Sun Apr  9 12:50:58 1995
@@ -1063,8 +1063,7 @@
 	SCpnt->request.dev = dev;
 	scsi_do_cmd (SCpnt,
 		     (void *) cmd, (STp->buffer)->b_data,
-		     (STp->buffer)->buffer_size,
-		     st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
+		     bytes, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 
 
 	/* this must be done with interrupts off */
diff -u --recursive --new-file v1.2.4/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.2.4/linux/fs/isofs/inode.c	Wed Feb 22 08:15:14 1995
+++ linux/fs/isofs/inode.c	Sun Apr  9 10:04:42 1995
@@ -79,7 +79,7 @@
 	popt->rock = 'y';
 	popt->cruft = 'n';
 	popt->unhide = 'n';
-	popt->conversion = 'a';
+	popt->conversion = 'b';		/* default: no conversion */
 	popt->blocksize = 1024;
 	popt->mode = S_IRUGO;
 	popt->gid = 0;
diff -u --recursive --new-file v1.2.4/linux/include/linux/major.h linux/include/linux/major.h
--- v1.2.4/linux/include/linux/major.h	Thu Feb 23 13:31:40 1995
+++ linux/include/linux/major.h	Tue Apr 11 08:03:29 1995
@@ -7,8 +7,8 @@
 
 /* limits */
 
-#define MAX_CHRDEV 32
-#define MAX_BLKDEV 32
+#define MAX_CHRDEV 64
+#define MAX_BLKDEV 64
 
 /*
  * assignments
diff -u --recursive --new-file v1.2.4/linux/include/linux/serial.h linux/include/linux/serial.h
--- v1.2.4/linux/include/linux/serial.h	Mon Feb 20 21:29:53 1995
+++ linux/include/linux/serial.h	Wed Apr 12 21:24:17 1995
@@ -140,6 +140,7 @@
 	int			xmit_tail;
 	int			xmit_cnt;
 	struct tq_struct	tqueue;
+	struct tq_struct	tqueue_hangup;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
 	struct wait_queue	*open_wait;
@@ -160,7 +161,6 @@
  * time, instead of at rs interrupt time.
  */
 #define RS_EVENT_WRITE_WAKEUP	0
-#define RS_EVENT_HANGUP		1
 
 /*
  * Multiport serial configuration structure --- internal structure
diff -u --recursive --new-file v1.2.4/linux/include/linux/tqueue.h linux/include/linux/tqueue.h
--- v1.2.4/linux/include/linux/tqueue.h	Wed Dec 28 16:38:30 1994
+++ linux/include/linux/tqueue.h	Wed Apr 12 21:24:17 1995
@@ -57,7 +57,7 @@
 #define DECLARE_TASK_QUEUE(q)  task_queue q = &tq_last
 
 extern struct tq_struct tq_last;
-extern task_queue tq_timer, tq_immediate;
+extern task_queue tq_timer, tq_immediate, tq_scheduler;
 
 #ifdef INCLUDE_INLINE_FUNCS
 struct tq_struct tq_last = {
diff -u --recursive --new-file v1.2.4/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.2.4/linux/kernel/ksyms.c	Sun Apr  9 11:59:57 1995
+++ linux/kernel/ksyms.c	Wed Apr 12 21:24:17 1995
@@ -41,8 +41,10 @@
 #include <linux/tcp.h>
 #include "../net/inet/protocol.h"
 #include "../net/inet/arp.h"
+#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
 #include "../drivers/net/slhc.h"
 #endif
+#endif
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif
@@ -209,6 +211,7 @@
 	X(del_timer),
 	X(tq_timer),
 	X(tq_immediate),
+	X(tq_scheduler),
 	X(tq_last),
 	X(timer_active),
 	X(timer_table),
@@ -273,12 +276,14 @@
 #ifdef CONFIG_INET	
 	X(inet_add_protocol),
 	X(inet_del_protocol),
+#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
 	X(slhc_init),
 	X(slhc_free),
 	X(slhc_remember),
 	X(slhc_compress),
 	X(slhc_uncompress),
 #endif
+#endif
 	/* Device callback registration */
 	X(register_netdevice_notifier),
 	X(unregister_netdevice_notifier),
@@ -323,6 +328,8 @@
 	X(scsi_register),
 	X(scsi_unregister),
 	X(scsicam_bios_param),
+        X(scsi_init_malloc),
+        X(scsi_init_free),
 	X(print_command),
 #endif
 	/* Added to make file system as module */
diff -u --recursive --new-file v1.2.4/linux/kernel/sched.c linux/kernel/sched.c
--- v1.2.4/linux/kernel/sched.c	Sun Apr  9 11:59:57 1995
+++ linux/kernel/sched.c	Wed Apr 12 21:24:17 1995
@@ -45,6 +45,7 @@
 
 DECLARE_TASK_QUEUE(tq_timer);
 DECLARE_TASK_QUEUE(tq_immediate);
+DECLARE_TASK_QUEUE(tq_scheduler);
 
 /*
  * phase-lock loop variables
@@ -119,6 +120,7 @@
 		printk("Aiee: scheduling in interrupt\n");
 		intr_count = 0;
 	}
+	run_task_queue(&tq_scheduler);
 	cli();
 	ticks = itimer_ticks;
 	itimer_ticks = 0;
