From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55672) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dk9KT-0000Yg-9W for qemu-devel@nongnu.org; Tue, 22 Aug 2017 09:34:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dk9KP-0007bV-Cq for qemu-devel@nongnu.org; Tue, 22 Aug 2017 09:34:49 -0400 Sender: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= References: <20170822131832.20191-1-pbonzini@redhat.com> <20170822131832.20191-3-pbonzini@redhat.com> From: =?UTF-8?Q?Philippe_Mathieu-Daud=c3=a9?= Message-ID: <054d7c07-ff2e-159c-32fe-72f42d90021c@amsat.org> Date: Tue, 22 Aug 2017 10:34:32 -0300 MIME-Version: 1.0 In-Reply-To: <20170822131832.20191-3-pbonzini@redhat.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [PATCH 02/10] scsi: move non-emulation specific code to scsi/ List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini , qemu-devel@nongnu.org Cc: famz@redhat.com, qemu-block@nongnu.org On 08/22/2017 10:18 AM, Paolo Bonzini wrote: > There is a bunch of SCSI code that is shared by block/iscsi.c and > hw/scsi, and the introduction of the persistent reservation helper > will add more instances of this. There is also include/block/scsi.h, > which actually is not part of the core block layer. > > Create a directory for this kind of shared code. > > Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé > --- > MAINTAINERS | 7 + > Makefile.objs | 2 +- > hw/scsi/scsi-bus.c | 397 ------------------------------------------------ > hw/scsi/scsi-generic.c | 8 - > include/block/scsi.h | 2 - > include/hw/scsi/scsi.h | 94 +----------- > include/scsi/utils.h | 116 ++++++++++++++ > scsi/Makefile.objs | 1 + > scsi/utils.c | 403 +++++++++++++++++++++++++++++++++++++++++++++++++ > 9 files changed, 529 insertions(+), 501 deletions(-) > create mode 100644 include/scsi/utils.h > create mode 100644 scsi/Makefile.objs > create mode 100644 scsi/utils.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index ccee28b12d..fa6e21cd38 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -1213,6 +1213,13 @@ F: migration/block* > F: include/block/aio.h > T: git git://github.com/stefanha/qemu.git block > > +Block SCSI subsystem > +M: Paolo Bonzini > +L: qemu-block@nongnu.org > +S: Supported > +F: include/scsi/* > +F: scsi/* > + > Block Jobs > M: Jeff Cody > L: qemu-block@nongnu.org > diff --git a/Makefile.objs b/Makefile.objs > index 24a4ea08b8..f68aa3b60d 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -11,7 +11,7 @@ chardev-obj-y = chardev/ > > block-obj-y += nbd/ > block-obj-y += block.o blockjob.o > -block-obj-y += block/ > +block-obj-y += block/ scsi/ > block-obj-y += qemu-io-cmds.o > block-obj-$(CONFIG_REPLICATION) += replication.o > > diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c > index 890f8fcc83..300912d213 100644 > --- a/hw/scsi/scsi-bus.c > +++ b/hw/scsi/scsi-bus.c > @@ -935,36 +935,6 @@ static int ata_passthrough_16_xfer(SCSIDevice *dev, uint8_t *buf) > return xfer * unit; > } > > -uint32_t scsi_data_cdb_xfer(uint8_t *buf) > -{ > - if ((buf[0] >> 5) == 0 && buf[4] == 0) { > - return 256; > - } else { > - return scsi_cdb_xfer(buf); > - } > -} > - > -uint32_t scsi_cdb_xfer(uint8_t *buf) > -{ > - switch (buf[0] >> 5) { > - case 0: > - return buf[4]; > - break; > - case 1: > - case 2: > - return lduw_be_p(&buf[7]); > - break; > - case 4: > - return ldl_be_p(&buf[10]) & 0xffffffffULL; > - break; > - case 5: > - return ldl_be_p(&buf[6]) & 0xffffffffULL; > - break; > - default: > - return -1; > - } > -} > - > static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) > { > cmd->xfer = scsi_cdb_xfer(buf); > @@ -1277,53 +1247,6 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd) > } > } > > -static uint64_t scsi_cmd_lba(SCSICommand *cmd) > -{ > - uint8_t *buf = cmd->buf; > - uint64_t lba; > - > - switch (buf[0] >> 5) { > - case 0: > - lba = ldl_be_p(&buf[0]) & 0x1fffff; > - break; > - case 1: > - case 2: > - case 5: > - lba = ldl_be_p(&buf[2]) & 0xffffffffULL; > - break; > - case 4: > - lba = ldq_be_p(&buf[2]); > - break; > - default: > - lba = -1; > - > - } > - return lba; > -} > - > -int scsi_cdb_length(uint8_t *buf) { > - int cdb_len; > - > - switch (buf[0] >> 5) { > - case 0: > - cdb_len = 6; > - break; > - case 1: > - case 2: > - cdb_len = 10; > - break; > - case 4: > - cdb_len = 16; > - break; > - case 5: > - cdb_len = 12; > - break; > - default: > - cdb_len = -1; > - } > - return cdb_len; > -} > - > int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf) > { > int rc; > @@ -1370,326 +1293,6 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense) > } > } > > -/* > - * Predefined sense codes > - */ > - > -/* No sense data available */ > -const struct SCSISense sense_code_NO_SENSE = { > - .key = NO_SENSE , .asc = 0x00 , .ascq = 0x00 > -}; > - > -/* LUN not ready, Manual intervention required */ > -const struct SCSISense sense_code_LUN_NOT_READY = { > - .key = NOT_READY, .asc = 0x04, .ascq = 0x03 > -}; > - > -/* LUN not ready, Medium not present */ > -const struct SCSISense sense_code_NO_MEDIUM = { > - .key = NOT_READY, .asc = 0x3a, .ascq = 0x00 > -}; > - > -/* LUN not ready, medium removal prevented */ > -const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = { > - .key = NOT_READY, .asc = 0x53, .ascq = 0x02 > -}; > - > -/* Hardware error, internal target failure */ > -const struct SCSISense sense_code_TARGET_FAILURE = { > - .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00 > -}; > - > -/* Illegal request, invalid command operation code */ > -const struct SCSISense sense_code_INVALID_OPCODE = { > - .key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00 > -}; > - > -/* Illegal request, LBA out of range */ > -const struct SCSISense sense_code_LBA_OUT_OF_RANGE = { > - .key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00 > -}; > - > -/* Illegal request, Invalid field in CDB */ > -const struct SCSISense sense_code_INVALID_FIELD = { > - .key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00 > -}; > - > -/* Illegal request, Invalid field in parameter list */ > -const struct SCSISense sense_code_INVALID_PARAM = { > - .key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00 > -}; > - > -/* Illegal request, Parameter list length error */ > -const struct SCSISense sense_code_INVALID_PARAM_LEN = { > - .key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00 > -}; > - > -/* Illegal request, LUN not supported */ > -const struct SCSISense sense_code_LUN_NOT_SUPPORTED = { > - .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00 > -}; > - > -/* Illegal request, Saving parameters not supported */ > -const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = { > - .key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00 > -}; > - > -/* Illegal request, Incompatible medium installed */ > -const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = { > - .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00 > -}; > - > -/* Illegal request, medium removal prevented */ > -const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = { > - .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02 > -}; > - > -/* Illegal request, Invalid Transfer Tag */ > -const struct SCSISense sense_code_INVALID_TAG = { > - .key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01 > -}; > - > -/* Command aborted, I/O process terminated */ > -const struct SCSISense sense_code_IO_ERROR = { > - .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 > -}; > - > -/* Command aborted, I_T Nexus loss occurred */ > -const struct SCSISense sense_code_I_T_NEXUS_LOSS = { > - .key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07 > -}; > - > -/* Command aborted, Logical Unit failure */ > -const struct SCSISense sense_code_LUN_FAILURE = { > - .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01 > -}; > - > -/* Command aborted, Overlapped Commands Attempted */ > -const struct SCSISense sense_code_OVERLAPPED_COMMANDS = { > - .key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00 > -}; > - > -/* Unit attention, Capacity data has changed */ > -const struct SCSISense sense_code_CAPACITY_CHANGED = { > - .key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09 > -}; > - > -/* Unit attention, Power on, reset or bus device reset occurred */ > -const struct SCSISense sense_code_RESET = { > - .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00 > -}; > - > -/* Unit attention, No medium */ > -const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = { > - .key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00 > -}; > - > -/* Unit attention, Medium may have changed */ > -const struct SCSISense sense_code_MEDIUM_CHANGED = { > - .key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00 > -}; > - > -/* Unit attention, Reported LUNs data has changed */ > -const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = { > - .key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e > -}; > - > -/* Unit attention, Device internal reset */ > -const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = { > - .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04 > -}; > - > -/* Data Protection, Write Protected */ > -const struct SCSISense sense_code_WRITE_PROTECTED = { > - .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00 > -}; > - > -/* Data Protection, Space Allocation Failed Write Protect */ > -const struct SCSISense sense_code_SPACE_ALLOC_FAILED = { > - .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07 > -}; > - > -/* > - * scsi_convert_sense > - * > - * Convert between fixed and descriptor sense buffers > - */ > -int scsi_convert_sense(uint8_t *in_buf, int in_len, > - uint8_t *buf, int len, bool fixed) > -{ > - bool fixed_in; > - SCSISense sense; > - if (!fixed && len < 8) { > - return 0; > - } > - > - if (in_len == 0) { > - sense.key = NO_SENSE; > - sense.asc = 0; > - sense.ascq = 0; > - } else { > - fixed_in = (in_buf[0] & 2) == 0; > - > - if (fixed == fixed_in) { > - memcpy(buf, in_buf, MIN(len, in_len)); > - return MIN(len, in_len); > - } > - > - if (fixed_in) { > - sense.key = in_buf[2]; > - sense.asc = in_buf[12]; > - sense.ascq = in_buf[13]; > - } else { > - sense.key = in_buf[1]; > - sense.asc = in_buf[2]; > - sense.ascq = in_buf[3]; > - } > - } > - > - memset(buf, 0, len); > - if (fixed) { > - /* Return fixed format sense buffer */ > - buf[0] = 0x70; > - buf[2] = sense.key; > - buf[7] = 10; > - buf[12] = sense.asc; > - buf[13] = sense.ascq; > - return MIN(len, SCSI_SENSE_LEN); > - } else { > - /* Return descriptor format sense buffer */ > - buf[0] = 0x72; > - buf[1] = sense.key; > - buf[2] = sense.asc; > - buf[3] = sense.ascq; > - return 8; > - } > -} > - > -const char *scsi_command_name(uint8_t cmd) > -{ > - static const char *names[] = { > - [ TEST_UNIT_READY ] = "TEST_UNIT_READY", > - [ REWIND ] = "REWIND", > - [ REQUEST_SENSE ] = "REQUEST_SENSE", > - [ FORMAT_UNIT ] = "FORMAT_UNIT", > - [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS", > - [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS", > - /* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */ > - [ READ_6 ] = "READ_6", > - [ WRITE_6 ] = "WRITE_6", > - [ SET_CAPACITY ] = "SET_CAPACITY", > - [ READ_REVERSE ] = "READ_REVERSE", > - [ WRITE_FILEMARKS ] = "WRITE_FILEMARKS", > - [ SPACE ] = "SPACE", > - [ INQUIRY ] = "INQUIRY", > - [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA", > - [ MAINTENANCE_IN ] = "MAINTENANCE_IN", > - [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT", > - [ MODE_SELECT ] = "MODE_SELECT", > - [ RESERVE ] = "RESERVE", > - [ RELEASE ] = "RELEASE", > - [ COPY ] = "COPY", > - [ ERASE ] = "ERASE", > - [ MODE_SENSE ] = "MODE_SENSE", > - [ START_STOP ] = "START_STOP/LOAD_UNLOAD", > - /* LOAD_UNLOAD and START_STOP use the same operation code */ > - [ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC", > - [ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC", > - [ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL", > - [ READ_CAPACITY_10 ] = "READ_CAPACITY_10", > - [ READ_10 ] = "READ_10", > - [ WRITE_10 ] = "WRITE_10", > - [ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT", > - /* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */ > - [ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10", > - [ VERIFY_10 ] = "VERIFY_10", > - [ SEARCH_HIGH ] = "SEARCH_HIGH", > - [ SEARCH_EQUAL ] = "SEARCH_EQUAL", > - [ SEARCH_LOW ] = "SEARCH_LOW", > - [ SET_LIMITS ] = "SET_LIMITS", > - [ PRE_FETCH ] = "PRE_FETCH/READ_POSITION", > - /* READ_POSITION and PRE_FETCH use the same operation code */ > - [ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE", > - [ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE", > - [ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE", > - /* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */ > - [ MEDIUM_SCAN ] = "MEDIUM_SCAN", > - [ COMPARE ] = "COMPARE", > - [ COPY_VERIFY ] = "COPY_VERIFY", > - [ WRITE_BUFFER ] = "WRITE_BUFFER", > - [ READ_BUFFER ] = "READ_BUFFER", > - [ UPDATE_BLOCK ] = "UPDATE_BLOCK", > - [ READ_LONG_10 ] = "READ_LONG_10", > - [ WRITE_LONG_10 ] = "WRITE_LONG_10", > - [ CHANGE_DEFINITION ] = "CHANGE_DEFINITION", > - [ WRITE_SAME_10 ] = "WRITE_SAME_10", > - [ UNMAP ] = "UNMAP", > - [ READ_TOC ] = "READ_TOC", > - [ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT", > - [ SANITIZE ] = "SANITIZE", > - [ GET_CONFIGURATION ] = "GET_CONFIGURATION", > - [ LOG_SELECT ] = "LOG_SELECT", > - [ LOG_SENSE ] = "LOG_SENSE", > - [ MODE_SELECT_10 ] = "MODE_SELECT_10", > - [ RESERVE_10 ] = "RESERVE_10", > - [ RELEASE_10 ] = "RELEASE_10", > - [ MODE_SENSE_10 ] = "MODE_SENSE_10", > - [ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN", > - [ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT", > - [ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16", > - [ EXTENDED_COPY ] = "EXTENDED_COPY", > - [ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16", > - [ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN", > - [ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT", > - [ READ_16 ] = "READ_16", > - [ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE", > - [ WRITE_16 ] = "WRITE_16", > - [ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16", > - [ VERIFY_16 ] = "VERIFY_16", > - [ PRE_FETCH_16 ] = "PRE_FETCH_16", > - [ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16", > - /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */ > - [ LOCATE_16 ] = "LOCATE_16", > - [ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16", > - /* ERASE_16 and WRITE_SAME_16 use the same operation code */ > - [ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16", > - [ WRITE_LONG_16 ] = "WRITE_LONG_16", > - [ REPORT_LUNS ] = "REPORT_LUNS", > - [ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12", > - [ MOVE_MEDIUM ] = "MOVE_MEDIUM", > - [ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM", > - [ READ_12 ] = "READ_12", > - [ WRITE_12 ] = "WRITE_12", > - [ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE", > - /* ERASE_12 and GET_PERFORMANCE use the same operation code */ > - [ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12", > - [ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12", > - [ VERIFY_12 ] = "VERIFY_12", > - [ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12", > - [ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12", > - [ SEARCH_LOW_12 ] = "SEARCH_LOW_12", > - [ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS", > - [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING", > - /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */ > - [ READ_CD ] = "READ_CD", > - [ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12", > - [ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE", > - [ RESERVE_TRACK ] = "RESERVE_TRACK", > - [ SEND_CUE_SHEET ] = "SEND_CUE_SHEET", > - [ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE", > - [ SET_CD_SPEED ] = "SET_CD_SPEED", > - [ SET_READ_AHEAD ] = "SET_READ_AHEAD", > - [ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE", > - [ MECHANISM_STATUS ] = "MECHANISM_STATUS", > - [ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION", > - [ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION", > - }; > - > - if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL) > - return "*UNKNOWN*"; > - return names[cmd]; > -} > - > SCSIRequest *scsi_req_ref(SCSIRequest *req) > { > assert(req->refcount > 0); > diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c > index 7e1cbab77e..7a8f500934 100644 > --- a/hw/scsi/scsi-generic.c > +++ b/hw/scsi/scsi-generic.c > @@ -36,14 +36,6 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0) > #include > #include "block/scsi.h" > > -#define SG_ERR_DRIVER_TIMEOUT 0x06 > -#define SG_ERR_DRIVER_SENSE 0x08 > - > -#define SG_ERR_DID_OK 0x00 > -#define SG_ERR_DID_NO_CONNECT 0x01 > -#define SG_ERR_DID_BUS_BUSY 0x02 > -#define SG_ERR_DID_TIME_OUT 0x03 > - > #ifndef MAX_UINT > #define MAX_UINT ((unsigned int)-1) > #endif > diff --git a/include/block/scsi.h b/include/block/scsi.h > index cdf0a58a07..a141dd71f8 100644 > --- a/include/block/scsi.h > +++ b/include/block/scsi.h > @@ -150,8 +150,6 @@ > #define READ_CD 0xbe > #define SEND_DVD_STRUCTURE 0xbf > > -const char *scsi_command_name(uint8_t cmd); > - > /* > * SERVICE ACTION IN subcodes > */ > diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h > index 6ef67fb504..23a8ee6a7d 100644 > --- a/include/hw/scsi/scsi.h > +++ b/include/hw/scsi/scsi.h > @@ -4,45 +4,20 @@ > #include "hw/qdev.h" > #include "hw/block/block.h" > #include "sysemu/sysemu.h" > +#include "scsi/utils.h" > #include "qemu/notify.h" > > #define MAX_SCSI_DEVS 255 > > -#define SCSI_CMD_BUF_SIZE 16 > -#define SCSI_SENSE_LEN 18 > -#define SCSI_SENSE_LEN_SCANNER 32 > -#define SCSI_INQUIRY_LEN 36 > - > typedef struct SCSIBus SCSIBus; > typedef struct SCSIBusInfo SCSIBusInfo; > -typedef struct SCSICommand SCSICommand; > typedef struct SCSIDevice SCSIDevice; > typedef struct SCSIRequest SCSIRequest; > typedef struct SCSIReqOps SCSIReqOps; > > -enum SCSIXferMode { > - SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */ > - SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */ > - SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */ > -}; > - > -typedef struct SCSISense { > - uint8_t key; > - uint8_t asc; > - uint8_t ascq; > -} SCSISense; > - > #define SCSI_SENSE_BUF_SIZE_OLD 96 > #define SCSI_SENSE_BUF_SIZE 252 > > -struct SCSICommand { > - uint8_t buf[SCSI_CMD_BUF_SIZE]; > - int len; > - size_t xfer; > - uint64_t lba; > - enum SCSIXferMode mode; > -}; > - > struct SCSIRequest { > SCSIBus *bus; > SCSIDevice *dev; > @@ -180,73 +155,6 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, > void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated); > void scsi_legacy_handle_cmdline(void); > > -/* > - * Predefined sense codes > - */ > - > -/* No sense data available */ > -extern const struct SCSISense sense_code_NO_SENSE; > -/* LUN not ready, Manual intervention required */ > -extern const struct SCSISense sense_code_LUN_NOT_READY; > -/* LUN not ready, Medium not present */ > -extern const struct SCSISense sense_code_NO_MEDIUM; > -/* LUN not ready, medium removal prevented */ > -extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED; > -/* Hardware error, internal target failure */ > -extern const struct SCSISense sense_code_TARGET_FAILURE; > -/* Illegal request, invalid command operation code */ > -extern const struct SCSISense sense_code_INVALID_OPCODE; > -/* Illegal request, LBA out of range */ > -extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE; > -/* Illegal request, Invalid field in CDB */ > -extern const struct SCSISense sense_code_INVALID_FIELD; > -/* Illegal request, Invalid field in parameter list */ > -extern const struct SCSISense sense_code_INVALID_PARAM; > -/* Illegal request, Parameter list length error */ > -extern const struct SCSISense sense_code_INVALID_PARAM_LEN; > -/* Illegal request, LUN not supported */ > -extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED; > -/* Illegal request, Saving parameters not supported */ > -extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED; > -/* Illegal request, Incompatible format */ > -extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT; > -/* Illegal request, medium removal prevented */ > -extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED; > -/* Illegal request, Invalid Transfer Tag */ > -extern const struct SCSISense sense_code_INVALID_TAG; > -/* Command aborted, I/O process terminated */ > -extern const struct SCSISense sense_code_IO_ERROR; > -/* Command aborted, I_T Nexus loss occurred */ > -extern const struct SCSISense sense_code_I_T_NEXUS_LOSS; > -/* Command aborted, Logical Unit failure */ > -extern const struct SCSISense sense_code_LUN_FAILURE; > -/* Command aborted, Overlapped Commands Attempted */ > -extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS; > -/* LUN not ready, Capacity data has changed */ > -extern const struct SCSISense sense_code_CAPACITY_CHANGED; > -/* LUN not ready, Medium not present */ > -extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM; > -/* Unit attention, Power on, reset or bus device reset occurred */ > -extern const struct SCSISense sense_code_RESET; > -/* Unit attention, Medium may have changed*/ > -extern const struct SCSISense sense_code_MEDIUM_CHANGED; > -/* Unit attention, Reported LUNs data has changed */ > -extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED; > -/* Unit attention, Device internal reset */ > -extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET; > -/* Data Protection, Write Protected */ > -extern const struct SCSISense sense_code_WRITE_PROTECTED; > -/* Data Protection, Space Allocation Failed Write Protect */ > -extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED; > - > -#define SENSE_CODE(x) sense_code_ ## x > - > -uint32_t scsi_data_cdb_xfer(uint8_t *buf); > -uint32_t scsi_cdb_xfer(uint8_t *buf); > -int scsi_cdb_length(uint8_t *buf); > -int scsi_convert_sense(uint8_t *in_buf, int in_len, > - uint8_t *buf, int len, bool fixed); > - > SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, > uint32_t tag, uint32_t lun, void *hba_private); > SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, > diff --git a/include/scsi/utils.h b/include/scsi/utils.h > new file mode 100644 > index 0000000000..35a74436bf > --- /dev/null > +++ b/include/scsi/utils.h > @@ -0,0 +1,116 @@ > +#ifndef SCSI_UTILS_H > +#define SCSI_UTILS_H 1 > + > +#ifdef CONFIG_LINUX > +#include > +#endif > + > +#define SCSI_CMD_BUF_SIZE 16 > +#define SCSI_SENSE_LEN 18 > +#define SCSI_SENSE_LEN_SCANNER 32 > +#define SCSI_INQUIRY_LEN 36 > + > +enum SCSIXferMode { > + SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */ > + SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */ > + SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */ > +}; > + > +typedef struct SCSICommand { > + uint8_t buf[SCSI_CMD_BUF_SIZE]; > + int len; > + size_t xfer; > + uint64_t lba; > + enum SCSIXferMode mode; > +} SCSICommand; > + > +typedef struct SCSISense { > + uint8_t key; > + uint8_t asc; > + uint8_t ascq; > +} SCSISense; > + > +/* > + * Predefined sense codes > + */ > + > +/* No sense data available */ > +extern const struct SCSISense sense_code_NO_SENSE; > +/* LUN not ready, Manual intervention required */ > +extern const struct SCSISense sense_code_LUN_NOT_READY; > +/* LUN not ready, Medium not present */ > +extern const struct SCSISense sense_code_NO_MEDIUM; > +/* LUN not ready, medium removal prevented */ > +extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED; > +/* Hardware error, internal target failure */ > +extern const struct SCSISense sense_code_TARGET_FAILURE; > +/* Illegal request, invalid command operation code */ > +extern const struct SCSISense sense_code_INVALID_OPCODE; > +/* Illegal request, LBA out of range */ > +extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE; > +/* Illegal request, Invalid field in CDB */ > +extern const struct SCSISense sense_code_INVALID_FIELD; > +/* Illegal request, Invalid field in parameter list */ > +extern const struct SCSISense sense_code_INVALID_PARAM; > +/* Illegal request, Parameter list length error */ > +extern const struct SCSISense sense_code_INVALID_PARAM_LEN; > +/* Illegal request, LUN not supported */ > +extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED; > +/* Illegal request, Saving parameters not supported */ > +extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED; > +/* Illegal request, Incompatible format */ > +extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT; > +/* Illegal request, medium removal prevented */ > +extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED; > +/* Illegal request, Invalid Transfer Tag */ > +extern const struct SCSISense sense_code_INVALID_TAG; > +/* Command aborted, I/O process terminated */ > +extern const struct SCSISense sense_code_IO_ERROR; > +/* Command aborted, I_T Nexus loss occurred */ > +extern const struct SCSISense sense_code_I_T_NEXUS_LOSS; > +/* Command aborted, Logical Unit failure */ > +extern const struct SCSISense sense_code_LUN_FAILURE; > +/* Command aborted, Overlapped Commands Attempted */ > +extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS; > +/* LUN not ready, Capacity data has changed */ > +extern const struct SCSISense sense_code_CAPACITY_CHANGED; > +/* LUN not ready, Medium not present */ > +extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM; > +/* Unit attention, Power on, reset or bus device reset occurred */ > +extern const struct SCSISense sense_code_RESET; > +/* Unit attention, Medium may have changed*/ > +extern const struct SCSISense sense_code_MEDIUM_CHANGED; > +/* Unit attention, Reported LUNs data has changed */ > +extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED; > +/* Unit attention, Device internal reset */ > +extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET; > +/* Data Protection, Write Protected */ > +extern const struct SCSISense sense_code_WRITE_PROTECTED; > +/* Data Protection, Space Allocation Failed Write Protect */ > +extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED; > + > +#define SENSE_CODE(x) sense_code_ ## x > + > +int scsi_convert_sense(uint8_t *in_buf, int in_len, > + uint8_t *buf, int len, bool fixed); > +const char *scsi_command_name(uint8_t cmd); > + > +uint64_t scsi_cmd_lba(SCSICommand *cmd); > +uint32_t scsi_data_cdb_xfer(uint8_t *buf); > +uint32_t scsi_cdb_xfer(uint8_t *buf); > +int scsi_cdb_length(uint8_t *buf); > + > +/* Linux SG_IO interface. */ > +#ifdef CONFIG_LINUX > +#define SG_ERR_DRIVER_TIMEOUT 0x06 > +#define SG_ERR_DRIVER_SENSE 0x08 > + > +#define SG_ERR_DID_OK 0x00 > +#define SG_ERR_DID_NO_CONNECT 0x01 > +#define SG_ERR_DID_BUS_BUSY 0x02 > +#define SG_ERR_DID_TIME_OUT 0x03 > + > +#define SG_ERR_DRIVER_SENSE 0x08 > +#endif > + > +#endif > diff --git a/scsi/Makefile.objs b/scsi/Makefile.objs > new file mode 100644 > index 0000000000..31b82a5a36 > --- /dev/null > +++ b/scsi/Makefile.objs > @@ -0,0 +1 @@ > +block-obj-y += utils.o > diff --git a/scsi/utils.c b/scsi/utils.c > new file mode 100644 > index 0000000000..0db727591f > --- /dev/null > +++ b/scsi/utils.c > @@ -0,0 +1,403 @@ > +#include "qemu/osdep.h" > +#include "block/scsi.h" > +#include "scsi/utils.h" > +#include "qemu/bswap.h" > + > +uint32_t scsi_data_cdb_xfer(uint8_t *buf) > +{ > + if ((buf[0] >> 5) == 0 && buf[4] == 0) { > + return 256; > + } else { > + return scsi_cdb_xfer(buf); > + } > +} > + > +uint32_t scsi_cdb_xfer(uint8_t *buf) > +{ > + switch (buf[0] >> 5) { > + case 0: > + return buf[4]; > + break; > + case 1: > + case 2: > + return lduw_be_p(&buf[7]); > + break; > + case 4: > + return ldl_be_p(&buf[10]) & 0xffffffffULL; > + break; > + case 5: > + return ldl_be_p(&buf[6]) & 0xffffffffULL; > + break; > + default: > + return -1; > + } > +} > + > +uint64_t scsi_cmd_lba(SCSICommand *cmd) > +{ > + uint8_t *buf = cmd->buf; > + uint64_t lba; > + > + switch (buf[0] >> 5) { > + case 0: > + lba = ldl_be_p(&buf[0]) & 0x1fffff; > + break; > + case 1: > + case 2: > + case 5: > + lba = ldl_be_p(&buf[2]) & 0xffffffffULL; > + break; > + case 4: > + lba = ldq_be_p(&buf[2]); > + break; > + default: > + lba = -1; > + > + } > + return lba; > +} > + > +int scsi_cdb_length(uint8_t *buf) > +{ > + int cdb_len; > + > + switch (buf[0] >> 5) { > + case 0: > + cdb_len = 6; > + break; > + case 1: > + case 2: > + cdb_len = 10; > + break; > + case 4: > + cdb_len = 16; > + break; > + case 5: > + cdb_len = 12; > + break; > + default: > + cdb_len = -1; > + } > + return cdb_len; > +} > + > +/* > + * Predefined sense codes > + */ > + > +/* No sense data available */ > +const struct SCSISense sense_code_NO_SENSE = { > + .key = NO_SENSE , .asc = 0x00 , .ascq = 0x00 > +}; > + > +/* LUN not ready, Manual intervention required */ > +const struct SCSISense sense_code_LUN_NOT_READY = { > + .key = NOT_READY, .asc = 0x04, .ascq = 0x03 > +}; > + > +/* LUN not ready, Medium not present */ > +const struct SCSISense sense_code_NO_MEDIUM = { > + .key = NOT_READY, .asc = 0x3a, .ascq = 0x00 > +}; > + > +/* LUN not ready, medium removal prevented */ > +const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = { > + .key = NOT_READY, .asc = 0x53, .ascq = 0x02 > +}; > + > +/* Hardware error, internal target failure */ > +const struct SCSISense sense_code_TARGET_FAILURE = { > + .key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00 > +}; > + > +/* Illegal request, invalid command operation code */ > +const struct SCSISense sense_code_INVALID_OPCODE = { > + .key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00 > +}; > + > +/* Illegal request, LBA out of range */ > +const struct SCSISense sense_code_LBA_OUT_OF_RANGE = { > + .key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00 > +}; > + > +/* Illegal request, Invalid field in CDB */ > +const struct SCSISense sense_code_INVALID_FIELD = { > + .key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00 > +}; > + > +/* Illegal request, Invalid field in parameter list */ > +const struct SCSISense sense_code_INVALID_PARAM = { > + .key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00 > +}; > + > +/* Illegal request, Parameter list length error */ > +const struct SCSISense sense_code_INVALID_PARAM_LEN = { > + .key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00 > +}; > + > +/* Illegal request, LUN not supported */ > +const struct SCSISense sense_code_LUN_NOT_SUPPORTED = { > + .key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00 > +}; > + > +/* Illegal request, Saving parameters not supported */ > +const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = { > + .key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00 > +}; > + > +/* Illegal request, Incompatible medium installed */ > +const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = { > + .key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00 > +}; > + > +/* Illegal request, medium removal prevented */ > +const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = { > + .key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02 > +}; > + > +/* Illegal request, Invalid Transfer Tag */ > +const struct SCSISense sense_code_INVALID_TAG = { > + .key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01 > +}; > + > +/* Command aborted, I/O process terminated */ > +const struct SCSISense sense_code_IO_ERROR = { > + .key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06 > +}; > + > +/* Command aborted, I_T Nexus loss occurred */ > +const struct SCSISense sense_code_I_T_NEXUS_LOSS = { > + .key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07 > +}; > + > +/* Command aborted, Logical Unit failure */ > +const struct SCSISense sense_code_LUN_FAILURE = { > + .key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01 > +}; > + > +/* Command aborted, Overlapped Commands Attempted */ > +const struct SCSISense sense_code_OVERLAPPED_COMMANDS = { > + .key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00 > +}; > + > +/* Unit attention, Capacity data has changed */ > +const struct SCSISense sense_code_CAPACITY_CHANGED = { > + .key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09 > +}; > + > +/* Unit attention, Power on, reset or bus device reset occurred */ > +const struct SCSISense sense_code_RESET = { > + .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00 > +}; > + > +/* Unit attention, No medium */ > +const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = { > + .key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00 > +}; > + > +/* Unit attention, Medium may have changed */ > +const struct SCSISense sense_code_MEDIUM_CHANGED = { > + .key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00 > +}; > + > +/* Unit attention, Reported LUNs data has changed */ > +const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = { > + .key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e > +}; > + > +/* Unit attention, Device internal reset */ > +const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = { > + .key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04 > +}; > + > +/* Data Protection, Write Protected */ > +const struct SCSISense sense_code_WRITE_PROTECTED = { > + .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00 > +}; > + > +/* Data Protection, Space Allocation Failed Write Protect */ > +const struct SCSISense sense_code_SPACE_ALLOC_FAILED = { > + .key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07 > +}; > + > +/* > + * scsi_convert_sense > + * > + * Convert between fixed and descriptor sense buffers > + */ > +int scsi_convert_sense(uint8_t *in_buf, int in_len, > + uint8_t *buf, int len, bool fixed) > +{ > + bool fixed_in; > + SCSISense sense; > + if (!fixed && len < 8) { > + return 0; > + } > + > + if (in_len == 0) { > + sense.key = NO_SENSE; > + sense.asc = 0; > + sense.ascq = 0; > + } else { > + fixed_in = (in_buf[0] & 2) == 0; > + > + if (fixed == fixed_in) { > + memcpy(buf, in_buf, MIN(len, in_len)); > + return MIN(len, in_len); > + } > + > + if (fixed_in) { > + sense.key = in_buf[2]; > + sense.asc = in_buf[12]; > + sense.ascq = in_buf[13]; > + } else { > + sense.key = in_buf[1]; > + sense.asc = in_buf[2]; > + sense.ascq = in_buf[3]; > + } > + } > + > + memset(buf, 0, len); > + if (fixed) { > + /* Return fixed format sense buffer */ > + buf[0] = 0x70; > + buf[2] = sense.key; > + buf[7] = 10; > + buf[12] = sense.asc; > + buf[13] = sense.ascq; > + return MIN(len, SCSI_SENSE_LEN); > + } else { > + /* Return descriptor format sense buffer */ > + buf[0] = 0x72; > + buf[1] = sense.key; > + buf[2] = sense.asc; > + buf[3] = sense.ascq; > + return 8; > + } > +} > + > +const char *scsi_command_name(uint8_t cmd) > +{ > + static const char *names[] = { > + [ TEST_UNIT_READY ] = "TEST_UNIT_READY", > + [ REWIND ] = "REWIND", > + [ REQUEST_SENSE ] = "REQUEST_SENSE", > + [ FORMAT_UNIT ] = "FORMAT_UNIT", > + [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS", > + [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS", > + /* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */ > + [ READ_6 ] = "READ_6", > + [ WRITE_6 ] = "WRITE_6", > + [ SET_CAPACITY ] = "SET_CAPACITY", > + [ READ_REVERSE ] = "READ_REVERSE", > + [ WRITE_FILEMARKS ] = "WRITE_FILEMARKS", > + [ SPACE ] = "SPACE", > + [ INQUIRY ] = "INQUIRY", > + [ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA", > + [ MAINTENANCE_IN ] = "MAINTENANCE_IN", > + [ MAINTENANCE_OUT ] = "MAINTENANCE_OUT", > + [ MODE_SELECT ] = "MODE_SELECT", > + [ RESERVE ] = "RESERVE", > + [ RELEASE ] = "RELEASE", > + [ COPY ] = "COPY", > + [ ERASE ] = "ERASE", > + [ MODE_SENSE ] = "MODE_SENSE", > + [ START_STOP ] = "START_STOP/LOAD_UNLOAD", > + /* LOAD_UNLOAD and START_STOP use the same operation code */ > + [ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC", > + [ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC", > + [ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL", > + [ READ_CAPACITY_10 ] = "READ_CAPACITY_10", > + [ READ_10 ] = "READ_10", > + [ WRITE_10 ] = "WRITE_10", > + [ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT", > + /* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */ > + [ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10", > + [ VERIFY_10 ] = "VERIFY_10", > + [ SEARCH_HIGH ] = "SEARCH_HIGH", > + [ SEARCH_EQUAL ] = "SEARCH_EQUAL", > + [ SEARCH_LOW ] = "SEARCH_LOW", > + [ SET_LIMITS ] = "SET_LIMITS", > + [ PRE_FETCH ] = "PRE_FETCH/READ_POSITION", > + /* READ_POSITION and PRE_FETCH use the same operation code */ > + [ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE", > + [ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE", > + [ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE", > + /* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */ > + [ MEDIUM_SCAN ] = "MEDIUM_SCAN", > + [ COMPARE ] = "COMPARE", > + [ COPY_VERIFY ] = "COPY_VERIFY", > + [ WRITE_BUFFER ] = "WRITE_BUFFER", > + [ READ_BUFFER ] = "READ_BUFFER", > + [ UPDATE_BLOCK ] = "UPDATE_BLOCK", > + [ READ_LONG_10 ] = "READ_LONG_10", > + [ WRITE_LONG_10 ] = "WRITE_LONG_10", > + [ CHANGE_DEFINITION ] = "CHANGE_DEFINITION", > + [ WRITE_SAME_10 ] = "WRITE_SAME_10", > + [ UNMAP ] = "UNMAP", > + [ READ_TOC ] = "READ_TOC", > + [ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT", > + [ SANITIZE ] = "SANITIZE", > + [ GET_CONFIGURATION ] = "GET_CONFIGURATION", > + [ LOG_SELECT ] = "LOG_SELECT", > + [ LOG_SENSE ] = "LOG_SENSE", > + [ MODE_SELECT_10 ] = "MODE_SELECT_10", > + [ RESERVE_10 ] = "RESERVE_10", > + [ RELEASE_10 ] = "RELEASE_10", > + [ MODE_SENSE_10 ] = "MODE_SENSE_10", > + [ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN", > + [ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT", > + [ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16", > + [ EXTENDED_COPY ] = "EXTENDED_COPY", > + [ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16", > + [ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN", > + [ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT", > + [ READ_16 ] = "READ_16", > + [ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE", > + [ WRITE_16 ] = "WRITE_16", > + [ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16", > + [ VERIFY_16 ] = "VERIFY_16", > + [ PRE_FETCH_16 ] = "PRE_FETCH_16", > + [ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16", > + /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */ > + [ LOCATE_16 ] = "LOCATE_16", > + [ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16", > + /* ERASE_16 and WRITE_SAME_16 use the same operation code */ > + [ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16", > + [ WRITE_LONG_16 ] = "WRITE_LONG_16", > + [ REPORT_LUNS ] = "REPORT_LUNS", > + [ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12", > + [ MOVE_MEDIUM ] = "MOVE_MEDIUM", > + [ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM", > + [ READ_12 ] = "READ_12", > + [ WRITE_12 ] = "WRITE_12", > + [ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE", > + /* ERASE_12 and GET_PERFORMANCE use the same operation code */ > + [ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12", > + [ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12", > + [ VERIFY_12 ] = "VERIFY_12", > + [ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12", > + [ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12", > + [ SEARCH_LOW_12 ] = "SEARCH_LOW_12", > + [ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS", > + [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING", > + /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */ > + [ READ_CD ] = "READ_CD", > + [ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12", > + [ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE", > + [ RESERVE_TRACK ] = "RESERVE_TRACK", > + [ SEND_CUE_SHEET ] = "SEND_CUE_SHEET", > + [ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE", > + [ SET_CD_SPEED ] = "SET_CD_SPEED", > + [ SET_READ_AHEAD ] = "SET_READ_AHEAD", > + [ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE", > + [ MECHANISM_STATUS ] = "MECHANISM_STATUS", > + [ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION", > + [ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION", > + }; > + > + if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL) { > + return "*UNKNOWN*"; > + } > + return names[cmd]; > +} >