int scsi_probe(struct scsibus_softc *sc, int target, int lun) { if (target == -1 && lun == -1) return (scsi_probe_bus(sc)); /* specific lun and wildcard target is bad */ if (target == -1) return (EINVAL); if (lun == -1) return (scsi_probe_target(sc, target)); return (scsi_probe_lun(sc, target, lun)); }
int scsibus_bioctl(struct device *dev, u_long cmd, caddr_t addr) { struct scsibus_softc *sc = (struct scsibus_softc *)dev; struct sbioc_device *sdev; switch (cmd) { case SBIOCPROBE: sdev = (struct sbioc_device *)addr; if (sdev->sd_target == -1 && sdev->sd_lun == -1) return (scsi_probe_bus(sc)); /* specific lun and wildcard target is bad */ if (sdev->sd_target == -1) return (EINVAL); if (sdev->sd_lun == -1) return (scsi_probe_target(sc, sdev->sd_target)); return (scsi_probe_lun(sc, sdev->sd_target, sdev->sd_lun)); case SBIOCDETACH: sdev = (struct sbioc_device *)addr; if (sdev->sd_target == -1 && sdev->sd_lun == -1) return (scsi_detach_bus(sc, 0)); if (sdev->sd_target == -1) return (EINVAL); if (sdev->sd_lun == -1) return (scsi_detach_target(sc, sdev->sd_target, 0)); return (scsi_detach_lun(sc, sdev->sd_target, sdev->sd_lun, 0)); default: return (ENOTTY); } }
int scsi_probe_target(struct scsibus_softc *sc, int target) { 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); link = sc->sc_link[target][0]; if (link == 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; } /* * 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; } free(report, M_TEMP); return (0); } dumbscan: for (i = 1; i < alink->luns; i++) { if (scsi_probe_lun(sc, target, i) == EINVAL) break; } return (0); }