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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user