diff --git a/include/iscsi.h b/include/iscsi.h index 3616b0a..0fa7bea 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -824,10 +824,19 @@ iscsi_modeselect6_task(struct iscsi_context *iscsi, int lun, int pf, int sp, struct scsi_mode_page *mp, iscsi_command_cb cb, void *private_data); EXTERN struct scsi_task * +iscsi_modeselect10_task(struct iscsi_context *iscsi, int lun, + int pf, int sp, struct scsi_mode_page *mp, + iscsi_command_cb cb, void *private_data); +EXTERN struct scsi_task * iscsi_modesense6_task(struct iscsi_context *iscsi, int lun, int dbd, int pc, int page_code, int sub_page_code, unsigned char alloc_len, iscsi_command_cb cb, void *private_data); +EXTERN struct scsi_task * +iscsi_modesense10_task(struct iscsi_context *iscsi, int lun, int llbaa, int dbd, + int pc, int page_code, int sub_page_code, + unsigned char alloc_len, iscsi_command_cb cb, + void *private_data); struct unmap_list { uint64_t lba; @@ -880,11 +889,20 @@ EXTERN struct scsi_task * iscsi_modeselect6_sync(struct iscsi_context *iscsi, int lun, int pf, int sp, struct scsi_mode_page *mp); +EXTERN struct scsi_task * +iscsi_modeselect10_sync(struct iscsi_context *iscsi, int lun, + int pf, int sp, struct scsi_mode_page *mp); + EXTERN struct scsi_task * iscsi_modesense6_sync(struct iscsi_context *iscsi, int lun, int dbd, int pc, int page_code, int sub_page_code, unsigned char alloc_len); +EXTERN struct scsi_task * +iscsi_modesense10_sync(struct iscsi_context *iscsi, int lun, int llbaa, int dbd, + int pc, int page_code, int sub_page_code, + unsigned char alloc_len); + EXTERN struct scsi_task * iscsi_reportluns_sync(struct iscsi_context *iscsi, int report_type, int alloc_len); diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index cb65b7b..4655443 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -50,6 +50,8 @@ enum scsi_opcode { SCSI_OPCODE_UNMAP = 0x42, SCSI_OPCODE_READTOC = 0x43, SCSI_OPCODE_SANITIZE = 0x48, + SCSI_OPCODE_MODESELECT10 = 0x55, + SCSI_OPCODE_MODESENSE10 = 0x5A, SCSI_OPCODE_PERSISTENT_RESERVE_IN = 0x5E, SCSI_OPCODE_PERSISTENT_RESERVE_OUT = 0x5F, SCSI_OPCODE_READ16 = 0x88, @@ -626,7 +628,7 @@ struct scsi_inquiry_device_identification { }; /* - * MODESENSE6 + * MODESENSE */ enum scsi_modesense_page_control { SCSI_MODESENSE_PC_CURRENT = 0x00, @@ -762,9 +764,17 @@ EXTERN struct scsi_task *scsi_cdb_modesense6(int dbd, int sub_page_code, unsigned char alloc_len); +EXTERN struct scsi_task *scsi_cdb_modesense10(int llbaa, int dbd, + enum scsi_modesense_page_control pc, + enum scsi_modesense_page_code page_code, + int sub_page_code, + unsigned char alloc_len); + EXTERN struct scsi_task *scsi_cdb_modeselect6(int pf, int sp, int param_len); +EXTERN struct scsi_task *scsi_cdb_modeselect10(int pf, int sp, int param_len); + EXTERN struct scsi_data * scsi_modesense_dataout_marshall(struct scsi_task *task, struct scsi_mode_page *mp, diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 096d2b7..1f0636c 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -1241,6 +1241,45 @@ iscsi_modeselect6_task(struct iscsi_context *iscsi, int lun, return task; } +struct scsi_task * +iscsi_modeselect10_task(struct iscsi_context *iscsi, int lun, + int pf, int sp, struct scsi_mode_page *mp, + iscsi_command_cb cb, void *private_data) +{ + struct scsi_task *task; + struct scsi_data *data; + struct iscsi_data d; + + task = scsi_cdb_modeselect10(pf, sp, 255); + if (task == NULL) { + iscsi_set_error(iscsi, "Out-of-memory: Failed to create " + "modeselect10 cdb."); + return NULL; + } + data = scsi_modesense_dataout_marshall(task, mp, 0); + if (data == NULL) { + iscsi_set_error(iscsi, "Error: Failed to marshall " + "modesense dataout buffer."); + scsi_free_scsi_task(task); + return NULL; + } + + d.data = data->data; + d.size = data->size; + task->cdb[7] = data->size >> 8; + task->cdb[8] = data->size & 0xff; + + task->expxferlen = data->size; + + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + &d, private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; + } + + return task; +} + struct scsi_task * iscsi_modesense6_task(struct iscsi_context *iscsi, int lun, int dbd, int pc, int page_code, int sub_page_code, @@ -1265,6 +1304,31 @@ iscsi_modesense6_task(struct iscsi_context *iscsi, int lun, int dbd, int pc, return task; } +struct scsi_task * +iscsi_modesense10_task(struct iscsi_context *iscsi, int lun, + int llbaa, int dbd, int pc, + int page_code, int sub_page_code, + unsigned char alloc_len, + iscsi_command_cb cb, void *private_data) +{ + struct scsi_task *task; + + task = scsi_cdb_modesense10(llbaa, dbd, pc, page_code, sub_page_code, + alloc_len); + if (task == NULL) { + iscsi_set_error(iscsi, "Out-of-memory: Failed to create " + "modesense10 cdb."); + return NULL; + } + if (iscsi_scsi_command_async(iscsi, lun, task, cb, + NULL, private_data) != 0) { + scsi_free_scsi_task(task); + return NULL; + } + + return task; +} + struct scsi_task * iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun, int immed, int pcm, int pc, diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 209c73b..72c0d20 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -25,8 +25,12 @@ iscsi_logout_async iscsi_logout_sync iscsi_modeselect6_sync iscsi_modeselect6_task +iscsi_modeselect10_sync +iscsi_modeselect10_task iscsi_modesense6_sync iscsi_modesense6_task +iscsi_modesense10_sync +iscsi_modesense10_task iscsi_nop_out_async iscsi_parse_full_url iscsi_parse_portal_url @@ -154,7 +158,9 @@ scsi_association_to_str scsi_cdb_inquiry scsi_cdb_get_lba_status scsi_cdb_modeselect6 +scsi_cdb_modeselect10 scsi_cdb_modesense6 +scsi_cdb_modesense10 scsi_cdb_persistent_reserve_in scsi_cdb_persistent_reserve_out scsi_cdb_prefetch10 diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index fb4d57c..f0ca8cd 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -23,8 +23,12 @@ iscsi_logout_async iscsi_logout_sync iscsi_modeselect6_sync iscsi_modeselect6_task +iscsi_modeselect10_sync +iscsi_modeselect10_task iscsi_modesense6_sync iscsi_modesense6_task +iscsi_modesense10_sync +iscsi_modesense10_task iscsi_nop_out_async iscsi_parse_full_url iscsi_parse_portal_url @@ -152,7 +156,9 @@ scsi_association_to_str scsi_cdb_inquiry scsi_cdb_get_lba_status scsi_cdb_modeselect6 +scsi_cdb_modeselect10 scsi_cdb_modesense6 +scsi_cdb_modesense10 scsi_cdb_persistent_reserve_in scsi_cdb_persistent_reserve_out scsi_cdb_prefetch10 diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index d61576a..32aa6c0 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -2181,6 +2181,46 @@ scsi_cdb_modesense6(int dbd, enum scsi_modesense_page_control pc, return task; } +/* + * MODESENSE10 + */ +struct scsi_task * +scsi_cdb_modesense10(int llbaa, int dbd, enum scsi_modesense_page_control pc, + enum scsi_modesense_page_code page_code, + int sub_page_code, unsigned char alloc_len) +{ + struct scsi_task *task; + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + return NULL; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_MODESENSE10; + + if (llbaa) { + task->cdb[1] |= 0x10; + } + if (dbd) { + task->cdb[1] |= 0x08; + } + task->cdb[2] = pc<<6 | page_code; + task->cdb[3] = sub_page_code; + + scsi_set_uint16(&task->cdb[7], alloc_len); + + task->cdb_size = 10; + if (alloc_len != 0) { + task->xfer_dir = SCSI_XFER_READ; + } else { + task->xfer_dir = SCSI_XFER_NONE; + } + task->expxferlen = alloc_len; + + return task; +} + /* * MODESELECT6 */ @@ -2216,6 +2256,42 @@ scsi_cdb_modeselect6(int pf, int sp, int param_len) return task; } +/* + * MODESELECT10 + */ +struct scsi_task * +scsi_cdb_modeselect10(int pf, int sp, int param_len) +{ + struct scsi_task *task; + + task = malloc(sizeof(struct scsi_task)); + if (task == NULL) { + return NULL; + } + + memset(task, 0, sizeof(struct scsi_task)); + task->cdb[0] = SCSI_OPCODE_MODESELECT10; + + if (pf) { + task->cdb[1] |= 0x10; + } + if (sp) { + task->cdb[1] |= 0x01; + } + + scsi_set_uint16(&task->cdb[7], param_len); + + task->cdb_size = 10; + if (param_len != 0) { + task->xfer_dir = SCSI_XFER_WRITE; + } else { + task->xfer_dir = SCSI_XFER_NONE; + } + task->expxferlen = param_len; + + return task; +} + struct scsi_mode_page * scsi_modesense_get_page(struct scsi_mode_sense *ms, enum scsi_modesense_page_code page_code, @@ -3062,6 +3138,8 @@ scsi_datain_unmarshall(struct scsi_task *task) return scsi_inquiry_datain_unmarshall(task); case SCSI_OPCODE_MODESENSE6: return scsi_modesense_datain_unmarshall(task, 1); + case SCSI_OPCODE_MODESENSE10: + return scsi_modesense_datain_unmarshall(task, 0); case SCSI_OPCODE_READCAPACITY10: return scsi_readcapacity10_datain_unmarshall(task); case SCSI_OPCODE_SYNCHRONIZECACHE10: diff --git a/lib/sync.c b/lib/sync.c index c20c9a5..2e9a39e 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -1176,6 +1176,26 @@ iscsi_modeselect6_sync(struct iscsi_context *iscsi, int lun, return state.task; } +struct scsi_task * +iscsi_modeselect10_sync(struct iscsi_context *iscsi, int lun, + int pf, int sp, struct scsi_mode_page *mp) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_modeselect10_task(iscsi, lun, pf, sp, mp, + scsi_sync_cb, &state) == NULL) { + iscsi_set_error(iscsi, + "Failed to send MODE_SELECT10 command"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.task; +} + struct scsi_task * iscsi_modesense6_sync(struct iscsi_context *iscsi, int lun, int dbd, int pc, int page_code, int sub_page_code, @@ -1196,3 +1216,25 @@ iscsi_modesense6_sync(struct iscsi_context *iscsi, int lun, int dbd, return state.task; } + +struct scsi_task * +iscsi_modesense10_sync(struct iscsi_context *iscsi, int lun, int llbaa, int dbd, + int pc, int page_code, int sub_page_code, + unsigned char alloc_len) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_modesense10_task(iscsi, lun, llbaa, dbd, pc, + page_code, sub_page_code, alloc_len, + scsi_sync_cb, &state) == NULL) { + iscsi_set_error(iscsi, + "Failed to send MODE_SENSE10 command"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.task; +} diff --git a/src/iscsi-swp.c b/src/iscsi-swp.c index 44607e4..c98ee6c 100644 --- a/src/iscsi-swp.c +++ b/src/iscsi-swp.c @@ -177,18 +177,18 @@ int main(int argc, char *argv[]) } - sense_task = iscsi_modesense6_sync(iscsi, iscsi_url->lun, - 1, SCSI_MODESENSE_PC_CURRENT, + sense_task = iscsi_modesense10_sync(iscsi, iscsi_url->lun, + 0, 1, SCSI_MODESENSE_PC_CURRENT, SCSI_MODESENSE_PAGECODE_CONTROL, 0, 255); if (sense_task == NULL) { - printf("Failed to send MODE_SENSE6 command: %s\n", + printf("Failed to send MODE_SENSE10 command: %s\n", iscsi_get_error(iscsi)); ret = 10; goto finished; } if (sense_task->status != SCSI_STATUS_GOOD) { - printf("MODE_SENSE6 failed: %s\n", + printf("MODE_SENSE10 failed: %s\n", iscsi_get_error(iscsi)); ret = 10; goto finished; @@ -220,16 +220,16 @@ int main(int argc, char *argv[]) } printf("Turning SWP %s\n", (swp == 1) ? "ON" : "OFF"); - select_task = iscsi_modeselect6_sync(iscsi, iscsi_url->lun, + select_task = iscsi_modeselect10_sync(iscsi, iscsi_url->lun, 1, 0, mp); if (select_task == NULL) { - printf("Failed to send MODE_SELECT6 command: %s\n", + printf("Failed to send MODE_SELECT10 command: %s\n", iscsi_get_error(iscsi)); ret = 10; goto finished; } if (select_task->status != SCSI_STATUS_GOOD) { - printf("MODE_SELECT6 failed: %s\n", + printf("MODE_SELECT10 failed: %s\n", iscsi_get_error(iscsi)); ret = 10; goto finished;