Index: linux/drivers/scsi/hosts.h
diff -c linux/drivers/scsi/hosts.h:1.1.1.2 linux/drivers/scsi/hosts.h:1.2
*** linux/drivers/scsi/hosts.h:1.1.1.2	Sat Dec 18 18:33:45 1999
--- linux/drivers/scsi/hosts.h	Wed Dec 22 02:41:24 1999
***************
*** 437,442 ****
--- 437,444 ----
      struct module * module;	  /* Used for loadable modules */
      unsigned char scsi_type;
      unsigned char major;
+     unsigned char min_major;      /* Minimum major in range. */ 
+     unsigned char max_major;      /* Maximum major in range. */
      unsigned char nr_dev;	  /* Number currently attached */
      unsigned char dev_noticed;	  /* Number of devices detected. */
      unsigned char dev_max;	  /* Current size of arrays */
***************
*** 447,453 ****
      void (*finish)(void);	  /* Perform initialization after attachment */
      int (*attach)(Scsi_Device *); /* Attach devices to arrays */
      void (*detach)(Scsi_Device *);
!     int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. */
  };
  
  extern struct Scsi_Device_Template sd_template;
--- 449,456 ----
      void (*finish)(void);	  /* Perform initialization after attachment */
      int (*attach)(Scsi_Device *); /* Attach devices to arrays */
      void (*detach)(Scsi_Device *);
!     int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
!                                            Selects command for blkdevs */
  };
  
  extern struct Scsi_Device_Template sd_template;
Index: linux/drivers/scsi/scsi.c
diff -c linux/drivers/scsi/scsi.c:1.1.1.4 linux/drivers/scsi/scsi.c:1.3
*** linux/drivers/scsi/scsi.c:1.1.1.4	Wed Dec 22 10:28:43 1999
--- linux/drivers/scsi/scsi.c	Wed Dec 22 02:41:24 1999
***************
*** 1470,1478 ****
  	 */
  
  
- 	host->host_busy++;
- 	device->device_busy++;
- 
  	/*
  	 * Our own function scsi_done (which marks the host as not busy, disables
  	 * the timeout counter, etc) will be called by us or by the
--- 1470,1475 ----
***************
*** 1575,1580 ****
--- 1572,1580 ----
  	 * Since serial_number is now 0, the error handler cound detect this
  	 * situation and avoid to call the the low level driver abort routine.
  	 * (DB)
+          *
+          * FIXME(eric) - I believe that this test is now redundant, due to
+          * the test of the return status of del_timer().
  	 */
  	if (SCpnt->state == SCSI_STATE_TIMEOUT) {
  		SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt));
Index: linux/drivers/scsi/scsi_error.c
diff -c linux/drivers/scsi/scsi_error.c:1.1.1.4 linux/drivers/scsi/scsi_error.c:1.4
*** linux/drivers/scsi/scsi_error.c:1.1.1.4	Wed Dec 22 10:28:44 1999
--- linux/drivers/scsi/scsi_error.c	Wed Dec 22 02:41:24 1999
***************
*** 1778,1783 ****
--- 1778,1794 ----
  	for (SCpnt = SCdone; SCpnt != NULL; SCpnt = SCdone) {
  		SCdone = SCpnt->bh_next;
  		SCpnt->bh_next = NULL;
+                 /*
+                  * Oh, this is a vile hack.  scsi_done() expects a timer
+                  * to be running on the command.  If there isn't, it assumes
+                  * that the command has actually timed out, and a timer
+                  * handler is running.  That may well be how we got into
+                  * this fix, but right now things are stable.  We add
+                  * a timer back again so that we can report completion.
+                  * scsi_done() will immediately remove said timer from
+                  * the command, and then process it.
+                  */
+ 		scsi_add_timer(SCpnt, 100, scsi_eh_times_out);
  		scsi_done(SCpnt);
  	}
  
***************
*** 1809,1815 ****
--- 1820,1833 ----
  	int rtn;
  	DECLARE_MUTEX_LOCKED(sem);
  
+         /*
+          * We only listen to signals if the HA was loaded as a module.
+          * If the HA was compiled into the kernel, then we don't listen
+          * to any signals.
+          */
+         if( host->loaded_as_module ) {
  	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+         }
  
  	lock_kernel();
  
***************
*** 1844,1853 ****
--- 1862,1875 ----
  		 * trying to unload a module.
  		 */
  		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n"));
+                 if( host->loaded_as_module ) {
  		down_interruptible(&sem);
  
  		if (signal_pending(current))
  			break;
+                 } else {
+                         down(&sem);
+                 }
  
  		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n"));
  
Index: linux/drivers/scsi/scsi_lib.c
diff -c linux/drivers/scsi/scsi_lib.c:1.1.1.3 linux/drivers/scsi/scsi_lib.c:1.3
*** linux/drivers/scsi/scsi_lib.c:1.1.1.3	Wed Dec 22 10:28:45 1999
--- linux/drivers/scsi/scsi_lib.c	Wed Dec 22 02:41:24 1999
***************
*** 607,612 ****
--- 607,628 ----
  		if (spnt->blk && spnt->major == major) {
  			return spnt;
  		}
+ 		/*
+ 		 * I am still not entirely satisfied with this solution,
+ 		 * but it is good enough for now.  Disks have a number of
+ 		 * major numbers associated with them, the primary
+ 		 * 8, which we test above, and a secondary range of 7
+ 		 * different consecutive major numbers.   If this ever
+ 		 * becomes insufficient, then we could add another function
+ 		 * to the structure, and generalize this completely.
+ 		 */
+ 		if( spnt->min_major != 0 
+ 		    && spnt->max_major != 0
+ 		    && major >= spnt->min_major
+ 		    && major <= spnt->max_major )
+ 		{
+ 			return spnt;
+ 		}
  	}
  	return NULL;
  }
***************
*** 742,750 ****
  			if (!SCpnt) {
  				break;
  			}
- 			SHpnt->host_busy++;
- 			SDpnt->device_busy++;
  		}
  
  		/*
  		 * FIXME(eric)
--- 758,771 ----
  			if (!SCpnt) {
  				break;
  			}
  		}
+ 
+ 		/*
+ 		 * Now bump the usage count for both the host and the
+ 		 * device.
+ 		 */
+ 		SHpnt->host_busy++;
+ 		SDpnt->device_busy++;
  
  		/*
  		 * FIXME(eric)
Index: linux/drivers/scsi/scsi_merge.c
diff -c linux/drivers/scsi/scsi_merge.c:1.1.1.3 linux/drivers/scsi/scsi_merge.c:1.3
*** linux/drivers/scsi/scsi_merge.c:1.1.1.3	Wed Dec 22 10:28:45 1999
--- linux/drivers/scsi/scsi_merge.c	Wed Dec 22 02:41:25 1999
***************
*** 290,295 ****
--- 290,319 ----
  
  	count = bh->b_size >> 9;
  	sector = bh->b_rsector;
+ #if CONFIG_HIGHMEM
+ 	/*
+ 	 * This is a temporary hack for the time being.
+ 	 * In some cases, the ll_rw_blk layer is creating
+ 	 * bounce buffers for us - this implies that we don't
+ 	 * need to down here, but queue management becomes quite
+ 	 * difficult otherwise.  When the ll_rw_blk layer gets
+ 	 * cleaned up to handle bounce buffers better, then
+ 	 * this hack can be cleaned up.
+ 	 */
+ 	if( sector == -1 )
+ 	{
+ 		struct buffer_head * bh_new;
+ 		bh_new = (struct buffer_head *) bh->b_dev_id;
+ 		if( bh_new != NULL )
+ 		{
+ 			sector = bh_new->b_rsector;
+ 		}
+ 		if( sector == -1 )
+ 		{
+ 			panic("Unable to merge ambiguous block request");
+ 		}
+ 	}
+ #endif
  
  	/*
  	 * We come in here in one of two cases.   The first is that we
***************
*** 765,771 ****
  	if( scsi_dma_free_sectors > 30 ) {
  		for (this_count = 0, bh = SCpnt->request.bh;
  		     bh; bh = bh->b_reqnext) {
! 			if( scsi_dma_free_sectors < 30 || this_count == sectors )
  			{
  				break;
  			}
--- 789,796 ----
  	if( scsi_dma_free_sectors > 30 ) {
  		for (this_count = 0, bh = SCpnt->request.bh;
  		     bh; bh = bh->b_reqnext) {
! 			if( scsi_dma_free_sectors - this_count < 30 
! 			    || this_count == sectors )
  			{
  				break;
  			}
***************
*** 831,854 ****
   * We always force "_VALID" to 1.  Eventually clean this up
   * and get rid of the extra argument.
   */
- #if 0
- /* Old definitions */
- INITIO(scsi_init_io_, 0, 0, 0)
- INITIO(scsi_init_io_d, 0, 0, 1)
- INITIO(scsi_init_io_c, 0, 1, 0)
- INITIO(scsi_init_io_dc, 0, 1, 1)
- 
- /* Newer redundant definitions. */
- INITIO(scsi_init_io_, 1, 0, 0)
- INITIO(scsi_init_io_d, 1, 0, 1)
- INITIO(scsi_init_io_c, 1, 1, 0)
- INITIO(scsi_init_io_dc, 1, 1, 1)
- #endif
- 
  INITIO(scsi_init_io_v, 1, 0, 0)
  INITIO(scsi_init_io_vd, 1, 0, 1)
  INITIO(scsi_init_io_vc, 1, 1, 0)
  INITIO(scsi_init_io_vdc, 1, 1, 1)
  /*
   * Function:    initialize_merge_fn()
   *
--- 856,866 ----
   * We always force "_VALID" to 1.  Eventually clean this up
   * and get rid of the extra argument.
   */
  INITIO(scsi_init_io_v, 1, 0, 0)
  INITIO(scsi_init_io_vd, 1, 0, 1)
  INITIO(scsi_init_io_vc, 1, 1, 0)
  INITIO(scsi_init_io_vdc, 1, 1, 1)
+ 
  /*
   * Function:    initialize_merge_fn()
   *
***************
*** 881,901 ****
  	 * If this host has an unlimited tablesize, then don't bother with a
  	 * merge manager.  The whole point of the operation is to make sure
  	 * that requests don't grow too large, and this host isn't picky.
! 	 */
! 	if (SHpnt->sg_tablesize == SG_ALL) {
! 		if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
! 			SDpnt->scsi_init_io_fn = scsi_init_io_v;
! 		} else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
! 			SDpnt->scsi_init_io_fn = scsi_init_io_vd;
! 		} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
! 			SDpnt->scsi_init_io_fn = scsi_init_io_vc;
! 		} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
! 			SDpnt->scsi_init_io_fn = scsi_init_io_vdc;
! 		}
! 		return;
! 	}
! 	/*
! 	 * Now pick out the correct function.
  	 */
  	if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
  		q->merge_fn = scsi_merge_fn_;
--- 893,904 ----
  	 * If this host has an unlimited tablesize, then don't bother with a
  	 * merge manager.  The whole point of the operation is to make sure
  	 * that requests don't grow too large, and this host isn't picky.
! 	 *
! 	 * Note that ll_rw_blk.c is effectively maintaining a segment
! 	 * count which is only valid if clustering is used, and it obviously
! 	 * doesn't handle the DMA case.   In the end, it
! 	 * is simply easier to do it ourselves with our own functions
! 	 * rather than rely upon the default behavior of ll_rw_blk.
  	 */
  	if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
  		q->merge_fn = scsi_merge_fn_;
Index: linux/drivers/scsi/sd.c
diff -c linux/drivers/scsi/sd.c:1.1.1.3 linux/drivers/scsi/sd.c:1.4
*** linux/drivers/scsi/sd.c:1.1.1.3	Wed Dec 22 10:28:46 1999
--- linux/drivers/scsi/sd.c	Wed Dec 22 18:37:56 1999
***************
*** 202,207 ****
--- 202,212 ----
  	tag:"sd",
  	scsi_type:TYPE_DISK,
  	major:SCSI_DISK0_MAJOR,
+         /*
+          * Secondary range of majors that this driver handles.
+          */
+ 	min_major:SCSI_DISK1_MAJOR,
+ 	max_major:SCSI_DISK7_MAJOR,
  	blk:1,
  	detect:sd_detect,
  	init:sd_init,
***************
*** 229,235 ****
  	Scsi_Disk *dpnt;
  	char nbuff[6];
  
! 	devm = MINOR(SCpnt->request.rq_dev);
  	dev = DEVICE_NR(SCpnt->request.rq_dev);
  
  	block = SCpnt->request.sector;
--- 234,240 ----
  	Scsi_Disk *dpnt;
  	char nbuff[6];
  
! 	devm = SD_PARTITION(SCpnt->request.rq_dev);
  	dev = DEVICE_NR(SCpnt->request.rq_dev);
  
  	block = SCpnt->request.sector;
***************
*** 561,567 ****
  			default:
  				break;
  			}
! 			error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
  			error_sector &= ~(block_sectors - 1);
  			good_sectors = error_sector - SCpnt->request.sector;
  			if (good_sectors < 0 || good_sectors >= this_count)
--- 566,572 ----
  			default:
  				break;
  			}
! 			error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;
  			error_sector &= ~(block_sectors - 1);
  			good_sectors = error_sector - SCpnt->request.sector;
  			if (good_sectors < 0 || good_sectors >= this_count)
Index: linux/drivers/scsi/sg.c
diff -c linux/drivers/scsi/sg.c:1.1.1.4 linux/drivers/scsi/sg.c:1.3
*** linux/drivers/scsi/sg.c:1.1.1.4	Wed Dec 22 10:28:46 1999
--- linux/drivers/scsi/sg.c	Wed Dec 22 02:41:25 1999
***************
*** 101,110 ****
  static void sg_detach(Scsi_Device *);
  
  
! struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
!                                            SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
!                                            sg_detect, sg_init,
!                                            sg_finish, sg_attach, sg_detach};
  
  
  typedef struct sg_scatter_hold  /* holding area for scsi scatter gather info */
--- 101,117 ----
  static void sg_detach(Scsi_Device *);
  
  
! struct Scsi_Device_Template sg_template = 
! {
! 	tag:"sg", 
! 	scsi_type:0xff,
! 	major:SCSI_GENERIC_MAJOR, 
! 	detect:sg_detect, 
! 	init:sg_init,
! 	finish:sg_finish, 
! 	attach:sg_attach, 
! 	detach:sg_detach
! };
  
  
  typedef struct sg_scatter_hold  /* holding area for scsi scatter gather info */
Index: linux/drivers/scsi/st.c
diff -c linux/drivers/scsi/st.c:1.1.1.3 linux/drivers/scsi/st.c:1.3
*** linux/drivers/scsi/st.c:1.1.1.3	Wed Dec 22 10:28:48 1999
--- linux/drivers/scsi/st.c	Wed Dec 22 02:41:25 1999
***************
*** 147,156 ****
  static void st_detach(Scsi_Device *);
  
  struct Scsi_Device_Template st_template =
! {NULL, "tape", "st", NULL, TYPE_TAPE,
!  SCSI_TAPE_MAJOR, 0, 0, 0, 0,
!  st_detect, st_init,
!  NULL, st_attach, st_detach};
  
  static int st_compression(Scsi_Tape *, int);
  
--- 147,162 ----
  static void st_detach(Scsi_Device *);
  
  struct Scsi_Device_Template st_template =
! {
! 	name:"tape", 
! 	tag:"st", 
! 	scsi_type:TYPE_TAPE,
! 	major:SCSI_TAPE_MAJOR, 
! 	detect:st_detect, 
! 	init:st_init,
! 	attach:st_attach, 
! 	detach:st_detach
! };
  
  static int st_compression(Scsi_Tape *, int);
  
