summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/cam_xpt.c131
1 files changed, 95 insertions, 36 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 0563467..4ea05d5 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -464,7 +464,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
{
/* I can't believe we need a quirk for DPT volumes. */
{ T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" },
- CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS,
+ CAM_QUIRK_NOLUNS,
/*mintags*/0, /*maxtags*/255
},
{
@@ -495,7 +495,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
"EXB-8200*", "*"
},
- CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+ CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
/*
@@ -506,7 +506,7 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
"IPL-6860*", "*"
},
- CAM_QUIRK_NOSERIAL|CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+ CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
/*
@@ -551,17 +551,6 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
},
{
/*
- * Maxtor Personal Storage 3000XT (Firewire)
- * hangs upon serial number probing.
- */
- {
- T_DIRECT, SIP_MEDIA_FIXED, "Maxtor",
- "1394 storage", "*"
- },
- CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
- },
- {
- /*
* Would repond to all LUNs if asked for.
*/
{
@@ -620,18 +609,6 @@ static struct xpt_quirk_entry xpt_quirk_table[] =
CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
- /*
- * Western Digital My Book 250GB (USB)
- * hangs upon serial number probing.
- * PR: 107495
- */
- {
- T_DIRECT, SIP_MEDIA_FIXED, "WD",
- "2500JB External", "*"
- },
- CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
- },
- {
/* Default tagged queuing parameters for all devices */
{
T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
@@ -5474,7 +5451,8 @@ typedef enum {
PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */
PROBE_FULL_INQUIRY,
PROBE_MODE_SENSE,
- PROBE_SERIAL_NUM,
+ PROBE_SERIAL_NUM_0,
+ PROBE_SERIAL_NUM_1,
PROBE_TUR_FOR_NEGOTIATION,
PROBE_INQUIRY_BASIC_DV1,
PROBE_INQUIRY_BASIC_DV2,
@@ -5817,10 +5795,42 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
}
xpt_print(periph->path, "Unable to mode sense control page - "
"malloc failure\n");
- softc->action = PROBE_SERIAL_NUM;
+ softc->action = PROBE_SERIAL_NUM_0;
}
/* FALLTHROUGH */
- case PROBE_SERIAL_NUM:
+ case PROBE_SERIAL_NUM_0:
+ {
+ struct scsi_vpd_supported_page_list *vpd_list = NULL;
+ struct cam_ed *device;
+
+ device = periph->path->device;
+ if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0) {
+ vpd_list = malloc(sizeof(*vpd_list), M_CAMXPT,
+ M_NOWAIT | M_ZERO);
+ }
+
+ if (vpd_list != NULL) {
+ scsi_inquiry(csio,
+ /*retries*/4,
+ probedone,
+ MSG_SIMPLE_Q_TAG,
+ (u_int8_t *)vpd_list,
+ sizeof(*vpd_list),
+ /*evpd*/TRUE,
+ SVPD_SUPPORTED_PAGE_LIST,
+ SSD_MIN_SIZE,
+ /*timeout*/60 * 1000);
+ break;
+ }
+ /*
+ * We'll have to do without, let our probedone
+ * routine finish up for us.
+ */
+ start_ccb->csio.data_ptr = NULL;
+ probedone(periph, start_ccb);
+ return;
+ }
+ case PROBE_SERIAL_NUM_1:
{
struct scsi_vpd_unit_serial_number *serial_buf;
struct cam_ed* device;
@@ -5830,10 +5840,8 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
device->serial_num = NULL;
device->serial_num_len = 0;
- if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0)
- serial_buf = (struct scsi_vpd_unit_serial_number *)
- malloc(sizeof(*serial_buf), M_CAMXPT,
- M_NOWAIT | M_ZERO);
+ serial_buf = (struct scsi_vpd_unit_serial_number *)
+ malloc(sizeof(*serial_buf), M_CAMXPT, M_NOWAIT|M_ZERO);
if (serial_buf != NULL) {
scsi_inquiry(csio,
@@ -6058,7 +6066,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
if (INQ_DATA_TQ_ENABLED(inq_buf))
softc->action = PROBE_MODE_SENSE;
else
- softc->action = PROBE_SERIAL_NUM;
+ softc->action = PROBE_SERIAL_NUM_0;
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
@@ -6123,11 +6131,62 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
}
xpt_release_ccb(done_ccb);
free(mode_hdr, M_CAMXPT);
- softc->action = PROBE_SERIAL_NUM;
+ softc->action = PROBE_SERIAL_NUM_0;
xpt_schedule(periph, priority);
return;
}
- case PROBE_SERIAL_NUM:
+ case PROBE_SERIAL_NUM_0:
+ {
+ struct ccb_scsiio *csio;
+ struct scsi_vpd_supported_page_list *page_list;
+ int length, serialnum_supported, i;
+
+ serialnum_supported = 0;
+ csio = &done_ccb->csio;
+ page_list =
+ (struct scsi_vpd_supported_page_list *)csio->data_ptr;
+
+ if (page_list == NULL) {
+ /*
+ * Don't process the command as it was never sent
+ */
+ } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
+ && (page_list->length > 0)) {
+ length = min(page_list->length,
+ SVPD_SUPPORTED_PAGES_SIZE);
+ for (i = 0; i < length; i++) {
+ if (page_list->list[i] ==
+ SVPD_UNIT_SERIAL_NUMBER) {
+ serialnum_supported = 1;
+ break;
+ }
+ }
+ } else if (cam_periph_error(done_ccb, 0,
+ SF_RETRY_UA|SF_NO_PRINT,
+ &softc->saved_ccb) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+
+ if (page_list != NULL)
+ free(page_list, M_DEVBUF);
+
+ if (serialnum_supported) {
+ xpt_release_ccb(done_ccb);
+ softc->action = PROBE_SERIAL_NUM_1;
+ xpt_schedule(periph, priority);
+ return;
+ }
+ xpt_release_ccb(done_ccb);
+ softc->action = PROBE_TUR_FOR_NEGOTIATION;
+ xpt_schedule(periph, done_ccb->ccb_h.pinfo.priority);
+ return;
+ }
+
+ case PROBE_SERIAL_NUM_1:
{
struct ccb_scsiio *csio;
struct scsi_vpd_unit_serial_number *serial_buf;
OpenPOWER on IntegriCloud