diff options
author | ken <ken@FreeBSD.org> | 2015-01-30 05:23:39 +0000 |
---|---|---|
committer | ken <ken@FreeBSD.org> | 2015-01-30 05:23:39 +0000 |
commit | 30e216f85893cebc73455d1d87e357e9867988c2 (patch) | |
tree | bf04618dc37ea082510032ade1cf35cb4b416c1c /sys/cam | |
parent | b55f1535733c70849d7a3b4eddc4ad91c884db86 (diff) | |
download | FreeBSD-src-30e216f85893cebc73455d1d87e357e9867988c2.zip FreeBSD-src-30e216f85893cebc73455d1d87e357e9867988c2.tar.gz |
Improve SCSI Extended Inquiry VPD page (0x86) support.
sys/cam/scsi/scsi_all.h:
In struct scsi_extended_inquiry_data:
- Increase the length field to 2 bytes, as it is 2 bytes in SPC-4.
- Add bit definitions for the various Activiate Microcode actions.
- Add the Sequential Access Logical Block Protection support bit,
since we need that in the sa(4) driver. (For modifications
that will come later.)
- Add definitions for the various Multi I_T Nexus Microcode
Download modes.
sys/cam/ctl/ctl.c:
As of SPC-4, a single report of "REPORTED LUNS DATA HAS CHANGED"
is to be given per I_T nexus. Once it is reported, the unit
attention condition should be cleared for all LUNS attached to
an I_T nexus.
Previously that only happened when a REPORT LUNS command was
processed.
This behavior may be different (according to SAM-5) when the
UA_INTLCK_CTRL bits are non-zero in the control mode page but
CTL does not currently support that.
So, in view of the spec, whenever we report a LUN inventory
change unit attention, clear it on all LUNs for that
particular I_T nexus.
Add a new function, ctl_clear_ua() that will clear a unit
attention on all LUNs for the given I_T nexus.
One field in the extended inquiry data that we could potentially
report at some point is the maximum supported sense data length.
To do that, we would the SIM to report (via path inquiry
perhaps) how much sense data it is able to send.
Add comments to explain some of the bits that are set in the
Extended Inquiry VPD page.
Add a few comments to make it more clear which functions handle
various VPD pages.
Sponsored by: Spectra Logic
MFC after: 1 week
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ctl/ctl.c | 74 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_all.h | 20 |
2 files changed, 89 insertions, 5 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 3565177..fb66b45 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -31,7 +31,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl.c#8 $ + * $Id$ */ /* * CAM Target Layer, a SCSI device emulation subsystem. @@ -446,6 +446,8 @@ static int ctl_scsiio_lun_check(struct ctl_lun *lun, struct ctl_scsiio *ctsio); //static int ctl_check_rtr(union ctl_io *pending_io, struct ctl_softc *softc); static void ctl_failover(void); +static void ctl_clear_ua(struct ctl_softc *ctl_softc, uint32_t initidx, + ctl_ua_type ua_type); static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio); static int ctl_scsiio(struct ctl_scsiio *ctsio); @@ -9433,6 +9435,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio) { struct scsi_request_sense *cdb; struct scsi_sense_data *sense_ptr; + struct ctl_softc *ctl_softc; struct ctl_lun *lun; uint32_t initidx; int have_error; @@ -9441,6 +9444,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio) cdb = (struct scsi_request_sense *)ctsio->cdb; + ctl_softc = control_softc; lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; CTL_DEBUG_PRINT(("ctl_request_sense\n")); @@ -9526,6 +9530,14 @@ ctl_request_sense(struct ctl_scsiio *ctsio) ua_type = ctl_build_ua(lun, initidx, sense_ptr, sense_format); if (ua_type != CTL_UA_NONE) have_error = 1; + if (ua_type == CTL_UA_LUN_CHANGE) { + mtx_unlock(&lun->lun_lock); + mtx_lock(&ctl_softc->ctl_lock); + ctl_clear_ua(ctl_softc, initidx, ua_type); + mtx_unlock(&ctl_softc->ctl_lock); + mtx_lock(&lun->lun_lock); + } + } mtx_unlock(&lun->lun_lock); @@ -9593,6 +9605,9 @@ ctl_cmddt_inquiry(struct ctl_scsiio *ctsio) } #endif +/* + * SCSI VPD page 0x00, the Supported VPD Pages page. + */ static int ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len) { @@ -9665,6 +9680,9 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len) return (CTL_RETVAL_COMPLETE); } +/* + * SCSI VPD page 0x80, the Unit Serial Number page. + */ static int ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len) { @@ -9721,6 +9739,9 @@ ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len) } +/* + * SCSI VPD page 0x86, the Extended INQUIRY Data page. + */ static int ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len) { @@ -9758,10 +9779,33 @@ ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len) else eid_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT; eid_ptr->page_code = SVPD_EXTENDED_INQUIRY_DATA; - eid_ptr->page_length = data_len - 4; + scsi_ulto2b(data_len - 4, eid_ptr->page_length); + /* + * We support head of queue, ordered and simple tags. + */ eid_ptr->flags2 = SVPD_EID_HEADSUP | SVPD_EID_ORDSUP | SVPD_EID_SIMPSUP; + /* + * Volatile cache supported. + */ eid_ptr->flags3 = SVPD_EID_V_SUP; + /* + * This means that we clear the REPORTED LUNS DATA HAS CHANGED unit + * attention for a particular IT nexus on all LUNs once we report + * it to that nexus once. This bit is required as of SPC-4. + */ + eid_ptr->flags4 = SVPD_EID_LUICLT; + + /* + * XXX KDM in order to correctly answer this, we would need + * information from the SIM to determine how much sense data it + * can send. So this would really be a path inquiry field, most + * likely. This can be set to a maximum of 252 according to SPC-4, + * but the hardware may or may not be able to support that much. + * 0 just means that the maximum sense data length is not reported. + */ + eid_ptr->max_sense_length = 0; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; @@ -9820,6 +9864,9 @@ ctl_inquiry_evpd_mpp(struct ctl_scsiio *ctsio, int alloc_len) return (CTL_RETVAL_COMPLETE); } +/* + * SCSI VPD page 0x83, the Device Identification page. + */ static int ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len) { @@ -10235,6 +10282,9 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len) return (CTL_RETVAL_COMPLETE); } +/* + * INQUIRY with the EVPD bit set. + */ static int ctl_inquiry_evpd(struct ctl_scsiio *ctsio) { @@ -10299,6 +10349,9 @@ err: return (retval); } +/* + * Standard INQUIRY data. + */ static int ctl_inquiry_std(struct ctl_scsiio *ctsio) { @@ -11468,6 +11521,23 @@ ctl_failover(void) mtx_unlock(&softc->ctl_lock); } +static void +ctl_clear_ua(struct ctl_softc *ctl_softc, uint32_t initidx, + ctl_ua_type ua_type) +{ + struct ctl_lun *lun; + ctl_ua_type *pu; + + mtx_assert(&ctl_softc->ctl_lock, MA_OWNED); + + STAILQ_FOREACH(lun, &ctl_softc->lun_list, links) { + mtx_lock(&lun->lun_lock); + pu = lun->pending_ua[initidx / CTL_MAX_INIT_PER_PORT]; + pu[initidx % CTL_MAX_INIT_PER_PORT] &= ~ua_type; + mtx_unlock(&lun->lun_lock); + } +} + static int ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio) { diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index d536a74..dfd0db0 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -2112,10 +2112,15 @@ struct scsi_vpd_extended_inquiry_data uint8_t device; uint8_t page_code; #define SVPD_EXTENDED_INQUIRY_DATA 0x86 - uint8_t reserved; - uint8_t page_length; + uint8_t page_length[2]; uint8_t flags1; -#define SVPD_EID_AM 0xC0 + + /* These values are for direct access devices */ +#define SVPD_EID_AM_MASK 0xC0 +#define SVPD_EID_AM_DEFER 0x80 +#define SVPD_EID_AM_IMMED 0x40 +#define SVPD_EID_AM_UNDEFINED 0x00 +#define SVPD_EID_AM_RESERVED 0xc0 #define SVPD_EID_SPT 0x38 #define SVPD_EID_SPT_1 0x00 #define SVPD_EID_SPT_12 0x08 @@ -2124,9 +2129,14 @@ struct scsi_vpd_extended_inquiry_data #define SVPD_EID_SPT_3 0x20 #define SVPD_EID_SPT_23 0x28 #define SVPD_EID_SPT_123 0x38 + + /* These values are for sequential access devices */ +#define SVPD_EID_SA_SPT_LBP 0x08 + #define SVPD_EID_GRD_CHK 0x04 #define SVPD_EID_APP_CHK 0x02 #define SVPD_EID_REF_CHK 0x01 + uint8_t flags2; #define SVPD_EID_UASK_SUP 0x20 #define SVPD_EID_GROUP_SUP 0x10 @@ -2147,6 +2157,10 @@ struct scsi_vpd_extended_inquiry_data #define SVPD_EID_CBCS 0x01 uint8_t flags6; #define SVPD_EID_MULTI_I_T_FW 0x0F +#define SVPD_EID_MC_VENDOR_SPEC 0x00 +#define SVPD_EID_MC_MODE_1 0x01 +#define SVPD_EID_MC_MODE_2 0x02 +#define SVPD_EID_MC_MODE_3 0x03 uint8_t est[2]; uint8_t flags7; #define SVPD_EID_POA_SUP 0x80 |