summaryrefslogtreecommitdiff
path: root/sys/scsi
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2004-01-23 02:44:22 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2004-01-23 02:44:22 +0000
commit2f7b61c6a3b09b222c20dc856c0ed52e8ce490a9 (patch)
tree4c56d21eb9d8ebaa14be60e0571ad6190b0ab570 /sys/scsi
parent384fea3e6e93607bb758d740d864c29e0dede828 (diff)
Don't probe impossible luns. If lun 0 is non-existant, or if the device shows
it doesn't grok luns then stop probing. Speeds up the probe of an empty scsi bus by approx. 30 seconds. From Marco Peereboom. Tested by Marco Peereboom, millert@, miod@, Diana Eichart, and a host of anonymous snapshot users. ok deraadt@.
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/scsiconf.c94
1 files changed, 50 insertions, 44 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index 1ad1851f6d4..9d1f067cd91 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.c,v 1.78 2004/01/17 13:56:56 krw Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.79 2004/01/23 02:44:21 krw Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
@@ -74,7 +74,7 @@
/*
* Declarations
*/
-void scsi_probedev(struct scsibus_softc *, struct scsi_inquiry_data *, int,
+int scsi_probedev(struct scsibus_softc *, struct scsi_inquiry_data *, int,
int);
int scsi_probe_bus(int bus, int target, int lun);
@@ -310,7 +310,9 @@ scsi_probe_bus(bus, target, lun)
if (target != scsi_addr) {
bzero(&inqbuflun0, sizeof inqbuflun0);
for (lun = minlun; lun <= maxlun; lun++)
- scsi_probedev(scsi, &inqbuflun0, target, lun);
+ if (scsi_probedev(scsi, &inqbuflun0, target,
+ lun) == EINVAL)
+ break;
}
return 0;
@@ -601,11 +603,12 @@ scsibusprint(aux, pnp)
}
/*
- * given a target and lu, ask the device what
- * it is, and find the correct driver table
- * entry.
+ * Given a target and lun, ask the device what it is, and find the correct
+ * driver table entry.
+ *
+ * Return 0 if further LUNs are possible, EINVAL if not.
*/
-void
+int
scsi_probedev(scsi, inqbuflun0, target, lun)
struct scsibus_softc *scsi;
struct scsi_inquiry_data *inqbuflun0;
@@ -614,17 +617,18 @@ scsi_probedev(scsi, inqbuflun0, target, lun)
struct scsi_link *sc_link;
static struct scsi_inquiry_data inqbuf;
const struct scsi_quirk_inquiry_pattern *finger;
- int priority;
+ int priority, rslt;
struct scsibus_attach_args sa;
struct cfdata *cf;
- /* Skip this slot if it is already attached. */
+ /* Skip this slot if it is already attached and try the next LUN. */
if (scsi->sc_link[target][lun])
- return;
+ return (0);
sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
if (sc_link == NULL)
- return;
+ return (EINVAL);
+
*sc_link = *scsi->adapter_link;
sc_link->target = target;
sc_link->lun = lun;
@@ -632,12 +636,13 @@ scsi_probedev(scsi, inqbuflun0, target, lun)
sc_link->inquiry_flags = 0;
sc_link->inquiry_flags2 = 0;
+ SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n"));
+
/*
- * Tell drivers that are paying attention to avoid
- * sync/wide/tags until INQUIRY data and quirks information
- * are available. Since bits in quirks may have already been
- * set by some drivers (e.g. NOLUNS for atapiscsi), just add
- * NOTAGS, NOWIDE and NOSYNC.
+ * Tell drivers that are paying attention to avoid sync/wide/tags until
+ * INQUIRY data has been processed and the quirks information is
+ * complete. Some drivers set bits in quirks before we get here, so
+ * just add NOTAGS, NOWIDE and NOSYNC.
*/
sc_link->quirks |= SDEV_NOSYNC | SDEV_NOWIDE | SDEV_NOTAGS;
@@ -664,27 +669,25 @@ scsi_probedev(scsi, inqbuflun0, target, lun)
memset(&inqbuf.revision, ' ', sizeof inqbuf.revision);
memset(&inqbuf.extra, ' ', sizeof inqbuf.extra);
- if (scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT) != 0)
- goto bad;
+ rslt = scsi_inquire(sc_link, &inqbuf, scsi_autoconf | SCSI_SILENT);
- if (lun == 0) {
- /*
- * Save the INQUIRY page of LUN 0 to compare to the remaining
- * LUN's. If the INQUIRY data is the same as LUN 0 it *is* LUN
- * 0 and threfore we can safely ignore it. This is to cover
- * stupid SCSI devices that don't handle the IDENTIFY message.
- */
+ if (lun == 0 && rslt != 0) {
+ /* A bad LUN 0 INQUIRY means no further LUNs possible. */
+ SC_DEBUG(sc_link, SDEV_DB2, ("No LUN 0. rslt == %i\n", rslt));
+ rslt = EINVAL;
+ goto bad;
+ } else if (rslt != 0) {
+ /* Just a failed LUN INQUIRY, try the next LUN. */
+ SC_DEBUG(sc_link, SDEV_DB2, ("Bad LUN. rslt == %i\n", rslt));
+ rslt = 0;
+ goto bad;
+ } else if (lun == 0) {
bcopy(&inqbuf, inqbuflun0, sizeof *inqbuflun0);
- } else {
- if (memcmp(&inqbuf, inqbuflun0, sizeof inqbuf) == 0) {
- /*
- * Stupid SCSI device that does not handle the IDENTIFY
- * message. Mark this LUN as not there.
- */
- SC_DEBUG(sc_link, SDEV_DB1,
- ("IDENTIFY not supported.\n"));
- goto bad;
- }
+ } else if (memcmp(&inqbuf, inqbuflun0, sizeof inqbuf) == 0) {
+ /* The device can't distinguish between LUNs. */
+ SC_DEBUG(sc_link, SDEV_DB1, ("IDENTIFY not supported.\n"));
+ rslt = EINVAL;
+ goto bad;
}
switch (inqbuf.device & SID_QUAL) {
@@ -752,22 +755,25 @@ scsi_probedev(scsi, inqbuflun0, target, lun)
scsi->sc_link[target][lun] = sc_link;
/*
- * Generate another TEST_UNIT_READY command. This gives
- * drivers waiting for valid quirks data a chance to set
- * wide/sync/tag options appropriately. Do this now so that
- * any messages generated by config_attach() do not have
- * negotiation messages inserted into their midst.
+ * Generate a TEST_UNIT_READY command. This gives drivers waiting for
+ * valid quirks data a chance to set wide/sync/tag options
+ * appropriately. It also clears any outstanding ACA conditions that
+ * INQUIRY may leave behind.
+ *
+ * Do this now so that any messages generated by config_attach() do not
+ * have negotiation messages inserted into their midst.
*/
- (void) scsi_test_unit_ready(sc_link, TEST_READY_RETRIES_DEFAULT,
- scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
+ scsi_test_unit_ready(sc_link, TEST_READY_RETRIES_DEFAULT,
+ scsi_autoconf | SCSI_IGNORE_ILLEGAL_REQUEST |
+ SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE);
config_attach((struct device *)scsi, cf, &sa, scsibusprint);
- return;
+ return (0);
bad:
free(sc_link, M_DEVBUF);
- return;
+ return (rslt);
}
/*