summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/mpi.c7
-rw-r--r--sys/scsi/scsiconf.c164
-rw-r--r--sys/scsi/scsiconf.h7
3 files changed, 75 insertions, 103 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index e661e72b25c..47a064bec01 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.75 2006/09/22 00:43:18 dlg Exp $ */
+/* $OpenBSD: mpi.c,v 1.76 2006/10/21 07:36:15 dlg Exp $ */
/*
* Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org>
@@ -197,12 +197,10 @@ mpi_attach(struct mpi_softc *sc)
goto free_replies;
}
-#ifdef notyet
if (mpi_eventnotify(sc) != 0) {
printf("%s: unable to get portfacts\n", DEVNAME(sc));
goto free_replies;
}
-#endif
if (mpi_portenable(sc) != 0) {
printf("%s: unable to enable port\n", DEVNAME(sc));
@@ -2025,8 +2023,7 @@ mpi_evt_sas(void *xsc, void *arg)
case MPI_EVT_SASCH_REASON_ADDED:
case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED:
/* XXX what an awful interface */
- scsi_probe_busses(sc->sc_scsibus->sc_dev.dv_unit,
- ch->target, -1);
+ scsi_probe_target(sc->sc_scsibus, ch->target);
break;
case MPI_EVT_SASCH_REASON_NOT_RESPONDING:
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);