diff options
author | 2006-07-23 14:34:55 +0000 | |
---|---|---|
committer | 2006-07-23 14:34:55 +0000 | |
commit | a022b4814c3e7d237d7ddb844fa42efdd9a1882f (patch) | |
tree | 39a42a878c53ee87112313f1f72e8faaac187104 /sys/scsi/scsiconf.c | |
parent | remove tzset(3) from SYNOPSIS: it has its own man page; (diff) | |
download | wireguard-openbsd-a022b4814c3e7d237d7ddb844fa42efdd9a1882f.tar.xz wireguard-openbsd-a022b4814c3e7d237d7ddb844fa42efdd9a1882f.zip |
Use REPORT LUNS to get the list of LUNs to probe. If such a list is
obtained probe the LUNs given without checking for duplicate INQUIRY
data.
For non-USB, non-ATAPI, devices claiming to be SCSI-3 compliant. And
the target must have something attached at LUN 0.
If REPORT LUNS can't be used or isn't supported, the old scan process
is used.
Fixes Fibre Channel and SCSI enclosure devices that provide identical
INQUIRY data for all LUNs and were thus being misprobed as having
only LUN 0.
Tested by Bob Kitella, dlg@, beck@. Suggestions from deraadt@.
ok dlg@ beck@
Diffstat (limited to 'sys/scsi/scsiconf.c')
-rw-r--r-- | sys/scsi/scsiconf.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 8e602244f8d..3f55b00f4c7 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.109 2006/07/22 18:25:42 krw Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.110 2006/07/23 14:34:55 krw Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -217,9 +217,11 @@ scsi_probe_busses(int bus, int target, int lun) int scsi_probe_bus(int bus, int target, int lun) { + struct scsi_report_luns_data *data = NULL; struct scsibus_softc *scsi; + struct scsi_link *sc_link; u_int16_t scsi_addr; - int maxtarget, mintarget, maxlun, minlun; + int i, luncount, maxtarget, mintarget, maxlun, minlun; if (bus < 0 || bus >= scsibus_cd.cd_ndevs) return (ENXIO); @@ -252,17 +254,55 @@ scsi_probe_bus(int bus, int target, int lun) else minlun = lun; } - + + data = malloc(sizeof *data, M_TEMP, M_NOWAIT); + for (target = mintarget; target <= maxtarget; target++) { if (target == scsi_addr) continue; - - for (lun = minlun; lun <= maxlun; lun++) { + if (scsi_probedev(scsi, target, 0) == EINVAL) + continue; + + sc_link = scsi->sc_link[target][0]; + if (sc_link != NULL && data != NULL && + (sc_link->flags & (SDEV_UMASS | SDEV_ATAPI)) == 0 && + (sc_link->inqdata.version & SID_ANSII) > 2) { + scsi_report_luns(sc_link, REPORT_NORMAL, data, + sizeof *data, scsi_autoconf | SCSI_SILENT | + SCSI_IGNORE_ILLEGAL_REQUEST | + SCSI_IGNORE_NOT_READY | SCSI_IGNORE_MEDIA_CHANGE, + 10000); + /* + * XXX In theory we should check if data is full, which + * would indicate it needs to be enlarged and REPORT + * LUNS tried again. Solaris tries up to 3 times with + * larger sizes for data. + */ + luncount = _4btol(data->length) / RPL_LUNDATA_SIZE; + for (i = 0; i < luncount; i++) { + if (data->luns[i].lundata[0] != 0) + continue; + lun = data->luns[i].lundata[RPL_LUNDATA_T0LUN]; + if (lun == 0 || lun < minlun || lun > maxlun) + continue; + /* Probe the provided LUN. Don't check LUN 0. */ + scsi->sc_link[target][0] = NULL; + scsi_probedev(scsi, target, lun); + scsi->sc_link[target][0] = sc_link; + } + if (luncount > 0) + continue; /* Next target. */ + } + + /* No LUN list available. Scan entire range. */ + for (lun = max(minlun, 1); lun <= maxlun; lun++) if (scsi_probedev(scsi, target, lun) == EINVAL) break; - } } + if (data != NULL) + free(data, M_TEMP); + return (0); } |