static void ide_atapi_cmd(IDEState *s)
{
    const uint8_t *packet;
    uint8_t *buf;
    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 and INQUIRY commands are allowed to complete. */
    if (s->sense_key == SENSE_UNIT_ATTENTION &&
	s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
	s->io_buffer[0] != GPCMD_INQUIRY) {
	ide_atapi_cmd_check_status(s);
	return;
    switch(s->io_buffer[0]) {
    case GPCMD_TEST_UNIT_READY:
        if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) {
            ide_atapi_cmd_ok(s);
        } else {
            s->cdrom_changed = 0;
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MODE_SENSE_6:
    case GPCMD_MODE_SENSE_10:
        {
            int action, code;
            if (packet[0] == GPCMD_MODE_SENSE_10)
            else
                max_len = packet[4];
            action = packet[2] >> 6;
            code = packet[2] & 0x3f;
            switch(action) {
            case 0: /* current values */
                switch(code) {
                case GPMODE_R_W_ERROR_PAGE: /* error recovery */
                    cpu_to_ube16(&buf[0], 16 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x01;
                    buf[9] = 0x06;
                    buf[10] = 0x00;
                    buf[11] = 0x05;
                    buf[12] = 0x00;
                    buf[13] = 0x00;
                    buf[14] = 0x00;
                    buf[15] = 0x00;
                    ide_atapi_cmd_reply(s, 16, max_len);
                case GPMODE_AUDIO_CTL_PAGE:
                    cpu_to_ube16(&buf[0], 24 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    /* Fill with CDROM audio volume */
                    buf[17] = 0;
                    buf[19] = 0;
                    buf[21] = 0;
                    buf[23] = 0;
                    ide_atapi_cmd_reply(s, 24, max_len);
                case GPMODE_CAPABILITIES_PAGE:
                    cpu_to_ube16(&buf[0], 28 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x2a;
                    buf[9] = 0x12;
                    buf[10] = 0x00;
                    buf[11] = 0x00;
                    /* Claim PLAY_AUDIO capability (0x01) since some Linux
                       code checks for this to automount media. */
                    buf[12] = 0x71;
                    buf[13] = 3 << 5;
                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
                    if (bdrv_is_locked(s->bs))
                        buf[6] |= 1 << 1;
                    buf[15] = 0x00;
                    cpu_to_ube16(&buf[16], 706);
                    buf[18] = 0;
                    buf[19] = 2;
                    cpu_to_ube16(&buf[20], 512);
                    cpu_to_ube16(&buf[22], 706);
                    buf[24] = 0;
                    buf[25] = 0;
                    buf[26] = 0;
                    buf[27] = 0;
                    ide_atapi_cmd_reply(s, 28, max_len);
                default:
                    goto error_cmd;
            case 1: /* changeable values */
                goto error_cmd;
            case 2: /* default values */
                goto error_cmd;
            default:
            case 3: /* saved values */
                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    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);
    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
        if (bdrv_is_inserted(s->bs)) {
            bdrv_set_locked(s->bs, packet[4] & 1);
            ide_atapi_cmd_ok(s);
        } else {
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_READ_10:
    case GPCMD_READ_12:
        {
            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 (nb_sectors == 0) {
                ide_atapi_cmd_ok(s);
            ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
    case GPCMD_READ_CD:
        {
            int nb_sectors, lba, transfer_request;
            nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
            lba = ube32_to_cpu(packet + 2);
            if (nb_sectors == 0) {
                ide_atapi_cmd_ok(s);
            transfer_request = packet[9];
            switch(transfer_request & 0xf8) {
            case 0x00:
                /* nothing */
                ide_atapi_cmd_ok(s);
            case 0x10:
                /* normal read */
                ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
            case 0xf8:
                /* read all data */
                ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
            default:
    case GPCMD_SEEK:
        {
            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);
            lba = ube32_to_cpu(packet + 2);
            if (lba >= total_sectors) {
                                    ASC_LOGICAL_BLOCK_OOR);
            ide_atapi_cmd_ok(s);
    case GPCMD_START_STOP_UNIT:
        {
            int start, eject, err = 0;
            start = packet[4] & 1;
            eject = (packet[4] >> 1) & 1;
            if (eject) {
                err = bdrv_eject(s->bs, !start);
            switch (err) {
            case 0:
                ide_atapi_cmd_ok(s);
            case -EBUSY:
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                    ASC_MEDIA_REMOVAL_PREVENTED);
            default:
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MECHANISM_STATUS:
        {
            max_len = ube16_to_cpu(packet + 8);
            cpu_to_ube16(buf, 0);
            /* no current LBA */
            buf[2] = 0;
            buf[3] = 0;
            buf[4] = 0;
            buf[5] = 1;
            cpu_to_ube16(buf + 6, 0);
            ide_atapi_cmd_reply(s, 8, max_len);
    case GPCMD_READ_TOC_PMA_ATIP:
        {
            int format, msf, start_track, len;
            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);
            format = packet[9] >> 6;
            msf = (packet[1] >> 1) & 1;
            start_track = packet[6];
            switch(format) {
            case 0:
                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(s, len, max_len);
            case 1:
                /* multi session : only a single session defined */
                memset(buf, 0, 12);
                buf[1] = 0x0a;
                buf[2] = 0x01;
                buf[3] = 0x01;
                ide_atapi_cmd_reply(s, 12, max_len);
            case 2:
                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(s, len, max_len);
            default:
            error_cmd:
    case GPCMD_READ_CDVD_CAPACITY:
        {
            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);
            /* 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);
    case GPCMD_READ_DVD_STRUCTURE:
        {
            int media = packet[1];
            int format = packet[7];
            int ret;
            max_len = ube16_to_cpu(packet + 8);
            if (format < 0xff) {
                if (media_is_cd(s)) {
                                        ASC_INCOMPATIBLE_FORMAT);
                } else if (!media_present(s)) {
            memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
                   IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
            switch (format) {
                case 0x00 ... 0x7f:
                case 0xff:
                    if (media == 0) {
                        ret = ide_dvd_read_structure(s, format, packet, buf);
                        if (ret < 0)
                            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
                        else
                            ide_atapi_cmd_reply(s, ret, max_len);
                    /* TODO: BD support, fall through for now */
                /* Generic disk structures */
                case 0x80: /* TODO: AACS volume identifier */
                case 0x81: /* TODO: AACS media serial number */
                case 0x82: /* TODO: AACS media identifier */
                case 0x83: /* TODO: AACS media key block */
                case 0x90: /* TODO: List of recognized format layers */
                case 0xc0: /* TODO: Write protection status */
                default:
    case GPCMD_SET_SPEED:
        ide_atapi_cmd_ok(s);
    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);
    case GPCMD_GET_CONFIGURATION:
        {
            uint32_t len;
            uint8_t index = 0;
            /* only feature 0 is supported */
            if (packet[2] != 0 || packet[3] != 0) {
            /* XXX: could result in alignment problems in some architectures */
            /*
             * 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);
    default:
                            ASC_ILLEGAL_OPCODE);
static void ide_atapi_cmd(IDEState *s)
{
    const uint8_t *packet;
    uint8_t *buf;
    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 (s->sense_key == SENSE_UNIT_ATTENTION &&
	s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
	s->io_buffer[0] != GPCMD_INQUIRY) {
	ide_atapi_cmd_check_status(s);
	return;
    switch(s->io_buffer[0]) {
    case GPCMD_TEST_UNIT_READY:
        if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) {
            ide_atapi_cmd_ok(s);
        } else {
            s->cdrom_changed = 0;
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MODE_SENSE_6:
    case GPCMD_MODE_SENSE_10:
        {
            int action, code;
            if (packet[0] == GPCMD_MODE_SENSE_10)
            else
                max_len = packet[4];
            action = packet[2] >> 6;
            code = packet[2] & 0x3f;
            switch(action) {
            case 0: 
                switch(code) {
                case GPMODE_R_W_ERROR_PAGE: 
                    cpu_to_ube16(&buf[0], 16 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x01;
                    buf[9] = 0x06;
                    buf[10] = 0x00;
                    buf[11] = 0x05;
                    buf[12] = 0x00;
                    buf[13] = 0x00;
                    buf[14] = 0x00;
                    buf[15] = 0x00;
                    ide_atapi_cmd_reply(s, 16, max_len);
                case GPMODE_AUDIO_CTL_PAGE:
                    cpu_to_ube16(&buf[0], 24 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    
                    buf[17] = 0;
                    buf[19] = 0;
                    buf[21] = 0;
                    buf[23] = 0;
                    ide_atapi_cmd_reply(s, 24, max_len);
                case GPMODE_CAPABILITIES_PAGE:
                    cpu_to_ube16(&buf[0], 28 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x2a;
                    buf[9] = 0x12;
                    buf[10] = 0x00;
                    buf[11] = 0x00;
                    

                    buf[12] = 0x71;
                    buf[13] = 3 << 5;
                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
                    if (bdrv_is_locked(s->bs))
                        buf[6] |= 1 << 1;
                    buf[15] = 0x00;
                    cpu_to_ube16(&buf[16], 706);
                    buf[18] = 0;
                    buf[19] = 2;
                    cpu_to_ube16(&buf[20], 512);
                    cpu_to_ube16(&buf[22], 706);
                    buf[24] = 0;
                    buf[25] = 0;
                    buf[26] = 0;
                    buf[27] = 0;
                    ide_atapi_cmd_reply(s, 28, max_len);
                default:
                    goto error_cmd;
            case 1: 
                goto error_cmd;
            case 2: 
                goto error_cmd;
            default:
            case 3: 
                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    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);
    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
        if (bdrv_is_inserted(s->bs)) {
            bdrv_set_locked(s->bs, packet[4] & 1);
            ide_atapi_cmd_ok(s);
        } else {
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_READ_10:
    case GPCMD_READ_12:
        {
            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 (nb_sectors == 0) {
                ide_atapi_cmd_ok(s);
            ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
    case GPCMD_READ_CD:
        {
            int nb_sectors, lba, transfer_request;
            nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
            lba = ube32_to_cpu(packet + 2);
            if (nb_sectors == 0) {
                ide_atapi_cmd_ok(s);
            transfer_request = packet[9];
            switch(transfer_request & 0xf8) {
            case 0x00:
                
                ide_atapi_cmd_ok(s);
            case 0x10:
                
                ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
            case 0xf8:
                
                ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
            default:
    case GPCMD_SEEK:
        {
            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);
            lba = ube32_to_cpu(packet + 2);
            if (lba >= total_sectors) {
                                    ASC_LOGICAL_BLOCK_OOR);
            ide_atapi_cmd_ok(s);
    case GPCMD_START_STOP_UNIT:
        {
            int start, eject, err = 0;
            start = packet[4] & 1;
            eject = (packet[4] >> 1) & 1;
            if (eject) {
                err = bdrv_eject(s->bs, !start);
            switch (err) {
            case 0:
                ide_atapi_cmd_ok(s);
            case -EBUSY:
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                    ASC_MEDIA_REMOVAL_PREVENTED);
            default:
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MECHANISM_STATUS:
        {
            max_len = ube16_to_cpu(packet + 8);
            cpu_to_ube16(buf, 0);
            
            buf[2] = 0;
            buf[3] = 0;
            buf[4] = 0;
            buf[5] = 1;
            cpu_to_ube16(buf + 6, 0);
            ide_atapi_cmd_reply(s, 8, max_len);
    case GPCMD_READ_TOC_PMA_ATIP:
        {
            int format, msf, start_track, len;
            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);
            format = packet[9] >> 6;
            msf = (packet[1] >> 1) & 1;
            start_track = packet[6];
            switch(format) {
            case 0:
                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(s, len, max_len);
            case 1:
                
                memset(buf, 0, 12);
                buf[1] = 0x0a;
                buf[2] = 0x01;
                buf[3] = 0x01;
                ide_atapi_cmd_reply(s, 12, max_len);
            case 2:
                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(s, len, max_len);
            default:
            error_cmd:
    case GPCMD_READ_CDVD_CAPACITY:
        {
            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);
            
            cpu_to_ube32(buf, total_sectors - 1);
            cpu_to_ube32(buf + 4, 2048);
            ide_atapi_cmd_reply(s, 8, 8);
    case GPCMD_READ_DVD_STRUCTURE:
        {
            int media = packet[1];
            int format = packet[7];
            int ret;
            max_len = ube16_to_cpu(packet + 8);
            if (format < 0xff) {
                if (media_is_cd(s)) {
                                        ASC_INCOMPATIBLE_FORMAT);
                } else if (!media_present(s)) {
            memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
                   IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
            switch (format) {
                case 0x00 ... 0x7f:
                case 0xff:
                    if (media == 0) {
                        ret = ide_dvd_read_structure(s, format, packet, buf);
                        if (ret < 0)
                            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
                        else
                            ide_atapi_cmd_reply(s, ret, max_len);
                    
                
                case 0x80: 
                case 0x81: 
                case 0x82: 
                case 0x83: 
                case 0x90: 
                case 0xc0: 
                default:
    case GPCMD_SET_SPEED:
        ide_atapi_cmd_ok(s);
    case GPCMD_INQUIRY:
        max_len = packet[4];
        buf[0] = 0x05; 
        buf[1] = 0x80; 
        buf[2] = 0x00; 
        buf[3] = 0x21; 
        buf[4] = 31; 
        buf[5] = 0; 
        buf[6] = 0; 
        buf[7] = 0; 
        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);
    case GPCMD_GET_CONFIGURATION:
        {
            uint32_t len;
            uint8_t index = 0;
            
            if (packet[2] != 0 || packet[3] != 0) {
            
            






            if (max_len > 512) 
                max_len = 512;
            memset(buf, 0, max_len);
            



            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; 
            len = 12; 
            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); 
            ide_atapi_cmd_reply(s, len, max_len);
    default:
                            ASC_ILLEGAL_OPCODE);
static void FUNC_0(IDEState *VAR_0)
{
    const uint8_t *VAR_1;
    uint8_t *buf;
    int VAR_2;
    VAR_1 = VAR_0->io_buffer;
    buf = VAR_0->io_buffer;
#ifdef DEBUG_IDE_ATAPI
    {
        int i;
        printf("ATAPI limit=0x%x VAR_1:", VAR_0->lcyl | (VAR_0->hcyl << 8));
        for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
            printf(" %02x", VAR_1[i]);
        printf("\n");
#endif
    

    if (VAR_0->sense_key == SENSE_UNIT_ATTENTION &&
	VAR_0->io_buffer[0] != GPCMD_REQUEST_SENSE &&
	VAR_0->io_buffer[0] != GPCMD_INQUIRY) {
	ide_atapi_cmd_check_status(VAR_0);
	return;
    switch(VAR_0->io_buffer[0]) {
    case GPCMD_TEST_UNIT_READY:
        if (bdrv_is_inserted(VAR_0->bs) && !VAR_0->cdrom_changed) {
            ide_atapi_cmd_ok(VAR_0);
        } else {
            VAR_0->cdrom_changed = 0;
            ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MODE_SENSE_6:
    case GPCMD_MODE_SENSE_10:
        {
            int VAR_3, VAR_4;
            if (VAR_1[0] == GPCMD_MODE_SENSE_10)
            else
                VAR_2 = VAR_1[4];
            VAR_3 = VAR_1[2] >> 6;
            VAR_4 = VAR_1[2] & 0x3f;
            switch(VAR_3) {
            case 0: 
                switch(VAR_4) {
                case GPMODE_R_W_ERROR_PAGE: 
                    cpu_to_ube16(&buf[0], 16 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x01;
                    buf[9] = 0x06;
                    buf[10] = 0x00;
                    buf[11] = 0x05;
                    buf[12] = 0x00;
                    buf[13] = 0x00;
                    buf[14] = 0x00;
                    buf[15] = 0x00;
                    ide_atapi_cmd_reply(VAR_0, 16, VAR_2);
                case GPMODE_AUDIO_CTL_PAGE:
                    cpu_to_ube16(&buf[0], 24 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    
                    buf[17] = 0;
                    buf[19] = 0;
                    buf[21] = 0;
                    buf[23] = 0;
                    ide_atapi_cmd_reply(VAR_0, 24, VAR_2);
                case GPMODE_CAPABILITIES_PAGE:
                    cpu_to_ube16(&buf[0], 28 + 6);
                    buf[2] = 0x70;
                    buf[3] = 0;
                    buf[4] = 0;
                    buf[5] = 0;
                    buf[6] = 0;
                    buf[7] = 0;
                    buf[8] = 0x2a;
                    buf[9] = 0x12;
                    buf[10] = 0x00;
                    buf[11] = 0x00;
                    

                    buf[12] = 0x71;
                    buf[13] = 3 << 5;
                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
                    if (bdrv_is_locked(VAR_0->bs))
                        buf[6] |= 1 << 1;
                    buf[15] = 0x00;
                    cpu_to_ube16(&buf[16], 706);
                    buf[18] = 0;
                    buf[19] = 2;
                    cpu_to_ube16(&buf[20], 512);
                    cpu_to_ube16(&buf[22], 706);
                    buf[24] = 0;
                    buf[25] = 0;
                    buf[26] = 0;
                    buf[27] = 0;
                    ide_atapi_cmd_reply(VAR_0, 28, VAR_2);
                default:
                    goto error_cmd;
            case 1: 
                goto error_cmd;
            case 2: 
                goto error_cmd;
            default:
            case 3: 
                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    case GPCMD_REQUEST_SENSE:
        VAR_2 = VAR_1[4];
        memset(buf, 0, 18);
        buf[0] = 0x70 | (1 << 7);
        buf[2] = VAR_0->sense_key;
        buf[7] = 10;
        buf[12] = VAR_0->asc;
        if (VAR_0->sense_key == SENSE_UNIT_ATTENTION)
            VAR_0->sense_key = SENSE_NONE;
        ide_atapi_cmd_reply(VAR_0, 18, VAR_2);
    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
        if (bdrv_is_inserted(VAR_0->bs)) {
            bdrv_set_locked(VAR_0->bs, VAR_1[4] & 1);
            ide_atapi_cmd_ok(VAR_0);
        } else {
            ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_READ_10:
    case GPCMD_READ_12:
        {
            int nb_sectors, lba;
            if (VAR_1[0] == GPCMD_READ_10)
                nb_sectors = ube16_to_cpu(VAR_1 + 7);
            else
                nb_sectors = ube32_to_cpu(VAR_1 + 6);
            lba = ube32_to_cpu(VAR_1 + 2);
            if (nb_sectors == 0) {
                ide_atapi_cmd_ok(VAR_0);
            ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2048);
    case GPCMD_READ_CD:
        {
            int nb_sectors, lba, transfer_request;
            nb_sectors = (VAR_1[6] << 16) | (VAR_1[7] << 8) | VAR_1[8];
            lba = ube32_to_cpu(VAR_1 + 2);
            if (nb_sectors == 0) {
                ide_atapi_cmd_ok(VAR_0);
            transfer_request = VAR_1[9];
            switch(transfer_request & 0xf8) {
            case 0x00:
                
                ide_atapi_cmd_ok(VAR_0);
            case 0x10:
                
                ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2048);
            case 0xf8:
                
                ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2352);
            default:
    case GPCMD_SEEK:
        {
            unsigned int lba;
            uint64_t total_sectors;
            bdrv_get_geometry(VAR_0->bs, &total_sectors);
            total_sectors >>= 2;
            if (total_sectors == 0) {
                ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
            lba = ube32_to_cpu(VAR_1 + 2);
            if (lba >= total_sectors) {
                                    ASC_LOGICAL_BLOCK_OOR);
            ide_atapi_cmd_ok(VAR_0);
    case GPCMD_START_STOP_UNIT:
        {
            int start, eject, err = 0;
            start = VAR_1[4] & 1;
            eject = (VAR_1[4] >> 1) & 1;
            if (eject) {
                err = bdrv_eject(VAR_0->bs, !start);
            switch (err) {
            case 0:
                ide_atapi_cmd_ok(VAR_0);
            case -EBUSY:
                ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                    ASC_MEDIA_REMOVAL_PREVENTED);
            default:
                ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
    case GPCMD_MECHANISM_STATUS:
        {
            VAR_2 = ube16_to_cpu(VAR_1 + 8);
            cpu_to_ube16(buf, 0);
            
            buf[2] = 0;
            buf[3] = 0;
            buf[4] = 0;
            buf[5] = 1;
            cpu_to_ube16(buf + 6, 0);
            ide_atapi_cmd_reply(VAR_0, 8, VAR_2);
    case GPCMD_READ_TOC_PMA_ATIP:
        {
            int format, msf, start_track, len;
            uint64_t total_sectors;
            bdrv_get_geometry(VAR_0->bs, &total_sectors);
            total_sectors >>= 2;
            if (total_sectors == 0) {
                ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
            format = VAR_1[9] >> 6;
            msf = (VAR_1[1] >> 1) & 1;
            start_track = VAR_1[6];
            switch(format) {
            case 0:
                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(VAR_0, len, VAR_2);
            case 1:
                
                memset(buf, 0, 12);
                buf[1] = 0x0a;
                buf[2] = 0x01;
                buf[3] = 0x01;
                ide_atapi_cmd_reply(VAR_0, 12, VAR_2);
            case 2:
                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
                if (len < 0)
                    goto error_cmd;
                ide_atapi_cmd_reply(VAR_0, len, VAR_2);
            default:
            error_cmd:
    case GPCMD_READ_CDVD_CAPACITY:
        {
            uint64_t total_sectors;
            bdrv_get_geometry(VAR_0->bs, &total_sectors);
            total_sectors >>= 2;
            if (total_sectors == 0) {
                ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
                                    ASC_MEDIUM_NOT_PRESENT);
            
            cpu_to_ube32(buf, total_sectors - 1);
            cpu_to_ube32(buf + 4, 2048);
            ide_atapi_cmd_reply(VAR_0, 8, 8);
    case GPCMD_READ_DVD_STRUCTURE:
        {
            int media = VAR_1[1];
            int format = VAR_1[7];
            int ret;
            VAR_2 = ube16_to_cpu(VAR_1 + 8);
            if (format < 0xff) {
                if (media_is_cd(VAR_0)) {
                                        ASC_INCOMPATIBLE_FORMAT);
                } else if (!media_present(VAR_0)) {
            memset(buf, 0, VAR_2 > IDE_DMA_BUF_SECTORS * 512 + 4 ?
                   IDE_DMA_BUF_SECTORS * 512 + 4 : VAR_2);
            switch (format) {
                case 0x00 ... 0x7f:
                case 0xff:
                    if (media == 0) {
                        ret = ide_dvd_read_structure(VAR_0, format, VAR_1, buf);
                        if (ret < 0)
                            ide_atapi_cmd_error(VAR_0, SENSE_ILLEGAL_REQUEST, -ret);
                        else
                            ide_atapi_cmd_reply(VAR_0, ret, VAR_2);
                    
                
                case 0x80: 
                case 0x81: 
                case 0x82: 
                case 0x83: 
                case 0x90: 
                case 0xc0: 
                default:
    case GPCMD_SET_SPEED:
        ide_atapi_cmd_ok(VAR_0);
    case GPCMD_INQUIRY:
        VAR_2 = VAR_1[4];
        buf[0] = 0x05; 
        buf[1] = 0x80; 
        buf[2] = 0x00; 
        buf[3] = 0x21; 
        buf[4] = 31; 
        buf[5] = 0; 
        buf[6] = 0; 
        buf[7] = 0; 
        padstr8(buf + 8, 8, "QEMU");
        padstr8(buf + 16, 16, "QEMU DVD-ROM");
        padstr8(buf + 32, 4, VAR_0->version);
        ide_atapi_cmd_reply(VAR_0, 36, VAR_2);
    case GPCMD_GET_CONFIGURATION:
        {
            uint32_t len;
            uint8_t index = 0;
            
            if (VAR_1[2] != 0 || VAR_1[3] != 0) {
            
            






            if (VAR_2 > 512) 
                VAR_2 = 512;
            memset(buf, 0, VAR_2);
            



            if (media_is_dvd(VAR_0))
                cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
            else if (media_is_cd(VAR_0))
                cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
            buf[10] = 0x02 | 0x01; 
            len = 12; 
            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); 
            ide_atapi_cmd_reply(VAR_0, len, VAR_2);
    default:
                            ASC_ILLEGAL_OPCODE);
static void FUNC_0(IDEState *VAR_0)
{ const uint8_t *VAR_1; uint8_t *buf; int VAR_2; VAR_1 = VAR_0->io_buffer; buf = VAR_0->io_buffer; #ifdef DEBUG_IDE_ATAPI
{ int i; printf("ATAPI limit=0x%x VAR_1:", VAR_0->lcyl | (VAR_0->hcyl << 8)); for(i = 0; i < ATAPI_PACKET_SIZE; i++) { printf(" %02x", VAR_1[i]); printf("\n"); #endif
if (VAR_0->sense_key == SENSE_UNIT_ATTENTION &&
VAR_0->io_buffer[0] != GPCMD_REQUEST_SENSE &&
VAR_0->io_buffer[0] != GPCMD_INQUIRY) { ide_atapi_cmd_check_status(VAR_0); return; switch(VAR_0->io_buffer[0]) { case GPCMD_TEST_UNIT_READY:
if (bdrv_is_inserted(VAR_0->bs) && !VAR_0->cdrom_changed) { ide_atapi_cmd_ok(VAR_0); } else { VAR_0->cdrom_changed = 0; ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
{ int VAR_3, VAR_4; if (VAR_1[0] == GPCMD_MODE_SENSE_10)
else
VAR_2 = VAR_1[4]; VAR_3 = VAR_1[2] >> 6; VAR_4 = VAR_1[2] & 0x3f; switch(VAR_3) { case 0:
switch(VAR_4) { case GPMODE_R_W_ERROR_PAGE:
cpu_to_ube16(&buf[0], 16 + 6); buf[2] = 0x70; buf[3] = 0; buf[4] = 0; buf[5] = 0; buf[6] = 0; buf[7] = 0; buf[8] = 0x01; buf[9] = 0x06; buf[10] = 0x00; buf[11] = 0x05; buf[12] = 0x00; buf[13] = 0x00; buf[14] = 0x00; buf[15] = 0x00; ide_atapi_cmd_reply(VAR_0, 16, VAR_2); case GPMODE_AUDIO_CTL_PAGE:
cpu_to_ube16(&buf[0], 24 + 6); buf[2] = 0x70; buf[3] = 0; buf[4] = 0; buf[5] = 0; buf[6] = 0; buf[7] = 0; buf[17] = 0; buf[19] = 0; buf[21] = 0; buf[23] = 0; ide_atapi_cmd_reply(VAR_0, 24, VAR_2); case GPMODE_CAPABILITIES_PAGE:
cpu_to_ube16(&buf[0], 28 + 6); buf[2] = 0x70; buf[3] = 0; buf[4] = 0; buf[5] = 0; buf[6] = 0; buf[7] = 0; buf[8] = 0x2a; buf[9] = 0x12; buf[10] = 0x00; buf[11] = 0x00; buf[12] = 0x71; buf[13] = 3 << 5; buf[14] = (1 << 0) | (1 << 3) | (1 << 5); if (bdrv_is_locked(VAR_0->bs))
buf[6] |= 1 << 1; buf[15] = 0x00; cpu_to_ube16(&buf[16], 706); buf[18] = 0; buf[19] = 2; cpu_to_ube16(&buf[20], 512); cpu_to_ube16(&buf[22], 706); buf[24] = 0; buf[25] = 0; buf[26] = 0; buf[27] = 0; ide_atapi_cmd_reply(VAR_0, 28, VAR_2); default:
goto error_cmd; case 1:
goto error_cmd; case 2:
goto error_cmd; default:
case 3:
ASC_SAVING_PARAMETERS_NOT_SUPPORTED); case GPCMD_REQUEST_SENSE:
VAR_2 = VAR_1[4]; memset(buf, 0, 18); buf[0] = 0x70 | (1 << 7); buf[2] = VAR_0->sense_key; buf[7] = 10; buf[12] = VAR_0->asc; if (VAR_0->sense_key == SENSE_UNIT_ATTENTION)
VAR_0->sense_key = SENSE_NONE; ide_atapi_cmd_reply(VAR_0, 18, VAR_2); case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
if (bdrv_is_inserted(VAR_0->bs)) { bdrv_set_locked(VAR_0->bs, VAR_1[4] & 1); ide_atapi_cmd_ok(VAR_0); } else { ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); case GPCMD_READ_10:
case GPCMD_READ_12:
{ int nb_sectors, lba; if (VAR_1[0] == GPCMD_READ_10)
nb_sectors = ube16_to_cpu(VAR_1 + 7); else
nb_sectors = ube32_to_cpu(VAR_1 + 6); lba = ube32_to_cpu(VAR_1 + 2); if (nb_sectors == 0) { ide_atapi_cmd_ok(VAR_0); ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2048); case GPCMD_READ_CD:
{ int nb_sectors, lba, transfer_request; nb_sectors = (VAR_1[6] << 16) | (VAR_1[7] << 8) | VAR_1[8]; lba = ube32_to_cpu(VAR_1 + 2); if (nb_sectors == 0) { ide_atapi_cmd_ok(VAR_0); transfer_request = VAR_1[9]; switch(transfer_request & 0xf8) { case 0x00:
ide_atapi_cmd_ok(VAR_0); case 0x10:
ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2048); case 0xf8:
ide_atapi_cmd_read(VAR_0, lba, nb_sectors, 2352); default:
case GPCMD_SEEK:
{ unsigned int lba; uint64_t total_sectors; bdrv_get_geometry(VAR_0->bs, &total_sectors); total_sectors >>= 2; if (total_sectors == 0) { ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); lba = ube32_to_cpu(VAR_1 + 2); if (lba >= total_sectors) { ASC_LOGICAL_BLOCK_OOR); ide_atapi_cmd_ok(VAR_0); case GPCMD_START_STOP_UNIT:
{ int start, eject, err = 0; start = VAR_1[4] & 1; eject = (VAR_1[4] >> 1) & 1; if (eject) { err = bdrv_eject(VAR_0->bs, !start); switch (err) { case 0:
ide_atapi_cmd_ok(VAR_0); case -EBUSY:
ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIA_REMOVAL_PREVENTED); default:
ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); case GPCMD_MECHANISM_STATUS:
{ VAR_2 = ube16_to_cpu(VAR_1 + 8); cpu_to_ube16(buf, 0); buf[2] = 0; buf[3] = 0; buf[4] = 0; buf[5] = 1; cpu_to_ube16(buf + 6, 0); ide_atapi_cmd_reply(VAR_0, 8, VAR_2); case GPCMD_READ_TOC_PMA_ATIP:
{ int format, msf, start_track, len; uint64_t total_sectors; bdrv_get_geometry(VAR_0->bs, &total_sectors); total_sectors >>= 2; if (total_sectors == 0) { ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); format = VAR_1[9] >> 6; msf = (VAR_1[1] >> 1) & 1; start_track = VAR_1[6]; switch(format) { case 0:
len = cdrom_read_toc(total_sectors, buf, msf, start_track); if (len < 0)
goto error_cmd; ide_atapi_cmd_reply(VAR_0, len, VAR_2); case 1:
memset(buf, 0, 12); buf[1] = 0x0a; buf[2] = 0x01; buf[3] = 0x01; ide_atapi_cmd_reply(VAR_0, 12, VAR_2); case 2:
len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track); if (len < 0)
goto error_cmd; ide_atapi_cmd_reply(VAR_0, len, VAR_2); default:
error_cmd:
case GPCMD_READ_CDVD_CAPACITY:
{ uint64_t total_sectors; bdrv_get_geometry(VAR_0->bs, &total_sectors); total_sectors >>= 2; if (total_sectors == 0) { ide_atapi_cmd_error(VAR_0, SENSE_NOT_READY,
ASC_MEDIUM_NOT_PRESENT); cpu_to_ube32(buf, total_sectors - 1); cpu_to_ube32(buf + 4, 2048); ide_atapi_cmd_reply(VAR_0, 8, 8); case GPCMD_READ_DVD_STRUCTURE:
{ int media = VAR_1[1]; int format = VAR_1[7]; int ret; VAR_2 = ube16_to_cpu(VAR_1 + 8); if (format < 0xff) { if (media_is_cd(VAR_0)) { ASC_INCOMPATIBLE_FORMAT); } else if (!media_present(VAR_0)) { memset(buf, 0, VAR_2 > IDE_DMA_BUF_SECTORS * 512 + 4 ?
IDE_DMA_BUF_SECTORS * 512 + 4 : VAR_2); switch (format) { case 0x00 ... 0x7f:
case 0xff:
if (media == 0) { ret = ide_dvd_read_structure(VAR_0, format, VAR_1, buf); if (ret < 0)
ide_atapi_cmd_error(VAR_0, SENSE_ILLEGAL_REQUEST, -ret); else
ide_atapi_cmd_reply(VAR_0, ret, VAR_2); case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x90:
case 0xc0:
default:
case GPCMD_SET_SPEED:
ide_atapi_cmd_ok(VAR_0); case GPCMD_INQUIRY:
VAR_2 = VAR_1[4]; buf[0] = 0x05; buf[1] = 0x80; buf[2] = 0x00; buf[3] = 0x21; buf[4] = 31; buf[5] = 0; buf[6] = 0; buf[7] = 0; padstr8(buf + 8, 8, "QEMU"); padstr8(buf + 16, 16, "QEMU DVD-ROM"); padstr8(buf + 32, 4, VAR_0->version); ide_atapi_cmd_reply(VAR_0, 36, VAR_2); case GPCMD_GET_CONFIGURATION:
{ uint32_t len; uint8_t index = 0; if (VAR_1[2] != 0 || VAR_1[3] != 0) { if (VAR_2 > 512)
VAR_2 = 512; memset(buf, 0, VAR_2); if (media_is_dvd(VAR_0))
cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM); else if (media_is_cd(VAR_0))
cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM); buf[10] = 0x02 | 0x01; len = 12; 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); ide_atapi_cmd_reply(VAR_0, len, VAR_2); default:
ASC_ILLEGAL_OPCODE);