[4652] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

[PATCH] Support for >= 16 SCSI disks (looking for TESTERS)

daemon@ATHENA.MIT.EDU (Jakub Jelinek)
Fri Sep 4 10:59:56 1998

From: Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
To: linux-kernel@vger.rutgers.edu, linux-scsi@vger.rutgers.edu
Date: 	Fri, 4 Sep 1998 16:34:03 +0200 (MET DST)

Hi!

This patch adds support for >= 16 SCSI disks (up to 128 SCSI disks in one
box). As Linus did not like the approach of enlargering kdev_t, this patch
adds 7 new SCSI majors (already registered in devices.tex).
Please test it if you can, not only in >= 16 sd configurations, but in
configurations with fewer disks as well, if nothing broke.
I've been using it for nearly a month on a single SCSI disk machine and it
now works on my 39 SCSI disk server without any problems.

(The patch is against current vger CVS, but I think it should apply cleanly
to 119 and other kernels as well - if you'll get any rejects, tell me and
I'll make another patch relative to kernel.org tree).

--- linux/drivers/block/acsi.c.jj	Fri Sep  4 10:50:02 1998
+++ linux/drivers/block/acsi.c	Fri Sep  4 13:35:47 1998
@@ -3,7 +3,7 @@
  *
  * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  *
- * Some parts are based on hd.c by Linus Thorvalds
+ * Some parts are based on hd.c by Linus Torvalds
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive for
--- linux/drivers/block/genhd.c.jj	Fri Sep  4 10:50:13 1998
+++ linux/drivers/block/genhd.c	Fri Sep  4 13:35:47 1998
@@ -69,7 +69,7 @@ char *disk_name (struct gendisk *hd, int
 {
 	unsigned int part;
 	const char *maj = hd->major_name;
-	char unit = (minor >> hd->minor_shift) + 'a';
+	int unit = (minor >> hd->minor_shift) + 'a';
 
 	/*
 	 * IDE devices use multiple major numbers, but the drives
@@ -85,8 +85,19 @@ char *disk_name (struct gendisk *hd, int
 			unit += 2;
 		case IDE0_MAJOR:
 			maj = "hd";
+			break;
 	}
 	part = minor & ((1 << hd->minor_shift) - 1);
+	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+		if (unit > 'z') {
+			unit -= 'z' + 1;
+			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
+			if (part)
+				sprintf(buf + 4, "%d", part);
+			return buf;
+		}
+	}
 	if (part)
 		sprintf(buf, "%s%c%d", maj, unit, part);
 	else
--- linux/drivers/block/ll_rw_blk.c.jj	Fri Sep  4 10:50:41 1998
+++ linux/drivers/block/ll_rw_blk.c	Fri Sep  4 13:35:47 1998
@@ -93,8 +93,8 @@ int * blksize_size[MAX_BLKDEV] = { NULL,
  *		then 512 bytes is assumed.
  * else
  *		sector_size is hardsect_size[MAJOR][MINOR]
- * This is currently set by some scsi device and read by the msdos fs driver
- * This might be a some uses later.
+ * This is currently set by some scsi devices and read by the msdos fs driver.
+ * Other uses may appear later.
  */
 int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
 
@@ -297,8 +297,8 @@ void add_request(struct blk_dev_struct *
 	int queue_new_request = 0;
 
 	switch (MAJOR(req->rq_dev)) {
-		case SCSI_DISK_MAJOR:
-			disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
+		case SCSI_DISK0_MAJOR:
+			disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
 			if (disk_index < 4)
 				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 			break;
@@ -479,7 +479,14 @@ void make_request(int major,int rw, stru
 			break;
 		/* fall through */
 
-	     case SCSI_DISK_MAJOR:
+	     case SCSI_DISK0_MAJOR:
+	     case SCSI_DISK1_MAJOR:
+	     case SCSI_DISK2_MAJOR:
+	     case SCSI_DISK3_MAJOR:
+	     case SCSI_DISK4_MAJOR:
+	     case SCSI_DISK5_MAJOR:
+	     case SCSI_DISK6_MAJOR:
+	     case SCSI_DISK7_MAJOR:
 	     case SCSI_CDROM_MAJOR:
 
 		do {
--- linux/drivers/char/sysrq.c.jj	Fri Sep  4 10:56:12 1998
+++ linux/drivers/char/sysrq.c	Fri Sep  4 13:35:47 1998
@@ -168,7 +168,14 @@ static int is_local_disk(kdev_t dev)	   
 	case IDE1_MAJOR:
 	case IDE2_MAJOR:
 	case IDE3_MAJOR:
-	case SCSI_DISK_MAJOR:
+	case SCSI_DISK0_MAJOR:
+	case SCSI_DISK1_MAJOR:
+	case SCSI_DISK2_MAJOR:
+	case SCSI_DISK3_MAJOR:
+	case SCSI_DISK4_MAJOR:
+	case SCSI_DISK5_MAJOR:
+	case SCSI_DISK6_MAJOR:
+	case SCSI_DISK7_MAJOR:
 		return 1;
 	default:
 		return 0;
--- linux/drivers/scsi/scsi.c.jj	Fri Sep  4 11:19:52 1998
+++ linux/drivers/scsi/scsi.c	Fri Sep  4 13:35:47 1998
@@ -1739,8 +1739,7 @@ scsi_finish_command(Scsi_Cmnd * SCpnt)
         host_active = NULL;
         
         /* For block devices "wake_up" is done in end_scsi_request */
-        if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
-            MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+        if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
             struct Scsi_Host * next;
             
             for (next = host->block; next != host; next = next->block)
--- linux/drivers/scsi/scsi_obsolete.c.jj	Fri Sep  4 11:20:00 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Fri Sep  4 13:35:47 1998
@@ -655,8 +655,7 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
 	    host_active = NULL;
 
 	    /* For block devices "wake_up" is done in end_scsi_request */
-	    if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
-		MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+	    if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
 		struct Scsi_Host * next;
 
 		for (next = host->block; next != host; next = next->block)
--- linux/drivers/scsi/sd.c.jj	Fri Sep  4 11:20:18 1998
+++ linux/drivers/scsi/sd.c	Fri Sep  4 13:41:05 1998
@@ -14,8 +14,11 @@
  *
  *       Modified by Eric Youngdale eric@aib.com to support loadable
  *       low-level scsi drivers.
+ *
+ *       Modified by Jirka Hanika geo@ff.cuni.cz to support more
+ *       scsi disks using eight major numbers.
  */
-
+ 
 #include <linux/module.h>
 #ifdef MODULE
 /*
@@ -41,7 +44,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#define MAJOR_NR SCSI_DISK_MAJOR
+#define MAJOR_NR SCSI_DISK0_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
@@ -54,6 +57,15 @@
 /*
  *  static const char RCSid[] = "$Header:";
  */
+ 
+#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+ 
+#define SCSI_DISKS_PER_MAJOR	16
+#define SD_MAJOR_NUMBER(i)	SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i)	((i) & 255)
+#define MKDEV_SD_PARTITION(i)	MKDEV(SD_MAJOR_NUMBER(i), (i) & 255)
+#define MKDEV_SD(index)		MKDEV_SD_PARTITION((index) << 4)
+#define N_USED_SD_MAJORS	((sd_template.dev_max + SCSI_DISKS_PER_MAJOR - 1) / SCSI_DISKS_PER_MAJOR)
 
 #define MAX_RETRIES 5
 
@@ -91,12 +103,9 @@ static void sd_detach(Scsi_Device *);
 
 static void sd_devname(unsigned int disknum, char * buffer)
 {
-    if( disknum <= 26 )
-    {
+    if( disknum < 26 )
         sprintf(buffer, "sd%c", 'a' + disknum);
-    }
-    else
-    {
+    else {
         unsigned int min1;
         unsigned int min2;
         /*
@@ -105,13 +114,13 @@ static void sd_devname(unsigned int disk
          */
         min1 = disknum / 26;
         min2 = disknum % 26;
-        sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2);
+        sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
     }
 }
 
 struct Scsi_Device_Template sd_template =
 { NULL, "disk", "sd", NULL, TYPE_DISK,
-      SCSI_DISK_MAJOR, 0, 0, 0, 1,
+      SCSI_DISK0_MAJOR, 0, 0, 0, 1,
       sd_detect, sd_init,
       sd_finish, sd_attach, sd_detach
 };
@@ -175,7 +184,7 @@ static int sd_open(struct inode * inode,
      * See if we are requesting a non-existent partition.  Do this
      * after checking for disk change.
      */
-    if(sd_sizes[MINOR(inode->i_rdev)] == 0)
+    if(sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)
 	return -ENXIO;
 
     if(rscsi_disks[target].device->removable)
@@ -230,8 +239,13 @@ static struct file_operations sd_fops = 
     fop_revalidate_scsidisk      /* revalidate */
 };
 
+/*
+ *	If we need more than one SCSI disk major (i.e. more than
+ *	16 SCSI disks), we'll have to kmalloc() more gendisks later.
+ */
+
 static struct gendisk sd_gendisk = {
-    MAJOR_NR,                    /* Major number */
+    SCSI_DISK0_MAJOR,            /* Major number */
     "sd",                        /* Major name */
     4,                           /* Bits to shift to get real from partition */
     1 << 4,                      /* Number of partitions per real */
@@ -242,7 +256,12 @@ static struct gendisk sd_gendisk = {
     0,                           /* number */
     NULL,                        /* internal */
     NULL                         /* next */
-};
+}; 
+
+static struct gendisk *sd_gendisks = &sd_gendisk;
+
+#define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+#define LAST_SD_GENDISK  sd_gendisks[N_USED_SD_MAJORS - 1]
 
 static void sd_geninit (struct gendisk *ignored)
 {
@@ -251,10 +270,6 @@ static void sd_geninit (struct gendisk *
     for (i = 0; i < sd_template.dev_max; ++i)
 	if(rscsi_disks[i].device)
 	    sd[i << 4].nr_sects = rscsi_disks[i].capacity;
-#if 0
-    /* No longer needed - we keep track of this as we attach/detach */
-    sd_gendisk.nr_real = sd_template.dev_max;
-#endif
 }
 
 /*
@@ -271,7 +286,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
     int good_sectors = (result == 0 ? this_count : 0);
     int block_sectors = 1;
 
-    sd_devname(MINOR(SCpnt->request.rq_dev) >> 4, nbuff);
+    sd_devname(DEVICE_NR(SCpnt->request.rq_dev), nbuff);
 
     SCSI_LOG_HLCOMPLETE(1,printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff,
 	   SCpnt->host->host_no, 
@@ -309,7 +324,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
 	  }
 	else if (sector_size == 256)
 	  error_sector >>= 1;
-	error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+	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)
@@ -524,7 +539,7 @@ static void do_sd_request (void)
 	}
 
 	INIT_SCSI_REQUEST;
-        SDev = rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device;
+        SDev = rscsi_disks[CURRENT_DEV].device;
 
         /*
          * If the host for this device is in error recovery mode, don't
@@ -578,7 +593,7 @@ static void do_sd_request (void)
 
 	if (flag++ == 0)
 	    SCpnt = scsi_allocate_device(&CURRENT,
-			   rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0);
+			   rscsi_disks[CURRENT_DEV].device, 0);
 	else SCpnt = NULL;
 
 	/*
@@ -643,7 +658,7 @@ static void requeue_sd_request (Scsi_Cmn
 	return;
     }
 
-    devm =  MINOR(SCpnt->request.rq_dev);
+    devm =  SD_PARTITION(SCpnt->request.rq_dev);
     dev = DEVICE_NR(SCpnt->request.rq_dev);
 
     block = SCpnt->request.sector;
@@ -1329,7 +1344,7 @@ static int sd_init_onedisk(int i)
 		printk ("scsi : deleting disk entry.\n");
 		rscsi_disks[i].device = NULL;
 		sd_template.nr_dev--;
-		sd_gendisk.nr_real--;
+		SD_GENDISK(i).nr_real--;
 
                 /* Wake up a process waiting for device */
                 wake_up(&SCpnt->device->device_wait);
@@ -1463,67 +1478,99 @@ static int sd_init()
 
     if (sd_template.dev_noticed == 0) return 0;
 
+    if (!rscsi_disks)
+        sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
+
+    /* 128 disks is our current limit (8 majors, 16 disks per major) */
+    if(sd_template.dev_max > 128)
+   	sd_template.dev_max = 128;
+
     if(!sd_registered) {
-	  if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) {
-	      printk("Unable to get major %d for SCSI disk\n",MAJOR_NR);
-	      return 1;
-	  }
-	  sd_registered++;
-      }
+	for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+	    if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) {
+		printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
+		return 1;
+	    }
+	}
+	sd_registered++;
+    }
 
     /* We do not support attaching loadable devices yet. */
     if(rscsi_disks) return 0;
 
-    sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
-
     rscsi_disks = (Scsi_Disk *)
 	scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
     memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
-
-    sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-					sizeof(int), GFP_ATOMIC);
+    
+  /* for every (necessary) major: */
+    sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
     memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
 
-    sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-					     sizeof(int), GFP_ATOMIC);
+    sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+    sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
 
-    sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-					    sizeof(int), GFP_ATOMIC);
-
-     for(i=0;i<(sd_template.dev_max << 4);i++)
-       {
-         sd_blocksizes[i] = 1024;
-         sd_hardsizes[i] = 512;
-       }
+    for(i=0; i < sd_template.dev_max << 4; i++) {
+	sd_blocksizes[i] = 1024;
+	sd_hardsizes[i] = 512;
+    }
  
-    blksize_size[MAJOR_NR] = sd_blocksizes;
-    hardsect_size[MAJOR_NR] = sd_hardsizes;
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+	blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+	hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+    }
     sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
 					       sizeof(struct hd_struct),
 					       GFP_ATOMIC);
 
-
-    sd_gendisk.max_nr = sd_template.dev_max;
-    sd_gendisk.part = sd;
-    sd_gendisk.sizes = sd_sizes;
-    sd_gendisk.real_devices = (void *) rscsi_disks;
+    if (N_USED_SD_MAJORS > 1)
+    	sd_gendisks = (struct gendisk *)
+    	    kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+	sd_gendisks[i].major = SD_MAJOR(i);
+	sd_gendisks[i].major_name = "sd";
+	sd_gendisks[i].minor_shift = 4;
+	sd_gendisks[i].max_p = 1 << 4;
+	sd_gendisks[i].max_nr = SCSI_DISKS_PER_MAJOR;
+	sd_gendisks[i].init = sd_geninit;
+	sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4);
+	sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4);
+	sd_gendisks[i].nr_real = 0;
+	sd_gendisks[i].next = sd_gendisks + i + 1;
+	sd_gendisks[i].real_devices =
+		 (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
+    }
+    LAST_SD_GENDISK.max_nr =
+    	sd_template.dev_max % SCSI_DISKS_PER_MAJOR;
+    LAST_SD_GENDISK.next = NULL;
     return 0;
 }
 
+/*
+ * sd_get_queue() returns the queue which corresponds to a given device.
+ */
+static struct request **sd_get_queue (kdev_t dev)
+{
+	return &blk_dev[MAJOR_NR].current_request;
+}
+
 static void sd_finish()
 {
     struct gendisk *gendisk;
     int i;
 
-    blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+    for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+        /* FIXME: After 2.2 we should implement multiple sd queues */
+        blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST;
+        if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue;
+    }
 
     for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next)
-      if (gendisk == &sd_gendisk)
+      if (gendisk == sd_gendisks)
 	break;
     if (gendisk == NULL)
       {
-	sd_gendisk.next = gendisk_head;
-	gendisk_head = &sd_gendisk;
+	LAST_SD_GENDISK.next = gendisk_head;
+	gendisk_head = sd_gendisks;
       }
 
     for (i = 0; i < sd_template.dev_max; ++i)
@@ -1534,7 +1581,7 @@ static void sd_finish()
 		&& !rscsi_disks[i].has_part_table) {
 		sd_sizes[i << 4] = rscsi_disks[i].capacity;
 		/* revalidate does sd_init_onedisk via MAYBE_REINIT*/
-		revalidate_scsidisk(MKDEV(MAJOR_NR, i << 4), 0);
+		revalidate_scsidisk(MKDEV_SD(i), 0);
 	    }
 	    else
 	    	i=sd_init_onedisk(i);
@@ -1542,13 +1589,17 @@ static void sd_finish()
 	}
 
     /* If our host adapter is capable of scatter-gather, then we increase
-     * the read-ahead to 16 blocks (32 sectors).  If not, we use
-     * a two block (4 sector) read ahead.
+     * the read-ahead to 60 blocks (120 sectors).  If not, we use
+     * a two block (4 sector) read ahead. We can only respect this with the
+     * granularity of every 16 disks (one device major).
      */
-    if(rscsi_disks[0].device && rscsi_disks[0].device->host->sg_tablesize)
-	read_ahead[MAJOR_NR] = 120;  /* 120 sector read-ahead */
-    else
-	read_ahead[MAJOR_NR] = 4;  /* 4 sector read-ahead */
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+        read_ahead[SD_MAJOR(i)] =
+            (rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device
+          && rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device->host->sg_tablesize)
+            ? 120  /* 120 sector read-ahead */
+            : 4;   /* 4 sector read-ahead */
+    }
 
     return;
 }
@@ -1586,7 +1637,7 @@ static int sd_attach(Scsi_Device * SDp){
     rscsi_disks[i].device = SDp;
     rscsi_disks[i].has_part_table = 0;
     sd_template.nr_dev++;
-    sd_gendisk.nr_real++;
+    SD_GENDISK(i).nr_real++;
     return 0;
 }
 
@@ -1594,7 +1645,6 @@ static int sd_attach(Scsi_Device * SDp){
 #define USAGE rscsi_disks[target].device->access_count
 #define CAPACITY rscsi_disks[target].capacity
 #define MAYBE_REINIT  sd_init_onedisk(target)
-#define GENDISK_STRUCT sd_gendisk
 
 /* This routine is called to flush all partitions and partition tables
  * for a changed scsi disk, and then re-read the new partition table.
@@ -1603,15 +1653,13 @@ static int sd_attach(Scsi_Device * SDp){
  * usage == 1 (we need an open channel to use an ioctl :-), so this
  * is our limit.
  */
-int revalidate_scsidisk(kdev_t dev, int maxusage){
+int revalidate_scsidisk(kdev_t dev, int maxusage) {
     int target;
-    struct gendisk * gdev;
     int max_p;
     int start;
     int i;
 
     target =  DEVICE_NR(dev);
-    gdev = &GENDISK_STRUCT;
 
     if (DEVICE_BUSY || USAGE > maxusage) {
 	printk("Device busy for revalidation (usage=%d)\n", USAGE);
@@ -1619,37 +1667,38 @@ int revalidate_scsidisk(kdev_t dev, int 
     }
     DEVICE_BUSY = 1;
 
-    max_p = gdev->max_p;
-    start = target << gdev->minor_shift;
+    max_p = sd_gendisks->max_p;
+    start = target << sd_gendisks->minor_shift;
 
     for (i=max_p - 1; i >=0 ; i--) {
-	int minor = start+i;
-	kdev_t devi = MKDEV(MAJOR_NR, minor);
+	int index = start+i;
+	kdev_t devi = MKDEV_SD_PARTITION(index);
         struct super_block *sb = get_super(devi);
 	sync_dev(devi);
 	if (sb) invalidate_inodes(sb);
 	invalidate_buffers(devi);
-	gdev->part[minor].start_sect = 0;
-	gdev->part[minor].nr_sects = 0;
+	sd_gendisks->part[index].start_sect = 0;
+	sd_gendisks->part[index].nr_sects = 0;
         /*
          * Reset the blocksize for everything so that we can read
          * the partition table.  Technically we will determine the
          * correct block size when we revalidate, but we do this just
          * to make sure that everything remains consistent.
          */
-        blksize_size[MAJOR_NR][minor] = 1024;
+        sd_blocksizes[index] = 1024;
         if( rscsi_disks[target].sector_size == 2048 )
-          blksize_size[MAJOR_NR][minor] = 2048;
+          sd_blocksizes[index] = 2048;
         else
-          blksize_size[MAJOR_NR][minor] = 1024;
+          sd_blocksizes[index] = 1024;
     }
 
 #ifdef MAYBE_REINIT
     MAYBE_REINIT;
 #endif
 
-    gdev->part[start].nr_sects = CAPACITY;
-    resetup_one_dev(gdev, target);
+    sd_gendisks->part[start].nr_sects = CAPACITY;
+    resetup_one_dev(&SD_GENDISK(target),
+		    target % SCSI_DISKS_PER_MAJOR);
 
     DEVICE_BUSY = 0;
     return 0;
@@ -1676,15 +1725,15 @@ static void sd_detach(Scsi_Device * SDp)
 	    start = i << sd_gendisk.minor_shift;
 
 	    for (i=max_p - 1; i >=0 ; i--) {
-		int minor = start+i;
-		kdev_t devi = MKDEV(MAJOR_NR, minor);
+		int index = start+i;
+		kdev_t devi = MKDEV_SD_PARTITION(index);
                 struct super_block *sb = get_super(devi);
 		sync_dev(devi);
 		if (sb) invalidate_inodes(sb);
 		invalidate_buffers(devi);
-		sd_gendisk.part[minor].start_sect = 0;
-		sd_gendisk.part[minor].nr_sects = 0;
-		sd_sizes[minor] = 0;
+		sd_gendisks->part[index].start_sect = 0;
+		sd_gendisks->part[index].nr_sects = 0;
+		sd_sizes[index] = 0;
 	    }
 
 	    dpnt->has_part_table = 0;
@@ -1693,7 +1742,7 @@ static void sd_detach(Scsi_Device * SDp)
 	    SDp->attached--;
 	    sd_template.dev_noticed--;
 	    sd_template.nr_dev--;
-	    sd_gendisk.nr_real--;
+	    SD_GENDISK(start).nr_real--;
 	    return;
 	}
     return;
@@ -1710,48 +1759,45 @@ void cleanup_module( void)
 {
     struct gendisk * prev_sdgd;
     struct gendisk * sdgd;
+    
+    int removed = 0;
 
     scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
     unregister_blkdev(SCSI_DISK_MAJOR, "sd");
     sd_registered--;
     if( rscsi_disks != NULL )
     {
-	scsi_init_free((char *) rscsi_disks,
-		       (sd_template.dev_noticed + SD_EXTRA_DEVS)
-		       * sizeof(Scsi_Disk));
-
+	scsi_init_free((char *) rscsi_disks, 
+			sd_template.dev_max * sizeof(Scsi_Disk));
 	scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int));
 	scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int));
 	scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int));
 	scsi_init_free((char *) sd,
 		       (sd_template.dev_max << 4) * sizeof(struct hd_struct));
 	/*
-	 * Now remove sd_gendisk from the linked list
+	 * Now remove sd_gendisks from the linked list
 	 */
-	sdgd = gendisk_head;
-	prev_sdgd = NULL;
-	while(sdgd != &sd_gendisk)
-	{
-	    prev_sdgd = sdgd;
-	    sdgd = sdgd->next;
-	}
 
-	if(sdgd != &sd_gendisk)
-	    printk("sd_gendisk not in disk chain.\n");
-	else {
-	    if(prev_sdgd != NULL)
-		prev_sdgd->next = sdgd->next;
-	    else
-		gendisk_head = sdgd->next;
-	}
+	for (sdgd = gendisk_head; sdgd; sdgd = sdgd->next)
+	{
+	    if (sdgd->next >= sd_gendisks && sdgd->next <= LAST_SD_GENDISK)
+	    	    removed++, sdgd->next = sdgd->next->next;
+	    else sdgd = sdgd->next;
+	}
+	if (removed != N_USED_SCSI_DISKS)
+	    printk("%s %d sd_gendisks in disk chain",
+	    	removed > N_USED_SCSI_DISKS ? "total" : "just", removed);
+	
     }
 
-    blksize_size[MAJOR_NR] = NULL;
-    blk_dev[MAJOR_NR].request_fn = NULL;
-    blk_size[MAJOR_NR] = NULL;
-    hardsect_size[MAJOR_NR] = NULL;
-    read_ahead[MAJOR_NR] = 0;
+    for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+        blk_dev[SD_MAJOR(i)].request_fn = NULL;
+        blk_size[SD_MAJOR(i)] = NULL;
+        hardsect_size[SD_MAJOR(i)] = NULL;
+        read_ahead[SD_MAJOR(i)] = 0;
+    }
     sd_template.dev_max = 0;
+    if (sd_gendisks != &sd_gendisk) kfree(sd_gendisks);
 }
 #endif /* MODULE */
 
--- linux/drivers/scsi/scsi.h.jj	Fri Sep  4 12:55:55 1998
+++ linux/drivers/scsi/scsi.h	Fri Sep  4 13:35:47 1998
@@ -684,16 +684,22 @@ static Scsi_Cmnd * end_scsi_request(Scsi
  * that an interrupt may start another request, so we run this with interrupts
  * turned off 
  */
-#define INIT_SCSI_REQUEST       \
-    if (!CURRENT) {             \
-	CLEAR_INTR;             \
-	return;                 \
-    }                           \
-    if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)           \
-	panic(DEVICE_NAME ": request list destroyed");\
-    if (CURRENT->bh) {                                \
-	if (!buffer_locked(CURRENT->bh))              \
-	    panic(DEVICE_NAME ": block not locked");  \
+#if MAJOR_NR == SCSI_DISK0_MAJOR
+#define CHECK_INITREQ_SD_MAJOR(major) SCSI_DISK_MAJOR(major)
+#else
+#define CHECK_INITREQ_SD_MAJOR(major) ((major) == MAJOR_NR)
+#endif
+
+#define INIT_SCSI_REQUEST       			\
+    if (!CURRENT) {             			\
+	CLEAR_INTR;             			\
+	return;                 			\
+    }                           			\
+    if (!CHECK_INITREQ_SD_MAJOR(MAJOR(CURRENT->rq_dev)))\
+	panic(DEVICE_NAME ": request list destroyed");	\
+    if (CURRENT->bh) {                                	\
+	if (!buffer_locked(CURRENT->bh))              	\
+	    panic(DEVICE_NAME ": block not locked");  	\
     }
 #endif
 
--- linux/drivers/scsi/scsi_debug.c.jj	Fri Sep  4 11:19:53 1998
+++ linux/drivers/scsi/scsi_debug.c	Fri Sep  4 13:35:47 1998
@@ -43,8 +43,8 @@ struct proc_dir_entry proc_scsi_scsi_deb
 
 /* A few options that we want selected */
 
-#define NR_HOSTS_PRESENT 1
-#define NR_FAKE_DISKS   3
+#define NR_HOSTS_PRESENT 20
+#define NR_FAKE_DISKS   6
 #define N_HEAD          32
 #define N_SECTOR        64
 #define DISK_READONLY(TGT)      (1)
@@ -56,6 +56,8 @@ struct proc_dir_entry proc_scsi_scsi_deb
 
 /* Skip some consistency checking.  Good for benchmarking */
 #define SPEEDY
+/* Read return zeros. Undefine for benchmarking */
+#define CLEAR
 
 /* Number of real scsi disks that will be detected ahead of time */
 static int NR_REAL=-1;
@@ -300,11 +302,8 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
     {
 	int delay = SCSI_SETUP_LATENCY;
-	double usec;
 	
-	usec = 0.0;
-	usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
-	delay += usec;
+	delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
 	if(delay) usleep(delay);
     };
 #endif
@@ -324,29 +323,31 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 	do{
 	    VERIFY1_DEBUG(READ);
 	    /* For the speedy test, we do not even want to fill the buffer with anything */
-#ifndef SPEEDY
+#ifdef CLEAR
 	    memset(buff, 0, bufflen);
 #endif
 	    /* If this is block 0, then we want to read the partition table for this
 	     * device.  Let's make one up */
-	    if(block == 0 && target == 0) {
+	    if(block == 0) {
+	    	int i;
                 memset(buff, 0, bufflen);
 		*((unsigned short *) (buff+510)) = 0xAA55;
 		p = (struct partition* ) (buff + 0x1be);
-		npart = 0;
-		while(starts[npart+1]){
-		    p->start_sect = starts[npart];
-		    p->nr_sects = starts[npart+1] - starts [npart];
+		i = 0;
+		while(starts[i+1]){
+		    p->start_sect = starts[i];
+		    p->nr_sects = starts[i+1] - starts [i];
 		    p->sys_ind = 0x81;  /* Linux partition */
-                    p->head       = (npart == 0 ? 1 : 0);
+                    p->head       = (i == 0 ? 1 : 0);
                     p->sector     = 1;
-                    p->cyl        = starts[npart] / N_HEAD / N_SECTOR;
+                    p->cyl        = starts[i] / N_HEAD / N_SECTOR;
                     p->end_head   = N_HEAD - 1;
                     p->end_sector = N_SECTOR;
-                    p->end_cyl    = starts[npart + 1] / N_HEAD / N_SECTOR;
+                    p->end_cyl    = starts[i + 1] / N_HEAD / N_SECTOR;
 		    p++;
-		    npart++;
+		    i++;
 		};
+		if (!npart) npart = i;
 		scsi_debug_errsts = 0;
 		break;
 	    };
@@ -377,7 +378,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 	    } /* End phony disk change code */
 #endif
 	    
-#ifndef SPEEDY
+#ifdef CLEAR
 	    memcpy(buff, &target, sizeof(target));
 	    memcpy(buff+sizeof(target), cmd, 24);
 	    memcpy(buff+60, &block, sizeof(block));
@@ -385,7 +386,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 #endif
 	    nbytes -= bufflen;
 	    if(SCpnt->use_sg){
-#ifndef SPEEDY
+#ifdef CLEAR
 		memcpy(buff+128, bh, sizeof(struct buffer_head));
 #endif
 		block += bufflen >> 9;
--- linux/drivers/scsi/fdomain.c.jj	Fri Sep  4 11:18:00 1998
+++ linux/drivers/scsi/fdomain.c	Fri Sep  4 13:35:47 1998
@@ -107,6 +107,7 @@
  2.0.12      5.44         8 Aug 1996  Use ID 7 for all PCI cards
  2.1.1       5.45         2 Oct 1996  Update ROM accesses for 2.1.x
  2.1.97      5.46	 23 Apr 1998  Rewritten PCI detection routines [mj]
+ 2.1.11x     5.47	  9 Aug 1998  Touched for 8 SCSI disk majors support
 
  
 
@@ -1891,7 +1892,11 @@ int fdomain_16x0_biosparam( Scsi_Disk *d
       0x0a bytes long.  Heads are one less than we need to report.
     */
 
-   drive = MINOR(dev) / 16;
+   if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+      printk("fdomain_16x0_biosparam: too many disks");
+      return 0;
+   }
+   drive = MINOR(dev) >> 4;
 
    if (bios_major == 2) {
       switch (Quantum) {
--- linux/drivers/scsi/sd.h.jj	Fri Sep  4 12:55:55 1998
+++ linux/drivers/scsi/sd.h	Fri Sep  4 13:35:47 1998
@@ -42,6 +42,11 @@ extern Scsi_Disk * rscsi_disks;
 
 extern int revalidate_scsidisk(kdev_t dev, int maxusage);
 
+#define N_SD_MAJORS	8
+
+#define SD_MAJOR_MASK	(N_SD_MAJORS - 1)
+#define SD_PARTITION(i)		(((MAJOR(i) & SD_MAJOR_MASK) << 8) | (MINOR(i) & 255))
+
 #endif
 
 /*
--- linux/drivers/scsi/sd_ioctl.c.jj	Fri Sep  4 11:20:18 1998
+++ linux/drivers/scsi/sd_ioctl.c	Fri Sep  4 13:35:47 1998
@@ -13,6 +13,7 @@
 
 #include <asm/uaccess.h>
 
+#define MAJOR_NR	SCSI_DISK0_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
 #include <scsi/scsi_ioctl.h>
@@ -29,7 +30,7 @@ int sd_ioctl(struct inode * inode, struc
     int diskinfo[4];
     struct hd_geometry *loc = (struct hd_geometry *) arg;
     
-    SDev = rscsi_disks[MINOR(dev) >> 4].device;
+    SDev = rscsi_disks[DEVICE_NR(dev)].device;
     /*
      * If we are in the middle of error recovery, don't let anyone
      * else try and use this device.  Also, if error recovery fails, it
@@ -47,34 +48,34 @@ int sd_ioctl(struct inode * inode, struc
 	error = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
 	if (error)
 	    return error;
-	host = rscsi_disks[MINOR(dev) >> 4].device->host;
+	host = rscsi_disks[DEVICE_NR(dev)].device->host;
 
 /* default to most commonly used values */
 
         diskinfo[0] = 0x40;
         diskinfo[1] = 0x20;
-        diskinfo[2] = rscsi_disks[MINOR(dev) >> 4].capacity >> 11;
+        diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
 
 /* override with calculated, extended default, or driver values */
 
 	if(host->hostt->bios_param != NULL)
-	    host->hostt->bios_param(&rscsi_disks[MINOR(dev) >> 4],
+	    host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
 				    dev,
 				    &diskinfo[0]);
-        else scsicam_bios_param(&rscsi_disks[MINOR(dev) >> 4],
+        else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
 				dev, &diskinfo[0]);
 
 	put_user(diskinfo[0], &loc->heads);
 	put_user(diskinfo[1], &loc->sectors);
 	put_user(diskinfo[2], &loc->cylinders);
-	put_user(sd[MINOR(inode->i_rdev)].start_sect, &loc->start);
+	put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start);
 	return 0;
     case BLKGETSIZE:   /* Return device size */
 	if (!arg)  return -EINVAL;
 	error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
 	if (error)
 	    return error;
-	put_user(sd[MINOR(inode->i_rdev)].nr_sects,
+	put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects,
 		 (long *) arg);
 	return 0;
 
@@ -110,7 +111,7 @@ int sd_ioctl(struct inode * inode, struc
     RO_IOCTLS(dev, arg);
 
     default:
-	return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg);
+	return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
     }
 }
 
--- linux/include/linux/blk.h.jj	Fri Sep  4 12:43:59 1998
+++ linux/include/linux/blk.h	Fri Sep  4 13:35:47 1998
@@ -147,13 +147,13 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
-#elif (MAJOR_NR == SCSI_DISK_MAJOR)
+#elif (SCSI_DISK_MAJOR(MAJOR_NR))
 
 #define DEVICE_NAME "scsidisk"
 #define DEVICE_INTR do_sd  
 #define TIMEOUT_VALUE (2*HZ)
 #define DEVICE_REQUEST do_sd_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
--- linux/include/linux/major.h.jj	Fri Sep  4 11:59:02 1998
+++ linux/include/linux/major.h	Fri Sep  4 13:40:22 1998
@@ -28,7 +28,7 @@
 #define LP_MAJOR	6
 #define VCS_MAJOR	7
 #define LOOP_MAJOR	7
-#define SCSI_DISK_MAJOR	8
+#define SCSI_DISK0_MAJOR 8
 #define SCSI_TAPE_MAJOR	9
 #define MD_MAJOR        9
 #define MISC_MAJOR	10
@@ -81,6 +81,14 @@
 #define IDE4_MAJOR	56
 #define IDE5_MAJOR	57
 
+#define SCSI_DISK1_MAJOR	65
+#define SCSI_DISK2_MAJOR	66
+#define SCSI_DISK3_MAJOR	67
+#define SCSI_DISK4_MAJOR	68
+#define SCSI_DISK5_MAJOR	69
+#define SCSI_DISK6_MAJOR	70
+#define SCSI_DISK7_MAJOR	71
+
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
 
@@ -92,8 +100,11 @@
  * Tests for SCSI devices.
  */
 
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+  
 #define SCSI_BLK_MAJOR(M) \
-  ((M) == SCSI_DISK_MAJOR	\
+  (SCSI_DISK_MAJOR(M)	\
    || (M) == SCSI_CDROM_MAJOR)
 
 static __inline__ int scsi_blk_major(int m) {


Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
Ultralinux - first 64bit OS to take full power of the UltraSparc
Linux version 2.1.119 on a sparc64 machine (498.80 BogoMips).
___________________________________________________________________

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post