From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex Williamson Subject: [PATCH] qemu: fix ATAPI read drive structure command Date: Thu, 22 May 2008 20:58:33 -0600 Message-ID: <1211511513.21166.135.camel@bling> Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit Cc: Avi Kivity To: kvm-devel Return-path: Received: from g4t0015.houston.hp.com ([15.201.24.18]:46246 "EHLO g4t0015.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757837AbYEWC6h (ORCPT ); Thu, 22 May 2008 22:58:37 -0400 Sender: kvm-owner@vger.kernel.org List-ID: I believe this fixes bug 1967368. Windows Vista hangs if you try to run diskpart.exe with a DVD image loaded. This does not occur on Xen because their version of Qemu doesn't try to emulate the GPCMD_READ_DVD_STRUCTURE command. If I comment out the version in KVM, diskpart.exe works. Digging through the versions of the MMC-6 spec I can find online, I believe the problem is that we're ignoring the allocation length field. This specifies the maximum number of bytes that may be returned by the drive. Instead we're returning the maximum possible table size each time. I also found that we seem to be using the wrong field for the format request. Byte 2 is MSB of the address field, we want byte 7. I also added a few missing comments for the fields as we fill them in. I've only tested this with Vista since it's the only thing that I know using this command. Thanks, Alex qemu: fix ATAPI read drive structure command Make use of the allocation length field in the command and only return the number of bytes requested. Fix location of format byte in command. Add comments for more fields as we fill them in. This fixes bug 1967368 (diskpart.exe in Vista hangs with DVD image loaded). Signed-off-by: Alex Williamson -- diff --git a/qemu/hw/ide.c b/qemu/hw/ide.c index 69363a9..0246fb6 100644 --- a/qemu/hw/ide.c +++ b/qemu/hw/ide.c @@ -1653,7 +1653,8 @@ static void ide_atapi_cmd(IDEState *s) { int media = packet[1]; int layer = packet[6]; - int format = packet[2]; + int format = packet[7]; + int length = ube16_to_cpu(packet + 8); uint64_t total_sectors; if (media != 0 || layer != 0) @@ -1672,20 +1673,26 @@ static void ide_atapi_cmd(IDEState *s) break; } - memset(buf, 0, 2052); + if (length == 0) + length = 2048 + 4; + if (length < 20) + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + + memset(buf, 0, length); buf[4] = 1; // DVD-ROM, part version 1 buf[5] = 0xf; // 120mm disc, maximum rate unspecified buf[6] = 0; // one layer, embossed data - buf[7] = 0; + buf[7] = 0; // default densities - cpu_to_ube32(buf + 8, 0); - cpu_to_ube32(buf + 12, total_sectors - 1); - cpu_to_ube32(buf + 16, total_sectors - 1); + cpu_to_ube32(buf + 8, 0); // start sector + cpu_to_ube32(buf + 12, total_sectors - 1); // end sector + cpu_to_ube32(buf + 16, total_sectors - 1); // l0 end sector - cpu_to_be16wu((uint16_t *)buf, 2048 + 4); + cpu_to_be16wu((uint16_t *)buf, length); - ide_atapi_cmd_reply(s, 2048 + 3, 2048 + 4); + ide_atapi_cmd_reply(s, length, length); break; default: