@@ -220,8 +220,19 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
case SET_CD_SPEED:
case SET_LIMITS:
case WRITE_LONG:
- case MOVE_MEDIUM:
+ case MOVE_MEDIUM: // also handles MMC PLAY_AUDIO_12
case UPDATE_BLOCK:
+ case PLAY_AUDIO_10:
+ case PLAY_AUDIO_MSF:
+ case PAUSE_RESUME:
+ case STOP_PLAY_SCAN:
+ case RESERVE_TRACK:
+ case FORMAT_UNIT:
+ case SET_READ_AHEAD:
+ case SCAN:
+ case BLANK:
+ case CLOSE_TRACK_SESSION:
+ case REPAIR_TRACK:
req->cmd.xfer = 0;
break;
case MODE_SENSE:
@@ -239,7 +250,11 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
req->cmd.xfer = 20;
break;
case SEND_VOLUME_TAG:
- req->cmd.xfer *= 40;
+ if (req->dev->type == TYPE_ROM) {
+ req->cmd.xfer = cmd[10] | (cmd[9] << 8); // MMC SET_STREAMING operation
+ } else {
+ req->cmd.xfer *= 40; // FIXME: questionable
+ }
break;
case MEDIUM_SCAN:
req->cmd.xfer *= 8;
@@ -271,6 +286,46 @@ static int scsi_req_length(SCSIRequest *req, uint8_t *cmd)
req->cmd.xfer = cmd[9] | (cmd[8] << 8);
}
break;
+ case READ_DISC_STRUCTURE:
+ case MECHANISM_STATUS:
+ case SEND_DISC_STRUCTURE:
+ req->cmd.xfer = cmd[9] | (cmd[8] << 8);
+ break;
+ case READ_CD:
+ case SEND_CUE_SHEET:
+ case READ_MASTER_CUE:
+ req->cmd.xfer = cmd[8] | (cmd[7] << 8) | (cmd[6] << 16);
+ break;
+ case READ_CD_MSF:
+ req->cmd.xfer = (((cmd[6] - cmd[3]) * 60 * 75) +
+ ((cmd[7] - cmd[4]) * 75) +
+ (cmd[8] - cmd[5])) * 2352;
+ break;
+ case GET_PERFORMANCE:
+ req->cmd.xfer = 8;
+
+ int max_descriptors = cmd[9] | (cmd[8] << 8);
+ switch(cmd[10]) {
+ case 0: // performance
+ req->cmd.xfer += (max_descriptors * 16);
+ break;
+ case 1: // Unusable area data
+ req->cmd.xfer += (max_descriptors * 8);
+ break;
+ case 2: // defect status data
+ req->cmd.xfer += (max_descriptors * 2048);
+ break;
+ case 3: // write speed
+ req->cmd.xfer += (max_descriptors * 16);
+ break;
+ case 4: // DBI
+ req->cmd.xfer += (max_descriptors * 8);
+ break;
+ case 5: // DBI cache zone
+ req->cmd.xfer += (max_descriptors * 8);
+ break;
+ }
+ break;
}
return 0;
}
@@ -332,20 +387,34 @@ static void scsi_req_xfer_mode(SCSIRequest *req)
case SEARCH_LOW_12:
case SET_WINDOW:
case MEDIUM_SCAN:
- case SEND_VOLUME_TAG:
+ case SEND_VOLUME_TAG: // also handles MMC SET_STREAMING
case WRITE_LONG_2:
case PERSISTENT_RESERVE_OUT:
- case MAINTENANCE_OUT:
+ case SEND_DISC_STRUCTURE:
+ case SEND_CUE_SHEET:
+ case SEND_OPC_INFORMATION:
+ case SECURITY_PROTOCOL_OUT:
req->cmd.mode = SCSI_XFER_TO_DEV;
+ return;
+ case MAINTENANCE_OUT: /* same code as MMC REPORT KEY */
+ if (req->dev->type != TYPE_ROM) {
+ req->cmd.mode = SCSI_XFER_TO_DEV;
+ return;
+ }
break;
- default:
- if (req->cmd.xfer)
- req->cmd.mode = SCSI_XFER_FROM_DEV;
- else {
- req->cmd.mode = SCSI_XFER_NONE;
+ case MAINTENANCE_IN: /* same code as MMC SEND KEY */
+ if (req->dev->type == TYPE_ROM) {
+ req->cmd.mode = SCSI_XFER_TO_DEV;
+ return;
}
break;
}
+
+ if (req->cmd.xfer)
+ req->cmd.mode = SCSI_XFER_FROM_DEV;
+ else {
+ req->cmd.mode = SCSI_XFER_NONE;
+ }
}
static uint64_t scsi_req_lba(SCSIRequest *req)
@@ -485,6 +554,33 @@ static const char *scsi_command_name(uint8_t cmd)
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
[ BLANK ] = "BLANK",
+ [ READ_FORMAT_CAPACITIES ] = "READ_FORMAT_CAPACITIES",
+ [ PLAY_AUDIO_10 ] = "PLAY_AUDIO_10",
+ [ PLAY_AUDIO_MSF ] = "PLAY_AUDIO_MSF",
+ [ GET_EVENT_STATUS ] = "GET_EVENT_STATUS",
+ [ PAUSE_RESUME ] = "PAUSE_RESUME",
+ [ STOP_PLAY_SCAN ] = "STOP_PLAY_SCAN",
+ [ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION",
+ [ READ_TRACK_INFORMATION ] = "READ_TRACK_INFORMATION",
+ [ RESERVE_TRACK ] = "RESERVE_TRACK",
+ [ SEND_OPC_INFORMATION ] = "SEND_OPC_INFORMATION",
+ [ REPAIR_TRACK ] = "REPAIR_TRACK",
+ [ CLOSE_TRACK_SESSION ] = "CLOSE_TRACK_SESSION",
+ [ READ_BUFFER_CAPACITY ] = "READ_BUFFER_CAPACITY",
+ [ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
+ [ SECURITY_PROTOCOL_IN ] = "SECURITY_PROTOCOL_IN",
+ [ SECURITY_PROTOCOL_OUT ] = "SECURITY_PROTOCOL_OUT",
+ [ SET_READ_AHEAD ] = "SET_READ_AHEAD",
+ [ READ_MEDIA_SERIAL_NUMBER ] = "READ_MEDIA_SERIAL_NUMBER",
+ [ READ_DISC_STRUCTURE ] = "READ_DISC_STRUCTURE",
+ [ SEND_DISC_STRUCTURE ] = "SEND_DISC_STRUCTURE",
+ [ READ_CD_MSF ] = "READ_CD_MSF",
+ [ READ_CD ] = "READ_CD",
+ [ SCAN ] = "SCAN",
+ [ MECHANISM_STATUS ] = "MECHANISM_STATUS",
+ [ READ_SUB_CHANNEL ] = "READ_SUB_CHANNEL",
+ [ READ_HEADER ] = "READ_HEADER",
+ [ READ_MASTER_CUE ] = "READ_MASTER_CUE",
};
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
@@ -49,6 +49,7 @@
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
+#define READ_FORMAT_CAPACITIES 0x23
#define SET_WINDOW 0x24
#define READ_CAPACITY 0x25
#define READ_10 0x28
@@ -75,26 +76,53 @@
#define WRITE_LONG 0x3f
#define CHANGE_DEFINITION 0x40
#define WRITE_SAME 0x41
+#define READ_SUB_CHANNEL 0x42
#define READ_TOC 0x43
+#define READ_HEADER 0x44
+#define PLAY_AUDIO_10 0x45
+#define PLAY_AUDIO_MSF 0x47
+#define GET_EVENT_STATUS 0x4a
+#define PAUSE_RESUME 0x4b
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
+#define STOP_PLAY_SCAN 0x4e
+#define READ_DISC_INFORMATION 0x51
+#define READ_TRACK_INFORMATION 0x52
+#define RESERVE_TRACK 0x53
+#define SEND_OPC_INFORMATION 0x54
#define MODE_SELECT_10 0x55
#define RESERVE_10 0x56
#define RELEASE_10 0x57
+#define REPAIR_TRACK 0x58
+#define READ_MASTER_CUE 0x59
#define MODE_SENSE_10 0x5a
+#define CLOSE_TRACK_SESSION 0x5b
+#define READ_BUFFER_CAPACITY 0x5c
+#define SEND_CUE_SHEET 0x5d
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
+#define SECURITY_PROTOCOL_IN 0xa2
#define MAINTENANCE_IN 0xa3
#define MAINTENANCE_OUT 0xa4
#define MOVE_MEDIUM 0xa5
+#define SET_READ_AHEAD 0xa7
#define READ_12 0xa8
#define WRITE_12 0xaa
+#define READ_MEDIA_SERIAL_NUMBER 0xab
+#define GET_PERFORMANCE 0xac
+#define READ_DISC_STRUCTURE 0xad
#define WRITE_VERIFY_12 0xae
#define SEARCH_HIGH_12 0xb0
#define SEARCH_EQUAL_12 0xb1
#define SEARCH_LOW_12 0xb2
+#define SECURITY_PROTOCOL_OUT 0xb5
#define READ_ELEMENT_STATUS 0xb8
#define SEND_VOLUME_TAG 0xb6
+#define READ_CD_MSF 0xb9
+#define SCAN 0xba
+#define MECHANISM_STATUS 0xbd
+#define READ_CD 0xbe
+#define SEND_DISC_STRUCTURE 0xbf
#define WRITE_LONG_2 0xea
/* from hw/scsi-generic.c */