scsi_periph: implemented VPD inquiry.
* declared block limits and logical block provisioning structs. * based on SPC-4 and SBC-4 standards.
This commit is contained in:
parent
91810926dc
commit
6fd00f80e8
@ -309,10 +309,28 @@ enum scsi_device_type {
|
||||
};
|
||||
|
||||
|
||||
// vital product data: pages
|
||||
#define SCSI_PAGE_SUPPORTED_VPD 0x00 /* Supported VPD Pages */
|
||||
#define SCSI_PAGE_USN 0x80 /* Unit serial number */
|
||||
#define SCSI_PAGE_BLOCK_LIMITS 0xb0 /* Block limits */
|
||||
#define SCSI_PAGE_BLOCK_DEVICE_CHARS 0xb1 /* Block device characteristics */
|
||||
#define SCSI_PAGE_LB_PROVISIONING 0xb2 /* Logical block provisioning */
|
||||
#define SCSI_PAGE_REFERRALS 0xb3 /* Referrals */
|
||||
|
||||
// vital product data: supported pages
|
||||
typedef struct scsi_page_list {
|
||||
LBITFIELD8_2(
|
||||
device_type : 5,
|
||||
device_qualifier : 3
|
||||
);
|
||||
uint8 page_code;
|
||||
uint8 _res2;
|
||||
|
||||
uint8 page_length;
|
||||
uint8 pages[1]; // size according to page_length
|
||||
} _PACKED scsi_page_list;
|
||||
|
||||
// vital product data: unit serial number page
|
||||
|
||||
#define SCSI_PAGE_USN 0x80
|
||||
|
||||
typedef struct scsi_page_usn {
|
||||
LBITFIELD8_2(
|
||||
device_type : 5,
|
||||
@ -325,6 +343,57 @@ typedef struct scsi_page_usn {
|
||||
char psn[1]; // size according to page_length
|
||||
} _PACKED scsi_page_usn;
|
||||
|
||||
typedef struct scsi_page_block_limits {
|
||||
LBITFIELD8_2(
|
||||
device_type : 5,
|
||||
device_qualifier : 3
|
||||
);
|
||||
uint8 page_code;
|
||||
|
||||
uint16 _page_length;
|
||||
LBITFIELD8_2(
|
||||
wsnz : 1,
|
||||
_res4_1 : 7
|
||||
);
|
||||
uint8 max_cmp_write_length;
|
||||
uint16 opt_transfer_length_grain;
|
||||
uint32 max_transfer_length;
|
||||
uint32 opt_transfer_length;
|
||||
uint32 max_prefetch_length;
|
||||
uint32 max_unmap_lba_count;
|
||||
uint32 max_unmap_blk_count;
|
||||
uint32 opt_unmap_grain;
|
||||
uint32 unmap_grain_align;
|
||||
uint64 max_write_same_length;
|
||||
uint8 _res44[20];
|
||||
} _PACKED scsi_page_block_limits;
|
||||
|
||||
typedef struct scsi_page_lb_provisioning {
|
||||
LBITFIELD8_2(
|
||||
device_type : 5,
|
||||
device_qualifier : 3
|
||||
);
|
||||
uint8 page_code;
|
||||
|
||||
uint16 page_length;
|
||||
uint8 threshold_exponent;
|
||||
LBITFIELD8_7(
|
||||
dp : 1,
|
||||
anc_sup : 1,
|
||||
lbprz : 1,
|
||||
_res5_3 : 2,
|
||||
lbpws10 : 1,
|
||||
lbpws : 1,
|
||||
lbpu : 1
|
||||
);
|
||||
LBITFIELD8_2(
|
||||
provisioning_type : 3,
|
||||
_res6_3 : 5
|
||||
);
|
||||
uint8 _res7;
|
||||
} _PACKED scsi_page_lb_provisioning;
|
||||
|
||||
|
||||
// READ CAPACITY (10)
|
||||
|
||||
typedef struct scsi_cmd_read_capacity {
|
||||
|
@ -31,6 +31,70 @@ inquiry(scsi_periph_device_info *device, scsi_inquiry *inquiry)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
vpd_page_inquiry(scsi_periph_device_info *device, uint8 page, void* data,
|
||||
uint16 length)
|
||||
{
|
||||
SHOW_FLOW0(0, "");
|
||||
|
||||
scsi_ccb* ccb = device->scsi->alloc_ccb(device->scsi_device);
|
||||
if (ccb == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)ccb->cdb;
|
||||
memset(cmd, 0, sizeof(scsi_cmd_inquiry));
|
||||
cmd->opcode = SCSI_OP_INQUIRY;
|
||||
cmd->lun = ccb->target_lun;
|
||||
cmd->evpd = 1;
|
||||
cmd->page_code = page;
|
||||
cmd->allocation_length = length;
|
||||
|
||||
ccb->flags = SCSI_DIR_IN;
|
||||
ccb->cdb_length = sizeof(scsi_cmd_inquiry);
|
||||
|
||||
ccb->sort = -1;
|
||||
ccb->timeout = device->std_timeout;
|
||||
|
||||
ccb->data = (uint8*)data;
|
||||
ccb->sg_list = NULL;
|
||||
ccb->data_length = length;
|
||||
|
||||
status_t status = periph_safe_exec(device, ccb);
|
||||
|
||||
device->scsi->free_ccb(ccb);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
vpd_page_get(scsi_periph_device_info *device, uint8 page, void* data,
|
||||
uint16 length)
|
||||
{
|
||||
SHOW_FLOW0(0, "");
|
||||
|
||||
status_t status = vpd_page_inquiry(device, 0, data, length);
|
||||
if (status != B_OK)
|
||||
return status; // or B_BAD_VALUE
|
||||
|
||||
if (page == 0)
|
||||
return B_OK;
|
||||
|
||||
scsi_page_list *list_data = (scsi_page_list*)data;
|
||||
int page_length = min_c(list_data->page_length, length -
|
||||
offsetof(scsi_page_list, pages));
|
||||
for (int i = 0; i < page_length; i++) {
|
||||
if (list_data->pages[i] == page)
|
||||
return vpd_page_inquiry(device, page, data, length);
|
||||
}
|
||||
|
||||
// TODO buffer might be not big enough
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static status_t
|
||||
prevent_allow(scsi_periph_device_info *device, bool prevent)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user