From 890471c8ccafc27ee51638c07eaf3cafe3f44a63 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 20 Nov 2012 19:00:55 -0800 Subject: [PATCH] Add support to unmarshall a CDB into a structure and update iscsi-dd Add two new helper functions scsi_get_uint32() and scsi_get_uint16() --- examples/iscsi-dd.c | 8 ++++++- include/scsi-lowlevel.h | 13 +++++++++++ lib/libiscsi.def | 1 + lib/libiscsi.syms | 1 + lib/scsi-lowlevel.c | 49 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/examples/iscsi-dd.c b/examples/iscsi-dd.c index 22f7c4c..01eee75 100644 --- a/examples/iscsi-dd.c +++ b/examples/iscsi-dd.c @@ -85,6 +85,7 @@ void read10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, struct client *client = (struct client *)private_data; struct scsi_task *task = command_data; struct write_task *wt; + struct scsi_read10_cdb *read10_cdb; if (status == SCSI_STATUS_CHECK_CONDITION) { printf("Read10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq); @@ -95,9 +96,14 @@ void read10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, wt->rt = task; wt->client = client; + read10_cdb = scsi_cdb_unmarshall(task); + if (read10_cdb == NULL) { + printf("Failed to unmarshall READ10 CDB.\n"); + exit(10); + } if (iscsi_write10_task(client->dst_iscsi, client->dst_lun, - task->params.read10.lba, + read10_cdb->lba, task->datain.data, task->datain.size, client->dst_blocksize, diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 3b28b7a..6d2a086 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -657,8 +657,21 @@ struct scsi_report_supported_op_codes { struct scsi_command_descriptor descriptors[0]; }; +struct scsi_read10_cdb { + enum scsi_opcode opcode; + uint8_t rdprotect; + uint8_t dpo; + uint8_t fua; + uint8_t fua_nv; + uint32_t lba; + uint8_t group; + uint16_t transfer_length; + uint8_t control; +}; + EXTERN int scsi_datain_getfullsize(struct scsi_task *task); EXTERN void *scsi_datain_unmarshall(struct scsi_task *task); +EXTERN void *scsi_cdb_unmarshall(struct scsi_task *task); EXTERN struct scsi_task *scsi_cdb_read6(uint32_t lba, uint32_t xferlen, int blocksize); EXTERN struct scsi_task *scsi_cdb_read10(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number); diff --git a/lib/libiscsi.def b/lib/libiscsi.def index ac8cb11..cbc374b 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -163,6 +163,7 @@ scsi_cdb_writesame16 scsi_codeset_to_str scsi_datain_getfullsize scsi_datain_unmarshall +scsi_cdb_unmarshall scsi_designator_type_to_str scsi_devqualifier_to_str scsi_devtype_to_str diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index ebcbb56..19408a9 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -161,6 +161,7 @@ scsi_cdb_writesame16 scsi_codeset_to_str scsi_datain_getfullsize scsi_datain_unmarshall +scsi_cdb_unmarshall scsi_designator_type_to_str scsi_devqualifier_to_str scsi_devtype_to_str diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 8d06233..a583a2b 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -15,8 +15,8 @@ along with this program; if not, see . */ /* - * would be nice if this could grow into a full blown library for scsi to - * 1, build a CDB + * would be nice if this could grow into a full blown library to + * 1, build and unmarshall a CDB * 2, check how big a complete data-in structure needs to be * 3, unmarshall data-in into a real structure * 4, marshall a real structure into a data-out blob @@ -160,6 +160,18 @@ scsi_sense_ascq_str(int ascq) return value_string_find(ascqs, ascq); } +static uint32_t +scsi_get_uint32(unsigned char *c) +{ + return ntohl(*(uint32_t *)c); +} + +static uint16_t +scsi_get_uint16(unsigned char *c) +{ + return ntohs(*(uint16_t *)c); +} + /* * TESTUNITREADY */ @@ -2298,6 +2310,39 @@ scsi_datain_unmarshall(struct scsi_task *task) } +static struct scsi_read10_cdb * +scsi_read10_cdb_unmarshall(struct scsi_task *task) +{ + struct scsi_read10_cdb *read10; + + read10 = scsi_malloc(task, sizeof(struct scsi_read10_cdb)); + if (read10 == NULL) { + return NULL; + } + + read10->opcode = SCSI_OPCODE_READ10; + read10->rdprotect = (task->cdb[1] >> 5) & 0x7; + read10->dpo = !!(task->cdb[1] & 0x10); + read10->fua = !!(task->cdb[1] & 0x08); + read10->fua_nv = !!(task->cdb[1] & 0x02); + read10->lba = scsi_get_uint32(&task->cdb[2]); + read10->group = task->cdb[6] & 0x1f; + read10->transfer_length = scsi_get_uint16(&task->cdb[7]); + read10->control = task->cdb[9]; + + return read10; +} + +void * +scsi_cdb_unmarshall(struct scsi_task *task) +{ + switch (task->cdb[0]) { + case SCSI_OPCODE_READ10: + return scsi_read10_cdb_unmarshall(task); + } + return NULL; +} + const char * scsi_devtype_to_str(enum scsi_inquiry_peripheral_device_type type) {