From b1da0a9868d5e5efa3ca0cd51101285b30e81551 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 26 Apr 2013 15:53:22 +0000 Subject: [PATCH] Added the ability to send ATA identify and Data Set Management (DSM) TRIM commands to an ATA device attached via a SCSI control. sys/cam/scsi/scsi_all.c: - Added scsi_ata_identify, scsi_ata_trim Which use ATA Pass-Through to send commands to the attached disk. sys/cam/scsi/scsi_all.h: - Added defines for all missing ATA Pass-Through commands values. - Added scsi_ata_identify, scsi_ata_trim methods used in ATA TRIM support. - Added scsi_vpd_logical_block_prov structure used when querying for the supported sizes UNMAP commands. - Added scsi_vpd_block_limits structure used when querying for the supported sizes of the UNMAP command. Reviewed by: mav Approved by: pjd (mentor) MFC after: 2 weeks --- sys/cam/scsi/scsi_all.c | 51 +++++++++++++++++++++++++++++++ sys/cam/scsi/scsi_all.h | 67 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index b28c29df181e..e206edf136dc 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -5852,6 +5852,57 @@ scsi_write_same(struct ccb_scsiio *csio, u_int32_t retries, timeout); } +void +scsi_ata_identify(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t *data_ptr, + u_int16_t dxfer_len, u_int8_t sense_len, + u_int32_t timeout) +{ + scsi_ata_pass_16(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_IN, + tag_action, + /*protocol*/AP_PROTO_PIO_IN, + /*ata_flags*/AP_FLAG_TDIR_FROM_DEV| + AP_FLAG_BYT_BLOK_BYTES|AP_FLAG_TLEN_SECT_CNT, + /*features*/0, + /*sector_count*/dxfer_len, + /*lba*/0, + /*command*/ATA_ATA_IDENTIFY, + /*control*/0, + data_ptr, + dxfer_len, + sense_len, + timeout); +} + +void +scsi_ata_trim(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int16_t block_count, + u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, + u_int32_t timeout) +{ + scsi_ata_pass_16(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_OUT, + tag_action, + /*protocol*/AP_EXTEND|AP_PROTO_DMA, + /*ata_flags*/AP_FLAG_TLEN_SECT_CNT|AP_FLAG_BYT_BLOK_BLOCKS, + /*features*/ATA_DSM_TRIM, + /*sector_count*/block_count, + /*lba*/0, + /*command*/ATA_DATA_SET_MANAGEMENT, + /*control*/0, + data_ptr, + dxfer_len, + sense_len, + timeout); +} + void scsi_ata_pass_16(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index 0b108ca55fdd..d2872a058e40 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -1429,6 +1429,61 @@ struct scsi_diag_page { uint8_t params[0]; }; +/* + * Logical Block Provisioning VPD Page based on + * T10/1799-D Revision 31 + */ +struct scsi_vpd_logical_block_prov +{ + u_int8_t device; + u_int8_t page_code; +#define SVPD_LBP 0xB2 + u_int8_t page_length[2]; +#define SVPD_LBP_PL_BASIC 0x04 + u_int8_t threshold_exponent; + u_int8_t flags; +#define SVPD_LBP_UNMAP 0x80 +#define SVPD_LBP_WS16 0x40 +#define SVPD_LBP_WS10 0x20 +#define SVPD_LBP_RZ 0x04 +#define SVPD_LBP_ANC_SUP 0x02 +#define SVPD_LBP_DP 0x01 + u_int8_t prov_type; +#define SVPD_LBP_RESOURCE 0x01 +#define SVPD_LBP_THIN 0x02 + u_int8_t reserved; + /* + * Provisioning Group Descriptor can be here if SVPD_LBP_DP is set + * Its size can be determined from page_length - 4 + */ +}; + +/* + * Block Limits VDP Page based on + * T10/1799-D Revision 31 + */ +struct scsi_vpd_block_limits +{ + u_int8_t device; + u_int8_t page_code; +#define SVPD_BLOCK_LIMITS 0xB0 + u_int8_t page_length[2]; +#define SVPD_BL_PL_BASIC 0x10 +#define SVPD_BL_PL_TP 0x3C + u_int8_t reserved1; + u_int8_t max_cmp_write_len; + u_int8_t opt_txfer_len_grain[2]; + u_int8_t max_txfer_len[4]; + u_int8_t opt_txfer_len[4]; + u_int8_t max_prefetch[4]; + u_int8_t max_unmap_lba_cnt[4]; + u_int8_t max_unmap_blk_cnt[4]; + u_int8_t opt_unmap_grain[4]; + u_int8_t unmap_grain_align[4]; + u_int8_t max_write_same_length[8]; + u_int8_t reserved2[20]; +}; + struct scsi_read_capacity { u_int8_t opcode; @@ -2396,6 +2451,18 @@ void scsi_write_same(struct ccb_scsiio *csio, u_int32_t retries, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout); +void scsi_ata_identify(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t *data_ptr, + u_int16_t dxfer_len, u_int8_t sense_len, + u_int32_t timeout); + +void scsi_ata_trim(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int16_t block_count, + u_int8_t *data_ptr, u_int16_t dxfer_len, + u_int8_t sense_len, u_int32_t timeout); + void scsi_ata_pass_16(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int8_t tag_action,