mirror of https://github.com/xemu-project/xemu.git
ide/atapi: Factor commands out
In preparation for a table of function pointers, factor each command out from ide_atapi_cmd() into its own function. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
33231e0e22
commit
a60cf7e7eb
477
hw/ide/atapi.c
477
hw/ide/atapi.c
|
@ -621,67 +621,103 @@ static void handle_get_event_status_notification(IDEState *s,
|
|||
ide_atapi_cmd_reply(s, used_len, max_len);
|
||||
}
|
||||
|
||||
void ide_atapi_cmd(IDEState *s)
|
||||
static void cmd_request_sense(IDEState *s, uint8_t *buf)
|
||||
{
|
||||
const uint8_t *packet;
|
||||
uint8_t *buf;
|
||||
int max_len = buf[4];
|
||||
|
||||
memset(buf, 0, 18);
|
||||
buf[0] = 0x70 | (1 << 7);
|
||||
buf[2] = s->sense_key;
|
||||
buf[7] = 10;
|
||||
buf[12] = s->asc;
|
||||
|
||||
if (s->sense_key == SENSE_UNIT_ATTENTION) {
|
||||
s->sense_key = SENSE_NONE;
|
||||
}
|
||||
|
||||
ide_atapi_cmd_reply(s, 18, max_len);
|
||||
}
|
||||
|
||||
static void cmd_inquiry(IDEState *s, uint8_t *buf)
|
||||
{
|
||||
int max_len = buf[4];
|
||||
|
||||
buf[0] = 0x05; /* CD-ROM */
|
||||
buf[1] = 0x80; /* removable */
|
||||
buf[2] = 0x00; /* ISO */
|
||||
buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
|
||||
buf[4] = 31; /* additional length */
|
||||
buf[5] = 0; /* reserved */
|
||||
buf[6] = 0; /* reserved */
|
||||
buf[7] = 0; /* reserved */
|
||||
padstr8(buf + 8, 8, "QEMU");
|
||||
padstr8(buf + 16, 16, "QEMU DVD-ROM");
|
||||
padstr8(buf + 32, 4, s->version);
|
||||
ide_atapi_cmd_reply(s, 36, max_len);
|
||||
}
|
||||
|
||||
static void cmd_get_configuration(IDEState *s, uint8_t *buf)
|
||||
{
|
||||
uint32_t len;
|
||||
uint8_t index = 0;
|
||||
int max_len;
|
||||
|
||||
packet = s->io_buffer;
|
||||
buf = s->io_buffer;
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
{
|
||||
int i;
|
||||
printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
|
||||
for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
|
||||
printf(" %02x", packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If there's a UNIT_ATTENTION condition pending, only
|
||||
* REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and
|
||||
* GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete.
|
||||
* MMC-5, section 4.1.6.1 lists only these commands being allowed
|
||||
* to complete, with other commands getting a CHECK condition
|
||||
* response unless a higher priority status, defined by the drive
|
||||
* here, is pending.
|
||||
*/
|
||||
if (s->sense_key == SENSE_UNIT_ATTENTION &&
|
||||
s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
|
||||
s->io_buffer[0] != GPCMD_INQUIRY &&
|
||||
s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) {
|
||||
ide_atapi_cmd_check_status(s);
|
||||
/* only feature 0 is supported */
|
||||
if (buf[2] != 0 || buf[3] != 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
return;
|
||||
}
|
||||
if (bdrv_is_inserted(s->bs) && s->cdrom_changed) {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
|
||||
s->cdrom_changed = 0;
|
||||
s->sense_key = SENSE_UNIT_ATTENTION;
|
||||
s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||
return;
|
||||
/* XXX: could result in alignment problems in some architectures */
|
||||
max_len = ube16_to_cpu(buf + 7);
|
||||
|
||||
/*
|
||||
* XXX: avoid overflow for io_buffer if max_len is bigger than
|
||||
* the size of that buffer (dimensioned to max number of
|
||||
* sectors to transfer at once)
|
||||
*
|
||||
* Only a problem if the feature/profiles grow.
|
||||
*/
|
||||
if (max_len > 512) {
|
||||
/* XXX: assume 1 sector */
|
||||
max_len = 512;
|
||||
}
|
||||
switch(s->io_buffer[0]) {
|
||||
case GPCMD_TEST_UNIT_READY:
|
||||
if (bdrv_is_inserted(s->bs)) {
|
||||
ide_atapi_cmd_ok(s);
|
||||
} else {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
|
||||
memset(buf, 0, max_len);
|
||||
/*
|
||||
* the number of sectors from the media tells us which profile
|
||||
* to use as current. 0 means there is no media
|
||||
*/
|
||||
if (media_is_dvd(s)) {
|
||||
cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
|
||||
} else if (media_is_cd(s)) {
|
||||
cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
|
||||
}
|
||||
break;
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
{
|
||||
|
||||
buf[10] = 0x02 | 0x01; /* persistent and current */
|
||||
len = 12; /* headers: 8 + 4 */
|
||||
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 */
|
||||
|
||||
ide_atapi_cmd_reply(s, len, max_len);
|
||||
}
|
||||
|
||||
static void cmd_mode_sense(IDEState *s, uint8_t *buf)
|
||||
{
|
||||
int action, code;
|
||||
if (packet[0] == GPCMD_MODE_SENSE_10)
|
||||
max_len = ube16_to_cpu(packet + 7);
|
||||
else
|
||||
max_len = packet[4];
|
||||
action = packet[2] >> 6;
|
||||
code = packet[2] & 0x3f;
|
||||
int max_len;
|
||||
|
||||
if (buf[0] == GPCMD_MODE_SENSE_10) {
|
||||
max_len = ube16_to_cpu(buf + 7);
|
||||
} else {
|
||||
max_len = buf[4];
|
||||
}
|
||||
|
||||
action = buf[2] >> 6;
|
||||
code = buf[2] & 0x3f;
|
||||
|
||||
switch(action) {
|
||||
case 0: /* current values */
|
||||
switch(code) {
|
||||
|
@ -768,51 +804,59 @@ void ide_atapi_cmd(IDEState *s)
|
|||
ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
max_len = packet[4];
|
||||
memset(buf, 0, 18);
|
||||
buf[0] = 0x70 | (1 << 7);
|
||||
buf[2] = s->sense_key;
|
||||
buf[7] = 10;
|
||||
buf[12] = s->asc;
|
||||
if (s->sense_key == SENSE_UNIT_ATTENTION)
|
||||
s->sense_key = SENSE_NONE;
|
||||
ide_atapi_cmd_reply(s, 18, max_len);
|
||||
break;
|
||||
case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
bdrv_set_locked(s->bs, packet[4] & 1);
|
||||
return;
|
||||
|
||||
error_cmd:
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
}
|
||||
|
||||
static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
|
||||
{
|
||||
if (bdrv_is_inserted(s->bs)) {
|
||||
ide_atapi_cmd_ok(s);
|
||||
break;
|
||||
case GPCMD_READ_10:
|
||||
case GPCMD_READ_12:
|
||||
{
|
||||
} else {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
bdrv_set_locked(s->bs, buf[4] & 1);
|
||||
ide_atapi_cmd_ok(s);
|
||||
}
|
||||
|
||||
static void cmd_read(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int nb_sectors, lba;
|
||||
|
||||
if (packet[0] == GPCMD_READ_10)
|
||||
nb_sectors = ube16_to_cpu(packet + 7);
|
||||
else
|
||||
nb_sectors = ube32_to_cpu(packet + 6);
|
||||
lba = ube32_to_cpu(packet + 2);
|
||||
if (buf[0] == GPCMD_READ_10) {
|
||||
nb_sectors = ube16_to_cpu(buf + 7);
|
||||
} else {
|
||||
nb_sectors = ube32_to_cpu(buf + 6);
|
||||
}
|
||||
|
||||
lba = ube32_to_cpu(buf + 2);
|
||||
if (nb_sectors == 0) {
|
||||
ide_atapi_cmd_ok(s);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
|
||||
}
|
||||
break;
|
||||
case GPCMD_READ_CD:
|
||||
{
|
||||
}
|
||||
|
||||
static void cmd_read_cd(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int nb_sectors, lba, transfer_request;
|
||||
|
||||
nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
|
||||
lba = ube32_to_cpu(packet + 2);
|
||||
nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8];
|
||||
lba = ube32_to_cpu(buf + 2);
|
||||
|
||||
if (nb_sectors == 0) {
|
||||
ide_atapi_cmd_ok(s);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
transfer_request = packet[9];
|
||||
|
||||
transfer_request = buf[9];
|
||||
switch(transfer_request & 0xf8) {
|
||||
case 0x00:
|
||||
/* nothing */
|
||||
|
@ -831,34 +875,35 @@ void ide_atapi_cmd(IDEState *s)
|
|||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_SEEK:
|
||||
{
|
||||
}
|
||||
|
||||
static void cmd_seek(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
unsigned int lba;
|
||||
uint64_t total_sectors;
|
||||
|
||||
bdrv_get_geometry(s->bs, &total_sectors);
|
||||
|
||||
total_sectors >>= 2;
|
||||
if (total_sectors == 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
return;
|
||||
}
|
||||
lba = ube32_to_cpu(packet + 2);
|
||||
|
||||
lba = ube32_to_cpu(buf + 2);
|
||||
if (lba >= total_sectors) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_LOGICAL_BLOCK_OOR);
|
||||
break;
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
|
||||
return;
|
||||
}
|
||||
|
||||
ide_atapi_cmd_ok(s);
|
||||
}
|
||||
break;
|
||||
case GPCMD_START_STOP_UNIT:
|
||||
{
|
||||
}
|
||||
|
||||
static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int start, eject, sense, err = 0;
|
||||
start = packet[4] & 1;
|
||||
eject = (packet[4] >> 1) & 1;
|
||||
start = buf[4] & 1;
|
||||
eject = (buf[4] >> 1) & 1;
|
||||
|
||||
if (eject) {
|
||||
err = bdrv_eject(s->bs, !start);
|
||||
|
@ -873,19 +918,18 @@ void ide_atapi_cmd(IDEState *s)
|
|||
if (bdrv_is_inserted(s->bs)) {
|
||||
sense = SENSE_ILLEGAL_REQUEST;
|
||||
}
|
||||
ide_atapi_cmd_error(s, sense,
|
||||
ASC_MEDIA_REMOVAL_PREVENTED);
|
||||
ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
|
||||
break;
|
||||
default:
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
{
|
||||
max_len = ube16_to_cpu(packet + 8);
|
||||
}
|
||||
|
||||
static void cmd_mechanism_status(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int max_len = ube16_to_cpu(buf + 8);
|
||||
|
||||
cpu_to_ube16(buf, 0);
|
||||
/* no current LBA */
|
||||
buf[2] = 0;
|
||||
|
@ -894,24 +938,27 @@ void ide_atapi_cmd(IDEState *s)
|
|||
buf[5] = 1;
|
||||
cpu_to_ube16(buf + 6, 0);
|
||||
ide_atapi_cmd_reply(s, 8, max_len);
|
||||
}
|
||||
break;
|
||||
case GPCMD_READ_TOC_PMA_ATIP:
|
||||
{
|
||||
}
|
||||
|
||||
static void cmd_read_toc_pma_atip(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int format, msf, start_track, len;
|
||||
uint64_t total_sectors;
|
||||
int max_len;
|
||||
|
||||
bdrv_get_geometry(s->bs, &total_sectors);
|
||||
|
||||
total_sectors >>= 2;
|
||||
if (total_sectors == 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
return;
|
||||
}
|
||||
max_len = ube16_to_cpu(packet + 7);
|
||||
format = packet[9] >> 6;
|
||||
msf = (packet[1] >> 1) & 1;
|
||||
start_track = packet[6];
|
||||
|
||||
max_len = ube16_to_cpu(buf + 7);
|
||||
format = buf[9] >> 6;
|
||||
msf = (buf[1] >> 1) & 1;
|
||||
start_track = buf[6];
|
||||
|
||||
switch(format) {
|
||||
case 0:
|
||||
len = cdrom_read_toc(total_sectors, buf, msf, start_track);
|
||||
|
@ -937,44 +984,45 @@ void ide_atapi_cmd(IDEState *s)
|
|||
error_cmd:
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPCMD_READ_CDVD_CAPACITY:
|
||||
{
|
||||
}
|
||||
|
||||
static void cmd_read_cdvd_capacity(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
uint64_t total_sectors;
|
||||
|
||||
bdrv_get_geometry(s->bs, &total_sectors);
|
||||
|
||||
total_sectors >>= 2;
|
||||
if (total_sectors == 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY,
|
||||
ASC_MEDIUM_NOT_PRESENT);
|
||||
break;
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: it is really the number of sectors minus 1 */
|
||||
cpu_to_ube32(buf, total_sectors - 1);
|
||||
cpu_to_ube32(buf + 4, 2048);
|
||||
ide_atapi_cmd_reply(s, 8, 8);
|
||||
}
|
||||
break;
|
||||
case GPCMD_READ_DVD_STRUCTURE:
|
||||
{
|
||||
int media = packet[1];
|
||||
int format = packet[7];
|
||||
}
|
||||
|
||||
static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
int max_len;
|
||||
int media = buf[1];
|
||||
int format = buf[7];
|
||||
int ret;
|
||||
|
||||
max_len = ube16_to_cpu(packet + 8);
|
||||
max_len = ube16_to_cpu(buf + 8);
|
||||
|
||||
if (format < 0xff) {
|
||||
if (media_is_cd(s)) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_INCOMPATIBLE_FORMAT);
|
||||
break;
|
||||
return;
|
||||
} else if (!media_present(s)) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,12 +1033,13 @@ void ide_atapi_cmd(IDEState *s)
|
|||
case 0x00 ... 0x7f:
|
||||
case 0xff:
|
||||
if (media == 0) {
|
||||
ret = ide_dvd_read_structure(s, format, packet, buf);
|
||||
ret = ide_dvd_read_structure(s, format, buf, buf);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
|
||||
else
|
||||
} else {
|
||||
ide_atapi_cmd_reply(s, ret, max_len);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1008,70 +1057,102 @@ void ide_atapi_cmd(IDEState *s)
|
|||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_set_speed(IDEState *s, uint8_t* buf)
|
||||
{
|
||||
ide_atapi_cmd_ok(s);
|
||||
}
|
||||
|
||||
void ide_atapi_cmd(IDEState *s)
|
||||
{
|
||||
const uint8_t *packet;
|
||||
uint8_t *buf;
|
||||
|
||||
packet = s->io_buffer;
|
||||
buf = s->io_buffer;
|
||||
#ifdef DEBUG_IDE_ATAPI
|
||||
{
|
||||
int i;
|
||||
printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
|
||||
for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
|
||||
printf(" %02x", packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If there's a UNIT_ATTENTION condition pending, only
|
||||
* REQUEST_SENSE, INQUIRY, GET_CONFIGURATION and
|
||||
* GET_EVENT_STATUS_NOTIFICATION commands are allowed to complete.
|
||||
* MMC-5, section 4.1.6.1 lists only these commands being allowed
|
||||
* to complete, with other commands getting a CHECK condition
|
||||
* response unless a higher priority status, defined by the drive
|
||||
* here, is pending.
|
||||
*/
|
||||
if (s->sense_key == SENSE_UNIT_ATTENTION &&
|
||||
s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
|
||||
s->io_buffer[0] != GPCMD_INQUIRY &&
|
||||
s->io_buffer[0] != GPCMD_GET_EVENT_STATUS_NOTIFICATION) {
|
||||
ide_atapi_cmd_check_status(s);
|
||||
return;
|
||||
}
|
||||
if (bdrv_is_inserted(s->bs) && s->cdrom_changed) {
|
||||
ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
|
||||
|
||||
s->cdrom_changed = 0;
|
||||
s->sense_key = SENSE_UNIT_ATTENTION;
|
||||
s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||
return;
|
||||
}
|
||||
switch(s->io_buffer[0]) {
|
||||
case GPCMD_TEST_UNIT_READY:
|
||||
cmd_test_unit_ready(s, buf);
|
||||
break;
|
||||
case GPCMD_MODE_SENSE_6:
|
||||
case GPCMD_MODE_SENSE_10:
|
||||
cmd_mode_sense(s, buf);
|
||||
break;
|
||||
case GPCMD_REQUEST_SENSE:
|
||||
cmd_request_sense(s, buf);
|
||||
break;
|
||||
case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
cmd_prevent_allow_medium_removal(s, buf);
|
||||
break;
|
||||
case GPCMD_READ_10:
|
||||
case GPCMD_READ_12:
|
||||
cmd_read(s, buf);
|
||||
break;
|
||||
case GPCMD_READ_CD:
|
||||
cmd_read_cd(s, buf);
|
||||
break;
|
||||
case GPCMD_SEEK:
|
||||
cmd_seek(s, buf);
|
||||
break;
|
||||
case GPCMD_START_STOP_UNIT:
|
||||
cmd_start_stop_unit(s, buf);
|
||||
break;
|
||||
case GPCMD_MECHANISM_STATUS:
|
||||
cmd_mechanism_status(s, buf);
|
||||
break;
|
||||
case GPCMD_READ_TOC_PMA_ATIP:
|
||||
cmd_read_toc_pma_atip(s, buf);
|
||||
break;
|
||||
case GPCMD_READ_CDVD_CAPACITY:
|
||||
cmd_read_cdvd_capacity(s, buf);
|
||||
break;
|
||||
case GPCMD_READ_DVD_STRUCTURE:
|
||||
cmd_read_dvd_structure(s, buf);
|
||||
break;
|
||||
case GPCMD_SET_SPEED:
|
||||
ide_atapi_cmd_ok(s);
|
||||
cmd_set_speed(s, buf);
|
||||
break;
|
||||
case GPCMD_INQUIRY:
|
||||
max_len = packet[4];
|
||||
buf[0] = 0x05; /* CD-ROM */
|
||||
buf[1] = 0x80; /* removable */
|
||||
buf[2] = 0x00; /* ISO */
|
||||
buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
|
||||
buf[4] = 31; /* additional length */
|
||||
buf[5] = 0; /* reserved */
|
||||
buf[6] = 0; /* reserved */
|
||||
buf[7] = 0; /* reserved */
|
||||
padstr8(buf + 8, 8, "QEMU");
|
||||
padstr8(buf + 16, 16, "QEMU DVD-ROM");
|
||||
padstr8(buf + 32, 4, s->version);
|
||||
ide_atapi_cmd_reply(s, 36, max_len);
|
||||
cmd_inquiry(s, buf);
|
||||
break;
|
||||
case GPCMD_GET_CONFIGURATION:
|
||||
{
|
||||
uint32_t len;
|
||||
uint8_t index = 0;
|
||||
|
||||
/* only feature 0 is supported */
|
||||
if (packet[2] != 0 || packet[3] != 0) {
|
||||
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
|
||||
ASC_INV_FIELD_IN_CMD_PACKET);
|
||||
cmd_get_configuration(s, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX: could result in alignment problems in some architectures */
|
||||
max_len = ube16_to_cpu(packet + 7);
|
||||
|
||||
/*
|
||||
* XXX: avoid overflow for io_buffer if max_len is bigger than
|
||||
* the size of that buffer (dimensioned to max number of
|
||||
* sectors to transfer at once)
|
||||
*
|
||||
* Only a problem if the feature/profiles grow.
|
||||
*/
|
||||
if (max_len > 512) /* XXX: assume 1 sector */
|
||||
max_len = 512;
|
||||
|
||||
memset(buf, 0, max_len);
|
||||
/*
|
||||
* the number of sectors from the media tells us which profile
|
||||
* to use as current. 0 means there is no media
|
||||
*/
|
||||
if (media_is_dvd(s))
|
||||
cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
|
||||
else if (media_is_cd(s))
|
||||
cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
|
||||
|
||||
buf[10] = 0x02 | 0x01; /* persistent and current */
|
||||
len = 12; /* headers: 8 + 4 */
|
||||
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 */
|
||||
|
||||
ide_atapi_cmd_reply(s, len, max_len);
|
||||
break;
|
||||
}
|
||||
case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
|
||||
handle_get_event_status_notification(s, buf, packet);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue