patch-2.4.7 linux/drivers/scsi/scsi_scan.c
Next file: linux/drivers/scsi/sd.c
Previous file: linux/drivers/scsi/scsi_obsolete.c
Back to the patch index
Back to the overall index
- Lines: 230
- Date:
Thu Jul 5 11:28:17 2001
- Orig file:
v2.4.6/linux/drivers/scsi/scsi_scan.c
- Orig date:
Tue Jul 3 17:08:20 2001
diff -u --recursive --new-file v2.4.6/linux/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
@@ -40,9 +40,13 @@
#define BLIST_ISROM 0x200
static void print_inquiry(unsigned char *data);
-static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev,
- int *sparse_lun, Scsi_Device ** SDpnt,
- struct Scsi_Host *shpnt, char *scsi_result);
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+ unsigned int lun, int lun0_scsi_level,
+ unsigned int *max_scsi_dev, unsigned int *sparse_lun,
+ Scsi_Device ** SDpnt, struct Scsi_Host *shpnt,
+ char *scsi_result);
+static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
+ struct Scsi_Host *shpnt);
struct dev_info {
const char *vendor;
@@ -135,6 +139,7 @@
{"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},
{"DEC","HSG80","*", BLIST_FORCELUN},
{"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN},
+ {"COMPAQ","CR3500","*", BLIST_FORCELUN},
{"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
@@ -143,7 +148,11 @@
{"MegaRAID", "LD", "*", BLIST_FORCELUN},
{"DGC", "RAID", "*", BLIST_SPARSELUN}, // Dell PV 650F (tgt @ LUN 0)
{"DGC", "DISK", "*", BLIST_SPARSELUN}, // Dell PV 650F (no tgt @ LUN 0)
+ {"DELL", "PV660F", "*", BLIST_SPARSELUN},
+ {"DELL", "PV660F PSEUDO", "*", BLIST_SPARSELUN},
+ {"DELL", "PSEUDO DEVICE .", "*", BLIST_SPARSELUN}, // Dell PV 530F
{"DELL", "PV530F", "*", BLIST_SPARSELUN}, // Dell PV 530F
+ {"EMC", "SYMMETRIX", "*", BLIST_SPARSELUN},
{"SONY", "TSL", "*", BLIST_FORCELUN}, // DDS3 & DDS4 autoloaders
{"DELL", "PERCRAID", "*", BLIST_FORCELUN},
{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
@@ -154,29 +163,31 @@
{NULL, NULL, NULL}
};
+#define MAX_SCSI_LUNS 0xFFFFFFFF
+
#ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns = 8;
+static unsigned int max_scsi_luns = MAX_SCSI_LUNS;
#else
-static int max_scsi_luns = 1;
+static unsigned 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_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)");
#else
static int __init scsi_luns_setup(char *str)
{
- int tmp;
+ unsigned int tmp;
if (get_option(&str, &tmp) == 1) {
max_scsi_luns = tmp;
return 1;
} else {
printk("scsi_luns_setup : usage max_scsi_luns=n "
- "(n should be between 1 and 8)\n");
+ "(n should be between 1 and 2^32-1)\n");
return 0;
}
}
@@ -264,14 +275,15 @@
uint hlun)
{
uint channel;
- int dev;
- int lun;
- int max_dev_lun;
+ unsigned int dev;
+ unsigned int lun;
+ unsigned int max_dev_lun;
unsigned char *scsi_result;
unsigned char scsi_result0[256];
Scsi_Device *SDpnt;
Scsi_Device *SDtail;
- int sparse_lun;
+ unsigned int sparse_lun;
+ int lun0_sl;
scsi_result = NULL;
@@ -343,8 +355,12 @@
lun = hlun;
if (lun >= shpnt->max_lun)
goto leave;
- scan_scsis_single(channel, dev, lun, &max_dev_lun, &sparse_lun,
- &SDpnt, shpnt, scsi_result);
+ if ((0 == lun) || (lun > 7))
+ lun0_sl = SCSI_3; /* actually don't care for 0 == lun */
+ else
+ lun0_sl = find_lun0_scsi_level(channel, dev, shpnt);
+ scan_scsis_single(channel, dev, lun, lun0_sl, &max_dev_lun,
+ &sparse_lun, &SDpnt, shpnt, scsi_result);
if (SDpnt != oldSDpnt) {
/* it could happen the blockdevice hasn't yet been inited */
@@ -400,12 +416,14 @@
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, shpnt,
- scsi_result)
+ for (lun = 0, lun0_sl = SCSI_2; lun < max_dev_lun; ++lun) {
+ if (!scan_scsis_single(channel, order_dev, lun, lun0_sl,
+ &max_dev_lun, &sparse_lun, &SDpnt, shpnt,
+ scsi_result)
&& !sparse_lun)
break; /* break means don't probe further for luns!=0 */
+ if (SDpnt && (0 == lun))
+ lun0_sl = SDpnt->scsi_level;
} /* for lun ends */
} /* if this_id != id ends */
} /* for dev ends */
@@ -461,9 +479,11 @@
* Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
* Global variables used : scsi_devices(linked list)
*/
-static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun,
- int *sparse_lun, Scsi_Device ** SDpnt2,
- struct Scsi_Host *shpnt, char *scsi_result)
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+ unsigned int lun, int lun0_scsi_level,
+ unsigned int *max_dev_lun, unsigned int *sparse_lun,
+ Scsi_Device ** SDpnt2, struct Scsi_Host *shpnt,
+ char *scsi_result)
{
char devname[64];
unsigned char scsi_cmd[MAX_COMMAND_SIZE];
@@ -509,7 +529,10 @@
* Build an INQUIRY command block.
*/
scsi_cmd[0] = INQUIRY;
- scsi_cmd[1] = (lun << 5) & 0xe0;
+ if ((lun > 0) && (lun0_scsi_level <= SCSI_2))
+ scsi_cmd[1] = (lun << 5) & 0xe0;
+ else
+ scsi_cmd[1] = 0; /* SCSI_3 and higher, don't touch */
scsi_cmd[2] = 0;
scsi_cmd[3] = 0;
scsi_cmd[4] = 255;
@@ -677,7 +700,9 @@
printk("Unlocked floptical drive.\n");
SDpnt->lockable = 0;
scsi_cmd[0] = MODE_SENSE;
- scsi_cmd[1] = (lun << 5) & 0xe0;
+ if (shpnt->max_lun <= 8)
+ scsi_cmd[1] = (lun << 5) & 0xe0;
+ else scsi_cmd[1] = 0; /* any other idea? */
scsi_cmd[2] = 0x2e;
scsi_cmd[3] = 0;
scsi_cmd[4] = 0x2a;
@@ -760,7 +785,19 @@
* other settings, and scan all of them.
*/
if (bflags & BLIST_SPARSELUN) {
- *max_dev_lun = 8;
+ /*
+ * Scanning MAX_SCSI_LUNS units would be a bad idea.
+ * Any better idea?
+ * I think we need REPORT LUNS in future to avoid scanning
+ * of unused LUNs. But, that is another item.
+ *
+ * FIXME(eric) - perhaps this should be a kernel configurable?
+ */
+ if (*max_dev_lun < shpnt->max_lun)
+ *max_dev_lun = shpnt->max_lun;
+ else if ((max_scsi_luns >> 1) >= *max_dev_lun)
+ *max_dev_lun += shpnt->max_lun;
+ else *max_dev_lun = max_scsi_luns;
*sparse_lun = 1;
return 1;
}
@@ -769,7 +806,17 @@
* settings, and scan all of them.
*/
if (bflags & BLIST_FORCELUN) {
- *max_dev_lun = 8;
+ /*
+ * Scanning MAX_SCSI_LUNS units would be a bad idea.
+ * Any better idea?
+ * I think we need REPORT LUNS in future to avoid scanning
+ * of unused LUNs. But, that is another item.
+ */
+ if (*max_dev_lun < shpnt->max_lun)
+ *max_dev_lun = shpnt->max_lun;
+ else if ((max_scsi_luns >> 1) >= *max_dev_lun)
+ *max_dev_lun += shpnt->max_lun;
+ else *max_dev_lun = max_scsi_luns;
return 1;
}
/*
@@ -793,3 +840,23 @@
return 1;
}
+/*
+ * The worker for scan_scsis.
+ * Returns the scsi_level of lun0 on this host, channel and dev (if already
+ * known), otherwise returns SCSI_2.
+ */
+static int find_lun0_scsi_level(unsigned int channel, unsigned int dev,
+ struct Scsi_Host *shpnt)
+{
+ int res = SCSI_2;
+ Scsi_Device *SDpnt;
+
+ for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
+ {
+ if ((0 == SDpnt->lun) && (dev == SDpnt->id) &&
+ (channel == SDpnt->channel))
+ return (int)SDpnt->scsi_level;
+ }
+ /* haven't found lun0, should send INQUIRY but take easy route */
+ return res;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)