diff -u --recursive --new-file v1.1.67/linux/CREDITS linux/CREDITS
--- v1.1.67/linux/CREDITS	Tue Nov 22 15:41:10 1994
+++ linux/CREDITS	Tue Nov 29 16:16:00 1994
@@ -539,6 +539,13 @@
 S: Victoria 3163
 S: Australia
 
+N: Pauline Middelink
+E: middelin@polyware.iaf.nl
+D: General low-level bug fixes, /proc fixes, identd support
+S: Boterkorfhoek 34
+S: 7546 JA  Enschede
+S: Netherlands
+
 N: Rick Miller
 E: rick@discus.mil.wi.us
 D: Linux Device Registrar (Major/minor numbers), "au-play", "bwBASIC"
diff -u --recursive --new-file v1.1.67/linux/Makefile linux/Makefile
--- v1.1.67/linux/Makefile	Mon Nov 28 14:21:43 1994
+++ linux/Makefile	Tue Nov 29 15:43:50 1994
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 67
+SUBLEVEL = 68
 
 ARCH = i386
 
diff -u --recursive --new-file v1.1.67/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c
--- v1.1.67/linux/drivers/block/cdu31a.c	Sat Nov 26 18:36:04 1994
+++ linux/drivers/block/cdu31a.c	Tue Nov 29 16:47:45 1994
@@ -2773,7 +2773,7 @@
    {
       irq_used = ints[2];
    }
-   if (*strings != '\0')
+   if ((strings != NULL) && (*strings != '\0'))
    {
       if (strcmp(strings, "PAS") == 0)
       {
diff -u --recursive --new-file v1.1.67/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.67/linux/drivers/char/console.c	Mon Nov 28 14:21:44 1994
+++ linux/drivers/char/console.c	Tue Nov 29 17:09:53 1994
@@ -2106,7 +2106,7 @@
 	}
 	lock = 1;
 #ifdef CONFIG_SELECTION
-	highlight_pointer(fg_console,-1);
+	clear_selection();
 #endif /* CONFIG_SELECTION */
 	if (!console_blanked)
 		get_scrmem(fg_console);
@@ -2148,7 +2148,7 @@
 	/* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */
 	chcount=video_num_columns*video_num_lines;
 	l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE,
-		buf, (2+chcount)*(1+mode!=0));
+		buf, (2+chcount)*(mode ? 2 : 1));
 	if (l)
 		return l;
 	if (mode<2) {
@@ -2162,12 +2162,14 @@
 		put_fs_byte(*sptr++,buf++);	
 			break;
 	    case 1:
+#ifdef CONFIG_SELECTION
+			clear_selection();
+#endif
 			put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); 
 			memcpy_tofs(buf,(char *)origin,2*chcount);
 			break;
 	    case 2:
-			buf+=2; /* skip the the numnber 9 and console number */
-			x=get_fs_byte(buf++); y=get_fs_byte(buf++);
+			buf+=4; /* ioctl#, console#, x,y */
 			memcpy_fromfs((char *)origin,buf,2*chcount);
 			break;
 	    }
@@ -2356,7 +2358,6 @@
 		case 3: /* pointer highlight */
 			if (sel_cons != currcons)
 			{
-				highlight_pointer(sel_cons,-1);
 				clear_selection();
 				sel_cons = currcons;
 			}
@@ -2491,7 +2492,8 @@
  */
 
 #define colourmap ((char *)0xa0000)
-/* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */
+/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
+   should use 0xA0000 for the bwmap as well.. */
 #define blackwmap ((char *)0xa0000)
 #define cmapsz 8192
 #define seq_port_reg (0x3c4)
diff -u --recursive --new-file v1.1.67/linux/drivers/net/MODULES linux/drivers/net/MODULES
--- v1.1.67/linux/drivers/net/MODULES	Thu Aug 11 08:59:58 1994
+++ linux/drivers/net/MODULES	Tue Nov 29 15:43:37 1994
@@ -3,5 +3,6 @@
 	de600.o \
 	de620.o \
 	3c501.o \
+	eexpress.o \
 	plip.o \
 	8390.o
diff -u --recursive --new-file v1.1.67/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v1.1.67/linux/drivers/net/eexpress.c	Wed Aug 10 20:00:12 1994
+++ linux/drivers/net/eexpress.c	Tue Nov 29 10:14:52 1994
@@ -17,6 +17,8 @@
 	Move the theory of operation and memory map documentation.
 	Rework the board error reset
 	The statistics need to be updated correctly.
+
+        Modularized my Pauline Middelink <middelin@polyware.iaf.nl>
 */
 
 static char *version =
@@ -53,6 +55,10 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include "../../tools/version.h"
+#endif
 
 #include <linux/malloc.h>
 
@@ -435,6 +441,9 @@
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
 	return 0;
 }
 
@@ -647,6 +656,9 @@
 
 	/* Update the statistics here. */
 
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
 	return 0;
 }
 
@@ -981,6 +993,32 @@
 	outw(saved_write_ptr, ioaddr + WRITE_PTR);
 }
 
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+static struct device dev_eexpress = {
+	"        " /*"eexpress"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe };
+
+int
+init_module(void)
+{
+	if (register_netdev(&dev_eexpress) != 0)
+		return -EIO;
+	return 0;
+}
+
+void
+cleanup_module(void)
+{
+	if (MOD_IN_USE)
+		printk("express: device busy, remove delayed\n");
+	else
+	{
+		unregister_netdev(&dev_eexpress);
+		kfree_s(dev_eexpress.priv,sizeof(struct net_local));
+		dev_eexpress.priv=NULL;
+	}
+}
+#endif /* MODULE */
 /*
  * Local variables:
  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c eexpress.c"
diff -u --recursive --new-file v1.1.67/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v1.1.67/linux/drivers/net/plip.c	Mon Nov 28 14:21:45 1994
+++ linux/drivers/net/plip.c	Tue Nov 29 10:05:13 1994
@@ -545,7 +545,7 @@
     enable_irq(dev->irq);
 }
 
-/* PLIP_ERROR --- wait til other end setteled */
+/* PLIP_ERROR --- wait til other end settled */
 static int
 plip_error(struct device *dev)
 {
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v1.1.67/linux/drivers/scsi/53c7,8xx.c	Sat Nov 26 18:36:05 1994
+++ linux/drivers/scsi/53c7,8xx.c	Tue Nov 29 10:07:12 1994
@@ -2424,7 +2424,7 @@
     tmp->select[0] = IDENTIFY (0, cmd->lun);
 #endif
     patch_dsa_32(tmp->dsa, dsa_msgout, 1, tmp->select);
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, COMMAND_SIZE(cmd->cmnd[0]));
+    patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
     patch_dsa_32(tmp->dsa, dsa_cmdout, 1, cmd->cmnd);
     patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
     	cmd_dataout : hostdata->script + hostdata->E_other_transfer / 
@@ -3740,10 +3740,6 @@
     printk ("scsi%d : DANGER : NCR53c7xx_reset is NOP\n",
 	cmd->host->host_no);
     return SCSI_RESET_SNOOZE;
-}
-
-const char *NCR53c7xx_info (void) {
-    return("More info here\n");
 }
 
 /*
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/53c7,8xx.h linux/drivers/scsi/53c7,8xx.h
--- v1.1.67/linux/drivers/scsi/53c7,8xx.h	Wed Aug 10 19:26:25 1994
+++ linux/drivers/scsi/53c7,8xx.h	Tue Nov 29 10:07:12 1994
@@ -50,12 +50,11 @@
 #include <linux/scsicam.h>
 extern int NCR53c7xx_abort(Scsi_Cmnd *);
 extern int NCR53c7xx_detect(Scsi_Host_Template *tpnt);
-extern const char *NCR53c7xx_info(void);
 extern int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 extern int NCR53c7xx_reset(Scsi_Cmnd *);
 
-#define NCR53c7xx {NULL, "NCR53c{7,8}xx (rel 3)", NCR53c7xx_detect, 	\
-    	NULL, NCR53c7xx_info,						\
+#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 3)", NCR53c7xx_detect, 	\
+    	NULL, NULL,						\
 	NULL, NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,\
         NULL, scsicam_bios_param, 					\
 	/* can queue */ 1, /* id */ 7, 255 /* old SG_ALL */, 		\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v1.1.67/linux/drivers/scsi/NCR5380.c	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/NCR5380.c	Tue Nov 29 10:07:13 1994
@@ -2306,7 +2306,7 @@
 		msgout = NOP;
 		break;
 	    case PHASE_CMDOUT:
-		len = COMMAND_SIZE(cmd->cmnd[0]);
+		len = cmd->cmd_len;
 		data = cmd->cmnd;
 		/* 
 		 * XXX for performance reasons, on machines with a 
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v1.1.67/linux/drivers/scsi/aha152x.c	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/aha152x.c	Tue Nov 29 10:07:13 1994
@@ -268,8 +268,6 @@
 #define P_BUSFREE  1
 #define P_PARITY   2
 
-static char *aha152x_id = AHA152X_REVID;
-
 static int port_base      = 0;
 static int this_host      = 0;
 static int can_disconnect = 0;
@@ -734,14 +732,6 @@
   return 1;
 }
 
-/*
- *  return the name of the thing
- */
-const char *aha152x_info(void)
-{
-  return(aha152x_id);
-}
-
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
@@ -1590,14 +1580,14 @@
           if(aha152x_debug & debug_cmd)
           {
             printk("DFIFOEMP, outsw (%d words), ",
-                   COMMAND_SIZE(current_SC->cmnd[0])>>1);
+                   current_SC->cmd_len >>1 );
             disp_ports();
           }
 #endif
   
           outsw( DATAPORT,
                  &current_SC->cmnd,
-                 COMMAND_SIZE(current_SC->cmnd[0])>>1 );
+		current_SC->cmd_len >>1 );
 
 #if defined(DEBUG_CMD)
 	  if(aha152x_debug & debug_cmd)
@@ -1622,7 +1612,7 @@
 #if defined(DEBUG_CMD) || defined(DEBUG_INTR)
           if(debug_cmd & debug_intr)
             printk("sent %d/%d command bytes, ", GETSTCNT(),
-                   COMMAND_SIZE(current_SC->cmnd[0]));
+                   current_SC->cmd_len);
 #endif
 
         }
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h
--- v1.1.67/linux/drivers/scsi/aha152x.h	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/aha152x.h	Tue Nov 29 10:07:12 1994
@@ -12,7 +12,6 @@
 #include <asm/io.h>
 
 int        aha152x_detect(Scsi_Host_Template *);
-const char *aha152x_info(void);
 int        aha152x_command(Scsi_Cmnd *);
 int        aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int        aha152x_abort(Scsi_Cmnd *);
@@ -27,10 +26,11 @@
 
 /* Initial value of Scsi_Host entry */
 #define AHA152X       { /* next */		NULL,			    \
+			/* usage_count */  	NULL,			    \
 			/* name */		AHA152X_REVID, 		    \
 			/* detect */		aha152x_detect,             \
 			/* release */		NULL,			    \
-			/* info */		aha152x_info,               \
+			/* info */		NULL,		            \
 			/* command */		aha152x_command,            \
 			/* queuecommand */	aha152x_queue,              \
                         /* abort */		aha152x_abort,              \
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v1.1.67/linux/drivers/scsi/aha1542.c	Tue Aug 23 09:48:51 1994
+++ linux/drivers/scsi/aha1542.c	Tue Nov 29 10:07:12 1994
@@ -10,6 +10,8 @@
  *        have the bios enabled to use the aha1542.
  *  Modified by David Gentzel
  *	  Don't call request_dma if dma mask is 0 (for BusLogic BT-445S VL-Bus controller).
+ *  Modified by Matti Aarnio
+ *        Accept parameters from LILO cmd-line. -- 1-Oct-94
  */
 
 #include <linux/kernel.h>
@@ -43,9 +45,38 @@
 /* The adaptec can be configured for quite a number of addresses, but
 I generally do not want the card poking around at random.  We allow
 two addresses - this allows people to use the Adaptec with a Midi
-card, which also used 0x330 */
+card, which also used 0x330 -- can be overriden with LILO! */
+
+#define MAXBOARDS 2	/* Increase this and the sizes of the
+			   arrays below, if you need more.. */
+
+static unsigned int bases[MAXBOARDS]={0x330, 0x334};
+
+/* set by aha1542_setup according to the command line */
+static int setup_called[MAXBOARDS]   = {0,0};
+static int setup_buson[MAXBOARDS]    = {0,0};
+static int setup_busoff[MAXBOARDS]   = {0,0};
+static int setup_dmaspeed[MAXBOARDS] = {-1,-1};
+
+static char *setup_str[MAXBOARDS] = {(char *)NULL,(char *)NULL};
+
+/*
+ * LILO params:  aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]
+ *
+ * Where:  <PORTBASE> is any of the valid AHA addresses:
+ *			0x130, 0x134, 0x230, 0x234, 0x330, 0x334
+ *	   <BUSON>  is the time (in microsecs) that AHA spends on the AT-bus
+ *		    when transferring data.  1542A power-on default is 11us,
+ *		    valid values are in range: 2..15 (decimal)
+ *	   <BUSOFF> is the time that AHA spends OFF THE BUS after while
+ *		    it is transferring data (not to monopolize the bus).
+ *		    Power-on default is 4us, valid range: 1..64 microseconds.
+ *	   <DMASPEED> Default is jumper selected (1542A: on the J1),
+ *		    but experimenter can alter it with this.
+ *		    Valid values: 5, 6, 7, 8, 10 (MB/s)
+ *		    Factory default is 5 MB/s.
+ */
 
-static unsigned int bases[]={0x330, 0x334};
 
 /* The DMA-Controller.  We need to fool with this because we want to 
    be able to use the aha1542 without having to have the bios enabled */
@@ -253,6 +284,7 @@
 
     /* In case some other card was probing here, reset interrupts */
     aha1542_intr_reset(bse);     /* reset interrupts, so they don't block */	
+
     outb(SRST|IRST/*|SCRST*/, CONTROL(bse));
 
     i = jiffies + 2;
@@ -302,14 +334,6 @@
     return 0;					/* 0 = not ok */
 }
 
-static const char aha_ident[] = "Adaptec 1542";
-
-/* What's this little function for? */
-const char *aha1542_info(void)
-{
-    return aha_ident;
-}
-
 /* A "high" level interrupt handler */
 static void aha1542_intr_handle(int foo)
 {
@@ -513,7 +537,7 @@
       printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
     aha1542_stat();
     printk("aha1542_queuecommand: dumping scsi cmd:");
-    for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]);
+    for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
     printk("\n");
     if (*cmd == WRITE_10 || *cmd == WRITE_6)
       return 0; /* we are still testing, so *don't* write */
@@ -549,7 +573,7 @@
 
     memset(&ccb[mbo], 0, sizeof(struct ccb));
 
-    ccb[mbo].cdblen = COMMAND_SIZE(*cmd);     /* SCSI Command Descriptor Block Length */
+    ccb[mbo].cdblen = SCpnt->cmd_len;
 
     direction = 0;
     if (*cmd == READ_10 || *cmd == READ_6)
@@ -590,7 +614,6 @@
 	any2scsi(cptr[i].datalen, sgpnt[i].length);
       };
       any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
-      if(((unsigned int) buff & 0xff000000)) goto baddma;
       any2scsi(ccb[mbo].dataptr, cptr);
 #ifdef DEBUG
       printk("cptr %x: ",cptr);
@@ -601,6 +624,7 @@
       ccb[mbo].op = 0;	      /* SCSI Initiator Command */
       SCpnt->host_scribble = NULL;
       any2scsi(ccb[mbo].datalen, bufflen);
+      if(((unsigned int) buff & 0xff000000)) goto baddma;
       any2scsi(ccb[mbo].dataptr, buff);
     };
     ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
@@ -813,6 +837,66 @@
   return 0;
 }
 
+/* called from init/main.c */
+void aha1542_setup( char *str, int *ints)
+{
+    char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
+    static int setup_idx = 0;
+    int setup_portbase;
+
+    if(setup_idx >= MAXBOARDS)
+      {
+	printk("aha1542: aha1542_setup called too many times! Bad LILO params ?\n");
+	printk("   Entryline 1: %s\n",setup_str[0]);
+	printk("   Entryline 2: %s\n",setup_str[1]);
+	printk("   This line:   %s\n",str);
+	return;
+      }
+    if (ints[0] < 1 || ints[0] > 4)
+      {
+	printk("aha1542: %s\n", str );
+	printk(ahausage);
+	printk("aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n");
+      }
+
+    setup_called[setup_idx]=ints[0];
+    setup_str[setup_idx]=str;
+
+    setup_portbase             = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */
+    setup_buson   [setup_idx]  = ints[0] >= 2 ? ints[2] : 7;
+    setup_busoff  [setup_idx]  = ints[0] >= 3 ? ints[3] : 5;
+    if (ints[0] >= 4) {
+      int atbt = -1;
+      switch (ints[4]) {
+	case 5:
+	    atbt = 0x00;
+	    break;
+	case 6:
+	    atbt = 0x04;
+	    break;
+        case 7:
+	    atbt = 0x01;
+	    break;
+	case 8:
+	    atbt = 0x02;
+	    break;
+	case 10:
+	    atbt = 0x03;
+	    break;
+	default:
+	    printk("aha1542: %s\n", str );
+	    printk(ahausage);
+	    printk("aha1542: Valid values for DMASPEED are 5-8, 10 MB/s.  Using jumper defaults.\n");
+	    break;
+      }
+      setup_dmaspeed[setup_idx]  = atbt;
+    }
+
+    if (setup_portbase != 0)
+      bases[setup_idx] = setup_portbase;
+
+    ++setup_idx;
+}
 
 /* return non-zero on detection */
 int aha1542_detect(Scsi_Host_Template * tpnt)
@@ -826,12 +910,19 @@
     int indx;
 
     DEB(printk("aha1542_detect: \n"));
-    
+
     for(indx = 0; indx < sizeof(bases)/sizeof(bases[0]); indx++)
-	    if(!check_region(bases[indx], 4)) { 
+	    if(bases[indx] != 0 && !check_region(bases[indx], 4)) { 
 		    shpnt = scsi_register(tpnt,
 					  sizeof(struct aha1542_hostdata));
 
+		    /* For now we do this - until kmalloc is more intelligent
+		       we are resigned to stupid hacks like this */
+		    if ((unsigned int) shpnt > 0xffffff) {
+		      printk("Invalid address for shpnt with 1542.\n");
+		      goto unregister;
+		    }
+
 		    if(!aha1542_test_port(bases[indx], shpnt)) goto unregister;
 
 
@@ -841,6 +932,12 @@
 	    {
 		    unchar oncmd[] = {CMD_BUSON_TIME, 7};
 		    unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
+
+		    if(setup_called[indx])
+		      {
+			oncmd[1]  = setup_buson[indx];
+			offcmd[1] = setup_busoff[indx];
+		      }
 		    
 		    aha1542_intr_reset(base_io);
 		    aha1542_out(base_io, oncmd, 2);
@@ -848,6 +945,14 @@
 		    aha1542_intr_reset(base_io);
 		    aha1542_out(base_io, offcmd, 2);
 		    WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
+		    if (setup_dmaspeed[indx] >= 0)
+		      {
+			unchar dmacmd[] = {CMD_DMASPEED, 0};
+			dmacmd[1] = setup_dmaspeed[indx];
+			aha1542_intr_reset(base_io);
+			aha1542_out(base_io, dmacmd, 2);
+			WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);
+		      }
 		    while (0) {
 		    fail:
 			    printk("aha1542_detect: setting bus on/off-time failed\n");
@@ -889,6 +994,7 @@
 		    }
 		    aha_host[irq_level - 9] = shpnt;
 		    shpnt->io_port = base_io;
+		    shpnt->n_io_port = 4;  /* Number of bytes of I/O space used */
 		    shpnt->dma_channel = dma_chan;
 		    shpnt->irq = irq_level;
 		    HOSTDATA(shpnt)->bios_translation  = trans;
@@ -1120,3 +1226,12 @@
 /*  if (ip[2] >= 1024) ip[2] = 1024; */
   return 0;
 }
+
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = AHA1542;
+
+#include "scsi_module.c"
+#endif
+
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha1542.h linux/drivers/scsi/aha1542.h
--- v1.1.67/linux/drivers/scsi/aha1542.h	Fri Aug 19 08:54:03 1994
+++ linux/drivers/scsi/aha1542.h	Tue Nov 29 10:07:12 1994
@@ -69,6 +69,7 @@
 #define CMD_EMBOI	0x05	/* Enable MailBox Out Interrupt */
 #define CMD_BUSON_TIME	0x07	/* Set Bus-On Time */
 #define CMD_BUSOFF_TIME	0x08	/* Set Bus-Off Time */
+#define CMD_DMASPEED	0x09	/* Set AT Bus Transfer Speed */
 #define CMD_RETDEVS	0x0a	/* Return Installed Devices */
 #define CMD_RETCONF	0x0b	/* Return Configuration Data */
 #define CMD_RETSETUP	0x0d	/* Return Setup Data */
@@ -132,7 +133,6 @@
 int aha1542_command(Scsi_Cmnd *);
 int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int aha1542_abort(Scsi_Cmnd *);
-const char *aha1542_info(void);
 int aha1542_reset(Scsi_Cmnd *);
 int aha1542_biosparam(Disk *, int, int*);
 
@@ -144,11 +144,11 @@
 	#define NULL 0
 #endif
 
-#define AHA1542 {  NULL,				\
+#define AHA1542 {  NULL, NULL,				\
 		     "Adaptec 1542", 			\
 		     aha1542_detect,			\
 		     NULL,				\
-		     aha1542_info, 			\
+		     NULL,	 			\
 		     aha1542_command,			\
 		     aha1542_queuecommand,		\
 		     aha1542_abort,			\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- v1.1.67/linux/drivers/scsi/aha1740.c	Tue Nov 15 15:35:39 1994
+++ linux/drivers/scsi/aha1740.c	Tue Nov 29 10:07:13 1994
@@ -163,12 +163,6 @@
     return 0;
 }
 
-const char *aha1740_info(void)
-{
-    static char buffer[] = "Adaptec 174x (EISA)";
-    return buffer;
-}
-
 /* A "high" level interrupt handler */
 void aha1740_intr_handle(int foo)
 {
@@ -273,7 +267,7 @@
         i = -1;
     printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
     printk("scsi cmd:");
-    for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]);
+    for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
     printk("\n");
 #endif
 
@@ -302,7 +296,7 @@
     printk("Sending command (%d %x)...",ecbno, done);
 #endif
 
-    ecb[ecbno].cdblen = COMMAND_SIZE(*cmd);	/* SCSI Command Descriptor Block Length */
+    ecb[ecbno].cdblen = SCpnt->cmd_len;	/* SCSI Command Descriptor Block Length */
 
     direction = 0;
     if (*cmd == READ_10 || *cmd == READ_6)
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h
--- v1.1.67/linux/drivers/scsi/aha1740.h	Sun Jul 10 09:09:39 1994
+++ linux/drivers/scsi/aha1740.h	Tue Nov 29 10:07:12 1994
@@ -156,7 +156,6 @@
 int aha1740_command(Scsi_Cmnd *);
 int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int aha1740_abort(Scsi_Cmnd *);
-const char *aha1740_info(void);
 int aha1740_reset(Scsi_Cmnd *);
 int aha1740_biosparam(Disk *, int, int*);
 
@@ -167,11 +166,11 @@
 #define NULL 0
 #endif
 
-#define AHA1740 {NULL,					\
-		   "Adaptec 1740", 			\
+#define AHA1740 {NULL,	NULL,				\
+		   "Adaptec 174x (EISA)",		\
 		   aha1740_detect,			\
 		   NULL,				\
-		   aha1740_info, 			\
+		   NULL, 				\
 		   aha1740_command,			\
 		   aha1740_queuecommand,		\
 		   aha1740_abort,			\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha274x.c linux/drivers/scsi/aha274x.c
--- v1.1.67/linux/drivers/scsi/aha274x.c	Wed Nov  2 12:03:45 1994
+++ linux/drivers/scsi/aha274x.c	Tue Nov 29 10:07:14 1994
@@ -1033,11 +1033,11 @@
 			found += aha274x_register(template, type, base);
 		}
 	}
-	template->name = (char *)aha274x_info();
+	template->name = (char *)aha274x_info(NULL);
 	return(found);
 }
 
-const char *aha274x_info(void)
+const char *aha274x_info(struct Scsi_Host * shost)
 {
 	return("Adaptec AHA274x/284x (EISA/VL-bus -> Fast SCSI) "
 	       AHA274X_SEQ_VERSION "/"
@@ -1100,7 +1100,7 @@
 	 *	  little-endian format.
 	 */
 	addr = cmd->cmnd;
-	scb->SCSI_cmd_length = COMMAND_SIZE(cmd->cmnd[0]);
+	scb->SCSI_cmd_length = cmd->cmd_len;
 	memcpy(scb->SCSI_cmd_pointer, &addr, sizeof(scb->SCSI_cmd_pointer));
 
 	if (cmd->use_sg) {
@@ -1155,7 +1155,7 @@
 #if 0
 	debug("aha274x_queue: cmd 0x%x (size %u), target %d, lun %d\n",
 	      cmd->cmnd[0],
-	      COMMAND_SIZE(cmd->cmnd[0]),
+	      cmd->cmd_len,
 	      cmd->target,
 	      cmd->lun);
 #endif
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/aha274x.h linux/drivers/scsi/aha274x.h
--- v1.1.67/linux/drivers/scsi/aha274x.h	Wed Nov  2 12:03:45 1994
+++ linux/drivers/scsi/aha274x.h	Tue Nov 29 10:07:14 1994
@@ -32,7 +32,8 @@
  */
 #define AHA274X	{						\
 	NULL,							\
-	"",							\
+	NULL,							\
+	NULL,							\
 	aha274x_detect,						\
 	NULL,							\
 	aha274x_info,						\
@@ -57,6 +58,6 @@
 extern int aha274x_command(Scsi_Cmnd *);
 extern int aha274x_abort(Scsi_Cmnd *);
 extern int aha274x_reset(Scsi_Cmnd *);
-extern const char *aha274x_info(void);
+extern const char *aha274x_info(struct Scsi_Host *);
 
 #endif
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c
--- v1.1.67/linux/drivers/scsi/buslogic.c	Fri Nov 18 15:22:09 1994
+++ linux/drivers/scsi/buslogic.c	Tue Nov 22 09:51:57 1994
@@ -8,17 +8,23 @@
  *	The original version of this driver was derived from aha1542.[ch] which
  *	is Copyright (C) 1992 Tommy Thorn.  Much has been reworked, but most of
  *	basic structure and substantial chunks of code still remain.
+ *
+ *	Thanks to the following individuals who have made contributions (of
+ *	(code, information, support, or testing) to this driver:
+ *		Eric Youngdale		Leonard Zubkoff
+ *		Tomas Hurka		Andrew Walker
  */
 
 /*
  * TODO:
- *	1. Cleanup error handling & reporting.
+ *	1. Clean up error handling & reporting.
  *	2. Find out why scatter/gather is limited to 16 requests per command.
- *	3. Add multiple outstanding requests.
- *	4. See if we can make good use of having more than one command per lun.
- *	5. Test/improve/fix abort & reset functions.
- *	6. Look at command linking.
- *	7. Allow multiple boards to share an IRQ if the bus allows (e.g. EISA).
+ *	3. Test/improve/fix abort & reset functions.
+ *	4. Look at command linking.
+ *	5. Allow multiple boards to share an IRQ if the bus allows (EISA, MCA,
+ *	   and PCI).
+ *	6. Avoid using the 445S workaround for board revs >= D.
+ *	7. Get cmd_per_lun put in the Scsi_Host structure.
  */
 
 /*
@@ -39,8 +45,6 @@
  *	BT-542B - ISA first-party DMA with floppy support.
  *	BT-545S - 542B + FAST SCSI and active termination.
  *	BT-545D - 545S + differential termination.
- *	BT-445S - VESA bus-master FAST SCSI with active termination and floppy
- *		  support.
  *	BT-640A - MCA bus-master with floppy support.
  *	BT-646S - 640A + FAST SCSI and active termination.
  *	BT-646D - 646S + differential termination.
@@ -49,14 +53,21 @@
  *	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-445C - 445S + enhanced BIOS & firmware options.
  *	BT-946C - PCI bus-master FAST SCSI. (??? Nothing else known.)
  *
- *    Should you require further information on any of these boards, BusLogic
- *    can be reached at (408)492-9090.
+ *    ??? 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.
  *
+ *    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
+ *    stands for "Big Brother System"?).
+ *
  *    Places flagged with a triple question-mark are things which are either
  *    unfinished, questionable, or wrong.
  */
@@ -81,13 +92,27 @@
 #include "buslogic.h"
 
 #ifndef BUSLOGIC_DEBUG
-# define BUSLOGIC_DEBUG UD_ABORT
+# define BUSLOGIC_DEBUG 0
 #endif
 
-#define BUSLOGIC_VERSION "1.00"
+/* If different port addresses are needed (e.g. to install more than two
+   cards), you must define BUSLOGIC_PORT_OVERRIDE to be a comma-separated list
+   of the addresses which will be checked.  This can also be used to resolve a
+   conflict if the port-probing at a standard port causes problems with
+   another board. */
+/* #define BUSLOGIC_PORT_OVERRIDE 0x330, 0x334, 0x130, 0x134, 0x230, 0x234 */
+
+/* Define this to be either BIOS_TRANSLATION_DEFAULT or BIOS_TRANSLATION_BIG
+   if you wish to bypass the test for this, which uses an undocumented port.
+   The test is believed to fail on at least some AMI BusLogic clones. */
+/* #define BIOS_TRANSLATION_OVERRIDE BIOS_TRANSLATION_BIG */
+
+#define BUSLOGIC_VERSION "1.13"
 
 /* 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. */
+/* ??? I don't really like this as it will wait longer on slow machines.
+   Perhaps we should base this on the loops_per_second "Bogomips" value? */
 #define WAITNEXTTIMEOUT 3000000
 
 /* This is for the scsi_malloc call in buslogic_queuecommand. */
@@ -101,22 +126,16 @@
 /* Since the SG list is malloced, we have to limit the length. */
 #define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain))
 
-/* The DMA-Controller.  We need to fool with this because we want to be able to
-   use an ISA BusLogic without having to have the BIOS enabled. */
-#define DMA_MODE_REG 0xD6
-#define DMA_MASK_REG 0xD4
-#define	CASCADE 0xC0
+/* ??? Arbitrary.  If we can dynamically allocate the mailbox arrays, I may
+   bump up this number. */
+#define BUSLOGIC_MAILBOXES 16
 
-#define BUSLOGIC_MAILBOXES 16	/* ??? Arbitrary? */
+#define BUSLOGIC_NONISA_CMDLUN 4	/* ??? Arbitrary (> 1) */
 
 /* 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
    random.  We allow two port addresses - this allows people to use a BusLogic
-   with a MIDI card, which frequently also uses 0x330.  If different port
-   addresses are needed (e.g. to install more than two cards), you must define
-   BUSLOGIC_PORT_OVERRIDE to be a list of the addresses which will be checked.
-   This can also be used to resolve a conflict if the port-probing at a
-   standard port causes problems with another board. */
+   with a MIDI card, which frequently also uses 0x330. */
 static const unsigned int bases[] = {
 #ifdef BUSLOGIC_PORT_OVERRIDE
     BUSLOGIC_PORT_OVERRIDE
@@ -129,10 +148,12 @@
 #define BIOS_TRANSLATION_BIG 1		/* Big disk (> 1G) case */
 
 struct hostdata {
-    unsigned char bus_type;
-    int bios_translation;	/* Mapping bios uses - for compatibility */
+    unsigned int bus_type;
+    unsigned int bios_translation: 1;	/* BIOS mapping (for compatibility) */
     size_t last_mbi_used;
     size_t last_mbo_used;
+    char model[7];
+    char firmware_rev[6];
     Scsi_Cmnd *sc[BUSLOGIC_MAILBOXES];
     struct mailbox mb[2 * BUSLOGIC_MAILBOXES];
     struct ccb ccbs[BUSLOGIC_MAILBOXES];
@@ -152,25 +173,28 @@
 
 #define CHECK(cond) if (cond) ; else goto fail
 
-#define WAIT(port, mask, allof, noneof) \
-    CHECK(wait(port, mask, allof, noneof, WAITNEXTTIMEOUT, FALSE))
-#define WAIT_WHILE(port, mask) WAIT(port, mask, 0, mask)
-#define WAIT_UNTIL(port, mask) WAIT(port, mask, mask, 0)
-#define WAIT_FAST(port, mask, allof, noneof) \
-    CHECK(wait(port, mask, allof, noneof, 100, TRUE))
-#define WAIT_WHILE_FAST(port, mask) WAIT_FAST(port, mask, 0, mask)
-#define WAIT_UNTIL_FAST(port, mask) WAIT_FAST(port, mask, mask, 0)
+#define WAIT(port, allof, noneof) \
+    CHECK(wait(port, allof, noneof, WAITNEXTTIMEOUT, FALSE))
+#define WAIT_WHILE(port, mask) WAIT(port, 0, mask)
+#define WAIT_UNTIL(port, mask) WAIT(port, mask, 0)
+#define WAIT_FAST(port, allof, noneof) \
+    CHECK(wait(port, allof, noneof, 100, TRUE))
+#define WAIT_WHILE_FAST(port, mask) WAIT_FAST(port, 0, mask)
+#define WAIT_UNTIL_FAST(port, mask) WAIT_FAST(port, mask, 0)
 
 /* If delay != 0, we use the udelay call to regulate the amount of time we
-   wait. */
-static __inline__ int wait(unsigned short port, unsigned char mask,
+   wait.
+
+   This is inline as it is always called with constant arguments and hence
+   will be very well optimized. */
+static __inline__ int wait(unsigned short port,
 			   unsigned char allof, unsigned char noneof,
 			   unsigned int timeout, int delay)
 {
     int bits;
 
     for (;;) {
-	bits = inb(port) & mask;
+	bits = inb(port);
 	if ((bits & allof) == allof && (bits & noneof) == 0)
 	    return TRUE;
 	if (delay)
@@ -185,16 +209,12 @@
     printk("BusLogic SCSI: ");
 }
 
-#if BUSLOGIC_DEBUG
 static void buslogic_stat(unsigned int base)
 {
     int s = inb(STATUS(base)), i = inb(INTERRUPT(base));
 
-    printk("status=%02X intrflags=%02X\n", s, i);
+    buslogic_printk("status=%02X intrflags=%02X\n", s, i);
 }
-#else
-# define buslogic_stat(base)
-#endif
 
 /* This is a bit complicated, but we need to make sure that an interrupt
    routine does not send something out while we are in the middle of this.
@@ -231,45 +251,60 @@
 }
 
 /* Only used at boot time, so we do not need to worry about latency as much
-   here. */
+   here.  This waits a very short period of time.  We use this if we are not
+   sure whether the board will respond to the command we just sent. */
 static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len)
 {
     cli();
     while (len--) {
-	WAIT_UNTIL(STATUS(base), DIRRDY);
+	WAIT_UNTIL_FAST(STATUS(base), DIRRDY);
 	*cmdp++ = inb(DATA_IN(base));
     }
     sti();
     return FALSE;
   fail:
     sti();
+#if (BUSLOGIC_DEBUG & BD_IO)
     buslogic_printk("buslogic_in failed(%u): ", len + 1);
     buslogic_stat(base);
+#endif
     return TRUE;
 }
 
-#if 0
-/* Similar to buslogic_in, except that we wait a very short period of time.
-   We use this if we know the board is alive and awake, but we are not sure
-   whether the board will respond the the command we are about to send. */
-static int buslogic_in_fast(unsigned int base, unsigned char *cmdp, size_t len)
+static unsigned int makecode(unsigned int haerr, unsigned int scsierr)
 {
-    cli();
-    while (len--) {
-	WAIT_UNTIL_FAST(STATUS(base), DIRRDY);
-	*cmdp++ = inb(DATA_IN(base));
-    }
-    sti();
-    return FALSE;
-  fail:
-    sti();
-    return TRUE;
-}
+    unsigned int hosterr;
+    const char *errstr = NULL;
+#if (BUSLOGIC_DEBUG & BD_ERRORS) && defined(CONFIG_SCSI_CONSTANTS)
+    static const char *const buslogic_status[] = {
+    /* 00 */	"Command completed normally",
+    /* 01-07 */	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 08-09 */	NULL, NULL,
+    /* 0A */	"Linked command completed normally",
+    /* 0B */	"Linked command completed normally, interrupt generated",
+    /* 0C-0F */	NULL, NULL, NULL, NULL,
+    /* 10 */	NULL,
+    /* 11 */	"Selection timed out",
+    /* 12 */	"Data overrun/underrun",
+    /* 13 */	"Unexpected bus free",
+    /* 14 */	"Target bus phase sequence failure",
+    /* 15 */	"First byte of outgoing MB was invalid",
+    /* 16 */	"Invalid CCB Operation Code",
+    /* 17 */	"Linked CCB does not have the same LUN",
+    /* 18 */	"Invalid Target Direction received from Host",
+    /* 19 */	"Duplicate CCB Received in Target Mode",
+    /* 1A */	"Invalid CCB or Segment List Parameter",
+    /* 1B */	"Auto request sense failed",
+    /* 1C */	"SCSI-2 tagged queueing message was rejected by the target",
+    /* 1D-1F */	NULL, NULL, NULL,
+    /* 20 */	"Host adapter hardware failure",
+    /* 21 */	"Target did not respond to SCSI ATN and the HA SCSI bus reset",
+    /* 22 */	"Host adapter asserted a SCSI bus reset",
+    /* 23 */	"Other SCSI devices asserted a SCSI bus reset",
+    };
 #endif
 
-static unsigned int makecode(unsigned int hosterr, unsigned int scsierr)
-{
-    switch (hosterr) {
+    switch (haerr) {
       case 0x00:	/* Normal completion. */
       case 0x0A:	/* Linked command complete without error and linked
 			   normally. */
@@ -280,7 +315,7 @@
 
       case 0x11:	/* Selection time out: the initiator selection or
 			   target reselection was not complete within the SCSI
-			   Time out period. */
+			   time out period. */
 	hosterr = DID_TIME_OUT;
 	break;
 
@@ -289,6 +324,10 @@
 			   target.  The host adapter will generate a SCSI
 			   Reset Condition, notifying the host with a RSTS
 			   interrupt. */
+      case 0x21:	/* The target did not respond to SCSI ATN and the host
+			   adapter consequently issued a SCSI bus reset to
+			   clear up the failure. */
+      case 0x22:	/* The host adapter asserted a SCSI bus reset. */
 	hosterr = DID_RESET;
 	break;
 
@@ -322,100 +361,38 @@
       case 0x1C:	/* SCSI-2 tagged queueing message was rejected by the
 			   target. */
       case 0x20:	/* The host adapter hardware failed. */
-      case 0x21:	/* The target did not respond to SCSI ATN and the host
-			   adapter consequently issued a SCSI bus reset to
-			   clear up the failure. */
-      case 0x22:	/* The host adapter asserted a SCSI bus reset. */
       case 0x23:	/* Other SCSI devices asserted a SCSI bus reset. */
-#if BUSLOGIC_DEBUG
-	buslogic_printk("%X %X\n", hosterr, scsierr);
-#endif
 	hosterr = DID_ERROR;	/* ??? Couldn't find any better. */
 	break;
 
       default:
-	buslogic_printk("makecode: unknown hoststatus %X\n", hosterr);
+#ifndef CONFIG_SCSI_CONSTANTS
+	errstr = "unknown hoststatus";
+#endif
+	hosterr = DID_ERROR;
 	break;
     }
-    return (hosterr << 16) | scsierr;
-}
-
-static int test_port(unsigned int base, struct Scsi_Host *shpnt)
-{
-    unsigned int i;
-    unsigned char inquiry_cmd[] = { CMD_INQUIRY };
-    unsigned char inquiry_result[4];
-    unsigned char *cmdp;
-    int len;
-    volatile int debug = 0;
-
-    /* Quick and dirty test for presence of the card. */
-    if (inb(STATUS(base)) == 0xFF)
-	return TRUE;
-
-    /* Reset the adapter.  I ought to make a hard reset, but it's not really
-       necessary. */
-
-#if BUSLOGIC_DEBUG
-    buslogic_printk("test_port called\n");
-#endif
-
-    /* In case some other card was probing here, reset interrupts. */
-    INTR_RESET(base);	/* reset interrupts, so they don't block */
-
-    outb(RSOFT | RINT/* | RSBUS*/, CONTROL(base));
-
-    /* Wait a little bit for things to settle down. */
-    i = jiffies + 2;
-    while (i > jiffies);
-
-    debug = 1;
-    /* Expect INREQ and HARDY, any of the others are bad. */
-    WAIT(STATUS(base), STATMASK, INREQ | HARDY,
-	 DACT | DFAIL | CMDINV | DIRRDY | CPRBSY);
-
-    debug = 2;
-    /* Shouldn't have generated any interrupts during reset. */
-    if (inb(INTERRUPT(base)) & INTRMASK)
-	goto fail;
-
-    /* Perform a host adapter inquiry instead so we do not need to set up the
-       mailboxes ahead of time. */
-    buslogic_out(base, inquiry_cmd, 1);
-
-    debug = 3;
-    len = 4;
-    cmdp = &inquiry_result[0];
-    while (len--) {
-	WAIT(STATUS(base), DIRRDY, DIRRDY, 0);
-	*cmdp++ = inb(DATA_IN(base));
+#if (BUSLOGIC_DEBUG & BD_ERRORS)
+# ifdef CONFIG_SCSI_CONSTANTS
+    if (hosterr != DID_OK) {
+	if (haerr < ARRAY_SIZE(buslogic_status))
+	    errstr = buslogic_status[haerr];
+	if (errstr == NULL)
+	    errstr = "unknown hoststatus";
     }
-
-    debug = 4;
-    /* Reading port should reset DIRRDY. */
-    if (inb(STATUS(base)) & DIRRDY)
-	goto fail;
-
-    debug = 5;
-    /* When CMDC, command is completed, and we're though testing. */
-    WAIT_UNTIL(INTERRUPT(base), CMDC);
-
-    /* now initialize adapter. */
-
-    debug = 6;
-    /* Clear interrupts. */
-    outb(RINT, CONTROL(base));
-
-    debug = 7;
-
-    return FALSE;				/* 0 = ok */
-  fail:
-    return TRUE;				/* 1 = not ok */
+# else
+    if (hosterr == DID_ERROR)
+	errstr = "";
+# endif
+#endif
+    if (errstr != NULL)
+	buslogic_printk("makecode: %s (%02X)\n", errstr, haerr);
+    return (hosterr << 16) | scsierr;
 }
 
 const char *buslogic_info(void)
 {
-    return "BusLogic SCSI Driver version " BUSLOGIC_VERSION;
+    return "BusLogic SCSI driver version " BUSLOGIC_VERSION;
 }
 
 /* A "high" level interrupt handler. */
@@ -442,7 +419,7 @@
     ccb = HOSTDATA(shpnt)->ccbs;
     base = shpnt->io_port;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
     flag = inb(INTERRUPT(base));
 
     buslogic_printk("buslogic_interrupt: ");
@@ -469,15 +446,17 @@
 	   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 & ~IMBL) {
+	if (flag & (MBOR | CMDC | RSTS)) {
+	    buslogic_printk("Unusual flag:");
 	    if (flag & MBOR)
-		printk("MBOR ");
+		printk(" MBOR");
 	    if (flag & CMDC)
-		printk("CMDC ");
+		printk(" CMDC");
 	    if (flag & RSTS) {
 		needs_restart = 1;
-		printk("RSTS ");
+		printk(" RSTS");
 	    }
+	    printk("\n");
 	}
 
 	INTR_RESET(base);
@@ -522,7 +501,7 @@
 	    return;
 	}
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
 	if (ccb[mbo].tarstat || ccb[mbo].hastat)
 	    buslogic_printk("buslogic_interrupt: returning %08X (status %d)\n",
 			    ((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat,
@@ -532,7 +511,7 @@
 	if (mbistatus == MBX_COMPLETION_NOT_FOUND)
 	    continue;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
 	buslogic_printk("...done %u %u\n", mbo, mbi);
 #endif
 
@@ -540,7 +519,7 @@
 
 	if (!sctmp || !sctmp->scsi_done) {
 	    buslogic_printk("buslogic_interrupt: Unexpected interrupt\n");
-	    buslogic_printk("tarstat=%02X, hastat=%02X id=%d lun=%d ccb#=%d\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;
@@ -550,26 +529,17 @@
 	if (sctmp->host_scribble)
 	    scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
 
-#if 0	/* ??? */
-	/* Fetch the sense data, and tuck it away, in the required slot.  The
-	   BusLogic automatically fetches it, and there is no guarantee that we
-	   will still have it in the cdb when we come back. */
-	if (ccb[mbo].tarstat == 2)	/* ??? */
-	    memcpy(sctmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],
-		   sizeof sctmp->sense_buffer);
-#endif
-
 	/* ??? more error checking left out here */
-	if (mbistatus != MBX_COMPLETION_OK)
+	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
+	} else
 	    errstatus = 0;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_INTERRUPT)
 	if (errstatus)
-	    buslogic_printk("error: %08X %04X %04X\n",
-			    errstatus, ccb[mbo].hastat, ccb[mbo].tarstat);
+	    buslogic_printk("error: %04X %04X\n",
+			    ccb[mbo].hastat, ccb[mbo].tarstat);
 
 	if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) {
 	    size_t i;
@@ -594,6 +564,7 @@
     }
 }
 
+/* ??? Why does queuecommand return a value?  scsi.c never looks at it... */
 int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *))
 {
     static const unsigned char buscmd[] = { CMD_START_SCSI };
@@ -607,7 +578,7 @@
     struct mailbox *mb;
     struct ccb *ccb;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
     if (target > 1) {
 	scpnt->result = DID_TIME_OUT << 16;
 	done(scpnt);
@@ -616,7 +587,7 @@
 #endif
 
     if (*cmd == REQUEST_SENSE) {
-#ifndef DEBUG
+#if (BUSLOGIC_DEBUG & (BD_COMMAND | BD_ERRORS))
 	if (bufflen != sizeof scpnt->sense_buffer) {
 	    buslogic_printk("Wrong buffer length supplied for request sense"
 			    " (%d)\n",
@@ -628,7 +599,7 @@
 	return 0;
     }
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
     {
 	int i;
 
@@ -671,8 +642,7 @@
 	    mbo = 0;
     } while (mbo != HOSTDATA(scpnt->host)->last_mbo_used);
 
-    if (mb[mbo].status != MBX_NOT_IN_USE
-	|| HOSTDATA(scpnt->host)->sc[mbo]) {
+    if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(scpnt->host)->sc[mbo]) {
 	/* ??? Instead of panicing, should we enable OMBR interrupts and
 	   sleep until we get one? */
 	panic("buslogic.c: unable to find empty mailbox");
@@ -686,7 +656,7 @@
 
     sti();
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
     buslogic_printk("sending command (%d %08X)...", mbo, done);
 #endif
 
@@ -731,7 +701,7 @@
 	}
 	ccb[mbo].datalen = scpnt->use_sg * sizeof (struct chain);
 	ccb[mbo].dataptr = cptr;
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
 	{
 	    unsigned char *ptr;
 
@@ -756,7 +726,7 @@
     ccb[mbo].linkptr = NULL;
     ccb[mbo].commlinkid = 0;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
     {
 	size_t i;
 
@@ -768,7 +738,7 @@
 #endif
 
     if (done) {
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
 	buslogic_printk("buslogic_queuecommand: now waiting for interrupt: ");
 	buslogic_stat(scpnt->host->io_port);
 #endif
@@ -776,7 +746,7 @@
 	mb[mbo].status = MBX_ACTION_START;
 	/* start scsi command */
 	buslogic_out(scpnt->host->io_port, buscmd, sizeof buscmd);
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
 	buslogic_stat(scpnt->host->io_port);
 #endif
     } else
@@ -793,8 +763,8 @@
 
 int buslogic_command(Scsi_Cmnd *scpnt)
 {
-#if BUSLOGIC_DEBUG
-    buslogic_printk("buslogic_command: ..calling buslogic_queuecommand\n");
+#if (BUSLOGIC_DEBUG & BD_COMMAND)
+    buslogic_printk("buslogic_command: calling buslogic_queuecommand\n");
 #endif
 
     buslogic_queuecommand(scpnt, internal_done);
@@ -824,46 +794,43 @@
     }
     INTR_RESET(base);	/* reset interrupts, so they don't block */
 
-    /* If this fails, this must be an Adaptec board */
     if (buslogic_out(base, (unsigned char *)&cmd, sizeof cmd))
-	goto must_be_adaptec;
+	goto fail;
+    WAIT_UNTIL(INTERRUPT(base), CMDC);
 
-    /* Wait until host adapter is done messing around, and then check to see
-       if the command was accepted.  If it failed, this must be an Adaptec
-       board. */
-    WAIT_UNTIL(STATUS(base), HARDY);
-    if (inb(STATUS(base)) & CMDINV)
-	goto must_be_adaptec;
+    ok = TRUE;
 
-    WAIT_UNTIL(INTERRUPT(base), CMDC);
     while (0) {
       fail:
 	buslogic_printk("buslogic_detect: failed setting up mailboxes\n");
     }
-    ok = TRUE;
-  must_be_adaptec:
+
     INTR_RESET(base);
-    if (!ok)
-	printk("- must be Adaptec\n");	/* So that the adaptec detect looks
-					   clean */
-    return ok;
+
+    return !ok;
 }
 
 static int getconfig(unsigned int base, unsigned char *irq,
 		     unsigned char *dma, unsigned char *id,
-		     unsigned char *bus_type, unsigned short *max_sg)
+		     char *bus_type, unsigned short *max_sg,
+		     const unsigned char **bios)
 {
     unsigned char inquiry_cmd[2];
     unsigned char inquiry_result[4];
     int i;
 
+#if (BUSLOGIC_DEBUG & BD_DETECT)
+    buslogic_printk("getconfig: called\n");
+#endif
+
     i = inb(STATUS(base));
     if (i & DIRRDY)
 	i = inb(DATA_IN(base));
     inquiry_cmd[0] = CMD_RETCONF;
     buslogic_out(base, inquiry_cmd, 1);
-    buslogic_in(base, inquiry_result, 3);
-    WAIT_UNTIL(INTERRUPT(base), CMDC);
+    if (buslogic_in(base, inquiry_result, 3))
+	goto fail;
+    WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
     INTR_RESET(base);
     /* Defer using the DMA value until we know the bus type. */
     *dma = inquiry_result[0];
@@ -889,29 +856,27 @@
       default:
 	buslogic_printk("Unable to determine BusLogic IRQ level."
 			"  Disabling board.\n");
-	return TRUE;
+	goto fail;
     }
     *id = inquiry_result[2] & 0x7;
 
+    /* I expected Adaptec boards to fail on this, but it doesn't happen... */
     inquiry_cmd[0] = CMD_INQEXTSETUP;
     inquiry_cmd[1] = 4;
-    if (buslogic_out(base, inquiry_cmd, 2)
-	|| buslogic_in(base, inquiry_result, 4))
-	return TRUE;
-    WAIT_UNTIL(INTERRUPT(base), CMDC);
+    if (buslogic_out(base, inquiry_cmd, 2))
+	goto fail;
+    if (buslogic_in(base, inquiry_result, inquiry_cmd[1]))
+	goto fail;
+    WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
+    if (inb(STATUS(base)) & CMDINV)
+	goto fail;
     INTR_RESET(base);
 
-#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE
-    *bus_type = BUS_TYPE_OVERRIDE;
-#else
     *bus_type = inquiry_result[0];
-#endif
     CHECK(*bus_type == 'A' || *bus_type == 'E' || *bus_type == 'M');
-#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE
-    if (inquiry_result[0] != BUS_TYPE_OVERRIDE)
-	buslogic_printk("Overriding bus type %c with %c\n",
-			inquiry_result[0], BUS_TYPE_OVERRIDE);
-#endif
+
+    *bios = (const unsigned char *)((unsigned int)inquiry_result[1] << 12);
+
     *max_sg = (inquiry_result[3] << 8) | inquiry_result[2];
 
     /* We only need a DMA channel for ISA boards.  Some other types of boards
@@ -935,60 +900,182 @@
 	  default:
 	    buslogic_printk("Unable to determine BusLogic DMA channel."
 			    "  Disabling board.\n");
-	    return TRUE;
+	    goto fail;
 	}
     else
 	*dma = 0;
 
     while (0) {
       fail:
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 	buslogic_printk("buslogic_detect: query board settings\n");
+#endif
 	return TRUE;
     }
 
     return FALSE;
 }
 
-static int get_translation(unsigned int base)
+/* Query the board.  This acts both as part of the detection sequence and as a
+   means to get necessary configuration information. */
+static int buslogic_query(unsigned int base, unsigned char *trans,
+			  unsigned char *irq, unsigned char *dma,
+			  unsigned char *id, char *bus_type,
+			  unsigned short *max_sg, const unsigned char **bios,
+			  char *model, char *firmware_rev)
 {
-    /* ??? Unlike UltraStor, I see no way of determining whether > 1G mapping
-       has been enabled.  However, it appears that BusLogic uses a mapping
-       scheme which varies with the disk size when > 1G mapping is enabled.
-       For disks <= 1G, this mapping is the same regardless of the setting of
-       > 1G mapping.  Therefore, we should be safe in always assuming that > 1G
-       mapping has been enabled. */
-    return BIOS_TRANSLATION_BIG;
-}
+    unsigned char inquiry_cmd[2];
+    unsigned char inquiry_result[6];
+    unsigned char geo;
+    unsigned int i;
 
-/* Query the board to find out the model. */
-static int buslogic_query(unsigned int base, int *trans)
-{
-    static const unsigned char inquiry_cmd[] = { CMD_INQUIRY };
-    unsigned char inquiry_result[4];
-    int i;
+#if (BUSLOGIC_DEBUG & BD_DETECT)
+    buslogic_printk("buslogic_query: called\n");
+#endif
 
-    i = inb(STATUS(base));
-    if (i & DIRRDY)
-	i = inb(DATA_IN(base));
-    buslogic_out(base, inquiry_cmd, sizeof inquiry_cmd);
-    buslogic_in(base, inquiry_result, 4);
-    WAIT_UNTIL(INTERRUPT(base), CMDC);
+    /* Quick and dirty test for presence of the card. */
+    if (inb(STATUS(base)) == 0xFF)
+	goto fail;
+
+    /* Check the GEOMETRY port early for quick bailout on Adaptec boards. */
+    geo = inb(GEOMETRY(base));
+#if (BUSLOGIC_DEBUG & BD_DETECT)
+    buslogic_printk("geometry bits: %02X\n", geo);
+#endif
+    /* Here is where we tell the men from the boys (i.e. Adaptec's don't
+       support the GEOMETRY port, the men do :-) */
+    if (geo == 0xFF)
+	goto fail;
+
+    /* In case some other card was probing here, reset interrupts. */
+    INTR_RESET(base);
+
+    /* Reset the adapter.  I ought to make a hard reset, but it's not really
+       necessary. */
+    outb(RSOFT | RINT/* | RSBUS*/, CONTROL(base));
+
+    /* Wait a little bit for things to settle down. */
+    i = jiffies + 2;
+    while (i > jiffies);
+
+    /* Expect INREQ and HARDY, any of the others are bad. */
+    WAIT(STATUS(base), INREQ | HARDY, DACT | DFAIL | CMDINV | DIRRDY | CPRBSY);
+
+    /* Shouldn't have generated any interrupts during reset. */
+    if (inb(INTERRUPT(base)) & INTRMASK)
+	goto fail;
+
+    /* Getting the BusLogic firmware revision level is a bit tricky.  We get
+       the first two digits (d.d) from CMD_INQUIRY and then use two undocumented
+       commands to get the remaining digit and letter (d.ddl as in 3.31C). */
+
+    inquiry_cmd[0] = CMD_INQUIRY;
+    buslogic_out(base, inquiry_cmd, 1);
+    if (buslogic_in(base, inquiry_result, 4))
+	goto fail;
+    /* Reading port should reset DIRRDY. */
+    if (inb(STATUS(base)) & DIRRDY)
+	goto fail;
+    WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
     INTR_RESET(base);
+    firmware_rev[0] = inquiry_result[2];
+    firmware_rev[1] = '.';
+    firmware_rev[2] = inquiry_result[3];
+    firmware_rev[3] = '\0';
+#if 0
+    buslogic_printk("Inquiry Bytes: %02X(%c) %02X(%c)\n",
+		    inquiry_result[0], inquiry_result[0],
+		    inquiry_result[1], inquiry_result[1]);
+#endif
+
+    if (getconfig(base, irq, dma, id, bus_type, max_sg, bios))
+	goto fail;
+
+    /* Set up defaults */
+#ifdef BIOS_TRANSLATION_OVERRIDE
+    *trans = BIOS_TRANSLATION_OVERRIDE;
+#else
+    *trans = BIOS_TRANSLATION_DEFAULT;
+#endif
+    model[0] = '\0';
+    model[6] = 0;
 
-#if 1	/* ??? Temporary */
-    buslogic_printk("Inquiry Bytes: %02X %02X %02X %02X\n",
-		    inquiry_result[0], inquiry_result[1],
-		    inquiry_result[2], inquiry_result[3]);
+    /* ??? Begin undocumented command use.
+       These may not be supported by clones. */
+
+    do {
+	/* ??? It appears as though AMI BusLogic clones don't implement this
+	   feature.  As an experiment, if we read a 00 we ignore the GEO_GT_1GB
+	   bit and skip all further undocumented commands. */
+	if (geo == 0x00)
+	    break;
+#ifndef BIOS_TRANSLATION_OVERRIDE
+	*trans = ((geo & GEO_GT_1GB)
+		  ? BIOS_TRANSLATION_BIG : BIOS_TRANSLATION_DEFAULT);
 #endif
 
+	inquiry_cmd[0] = CMD_VER_NO_LAST;
+	buslogic_out(base, inquiry_cmd, 1);
+	if (buslogic_in(base, inquiry_result, 1))
+	    break;
+	WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
+	INTR_RESET(base);
+	firmware_rev[3] = inquiry_result[0];
+	firmware_rev[4] = '\0';
+
+	inquiry_cmd[0] = CMD_VER_NO_LETTER;
+	buslogic_out(base, inquiry_cmd, 1);
+	if (buslogic_in(base, inquiry_result, 1))
+	    break;
+	WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
+	INTR_RESET(base);
+	firmware_rev[4] = inquiry_result[0];
+	firmware_rev[5] = '\0';
+
+	/* Use undocumented command to get model number and revision. */
+
+	inquiry_cmd[0] = CMD_RET_MODEL_NO;
+	inquiry_cmd[1] = 6;
+	buslogic_out(base, inquiry_cmd, 2);
+	if (buslogic_in(base, inquiry_result, inquiry_cmd[1]))
+	    break;
+	WAIT_UNTIL_FAST(INTERRUPT(base), CMDC);
+	INTR_RESET(base);
+	memcpy(model, inquiry_result, 5);
+	model[5] = '\0';
+	model[6] = inquiry_result[5];
+    } while (0);
+
+    /* ??? End undocumented command use. */
+
+    /* bus_type from getconfig doesn't differentiate between EISA/VESA.  We
+       override using the model number here. */
+    /* ??? What bus_type gets returned for PCI? */
+    switch (*bus_type) {
+      case 'E':
+	switch (model[0]) {
+	  case '4':
+	    *bus_type = 'V';
+	    break;
+	  case '7':
+	    break;
+	  default:
+	    *bus_type = 'X';
+	    break;
+	}
+	break;
+      default:
+	break;
+    }
+
     while (0) {
       fail:
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 	buslogic_printk("buslogic_query: query board settings\n");
+#endif
 	return TRUE;
     }
 
-    *trans = get_translation(base);
-
     return FALSE;
 }
 
@@ -997,31 +1084,46 @@
 {
     unsigned char dma;
     unsigned char irq;
-    unsigned int base = 0;
+    unsigned int base;
     unsigned char id;
-    unsigned char bus_type;
+    char bus_type;
     unsigned short max_sg;
-    int trans;
-    struct Scsi_Host *shpnt = NULL;
+    unsigned char bios_translation;
+    const unsigned char *bios;
+    char *model;
+    char *firmware_rev;
+    struct Scsi_Host *shpnt;
+    size_t indx;
     int count = 0;
-    int indx;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_DETECT)
     buslogic_printk("buslogic_detect:\n");
 #endif
 
     tpnt->can_queue = BUSLOGIC_MAILBOXES;
     for (indx = 0; indx < ARRAY_SIZE(bases); indx++)
-	if (!check_region(bases[indx], 3)) {
+	if (!check_region(bases[indx], 4)) {
 	    shpnt = scsi_register(tpnt, sizeof (struct hostdata));
 
 	    base = bases[indx];
 
-	    if (test_port(base, shpnt))
+	    model = HOSTDATA(shpnt)->model;
+	    firmware_rev = HOSTDATA(shpnt)->firmware_rev;
+	    if (buslogic_query(base, &bios_translation, &irq, &dma, &id,
+			       &bus_type, &max_sg, &bios, model, firmware_rev))
 		goto unregister;
 
-	    /* Set the Bus on/off-times as not to ruin floppy performance. */
-	    {
+#if (BUSLOGIC_DEBUG & BD_DETECT)
+	    buslogic_stat(base);
+#endif
+
+	    if (setup_mailboxes(base, shpnt))
+		goto unregister;
+
+	    /* Set the Bus on/off-times as not to ruin floppy performance.
+	       CMD_BUSOFF_TIME is a noop for EISA boards (and possibly
+	       others???). */
+	    if (bus_type != 'E') {
 		/* The default ON/OFF times for BusLogic adapters is 7/4. */
 		static const unsigned char oncmd[] = { CMD_BUSON_TIME, 7 };
 		static const unsigned char offcmd[] = { CMD_BUSOFF_TIME, 5 };
@@ -1029,9 +1131,6 @@
 		INTR_RESET(base);
 		buslogic_out(base, oncmd, sizeof oncmd);
 		WAIT_UNTIL(INTERRUPT(base), CMDC);
-		/* CMD_BUSOFF_TIME is a noop for EISA boards, but as there is
-		   no way to to differentiate EISA from VESA we send it
-		   unconditionally. */
 		INTR_RESET(base);
 		buslogic_out(base, offcmd, sizeof offcmd);
 		WAIT_UNTIL(INTERRUPT(base), CMDC);
@@ -1043,33 +1142,32 @@
 		INTR_RESET(base);
 	    }
 
-	    if (buslogic_query(base, &trans))
-		goto unregister;
-
-	    if (getconfig(base, &irq, &dma, &id, &bus_type, &max_sg))
-		goto unregister;
-
-#if BUSLOGIC_DEBUG
-	    buslogic_stat(base);
-#endif
-	    /* Here is where we tell the men from the boys (i.e. an Adaptec
-	       will fail in setup_mailboxes, the men will not :-) */
-	    if (!setup_mailboxes(base, shpnt))
-		goto unregister;
-
-	    printk("Configuring BusLogic %s HA at port 0x%03X, IRQ %u",
-		   (bus_type == 'A' ? "ISA"
-		    : (bus_type == 'E' ? "EISA/VESA" : "MCA")),
-		   base, irq);
+	    buslogic_printk("Configuring %s HA at port 0x%03X, IRQ %u",
+			    (bus_type == 'A' ? "ISA"
+			     : (bus_type == 'E' ? "EISA"
+				: (bus_type == 'M' ? "MCA"
+				   : (bus_type == 'P' ? "PCI"
+				      : (bus_type == 'V' ? "VESA"
+					 : (bus_type == 'X' ? "EISA/VESA"
+					    : "Unknown")))))),
+			    base, irq);
+	    if (bios != NULL)
+		printk(", BIOS 0x%05X", (unsigned int)bios);
 	    if (dma != 0)
 		printk(", DMA %u", dma);
 	    printk(", ID %u\n", id);
+	    buslogic_printk("Model Number: %s",
+			    (model[0] ? model : "Unknown"));
+	    if (model[0])
+		printk(" (revision %d)", model[6]);
+	    printk("\n");
+	    buslogic_printk("Firmware revision: %s\n", firmware_rev);
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 	    buslogic_stat(base);
 #endif
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 	    buslogic_printk("buslogic_detect: enable interrupt channel %d\n",
 			    irq);
 #endif
@@ -1083,7 +1181,7 @@
 	    }
 
 	    if (dma) {
-		if (request_dma(dma,"buslogic")) {
+		if (request_dma(dma, "buslogic")) {
 		    buslogic_printk("Unable to allocate DMA channel for "
 				    "BusLogic controller.\n");
 		    free_irq(irq);
@@ -1091,36 +1189,63 @@
 		    goto unregister;
 		}
 
-		if (dma >= 5) {
-		    outb((dma - 4) | CASCADE, DMA_MODE_REG);
-		    outb(dma - 4, DMA_MASK_REG);
-		}
+		/* The DMA-Controller.  We need to fool with this because we
+		   want to be able to use an ISA BusLogic without having to
+		   have the BIOS enabled. */
+		set_dma_mode(dma, DMA_MODE_CASCADE);
+		enable_dma(dma);
 	    }
 
 	    host[irq - 9] = shpnt;
 	    shpnt->this_id = id;
-#ifdef CONFIG_NO_BUGGY_BUSLOGIC
 	    /* Only type 'A' (AT/ISA) bus adapters use unchecked DMA. */
 	    shpnt->unchecked_isa_dma = (bus_type == 'A');
+#ifndef CONFIG_NO_BUGGY_BUSLOGIC
+	    /* There is a hardware bug in the BT-445S prior to revision D.
+	       When the BIOS is enabled and you have more than 16MB of memory,
+	       the card mishandles memory transfers over 16MB which (if viewed
+	       as a 24-bit address) overlap with the BIOS address space.  For
+	       example if you have the BIOS located at physical address
+	       0xDC000 and a DMA transfer from the card to RAM starts at
+	       physical address 0x10DC000 then the transfer is messed up.  To
+	       be more precise every fourth byte of the transfer is messed up.
+	       (This analysis courtesy of Tomas Hurka, author of the NeXTSTEP
+	       BusLogic driver.) */
+
+	    if (bus_type == 'V'				    /* 445 */
+		&& firmware_rev[0] <= '3'		    /* S */
+		&& bios != NULL) {			    /* BIOS enabled */
+#if 0
+		/* ??? Once LNZ's forbidden_addr stuff makes it into the higher
+		   level scsi code, we can use this instead. */
+		/* Avoid addresses which "mirror" the BIOS for DMA. */
+		shpnt->forbidden_addr = bios;
+		shpnt->forbidden_size = 16 * 1024;
 #else
-	    /* Bugs in the firmware of the 445S with >16M.  This does not seem
-	       to affect Revision E boards with firmware 3.37. */
-	    shpnt->unchecked_isa_dma = 1;
+		/* Use double-buffering. */
+		shpnt->unchecked_isa_dma = TRUE;
 #endif
+	    }
+#endif
+	    /* Have to keep cmd_per_lun at 1 for ISA machines otherwise lots
+	       of memory gets sucked up for bounce buffers.  */
+	    /* ??? Unfortunately, cmd_per_lun is only in the
+	       Scsi_Host_Template structure, not the Scsi_Host structure.
+	       Therefore, this could cause high memory consumption if a system
+	       has multiple BusLogic adapters which are a mix of ISA and
+	       non-ISA. */
+	    if (!shpnt->unchecked_isa_dma)
+		shpnt->hostt->cmd_per_lun = BUSLOGIC_NONISA_CMDLUN;
 	    shpnt->sg_tablesize = max_sg;
 	    if (shpnt->sg_tablesize > BUSLOGIC_MAX_SG)
 		shpnt->sg_tablesize = BUSLOGIC_MAX_SG;
-	    /* ??? If we can dynamically allocate the mailbox arrays, I'll
-	       probably bump up this number. */
-	    shpnt->hostt->can_queue = BUSLOGIC_MAILBOXES;
-	    /* No known way to determine BIOS base address, but we don't
-	       care since we don't use it anyway. */
-	    shpnt->base = NULL;
+	    /* ??? shpnt->base should really be "const unsigned char *"... */
+	    shpnt->base = (unsigned char *)bios;
 	    shpnt->io_port = base;
 	    shpnt->dma_channel = dma;
 	    shpnt->irq = irq;
-	    HOSTDATA(shpnt)->bios_translation = trans;
-	    if (trans == BIOS_TRANSLATION_BIG)
+	    HOSTDATA(shpnt)->bios_translation = bios_translation;
+	    if (bios_translation == BIOS_TRANSLATION_BIG)
 		buslogic_printk("Using extended bios translation.\n");
 	    HOSTDATA(shpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1;
 	    HOSTDATA(shpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1;
@@ -1134,7 +1259,7 @@
 		    = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 		size_t i;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 		buslogic_printk("*** READ CAPACITY ***\n");
 #endif
 		for (i = 0; i < sizeof buf; i++)
@@ -1146,7 +1271,7 @@
 					i, *(int *)(buf + 4), *(int *)buf);
 		    }
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_DETECT)
 		buslogic_printk("*** NOW RUNNING MY OWN TEST ***\n");
 #endif
 		for (i = 0; i < 4; i++) {
@@ -1164,7 +1289,7 @@
 	    }
 #endif
 
-	    snarf_region(bases[indx], 3);	/* Register the IO ports that
+	    snarf_region(bases[indx], 4);	/* Register the IO ports that
 						   we use */
 	    count++;
 	    continue;
@@ -1292,7 +1417,7 @@
     static const unsigned char buscmd[] = { CMD_START_SCSI };
     unsigned int i;
 
-#if BUSLOGIC_DEBUG
+#if (BUSLOGIC_DEBUG & BD_RESET)
     buslogic_printk("buslogic_reset\n");
 #endif
 #if 0
@@ -1303,8 +1428,7 @@
     /* First locate the ccb for this command. */
     for (i = 0; i < BUSLOGIC_MAILBOXES; i++)
 	if (HOSTDATA(scpnt->host)->sc[i] == scpnt) {
-	    HOSTDATA(scpnt->host)->ccbs[i].op = 0x81;	/* ??? BUS DEVICE
-							   RESET */
+	    HOSTDATA(scpnt->host)->ccbs[i].op = CCB_OP_BUS_RESET;
 
 	    /* Now tell the BusLogic to flush all pending commands for this
 	       target. */
@@ -1329,7 +1453,8 @@
 		    sctmp->result = DID_RESET << 16;
 		    if (sctmp->host_scribble)
 			scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC);
-		    printk("Sending DID_RESET for target %d\n", scpnt->target);
+		    buslogic_printk("Sending DID_RESET for target %d\n",
+				    scpnt->target);
 		    sctmp->scsi_done(scpnt);
 
 		    HOSTDATA(scpnt->host)->sc[i] = NULL;
@@ -1347,35 +1472,41 @@
     return SCSI_RESET_PUNT;
 }
 
+/* ??? This is probably not correct for series "C" boards.  I believe these
+   support separate mappings for each disk.  We would need to issue a
+   CMD_READ_FW_LOCAL_RAM command to check for the particular drive being
+   queried.  Note that series "C" boards can be differentiated by having
+   HOSTDATA(disk->device->host)->firmware_rev[0] >= '4'. */
 int buslogic_biosparam(Disk *disk, int dev, int *ip)
 {
-    /* ??? This truncates.  Should we round up to next MB? */
-    unsigned int mb = disk->capacity >> 11;
+    unsigned int size = disk->capacity;
 
     /* ip[0] == heads, ip[1] == sectors, ip[2] == cylinders */
     if (HOSTDATA(disk->device->host)->bios_translation == BIOS_TRANSLATION_BIG
-	&& mb > 1024) {
-	if (mb > 4096) {
+	&& size >= 0x200000) {		/* 1GB */
+	if (size >= 0x400000) {		/* 2GB */
+#if 0	/* ??? Used in earlier kernels, but disagrees with BusLogic info. */
+	    if (mb >= 0x800000) {	/* 4GB */
+		ip[0] = 256;
+		ip[1] = 64;
+	    } else {
+		ip[0] = 256;
+		ip[1] = 32;
+	    }
+#else
 	    ip[0] = 256;
 	    ip[1] = 64;
-	    ip[2] = mb >> 3;
-/*	    if (ip[2] > 1024)
-		ip[2] = 1024; */
-	} else if (mb > 2048) {
-	    ip[0] = 256;
-	    ip[1] = 32;
-	    ip[2] = mb >> 2;
+#endif
 	} else {
 	    ip[0] = 128;
 	    ip[1] = 32;
-	    ip[2] = mb >> 1;
 	}
     } else {
 	ip[0] = 64;
 	ip[1] = 32;
-	ip[2] = mb;
-/*	if (ip[2] > 1024)
-	    ip[2] = 1024; */
     }
+    ip[2] = size / (ip[0] * ip[1]);
+/*    if (ip[2] > 1024)
+	ip[2] = 1024; */
     return 0;
 }
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/buslogic.h linux/drivers/scsi/buslogic.h
--- v1.1.67/linux/drivers/scsi/buslogic.h	Wed Oct 12 14:57:29 1994
+++ linux/drivers/scsi/buslogic.h	Fri Nov  4 08:30:44 1994
@@ -20,15 +20,14 @@
 int buslogic_biosparam(Disk *, int, int *);
 
 #define BUSLOGIC_CMDLUN 1	/* Do not set this too high.  It sucks
-				   up lots of memory on machines with > 16Mb
-				   because of the huge number of bounce
-				   buffers that need to be allocated.
+				   up lots of memory on ISA machines
+				   with > 16MB because of the huge number of
+				   bounce buffers that need to be allocated.
 				   For boards that use non-ISA bus, we can
 				   bump this in the board detect routine.  
-				   			10/8/94 ERY */
-				   
+							10/8/94 ERY */
 
-#define BUSLOGIC { NULL, 			\
+#define BUSLOGIC { NULL,			\
 		   "BusLogic",			\
 		   buslogic_detect,		\
 		   NULL,			\
@@ -65,8 +64,11 @@
 #define BD_ABORT	0x0001
 #define BD_COMMAND	0x0002
 #define BD_DETECT	0x0004
-#define BD_INTERRUPT	0x0008
-#define BD_RESET	0x0010
+#define BD_ERRORS	0x0008
+#define BD_INTERRUPT	0x0010
+#define BD_IO		0x0020
+#define BD_RESET	0x0040
+#define BD_UNDOCUMENTED	0x0080
 
 /* I/O Port interface */
 /* READ */
@@ -77,18 +79,27 @@
 #define HARDY 0x10		/* Host Adapter Ready */
 #define CPRBSY 0x08		/* Command/Parameter Register Busy */
 #define DIRRDY 0x04		/* Data In Register Ready */
+				/* 0x02 is reserved */
 #define CMDINV 0x01		/* Command Invalid */
-#define STATMASK 0xFD		/* 0x02 is reserved */
 
 #define DATA_IN(base) (STATUS(base) + 1)
 
 #define INTERRUPT(base) (STATUS(base) + 2)
 #define INTV 0x80		/* Interrupt Valid */
+				/* 0x70 are reserved */
 #define RSTS 0x08		/* SCSI Reset State */
 #define CMDC 0x04		/* Command Complete */
 #define MBOR 0x02		/* Mailbox Out Ready */
 #define IMBL 0x01		/* Incoming Mailbox Loaded */
-#define INTRMASK 0x8F		/* 0x70 are reserved */
+#define INTRMASK 0x8F
+
+/* This undocumented port returns a bitmask indicating geometry translation. */
+#define GEOMETRY(base) (STATUS(base) + 3)
+#define GEO_GT_1GB 0x80		/* > 1GB under DOS geometry mapping */
+				/* 0x70 are unknown */
+#define GEO_XLATION_S_D1 0x0C	/* Disk 1 geometry ("S" models only) */
+#define GEO_XLATION_S_D0 0x03	/* Disk 0 geometry ("S" models only) */
+
 
 /* WRITE */
 #define CONTROL(base) STATUS(base)
@@ -96,6 +107,7 @@
 #define RSOFT 0x40		/* Soft Reset */
 #define RINT 0x20		/* Interrupt Reset */
 #define RSBUS 0x10		/* SCSI Bus Reset */
+				/* 0x0F are reserved */
 
 #define COMMAND_PARAMETER(base) (STATUS(base) + 1)
 #define CMD_TSTCMDCINT 0x00	/* Test CMDC Interrupt */
@@ -120,7 +132,13 @@
 #define CMD_HA_DIAG 0x20	/* Host Adapter Diagnostic */
 #define CMD_HA_OPTIONS 0x21	/* Host Adapter Options */
 #define CMD_INITEXTMB 0x81	/* Initialize Extended Mailbox */
+#define CMD_VER_NO_LAST 0x84	/* Version Number Last Byte (undocumented) */
+#define CMD_VER_NO_LETTER 0x85	/* Version Number One Letter (undocumented) */
+#define CMD_RET_MODEL_NO 0x8B	/* Return Model Number (undocumented) */
 #define CMD_INQEXTSETUP 0x8D	/* Inquire Extended Set-up Information */
+#define CMD_ROUND_ROBIN 0x8F	/* Enable strict vs. half-assed round-robin
+				   mailbox filling (undocumented) */
+#define CMD_READ_FW_LCL_RAM 0x91/* Read Firmware Local RAM (undocumented) */
 #define CMD_WRITE_INQ_BUF 0x9A	/* Write Inquiry Data Buffer
 				   (Target Mode Only) */
 #define CMD_READ_INQ_BUF 0x9B	/* Read Inquiry Data Buffer
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v1.1.67/linux/drivers/scsi/eata.c	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/eata.c	Tue Nov 29 10:07:14 1994
@@ -367,10 +367,6 @@
    return j;
 }
 
-const char *eata_info (void) {
-   return driver_name;
-}
-
 static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
    unsigned int k;
    struct scatterlist * sgpnt;
@@ -471,7 +467,7 @@
       cpp->data_len = htonl(SCpnt->request_bufflen);
       }
 
-   memcpy(cpp->cdb, SCpnt->cmnd, COMMAND_SIZE(*SCpnt->cmnd));
+   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
    /* Send control packet to the board */
    if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v1.1.67/linux/drivers/scsi/eata.h	Tue Nov 22 15:41:12 1994
+++ linux/drivers/scsi/eata.h	Tue Nov 29 10:07:14 1994
@@ -10,16 +10,16 @@
 int eata_detect(Scsi_Host_Template *);
 int eata_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int eata_abort(Scsi_Cmnd *);
-const char *eata_info(void);
 int eata_reset(Scsi_Cmnd *);
 int eata_bios_param(Disk *, int, int*);
 
 #define EATA {  NULL, /* Ptr for modules */                    \
+		  NULL, /* usage count for modules */	       \
                 "EISA EATA 2.0A rev. " EATA_VERSION " by "     \
-                "Dario_Ballabio@milano.europe.dg.com.",\
+                "Dario_Ballabio@milano.europe.dg.com.",        \
                 eata_detect,	        	               \
                 NULL, /* Release */     	               \
-		eata_info,                                     \
+		NULL,	                                       \
 		NULL,    			       	       \
 		eata_queuecommand,			       \
 		eata_abort,				       \
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v1.1.67/linux/drivers/scsi/fdomain.c	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/fdomain.c	Tue Nov 29 10:07:13 1994
@@ -375,9 +375,9 @@
 
 #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
 
-static void print_banner( void )
+static void print_banner( struct Scsi_Host * shpnt )
 {
-   printk( "%s", fdomain_16x0_info() );
+   printk( "%s", fdomain_16x0_info(shpnt) );
    printk( "Future Domain: BIOS version %d.%d, %s\n",
 	   bios_major, bios_minor,
 	   chip == tmc1800 ? "TMC-1800"
@@ -637,7 +637,7 @@
       return 0;		/* Cannot find valid set of ports */
    }
 
-   print_banner();
+   print_banner(NULL);
 
    SCSI_Mode_Cntl_port   = port_base + SCSI_Mode_Cntl;
    FIFO_Data_Count_port  = port_base + FIFO_Data_Count;
@@ -755,7 +755,7 @@
    return 1;
 }
 
-const char *fdomain_16x0_info(void)
+const char *fdomain_16x0_info(struct Scsi_Host * shpnt)
 {
    static char buffer[80];
    char        *pt;
@@ -1014,7 +1014,7 @@
    if (chip == tmc1800
        && !current_SC->SCp.have_data_in
        && (current_SC->SCp.sent_command
-	   >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
+	   >= current_SC->cmd_len)) {
 				/* We have to get the FIFO direction
 				   correct, so I've made a table based
 				   on the SCSI Standard of which commands
@@ -1376,7 +1376,7 @@
    unsigned int irr;
    unsigned int isr;
    
-   print_banner();
+   print_banner(SCpnt->host);
    switch (SCpnt->SCp.phase) {
    case in_arbitration: printk( "arbitration " ); break;
    case in_selection:   printk( "selection " );   break;
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h
--- v1.1.67/linux/drivers/scsi/fdomain.h	Mon Aug  1 08:05:56 1994
+++ linux/drivers/scsi/fdomain.h	Tue Nov 29 10:07:12 1994
@@ -28,13 +28,13 @@
 int        fdomain_16x0_detect( Scsi_Host_Template * );
 int        fdomain_16x0_command( Scsi_Cmnd * );
 int        fdomain_16x0_abort( Scsi_Cmnd * );
-const char *fdomain_16x0_info( void );
+const char *fdomain_16x0_info( struct Scsi_Host * );
 int        fdomain_16x0_reset( Scsi_Cmnd * ); 
 int        fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
 int        fdomain_16x0_biosparam( Disk *, int, int * );
 
-#define FDOMAIN_16X0 { NULL,                             \
-		       "Future Domain TMC-16x0",         \
+#define FDOMAIN_16X0 { NULL, NULL,                            \
+		       NULL,			         \
 		       fdomain_16x0_detect,              \
 		       NULL,				 \
 		       fdomain_16x0_info,                \
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/g_NCR5380.h linux/drivers/scsi/g_NCR5380.h
--- v1.1.67/linux/drivers/scsi/g_NCR5380.h	Tue Aug  2 11:29:19 1994
+++ linux/drivers/scsi/g_NCR5380.h	Tue Nov 29 10:07:12 1994
@@ -35,7 +35,6 @@
 #ifndef ASM
 int generic_NCR5380_abort(Scsi_Cmnd *);
 int generic_NCR5380_detect(Scsi_Host_Template *);
-const char *generic_NCR5380_info(void);
 int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int generic_NCR5380_reset(Scsi_Cmnd *);
 
@@ -54,8 +53,8 @@
 
 #ifdef HOSTS_C
 
-#define GENERIC_NCR5380 {NULL, "Trantor T128/T128F/T228", 		\
-	generic_NCR5380_detect, NULL, generic_NCR5380_info, NULL, 	\
+#define GENERIC_NCR5380 {NULL, NULL, "Trantor T128/T128F/T228", 	\
+	generic_NCR5380_detect, NULL, NULL, NULL, 	\
 	generic_NCR5380_queue_command, generic_NCR5380_abort, 		\
 	generic_NCR5380_reset, NULL, 					\
 	NULL, /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,		\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v1.1.67/linux/drivers/scsi/hosts.c	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/hosts.c	Tue Nov 29 10:07:11 1994
@@ -227,6 +227,7 @@
 	struct Scsi_Host * retval, *shpnt;
 	retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j);
 	retval->host_busy = 0;
+	retval->block = NULL;
 	if(j > 0xffff) panic("Too many extra bytes requested\n");
 	retval->extra_bytes = j;
 	retval->loaded_as_module = scsi_loadable_module_flag;
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v1.1.67/linux/drivers/scsi/hosts.h	Tue Nov 15 15:35:39 1994
+++ linux/drivers/scsi/hosts.h	Tue Nov 29 10:07:11 1994
@@ -52,6 +52,9 @@
 	  /* Used with loadable modules so we can construct a linked list. */
 	  struct SHT * next;
 
+	  /* Used with loadable modules so that we know when it is safe to unload */
+	  int * usage_count;
+
 	/*
 		The name pointer is a pointer to the name of the SCSI
 		device detected.
@@ -77,14 +80,18 @@
 
 	int (* detect)(struct SHT *); 
 
-	  /* Used with loadable modules to unload the host structures */
+	  /* Used with loadable modules to unload the host structures.  Note:
+	   there is a default action built into the modules code which may
+	   be sufficient for most host adapters.  Thus you may not have to supply
+	   this at all. */
 	int (*release)(struct Scsi_Host *);
 	/*
 		The info function will return whatever useful
-		information the developer sees fit.              
+		information the developer sees fit.  If not provided, then
+		the name field will be used instead.
 	*/
 
-        const char *(* info)(void);
+        const char *(* info)(struct Scsi_Host *);
 
 	/*
 		The command function takes a target, a command (this is a SCSI 
@@ -221,6 +228,8 @@
 	be two Scsi_Host entries, but only 1 Scsi_Host_Template entries.
 */
 
+#define SCSI_HOST_BLOCK 0x800
+
 struct Scsi_Host
 	{
 		struct Scsi_Host * next;
@@ -232,9 +241,15 @@
 		Scsi_Cmnd *host_queue; 
 		Scsi_Host_Template * hostt;
 
+		/* Pointer to a circularly linked list - this indicates the hosts
+		   that should be locked out of performing I/O while we have an active
+		   command on this host. */
+		struct Scsi_Host * block;
+
 		/* These parameters should be set by the detect routine */
 		unsigned char *base;
 		short unsigned int io_port;
+		unsigned char n_io_port;
 		unsigned char irq;
 		unsigned char dma_channel;
 		/*
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v1.1.67/linux/drivers/scsi/in2000.c	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/in2000.c	Tue Nov 29 10:07:14 1994
@@ -399,7 +399,7 @@
 	}			/* end while intrpt active */
 }
 
-static int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
     unchar direction;
     unchar *cmd = (unchar *) SCpnt->cmnd;
@@ -551,7 +551,7 @@
     ++internal_done_flag;
 }
 
-static int in2000_command(Scsi_Cmnd * SCpnt)
+int in2000_command(Scsi_Cmnd * SCpnt)
 {
     in2000_queuecommand(SCpnt, internal_done);
 
@@ -560,7 +560,7 @@
     return internal_done_errcode;
 }
 
-static int in2000_detect(Scsi_Host_Template * tpnt)
+int in2000_detect(Scsi_Host_Template * tpnt)
 {
 /* Order chosen to reduce conflicts with some multi-port serial boards */
     int base_tab[] = { 0x220,0x200,0x110,0x100 };
@@ -632,7 +632,7 @@
     return 1;
 }
 
-static int in2000_abort(Scsi_Cmnd * SCpnt)
+int in2000_abort(Scsi_Cmnd * SCpnt)
 {
     DEB(printk("in2000_abort\n"));
     /*
@@ -649,7 +649,7 @@
     while (jiffies < time) ;
 }
 
-static int in2000_reset(Scsi_Cmnd * SCpnt)
+int in2000_reset(Scsi_Cmnd * SCpnt)
 {
     DEB(printk("in2000_reset called\n"));
     /*
@@ -671,7 +671,7 @@
 #endif
 }
 
-static int in2000_biosparam(Disk * disk, int dev, int* iinfo)
+int in2000_biosparam(Disk * disk, int dev, int* iinfo)
 	{
 	  int size = disk->capacity;
     DEB(printk("in2000_biosparam\n"));
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v1.1.67/linux/drivers/scsi/in2000.h	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/in2000.h	Tue Nov 29 10:07:14 1994
@@ -94,12 +94,12 @@
 #define MAX_SENSE 14
 #define MAX_STATUS 32
 
-static int in2000_detect(Scsi_Host_Template *);
-static int in2000_command(Scsi_Cmnd *);
-static int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int in2000_abort(Scsi_Cmnd *);
-static int in2000_reset(Scsi_Cmnd *);
-static int in2000_biosparam(Disk *, int, int*);
+int in2000_detect(Scsi_Host_Template *);
+int in2000_command(Scsi_Cmnd *);
+int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int in2000_abort(Scsi_Cmnd *);
+int in2000_reset(Scsi_Cmnd *);
+int in2000_biosparam(Disk *, int, int*);
 
 
 #ifndef NULL
@@ -108,7 +108,7 @@
 
 /* next may be "SG_NONE" or "SG_ALL" or nr. of (1k) blocks per R/W Cmd. */
 #define IN2000_SG SG_ALL
-#define IN2000 {NULL, "Always IN2000", in2000_detect, NULL,	\
+#define IN2000 {NULL, NULL, "Always IN2000", in2000_detect, NULL,	\
 		NULL, in2000_command,		\
 		in2000_queuecommand,		\
 		in2000_abort,			\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v1.1.67/linux/drivers/scsi/pas16.c	Sun Aug 21 15:52:02 1994
+++ linux/drivers/scsi/pas16.c	Tue Nov 29 10:07:13 1994
@@ -525,17 +525,4 @@
 	return 0;
 }
 
-/*
- * Function : const char *pas16_info(void)
- *
- * Purpose : provide further information about this driver.
- *
- * Returns : an empty string.
- */
-
-const char *pas16_info (void) {
-    static const char string[]="";
-    return string;
-}
-
 #include "NCR5380.c"
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/pas16.h linux/drivers/scsi/pas16.h
--- v1.1.67/linux/drivers/scsi/pas16.h	Fri Aug 19 08:54:04 1994
+++ linux/drivers/scsi/pas16.h	Tue Nov 29 10:07:12 1994
@@ -117,7 +117,6 @@
 int pas16_abort(Scsi_Cmnd *);
 int pas16_biosparam(Disk *, int, int*);
 int pas16_detect(Scsi_Host_Template *);
-const char *pas16_info(void);
 int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int pas16_reset(Scsi_Cmnd *);
 
@@ -141,8 +140,8 @@
 
 #ifdef HOSTS_C
 
-#define MV_PAS16 {NULL, "Pro Audio Spectrum-16 SCSI", 			\
-	pas16_detect, NULL, pas16_info,					\
+#define MV_PAS16 {NULL, NULL, "Pro Audio Spectrum-16 SCSI", 		\
+	pas16_detect, NULL, NULL,					\
 	NULL, pas16_queue_command, pas16_abort, pas16_reset, NULL, 	\
 	pas16_biosparam, 						\
 	/* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,			\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/qlogic.c linux/drivers/scsi/qlogic.c
--- v1.1.67/linux/drivers/scsi/qlogic.c	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/qlogic.c	Tue Nov 29 10:07:14 1994
@@ -258,7 +258,7 @@
 	outb(0x99, qbase + 5);	/* timer */
 	outb(cmd->target, qbase + 4);
 
-	for (i = 0; i < COMMAND_SIZE(cmd->cmnd[0]); i++)
+	for (i = 0; i < cmd->cmd_len; i++)
 		outb(cmd->cmnd[i], qbase + 2);
 	qlcmd = cmd;
 	outb(0x41, qbase + 3);	/* select and send command */
@@ -558,7 +558,7 @@
 
 /*----------------------------------------------------------------*/
 /* return info string */
-const char	*qlogic_info()
+const char	*qlogic_info(struct Scsi_Host * host)
 {
 	return qinfo;
 }
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/qlogic.h linux/drivers/scsi/qlogic.h
--- v1.1.67/linux/drivers/scsi/qlogic.h	Sat Nov 26 18:36:06 1994
+++ linux/drivers/scsi/qlogic.h	Tue Nov 29 10:07:14 1994
@@ -2,7 +2,7 @@
 #define _QLOGIC_H
 
 int qlogic_detect(Scsi_Host_Template * );
-const char * qlogic_info(void);
+const char * qlogic_info(struct Scsi_Host *);
 int qlogic_command(Scsi_Cmnd *);
 int qlogic_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int qlogic_abort(Scsi_Cmnd *);
@@ -14,6 +14,7 @@
 #endif
 
 #define QLOGIC {		\
+	NULL,			\
 	NULL,			\
 	NULL,			\
 	qlogic_detect,		\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.1.67/linux/drivers/scsi/scsi.c	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/scsi.c	Tue Nov 29 10:07:11 1994
@@ -269,8 +269,10 @@
 	  SCmd.target = dev;
 	  SCmd.lun = lun;
 
+	  SCmd.request.sem = NULL;  /* Used for mutex if loading devices after boot */
 	  SCmd.request.dev = 0xffff; /* Mark not busy */
 	  SCmd.use_sg  = 0;
+	  SCmd.cmd_len = 0;
 	  SCmd.old_use_sg  = 0;
 	  SCmd.transfersize = 0;
 	  SCmd.underflow = 0;
@@ -316,6 +318,7 @@
 	  scsi_cmd[5] = 0;
 	  
 	  SCmd.request.dev = 0xffff; /* Mark not busy */
+	  SCmd.cmd_len = 0;
 	  
 	  scsi_do_cmd (&SCmd,
 		       (void *)  scsi_cmd, (void *) 
@@ -462,6 +465,7 @@
 		    scsi_cmd[5] = 0;
 		    
 		    SCmd.request.dev = 0xffff; /* Mark not busy */
+		    SCmd.cmd_len = 0;
 		    
 		    scsi_do_cmd (&SCmd,
 				 (void *)  scsi_cmd, (void *) 
@@ -527,10 +531,6 @@
 		{
 		case NORMAL_TIMEOUT:
 			if (!in_scan_scsis) {
-			      printk("scsi : aborting command due to timeout : pid %lu, scsi%d, id %d, lun %d ",
-				SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->target, (int) 
-				SCpnt->lun);
-				print_command (SCpnt->cmnd);
 #ifdef DEBUG_TIMEOUT
 			  scsi_dump_status();
 #endif
@@ -572,10 +572,10 @@
   struct buffer_head * bh, *bhp;
 
   if (!device)
-    panic ("No device passed to allocate_device().\n");
+    panic ("No device passed to request_queueable().\n");
   
   if (req && req->dev <= 0)
-    panic("Invalid device in allocate_device");
+    panic("Invalid device in request_queueable");
   
   SCpnt =  device->host->host_queue;
     while(SCpnt){
@@ -629,6 +629,7 @@
   SCpnt->old_use_sg  = 0;
   SCpnt->transfersize = 0;
   SCpnt->underflow = 0;
+  SCpnt->cmd_len = 0;
   return SCpnt;
 }
 
@@ -734,6 +735,7 @@
   SCpnt->use_sg = 0;  /* Reset the scatter-gather flag */
   SCpnt->old_use_sg  = 0;
   SCpnt->transfersize = 0;      /* No default transfer size */
+  SCpnt->cmd_len = 0;
   SCpnt->underflow = 0;         /* Do not flag underflow conditions */
   return SCpnt;
 }
@@ -832,8 +834,10 @@
 	SCpnt->request_buffer = &SCpnt->sense_buffer;
 	SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
 	SCpnt->use_sg = 0;
+	SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
 	internal_cmnd (SCpnt);
 	SCpnt->use_sg = SCpnt->old_use_sg;
+	SCpnt->cmd_len = SCpnt->old_cmd_len;
 	}
 
 
@@ -891,6 +895,11 @@
 			 (host->host_busy >= host->can_queue));
 	    } else {
 	      host->host_busy++;
+	      if (host->block) {
+		struct Scsi_Host * block;
+		for(block = host->block; block != host; block = block->block)
+		  block->host_busy |= ~SCSI_HOST_BLOCK;
+	      }
 	      sti();
 	      break;
 	    };
@@ -924,6 +933,9 @@
 	SCpnt->request_buffer = buffer;
 	SCpnt->request_bufflen = bufflen;
 	SCpnt->old_use_sg = SCpnt->use_sg;
+	if (SCpnt->cmd_len == 0)
+		SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
+	SCpnt->old_cmd_len = SCpnt->cmd_len;
 
 	/* Start the timer ticking.  */
 
@@ -1329,6 +1341,7 @@
 			    SCpnt->request_buffer = SCpnt->buffer;
 			    SCpnt->request_bufflen = SCpnt->bufflen;
 			    SCpnt->use_sg = SCpnt->old_use_sg;
+			    SCpnt->cmd_len = SCpnt->old_cmd_len;
 			    internal_cmnd (SCpnt);
 			  };
 			break;	
@@ -1337,14 +1350,29 @@
 		}
 
 	if (status == FINISHED) 
-		{
-		#ifdef DEBUG
-			printk("Calling done function - at address %08x\n", SCpnt->done);
-		#endif
+	  {
+#ifdef DEBUG
+	    	printk("Calling done function - at address %08x\n", SCpnt->done);
+#endif
 		host->host_busy--; /* Indicate that we are free */
+		if (host->host_busy == 0 && host->block) {
+		  struct Scsi_Host * block;
+		  /*
+		   * Now remove the locks for all of the related hosts.
+		   */
+		  for(block = host->block; block != host; block = block->block)
+		      block->host_busy &= ~SCSI_HOST_BLOCK;
+		  /*
+		   * Now wake them up.  We do this in two separate stages to prevent
+		   * race conditions.
+		   */
+		  for(block = host->block; block != host; block = block->block)
+		      wake_up(&block->host_wait);
+		}
 		wake_up(&host->host_wait);
 		SCpnt->result = result | ((exit & 0xff) << 24);
 		SCpnt->use_sg = SCpnt->old_use_sg;
+		SCpnt->cmd_len = SCpnt->old_cmd_len;
 		SCpnt->done (SCpnt);
 		}
 
@@ -1403,6 +1431,10 @@
 			  update_timeout(SCpnt, oldto);
 			  return 0;
 			}
+			printk("scsi : aborting command due to timeout : pid %lu, scsi%d, id %d, lun %d ",
+			       SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->target, (int) 
+			       SCpnt->lun);
+			print_command (SCpnt->cmnd);
 			SCpnt->abort_reason = why;
 			switch(host->hostt->abort(SCpnt)) {
 			  /* We do not know how to abort.  Try waiting another
@@ -1787,6 +1819,8 @@
 	      SCpnt->request.dev = -1; /* Mark not busy */
 	      SCpnt->use_sg = 0;
 	      SCpnt->old_use_sg = 0;
+	      SCpnt->old_cmd_len = 0;
+	      SCpnt->timeout = 0;
               SCpnt->underflow = 0;
               SCpnt->transfersize = 0;
 	      SCpnt->host_scribble = NULL;
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.1.67/linux/drivers/scsi/scsi.h	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/scsi.h	Tue Nov 29 10:07:13 1994
@@ -428,6 +428,8 @@
 	struct Scsi_Host * host;
 	Scsi_Device * device;
 	unsigned char target, lun;
+	unsigned char cmd_len;
+	unsigned char old_cmd_len;
 	struct scsi_cmnd *next, *prev;	
 
 /* These elements define the operation we are about to perform */
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/scsi_debug.h linux/drivers/scsi/scsi_debug.h
--- v1.1.67/linux/drivers/scsi/scsi_debug.h	Sun Jul 10 09:09:38 1994
+++ linux/drivers/scsi/scsi_debug.h	Tue Nov 29 10:07:12 1994
@@ -7,7 +7,6 @@
 int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int scsi_debug_abort(Scsi_Cmnd *);
 int scsi_debug_biosparam(Disk *, int, int[]);
-const char *scsi_debug_info(void);
 int scsi_debug_reset(Scsi_Cmnd *);
 
 #ifndef NULL
@@ -16,8 +15,8 @@
 
 #define SCSI_DEBUG_MAILBOXES 8
 
-#define SCSI_DEBUG {NULL, "SCSI DEBUG", scsi_debug_detect, NULL,	\
-		scsi_debug_info, scsi_debug_command,		\
+#define SCSI_DEBUG {NULL, NULL, "SCSI DEBUG", scsi_debug_detect, NULL,	\
+		NULL, scsi_debug_command,		\
 		scsi_debug_queuecommand,			\
 		scsi_debug_abort,				\
 		scsi_debug_reset,				\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v1.1.67/linux/drivers/scsi/scsi_ioctl.c	Sat Jul 16 22:24:36 1994
+++ linux/drivers/scsi/scsi_ioctl.c	Tue Nov 29 10:07:13 1994
@@ -33,12 +33,17 @@
 	
 	if ((temp = host->hostt->present) && buffer) {
 		len = get_fs_long ((unsigned long *) buffer);
-		string = host->hostt->info();
-		slen = strlen(string);
-		if (len > slen)
-			len = slen + 1;
-		verify_area(VERIFY_WRITE, buffer, len);
-		memcpy_tofs (buffer, string, len);
+		if(host->hostt->info)
+		  string = host->hostt->info(host);
+		else 
+		  string = host->hostt->name;
+		if(string) {
+		  slen = strlen(string);
+		  if (len > slen)
+		    len = slen + 1;
+		  verify_area(VERIFY_WRITE, buffer, len);
+		  memcpy_tofs (buffer, string, len);
+		}
 	}
 	return temp;
 }
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.1.67/linux/drivers/scsi/sd.c	Tue Nov 15 15:35:40 1994
+++ linux/drivers/scsi/sd.c	Tue Nov 29 10:07:14 1994
@@ -838,6 +838,7 @@
       cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
       memset ((void *) &cmd[2], 0, 8);
       SCpnt->request.dev = 0xffff;  /* Mark as really busy again */
+      SCpnt->cmd_len = 0;
       SCpnt->sense_buffer[0] = 0;
       SCpnt->sense_buffer[2] = 0;
       
@@ -863,6 +864,7 @@
 	  memset ((void *) &cmd[2], 0, 8);
 	  cmd[4] = 1; /* Start spin cycle */
 	  SCpnt->request.dev = 0xffff;  /* Mark as really busy again */
+	  SCpnt->cmd_len = 0;
 	  SCpnt->sense_buffer[0] = 0;
 	  SCpnt->sense_buffer[2] = 0;
 	  
@@ -897,6 +899,7 @@
     memset ((void *) &cmd[2], 0, 8);
     memset ((void *) buffer, 0, 8);
     SCpnt->request.dev = 0xffff;  /* Mark as really busy again */
+    SCpnt->cmd_len = 0;
     SCpnt->sense_buffer[0] = 0;
     SCpnt->sense_buffer[2] = 0;
     
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/sd.h linux/drivers/scsi/sd.h
--- v1.1.67/linux/drivers/scsi/sd.h	Thu Jul  7 18:45:07 1994
+++ linux/drivers/scsi/sd.h	Tue Nov 29 10:07:11 1994
@@ -39,6 +39,7 @@
 		unsigned char sector_bit_shift;	/* power of 2 sectors per FS block */
 		unsigned ten:1;			/* support ten byte read / write */
 		unsigned remap:1;		/* support remapping  */
+		unsigned has_part_table:1;	/* has partition table */
 		} Scsi_Disk;
 	
 extern Scsi_Disk * rscsi_disks;
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v1.1.67/linux/drivers/scsi/seagate.c	Tue Sep 13 06:55:10 1994
+++ linux/drivers/scsi/seagate.c	Tue Nov 29 10:07:11 1994
@@ -362,7 +362,7 @@
 		}
 	}
 	 
-const char *seagate_st0x_info(void) {
+const char *seagate_st0x_info(struct Scsi_Host * shpnt) {
       static char buffer[256];
         sprintf(buffer, "scsi%d : %s at irq %d address %p options :"
 #ifdef ARBITRATE
@@ -525,7 +525,7 @@
  * Set linked command bit in control field of SCSI command.
  */
 
-	  current_cmnd[COMMAND_SIZE(current_cmnd[0])] |= 0x01;
+	  current_cmnd[SCpnt->cmd_len] |= 0x01;
 	  if (linked_connected) {
 #if (DEBUG & DEBUG_LINKED) 
 	    printk("scsi%d : using linked commands, current I_T_L nexus is ",
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/seagate.h linux/drivers/scsi/seagate.h
--- v1.1.67/linux/drivers/scsi/seagate.h	Sun Jul 10 09:09:38 1994
+++ linux/drivers/scsi/seagate.h	Tue Nov 29 10:07:11 1994
@@ -17,7 +17,7 @@
 int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 
 int seagate_st0x_abort(Scsi_Cmnd *);
-const char *seagate_st0x_info(void);
+const char *seagate_st0x_info(struct Scsi_Host *);
 int seagate_st0x_reset(Scsi_Cmnd *); 
 
 #ifndef NULL
@@ -26,7 +26,7 @@
 
 int seagate_st0x_biosparam(Disk *, int, int*);
 
-#define SEAGATE_ST0X  {NULL, "Seagate ST-01/ST-02", seagate_st0x_detect, \
+#define SEAGATE_ST0X  {NULL, NULL, NULL, seagate_st0x_detect, 		\
 			 NULL, 						\
 			 seagate_st0x_info, seagate_st0x_command,  	\
 			 seagate_st0x_queue_command, seagate_st0x_abort, \
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v1.1.67/linux/drivers/scsi/sg.c	Sat Aug  6 20:32:14 1994
+++ linux/drivers/scsi/sg.c	Tue Nov 29 10:07:11 1994
@@ -220,6 +220,7 @@
   int dev=MINOR(inode->i_rdev);
   Scsi_Cmnd *SCpnt;
   int bsize,size,amt,i;
+  unsigned char opcode;
   unsigned char cmnd[MAX_COMMAND_SIZE];
   struct scsi_generic *device=&scsi_generics[dev];
 
@@ -274,6 +275,9 @@
   SCpnt->request.dev=dev;
   SCpnt->sense_buffer[0]=0;
   size=COMMAND_SIZE(get_fs_byte(buf));
+  size=COMMAND_SIZE(opcode);
+  if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
+  SCpnt->cmd_len = size;
   memcpy_fromfs(cmnd,buf,size);
   buf+=size;
   memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header));
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/sg.h linux/drivers/scsi/sg.h
--- v1.1.67/linux/drivers/scsi/sg.h	Fri Aug 19 08:54:06 1994
+++ linux/drivers/scsi/sg.h	Tue Nov 29 10:07:11 1994
@@ -17,7 +17,8 @@
   int reply_len;   /* maximum length <4096 of expected reply */
   int pack_id;     /* id number of packet */
   int result;      /* 0==ok, otherwise refer to errno codes */
-  int flags;			/* for future use */
+  unsigned int twelve_byte:1; /* Force 12 byte command length for group 6 & 7 commands  */
+  unsigned int other_flags:31;			/* for future use */
   unsigned char sense_buffer[16]; /* used only by reads */
   /* command follows then data for command */
  };
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.67/linux/drivers/scsi/sr.c	Mon Nov 28 14:21:45 1994
+++ linux/drivers/scsi/sr.c	Tue Nov 29 15:55:55 1994
@@ -325,9 +325,11 @@
       sec   = (unsigned long)buffer[16]/16*10 + (unsigned long)buffer[16]%16;
       frame = (unsigned long)buffer[17]/16*10 + (unsigned long)buffer[17]%16;
       sector = min*60*75 + sec*75 + frame;
-      sector-=CD_BLOCK_OFFSET;
       if (sector) {
-	printk("sr_photocd: multisession PhotoCD detected\n"); }}
+      	sector -= CD_BLOCK_OFFSET;
+	printk("sr_photocd: multisession PhotoCD detected\n");
+      }
+    }
     scsi_free(buffer,512);
     SCpnt->request.dev = -1;
     break;
@@ -374,9 +376,11 @@
       sec   = (unsigned long)buffer[2]/16*10 + (unsigned long)buffer[2]%16;
       frame = (unsigned long)buffer[3]/16*10 + (unsigned long)buffer[3]%16;
       sector = min*60*75 + sec*75 + frame;
-      sector-=CD_BLOCK_OFFSET;
       if (sector) {
-        printk("sr_photocd: multisession PhotoCD detected: %lu\n",sector); }}
+        sector -= CD_BLOCK_OFFSET;
+        printk("sr_photocd: multisession PhotoCD detected: %lu\n",sector);
+      }
+    }
     scsi_free(buffer,512);
     SCpnt->request.dev = -1;
     break;
@@ -826,10 +830,11 @@
 
 static void get_sectorsize(int i){
   unsigned char cmd[10];
-  unsigned char buffer[513];
+  unsigned char *buffer;
   int the_result, retries;
   Scsi_Cmnd * SCpnt;
   
+  buffer = (unsigned char *) scsi_malloc(512);
   SCpnt = allocate_device(NULL, scsi_CDs[i].device, 1);
 
   retries = 3;
@@ -838,6 +843,7 @@
     cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;
     memset ((void *) &cmd[2], 0, 8);
     SCpnt->request.dev = 0xffff;  /* Mark as really busy */
+    SCpnt->cmd_len = 0;
     
     memset(buffer, 0, 8);
 
@@ -887,6 +893,7 @@
       scsi_CDs[i].capacity *= 4;
     scsi_CDs[i].needs_sector_size = 0;
   };
+  scsi_free(buffer, 512);
 }
 
 static void sr_init()
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c
--- v1.1.67/linux/drivers/scsi/t128.c	Fri Aug 19 08:54:06 1994
+++ linux/drivers/scsi/t128.c	Tue Nov 29 10:07:11 1994
@@ -385,17 +385,4 @@
 	return 0;
 }
 
-/*
- * Function : const char *t128_info(void)
- *
- * Purpose : provide further information about this driver.
- *
- * Returns : an empty string.
- */
-
-const char *t128_info (void) {
-    static const char string[]="";
-    return string;
-}
-
 #include "NCR5380.c"
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/t128.h linux/drivers/scsi/t128.h
--- v1.1.67/linux/drivers/scsi/t128.h	Fri Aug 19 08:54:06 1994
+++ linux/drivers/scsi/t128.h	Tue Nov 29 10:07:11 1994
@@ -94,7 +94,6 @@
 int t128_abort(Scsi_Cmnd *);
 int t128_biosparam(Disk *, int, int*);
 int t128_detect(Scsi_Host_Template *);
-const char *t128_info(void);
 int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int t128_reset(Scsi_Cmnd *);
 
@@ -118,8 +117,8 @@
 
 #ifdef HOSTS_C
 
-#define TRANTOR_T128 {NULL, "Trantor T128/T128F/T228", t128_detect, NULL,  \
-	t128_info,							\
+#define TRANTOR_T128 {NULL, NULL, "Trantor T128/T128F/T228", t128_detect, NULL,  \
+	NULL,							\
 	NULL, t128_queue_command, t128_abort, t128_reset, NULL, 	\
 	t128_biosparam, 						\
 	/* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,			\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v1.1.67/linux/drivers/scsi/u14-34f.c	Sat Nov 26 18:36:07 1994
+++ linux/drivers/scsi/u14-34f.c	Tue Nov 29 10:07:14 1994
@@ -416,10 +416,6 @@
    return j;
 }
 
-const char *u14_34f_info(void) {
-   return driver_name;
-}
-
 static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
    unsigned int k, data_len = 0;
    struct scatterlist * sgpnt;
@@ -506,7 +502,7 @@
       cpp->data_len = SCpnt->request_bufflen;
       }
 
-   cpp->scsi_cdbs_len = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd);
+   cpp->scsi_cdbs_len = SCpnt->cmd_len;
    memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len);
 
    if (wait_on_busy(sh[j]->io_port)) {
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v1.1.67/linux/drivers/scsi/u14-34f.h	Fri Nov 18 15:22:09 1994
+++ linux/drivers/scsi/u14-34f.h	Tue Nov 29 10:07:11 1994
@@ -5,7 +5,6 @@
 #define _U14_34F_H
 
 int u14_34f_detect(Scsi_Host_Template *);
-const char *u14_34f_info(void);
 int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *);
@@ -15,11 +14,12 @@
 
 #define ULTRASTOR_14_34F {                                            \
                 NULL,                                                 \
+                NULL,                                                 \
                 "UltraStor 14F/34F rev. " U14_34F_VERSION " by "      \
                 "Dario_Ballabio@milano.europe.dg.com.",\
                 u14_34f_detect,                                       \
                 NULL,                                                 \
-                u14_34f_info,                                         \
+                NULL,		                                      \
                 NULL,                                                 \
                 u14_34f_queuecommand,                                 \
                 u14_34f_abort,                                        \
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v1.1.67/linux/drivers/scsi/ultrastor.c	Wed Oct 12 15:49:14 1994
+++ linux/drivers/scsi/ultrastor.c	Tue Nov 29 10:07:11 1994
@@ -620,7 +620,7 @@
   return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt);
 }
 
-const char *ultrastor_info(void)
+const char *ultrastor_info(struct Scsi_Host * shpnt)
 {
     static char buf[64];
 
@@ -714,7 +714,7 @@
     my_mscp->command_link = 0;		/*???*/
     my_mscp->scsi_command_link_id = 0;	/*???*/
     my_mscp->length_of_sense_byte = sizeof SCpnt->sense_buffer;
-    my_mscp->length_of_scsi_cdbs = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd);
+    my_mscp->length_of_scsi_cdbs = SCpnt->cmd_len;
     memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs);
     my_mscp->adapter_status = 0;
     my_mscp->target_status = 0;
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/ultrastor.h linux/drivers/scsi/ultrastor.h
--- v1.1.67/linux/drivers/scsi/ultrastor.h	Sun Jul 10 09:09:36 1994
+++ linux/drivers/scsi/ultrastor.h	Tue Nov 29 10:07:11 1994
@@ -14,7 +14,7 @@
 #define _ULTRASTOR_H
 
 int ultrastor_detect(Scsi_Host_Template *);
-const char *ultrastor_info(void);
+const char *ultrastor_info(struct Scsi_Host * shpnt);
 int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int ultrastor_abort(Scsi_Cmnd *);
 int ultrastor_reset(Scsi_Cmnd *);
@@ -29,8 +29,8 @@
 #define ULTRASTOR_24F_PORT 0xC80
 
 
-#define ULTRASTOR_14F { NULL, /* Ptr for modules*/	\
-			  "UltraStor 14F/24F/34F", 	\
+#define ULTRASTOR_14F { NULL, NULL, /* Ptr for modules*/ \
+			  NULL,			 	\
 			  ultrastor_detect, 		\
 			  NULL,	/* Release */		\
 			  ultrastor_info, 		\
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v1.1.67/linux/drivers/scsi/wd7000.c	Tue Aug 23 09:48:52 1994
+++ linux/drivers/scsi/wd7000.c	Tue Nov 29 10:07:11 1994
@@ -900,7 +900,7 @@
     register short cdblen;
     Adapter *host = (Adapter *) SCpnt->host->hostdata;
 
-    cdblen = COMMAND_SIZE(cdb[0]);
+    cdblen = SCpnt->cmd_len;
     idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7);
     SCpnt->scsi_done = done;
     SCpnt->SCp.phase = 1;
@@ -1203,18 +1203,6 @@
 int wd7000_reset(Scsi_Cmnd * SCpnt)
 {
     return SCSI_RESET_PUNT;
-}
-
-
-/*
- *  The info routine in the WD7000 structure isn't per-adapter, so it can't
- *  really return any useful information about an adapter.  Because of this,
- *  I'm no longer using it to return rev. level.
- */
-const char *wd7000_info(void)
-{
-    static char info[] = "Western Digital WD-7000";
-    return info;
 }
 
 
diff -u --recursive --new-file v1.1.67/linux/drivers/scsi/wd7000.h linux/drivers/scsi/wd7000.h
--- v1.1.67/linux/drivers/scsi/wd7000.h	Sun Jul 10 09:09:38 1994
+++ linux/drivers/scsi/wd7000.h	Tue Nov 29 10:07:11 1994
@@ -16,7 +16,6 @@
 int wd7000_command(Scsi_Cmnd *);
 int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int wd7000_abort(Scsi_Cmnd *);
-const char *wd7000_info(void);
 int wd7000_reset(Scsi_Cmnd *);
 int wd7000_biosparam(Disk *, int, int*);
 
@@ -38,11 +37,11 @@
 #define WD7000_Q    16
 #define WD7000_SG   16
 
-#define WD7000 { NULL, \
+#define WD7000 { NULL, NULL, \
 	"Western Digital WD-7000",      \
 	wd7000_detect,                  \
 	NULL,				\
-	wd7000_info,                    \
+	NULL,		                \
 	wd7000_command,	                \
 	wd7000_queuecommand,	        \
 	wd7000_abort,			\
diff -u --recursive --new-file v1.1.67/linux/fs/locks.c linux/fs/locks.c
--- v1.1.67/linux/fs/locks.c	Mon Nov 28 14:21:45 1994
+++ linux/fs/locks.c	Tue Nov 29 10:05:13 1994
@@ -186,7 +186,7 @@
 				if (ret_val) return -EDEADLOCK;
 			}
 			dlock_wait = dlock_wait->next;
-		} while (dlock_wait != fl->fl_wait);
+		} while (dlock_wait != NULL);
 	}
 	return 0;
 }
diff -u --recursive --new-file v1.1.67/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.1.67/linux/fs/proc/array.c	Tue Aug 23 09:48:52 1994
+++ linux/fs/proc/array.c	Tue Nov 29 16:16:00 1994
@@ -12,7 +12,7 @@
  *                      make sure SET_PROCTITLE works. Also removed
  *                      bad '!' which forced address recalculation for
  *                      EVERY character on the current page.
- *                      <middelin@calvin.iaf.nl>
+ *                      <middelin@polyware.iaf.nl>
  */
 
 #include <linux/types.h>
diff -u --recursive --new-file v1.1.67/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c
--- v1.1.67/linux/fs/umsdos/emd.c	Wed Nov  2 12:03:47 1994
+++ linux/fs/umsdos/emd.c	Tue Nov 29 10:09:59 1994
@@ -25,9 +25,10 @@
 	int count)
 {
 	int ret;
+	int old_fs = get_fs();
 	set_fs (KERNEL_DS);
 	ret = msdos_readdir(inode,filp,dirent,count);
-	set_fs (USER_DS);
+	set_fs (old_fs);
 	return ret;
 }
 /*
@@ -39,10 +40,11 @@
 	char *buf,
 	int count)
 {
-	int ret;	
+	int ret;
+	int old_fs = get_fs();	
 	set_fs (KERNEL_DS);
 	ret = msdos_file_read(inode,filp,buf,count);
-	set_fs (USER_DS);
+	set_fs (old_fs);
 	return ret;
 }
 /*
@@ -55,9 +57,10 @@
 	int count)
 {
 	int ret;
+	int old_fs = get_fs();
 	set_fs (KERNEL_DS);
 	ret = msdos_file_write(inode,filp,buf,count);
-	set_fs (USER_DS);
+	set_fs (old_fs);
 	return ret;
 }
 
@@ -208,7 +211,7 @@
 	return ret;
 }
 
-#define CHUNK_SIZE (16*UMSDOS_REC_SIZE)
+#define CHUNK_SIZE (8*UMSDOS_REC_SIZE)
 struct find_buffer{
 	char buffer[CHUNK_SIZE];
 	int pos;	/* read offset in buffer */
diff -u --recursive --new-file v1.1.67/linux/include/asm-i386/dma.h linux/include/asm-i386/dma.h
--- v1.1.67/linux/include/asm-i386/dma.h	Mon Nov 28 14:21:46 1994
+++ linux/include/asm-i386/dma.h	Tue Nov 29 10:07:10 1994
@@ -69,6 +69,9 @@
 
 #define MAX_DMA_CHANNELS	8
 
+/* The maximum address that we can perform a DMA transfer to on this platform */
+#define MAX_DMA_ADDRESS      0xffffff
+
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
 #define IO_DMA2_BASE	0xC0	/* 16 bit master DMA, ch 4(=slave input)..7 */
diff -u --recursive --new-file v1.1.67/linux/include/linux/inet.h linux/include/linux/inet.h
--- v1.1.67/linux/include/linux/inet.h	Wed Aug 10 19:26:43 1994
+++ linux/include/linux/inet.h	Tue Nov 29 16:04:04 1994
@@ -42,11 +42,14 @@
 #ifndef _LINUX_INET_H
 #define _LINUX_INET_H
 
-#ifdef __i386__
+#if defined(__i386__)
 #define NET16(x)	((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
-#endif
-#ifdef __mc680x0__
+#elif defined(__mc68000__)
 #define NET16(x)	(x)
+#elif defined(__alpha__)
+#define NET16(x)	((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
+#else
+#error change this to match your machine
 #endif
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v1.1.67/linux/include/linux/ioport.h linux/include/linux/ioport.h
--- v1.1.67/linux/include/linux/ioport.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/ioport.h	Tue Nov 29 10:07:10 1994
@@ -14,10 +14,12 @@
 /*
  * Call check_region() before probing for your hardware.
  * Once you have found you hardware, register it with snarf_region().
+ * If you unload the driver, use release_region to free ports.
  */
 extern void reserve_setup(char *str, int *ints);
 extern int check_region(unsigned int from, unsigned int extent);
 extern void snarf_region(unsigned int from, unsigned int extent);
+extern void release_region(unsigned int from, unsigned int extent);
 
 
 #define HAVE_AUTOIRQ
diff -u --recursive --new-file v1.1.67/linux/include/linux/ip.h linux/include/linux/ip.h
--- v1.1.67/linux/include/linux/ip.h	Mon Nov 28 14:21:46 1994
+++ linux/include/linux/ip.h	Tue Nov 29 16:02:35 1994
@@ -35,7 +35,7 @@
 #if defined(__i386__)  
 		u8	flags:4,
 			overflow:4;
-#elif defined(__mc680x0__)
+#elif defined(__mc68000__)
 		u8	overflow:4,
 			flags:4;
 #elif defined(__alpha__)
@@ -76,7 +76,7 @@
 #if defined(__i386__)
 	u8	ihl:4,
 		version:4;
-#elif defined (__mc680x0__)
+#elif defined (__mc68000__)
 	u8	version:4,
   		ihl:4;
 #elif defined (__alpha__)
diff -u --recursive --new-file v1.1.67/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.1.67/linux/include/linux/mm.h	Mon Nov 28 14:21:46 1994
+++ linux/include/linux/mm.h	Tue Nov 29 10:07:10 1994
@@ -234,6 +234,11 @@
 #define GFP_NOBUFFER	0x04
 #define GFP_NFS		0x05
 
+/* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
+   platforms, used as appropriate on others */
+
+#define GFP_DMA		0x80
+
 /*
  * vm_ops not present page codes for shared memory.
  *
diff -u --recursive --new-file v1.1.67/linux/include/linux/tcp.h linux/include/linux/tcp.h
--- v1.1.67/linux/include/linux/tcp.h	Mon Nov 28 14:21:46 1994
+++ linux/include/linux/tcp.h	Tue Nov 29 16:02:45 1994
@@ -37,7 +37,7 @@
 		ack:1,
 		urg:1,
 		res2:2;
-#elif defined(__mc680x0__)
+#elif defined(__mc68000__)
 	u16	res2:2,
 		urg:1,
 		ack:1,
diff -u --recursive --new-file v1.1.67/linux/init/main.c linux/init/main.c
--- v1.1.67/linux/init/main.c	Sat Nov 26 18:36:07 1994
+++ linux/init/main.c	Tue Nov 29 10:07:10 1994
@@ -92,6 +92,7 @@
 extern void pas16_setup(char *str, int *ints);
 extern void generic_NCR5380_setup(char *str, int *intr);
 extern void aha152x_setup(char *str, int *ints);
+extern void aha1542_setup(char *str, int *ints);
 extern void aha274x_setup(char *str, int *ints);
 extern void scsi_luns_setup(char *str, int *ints);
 extern void sound_setup(char *str, int *ints);
@@ -210,6 +211,9 @@
 #endif
 #ifdef CONFIG_SCSI_AHA152X
         { "aha152x=", aha152x_setup},
+#endif
+#ifdef CONFIG_SCSI_AHA1542
+        { "aha1542=", aha1542_setup},
 #endif
 #ifdef CONFIG_SCSI_AHA274X
         { "aha274x=", aha274x_setup},
diff -u --recursive --new-file v1.1.67/linux/kernel/ioport.c linux/kernel/ioport.c
--- v1.1.67/linux/kernel/ioport.c	Wed Dec  1 14:44:15 1993
+++ linux/kernel/ioport.c	Tue Nov 29 10:07:10 1994
@@ -165,6 +165,16 @@
 	return;
 }
 
+void release_region(unsigned int from, unsigned int num)
+{
+	if (from > IO_BITMAP_SIZE*32)
+		return;
+	if (from + num > IO_BITMAP_SIZE*32)
+		num = IO_BITMAP_SIZE*32 - from;
+	set_bitmap(ioport_registrar, from, num, 0);
+	return;
+}
+
 int check_region(unsigned int from, unsigned int num)
 {
 	if (from > IO_BITMAP_SIZE*32)
diff -u --recursive --new-file v1.1.67/linux/modules/NET_MODULES linux/modules/NET_MODULES
--- v1.1.67/linux/modules/NET_MODULES	Fri Oct 28 13:07:37 1994
+++ linux/modules/NET_MODULES	Tue Nov 29 17:10:13 1994
@@ -1 +1 @@
-3c509.o de600.o de620.o 3c501.o plip.o 8390.o
+3c509.o de600.o de620.o 3c501.o eexpress.o plip.o 8390.o
diff -u --recursive --new-file v1.1.67/linux/net/inet/proc.c linux/net/inet/proc.c
--- v1.1.67/linux/net/inet/proc.c	Thu Nov  3 17:53:30 1994
+++ linux/net/inet/proc.c	Tue Nov 29 16:16:00 1994
@@ -17,7 +17,7 @@
  * Fixes:
  *		Alan Cox	:	UDP sockets show the rxqueue/txqueue
  *					using hint flag for the netinfo.
- *	Pauline Middelink	:	Pidentd support
+ *	Pauline Middelink	:	identd support
  *		Alan Cox	:	Make /proc safer.
  *	Erik Schoenfelder	:	/proc/net/snmp
  *		Alan Cox	:	Handle dead sockets properly.
diff -u --recursive --new-file v1.1.67/linux/net/inet/sock.c linux/net/inet/sock.c
--- v1.1.67/linux/net/inet/sock.c	Mon Nov 28 14:21:47 1994
+++ linux/net/inet/sock.c	Tue Nov 29 16:16:00 1994
@@ -46,7 +46,7 @@
  *		Alan Cox	:	Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so...
  *		Rick Sladkey	:	Relaxed UDP rules for matching packets.
  *		C.E.Hawkins	:	IFF_PROMISC/SIOCGHWADDR support
- *	Pauline Middelink	:	Pidentd support
+ *	Pauline Middelink	:	identd support
  *		Alan Cox	:	Fixed connect() taking signals I think.
  *		Alan Cox	:	SO_LINGER supported
  *		Alan Cox	:	Error reporting fixes
