Fix ATAPI GET_CONFIGURATION function (Alexander Graf, Carlo Marcelo Arenas Belon).

The current implementation of GET_CONFIGURATION in the ATAPI stack of qemu
replies a different length depending on the buffer, the data should be
written into.

On the other hand the SCSI spec defines that length information has to be
consistent and independent of return buffer lengths.

This patch makes the ATAPI emulation behave according to the spec and fixes
the Darwin DVD driver.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Kevin Wolf <kwolf@suse.de>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4649 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
balrog 2008-06-02 03:12:06 +00:00
parent a60de94777
commit 091d055b3e

View File

@ -1715,6 +1715,7 @@ static void ide_atapi_cmd(IDEState *s)
case GPCMD_GET_CONFIGURATION: case GPCMD_GET_CONFIGURATION:
{ {
uint32_t len; uint32_t len;
uint8_t index = 0;
/* only feature 0 is supported */ /* only feature 0 is supported */
if (packet[2] != 0 || packet[3] != 0) { if (packet[2] != 0 || packet[3] != 0) {
@ -1725,12 +1726,13 @@ static void ide_atapi_cmd(IDEState *s)
/* XXX: could result in alignment problems in some architectures */ /* XXX: could result in alignment problems in some architectures */
max_len = ube16_to_cpu(packet + 7); max_len = ube16_to_cpu(packet + 7);
/* /*
* XXX: avoid overflow for io_buffer if max_len is bigger than the * XXX: avoid overflow for io_buffer if max_len is bigger than
* size of that buffer (dimensioned to max number of sectors * the size of that buffer (dimensioned to max number of
* to transfer at once) * sectors to transfer at once)
* *
* Only a problem if the feature/profiles grow exponentially. * Only a problem if the feature/profiles grow.
*/ */
if (max_len > 512) /* XXX: assume 1 sector */ if (max_len > 512) /* XXX: assume 1 sector */
max_len = 512; max_len = 512;
@ -1743,22 +1745,17 @@ static void ide_atapi_cmd(IDEState *s)
* XXX: fails to detect correctly DVDs with less data burned * XXX: fails to detect correctly DVDs with less data burned
* than what a CD can hold * than what a CD can hold
*/ */
if ((s -> nb_sectors)) { if (s -> nb_sectors) {
if ((s -> nb_sectors > CD_MAX_SECTORS)) if (s -> nb_sectors > CD_MAX_SECTORS)
cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
else else
cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
} }
len = 8; /* header completed */ buf[10] = 0x02 | 0x01; /* persistent and current */
if (max_len > len) { len = 12; /* headers: 8 + 4 */
uint8_t index = 0; len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
buf[10] = 0x02 | 0x01; /* persistent and current */
len += 4; /* header */
len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
}
cpu_to_ube32(buf, len - 4); /* data length */ cpu_to_ube32(buf, len - 4); /* data length */
ide_atapi_cmd_reply(s, len, max_len); ide_atapi_cmd_reply(s, len, max_len);