summaryrefslogtreecommitdiff
path: root/sys/scsi
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2006-10-21 07:36:16 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2006-10-21 07:36:16 +0000
commitdd98b50bc85201486c023d89677287827298d979 (patch)
tree083ba52fdf2c1f1d176f353ba7a5d4a7e7717d39 /sys/scsi
parentdd60917a693a797ca646ccf5e4a2b6e1693b96e1 (diff)
rework the bus scanning code by splitting it out into separate functions
for walking the bus and targets, and probing the luns. this removes the need to use magic numbers to wildcard each of these, which in turn makes the code a lot easier to read. as a bonus we get some more space to work in (80 chars isnt that much somtimes). note that this code wont probe high luns if lun 0 doesnt exist. ok krw@
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/scsiconf.c164
-rw-r--r--sys/scsi/scsiconf.h7
2 files changed, 73 insertions, 98 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index 1aa76c9c005..3028dbe54bf 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.c,v 1.116 2006/10/07 23:40:07 beck Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.117 2006/10/21 07:36:15 dlg Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
@@ -60,7 +60,6 @@
* Declarations
*/
int scsi_probedev(struct scsibus_softc *, int, int);
-int scsi_probe_bus(int, int, int);
struct scsi_device probe_switch = {
NULL,
@@ -160,7 +159,7 @@ scsibusattach(struct device *parent, struct device *self, void *aux)
bzero(sb->sc_link[i], nbytes);
}
- scsi_probe_bus(sb->sc_dev.dv_unit, -1, -1);
+ scsi_probe_bus(sb);
}
int
@@ -211,118 +210,91 @@ scsibussubmatch(struct device *parent, void *match, void *aux)
return ((*cf->cf_attach->ca_match)(parent, match, aux));
}
-/*
- * Probe the requested scsi bus. It must be already set up.
- * -1 requests all set up scsi busses.
- * target and lun optionally narrow the search if not -1
- */
int
-scsi_probe_busses(int bus, int target, int lun)
+scsi_probe_bus(struct scsibus_softc *sc)
{
- if (bus == -1) {
- for (bus = 0; bus < scsibus_cd.cd_ndevs; bus++)
- if (scsibus_cd.cd_devs[bus])
- scsi_probe_bus(bus, target, lun);
- return (0);
- }
+ struct scsi_link *alink = sc->adapter_link;
+ int i;
- return (scsi_probe_bus(bus, target, lun));
+ for (i = 0; i < alink->adapter_buswidth; i++)
+ scsi_probe_target(sc, i);
+
+ return (0);
}
-/*
- * Probe the requested scsi bus. It must be already set up.
- * target and lun optionally narrow the search if not -1
- */
int
-scsi_probe_bus(int bus, int target, int lun)
+scsi_probe_target(struct scsibus_softc *sc, int target)
{
- struct scsi_report_luns_data *data = NULL;
- struct scsibus_softc *scsi;
- struct scsi_link *sc_link;
- u_int16_t scsi_addr;
- int i, luncount, maxtarget, mintarget, maxlun, minlun;
+ struct scsi_link *alink = sc->adapter_link;
+ struct scsi_link *link;
+ struct scsi_report_luns_data *report;
+ int i, nluns, lun;
+
+ if (scsi_probe_lun(sc, target, 0) == EINVAL)
+ return (EINVAL);
- if (bus < 0 || bus >= scsibus_cd.cd_ndevs)
+ link = sc->sc_link[target][0];
+ if (link == NULL)
return (ENXIO);
- scsi = scsibus_cd.cd_devs[bus];
- if (scsi == NULL)
- return ENXIO;
+ if ((link->flags & (SDEV_UMASS | SDEV_ATAPI)) == 0 &&
+ SCSISPC(link->inqdata.version) > 2) {
+ report = malloc(sizeof(*report), M_TEMP, M_WAITOK);
+ if (report == NULL)
+ goto dumbscan;
+
+ if (scsi_report_luns(link, REPORT_NORMAL, report,
+ sizeof(*report), scsi_autoconf | SCSI_SILENT |
+ SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
+ SCSI_IGNORE_MEDIA_CHANGE, 10000) != 0) {
+ free(report, M_TEMP);
+ goto dumbscan;
+ }
- scsi_addr = scsi->adapter_link->adapter_target;
+ /*
+ * 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.
+ */
+ nluns = _4btol(report->length) / RPL_LUNDATA_SIZE;
+ for (i = 0; i < nluns; i++) {
+ if (report->luns[i].lundata[0] != 0)
+ continue;
+ lun = report->luns[i].lundata[RPL_LUNDATA_T0LUN];
+ if (lun == 0)
+ continue;
+
+ /* Probe the provided LUN. Don't check LUN 0. */
+ sc->sc_link[target][0] = NULL;
+ scsi_probe_lun(sc, target, lun);
+ sc->sc_link[target][0] = link;
+ }
- if (target == -1) {
- maxtarget = scsi->adapter_link->adapter_buswidth - 1;
- mintarget = 0;
- } else {
- if (target < 0 ||
- target >= scsi->adapter_link->adapter_buswidth)
- return (EINVAL);
- maxtarget = mintarget = target;
+ free(report, M_TEMP);
+ return (0);
}
- if (lun == -1) {
- maxlun = scsi->adapter_link->luns - 1;
- minlun = 0;
- } else {
- if (lun < 0 || lun >= scsi->adapter_link->luns)
- return (EINVAL);
- maxlun = lun;
- if (target == -1 || scsi->sc_link[target][0] == NULL)
- minlun = 0;
- else
- minlun = lun;
+dumbscan:
+ for (i = 1; i < alink->luns; i++) {
+ if (scsi_probe_lun(sc, target, i) == EINVAL)
+ break;
}
- data = malloc(sizeof *data, M_TEMP, M_NOWAIT);
-
- for (target = mintarget; target <= maxtarget; target++) {
- if (target == scsi_addr)
- continue;
- 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 &&
- SCSISPC(sc_link->inqdata.version) > 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. */
- }
+ return (0);
+}
- /* No LUN list available. Scan entire range. */
- for (lun = max(minlun, 1); lun <= maxlun; lun++)
- if (scsi_probedev(scsi, target, lun) == EINVAL)
- break;
- }
+int
+scsi_probe_lun(struct scsibus_softc *sc, int target, int lun)
+{
+ struct scsi_link *alink = sc->adapter_link;
- if (data != NULL)
- free(data, M_TEMP);
+ if (target < 0 || target >= alink->adapter_buswidth ||
+ target == alink->adapter_target ||
+ lun < 0 || lun >= alink->luns)
+ return (ENXIO);
- return (0);
+ return (scsi_probedev(sc, target, lun));
}
void
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index a04d6299027..ffdf1d49a9a 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.75 2006/10/07 23:40:07 beck Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.76 2006/10/21 07:36:15 dlg Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -343,10 +343,13 @@ void show_scsi_xs(struct scsi_xfer *);
void scsi_print_sense(struct scsi_xfer *);
void show_scsi_cmd(struct scsi_xfer *);
void show_mem(u_char *, int);
-int scsi_probe_busses(int, int, int);
void scsi_strvis(u_char *, u_char *, int);
int scsi_delay(struct scsi_xfer *, int);
+int scsi_probe_bus(struct scsibus_softc *);
+int scsi_probe_target(struct scsibus_softc *, int);
+int scsi_probe_lun(struct scsibus_softc *, int, int);
+
static __inline void _lto2b(u_int32_t val, u_int8_t *bytes);
static __inline void _lto3b(u_int32_t val, u_int8_t *bytes);
static __inline void _lto4b(u_int32_t val, u_int8_t *bytes);