diff options
-rw-r--r-- | sys/dev/ic/mpi.c | 7 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 164 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 7 |
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); |