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); }
int scsi_parse(uint8_t *block, uint8_t in_len) { /* set new operation */ if (state == USB_MS_SCSI_STATE_IDLE) { state = USB_MS_SCSI_STATE_PARSE; op = block[0]; } /* skip operation if sending reply */ if (state != USB_MS_SCSI_STATE_REPLY) { switch (op) { case SCSI_INQUIRY: scsi_inquiry(block, in_len); break; case SCSI_MODE_SENSE6: scsi_mode_sense6(block, in_len); break; case SCSI_READ10: scsi_read10(block, in_len); break; case SCSI_READ_CAPACITY10: scsi_read_capacity10(block, in_len); break; case SCSI_READ_FORMAT_CAPACITIES: scsi_read_format_capacities(block, in_len); break; case SCSI_REPORT_LUNS: scsi_report_luns(block, in_len); break; case SCSI_REQUEST_SENSE: scsi_request_sense(block, in_len); break; case SCSI_START_STOP_UNIT: scsi_start_stop_unit(block, in_len); break; case SCSI_SYNCHRONIZE_CACHE10: scsi_synchronize_cache10(block, in_len); break; case SCSI_TEST_UNIT_READY: scsi_test_unit_ready(block, in_len); break; case SCSI_WRITE10: scsi_write10(block, in_len); break; default: state = USB_MS_SCSI_STATE_REPLY; scsi_sense_code(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_SENSE_CODE_INVALID_COMMAND_OPERATION_CODE); break; } } /* error during data rx/tx */ if (((state == USB_MS_SCSI_STATE_DATA_OUT) || (state == USB_MS_SCSI_STATE_DATA_IN)) && scsi_sense_data.key) { btable_ep[USB_EP_MS_TX].tx_count = 0; state = USB_MS_SCSI_STATE_REPLY; return SCSI_STATUS_CONTINUE; } /* done sending data */ if (state == USB_MS_SCSI_STATE_REPLY) { state = USB_MS_SCSI_STATE_IDLE; return scsi_sense_data.key; } /* still sending/receiving data and no error has occurred */ return SCSI_STATUS_CONTINUE; }