From patchwork Fri Nov 19 02:07:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: adq X-Patchwork-Id: 72185 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 10924B719A for ; Fri, 19 Nov 2010 13:08:53 +1100 (EST) Received: from localhost ([127.0.0.1]:56081 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PJGOs-0007px-Ai for incoming@patchwork.ozlabs.org; Thu, 18 Nov 2010 21:08:30 -0500 Received: from [140.186.70.92] (port=43944 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PJGNh-0007Ug-2N for qemu-devel@nongnu.org; Thu, 18 Nov 2010 21:07:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PJGNe-0004kX-Qa for qemu-devel@nongnu.org; Thu, 18 Nov 2010 21:07:16 -0500 Received: from mail-qy0-f173.google.com ([209.85.216.173]:42036) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PJGNe-0004kT-M5 for qemu-devel@nongnu.org; Thu, 18 Nov 2010 21:07:14 -0500 Received: by qyl33 with SMTP id 33so8770725qyl.4 for ; Thu, 18 Nov 2010 18:07:13 -0800 (PST) MIME-Version: 1.0 Received: by 10.229.246.129 with SMTP id ly1mr1238521qcb.126.1290132433271; Thu, 18 Nov 2010 18:07:13 -0800 (PST) Received: by 10.229.99.74 with HTTP; Thu, 18 Nov 2010 18:07:13 -0800 (PST) X-Originating-IP: [82.71.49.12] In-Reply-To: References: <4C5EACF8.1010101@redhat.com> <4CDD1057.7060103@redhat.com> Date: Fri, 19 Nov 2010 02:07:13 +0000 Message-ID: From: adq To: Paolo Bonzini X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] Re: [patch] fix scsi-generic X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On 17 November 2010 23:33, adq wrote: >> On 12 November 2010 10:00, Paolo Bonzini 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 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 */