On 17 November 2010 23:33, adq <[email protected]> wrote:
>> On 12 November 2010 10:00, Paolo Bonzini <[email protected]> wrote:
>>> On 08/09/2010 01:51 AM, adq wrote:
>>>>
>>>> Figured out what the problem is - READ DVD STRUCTURE has its xfer
>>>> length in an unexpected place, so hw/scsi-bus.c retrieves completely
>>>> the wrong value for the transfer length. Attached nasty hacky (!)
>>>> patch fixes it as a proof of concept, will see what I can do to clean
>>>> it up later. I'd probably want it to warn if it sees SCSI commands it
>>>> doesn't know how to explicitly handle to aid debugging this sort of
>>>> thing in future.
>>>
>>> Hi Andrew, are you going to submit a similar patch in definitive form?
>
> Oops, sorry for top replying before.
>
> Anyway, found the patch and it looks to be in good condition (just
> missing one last SCSI MMC command and testing, which I shall work on).
>
> However, could someone please check the code for the existing
> SEND_VOLUME_TAG code in hw/scsi-bus.c? A doc on this command is h ere:
> http://www.t10.org/ftp/t10/document.05/05-414r4.pdf
>
> I'm not certain "req->cmd.xfer *= 40;" is correct. For a type 5 SCSI
> command, req->cmd.xfer will be set to the value in bytes 9/8/7/6,
> which is defined as PARAMETER LIST LENGTH (i.e. the number of bytes in
> the data transfer according to SPC3). The PARAMETER LIST LENGTH for
> this command should be 40, so multiplying it by 40 again ain't right
> surely?
>
> As I've never seen this command used and have no access to a device
> which could generate it, I just don't know....
>
Hi, attached is a cleaned up version of my patch against the latest
git. It adds support for all the SCSI MMC commands I could find
(although not all have been tested yet). AnyDVD is now able to rip a
video DVD.
Please let me know what you think. The SEND_VOLUME_TAG issue is still
unresolved.
Note for testers: to setup a CDROM to use with this, use a command
line something like: "-device lsi -device scsi-generic,drive=sgcd
-drive file=/dev/sg1,media=cdrom,if=none,id=sgcd" to hook in the
/dev/sgX device for your DVD drive.
Signed-off-by: Andrew de Quincey <[email protected]>
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 5a3fd4b..aac8fa1 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -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)
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index a4a3518..2d56044 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -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 */