[Patch2.3.40] new configuration scheme for SCSI boot options

From: Haese Gerald (Gerald.Haese@icn.siemens.de)
Date: Tue Jan 25 2000 - 05:18:40 EST


Hi!

The current scsi mid level driver (scsi.c) supports only the following boot
time options:
 "scsi_logging=<value>"
 "scsi_max_luns=<value>".

But i found not way to enable "reverse ordereing" for one or several host
adapters at boot time. In some cases it could be necessary to detect the
devices with "wide IDs" first but in the right order like "8 , ..., 15, 0,
..., 7" (swap_lohi). For example my system disks are "wide" devices with ID
8 and 9. But sometimes I need access to external "narrow" disks and in this
case the name of the detected devices is changed because Linux recorgneizes
the external disks first. The use of "devfs" would be a solution but it's
not included in the standard kernel yet :-(

So I implemented a new init-function for the scsi mid level driver with new
options and adapted the old ones. The append line option in lilo.conf looks
like:

"scsi=<option1>:<value>,<option2>:<value>,..."

Following options are possible at the moment:

  logging:<level> (the same as "scsi_logging=...")

  max_luns:<value> (the same as "scsi_max_lun=...")
  reverse_ordering:<bitmask>
  swap_lohi_order :<bitmask>

"bitmask" means that each bit stands for one host in the system, bit0
->host0, bit1->host1, ...
The option is valid for all hosts if no value is given.

For backward compatibility I left the old init options in the driver.

What's your opinion?

Gerald

PS: a gziped version is attached at the end

--- linux/drivers/scsi/hosts.h Sun Jan 23 23:18:35 2000
+++ 2.3/drivers/scsi/hosts.h Sun Jan 23 23:24:31 2000
@@ -379,6 +379,12 @@
      * set for the minority of drivers whose authors actually read the spec
;)
      */
     unsigned reverse_ordering:1;
+
+ /*
+ * Host swaps detection order of narrow and wide addressed devices
+ * (e.g. first the dev-id 8...15, then 0...7)
+ */
+ unsigned swap_lohi_order:1;
 
     /*
      * Indicates that one or more devices on this host were starved, and
--- linux/drivers/scsi/scsi.c Sun Jan 23 23:18:56 2000
+++ 2.3/drivers/scsi/scsi.c Sun Jan 23 23:29:41 2000
@@ -34,6 +34,8 @@
  * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  *
  * out_of_space hacks, D. Gilbert (dpg) 990608
+ *
+ * New boot options pattern, G. Haese (gerald.haese@gmx.de), 23 Jan 2000
  */
 
 #include <linux/config.h>
@@ -150,7 +152,14 @@
  * Note - the initial logging level can be set here to log events at boot
time.
  * After the system is up, you may enable logging via the /proc interface.
  */
-unsigned int scsi_logging_level = 0;
+unsigned int scsi_logging_level = 0;
+static unsigned int scsi_reverse_ordering = 0;
+static unsigned int scsi_swap_lohi_order = 0;
+#ifdef CONFIG_SCSI_MULTI_LUN
+static unsigned int scsi_max_luns = 8;
+#else
+static unsigned int scsi_max_luns = 1;
+#endif
 
 const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
 {
@@ -268,9 +277,9 @@
         {"REGAL", "CDC-4X", "*", BLIST_MAX5LUN | BLIST_SINGLELUN},
         {"NAKAMICH", "MJ-4.8S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
         {"NAKAMICH", "MJ-5.16S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-600", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-602X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-604X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
+ {"PIONEER", "CD-ROM DRM-600", "*", BLIST_FORCELUN |
BLIST_SINGLELUN},
+ {"PIONEER", "CD-ROM DRM-602X", "*", BLIST_FORCELUN |
BLIST_SINGLELUN},
+ {"PIONEER", "CD-ROM DRM-604X", "*", BLIST_FORCELUN |
BLIST_SINGLELUN},
         {"EMULEX", "MD21/S2 ESDI", "*", BLIST_SINGLELUN},
         {"CANON", "IPUBJD", "*", BLIST_SPARSELUN},
         {"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},
@@ -283,7 +292,6 @@
          {"TOSHIBA","CDROM","*", BLIST_ISROM},
         {"TOSHIBA","DVD-RAM SD-W1101","*", BLIST_GHOST},
         {"TOSHIBA","DVD-RAM SD-W1111","*", BLIST_GHOST},
-
         /*
          * Must be at end of list...
          */
@@ -326,6 +334,73 @@
 }
 
 #ifdef MODULE
+MODULE_PARM(scsi_swap_lohi_order, "i");
+MODULE_PARM_DESC(scsi_swap_lohi_order, "Detection of SCSI devices with IDs
> 7 first; should be nonzero (true) or zero");
+
+#else
+
+#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
+
+/*
+ * boot time opions: "scsi=<option1>:<value>,<option2:<value>,..."
+ * options: max_luns:<number>
+ * logging[:<level>]
+ * reverse_ordering[:<bit mask>]
+ * swap_lohi_order[:<bit mask>]
+ *
+ * "bit mask" means that the flag can be set seperatly for each host
adapter
+ * in the system. E.g. "reverse_ordering: 0x3" means host 0 (bit 1) and
+ * host 1 (bit 2) should order the devices reversely.
+ * The option is valid for all hosts if no value or bit mask is given (the
+ * same for swap_lohi_order).
+ */
+static int __init scsi_setup(char *str)
+{
+ int i, n;
+ char *p;
+ char *end;
+
+ static struct {
+ const char *name;
+ unsigned int *flag;
+ } options[] = {
+ { "max_luns", &scsi_max_luns },
+ { "logging", &scsi_logging_level },
+ { "swap_lohi_order", &scsi_swap_lohi_order },
+ { "reverse_ordering", &scsi_reverse_ordering },
+ };
+
+ end = strchr(str, '\0');
+
+ for (p = strtok(str, ",."); p; p = strtok(NULL, ",.")) {
+ for (i = 0; i < NUMBER(options); i++) {
+ n = strlen(options[i].name);
+ if (!strncmp(options[i].name, p, n)) {
+ if (!strncmp(p, "max_luns", n)) {
+ unsigned int luns = (unsigned
int)(-1);
+
+ if (p[n] == ':')
+ luns = (unsigned
int)simple_strtoul(p + n + 1, NULL, 0);
+ if (luns-1 < 8)
+ *(options[i].flag) = luns;
+ } else {
+ if (p[n] == ':') {
+ *(options[i].flag) =
simple_strtoul(p + n + 1, NULL, 0);
+ } else {
+ *(options[i].flag) =
~(*(options[i].flag));
+ }
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+__setup("scsi=", scsi_setup);
+
+#endif
+
+#ifdef MODULE
 MODULE_PARM(scsi_logging_level, "i");
 MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or
nonzero");
 
@@ -349,25 +424,19 @@
 
 #endif
 
-#ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns = 8;
-#else
-static int max_scsi_luns = 1;
-#endif
-
 #ifdef MODULE
 
-MODULE_PARM(max_scsi_luns, "i");
-MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and
8)");
+MODULE_PARM(scsi_max_luns, "i");
+MODULE_PARM_DESC(scsi_max_luns, "last scsi LUN (should be between 1 and
8)");
 
 #else
 
 static int __init scsi_luns_setup(char *str)
 {
- int tmp;
+ unsigned int tmp;
 
         if (get_option(&str, &tmp) == 1) {
- max_scsi_luns = tmp;
+ scsi_max_luns = tmp;
                 return 1;
         } else {
                 printk("scsi_luns_setup : usage max_scsi_luns=n "
@@ -415,7 +484,7 @@
         int channel;
         int dev;
         int lun;
- int max_dev_lun;
+ unsigned int max_dev_lun;
         Scsi_Cmnd *SCpnt;
         unsigned char *scsi_result;
         unsigned char scsi_result0[256];
@@ -529,36 +598,61 @@
                         }
                 }
         } else {
- /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0
*/
- int order_dev;
-
+ int fdev, ldev;
+ int max_id = shpnt->max_id - 1;
+ int swap_lohi = shpnt->swap_lohi_order && ( max_id > 7 );
+ int step = shpnt->reverse_ordering ? -1 : 1;
+ int cycle = swap_lohi ? 2 : 1;
+
                 for (channel = 0; channel <= shpnt->max_channel; channel++)
{
- for (dev = 0; dev < shpnt->max_id; ++dev) {
- if (shpnt->reverse_ordering)
- /* Shift to scanning 15,14,13... or
7,6,5,4, */
- order_dev = shpnt->max_id - dev - 1;
- else
- order_dev = dev;
-
- if (shpnt->this_id != order_dev) {
-
- /*
- * We need the for so our continue,
etc. work fine. We put this in
- * a variable so that we can
override it during the scan if we
- * detect a device *KNOWN* to have
multiple logical units.
- */
- max_dev_lun = (max_scsi_luns <
shpnt->max_lun ?
- max_scsi_luns : shpnt->max_lun);
- sparse_lun = 0;
- for (lun = 0; lun < max_dev_lun;
++lun) {
- if
(!scan_scsis_single(channel, order_dev, lun, &max_dev_lun,
-
&sparse_lun, &SDpnt, SCpnt, shpnt,
- scsi_result)
- && !sparse_lun)
- break; /* break
means don't probe further for luns!=0 */
- } /* for lun ends */
- } /* if this_id != id ends */
- } /* for dev ends */
+ /* set first and last device ID according to the
boot options */
+ if (step > 0) {
+ fdev = 0;
+ ldev = max_id;
+ } else {
+ fdev = max_id;
+ ldev = 0;
+ }
+ do {
+ /* set cycle number and correct first and
last device
+ * per cycle, if detection order of narrow
and wide addressed
+ * devices is swaped by boot options
+ */
+ if (swap_lohi) {
+ if (cycle > 1) {
+ fdev = (step > 0) ? 8 : 7;
+ } else {
+ if (step > 0) {
+ fdev = 0;
+ ldev = 7;
+ } else {
+ fdev = max_id;
+ ldev = 8;
+ }
+ }
+ }
+ ldev += step;
+ for (dev = fdev; dev != ldev; dev += step) {

+ if (shpnt->this_id != dev) {
+
+ /*
+ * We need the for so our
continue, etc. work fine. We put this in
+ * a variable so that we can
override it during the scan if we
+ * detect a device *KNOWN*
to have multiple logical units.
+ */
+ max_dev_lun = (scsi_max_luns
< shpnt->max_lun ?
+ scsi_max_luns :
shpnt->max_lun);
+ sparse_lun = 0;
+ for (lun = 0; lun <
max_dev_lun; ++lun) {
+ if
(!scan_scsis_single(channel, dev, lun, &max_dev_lun,
+
&sparse_lun, &SDpnt, SCpnt, shpnt,
+
scsi_result)
+ && !sparse_lun)
+ break; /*
break means don't probe further for luns!=0 */
+ } /* for lun ends */
+ } /* if this_id != id ends */
+ } /* for dev ends */
+ } while (--cycle);
                 } /* for channel ends */
         } /* if/else hardcoded */
 
@@ -2050,6 +2144,7 @@
         struct Scsi_Host *shpnt;
         struct Scsi_Device_Template *sdtpnt;
         struct proc_dir_entry *generic;
+ unsigned int flag;
 #ifdef FOO_ON_YOU
         return;
 #endif
@@ -2077,6 +2172,13 @@
 
         /* Init a few things so we can "malloc" memory. */
         scsi_loadable_module_flag = 0;
+
+ /* show the values of the bootparams for the scsi-midlevel-driver*/
+ printk("scsi setup:\n");
+ printk(" max luns : %d\n logging level : 0x%x\n",
+ scsi_max_luns, scsi_logging_level );
+ printk(" reverse ordering: 0x%x\n swap lo/hi order: 0x%x\n",
+ scsi_reverse_ordering, scsi_swap_lohi_order);
 
         /* initialize all hosts */
         scsi_init();
@@ -2088,19 +2190,25 @@
          */
         init_bh(SCSI_BH, scsi_bottom_half_handler);
 
+ flag = 1;
         for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+ if (scsi_reverse_ordering & flag)
+ shpnt->reverse_ordering = 1;
+ if (scsi_swap_lohi_order & flag)
+ shpnt->swap_lohi_order = 1;
+ flag <<= 1;
                 scan_scsis(shpnt, 0, 0, 0, 0); /* scan for scsi devices */
                 if (shpnt->select_queue_depths != NULL)
                         (shpnt->select_queue_depths) (shpnt,
shpnt->host_queue);
         }
 
- printk("scsi : detected ");
+ printk("scsi : detected ");
         for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
                 if (sdtpnt->dev_noticed && sdtpnt->name)
                         printk("%d SCSI %s%s ", sdtpnt->dev_noticed,
sdtpnt->name,
                                (sdtpnt->dev_noticed != 1) ? "s" : "");
         printk("total.\n");
-
+
         for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
                 if (sdtpnt->init && sdtpnt->dev_noticed)
                         (*sdtpnt->init) ();

 <<scsi.diff.gz>>



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jan 31 2000 - 21:00:14 EST