summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorChristian Hoff <christian.hoff@de.ibm.com>2012-06-14 15:55:27 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2012-07-02 11:27:00 +0200
commit40723a99b8c406143f27538846103f98942e4e24 (patch)
tree19eff7566c5c0286854e06e51bb70d86bde7b637 /hw
parent28b70c9dbdce0d517ade9c04c7d7ae05c8b76d2f (diff)
downloadqemu-40723a99b8c406143f27538846103f98942e4e24.tar.gz
qemu-40723a99b8c406143f27538846103f98942e4e24.tar.bz2
qemu-40723a99b8c406143f27538846103f98942e4e24.zip
scsi: Add basic support for SCSI media changer commands.
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.hoff@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/scsi-bus.c45
-rw-r--r--hw/scsi-defs.h4
2 files changed, 43 insertions, 6 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 4ec9b52c7d..9c64e30279 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -770,7 +770,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:
@@ -914,6 +913,29 @@ 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:
+ case INITIALIZE_ELEMENT_STATUS:
+ case INITIALIZE_ELEMENT_STATUS_WITH_RANGE:
+ case MOVE_MEDIUM:
+ case POSITION_TO_ELEMENT:
+ cmd->xfer = 0;
+ break;
+ case READ_ELEMENT_STATUS:
+ cmd->xfer = buf[9] | (buf[8] << 8) | (buf[7] << 16);
+ break;
+
+ /* generic commands */
+ default:
+ return scsi_req_length(cmd, dev, buf);
+ }
+ return 0;
+}
+
+
static void scsi_cmd_xfer_mode(SCSICommand *cmd)
{
if (!cmd->xfer) {
@@ -1011,11 +1033,18 @@ int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
return -1;
}
- 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;
@@ -1193,7 +1222,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",
@@ -1218,7 +1248,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",
@@ -1229,7 +1260,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",
@@ -1274,6 +1306,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 6578bb9950..ade82a488f 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
@@ -118,6 +121,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