diff options
author | ken <ken@FreeBSD.org> | 2015-02-18 23:08:13 +0000 |
---|---|---|
committer | ken <ken@FreeBSD.org> | 2015-02-18 23:08:13 +0000 |
commit | c0ca6257a68a40f3e05c0b4bad5b74ec48921b2d (patch) | |
tree | 13d88680c90d0edbacf71d8de78bb23268f58d7c /sys/cam | |
parent | 6bd13609ea0011ec42beeec19f2cdbe912103d36 (diff) | |
download | FreeBSD-src-c0ca6257a68a40f3e05c0b4bad5b74ec48921b2d.zip FreeBSD-src-c0ca6257a68a40f3e05c0b4bad5b74ec48921b2d.tar.gz |
MFC 278228:
The __FreeBSD_version has been changed to 1001508 for the addition of the
CDAI_TYPE_EXT_INQ request type.
------------------------------------------------------------------------
r278228 | ken | 2015-02-04 17:12:21 -0700 (Wed, 04 Feb 2015) | 32 lines
Add support for probing the SCSI VPD Extended Inquiry page (0x86).
This VPD page is effectively an extension of the standard Inquiry
data page, and includes lots of additional bits.
This commit includes support for probing the page in the SCSI probe code,
and an additional request type for the XPT_DEV_ADVINFO CCB. CTL already
supports the Extended Inquiry page.
Support for querying this page in the sa(4) driver will come later.
sys/cam/scsi/scsi_xpt.c:
Probe the Extended Inquiry page, if the device supports it, and
return it in response to a XPT_DEV_ADVINFO CCB if it is requested.
sys/cam/scsi/cam_ccb.h:
Define a new advanced information CCB data type, CDAI_TYPE_EXT_INQ.
sys/cam/cam_xpt.c:
Free the extended inquiry data in a device when the device goes
away.
sys/cam/cam_xpt_internal.h:
Add an extended inquiry data pointer and length to struct cam_ed.
sys/sys/param.h
Bump __FreeBSD_version for the addition of the new
CDAI_TYPE_EXT_INQ advanced information type.
Sponsored by: Spectra Logic
MFC after: 1 week
------------------------------------------------------------------------
Sponsored by: Spectra Logic
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam_ccb.h | 1 | ||||
-rw-r--r-- | sys/cam/cam_xpt.c | 1 | ||||
-rw-r--r-- | sys/cam/cam_xpt_internal.h | 2 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_xpt.c | 89 |
4 files changed, 93 insertions, 0 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index c2f6c46..9b882ca 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -1152,6 +1152,7 @@ struct ccb_dev_advinfo { #define CDAI_TYPE_SERIAL_NUM 2 #define CDAI_TYPE_PHYS_PATH 3 #define CDAI_TYPE_RCAPLONG 4 +#define CDAI_TYPE_EXT_INQ 5 off_t bufsiz; /* IN: Size of external buffer */ #define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */ off_t provsiz; /* OUT: Size required/used */ diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index c8a7256..b48654a 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -4793,6 +4793,7 @@ xpt_release_device(struct cam_ed *device) */ free(device->supported_vpds, M_CAMXPT); free(device->device_id, M_CAMXPT); + free(device->ext_inq, M_CAMXPT); free(device->physpath, M_CAMXPT); free(device->rcap_buf, M_CAMXPT); free(device->serial_num, M_CAMXPT); diff --git a/sys/cam/cam_xpt_internal.h b/sys/cam/cam_xpt_internal.h index f8c6498..23d6d34 100644 --- a/sys/cam/cam_xpt_internal.h +++ b/sys/cam/cam_xpt_internal.h @@ -83,6 +83,8 @@ struct cam_ed { uint8_t supported_vpds_len; uint32_t device_id_len; uint8_t *device_id; + uint32_t ext_inq_len; + uint8_t *ext_inq; uint8_t physpath_len; uint8_t *physpath; /* physical path string form */ uint32_t rcap_len; diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index df82871..57bcfb2 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -142,6 +142,7 @@ typedef enum { PROBE_MODE_SENSE, PROBE_SUPPORTED_VPD_LIST, PROBE_DEVICE_ID, + PROBE_EXTENDED_INQUIRY, PROBE_SERIAL_NUM, PROBE_TUR_FOR_NEGOTIATION, PROBE_INQUIRY_BASIC_DV1, @@ -159,6 +160,7 @@ static char *probe_action_text[] = { "PROBE_MODE_SENSE", "PROBE_SUPPORTED_VPD_LIST", "PROBE_DEVICE_ID", + "PROBE_EXTENDED_INQUIRY", "PROBE_SERIAL_NUM", "PROBE_TUR_FOR_NEGOTIATION", "PROBE_INQUIRY_BASIC_DV1", @@ -926,6 +928,34 @@ done: } goto done; } + case PROBE_EXTENDED_INQUIRY: + { + struct scsi_vpd_extended_inquiry_data *ext_inq; + + ext_inq = NULL; + if (scsi_vpd_supported_page(periph, SVPD_EXTENDED_INQUIRY_DATA)) + ext_inq = malloc(sizeof(*ext_inq), M_CAMXPT, + M_NOWAIT | M_ZERO); + + if (ext_inq != NULL) { + scsi_inquiry(csio, + /*retries*/4, + probedone, + MSG_SIMPLE_Q_TAG, + (uint8_t *)ext_inq, + sizeof(*ext_inq), + /*evpd*/TRUE, + SVPD_EXTENDED_INQUIRY_DATA, + SSD_MIN_SIZE, + /*timeout*/60 * 1000); + break; + } + /* + * We'll have to do without, let our probedone + * routine finish up for us. + */ + goto done; + } case PROBE_SERIAL_NUM: { struct scsi_vpd_unit_serial_number *serial_buf; @@ -1457,6 +1487,50 @@ out: if (devid && length == 0) free(devid, M_CAMXPT); xpt_release_ccb(done_ccb); + PROBE_SET_ACTION(softc, PROBE_EXTENDED_INQUIRY); + xpt_schedule(periph, priority); + goto out; + } + case PROBE_EXTENDED_INQUIRY: { + struct scsi_vpd_extended_inquiry_data *ext_inq; + struct ccb_scsiio *csio; + int32_t length = 0; + + csio = &done_ccb->csio; + ext_inq = (struct scsi_vpd_extended_inquiry_data *) + csio->data_ptr; + if (path->device->ext_inq != NULL) { + path->device->ext_inq_len = 0; + free(path->device->ext_inq, M_CAMXPT); + path->device->ext_inq = NULL; + } + + if (ext_inq == NULL) { + /* Don't process the command as it was never sent */ + } else if (CCB_COMPLETED_OK(csio->ccb_h)) { + length = scsi_2btoul(ext_inq->page_length) + + __offsetof(struct scsi_vpd_extended_inquiry_data, + flags1); + length = min(length, sizeof(*ext_inq)); + length -= csio->resid; + if (length > 0) { + path->device->ext_inq_len = length; + path->device->ext_inq = (uint8_t *)ext_inq; + } + } else if (cam_periph_error(done_ccb, 0, + SF_RETRY_UA, + &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); + } + + /* Free the device id space if we don't use it */ + if (ext_inq && length <= 0) + free(ext_inq, M_CAMXPT); + xpt_release_ccb(done_ccb); PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); xpt_schedule(periph, priority); goto out; @@ -2486,6 +2560,21 @@ scsi_dev_advinfo(union ccb *start_ccb) memcpy(cdai->buf, device->rcap_buf, amt); } break; + case CDAI_TYPE_EXT_INQ: + /* + * We fetch extended inquiry data during probe, if + * available. We don't allow changing it. + */ + if (cdai->flags & CDAI_FLAG_STORE) + return; + cdai->provsiz = device->ext_inq_len; + if (device->ext_inq_len == 0) + break; + amt = device->ext_inq_len; + if (cdai->provsiz > cdai->bufsiz) + amt = cdai->bufsiz; + memcpy(cdai->buf, device->ext_inq, amt); + break; default: return; } |