From: Christian Hoff <christian.h...@de.ibm.com> This adds basic support for SCSI media changer commands. Not all commands are supported as of now, but enough to cover basic functionality.
Signed-off-by: Christian Hoff <christian.h...@de.ibm.com> Signed-off-by: Christian Borntraeger <borntrae...@de.ibm.com> --- hw/scsi-bus.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++----- hw/scsi-defs.h | 4 +++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 0e484d2..a93d3da 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -724,7 +724,6 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) case SET_CD_SPEED: case SET_LIMITS: case WRITE_LONG_10: - case MOVE_MEDIUM: case UPDATE_BLOCK: case RESERVE_TRACK: case SET_READ_AHEAD: @@ -852,6 +851,43 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu return 0; } +static int scsi_req_medium_changer_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) +{ + switch (buf[0]) { + /* medium changer commands */ + case EXCHANGE_MEDIUM: + cmd->xfer = 0; + cmd->len = 12; + break; + case INITIALIZE_ELEMENT_STATUS: + cmd->xfer = 0; + cmd->len = 6; + break; + case INITIALIZE_ELEMENT_STATUS_WITH_RANGE: + cmd->xfer = 0; + cmd->len = 10; + break; + case MOVE_MEDIUM: + cmd->xfer = 0; + cmd->len = 12; + break; + case POSITION_TO_ELEMENT: + cmd->xfer = 0; + cmd->len = 10; + break; + case READ_ELEMENT_STATUS: + cmd->xfer = buf[9] | (buf[8] << 8) | (buf[7] << 16); + cmd->len = 12; + break; + + /* generic commands */ + default: + return scsi_req_length(cmd, dev, buf); + } + return 0; +} + + static void scsi_cmd_xfer_mode(SCSICommand *cmd) { switch (cmd->buf[0]) { @@ -928,11 +964,18 @@ int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) { int rc; - if (dev->type == TYPE_TAPE) { + switch (dev->type) { + case TYPE_TAPE: rc = scsi_req_stream_length(cmd, dev, buf); - } else { + break; + case TYPE_MEDIUM_CHANGER: + rc = scsi_req_medium_changer_length(cmd, dev, buf); + break; + default: rc = scsi_req_length(cmd, dev, buf); + break; } + if (rc != 0) return rc; @@ -1110,7 +1153,8 @@ static const char *scsi_command_name(uint8_t cmd) [ REQUEST_SENSE ] = "REQUEST_SENSE", [ FORMAT_UNIT ] = "FORMAT_UNIT", [ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS", - [ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS", + [ 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", @@ -1135,7 +1179,8 @@ static const char *scsi_command_name(uint8_t cmd) [ READ_CAPACITY_10 ] = "READ_CAPACITY_10", [ READ_10 ] = "READ_10", [ WRITE_10 ] = "WRITE_10", - [ SEEK_10 ] = "SEEK_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", @@ -1146,7 +1191,8 @@ static const char *scsi_command_name(uint8_t cmd) /* 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", + [ 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", @@ -1190,6 +1236,7 @@ static const char *scsi_command_name(uint8_t cmd) [ REPORT_LUNS ] = "REPORT_LUNS", [ BLANK ] = "BLANK", [ MOVE_MEDIUM ] = "MOVE_MEDIUM", + [ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM", [ LOAD_UNLOAD ] = "LOAD_UNLOAD", [ READ_12 ] = "READ_12", [ WRITE_12 ] = "WRITE_12", diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h index 2b0db4b..2c40855 100644 --- a/hw/scsi-defs.h +++ b/hw/scsi-defs.h @@ -29,6 +29,7 @@ #define REQUEST_SENSE 0x03 #define FORMAT_UNIT 0x04 #define READ_BLOCK_LIMITS 0x05 +#define INITIALIZE_ELEMENT_STATUS 0x07 #define REASSIGN_BLOCKS 0x07 #define READ_6 0x08 #define WRITE_6 0x0a @@ -54,6 +55,7 @@ #define WRITE_10 0x2a #define SEEK_10 0x2b #define LOCATE_10 0x2b +#define POSITION_TO_ELEMENT 0x2b #define WRITE_VERIFY_10 0x2e #define VERIFY_10 0x2f #define SEARCH_HIGH 0x30 @@ -64,6 +66,7 @@ #define READ_POSITION 0x34 #define SYNCHRONIZE_CACHE 0x35 #define LOCK_UNLOCK_CACHE 0x36 +#define INITIALIZE_ELEMENT_STATUS_WITH_RANGE 0x37 #define READ_DEFECT_DATA 0x37 #define MEDIUM_SCAN 0x38 #define COMPARE 0x39 @@ -115,6 +118,7 @@ #define MAINTENANCE_IN 0xa3 #define MAINTENANCE_OUT 0xa4 #define MOVE_MEDIUM 0xa5 +#define EXCHANGE_MEDIUM 0xa6 #define SET_READ_AHEAD 0xa7 #define READ_12 0xa8 #define WRITE_12 0xaa -- 1.7.0.4