Add support for BLOCK LIMITS VPD page

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
Ronnie Sahlberg
2012-04-20 17:57:40 +10:00
parent 86bf89aabf
commit d71a9d4f95
3 changed files with 72 additions and 6 deletions

View File

@@ -293,6 +293,7 @@ enum scsi_inquiry_pagecode {
SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES = 0x00,
SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER = 0x80,
SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION = 0x83,
SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS = 0xB0,
SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS = 0xB1,
SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING = 0xB2
};
@@ -308,6 +309,25 @@ struct scsi_inquiry_supported_pages {
unsigned char *pages;
};
struct scsi_inquiry_block_limits {
enum scsi_inquiry_peripheral_qualifier periperal_qualifier;
enum scsi_inquiry_peripheral_device_type periperal_device_type;
enum scsi_inquiry_pagecode pagecode;
int wsnz; /* write same no zero */
uint8_t max_cmp; /* maximum_compare_and_write_length */
uint16_t opt_gran; /* optimal_transfer_length_granularity */
uint32_t max_xfer_len; /* maximum_transfer_length */
uint32_t opt_xfer_len; /* optimal_transfer_length */
uint32_t max_prefetch; /* maximum_prefetched_xdread_xdwrite_transfer_length */
uint32_t max_unmap; /* maximum_unmap_lba_count */
uint32_t max_unmap_bdc; /* maximum_unmap_block_descriptor_count */
uint32_t opt_unmap_gran; /* optimal_unmap_granularity */
int ugavalid;
uint32_t unmap_gran_align; /* unmap_granularity_alignment */
uint64_t max_ws_len; /* maximum_write_same_length */
};
struct scsi_inquiry_block_device_characteristics {
enum scsi_inquiry_peripheral_qualifier periperal_qualifier;
enum scsi_inquiry_peripheral_device_type periperal_device_type;

View File

@@ -371,13 +371,13 @@ scsi_inquiry_datain_getfullsize(struct scsi_task *task)
switch (task->params.inquiry.page_code) {
case SCSI_INQUIRY_PAGECODE_SUPPORTED_VPD_PAGES:
return task->datain.data[3] + 4;
case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
case SCSI_INQUIRY_PAGECODE_UNIT_SERIAL_NUMBER:
return task->datain.data[3] + 4;
case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
return ntohs(*(uint16_t *)&task->datain.data[2]) + 4;
case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
return task->datain.data[3] + 4;
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
case SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING:
return ntohs(*(uint16_t *)&task->datain.data[2]) + 4;
default:
return -1;
}
@@ -522,6 +522,34 @@ scsi_inquiry_datain_unmarshall(struct scsi_task *task)
dptr += dev->designator_length + 4;
}
return inq;
} else if (task->params.inquiry.page_code
== SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS) {
struct scsi_inquiry_block_limits *inq;
inq = scsi_malloc(task,
sizeof(struct scsi_inquiry_block_limits));
if (inq == NULL) {
return NULL;
}
inq->periperal_qualifier = (task->datain.data[0]>>5)&0x07;
inq->periperal_device_type = task->datain.data[0]&0x1f;
inq->pagecode = task->datain.data[1];
inq->wsnz = task->datain.data[4] & 0x01;
inq->max_cmp = task->datain.data[5];
inq->opt_gran = ntohs(*(uint16_t *)&task->datain.data[6]);
inq->max_xfer_len = ntohl(*(uint32_t *)&task->datain.data[8]);
inq->opt_xfer_len = ntohl(*(uint32_t *)&task->datain.data[12]);
inq->max_prefetch = ntohl(*(uint32_t *)&task->datain.data[16]);
inq->max_unmap = ntohl(*(uint32_t *)&task->datain.data[20]);
inq->max_unmap_bdc = ntohl(*(uint32_t *)&task->datain.data[24]);
inq->opt_unmap_gran = ntohl(*(uint32_t *)&task->datain.data[28]);
inq->ugavalid = !!(task->datain.data[32]&0x80);
inq->unmap_gran_align = ntohl(*(uint32_t *)&task->datain.data[32]) & 0x7fffffff;
inq->max_ws_len = ntohl(*(uint32_t *)&task->datain.data[36]);
inq->max_ws_len = (inq->max_ws_len << 32) | ntohl(*(uint32_t *)&task->datain.data[40]);
return inq;
} else if (task->params.inquiry.page_code
== SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS) {
@@ -536,8 +564,7 @@ scsi_inquiry_datain_unmarshall(struct scsi_task *task)
inq->periperal_device_type = task->datain.data[0]&0x1f;
inq->pagecode = task->datain.data[1];
inq->medium_rotation_rate = ntohs(*(uint16_t *)
&task->datain.data[4]);
inq->medium_rotation_rate = ntohs(*(uint16_t *)&task->datain.data[4]);
return inq;
} else if (task->params.inquiry.page_code
== SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING) {

View File

@@ -27,6 +27,22 @@
const char *initiator = "iqn.2010-11.ronnie:iscsi-inq";
void inquiry_block_limits(struct scsi_inquiry_block_limits *inq)
{
printf("wsnz:%d\n", inq->wsnz);
printf("maximum compare and write length:%d\n", inq->max_cmp);
printf("optimal transfer length granularity:%d\n", inq->opt_gran);
printf("maximum transfer length:%d\n", inq->max_xfer_len);
printf("optimal transfer length:%d\n",inq->opt_xfer_len);
printf("maximum prefetch xdread xdwrite transfer length:%d\n", inq->max_prefetch);
printf("maximum unmap lba count:%d\n", inq->max_unmap);
printf("maximum unmap block descriptor count:%d\n", inq->max_unmap_bdc);
printf("optimal unmap granularity:%d\n", inq->opt_unmap_gran);
printf("ugavalid:%d\n", inq->ugavalid);
printf("unmap granularity alignment:%d\n", inq->unmap_gran_align);
printf("maximum write same length:%d\n", (int)inq->max_ws_len);
}
void inquiry_logical_block_provisioning(struct scsi_inquiry_logical_block_provisioning *inq)
{
printf("Threshold Exponent:%d\n", inq->threshold_exponent);
@@ -151,6 +167,9 @@ void do_inquiry(struct iscsi_context *iscsi, int lun, int evpd, int pc)
case SCSI_INQUIRY_PAGECODE_DEVICE_IDENTIFICATION:
inquiry_device_identification(inq);
break;
case SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS:
inquiry_block_limits(inq);
break;
case SCSI_INQUIRY_PAGECODE_BLOCK_DEVICE_CHARACTERISTICS:
inquiry_block_device_characteristics(inq);
break;