* [Qemu-devel] ATAPI pass throug v4 @ 2009-08-07 17:33 Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 1/7] atapi: fix up a few comments Alexandre Bique 2009-08-10 20:09 ` [Qemu-devel] ATAPI pass throug v4 Anthony Liguori 0 siblings, 2 replies; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel Hi, This is the new version of the ATAPI pass through patches. What's new from the v3 ? - applied Christoph and Juan comments - made some part of ide.c public and added new files: - ide.h some defines, structures and function declarations - atapi-defines.h atapi related defines and function to retrive name from the command - atapi-data.c some data tables - atapi-pt.h atapi pass through structures and public functions - atapi-pt.c atapi pass through implementation I hope this one is alright. Thanks. ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 1/7] atapi: fix up a few comments 2009-08-07 17:33 [Qemu-devel] ATAPI pass throug v4 Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 2/7] atapi: protocol define updates Alexandre Bique 2009-08-10 20:09 ` [Qemu-devel] ATAPI pass throug v4 Anthony Liguori 1 sibling, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- hw/ide.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ide.c b/hw/ide.c index 6cf04a6..e4e2ab7 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -1680,9 +1680,9 @@ static void ide_atapi_cmd(IDEState *s) switch(action) { case 0: /* current values */ switch(code) { - case 0x01: /* error recovery */ + case 0x01: /* read write error recovery parameters */ cpu_to_ube16(&buf[0], 16 + 6); - buf[2] = 0x70; + buf[2] = 0x70; /* Obsolete: medium type code */ buf[3] = 0; buf[4] = 0; buf[5] = 0; @@ -1699,17 +1699,17 @@ static void ide_atapi_cmd(IDEState *s) buf[15] = 0x00; ide_atapi_cmd_reply(s, 16, max_len); break; - case 0x2a: + case 0x2a: /* CD/DVD capabilities & mechanical status */ cpu_to_ube16(&buf[0], 28 + 6); - buf[2] = 0x70; + buf[2] = 0x70; /* Obsolete: medium type code */ buf[3] = 0; buf[4] = 0; buf[5] = 0; buf[6] = 0; buf[7] = 0; - buf[8] = 0x2a; - buf[9] = 0x12; + buf[8] = 0x2a; /* page code */ + buf[9] = 0x12; /* page length */ buf[10] = 0x00; buf[11] = 0x00; -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/7] atapi: protocol define updates 2009-08-07 17:33 ` [Qemu-devel] [PATCH 1/7] atapi: fix up a few comments Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 3/7] atapi: guessing if the cdrom device is a scsi device Alexandre Bique 0 siblings, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique Add some missing ATAPI protocol defintions, and fix up some whitespaces and comments on the way. Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- hw/ide.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 60 insertions(+), 17 deletions(-) diff --git a/hw/ide.c b/hw/ide.c index e4e2ab7..5c2693e 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -216,13 +216,17 @@ #define ATAPI_PACKET_SIZE 12 -/* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +/********************************************************************* + * Generic Packet commands, MMC commands, and such + *********************************************************************/ + + /* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ #define GPCMD_BLANK 0xa1 #define GPCMD_CLOSE_TRACK 0x5b #define GPCMD_FLUSH_CACHE 0x35 #define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_CONFIGURATION 0x46 #define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a #define GPCMD_GET_PERFORMANCE 0xac #define GPCMD_INQUIRY 0x12 @@ -238,6 +242,8 @@ #define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define GPCMD_READ_10 0x28 #define GPCMD_READ_12 0xa8 +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_READ_BUFFER_CAPACITY 0x5c #define GPCMD_READ_CDVD_CAPACITY 0x25 #define GPCMD_READ_CD 0xbe #define GPCMD_READ_CD_MSF 0xb9 @@ -246,15 +252,16 @@ #define GPCMD_READ_FORMAT_CAPACITIES 0x23 #define GPCMD_READ_HEADER 0x44 #define GPCMD_READ_TRACK_RZONE_INFO 0x52 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 #define GPCMD_REPAIR_RZONE_TRACK 0x58 #define GPCMD_REPORT_KEY 0xa4 #define GPCMD_REQUEST_SENSE 0x03 #define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SEND_CUE_SHEET 0x5d #define GPCMD_SCAN 0xba #define GPCMD_SEEK 0x2b -#define GPCMD_SEND_DVD_STRUCTURE 0xad +#define GPCMD_SEND_DVD_STRUCTURE 0xbf #define GPCMD_SEND_EVENT 0xa2 #define GPCMD_SEND_KEY 0xa3 #define GPCMD_SEND_OPC 0x54 @@ -263,9 +270,11 @@ #define GPCMD_START_STOP_UNIT 0x1b #define GPCMD_STOP_PLAY_SCAN 0x4e #define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_VERIFY_10 0x2f +#define GPCMD_VERIFY_10 0x2f #define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_12 0xaa #define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_WRITE_BUFFER 0x3b /* This is listed as optional in ATAPI 2.6, but is (curiously) * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji * Table 377 as an MMC command for SCSi devices though... Most ATAPI @@ -279,18 +288,20 @@ * older drives only. */ #define GPCMD_GET_MEDIA_STATUS 0xda -#define GPCMD_MODE_SENSE_6 0x1a +#define GPCMD_MODE_SENSE_6 0x1a /* Mode page codes for mode sense/set */ +#define GPMODE_VENDOR_PAGE 0x00 #define GPMODE_R_W_ERROR_PAGE 0x01 #define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_WCACHING_PAGE 0x08 #define GPMODE_AUDIO_CTL_PAGE 0x0e #define GPMODE_POWER_PAGE 0x1a #define GPMODE_FAULT_FAIL_PAGE 0x1c #define GPMODE_TO_PROTECT_PAGE 0x1d #define GPMODE_CAPABILITIES_PAGE 0x2a #define GPMODE_ALL_PAGES 0x3f -/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor +/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor * of MODE_SENSE_POWER_PAGE */ #define GPMODE_CDROM_PAGE 0x0d @@ -304,10 +315,26 @@ */ /* Some generally useful CD-ROM information */ -#define CD_MINS 80 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_MINS 80 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ +#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ +#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ +#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ +#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ +#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ +/* most drives don't deliver everything: */ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ + #define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) #define CD_MAX_SECTORS (CD_MAX_BYTES / 512) @@ -346,12 +373,15 @@ #define MMC_PROFILE_HDDVD_RW_DL 0x005A #define MMC_PROFILE_INVALID 0xFFFF + #define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ #define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ #define ATAPI_INT_REASON_REL 0x04 #define ATAPI_INT_REASON_TAG 0xf8 /* same constants as bochs */ +#define ASC_NONE 0x00 +#define ASC_READ_ERROR 0x11 #define ASC_ILLEGAL_OPCODE 0x20 #define ASC_LOGICAL_BLOCK_OOR 0x21 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 @@ -367,10 +397,23 @@ #define CFA_INVALID_ADDRESS 0x21 #define CFA_ADDRESS_OVERFLOW 0x2f -#define SENSE_NONE 0 -#define SENSE_NOT_READY 2 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 +/* Sense keys */ +#define SENSE_NONE 0 +#define SENSE_RECOVERED_ERROR 1 +#define SENSE_NOT_READY 2 +#define SENSE_MEDIUM_ERROR 3 +#define SENSE_HARDWARE_ERROR 4 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 +#define SENSE_DATA_PROTECT 7 +#define SENSE_BLANK_CHECK 8 +#define SENSE_VENDOR_SPECIFIC 9 +#define SENSE_COPY_ABORTED 10 +#define SENSE_ABORTED_COMMAND 11 +#define SENSE_VOLUME_OVERFLOW 13 +#define SENSE_MISCOMPARE 14 + +#define IO_BUFFER_MAX_SIZE (IDE_DMA_BUF_SECTORS * 512 + 4) struct IDEState; -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/7] atapi: guessing if the cdrom device is a scsi device. 2009-08-07 17:33 ` [Qemu-devel] [PATCH 2/7] atapi: protocol define updates Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 4/7] atapi: adds header guards to hw/pcmia.h Alexandre Bique 0 siblings, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique ATAPI pass through code is enabled when the block device is a scsi device. So we have to guess if the block device is a scsi device in cdrom_open(). Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- block/raw-posix.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index bdee07f..ebb13d4 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1305,6 +1305,14 @@ static int cdrom_open(BlockDriverState *bs, const char *filename, int flags) s->type = FTYPE_CD; /* open will not fail even if no CD is inserted, so add O_NONBLOCK */ +#if defined(__linux__) && defined(CONFIG_AIO) + if (strstart(filename, "/dev/sg", NULL) || + strstart(filename, "/dev/cd", NULL) || + strstart(filename, "/dev/dvd", NULL) || + strstart(filename, "/dev/sr", NULL)) { + bs->sg = 1; + } +#endif return raw_open_common(bs, filename, flags, O_NONBLOCK); } -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 4/7] atapi: adds header guards to hw/pcmia.h 2009-08-07 17:33 ` [Qemu-devel] [PATCH 3/7] atapi: guessing if the cdrom device is a scsi device Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 5/7] atapi: adds header guards to hw/mac_dbdma.h Alexandre Bique 0 siblings, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- hw/pcmcia.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/pcmcia.h b/hw/pcmcia.h index 7171504..3c59698 100644 --- a/hw/pcmcia.h +++ b/hw/pcmcia.h @@ -1,5 +1,8 @@ /* PCMCIA/Cardbus */ +#ifndef PCMCIA_H +#define PCMCIA_H + #include "qemu-common.h" typedef struct { @@ -49,3 +52,5 @@ struct PCMCIACardState { /* dscm1xxxx.c */ PCMCIACardState *dscm1xxxx_init(BlockDriverState *bdrv); + +#endif -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 5/7] atapi: adds header guards to hw/mac_dbdma.h 2009-08-07 17:33 ` [Qemu-devel] [PATCH 4/7] atapi: adds header guards to hw/pcmia.h Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi Alexandre Bique 0 siblings, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- hw/mac_dbdma.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/hw/mac_dbdma.h b/hw/mac_dbdma.h index d236c5b..fc37590 100644 --- a/hw/mac_dbdma.h +++ b/hw/mac_dbdma.h @@ -20,6 +20,9 @@ * THE SOFTWARE. */ +#ifndef MAC_DBDMA_H +#define MAC_DBDMA_H + typedef struct DBDMA_io DBDMA_io; typedef void (*DBDMA_flush)(DBDMA_io *io); @@ -41,3 +44,5 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, void *opaque); void DBDMA_schedule(void); void* DBDMA_init (int *dbdma_mem_index); + +#endif /* !MAC_DBDMA_H */ -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi. 2009-08-07 17:33 ` [Qemu-devel] [PATCH 5/7] atapi: adds header guards to hw/mac_dbdma.h Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 7/7] atapi: introducing atapi pass through Alexandre Bique 0 siblings, 1 reply; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- hw/atapi-data.c | 269 ++++++++++++++++++++++++++ hw/atapi-defines.h | 234 ++++++++++++++++++++++ hw/ide.c | 544 ++-------------------------------------------------- hw/ide.h | 377 ++++++++++++++++++++++++++++++++++++ 4 files changed, 893 insertions(+), 531 deletions(-) create mode 100644 hw/atapi-data.c create mode 100644 hw/atapi-defines.h create mode 100644 hw/ide.h diff --git a/hw/atapi-data.c b/hw/atapi-data.c new file mode 100644 index 0000000..b995b77 --- /dev/null +++ b/hw/atapi-data.c @@ -0,0 +1,269 @@ +/* + * ATAPI pass through addition data + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "atapi-defines.h" + +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned short packet_command; + const char * const text; +} packet_command_texts[] = { + { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, + { GPCMD_REQUEST_SENSE, "Request Sense" }, + { GPCMD_FORMAT_UNIT, "Format Unit" }, + { GPCMD_INQUIRY, "Inquiry" }, + { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, + { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, + { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, + { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, + { GPCMD_READ_10, "Read 10" }, + { GPCMD_WRITE_10, "Write 10" }, + { GPCMD_SEEK, "Seek" }, + { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, + { GPCMD_VERIFY_10, "Verify 10" }, + { GPCMD_FLUSH_CACHE, "Flush Cache" }, + { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, + { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, + { GPCMD_READ_HEADER, "Read Header" }, + { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, + { GPCMD_GET_CONFIGURATION, "Get Configuration" }, + { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, + { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, + { GPCMD_GET_EVENT_STATUS_NOTIFICATION, + "Get Event Status Notification" }, + { GPCMD_PAUSE_RESUME, "Pause/Resume" }, + { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, + { GPCMD_READ_DISC_INFO, "Read Disc Info" }, + { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, + { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, + { GPCMD_SEND_OPC, "Send OPC" }, + { GPCMD_MODE_SELECT_10, "Mode Select 10" }, + { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, + { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, + { GPCMD_CLOSE_TRACK, "Close Track" }, + { GPCMD_BLANK, "Blank" }, + { GPCMD_SEND_EVENT, "Send Event" }, + { GPCMD_SEND_KEY, "Send Key" }, + { GPCMD_REPORT_KEY, "Report Key" }, + { GPCMD_LOAD_UNLOAD, "Load/Unload" }, + { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, + { GPCMD_READ_12, "Read 12" }, + { GPCMD_GET_PERFORMANCE, "Get Performance" }, + { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, + { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, + { GPCMD_SET_STREAMING, "Set Streaming" }, + { GPCMD_READ_CD_MSF, "Read CD MSF" }, + { GPCMD_SCAN, "Scan" }, + { GPCMD_SET_SPEED, "Set Speed" }, + { GPCMD_PLAY_CD, "Play CD" }, + { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, + { GPCMD_READ_CD, "Read CD" }, + { GPCMD_READ_BUFFER_CAPACITY, "Read Buffer Capacity" }, + { GPCMD_READ_BUFFER, "Read Buffer" }, + { GPCMD_SEND_CUE_SHEET, "Send Cue Sheet" }, + { 0, 0 } +}; + +const char *atapi_cmd_to_str(int cmd) +{ + int i; + + for (i = 0; packet_command_texts[i].text; ++i) + if (packet_command_texts[i].packet_command == cmd) + return packet_command_texts[i].text; + return 0; +} + +/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +const char * const sense_key_texts[16] = { + "No sense data", + "Recovered error", + "Not ready", + "Medium error", + "Hardware error", + "Illegal request", + "Unit attention", + "Data protect", + "Blank check", + "(reserved)", + "(reserved)", + "Aborted command", + "(reserved)", + "(reserved)", + "Miscompare", + "(reserved)", +}; + +/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned long asc_ascq; + const char * const text; +} sense_data_texts[] = { + { 0x000000, "No additional sense information" }, + { 0x000011, "Play operation in progress" }, + { 0x000012, "Play operation paused" }, + { 0x000013, "Play operation successfully completed" }, + { 0x000014, "Play operation stopped due to error" }, + { 0x000015, "No current audio status to return" }, + { 0x010c0a, "Write error - padding blocks added" }, + { 0x011700, "Recovered data with no error correction applied" }, + { 0x011701, "Recovered data with retries" }, + { 0x011702, "Recovered data with positive head offset" }, + { 0x011703, "Recovered data with negative head offset" }, + { 0x011704, "Recovered data with retries and/or CIRC applied" }, + { 0x011705, "Recovered data using previous sector ID" }, + { 0x011800, "Recovered data with error correction applied" }, + { 0x011801, "Recovered data with error correction and retries applied"}, + { 0x011802, "Recovered data - the data was auto-reallocated" }, + { 0x011803, "Recovered data with CIRC" }, + { 0x011804, "Recovered data with L-EC" }, + { 0x015d00, "Failure prediction threshold exceeded" + " - Predicted logical unit failure" }, + { 0x015d01, "Failure prediction threshold exceeded" + " - Predicted media failure" }, + { 0x015dff, "Failure prediction threshold exceeded - False" }, + { 0x017301, "Power calibration area almost full" }, + { 0x020400, "Logical unit not ready - cause not reportable" }, + /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ + { 0x020401, "Logical unit not ready" + " - in progress [sic] of becoming ready" }, + { 0x020402, "Logical unit not ready - initializing command required" }, + { 0x020403, "Logical unit not ready - manual intervention required" }, + { 0x020404, "Logical unit not ready - format in progress" }, + { 0x020407, "Logical unit not ready - operation in progress" }, + { 0x020408, "Logical unit not ready - long write in progress" }, + { 0x020600, "No reference position found (media may be upside down)" }, + { 0x023000, "Incompatible medium installed" }, + { 0x023a00, "Medium not present" }, + { 0x025300, "Media load or eject failed" }, + { 0x025700, "Unable to recover table of contents" }, + { 0x030300, "Peripheral device write fault" }, + { 0x030301, "No write current" }, + { 0x030302, "Excessive write errors" }, + { 0x030c00, "Write error" }, + { 0x030c01, "Write error - Recovered with auto reallocation" }, + { 0x030c02, "Write error - auto reallocation failed" }, + { 0x030c03, "Write error - recommend reassignment" }, + { 0x030c04, "Compression check miscompare error" }, + { 0x030c05, "Data expansion occurred during compress" }, + { 0x030c06, "Block not compressible" }, + { 0x030c07, "Write error - recovery needed" }, + { 0x030c08, "Write error - recovery failed" }, + { 0x030c09, "Write error - loss of streaming" }, + { 0x031100, "Unrecovered read error" }, + { 0x031106, "CIRC unrecovered error" }, + { 0x033101, "Format command failed" }, + { 0x033200, "No defect spare location available" }, + { 0x033201, "Defect list update failure" }, + { 0x035100, "Erase failure" }, + { 0x037200, "Session fixation error" }, + { 0x037201, "Session fixation error writin lead-in" }, + { 0x037202, "Session fixation error writin lead-out" }, + { 0x037300, "CD control error" }, + { 0x037302, "Power calibration area is full" }, + { 0x037303, "Power calibration area error" }, + { 0x037304, "Program memory area / RMA update failure" }, + { 0x037305, "Program memory area / RMA is full" }, + { 0x037306, "Program memory area / RMA is (almost) full" }, + { 0x040200, "No seek complete" }, + { 0x040300, "Write fault" }, + { 0x040900, "Track following error" }, + { 0x040901, "Tracking servo failure" }, + { 0x040902, "Focus servo failure" }, + { 0x040903, "Spindle servo failure" }, + { 0x041500, "Random positioning error" }, + { 0x041501, "Mechanical positioning or changer error" }, + { 0x041502, "Positioning error detected by read of medium" }, + { 0x043c00, "Mechanical positioning or changer error" }, + { 0x044000, "Diagnostic failure on component (ASCQ)" }, + { 0x044400, "Internal CD/DVD logical unit failure" }, + { 0x04b600, "Media load mechanism failed" }, + { 0x051a00, "Parameter list length error" }, + { 0x052000, "Invalid command operation code" }, + { 0x052100, "Logical block address out of range" }, + { 0x052102, "Invalid address for write" }, + { 0x052400, "Invalid field in command packet" }, + { 0x052600, "Invalid field in parameter list" }, + { 0x052601, "Parameter not supported" }, + { 0x052602, "Parameter value invalid" }, + { 0x052700, "Write protected media" }, + { 0x052c00, "Command sequence error" }, + { 0x052c03, "Current program area is not empty" }, + { 0x052c04, "Current program area is empty" }, + { 0x053001, "Cannot read medium - unknown format" }, + { 0x053002, "Cannot read medium - incompatible format" }, + { 0x053900, "Saving parameters not supported" }, + { 0x054e00, "Overlapped commands attempted" }, + { 0x055302, "Medium removal prevented" }, + { 0x055500, "System resource failure" }, + { 0x056300, "End of user area encountered on this track" }, + { 0x056400, "Illegal mode for this track or incompatible medium" }, + { 0x056f00, "Copy protection key exchange failure" + " - Authentication failure" }, + { 0x056f01, "Copy protection key exchange failure - Key not present" }, + { 0x056f02, "Copy protection key exchange failure" + " - Key not established" }, + { 0x056f03, "Read of scrambled sector without authentication" }, + { 0x056f04, "Media region code is mismatched to logical unit" }, + { 0x056f05, "Drive region must be permanent" + " / region reset count error" }, + { 0x057203, "Session fixation error - incomplete track in session" }, + { 0x057204, "Empty or partially written reserved track" }, + { 0x057205, "No more RZONE reservations are allowed" }, + { 0x05bf00, "Loss of streaming" }, + { 0x062800, "Not ready to ready transition, medium may have changed" }, + { 0x062900, "Power on, reset or hardware reset occurred" }, + { 0x062a00, "Parameters changed" }, + { 0x062a01, "Mode parameters changed" }, + { 0x062e00, "Insufficient time for operation" }, + { 0x063f00, "Logical unit operating conditions have changed" }, + { 0x063f01, "Microcode has been changed" }, + { 0x065a00, "Operator request or state change input (unspecified)" }, + { 0x065a01, "Operator medium removal request" }, + { 0x0bb900, "Play operation aborted" }, + /* Here we use 0xff for the key (not a valid key) to signify + * that these can have _any_ key value associated with them... */ + { 0xff0401, "Logical unit is in process of becoming ready" }, + { 0xff0400, "Logical unit not ready, cause not reportable" }, + { 0xff0402, "Logical unit not ready, initializing command required" }, + { 0xff0403, "Logical unit not ready, manual intervention required" }, + { 0xff0500, "Logical unit does not respond to selection" }, + { 0xff0800, "Logical unit communication failure" }, + { 0xff0802, "Logical unit communication parity error" }, + { 0xff0801, "Logical unit communication time-out" }, + { 0xff2500, "Logical unit not supported" }, + { 0xff4c00, "Logical unit failed self-configuration" }, + { 0xff3e00, "Logical unit has not self-configured yet" }, +}; + +const char *atapi_ascq_to_str(int ascq) +{ + int i; + + for (i = 0; sense_data_texts[i].text; ++i) + if (sense_data_texts[i].asc_ascq == ascq) + return sense_data_texts[i].text; + return 0; +} diff --git a/hw/atapi-defines.h b/hw/atapi-defines.h new file mode 100644 index 0000000..82b1da4 --- /dev/null +++ b/hw/atapi-defines.h @@ -0,0 +1,234 @@ +/* + * ATAPI definitions + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ATAPI_DEFINES_H +#define ATAPI_DEFINES_H + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/********************************************************************* + * Generic Packet commands, MMC commands, and such + *********************************************************************/ + + /* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_READ_BUFFER_CAPACITY 0x5c +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SEND_CUE_SHEET 0x5d +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xbf +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_12 0xaa +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_WRITE_BUFFER 0x3b +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda +#define GPCMD_MODE_SENSE_6 0x1a + +/* Mode page codes for mode sense/set */ +#define GPMODE_VENDOR_PAGE 0x00 +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_WCACHING_PAGE 0x08 +#define GPMODE_AUDIO_CTL_PAGE 0x0e +#define GPMODE_POWER_PAGE 0x1a +#define GPMODE_FAULT_FAIL_PAGE 0x1c +#define GPMODE_TO_PROTECT_PAGE 0x1d +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f +/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor + * of MODE_SENSE_POWER_PAGE */ +#define GPMODE_CDROM_PAGE 0x0d + +/* + * Based on values from <linux/cdrom.h> but extending CD_MINS + * to the maximum common size allowed by the Orange's Book ATIP + * + * 90 and 99 min CDs are also available but using them as the + * upper limit reduces the effectiveness of the heuristic to + * detect DVDs burned to less than 25% of their maximum capacity + */ + +/* Some generally useful CD-ROM information */ +#define CD_MINS 80 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ +#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ +#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ +#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ +#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ +#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ +/* most drives don't deliver everything: */ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ + +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) +#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) + +/* + * The MMC values are not IDE specific and might need to be moved + * to a common header if they are also needed for the SCSI emulation + */ + +/* Profile list from MMC-6 revision 1 table 91 */ +#define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_CD_ROM 0x0008 +#define MMC_PROFILE_CD_R 0x0009 +#define MMC_PROFILE_CD_RW 0x000A +#define MMC_PROFILE_DVD_ROM 0x0010 +#define MMC_PROFILE_DVD_R_SR 0x0011 +#define MMC_PROFILE_DVD_RAM 0x0012 +#define MMC_PROFILE_DVD_RW_RO 0x0013 +#define MMC_PROFILE_DVD_RW_SR 0x0014 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016 +#define MMC_PROFILE_DVD_RW_DL 0x0017 +#define MMC_PROFILE_DVD_DDR 0x0018 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A +#define MMC_PROFILE_DVD_PLUS_R 0x001B +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B +#define MMC_PROFILE_BD_ROM 0x0040 +#define MMC_PROFILE_BD_R_SRM 0x0041 +#define MMC_PROFILE_BD_R_RRM 0x0042 +#define MMC_PROFILE_BD_RE 0x0043 +#define MMC_PROFILE_HDDVD_ROM 0x0050 +#define MMC_PROFILE_HDDVD_R 0x0051 +#define MMC_PROFILE_HDDVD_RAM 0x0052 +#define MMC_PROFILE_HDDVD_RW 0x0053 +#define MMC_PROFILE_HDDVD_R_DL 0x0058 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A +#define MMC_PROFILE_INVALID 0xFFFF + + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_NONE 0x00 +#define ASC_READ_ERROR 0x11 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 + +#define CFA_NO_ERROR 0x00 +#define CFA_MISC_ERROR 0x09 +#define CFA_INVALID_COMMAND 0x20 +#define CFA_INVALID_ADDRESS 0x21 +#define CFA_ADDRESS_OVERFLOW 0x2f + +/* Sense keys */ +#define SENSE_NONE 0 +#define SENSE_RECOVERED_ERROR 1 +#define SENSE_NOT_READY 2 +#define SENSE_MEDIUM_ERROR 3 +#define SENSE_HARDWARE_ERROR 4 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 +#define SENSE_DATA_PROTECT 7 +#define SENSE_BLANK_CHECK 8 +#define SENSE_VENDOR_SPECIFIC 9 +#define SENSE_COPY_ABORTED 10 +#define SENSE_ABORTED_COMMAND 11 +#define SENSE_VOLUME_OVERFLOW 13 +#define SENSE_MISCOMPARE 14 + +extern const char * const sense_key_texts[16]; + +const char *atapi_cmd_to_str(int cmd); +const char *atapi_ascq_to_str(int ascq); + +#endif /* !ATAPI_DEFINES_H */ diff --git a/hw/ide.c b/hw/ide.c index 5c2693e..9db9cb2 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -35,6 +35,8 @@ #include "mac_dbdma.h" #include "sh.h" #include "dma.h" +#include "ide.h" +#include "atapi-defines.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -42,452 +44,6 @@ //#define DEBUG_AIO #define USE_DMA_CDROM -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SRV_STAT 0x10 -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* Bits of HD_NSECTOR */ -#define CD 0x01 -#define IO 0x02 -#define REL 0x04 -#define TAG_MASK 0xf8 - -#define IDE_CMD_RESET 0x04 -#define IDE_CMD_DISABLE_IRQ 0x02 - -/* ATA/ATAPI Commands pre T13 Spec */ -#define WIN_NOP 0x00 -/* - * 0x01->0x02 Reserved - */ -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ -/* - * 0x04->0x07 Reserved - */ -#define WIN_SRST 0x08 /* ATAPI soft reset command */ -#define WIN_DEVICE_RESET 0x08 -/* - * 0x09->0x0F Reserved - */ -#define WIN_RECAL 0x10 -#define WIN_RESTORE WIN_RECAL -/* - * 0x10->0x1F Reserved - */ -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ -#define WIN_READ_LONG 0x22 /* 28-Bit */ -#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ -#define WIN_READ_EXT 0x24 /* 48-Bit */ -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ -/* - * 0x28 - */ -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ -/* - * 0x2A->0x2F Reserved - */ -#define WIN_WRITE 0x30 /* 28-Bit */ -#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ -#define WIN_WRITE_LONG 0x32 /* 28-Bit */ -#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ -/* - * 0x3A->0x3B Reserved - */ -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ -/* - * 0x3D->0x3F Reserved - */ -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ -#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ -/* - * 0x43->0x4F Reserved - */ -#define WIN_FORMAT 0x50 -/* - * 0x51->0x5F Reserved - */ -#define WIN_INIT 0x60 -/* - * 0x61->0x5F Reserved - */ -#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_DOWNLOAD_MICROCODE 0x92 -#define WIN_STANDBYNOW2 0x94 -#define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */ -#define WIN_STANDBY2 0x96 -#define WIN_SETIDLE2 0x97 -#define WIN_CHECKPOWERMODE2 0x98 -#define WIN_SLEEPNOW2 0x99 -/* - * 0x9A VENDOR - */ -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_QUEUED_SERVICE 0xA2 -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ -#define CFA_ACCESS_METADATA_STORAGE 0xB8 -#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ -#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ -#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ -#define WIN_GETMEDIASTATUS 0xDA -#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ -#define WIN_POSTBOOT 0xDC -#define WIN_PREBOOT 0xDD -#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ -#define WIN_SETIDLE1 0xE3 -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEPNOW1 0xE6 -#define WIN_FLUSH_CACHE 0xE7 -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ -#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ - /* SET_FEATURES 0x22 or 0xDD */ -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_MEDIAEJECT 0xED -#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define EXABYTE_ENABLE_NEST 0xF0 -#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */ -#define WIN_SECURITY_SET_PASS 0xF1 -#define WIN_SECURITY_UNLOCK 0xF2 -#define WIN_SECURITY_ERASE_PREPARE 0xF3 -#define WIN_SECURITY_ERASE_UNIT 0xF4 -#define WIN_SECURITY_FREEZE_LOCK 0xF5 -#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */ -#define WIN_SECURITY_DISABLE 0xF6 -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ -#define WIN_SET_MAX 0xF9 -#define DISABLE_SEAGATE 0xFB - -/* set to 1 set disable mult support */ -#define MAX_MULT_SECTORS 16 - -#define IDE_DMA_BUF_SECTORS 256 - -#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) -#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" -#endif - -/* ATAPI defines */ - -#define ATAPI_PACKET_SIZE 12 - -/********************************************************************* - * Generic Packet commands, MMC commands, and such - *********************************************************************/ - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -#define GPCMD_BLANK 0xa1 -#define GPCMD_CLOSE_TRACK 0x5b -#define GPCMD_FLUSH_CACHE 0x35 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_GET_PERFORMANCE 0xac -#define GPCMD_INQUIRY 0x12 -#define GPCMD_LOAD_UNLOAD 0xa6 -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TI 0x48 -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define GPCMD_READ_10 0x28 -#define GPCMD_READ_12 0xa8 -#define GPCMD_READ_BUFFER 0x3c -#define GPCMD_READ_BUFFER_CAPACITY 0x5c -#define GPCMD_READ_CDVD_CAPACITY 0x25 -#define GPCMD_READ_CD 0xbe -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_READ_DISC_INFO 0x51 -#define GPCMD_READ_DVD_STRUCTURE 0xad -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_READ_TRACK_RZONE_INFO 0x52 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_REPAIR_RZONE_TRACK 0x58 -#define GPCMD_REPORT_KEY 0xa4 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_RESERVE_RZONE_TRACK 0x53 -#define GPCMD_SEND_CUE_SHEET 0x5d -#define GPCMD_SCAN 0xba -#define GPCMD_SEEK 0x2b -#define GPCMD_SEND_DVD_STRUCTURE 0xbf -#define GPCMD_SEND_EVENT 0xa2 -#define GPCMD_SEND_KEY 0xa3 -#define GPCMD_SEND_OPC 0x54 -#define GPCMD_SET_READ_AHEAD 0xa7 -#define GPCMD_SET_STREAMING 0xb6 -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_WRITE_10 0x2a -#define GPCMD_WRITE_12 0xaa -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -#define GPCMD_WRITE_BUFFER 0x3b -/* This is listed as optional in ATAPI 2.6, but is (curiously) - * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji - * Table 377 as an MMC command for SCSi devices though... Most ATAPI - * drives support it. */ -#define GPCMD_SET_SPEED 0xbb -/* This seems to be a SCSI specific CD-ROM opcode - * to play data at track/index */ -#define GPCMD_PLAYAUDIO_TI 0x48 -/* - * From MS Media Status Notification Support Specification. For - * older drives only. - */ -#define GPCMD_GET_MEDIA_STATUS 0xda -#define GPCMD_MODE_SENSE_6 0x1a - -/* Mode page codes for mode sense/set */ -#define GPMODE_VENDOR_PAGE 0x00 -#define GPMODE_R_W_ERROR_PAGE 0x01 -#define GPMODE_WRITE_PARMS_PAGE 0x05 -#define GPMODE_WCACHING_PAGE 0x08 -#define GPMODE_AUDIO_CTL_PAGE 0x0e -#define GPMODE_POWER_PAGE 0x1a -#define GPMODE_FAULT_FAIL_PAGE 0x1c -#define GPMODE_TO_PROTECT_PAGE 0x1d -#define GPMODE_CAPABILITIES_PAGE 0x2a -#define GPMODE_ALL_PAGES 0x3f -/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor - * of MODE_SENSE_POWER_PAGE */ -#define GPMODE_CDROM_PAGE 0x0d - -/* - * Based on values from <linux/cdrom.h> but extending CD_MINS - * to the maximum common size allowed by the Orange's Book ATIP - * - * 90 and 99 min CDs are also available but using them as the - * upper limit reduces the effectiveness of the heuristic to - * detect DVDs burned to less than 25% of their maximum capacity - */ - -/* Some generally useful CD-ROM information */ -#define CD_MINS 80 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ -#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ -#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ -#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ -#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ -#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ -#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ -#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ -#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ -#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ -#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ -/* most drives don't deliver everything: */ -#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ -#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ - -#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) -#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) - -/* - * The MMC values are not IDE specific and might need to be moved - * to a common header if they are also needed for the SCSI emulation - */ - -/* Profile list from MMC-6 revision 1 table 91 */ -#define MMC_PROFILE_NONE 0x0000 -#define MMC_PROFILE_CD_ROM 0x0008 -#define MMC_PROFILE_CD_R 0x0009 -#define MMC_PROFILE_CD_RW 0x000A -#define MMC_PROFILE_DVD_ROM 0x0010 -#define MMC_PROFILE_DVD_R_SR 0x0011 -#define MMC_PROFILE_DVD_RAM 0x0012 -#define MMC_PROFILE_DVD_RW_RO 0x0013 -#define MMC_PROFILE_DVD_RW_SR 0x0014 -#define MMC_PROFILE_DVD_R_DL_SR 0x0015 -#define MMC_PROFILE_DVD_R_DL_JR 0x0016 -#define MMC_PROFILE_DVD_RW_DL 0x0017 -#define MMC_PROFILE_DVD_DDR 0x0018 -#define MMC_PROFILE_DVD_PLUS_RW 0x001A -#define MMC_PROFILE_DVD_PLUS_R 0x001B -#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A -#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B -#define MMC_PROFILE_BD_ROM 0x0040 -#define MMC_PROFILE_BD_R_SRM 0x0041 -#define MMC_PROFILE_BD_R_RRM 0x0042 -#define MMC_PROFILE_BD_RE 0x0043 -#define MMC_PROFILE_HDDVD_ROM 0x0050 -#define MMC_PROFILE_HDDVD_R 0x0051 -#define MMC_PROFILE_HDDVD_RAM 0x0052 -#define MMC_PROFILE_HDDVD_RW 0x0053 -#define MMC_PROFILE_HDDVD_R_DL 0x0058 -#define MMC_PROFILE_HDDVD_RW_DL 0x005A -#define MMC_PROFILE_INVALID 0xFFFF - - -#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ -#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ -#define ATAPI_INT_REASON_REL 0x04 -#define ATAPI_INT_REASON_TAG 0xf8 - -/* same constants as bochs */ -#define ASC_NONE 0x00 -#define ASC_READ_ERROR 0x11 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LOGICAL_BLOCK_OOR 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 -#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 - -#define CFA_NO_ERROR 0x00 -#define CFA_MISC_ERROR 0x09 -#define CFA_INVALID_COMMAND 0x20 -#define CFA_INVALID_ADDRESS 0x21 -#define CFA_ADDRESS_OVERFLOW 0x2f - -/* Sense keys */ -#define SENSE_NONE 0 -#define SENSE_RECOVERED_ERROR 1 -#define SENSE_NOT_READY 2 -#define SENSE_MEDIUM_ERROR 3 -#define SENSE_HARDWARE_ERROR 4 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 -#define SENSE_DATA_PROTECT 7 -#define SENSE_BLANK_CHECK 8 -#define SENSE_VENDOR_SPECIFIC 9 -#define SENSE_COPY_ABORTED 10 -#define SENSE_ABORTED_COMMAND 11 -#define SENSE_VOLUME_OVERFLOW 13 -#define SENSE_MISCOMPARE 14 - -#define IO_BUFFER_MAX_SIZE (IDE_DMA_BUF_SECTORS * 512 + 4) - -struct IDEState; - -typedef void EndTransferFunc(struct IDEState *); - -/* NOTE: IDEState represents in fact one drive */ -typedef struct IDEState { - /* ide config */ - int is_cdrom; - int is_cf; - int cylinders, heads, sectors; - int64_t nb_sectors; - int mult_sectors; - int identify_set; - uint16_t identify_data[256]; - qemu_irq irq; - PCIDevice *pci_dev; - struct BMDMAState *bmdma; - int drive_serial; - char drive_serial_str[21]; - /* ide regs */ - uint8_t feature; - uint8_t error; - uint32_t nsector; - uint8_t sector; - uint8_t lcyl; - uint8_t hcyl; - /* other part of tf for lba48 support */ - uint8_t hob_feature; - uint8_t hob_nsector; - uint8_t hob_sector; - uint8_t hob_lcyl; - uint8_t hob_hcyl; - - uint8_t select; - uint8_t status; - - /* 0x3f6 command, only meaningful for drive 0 */ - uint8_t cmd; - /* set for lba48 access */ - uint8_t lba48; - /* depends on bit 4 in select, only meaningful for drive 0 */ - struct IDEState *cur_drive; - BlockDriverState *bs; - /* ATAPI specific */ - uint8_t sense_key; - uint8_t asc; - int packet_transfer_size; - int elementary_transfer_size; - int io_buffer_index; - int lba; - int cd_sector_size; - int atapi_dma; /* true if dma is requested for the packet cmd */ - /* ATA DMA state */ - int io_buffer_size; - QEMUSGList sg; - /* PIO transfer handling */ - int req_nb_sectors; /* number of sectors per interrupt */ - EndTransferFunc *end_transfer_func; - uint8_t *data_ptr; - uint8_t *data_end; - uint8_t *io_buffer; - QEMUTimer *sector_write_timer; /* only used for win2k install hack */ - uint32_t irq_count; /* counts IRQs when using win2k install hack */ - /* CF-ATA extended error */ - uint8_t ext_error; - /* CF-ATA metadata storage */ - uint32_t mdata_size; - uint8_t *mdata_storage; - int media_changed; - /* for pmac */ - int is_read; -} IDEState; - /* XXX: DVDs that could fit on a CD will be reported as a CD */ static inline int media_present(IDEState *s) { @@ -504,59 +60,9 @@ static inline int media_is_cd(IDEState *s) return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS); } -#define BM_STATUS_DMAING 0x01 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_INT 0x04 -#define BM_STATUS_DMA_RETRY 0x08 -#define BM_STATUS_PIO_RETRY 0x10 - -#define BM_CMD_START 0x01 -#define BM_CMD_READ 0x08 - -#define IDE_TYPE_PIIX3 0 -#define IDE_TYPE_CMD646 1 -#define IDE_TYPE_PIIX4 2 - -/* CMD646 specific */ -#define MRDMODE 0x71 -#define MRDMODE_INTR_CH0 0x04 -#define MRDMODE_INTR_CH1 0x08 -#define MRDMODE_BLK_CH0 0x10 -#define MRDMODE_BLK_CH1 0x20 -#define UDIDETCR0 0x73 -#define UDIDETCR1 0x7B - -typedef struct BMDMAState { - uint8_t cmd; - uint8_t status; - uint32_t addr; - - struct PCIIDEState *pci_dev; - /* current transfer state */ - uint32_t cur_addr; - uint32_t cur_prd_last; - uint32_t cur_prd_addr; - uint32_t cur_prd_len; - IDEState *ide_if; - BlockDriverCompletionFunc *dma_cb; - BlockDriverAIOCB *aiocb; - struct iovec iov; - QEMUIOVector qiov; - int64_t sector_num; - uint32_t nsector; - QEMUBH *bh; -} BMDMAState; - -typedef struct PCIIDEState { - PCIDevice dev; - IDEState ide_if[4]; - BMDMAState bmdma[2]; - int type; /* see IDE_TYPE_xxx */ -} PCIIDEState; - -static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); static void ide_dma_restart(IDEState *s); static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); +static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); static void padstr(char *str, const char *src, int len) { @@ -655,7 +161,7 @@ static void ide_identify(IDEState *s) s->identify_set = 1; } -static void ide_atapi_identify(IDEState *s) +void ide_atapi_identify(IDEState *s) { uint16_t *p; @@ -801,7 +307,7 @@ static inline void ide_dma_submit_check(IDEState *s, dma_cb(bm, -1); } -static inline void ide_set_irq(IDEState *s) +void ide_set_irq(IDEState *s) { BMDMAState *bm = s->bmdma; if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { @@ -813,8 +319,8 @@ static inline void ide_set_irq(IDEState *s) } /* prepare data transfer and tell what to do after */ -static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, - EndTransferFunc *end_transfer_func) +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func) { s->end_transfer_func = end_transfer_func; s->data_ptr = buf; @@ -823,7 +329,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, s->status |= DRQ_STAT; } -static void ide_transfer_stop(IDEState *s) +void ide_transfer_stop(IDEState *s) { s->end_transfer_func = ide_transfer_stop; s->data_ptr = s->io_buffer; @@ -994,7 +500,7 @@ static int ide_handle_write_error(IDEState *s, int error, int op) } /* return 0 if buffer completed */ -static int dma_buf_rw(BMDMAState *bm, int is_write) +int dma_buf_rw(BMDMAState *bm, int is_write) { IDEState *s = bm->ide_if; struct { @@ -1237,7 +743,7 @@ static void ide_sector_write_dma(IDEState *s) ide_dma_start(s, ide_write_dma_cb); } -static void ide_atapi_cmd_ok(IDEState *s) +void ide_atapi_cmd_ok(IDEState *s) { s->error = 0; s->status = READY_STAT | SEEK_STAT; @@ -1269,30 +775,6 @@ static void ide_atapi_cmd_check_status(IDEState *s) ide_set_irq(s); } -static inline void cpu_to_ube16(uint8_t *buf, int val) -{ - buf[0] = val >> 8; - buf[1] = val & 0xff; -} - -static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) -{ - buf[0] = val >> 24; - buf[1] = val >> 16; - buf[2] = val >> 8; - buf[3] = val & 0xff; -} - -static inline int ube16_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 8) | buf[1]; -} - -static inline int ube32_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - static void lba_to_msf(uint8_t *buf, int lba) { lba += 150; @@ -1340,7 +822,7 @@ static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, return ret; } -static void ide_atapi_io_error(IDEState *s, int ret) +void ide_atapi_io_error(IDEState *s, int ret) { /* XXX: handle more errors */ if (ret == -ENOMEDIUM) { @@ -1432,7 +914,7 @@ static void ide_atapi_cmd_reply_end(IDEState *s) } /* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ -static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) +void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) { if (size > max_size) size = max_size; @@ -3003,7 +2485,7 @@ static void ide_map(PCIDevice *pci_dev, int region_num, } } -static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) +void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) { BMDMAState *bm = s->bmdma; if(!bm) diff --git a/hw/ide.h b/hw/ide.h new file mode 100644 index 0000000..064e2d3 --- /dev/null +++ b/hw/ide.h @@ -0,0 +1,377 @@ +/* + * QEMU IDE disk and CD/DVD-ROM Emulator definitions + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef IDE_H +#define IDE_H + +#include "hw.h" +#include "pc.h" +#include "pci.h" +#include "scsi-disk.h" +#include "pcmcia.h" +#include "block.h" +#include "block_int.h" +#include "qemu-timer.h" +#include "sysemu.h" +#include "ppc_mac.h" +#include "mac_dbdma.h" +#include "sh.h" +#include "dma.h" +#include "atapi-defines.h" + +#include <stdint.h> + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SRV_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* Bits of HD_NSECTOR */ +#define CD 0x01 +#define IO 0x02 +#define REL 0x04 +#define TAG_MASK 0xf8 + +#define IDE_CMD_RESET 0x04 +#define IDE_CMD_DISABLE_IRQ 0x02 + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +#define WIN_RESTORE WIN_RECAL +/* + * 0x10->0x1F Reserved + */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* + * 0x28 + */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ +#define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ +#define WIN_INIT 0x60 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */ +#define WIN_STANDBY2 0x96 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ACCESS_METADATA_STORAGE 0xB8 +#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ +#define WIN_POSTBOOT 0xDC +#define WIN_PREBOOT 0xDD +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ + /* SET_FEATURES 0x22 or 0xDD */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */ +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */ +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* set to 1 set disable mult support */ +#define MAX_MULT_SECTORS 16 + +#define IDE_DMA_BUF_SECTORS 256 + +#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) +#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" +#endif + +#define IO_BUFFER_MAX_SIZE (IDE_DMA_BUF_SECTORS * 512 + 4) + +struct IDEState; + +typedef void EndTransferFunc(struct IDEState *); + +/* NOTE: IDEState represents in fact one drive */ +typedef struct IDEState { + /* ide config */ + int is_cdrom; + int is_cf; + int cylinders, heads, sectors; + int64_t nb_sectors; + int mult_sectors; + int identify_set; + uint16_t identify_data[256]; + qemu_irq irq; + PCIDevice *pci_dev; + struct BMDMAState *bmdma; + int drive_serial; + char drive_serial_str[21]; + /* ide regs */ + uint8_t feature; + uint8_t error; + uint32_t nsector; + uint8_t sector; + uint8_t lcyl; + uint8_t hcyl; + /* other part of tf for lba48 support */ + uint8_t hob_feature; + uint8_t hob_nsector; + uint8_t hob_sector; + uint8_t hob_lcyl; + uint8_t hob_hcyl; + + uint8_t select; + uint8_t status; + + /* 0x3f6 command, only meaningful for drive 0 */ + uint8_t cmd; + /* set for lba48 access */ + uint8_t lba48; + /* depends on bit 4 in select, only meaningful for drive 0 */ + struct IDEState *cur_drive; + BlockDriverState *bs; + /* ATAPI specific */ + uint8_t sense_key; + uint8_t asc; + int packet_transfer_size; + int elementary_transfer_size; + int io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ + /* ATA DMA state */ + int io_buffer_size; + QEMUSGList sg; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ + EndTransferFunc *end_transfer_func; + uint8_t *data_ptr; + uint8_t *data_end; + uint8_t *io_buffer; + QEMUTimer *sector_write_timer; /* only used for win2k install hack */ + uint32_t irq_count; /* counts IRQs when using win2k install hack */ + /* CF-ATA extended error */ + uint8_t ext_error; + /* CF-ATA metadata storage */ + uint32_t mdata_size; + uint8_t *mdata_storage; + int media_changed; + /* for pmac */ + int is_read; +} IDEState; + +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 +#define BM_STATUS_DMA_RETRY 0x08 +#define BM_STATUS_PIO_RETRY 0x10 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + +#define IDE_TYPE_PIIX3 0 +#define IDE_TYPE_CMD646 1 +#define IDE_TYPE_PIIX4 2 + +/* CMD646 specific */ +#define MRDMODE 0x71 +#define MRDMODE_INTR_CH0 0x04 +#define MRDMODE_INTR_CH1 0x08 +#define MRDMODE_BLK_CH0 0x10 +#define MRDMODE_BLK_CH1 0x20 +#define UDIDETCR0 0x73 +#define UDIDETCR1 0x7B + +typedef struct BMDMAState { + uint8_t cmd; + uint8_t status; + uint32_t addr; + + struct PCIIDEState *pci_dev; + /* current transfer state */ + uint32_t cur_addr; + uint32_t cur_prd_last; + uint32_t cur_prd_addr; + uint32_t cur_prd_len; + IDEState *ide_if; + BlockDriverCompletionFunc *dma_cb; + BlockDriverAIOCB *aiocb; + struct iovec iov; + QEMUIOVector qiov; + int64_t sector_num; + uint32_t nsector; + QEMUBH *bh; +} BMDMAState; + +typedef struct PCIIDEState { + PCIDevice dev; + IDEState ide_if[4]; + BMDMAState bmdma[2]; + int type; /* see IDE_TYPE_xxx */ +} PCIIDEState; + +void ide_set_irq(IDEState *s); +void ide_atapi_cmd_ok(IDEState *s); +void ide_transfer_stop(IDEState *s); +void ide_atapi_io_error(IDEState *s, int ret); +int dma_buf_rw(BMDMAState *bm, int is_write); +void ide_atapi_identify(IDEState *s); +void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func); +void ide_atapi_cmd_reply(IDEState *s, int size, int max_size); + +static inline void cpu_to_ube16(uint8_t *buf, int val) +{ + buf[0] = val >> 8; + buf[1] = val & 0xff; +} + +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val & 0xff; +} + +static inline int ube16_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 8) | buf[1]; +} + +static inline int ube32_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + + +#endif /* !IDE_H */ + -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 7/7] atapi: introducing atapi pass through 2009-08-07 17:33 ` [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi Alexandre Bique @ 2009-08-07 17:33 ` Alexandre Bique 0 siblings, 0 replies; 10+ messages in thread From: Alexandre Bique @ 2009-08-07 17:33 UTC (permalink / raw) To: qemu-devel; +Cc: Alexandre Bique This patch introduce atapi pass through. The pass through code is used by default when the underlying block is a scsi device. This brings 1 new option to the command line interface: -cdrom-allow-fw-upgrade which allow to pass through the firmware upgrade which is blocked by default. See the WRITE_BUFFER command for more details. Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> --- Makefile.target | 14 +- hw/atapi-pt.c | 796 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/atapi-pt.h | 35 +++ hw/ide.c | 31 +-- hw/ide.h | 104 ++++++-- qemu-options.hx | 7 + vl.c | 5 + 7 files changed, 952 insertions(+), 40 deletions(-) create mode 100644 hw/atapi-pt.c create mode 100644 hw/atapi-pt.h diff --git a/Makefile.target b/Makefile.target index 49ba08d..cf0cb27 100644 --- a/Makefile.target +++ b/Makefile.target @@ -327,7 +327,7 @@ obj-y += e1000.o obj-y += wdt_ib700.o wdt_i6300esb.o # Hardware support -obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o +obj-i386-y = ide.o atapi-pt.o atapi-data.o pckbd.o vga.o $(sound-obj-y) dma.o obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o @@ -338,7 +338,8 @@ CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE endif # shared objects -obj-ppc-y = ppc.o ide.o vga.o $(sound-obj-y) dma.o openpic.o +obj-ppc-y = ppc.o ide.o atapi-pt.o atapi-data.o +obj-ppc-y += vga.o $(sound-obj-y) dma.o openpic.o # PREP target obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o obj-ppc-y += prep_pci.o ppc_prep.o @@ -365,7 +366,8 @@ LIBS+= $(FDT_LIBS) obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o obj-mips-y += mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o obj-mips-y += g364fb.o jazz_led.o dp8393x.o -obj-mips-y += ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o +obj-mips-y += ide.o atapi-pt.o atapi-data.o gt64xxx.o +obj-mips-y += pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o obj-mips-y += piix_pci.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y) obj-mips-y += mipsnet.o obj-mips-y += pflash_cfi01.o @@ -401,7 +403,7 @@ obj-cris-y += etraxfs_ser.o obj-cris-y += pflash_cfi02.o ifeq ($(TARGET_ARCH), sparc64) -obj-sparc-y = sun4u.o ide.o pckbd.o vga.o apb_pci.o +obj-sparc-y = sun4u.o ide.o atapi-pt.o atapi-data.o pckbd.o vga.o apb_pci.o obj-sparc-y += fdc.o mc146818rtc.o serial.o obj-sparc-y += cirrus_vga.o parallel.o else @@ -420,7 +422,7 @@ obj-arm-y += arm-semi.o obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o obj-arm-y += pflash_cfi01.o gumstix.o -obj-arm-y += zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o +obj-arm-y += zaurus.o ide.o atapi-pt.o atapi-data.o serial.o spitz.o tosa.o tc6393xb.o obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o obj-arm-y += omap2.o omap_dss.o soc_dma.o obj-arm-y += omap_sx1.o palm.o tsc210x.o @@ -438,7 +440,7 @@ endif obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o -obj-sh4-y += ide.o +obj-sh4-y += ide.o atapi-pt.o atapi-data.o obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o obj-m68k-y += m68k-semi.o dummy_m68k.o diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c new file mode 100644 index 0000000..abb5c26 --- /dev/null +++ b/hw/atapi-pt.c @@ -0,0 +1,796 @@ +/* + * ATAPI pass through implementation + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "block.h" +#include "atapi-defines.h" +#include "atapi-pt.h" + +int atapi_pt_allow_fw_upgrade = 0; + +#define DEBUG_IDE_ATAPI_PT + +#ifdef DEBUG_IDE_ATAPI_PT +# define DPRINTF(Args...) printf(Args) +# define CHECK_EQUAL(Val1, Val2) \ + do { \ + if ((Val1) != (Val2)) \ + printf("[\e[1;32m!VALUE\e[m] %s:%d, %s=%d %s=%d\n", \ + __PRETTY_FUNCTION__, __LINE__, #Val1, (Val1), \ + #Val2, (Val2)); \ + } while (0) +#else +# define DPRINTF(Args...) +# define CHECK_EQUAL(Val1, Val2) +#endif /* DEBUG_IDE_ATAPI_PT */ + +static inline uint32_t msf_to_frames(uint32_t minutes, + uint32_t seconds, + uint32_t frames) +{ + return (minutes * CD_SECS + seconds) * CD_FRAMES + frames; +} + +static void ide_atapi_pt_set_error(IDEState *s, int sense_key, int asc, int error) +{ + s->atapi_pt.sense.sense_key = sense_key; + s->atapi_pt.sense.asc = asc; + s->atapi_pt.sense.error_code = error; + s->status = READY_STAT | ERR_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +} + +static void ide_atapi_pt_error(IDEState *s) +{ + s->status = READY_STAT | ERR_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +} + +static void ide_atapi_pt_sg_io_finished(void *opaque, int ret) +{ + IDEState *s = opaque; + + if (ret) { + DPRINTF("IO error\n"); + ide_atapi_pt_error(s); + return; + } + + if (s->atapi_pt.cmd.driver_status || + s->atapi_pt.cmd.host_status || + s->atapi_pt.cmd.status) + { + DPRINTF("[\e[1;31mERROR\e[m]\n" + "\tsense_key: 0x%02x (\e[0;35m%s\e[m)\n" + "\terror: 0x%02x\n" + "\tasc: 0x%02x, 0x%x (\e[0;35m%s\e[m)\n" + "\terrno: %d (%s)\n" + "\tdriver: %d, host: %d, status: %d\n", + s->atapi_pt.sense.sense_key, + sense_key_texts[s->atapi_pt.sense.sense_key], + s->atapi_pt.sense.error_code, + s->atapi_pt.sense.asc, + s->atapi_pt.sense.ascq, + atapi_ascq_to_str(s->atapi_pt.sense.ascq), + errno, + strerror(errno) ? : "(null)", + s->atapi_pt.cmd.driver_status, + s->atapi_pt.cmd.host_status, + s->atapi_pt.cmd.status); + ide_atapi_pt_error(s); + return; + } + s->atapi_pt.cmd_sent(s); +} + +static void ide_atapi_pt_send_packet(IDEState *s) +{ + DPRINTF("[ATAPI-PT] sending command: 0x%02x (\e[0;32m%s\e[m)\n", + s->atapi_pt.request[0], atapi_cmd_to_str(s->atapi_pt.request[0])); + bdrv_aio_ioctl(s->bs, SG_IO, &s->atapi_pt.cmd, + ide_atapi_pt_sg_io_finished, s); +} + +static void ide_atapi_pt_read_finish(IDEState *s) +{ + s->atapi_pt.cmd.dxferp = s->io_buffer; + s->atapi_pt.cmd_sent = ide_atapi_cmd_ok; + ide_atapi_pt_send_packet(s); +} + +static void ide_atapi_pt_read_pio_end(IDEState *s) +{ + ide_transfer_stop(s); + ide_atapi_pt_read_finish(s); +} + +static void ide_atapi_pt_read_dma_cb(void *opaque, int ret) +{ + BMDMAState *bm = opaque; + IDEState *s = bm->ide_if; + int i = 0; + + if (ret < 0) { + ide_atapi_io_error(s, ret); + return; + } + + i = dma_buf_rw(bm, 0); + ide_atapi_pt_read_finish(s); +} + +static void ide_atapi_pt_wcmd(IDEState *s) +{ + if (s->atapi_dma) + { + /* DMA */ + s->io_buffer_index = 0; + s->io_buffer_size = s->atapi_pt.cmd.dxfer_len; + ide_dma_start(s, ide_atapi_pt_read_dma_cb); + return; + } + + /* PIO */ + s->packet_transfer_size = s->atapi_pt.cmd.dxfer_len; + s->io_buffer_size = 0; + s->elementary_transfer_size = 0; + s->io_buffer_index = 0; + s->status |= DRQ_STAT; + s->status &= ~BUSY_STAT; + s->nsector = (s->nsector & ~7) & + ~ATAPI_INT_REASON_IO & + ~ATAPI_INT_REASON_CD; + ide_transfer_start(s, s->io_buffer, s->atapi_pt.cmd.dxfer_len, + ide_atapi_pt_read_pio_end); + ide_set_irq(s); + return; +} + +static void ide_atapi_pt_read_format_capacities_sent(IDEState *s) +{ + int size = (s->io_buffer[3] << 3) + 4; + ide_atapi_cmd_reply(s, size, s->atapi_pt.cmd.dxfer_len); +} + +static void ide_atapi_pt_standard_reply(IDEState *s) +{ + uint32_t size = s->atapi_pt.reply_size_init; + + switch (s->atapi_pt.reply_size_len) + { + case 0: + break; + case 1: + size += s->io_buffer[s->atapi_pt.reply_size_offset]; + break; + case 2: + size += ube16_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); + break; + case 3: + size += ube24_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); + break; + case 4: + size += ube32_to_cpu(s->io_buffer + s->atapi_pt.reply_size_offset); + break; + default: + fprintf(stderr, + "The imposible has happened!!! We received a reply with a %d " + "bytes length field. Please inform " + "Alexandre Bique <bique.alexandre@gmail.com>.", + s->atapi_pt.reply_size_len); + assert(0); + break; + } + DPRINTF("[reply] size: %d, resid: %d, max_in:%d\n", + size, s->atapi_pt.cmd.resid, s->atapi_pt.cmd.dxfer_len); + ide_atapi_cmd_reply(s, size, s->atapi_pt.cmd.dxfer_len); +} + +/* This data comes from the "Mt. Fuji Commands for + * Multimedia Devices SFF8090i v4" page 343. */ +static int ide_atapi_pt_read_cd_block_size(const uint8_t *io_buffer) +{ + int sector_type = (io_buffer[2] >> 2) & 7; + int error_flags = (io_buffer[9] >> 1) & 3; + int flags_bits = io_buffer[9] & ~7; + int block_size = 0; + + // expected sector type + switch (sector_type) + { + case 0: // Any type + case 1: // CD-DA + block_size = (flags_bits) ? 2352 : 0; + break; + + case 2: // Mode 1 + switch (flags_bits) + { + case 0x0: block_size = 0; break; + case 0x10: + case 0x50: block_size = 2048; break; + case 0x18: + case 0x58: block_size = 2336; break; + case 0x20: + case 0x60: block_size = 4; break; + case 0x30: + case 0x70: + case 0x78: block_size = 2052; break; + case 0x38: block_size = 2340; break; + case 0x40: block_size = 0; break; + case 0xa0: block_size = 16; break; + case 0xb0: block_size = 2064; break; + case 0xb8: block_size = 2352; break; + case 0xe0: block_size = 16; break; + case 0xf0: block_size = 2064; break; + case 0xf8: block_size = 2352; break; + + default: return 0; // illegal + } + break; + + case 3: // Mode 2 + switch (flags_bits) + { + case 0x0: block_size = 0; break; + case 0x10: + case 0x50: + case 0x18: + case 0x58: block_size = 2336; break; + case 0x20: + case 0x60: block_size = 4; break; + case 0x30: + case 0x70: + case 0x78: + case 0x38: block_size = 2340; break; + case 0x40: block_size = 0; break; + case 0xa0: block_size = 16; break; + case 0xb0: + case 0xb8: block_size = 2352; break; + case 0xe0: block_size = 16; break; + case 0xf0: + case 0xf8: block_size = 2352; break; + default: return 0; // illegal + } + break; + + case 4: // Mode 2 Form 1 + switch (flags_bits) + { + case 0x0: block_size = 0; break; + case 0x10: block_size = 2048; break; + case 0x18: block_size = 2328; break; + case 0x20: block_size = 4; break; + case 0x40: block_size = 8; break; + case 0x50: block_size = 2056; break; + case 0x58: block_size = 2336; break; + case 0x60: block_size = 12; break; + case 0x70: block_size = 2060; break; + case 0x78: block_size = 2340; break; + case 0xa0: block_size = 16; break; + case 0xe0: block_size = 24; break; + case 0xf0: block_size = 2072; break; + case 0xf8: block_size = 2352; break; + default: return 0; // illegal + } + break; + + case 5: // Mode 2 Form 2 + switch (flags_bits) + { + case 0x0: block_size = 0; break; + case 0x10: + case 0x18: block_size = 2328; break; + case 0x20: block_size = 4; break; + case 0x40: block_size = 8; break; + case 0x50: + case 0x58: block_size = 2336; break; + case 0x60: block_size = 12; break; + case 0x70: + case 0x78: block_size = 2340; break; + case 0xa0: block_size = 16; break; + case 0xe0: block_size = 24; break; + case 0xf0: + case 0xf8: block_size = 2352; break; + default: return 0; // illegal + } + break; + + default: + return 0; // illegal + } + + switch (error_flags) + { + case 1: block_size += 294; break; + case 2: block_size += 296; break; + } + + return block_size; +} + +void ide_atapi_pt_cmd(IDEState *s) +{ + struct sg_io_hdr *cmd = &s->atapi_pt.cmd; + + memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE); + cmd->interface_id = 'S'; + cmd->dxfer_direction = SG_DXFER_NONE; + cmd->cmd_len = ATAPI_PACKET_SIZE; + cmd->mx_sb_len = sizeof (s->atapi_pt.sense); + cmd->dxfer_len = 0; + cmd->iovec_count = 0; + cmd->dxferp = s->io_buffer; + cmd->cmdp = s->atapi_pt.request; + cmd->sbp = (unsigned char *)&s->atapi_pt.sense; + cmd->timeout = 0xffffff; // 15 seconds + + s->status |= BUSY_STAT; + s->atapi_pt.reply_size_init = 0; + s->atapi_pt.reply_size_offset = 0; + s->atapi_pt.reply_size_len = 0; + + switch (s->io_buffer[0]) + { + /*******************/ + /* SIMPLE COMMANDS */ + /*******************/ + + case GPCMD_BLANK: // bigger timeout while blanking + cmd->timeout = 1000 * 60 * 80; // 80 mins + goto simple_cmd; + case GPCMD_CLOSE_TRACK: + cmd->timeout = 1000 * 60 * 5; // 5 mins + goto simple_cmd; + case GPCMD_FLUSH_CACHE: // also called SYNCHRONIZE_CACHE + case GPCMD_LOAD_UNLOAD: + case GPCMD_PAUSE_RESUME: + case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + case GPCMD_REPAIR_RZONE_TRACK: + case GPCMD_RESERVE_RZONE_TRACK: + case GPCMD_SCAN: + case GPCMD_SEEK: + case GPCMD_SET_READ_AHEAD: + case GPCMD_START_STOP_UNIT: + case GPCMD_STOP_PLAY_SCAN: + case GPCMD_TEST_UNIT_READY: + case GPCMD_VERIFY_10: + case GPCMD_SET_SPEED: /* FIXME: find the documentation */ + simple_cmd: + CHECK_EQUAL(s->lcyl, 0); + CHECK_EQUAL(s->hcyl, 0); + cmd->dxfer_direction = SG_DXFER_NONE; + s->atapi_pt.cmd_sent = ide_atapi_cmd_ok; + ide_atapi_pt_send_packet(s); + return; + + /******************/ + /* WRITE COMMANDS */ + /******************/ + + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7) * CD_FRAMESIZE; + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_WRITE_12: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube32_to_cpu(s->io_buffer + 6); + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_WRITE_BUFFER: + { + int32_t parameter_list_length = ube24_to_cpu(s->io_buffer + 3); + int8_t mode = s->io_buffer[1] & 0x03; + + cmd->dxfer_direction = SG_DXFER_TO_DEV; + switch (mode) + { + case 0x0: // Combined header and data mode + // The documentation is confusing because it says that parameter + // list length contains all the data, but the buffer should be + // greater than parameter list length + 4... + cmd->dxfer_len = parameter_list_length + 4; + break; + case 0x2: // Data mode + cmd->dxfer_len = parameter_list_length; + break; + case 0x1: // Vendor specific + case 0x4: // Download microcode + case 0x5: // Download microcode and save mode + case 0x6: // Download microcode with offsets + case 0x7: // Download microcode with offsets and save mode + default: + if (!atapi_pt_allow_fw_upgrade) + goto illegal_request; + cmd->dxfer_len = parameter_list_length; + break; + } + + ide_atapi_pt_wcmd(s); + return; + } + + case GPCMD_SEND_CUE_SHEET: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube24_to_cpu(s->io_buffer + 6); + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_MODE_SELECT_10: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + CHECK_EQUAL(s->lcyl | (s->hcyl << 8), cmd->dxfer_len); + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_SEND_KEY: + case GPCMD_SEND_EVENT: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 8); + if (cmd->dxfer_len == 0) + goto simple_cmd; + CHECK_EQUAL(s->lcyl | (s->hcyl << 8), cmd->dxfer_len); + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_SEND_OPC: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7) << 3; + CHECK_EQUAL(s->lcyl | (s->hcyl << 8), cmd->dxfer_len); + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_SET_STREAMING: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 9); + if (cmd->dxfer_len == 0) + goto simple_cmd; + ide_atapi_pt_wcmd(s); + return; + + case GPCMD_FORMAT_UNIT: + cmd->dxfer_direction = SG_DXFER_TO_DEV; + cmd->dxfer_len = 12; + ide_atapi_pt_wcmd(s); + return; + + /*****************/ + /* READ COMMANDS */ + /*****************/ + + case GPCMD_INQUIRY: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = s->io_buffer[4]; + s->atapi_pt.reply_size_init = 5; + s->atapi_pt.reply_size_offset = 4; + s->atapi_pt.reply_size_len = 1; + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_REQUEST_SENSE: + { + // send the previous sense command + DPRINTF("=== REQUEST SENSE ===\n" + "atapi_cmd_error: sense=0x%x asc=0x%x error=0x%x\n", + s->atapi_pt.sense.sense_key, + s->atapi_pt.sense.asc, + s->atapi_pt.sense.error_code); + + int max_size = s->io_buffer[4]; + + int size = 8 + s->atapi_pt.sense.add_sense_len; + + DPRINTF("max_size: %d, add_sense_len: %d, sizeof: %lu\n", + max_size, s->atapi_pt.sense.add_sense_len, + sizeof (s->atapi_pt.sense)); + memcpy(s->io_buffer, &s->atapi_pt.sense, sizeof (s->atapi_pt.sense)); + ide_atapi_cmd_reply(s, size, max_size); + return; + } + + case GPCMD_READ_DVD_STRUCTURE: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 8); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 4; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_HEADER: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_MECHANISM_STATUS: + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 8); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_offset = 6; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_REPORT_KEY: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 8); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 2; + s->atapi_pt.reply_size_init = 2; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_BUFFER_CAPACITY: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 2; + s->atapi_pt.reply_size_init = 2; + return; + + case GPCMD_GET_PERFORMANCE: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = 8 + 8 * ube16_to_cpu(s->io_buffer + 8); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 4; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_10: + case GPCMD_READ_12: + { + int blocksize = 0, nbblocks; + + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + switch (s->io_buffer[0]) { + case GPCMD_READ_10: + blocksize = CD_FRAMESIZE; + nbblocks = ube16_to_cpu(s->io_buffer + 7); + break; + case GPCMD_READ_12: + blocksize = CD_FRAMESIZE_RAW0; + nbblocks = ube32_to_cpu(s->io_buffer + 6); + break; + default: + assert(0); + break; + } + cmd->dxfer_len = nbblocks * blocksize; + CHECK_EQUAL(cmd->dxfer_len, (s->hcyl << 8) | s->lcyl); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + } + + case GPCMD_READ_BUFFER: + // TODO check this one is correct + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube24_to_cpu(s->io_buffer + 6); + + switch (s->io_buffer[1] & 0x7) + { + case 0: // data with header + s->atapi_pt.reply_size_init = 4; + s->atapi_pt.reply_size_len = 3; + s->atapi_pt.reply_size_offset = 1; + break; + + case 2: // data only + s->atapi_pt.reply_size_init = cmd->dxfer_len; + break; + + case 3: // header only + s->atapi_pt.reply_size_init = 4; + break; + + case 1: // vendor specific + default: + goto illegal_request; + } + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_CDVD_CAPACITY: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = 8; + CHECK_EQUAL(s->lcyl | (s->hcyl << 8), cmd->dxfer_len); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_MODE_SENSE_10: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + CHECK_EQUAL(s->lcyl | (s->hcyl << 8), cmd->dxfer_len); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 2; + s->atapi_pt.reply_size_init = 2; + //s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + case GPCMD_READ_DISC_INFO: + case GPCMD_READ_TOC_PMA_ATIP: + case GPCMD_READ_TRACK_RZONE_INFO: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 2; + s->atapi_pt.reply_size_init = 2; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_SUBCHANNEL: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_len = 2; + s->atapi_pt.reply_size_offset = 2; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_READ_CD: + { + // command fields + int block_count = ((s->io_buffer[6] << 16) | + ube16_to_cpu(s->io_buffer + 7)); + int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer); + + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = block_count * block_size; + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + } + + case GPCMD_READ_CD_MSF: + { + // command fields + int starting_frame = + msf_to_frames(s->io_buffer[3], s->io_buffer[4], s->io_buffer[5]); + int ending_frame = + msf_to_frames(s->io_buffer[6], s->io_buffer[7], s->io_buffer[8]); + int block_count = ending_frame - starting_frame; + int block_size = ide_atapi_pt_read_cd_block_size(s->io_buffer); + + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = block_count * block_size; + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + } + + case GPCMD_PLAY_AUDIO_10: + { + int block_count = ube16_to_cpu(s->io_buffer + 7); + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = block_count * CD_FRAMESIZE; + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + } + + case GPCMD_PLAY_AUDIO_MSF: + { + int starting_frame = + msf_to_frames(s->io_buffer[3], s->io_buffer[4], s->io_buffer[5]); + int ending_frame = + msf_to_frames(s->io_buffer[6], s->io_buffer[7], s->io_buffer[8]); + int block_count = ending_frame - starting_frame; + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = block_count * CD_FRAMESIZE; + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = cmd->dxfer_len; + ide_atapi_pt_send_packet(s); + return; + } + + case GPCMD_READ_FORMAT_CAPACITIES: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_read_format_capacities_sent; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_GET_CONFIGURATION: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 7); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = 4; + s->atapi_pt.reply_size_len = 4; + ide_atapi_pt_send_packet(s); + return; + + case GPCMD_SEND_DVD_STRUCTURE: + cmd->dxfer_direction = SG_DXFER_FROM_DEV; + cmd->dxfer_len = ube16_to_cpu(s->io_buffer + 8); + s->atapi_pt.cmd_sent = ide_atapi_pt_standard_reply; + s->atapi_pt.reply_size_init = 2; + s->atapi_pt.reply_size_len = 2; + ide_atapi_pt_send_packet(s); + return; + + case 0x01: // GPMODE_R_W_ERROR_PAGE ? + case 0x1a: // GPMODE_POWER_PAGE ? + case 0xfa: + case 0xfd: + case 0xf2: + case 0xf3: // WIN_SECURITY_ERASE_PREPARE ? + case 0xee: // WIN_IDENTIFY_DMA ? + case 0xdf: // WIN_DOORUNLOCK ? + DPRINTF("[\e[3;31mILLEGAL?\e[m] 0x%02x, size: %d\n", + s->io_buffer[0], s->lcyl | (s->hcyl << 8)); + illegal_request: + ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, + ASC_ILLEGAL_OPCODE, 0x70); + return; + + default: + fprintf(stderr, "[ATAPI-PT] We got an unhandled command: 0x%02x. " + "Please report.\n", s->io_buffer[0]); + exit(1); + return; + } +} + +void ide_atapi_pt_identify(IDEState *s) +{ + if (s->identify_set) { + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); + return; + } + + if (bdrv_ioctl(s->bs, HDIO_GET_IDENTITY, s->io_buffer)) { + ide_atapi_identify(s); + perror("atapi"); + exit(1); + return; + } + + memcpy(s->identify_data, s->io_buffer, sizeof(s->identify_data)); + s->identify_set = 1; +} diff --git a/hw/atapi-pt.h b/hw/atapi-pt.h new file mode 100644 index 0000000..639270e --- /dev/null +++ b/hw/atapi-pt.h @@ -0,0 +1,35 @@ +/* + * ATAPI pass through declarations + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ATAPI_PT_H +# define ATAPI_PT_H + +# include "ide.h" + +extern int atapi_pt_allow_fw_upgrade; + +void ide_atapi_pt_cmd(IDEState * s); +void ide_atapi_pt_identify(IDEState * s); + +#endif /* !ATAPI_PT_H */ diff --git a/hw/ide.c b/hw/ide.c index 9db9cb2..382b05e 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -22,21 +22,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" -#include "pc.h" -#include "pci.h" -#include "scsi-disk.h" -#include "pcmcia.h" -#include "block.h" -#include "block_int.h" -#include "qemu-timer.h" -#include "sysemu.h" -#include "ppc_mac.h" -#include "mac_dbdma.h" -#include "sh.h" -#include "dma.h" #include "ide.h" -#include "atapi-defines.h" +#include "atapi-pt.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -44,6 +31,7 @@ //#define DEBUG_AIO #define USE_DMA_CDROM + /* XXX: DVDs that could fit on a CD will be reported as a CD */ static inline int media_present(IDEState *s) { @@ -62,7 +50,6 @@ static inline int media_is_cd(IDEState *s) static void ide_dma_restart(IDEState *s); static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); -static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); static void padstr(char *str, const char *src, int len) { @@ -1977,7 +1964,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) /* ATAPI commands */ case WIN_PIDENTIFY: if (s->is_cdrom) { - ide_atapi_identify(s); + s->atapi_identify(s); s->status = READY_STAT | SEEK_STAT; ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); } else { @@ -2015,7 +2002,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) s->atapi_dma = s->feature & 1; s->nsector = 1; ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, - ide_atapi_cmd); + s->atapi_cmd); break; /* CF-ATA commands */ case CFA_REQ_EXT_ERROR_CODE: @@ -2354,6 +2341,16 @@ static void ide_init2(IDEState *ide_state, if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { s->is_cdrom = 1; + if (!bdrv_is_sg(s->bs)) { + s->atapi_cmd = ide_atapi_cmd; + s->atapi_identify = ide_atapi_identify; + } +#if CONFIG_ATAPI_PT + else { + s->atapi_cmd = ide_atapi_pt_cmd; + s->atapi_identify = ide_atapi_pt_identify; + } +#endif /* CONFIG_ATAPI_PT */ bdrv_set_change_cb(s->bs, cdrom_change_cb, s); } } diff --git a/hw/ide.h b/hw/ide.h index 064e2d3..58c74b9 100644 --- a/hw/ide.h +++ b/hw/ide.h @@ -40,7 +40,20 @@ #include "dma.h" #include "atapi-defines.h" + #include <stdint.h> +#include <limits.h> +#include <asm/byteorder.h> +#include <assert.h> + +#ifdef __linux__ +# include <linux/hdreg.h> +# define CONFIG_ATAPI_PT 1 +#else +# define CONFIG_ATAPI_PT 0 +#endif /* __linux__ */ + +#include <scsi/sg.h> /* Bits of HD_STATUS */ #define ERR_STAT 0x01 @@ -218,6 +231,50 @@ struct IDEState; typedef void EndTransferFunc(struct IDEState *); +typedef struct request_sense { +#if defined(__BIG_ENDIAN_BITFIELD) + uint8_t valid : 1; + uint8_t error_code : 7; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + uint8_t error_code : 7; + uint8_t valid : 1; +#endif + uint8_t segment_number; +#if defined(__BIG_ENDIAN_BITFIELD) + uint8_t reserved1 : 2; + uint8_t ili : 1; + uint8_t reserved2 : 1; + uint8_t sense_key : 4; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + uint8_t sense_key : 4; + uint8_t reserved2 : 1; + uint8_t ili : 1; + uint8_t reserved1 : 2; +#endif + uint8_t information[4]; + uint8_t add_sense_len; + uint8_t command_info[4]; + uint8_t asc; + uint8_t ascq; + uint8_t fruc; + uint8_t sks[3]; + uint8_t asb[46]; +} request_sense; + +#if CONFIG_ATAPI_PT +typedef struct ATAPIPassThroughState +{ + uint8_t request[ATAPI_PACKET_SIZE]; + struct sg_io_hdr cmd; + struct request_sense sense; + void (*cmd_sent)(struct IDEState *); + + uint32_t reply_size_init; // initial value + uint32_t reply_size_offset; // offset in s->io_buffer + uint32_t reply_size_len; // length in byte (0, 1, 2, 3 or 4) +} ATAPIPassThroughState; +#endif /* CONFIG_ATAPI_PT */ + /* NOTE: IDEState represents in fact one drive */ typedef struct IDEState { /* ide config */ @@ -266,6 +323,11 @@ typedef struct IDEState { int lba; int cd_sector_size; int atapi_dma; /* true if dma is requested for the packet cmd */ +#if CONFIG_ATAPI_PT + ATAPIPassThroughState atapi_pt; +#endif /* CONFIG_ATAPI_PT */ + void (*atapi_identify)(struct IDEState *); // the ATAPI identify + void (*atapi_cmd)(struct IDEState *); // the ATAPI cmd handler /* ATA DMA state */ int io_buffer_size; QEMUSGList sg; @@ -287,27 +349,27 @@ typedef struct IDEState { int is_read; } IDEState; -#define BM_STATUS_DMAING 0x01 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_INT 0x04 -#define BM_STATUS_DMA_RETRY 0x08 -#define BM_STATUS_PIO_RETRY 0x10 +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 +#define BM_STATUS_DMA_RETRY 0x08 +#define BM_STATUS_PIO_RETRY 0x10 -#define BM_CMD_START 0x01 -#define BM_CMD_READ 0x08 +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 -#define IDE_TYPE_PIIX3 0 -#define IDE_TYPE_CMD646 1 -#define IDE_TYPE_PIIX4 2 +#define IDE_TYPE_PIIX3 0 +#define IDE_TYPE_CMD646 1 +#define IDE_TYPE_PIIX4 2 /* CMD646 specific */ -#define MRDMODE 0x71 -#define MRDMODE_INTR_CH0 0x04 -#define MRDMODE_INTR_CH1 0x08 -#define MRDMODE_BLK_CH0 0x10 -#define MRDMODE_BLK_CH1 0x20 -#define UDIDETCR0 0x73 -#define UDIDETCR1 0x7B +#define MRDMODE 0x71 +#define MRDMODE_INTR_CH0 0x04 +#define MRDMODE_INTR_CH1 0x08 +#define MRDMODE_BLK_CH0 0x10 +#define MRDMODE_BLK_CH1 0x20 +#define UDIDETCR0 0x73 +#define UDIDETCR1 0x7B typedef struct BMDMAState { uint8_t cmd; @@ -367,6 +429,14 @@ static inline int ube16_to_cpu(const uint8_t *buf) return (buf[0] << 8) | buf[1]; } +#if CONFIG_ATAPI_PT /* only atapi-pt uses it so let's avoid unused + * warning */ +static inline int ube24_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 16) | (buf[1] << 8) | buf[2]; +} +#endif /* CONFIG_ATAPI_PT */ + static inline int ube32_to_cpu(const uint8_t *buf) { return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; diff --git a/qemu-options.hx b/qemu-options.hx index 1b420a3..2761223 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -91,6 +91,13 @@ Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and using @file{/dev/cdrom} as filename (@pxref{host_drives}). ETEXI +DEF("cdrom-allow-fw-upgrade", 0, QEMU_OPTION_cdrom_allow_fw_upgrade, + "-cdrom-allow-fw-upgrade allow the guest to process cdrom firmware upgrade.\n") +STEXI +@item -cdrom-allow-fw-upgrade +Allow Qemu to pass through ATAPI firmware upgrade command. +ETEXI + DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n" " [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n" diff --git a/vl.c b/vl.c index fdd4f03..e29d13c 100644 --- a/vl.c +++ b/vl.c @@ -142,6 +142,7 @@ int main(int argc, char **argv) #include "hw/smbios.h" #include "hw/xen.h" #include "hw/qdev.h" +#include "hw/atapi-pt.h" #include "bt-host.h" #include "net.h" #include "monitor.h" @@ -1792,6 +1793,7 @@ static int bt_parse(const char *opt) #define HD_ALIAS "index=%d,media=disk" #define CDROM_ALIAS "index=2,media=cdrom" +#define CDROM_PT_ALIAS "index=2,media=cdrompt" #define FD_ALIAS "index=%d,if=floppy" #define PFLASH_ALIAS "if=pflash" #define MTD_ALIAS "if=mtd" @@ -5119,6 +5121,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_cdrom: drive_add(optarg, CDROM_ALIAS); break; + case QEMU_OPTION_cdrom_allow_fw_upgrade: + atapi_pt_allow_fw_upgrade = 1; + break; case QEMU_OPTION_boot: { static const char * const params[] = { -- 1.6.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] ATAPI pass throug v4 2009-08-07 17:33 [Qemu-devel] ATAPI pass throug v4 Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 1/7] atapi: fix up a few comments Alexandre Bique @ 2009-08-10 20:09 ` Anthony Liguori 1 sibling, 0 replies; 10+ messages in thread From: Anthony Liguori @ 2009-08-10 20:09 UTC (permalink / raw) To: Alexandre Bique; +Cc: qemu-devel Alexandre Bique wrote: > Hi, > > This is the new version of the ATAPI pass through patches. > This series breaks the cris-softmmu build. Also, I think Paul and I both requested that fw upgrade not be disabled by default. I would also suggest that you only expose this as an option through qdev properties instead of a new command line option as it should be controllable on a per-device basis. Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <<19074.63829.151234.423348@mariner.uk.xensource.com>]
* [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi. [not found] <<19074.63829.151234.423348@mariner.uk.xensource.com> @ 2009-08-12 16:38 ` Ian Jackson 0 siblings, 0 replies; 10+ messages in thread From: Ian Jackson @ 2009-08-12 16:38 UTC (permalink / raw) To: qemu-devel Signed-off-by: Alexandre Bique <alexandre.bique@citrix.com> Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> --- hw/atapi-data.c | 269 ++++++++++++++++++++++++ hw/atapi-defines.h | 234 +++++++++++++++++++++ hw/ide.c | 545 ++----------------------------------------------- hw/ide.h | 579 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1095 insertions(+), 532 deletions(-) diff --git a/hw/atapi-data.c b/hw/atapi-data.c new file mode 100644 index 0000000..b995b77 --- /dev/null +++ b/hw/atapi-data.c @@ -0,0 +1,269 @@ +/* + * ATAPI pass through addition data + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "atapi-defines.h" + +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned short packet_command; + const char * const text; +} packet_command_texts[] = { + { GPCMD_TEST_UNIT_READY, "Test Unit Ready" }, + { GPCMD_REQUEST_SENSE, "Request Sense" }, + { GPCMD_FORMAT_UNIT, "Format Unit" }, + { GPCMD_INQUIRY, "Inquiry" }, + { GPCMD_START_STOP_UNIT, "Start/Stop Unit" }, + { GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" }, + { GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" }, + { GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" }, + { GPCMD_READ_10, "Read 10" }, + { GPCMD_WRITE_10, "Write 10" }, + { GPCMD_SEEK, "Seek" }, + { GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" }, + { GPCMD_VERIFY_10, "Verify 10" }, + { GPCMD_FLUSH_CACHE, "Flush Cache" }, + { GPCMD_READ_SUBCHANNEL, "Read Subchannel" }, + { GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" }, + { GPCMD_READ_HEADER, "Read Header" }, + { GPCMD_PLAY_AUDIO_10, "Play Audio 10" }, + { GPCMD_GET_CONFIGURATION, "Get Configuration" }, + { GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" }, + { GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" }, + { GPCMD_GET_EVENT_STATUS_NOTIFICATION, + "Get Event Status Notification" }, + { GPCMD_PAUSE_RESUME, "Pause/Resume" }, + { GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" }, + { GPCMD_READ_DISC_INFO, "Read Disc Info" }, + { GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" }, + { GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" }, + { GPCMD_SEND_OPC, "Send OPC" }, + { GPCMD_MODE_SELECT_10, "Mode Select 10" }, + { GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" }, + { GPCMD_MODE_SENSE_10, "Mode Sense 10" }, + { GPCMD_CLOSE_TRACK, "Close Track" }, + { GPCMD_BLANK, "Blank" }, + { GPCMD_SEND_EVENT, "Send Event" }, + { GPCMD_SEND_KEY, "Send Key" }, + { GPCMD_REPORT_KEY, "Report Key" }, + { GPCMD_LOAD_UNLOAD, "Load/Unload" }, + { GPCMD_SET_READ_AHEAD, "Set Read-ahead" }, + { GPCMD_READ_12, "Read 12" }, + { GPCMD_GET_PERFORMANCE, "Get Performance" }, + { GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" }, + { GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" }, + { GPCMD_SET_STREAMING, "Set Streaming" }, + { GPCMD_READ_CD_MSF, "Read CD MSF" }, + { GPCMD_SCAN, "Scan" }, + { GPCMD_SET_SPEED, "Set Speed" }, + { GPCMD_PLAY_CD, "Play CD" }, + { GPCMD_MECHANISM_STATUS, "Mechanism Status" }, + { GPCMD_READ_CD, "Read CD" }, + { GPCMD_READ_BUFFER_CAPACITY, "Read Buffer Capacity" }, + { GPCMD_READ_BUFFER, "Read Buffer" }, + { GPCMD_SEND_CUE_SHEET, "Send Cue Sheet" }, + { 0, 0 } +}; + +const char *atapi_cmd_to_str(int cmd) +{ + int i; + + for (i = 0; packet_command_texts[i].text; ++i) + if (packet_command_texts[i].packet_command == cmd) + return packet_command_texts[i].text; + return 0; +} + +/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +const char * const sense_key_texts[16] = { + "No sense data", + "Recovered error", + "Not ready", + "Medium error", + "Hardware error", + "Illegal request", + "Unit attention", + "Data protect", + "Blank check", + "(reserved)", + "(reserved)", + "Aborted command", + "(reserved)", + "(reserved)", + "Miscompare", + "(reserved)", +}; + +/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +static const struct { + unsigned long asc_ascq; + const char * const text; +} sense_data_texts[] = { + { 0x000000, "No additional sense information" }, + { 0x000011, "Play operation in progress" }, + { 0x000012, "Play operation paused" }, + { 0x000013, "Play operation successfully completed" }, + { 0x000014, "Play operation stopped due to error" }, + { 0x000015, "No current audio status to return" }, + { 0x010c0a, "Write error - padding blocks added" }, + { 0x011700, "Recovered data with no error correction applied" }, + { 0x011701, "Recovered data with retries" }, + { 0x011702, "Recovered data with positive head offset" }, + { 0x011703, "Recovered data with negative head offset" }, + { 0x011704, "Recovered data with retries and/or CIRC applied" }, + { 0x011705, "Recovered data using previous sector ID" }, + { 0x011800, "Recovered data with error correction applied" }, + { 0x011801, "Recovered data with error correction and retries applied"}, + { 0x011802, "Recovered data - the data was auto-reallocated" }, + { 0x011803, "Recovered data with CIRC" }, + { 0x011804, "Recovered data with L-EC" }, + { 0x015d00, "Failure prediction threshold exceeded" + " - Predicted logical unit failure" }, + { 0x015d01, "Failure prediction threshold exceeded" + " - Predicted media failure" }, + { 0x015dff, "Failure prediction threshold exceeded - False" }, + { 0x017301, "Power calibration area almost full" }, + { 0x020400, "Logical unit not ready - cause not reportable" }, + /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ + { 0x020401, "Logical unit not ready" + " - in progress [sic] of becoming ready" }, + { 0x020402, "Logical unit not ready - initializing command required" }, + { 0x020403, "Logical unit not ready - manual intervention required" }, + { 0x020404, "Logical unit not ready - format in progress" }, + { 0x020407, "Logical unit not ready - operation in progress" }, + { 0x020408, "Logical unit not ready - long write in progress" }, + { 0x020600, "No reference position found (media may be upside down)" }, + { 0x023000, "Incompatible medium installed" }, + { 0x023a00, "Medium not present" }, + { 0x025300, "Media load or eject failed" }, + { 0x025700, "Unable to recover table of contents" }, + { 0x030300, "Peripheral device write fault" }, + { 0x030301, "No write current" }, + { 0x030302, "Excessive write errors" }, + { 0x030c00, "Write error" }, + { 0x030c01, "Write error - Recovered with auto reallocation" }, + { 0x030c02, "Write error - auto reallocation failed" }, + { 0x030c03, "Write error - recommend reassignment" }, + { 0x030c04, "Compression check miscompare error" }, + { 0x030c05, "Data expansion occurred during compress" }, + { 0x030c06, "Block not compressible" }, + { 0x030c07, "Write error - recovery needed" }, + { 0x030c08, "Write error - recovery failed" }, + { 0x030c09, "Write error - loss of streaming" }, + { 0x031100, "Unrecovered read error" }, + { 0x031106, "CIRC unrecovered error" }, + { 0x033101, "Format command failed" }, + { 0x033200, "No defect spare location available" }, + { 0x033201, "Defect list update failure" }, + { 0x035100, "Erase failure" }, + { 0x037200, "Session fixation error" }, + { 0x037201, "Session fixation error writin lead-in" }, + { 0x037202, "Session fixation error writin lead-out" }, + { 0x037300, "CD control error" }, + { 0x037302, "Power calibration area is full" }, + { 0x037303, "Power calibration area error" }, + { 0x037304, "Program memory area / RMA update failure" }, + { 0x037305, "Program memory area / RMA is full" }, + { 0x037306, "Program memory area / RMA is (almost) full" }, + { 0x040200, "No seek complete" }, + { 0x040300, "Write fault" }, + { 0x040900, "Track following error" }, + { 0x040901, "Tracking servo failure" }, + { 0x040902, "Focus servo failure" }, + { 0x040903, "Spindle servo failure" }, + { 0x041500, "Random positioning error" }, + { 0x041501, "Mechanical positioning or changer error" }, + { 0x041502, "Positioning error detected by read of medium" }, + { 0x043c00, "Mechanical positioning or changer error" }, + { 0x044000, "Diagnostic failure on component (ASCQ)" }, + { 0x044400, "Internal CD/DVD logical unit failure" }, + { 0x04b600, "Media load mechanism failed" }, + { 0x051a00, "Parameter list length error" }, + { 0x052000, "Invalid command operation code" }, + { 0x052100, "Logical block address out of range" }, + { 0x052102, "Invalid address for write" }, + { 0x052400, "Invalid field in command packet" }, + { 0x052600, "Invalid field in parameter list" }, + { 0x052601, "Parameter not supported" }, + { 0x052602, "Parameter value invalid" }, + { 0x052700, "Write protected media" }, + { 0x052c00, "Command sequence error" }, + { 0x052c03, "Current program area is not empty" }, + { 0x052c04, "Current program area is empty" }, + { 0x053001, "Cannot read medium - unknown format" }, + { 0x053002, "Cannot read medium - incompatible format" }, + { 0x053900, "Saving parameters not supported" }, + { 0x054e00, "Overlapped commands attempted" }, + { 0x055302, "Medium removal prevented" }, + { 0x055500, "System resource failure" }, + { 0x056300, "End of user area encountered on this track" }, + { 0x056400, "Illegal mode for this track or incompatible medium" }, + { 0x056f00, "Copy protection key exchange failure" + " - Authentication failure" }, + { 0x056f01, "Copy protection key exchange failure - Key not present" }, + { 0x056f02, "Copy protection key exchange failure" + " - Key not established" }, + { 0x056f03, "Read of scrambled sector without authentication" }, + { 0x056f04, "Media region code is mismatched to logical unit" }, + { 0x056f05, "Drive region must be permanent" + " / region reset count error" }, + { 0x057203, "Session fixation error - incomplete track in session" }, + { 0x057204, "Empty or partially written reserved track" }, + { 0x057205, "No more RZONE reservations are allowed" }, + { 0x05bf00, "Loss of streaming" }, + { 0x062800, "Not ready to ready transition, medium may have changed" }, + { 0x062900, "Power on, reset or hardware reset occurred" }, + { 0x062a00, "Parameters changed" }, + { 0x062a01, "Mode parameters changed" }, + { 0x062e00, "Insufficient time for operation" }, + { 0x063f00, "Logical unit operating conditions have changed" }, + { 0x063f01, "Microcode has been changed" }, + { 0x065a00, "Operator request or state change input (unspecified)" }, + { 0x065a01, "Operator medium removal request" }, + { 0x0bb900, "Play operation aborted" }, + /* Here we use 0xff for the key (not a valid key) to signify + * that these can have _any_ key value associated with them... */ + { 0xff0401, "Logical unit is in process of becoming ready" }, + { 0xff0400, "Logical unit not ready, cause not reportable" }, + { 0xff0402, "Logical unit not ready, initializing command required" }, + { 0xff0403, "Logical unit not ready, manual intervention required" }, + { 0xff0500, "Logical unit does not respond to selection" }, + { 0xff0800, "Logical unit communication failure" }, + { 0xff0802, "Logical unit communication parity error" }, + { 0xff0801, "Logical unit communication time-out" }, + { 0xff2500, "Logical unit not supported" }, + { 0xff4c00, "Logical unit failed self-configuration" }, + { 0xff3e00, "Logical unit has not self-configured yet" }, +}; + +const char *atapi_ascq_to_str(int ascq) +{ + int i; + + for (i = 0; sense_data_texts[i].text; ++i) + if (sense_data_texts[i].asc_ascq == ascq) + return sense_data_texts[i].text; + return 0; +} diff --git a/hw/atapi-defines.h b/hw/atapi-defines.h new file mode 100644 index 0000000..82b1da4 --- /dev/null +++ b/hw/atapi-defines.h @@ -0,0 +1,234 @@ +/* + * ATAPI definitions + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ATAPI_DEFINES_H +#define ATAPI_DEFINES_H + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/********************************************************************* + * Generic Packet commands, MMC commands, and such + *********************************************************************/ + + /* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_READ_BUFFER_CAPACITY 0x5c +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SEND_CUE_SHEET 0x5d +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xbf +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_12 0xaa +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_WRITE_BUFFER 0x3b +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda +#define GPCMD_MODE_SENSE_6 0x1a + +/* Mode page codes for mode sense/set */ +#define GPMODE_VENDOR_PAGE 0x00 +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_WCACHING_PAGE 0x08 +#define GPMODE_AUDIO_CTL_PAGE 0x0e +#define GPMODE_POWER_PAGE 0x1a +#define GPMODE_FAULT_FAIL_PAGE 0x1c +#define GPMODE_TO_PROTECT_PAGE 0x1d +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f +/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor + * of MODE_SENSE_POWER_PAGE */ +#define GPMODE_CDROM_PAGE 0x0d + +/* + * Based on values from <linux/cdrom.h> but extending CD_MINS + * to the maximum common size allowed by the Orange's Book ATIP + * + * 90 and 99 min CDs are also available but using them as the + * upper limit reduces the effectiveness of the heuristic to + * detect DVDs burned to less than 25% of their maximum capacity + */ + +/* Some generally useful CD-ROM information */ +#define CD_MINS 80 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ +#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ +#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ +#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ +#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ +#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ +/* most drives don't deliver everything: */ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ + +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) +#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) + +/* + * The MMC values are not IDE specific and might need to be moved + * to a common header if they are also needed for the SCSI emulation + */ + +/* Profile list from MMC-6 revision 1 table 91 */ +#define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_CD_ROM 0x0008 +#define MMC_PROFILE_CD_R 0x0009 +#define MMC_PROFILE_CD_RW 0x000A +#define MMC_PROFILE_DVD_ROM 0x0010 +#define MMC_PROFILE_DVD_R_SR 0x0011 +#define MMC_PROFILE_DVD_RAM 0x0012 +#define MMC_PROFILE_DVD_RW_RO 0x0013 +#define MMC_PROFILE_DVD_RW_SR 0x0014 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016 +#define MMC_PROFILE_DVD_RW_DL 0x0017 +#define MMC_PROFILE_DVD_DDR 0x0018 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A +#define MMC_PROFILE_DVD_PLUS_R 0x001B +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B +#define MMC_PROFILE_BD_ROM 0x0040 +#define MMC_PROFILE_BD_R_SRM 0x0041 +#define MMC_PROFILE_BD_R_RRM 0x0042 +#define MMC_PROFILE_BD_RE 0x0043 +#define MMC_PROFILE_HDDVD_ROM 0x0050 +#define MMC_PROFILE_HDDVD_R 0x0051 +#define MMC_PROFILE_HDDVD_RAM 0x0052 +#define MMC_PROFILE_HDDVD_RW 0x0053 +#define MMC_PROFILE_HDDVD_R_DL 0x0058 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A +#define MMC_PROFILE_INVALID 0xFFFF + + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_NONE 0x00 +#define ASC_READ_ERROR 0x11 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 + +#define CFA_NO_ERROR 0x00 +#define CFA_MISC_ERROR 0x09 +#define CFA_INVALID_COMMAND 0x20 +#define CFA_INVALID_ADDRESS 0x21 +#define CFA_ADDRESS_OVERFLOW 0x2f + +/* Sense keys */ +#define SENSE_NONE 0 +#define SENSE_RECOVERED_ERROR 1 +#define SENSE_NOT_READY 2 +#define SENSE_MEDIUM_ERROR 3 +#define SENSE_HARDWARE_ERROR 4 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 +#define SENSE_DATA_PROTECT 7 +#define SENSE_BLANK_CHECK 8 +#define SENSE_VENDOR_SPECIFIC 9 +#define SENSE_COPY_ABORTED 10 +#define SENSE_ABORTED_COMMAND 11 +#define SENSE_VOLUME_OVERFLOW 13 +#define SENSE_MISCOMPARE 14 + +extern const char * const sense_key_texts[16]; + +const char *atapi_cmd_to_str(int cmd); +const char *atapi_ascq_to_str(int ascq); + +#endif /* !ATAPI_DEFINES_H */ diff --git a/hw/ide.c b/hw/ide.c index bc36f65..83d7acc 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -35,6 +35,8 @@ #include "mac_dbdma.h" #include "sh.h" #include "dma.h" +#include "ide.h" +#include "atapi-defines.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -42,453 +44,6 @@ //#define DEBUG_AIO #define USE_DMA_CDROM -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SRV_STAT 0x10 -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* Bits of HD_NSECTOR */ -#define CD 0x01 -#define IO 0x02 -#define REL 0x04 -#define TAG_MASK 0xf8 - -#define IDE_CMD_RESET 0x04 -#define IDE_CMD_DISABLE_IRQ 0x02 - -/* ATA/ATAPI Commands pre T13 Spec */ -#define WIN_NOP 0x00 -/* - * 0x01->0x02 Reserved - */ -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ -/* - * 0x04->0x07 Reserved - */ -#define WIN_SRST 0x08 /* ATAPI soft reset command */ -#define WIN_DEVICE_RESET 0x08 -/* - * 0x09->0x0F Reserved - */ -#define WIN_RECAL 0x10 -#define WIN_RESTORE WIN_RECAL -/* - * 0x10->0x1F Reserved - */ -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ -#define WIN_READ_LONG 0x22 /* 28-Bit */ -#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ -#define WIN_READ_EXT 0x24 /* 48-Bit */ -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ -/* - * 0x28 - */ -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ -/* - * 0x2A->0x2F Reserved - */ -#define WIN_WRITE 0x30 /* 28-Bit */ -#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ -#define WIN_WRITE_LONG 0x32 /* 28-Bit */ -#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ -/* - * 0x3A->0x3B Reserved - */ -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ -/* - * 0x3D->0x3F Reserved - */ -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ -#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ -/* - * 0x43->0x4F Reserved - */ -#define WIN_FORMAT 0x50 -/* - * 0x51->0x5F Reserved - */ -#define WIN_INIT 0x60 -/* - * 0x61->0x5F Reserved - */ -#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation */ -#define WIN_DOWNLOAD_MICROCODE 0x92 -#define WIN_STANDBYNOW2 0x94 -#define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */ -#define WIN_STANDBY2 0x96 -#define WIN_SETIDLE2 0x97 -#define WIN_CHECKPOWERMODE2 0x98 -#define WIN_SLEEPNOW2 0x99 -/* - * 0x9A VENDOR - */ -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_QUEUED_SERVICE 0xA2 -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ -#define CFA_ACCESS_METADATA_STORAGE 0xB8 -#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ -#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ -#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ -#define WIN_GETMEDIASTATUS 0xDA -#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ -#define WIN_POSTBOOT 0xDC -#define WIN_PREBOOT 0xDD -#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ -#define WIN_SETIDLE1 0xE3 -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEPNOW1 0xE6 -#define WIN_FLUSH_CACHE 0xE7 -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ -#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ - /* SET_FEATURES 0x22 or 0xDD */ -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_MEDIAEJECT 0xED -#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define EXABYTE_ENABLE_NEST 0xF0 -#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */ -#define WIN_SECURITY_SET_PASS 0xF1 -#define WIN_SECURITY_UNLOCK 0xF2 -#define WIN_SECURITY_ERASE_PREPARE 0xF3 -#define WIN_SECURITY_ERASE_UNIT 0xF4 -#define WIN_SECURITY_FREEZE_LOCK 0xF5 -#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */ -#define WIN_SECURITY_DISABLE 0xF6 -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ -#define WIN_SET_MAX 0xF9 -#define DISABLE_SEAGATE 0xFB - -/* set to 1 set disable mult support */ -#define MAX_MULT_SECTORS 16 - -#define IDE_DMA_BUF_SECTORS 256 - -#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) -#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" -#endif - -/* ATAPI defines */ - -#define ATAPI_PACKET_SIZE 12 - -/********************************************************************* - * Generic Packet commands, MMC commands, and such - *********************************************************************/ - - /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -#define GPCMD_BLANK 0xa1 -#define GPCMD_CLOSE_TRACK 0x5b -#define GPCMD_FLUSH_CACHE 0x35 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_GET_PERFORMANCE 0xac -#define GPCMD_INQUIRY 0x12 -#define GPCMD_LOAD_UNLOAD 0xa6 -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TI 0x48 -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define GPCMD_READ_10 0x28 -#define GPCMD_READ_12 0xa8 -#define GPCMD_READ_BUFFER 0x3c -#define GPCMD_READ_BUFFER_CAPACITY 0x5c -#define GPCMD_READ_CDVD_CAPACITY 0x25 -#define GPCMD_READ_CD 0xbe -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_READ_DISC_INFO 0x51 -#define GPCMD_READ_DVD_STRUCTURE 0xad -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_READ_TRACK_RZONE_INFO 0x52 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_REPAIR_RZONE_TRACK 0x58 -#define GPCMD_REPORT_KEY 0xa4 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_RESERVE_RZONE_TRACK 0x53 -#define GPCMD_SEND_CUE_SHEET 0x5d -#define GPCMD_SCAN 0xba -#define GPCMD_SEEK 0x2b -#define GPCMD_SEND_DVD_STRUCTURE 0xbf -#define GPCMD_SEND_EVENT 0xa2 -#define GPCMD_SEND_KEY 0xa3 -#define GPCMD_SEND_OPC 0x54 -#define GPCMD_SET_READ_AHEAD 0xa7 -#define GPCMD_SET_STREAMING 0xb6 -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_WRITE_10 0x2a -#define GPCMD_WRITE_12 0xaa -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -#define GPCMD_WRITE_BUFFER 0x3b -/* This is listed as optional in ATAPI 2.6, but is (curiously) - * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji - * Table 377 as an MMC command for SCSi devices though... Most ATAPI - * drives support it. */ -#define GPCMD_SET_SPEED 0xbb -/* This seems to be a SCSI specific CD-ROM opcode - * to play data at track/index */ -#define GPCMD_PLAYAUDIO_TI 0x48 -/* - * From MS Media Status Notification Support Specification. For - * older drives only. - */ -#define GPCMD_GET_MEDIA_STATUS 0xda -#define GPCMD_MODE_SENSE_6 0x1a - -/* Mode page codes for mode sense/set */ -#define GPMODE_VENDOR_PAGE 0x00 -#define GPMODE_R_W_ERROR_PAGE 0x01 -#define GPMODE_WRITE_PARMS_PAGE 0x05 -#define GPMODE_WCACHING_PAGE 0x08 -#define GPMODE_AUDIO_CTL_PAGE 0x0e -#define GPMODE_POWER_PAGE 0x1a -#define GPMODE_FAULT_FAIL_PAGE 0x1c -#define GPMODE_TO_PROTECT_PAGE 0x1d -#define GPMODE_CAPABILITIES_PAGE 0x2a -#define GPMODE_ALL_PAGES 0x3f -/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor - * of MODE_SENSE_POWER_PAGE */ -#define GPMODE_CDROM_PAGE 0x0d - -/* - * Based on values from <linux/cdrom.h> but extending CD_MINS - * to the maximum common size allowed by the Orange's Book ATIP - * - * 90 and 99 min CDs are also available but using them as the - * upper limit reduces the effectiveness of the heuristic to - * detect DVDs burned to less than 25% of their maximum capacity - */ - -/* Some generally useful CD-ROM information */ -#define CD_MINS 80 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ -#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ -#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ -#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ -#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ -#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ -#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ -#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ -#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ -#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ -#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ -/* most drives don't deliver everything: */ -#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ -#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ - -#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) -#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) - -/* - * The MMC values are not IDE specific and might need to be moved - * to a common header if they are also needed for the SCSI emulation - */ - -/* Profile list from MMC-6 revision 1 table 91 */ -#define MMC_PROFILE_NONE 0x0000 -#define MMC_PROFILE_CD_ROM 0x0008 -#define MMC_PROFILE_CD_R 0x0009 -#define MMC_PROFILE_CD_RW 0x000A -#define MMC_PROFILE_DVD_ROM 0x0010 -#define MMC_PROFILE_DVD_R_SR 0x0011 -#define MMC_PROFILE_DVD_RAM 0x0012 -#define MMC_PROFILE_DVD_RW_RO 0x0013 -#define MMC_PROFILE_DVD_RW_SR 0x0014 -#define MMC_PROFILE_DVD_R_DL_SR 0x0015 -#define MMC_PROFILE_DVD_R_DL_JR 0x0016 -#define MMC_PROFILE_DVD_RW_DL 0x0017 -#define MMC_PROFILE_DVD_DDR 0x0018 -#define MMC_PROFILE_DVD_PLUS_RW 0x001A -#define MMC_PROFILE_DVD_PLUS_R 0x001B -#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A -#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B -#define MMC_PROFILE_BD_ROM 0x0040 -#define MMC_PROFILE_BD_R_SRM 0x0041 -#define MMC_PROFILE_BD_R_RRM 0x0042 -#define MMC_PROFILE_BD_RE 0x0043 -#define MMC_PROFILE_HDDVD_ROM 0x0050 -#define MMC_PROFILE_HDDVD_R 0x0051 -#define MMC_PROFILE_HDDVD_RAM 0x0052 -#define MMC_PROFILE_HDDVD_RW 0x0053 -#define MMC_PROFILE_HDDVD_R_DL 0x0058 -#define MMC_PROFILE_HDDVD_RW_DL 0x005A -#define MMC_PROFILE_INVALID 0xFFFF - - -#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ -#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ -#define ATAPI_INT_REASON_REL 0x04 -#define ATAPI_INT_REASON_TAG 0xf8 - -/* same constants as bochs */ -#define ASC_NONE 0x00 -#define ASC_READ_ERROR 0x11 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LOGICAL_BLOCK_OOR 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 -#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 - -#define CFA_NO_ERROR 0x00 -#define CFA_MISC_ERROR 0x09 -#define CFA_INVALID_COMMAND 0x20 -#define CFA_INVALID_ADDRESS 0x21 -#define CFA_ADDRESS_OVERFLOW 0x2f - -/* Sense keys */ -#define SENSE_NONE 0 -#define SENSE_RECOVERED_ERROR 1 -#define SENSE_NOT_READY 2 -#define SENSE_MEDIUM_ERROR 3 -#define SENSE_HARDWARE_ERROR 4 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 -#define SENSE_DATA_PROTECT 7 -#define SENSE_BLANK_CHECK 8 -#define SENSE_VENDOR_SPECIFIC 9 -#define SENSE_COPY_ABORTED 10 -#define SENSE_ABORTED_COMMAND 11 -#define SENSE_VOLUME_OVERFLOW 13 -#define SENSE_MISCOMPARE 14 - -#define IO_BUFFER_MAX_SIZE (IDE_DMA_BUF_SECTORS * 512 + 4) - -struct IDEState; - -typedef void EndTransferFunc(struct IDEState *); - -/* NOTE: IDEState represents in fact one drive */ -typedef struct IDEState { - /* ide config */ - int is_cdrom; - int is_cf; - int cylinders, heads, sectors; - int64_t nb_sectors; - int mult_sectors; - int identify_set; - uint16_t identify_data[256]; - qemu_irq irq; - PCIDevice *pci_dev; - struct BMDMAState *bmdma; - int drive_serial; - char drive_serial_str[21]; - /* ide regs */ - uint8_t feature; - uint8_t error; - uint32_t nsector; - uint8_t sector; - uint8_t lcyl; - uint8_t hcyl; - /* other part of tf for lba48 support */ - uint8_t hob_feature; - uint8_t hob_nsector; - uint8_t hob_sector; - uint8_t hob_lcyl; - uint8_t hob_hcyl; - - uint8_t select; - uint8_t status; - - /* 0x3f6 command, only meaningful for drive 0 */ - uint8_t cmd; - /* set for lba48 access */ - uint8_t lba48; - /* depends on bit 4 in select, only meaningful for drive 0 */ - struct IDEState *cur_drive; - BlockDriverState *bs; - /* ATAPI specific */ - uint8_t sense_key; - uint8_t asc; - uint8_t cdrom_changed; - int packet_transfer_size; - int elementary_transfer_size; - int io_buffer_index; - int lba; - int cd_sector_size; - int atapi_dma; /* true if dma is requested for the packet cmd */ - /* ATA DMA state */ - int io_buffer_size; - QEMUSGList sg; - /* PIO transfer handling */ - int req_nb_sectors; /* number of sectors per interrupt */ - EndTransferFunc *end_transfer_func; - uint8_t *data_ptr; - uint8_t *data_end; - uint8_t *io_buffer; - QEMUTimer *sector_write_timer; /* only used for win2k install hack */ - uint32_t irq_count; /* counts IRQs when using win2k install hack */ - /* CF-ATA extended error */ - uint8_t ext_error; - /* CF-ATA metadata storage */ - uint32_t mdata_size; - uint8_t *mdata_storage; - int media_changed; - /* for pmac */ - int is_read; -} IDEState; - /* XXX: DVDs that could fit on a CD will be reported as a CD */ static inline int media_present(IDEState *s) { @@ -505,59 +60,9 @@ static inline int media_is_cd(IDEState *s) return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS); } -#define BM_STATUS_DMAING 0x01 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_INT 0x04 -#define BM_STATUS_DMA_RETRY 0x08 -#define BM_STATUS_PIO_RETRY 0x10 - -#define BM_CMD_START 0x01 -#define BM_CMD_READ 0x08 - -#define IDE_TYPE_PIIX3 0 -#define IDE_TYPE_CMD646 1 -#define IDE_TYPE_PIIX4 2 - -/* CMD646 specific */ -#define MRDMODE 0x71 -#define MRDMODE_INTR_CH0 0x04 -#define MRDMODE_INTR_CH1 0x08 -#define MRDMODE_BLK_CH0 0x10 -#define MRDMODE_BLK_CH1 0x20 -#define UDIDETCR0 0x73 -#define UDIDETCR1 0x7B - -typedef struct BMDMAState { - uint8_t cmd; - uint8_t status; - uint32_t addr; - - struct PCIIDEState *pci_dev; - /* current transfer state */ - uint32_t cur_addr; - uint32_t cur_prd_last; - uint32_t cur_prd_addr; - uint32_t cur_prd_len; - IDEState *ide_if; - BlockDriverCompletionFunc *dma_cb; - BlockDriverAIOCB *aiocb; - struct iovec iov; - QEMUIOVector qiov; - int64_t sector_num; - uint32_t nsector; - QEMUBH *bh; -} BMDMAState; - -typedef struct PCIIDEState { - PCIDevice dev; - IDEState ide_if[4]; - BMDMAState bmdma[2]; - int type; /* see IDE_TYPE_xxx */ -} PCIIDEState; - -static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); static void ide_dma_restart(IDEState *s); static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); +static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); static void padstr(char *str, const char *src, int len) { @@ -656,7 +161,7 @@ static void ide_identify(IDEState *s) s->identify_set = 1; } -static void ide_atapi_identify(IDEState *s) +void ide_atapi_identify(IDEState *s) { uint16_t *p; @@ -802,7 +307,7 @@ static inline void ide_dma_submit_check(IDEState *s, dma_cb(bm, -1); } -static inline void ide_set_irq(IDEState *s) +void ide_set_irq(IDEState *s) { BMDMAState *bm = s->bmdma; if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { @@ -814,8 +319,8 @@ static inline void ide_set_irq(IDEState *s) } /* prepare data transfer and tell what to do after */ -static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, - EndTransferFunc *end_transfer_func) +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func) { s->end_transfer_func = end_transfer_func; s->data_ptr = buf; @@ -824,7 +329,7 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, s->status |= DRQ_STAT; } -static void ide_transfer_stop(IDEState *s) +void ide_transfer_stop(IDEState *s) { s->end_transfer_func = ide_transfer_stop; s->data_ptr = s->io_buffer; @@ -995,7 +500,7 @@ static int ide_handle_write_error(IDEState *s, int error, int op) } /* return 0 if buffer completed */ -static int dma_buf_rw(BMDMAState *bm, int is_write) +int dma_buf_rw(BMDMAState *bm, int is_write) { IDEState *s = bm->ide_if; struct { @@ -1238,7 +743,7 @@ static void ide_sector_write_dma(IDEState *s) ide_dma_start(s, ide_write_dma_cb); } -static void ide_atapi_cmd_ok(IDEState *s) +void ide_atapi_cmd_ok(IDEState *s) { s->error = 0; s->status = READY_STAT | SEEK_STAT; @@ -1270,30 +775,6 @@ static void ide_atapi_cmd_check_status(IDEState *s) ide_set_irq(s); } -static inline void cpu_to_ube16(uint8_t *buf, int val) -{ - buf[0] = val >> 8; - buf[1] = val & 0xff; -} - -static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) -{ - buf[0] = val >> 24; - buf[1] = val >> 16; - buf[2] = val >> 8; - buf[3] = val & 0xff; -} - -static inline int ube16_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 8) | buf[1]; -} - -static inline int ube32_to_cpu(const uint8_t *buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - static void lba_to_msf(uint8_t *buf, int lba) { lba += 150; @@ -1341,7 +822,7 @@ static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, return ret; } -static void ide_atapi_io_error(IDEState *s, int ret) +void ide_atapi_io_error(IDEState *s, int ret) { /* XXX: handle more errors */ if (ret == -ENOMEDIUM) { @@ -1433,7 +914,7 @@ static void ide_atapi_cmd_reply_end(IDEState *s) } /* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ -static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) +void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) { if (size > max_size) size = max_size; @@ -3012,7 +2493,7 @@ static void ide_map(PCIDevice *pci_dev, int region_num, } } -static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) +void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) { BMDMAState *bm = s->bmdma; if(!bm) diff --git a/hw/ide.h b/hw/ide.h new file mode 100644 index 0000000..2c24e08 --- /dev/null +++ b/hw/ide.h @@ -0,0 +1,579 @@ +/* + * QEMU IDE disk and CD/DVD-ROM Emulator definitions + * + * Copyright (c) 2009 Alexandre Bique + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef IDE_H +#define IDE_H + +#include "hw.h" +#include "pc.h" +#include "pci.h" +#include "scsi-disk.h" +#include "pcmcia.h" +#include "block.h" +#include "block_int.h" +#include "qemu-timer.h" +#include "sysemu.h" +#include "ppc_mac.h" +#include "mac_dbdma.h" +#include "sh.h" +#include "dma.h" +#include "atapi-defines.h" + +#include <stdint.h> + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SRV_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* Bits of HD_NSECTOR */ +#define CD 0x01 +#define IO 0x02 +#define REL 0x04 +#define TAG_MASK 0xf8 + +#define IDE_CMD_RESET 0x04 +#define IDE_CMD_DISABLE_IRQ 0x02 + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +#define WIN_RESTORE WIN_RECAL +/* + * 0x10->0x1F Reserved + */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* + * 0x28 + */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ +#define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ +#define WIN_INIT 0x60 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */ +#define WIN_STANDBY2 0x96 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ACCESS_METADATA_STORAGE 0xB8 +#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ +#define WIN_POSTBOOT 0xDC +#define WIN_PREBOOT 0xDD +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ + /* SET_FEATURES 0x22 or 0xDD */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */ +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */ +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* set to 1 set disable mult support */ +#define MAX_MULT_SECTORS 16 + +#define IDE_DMA_BUF_SECTORS 256 + +#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) +#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" +#endif + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/********************************************************************* + * Generic Packet commands, MMC commands, and such + *********************************************************************/ + + /* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_READ_BUFFER_CAPACITY 0x5c +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SEND_CUE_SHEET 0x5d +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xbf +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_12 0xaa +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_WRITE_BUFFER 0x3b +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda +#define GPCMD_MODE_SENSE_6 0x1a + +/* Mode page codes for mode sense/set */ +#define GPMODE_VENDOR_PAGE 0x00 +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_WCACHING_PAGE 0x08 +#define GPMODE_AUDIO_CTL_PAGE 0x0e +#define GPMODE_POWER_PAGE 0x1a +#define GPMODE_FAULT_FAIL_PAGE 0x1c +#define GPMODE_TO_PROTECT_PAGE 0x1d +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f +/* Not in Mt. Fuji, but in ATAPI 2.6 -- deprecated now in favor + * of MODE_SENSE_POWER_PAGE */ +#define GPMODE_CDROM_PAGE 0x0d + +/* + * Based on values from <linux/cdrom.h> but extending CD_MINS + * to the maximum common size allowed by the Orange's Book ATIP + * + * 90 and 99 min CDs are also available but using them as the + * upper limit reduces the effectiveness of the heuristic to + * detect DVDs burned to less than 25% of their maximum capacity + */ + +/* Some generally useful CD-ROM information */ +#define CD_MINS 80 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ +#define CD_CHUNK_SIZE 24 /* lowest-level "data bytes piece" */ +#define CD_NUM_OF_CHUNKS 98 /* chunks per frame */ +#define CD_FRAMESIZE_SUB 96 /* subchannel data "frame" size */ +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +#define CD_EDC_SIZE 4 /* bytes EDC per most raw data frame types */ +#define CD_ZERO_SIZE 8 /* bytes zero per yellow book mode 1 frame */ +#define CD_ECC_SIZE 276 /* bytes ECC per most raw data frame types */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAWER 2646 /* The maximum possible returned bytes */ +/* most drives don't deliver everything: */ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ + +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) +#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) + +/* + * The MMC values are not IDE specific and might need to be moved + * to a common header if they are also needed for the SCSI emulation + */ + +/* Profile list from MMC-6 revision 1 table 91 */ +#define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_CD_ROM 0x0008 +#define MMC_PROFILE_CD_R 0x0009 +#define MMC_PROFILE_CD_RW 0x000A +#define MMC_PROFILE_DVD_ROM 0x0010 +#define MMC_PROFILE_DVD_R_SR 0x0011 +#define MMC_PROFILE_DVD_RAM 0x0012 +#define MMC_PROFILE_DVD_RW_RO 0x0013 +#define MMC_PROFILE_DVD_RW_SR 0x0014 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016 +#define MMC_PROFILE_DVD_RW_DL 0x0017 +#define MMC_PROFILE_DVD_DDR 0x0018 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A +#define MMC_PROFILE_DVD_PLUS_R 0x001B +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B +#define MMC_PROFILE_BD_ROM 0x0040 +#define MMC_PROFILE_BD_R_SRM 0x0041 +#define MMC_PROFILE_BD_R_RRM 0x0042 +#define MMC_PROFILE_BD_RE 0x0043 +#define MMC_PROFILE_HDDVD_ROM 0x0050 +#define MMC_PROFILE_HDDVD_R 0x0051 +#define MMC_PROFILE_HDDVD_RAM 0x0052 +#define MMC_PROFILE_HDDVD_RW 0x0053 +#define MMC_PROFILE_HDDVD_R_DL 0x0058 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A +#define MMC_PROFILE_INVALID 0xFFFF + + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_NONE 0x00 +#define ASC_READ_ERROR 0x11 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 + +#define CFA_NO_ERROR 0x00 +#define CFA_MISC_ERROR 0x09 +#define CFA_INVALID_COMMAND 0x20 +#define CFA_INVALID_ADDRESS 0x21 +#define CFA_ADDRESS_OVERFLOW 0x2f + +/* Sense keys */ +#define SENSE_NONE 0 +#define SENSE_RECOVERED_ERROR 1 +#define SENSE_NOT_READY 2 +#define SENSE_MEDIUM_ERROR 3 +#define SENSE_HARDWARE_ERROR 4 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 +#define SENSE_DATA_PROTECT 7 +#define SENSE_BLANK_CHECK 8 +#define SENSE_VENDOR_SPECIFIC 9 +#define SENSE_COPY_ABORTED 10 +#define SENSE_ABORTED_COMMAND 11 +#define SENSE_VOLUME_OVERFLOW 13 +#define SENSE_MISCOMPARE 14 + +#define IO_BUFFER_MAX_SIZE (IDE_DMA_BUF_SECTORS * 512 + 4) + +struct IDEState; + +typedef void EndTransferFunc(struct IDEState *); + +/* NOTE: IDEState represents in fact one drive */ +typedef struct IDEState { + /* ide config */ + int is_cdrom; + int is_cf; + int cylinders, heads, sectors; + int64_t nb_sectors; + int mult_sectors; + int identify_set; + uint16_t identify_data[256]; + qemu_irq irq; + PCIDevice *pci_dev; + struct BMDMAState *bmdma; + int drive_serial; + char drive_serial_str[21]; + /* ide regs */ + uint8_t feature; + uint8_t error; + uint32_t nsector; + uint8_t sector; + uint8_t lcyl; + uint8_t hcyl; + /* other part of tf for lba48 support */ + uint8_t hob_feature; + uint8_t hob_nsector; + uint8_t hob_sector; + uint8_t hob_lcyl; + uint8_t hob_hcyl; + + uint8_t select; + uint8_t status; + + /* 0x3f6 command, only meaningful for drive 0 */ + uint8_t cmd; + /* set for lba48 access */ + uint8_t lba48; + /* depends on bit 4 in select, only meaningful for drive 0 */ + struct IDEState *cur_drive; + BlockDriverState *bs; + /* ATAPI specific */ + uint8_t sense_key; + uint8_t asc; + uint8_t cdrom_changed; + int packet_transfer_size; + int elementary_transfer_size; + int io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ + /* ATA DMA state */ + int io_buffer_size; + QEMUSGList sg; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ + EndTransferFunc *end_transfer_func; + uint8_t *data_ptr; + uint8_t *data_end; + uint8_t *io_buffer; + QEMUTimer *sector_write_timer; /* only used for win2k install hack */ + uint32_t irq_count; /* counts IRQs when using win2k install hack */ + /* CF-ATA extended error */ + uint8_t ext_error; + /* CF-ATA metadata storage */ + uint32_t mdata_size; + uint8_t *mdata_storage; + int media_changed; + /* for pmac */ + int is_read; +} IDEState; + +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 +#define BM_STATUS_DMA_RETRY 0x08 +#define BM_STATUS_PIO_RETRY 0x10 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + +#define IDE_TYPE_PIIX3 0 +#define IDE_TYPE_CMD646 1 +#define IDE_TYPE_PIIX4 2 + +/* CMD646 specific */ +#define MRDMODE 0x71 +#define MRDMODE_INTR_CH0 0x04 +#define MRDMODE_INTR_CH1 0x08 +#define MRDMODE_BLK_CH0 0x10 +#define MRDMODE_BLK_CH1 0x20 +#define UDIDETCR0 0x73 +#define UDIDETCR1 0x7B + +typedef struct BMDMAState { + uint8_t cmd; + uint8_t status; + uint32_t addr; + + struct PCIIDEState *pci_dev; + /* current transfer state */ + uint32_t cur_addr; + uint32_t cur_prd_last; + uint32_t cur_prd_addr; + uint32_t cur_prd_len; + IDEState *ide_if; + BlockDriverCompletionFunc *dma_cb; + BlockDriverAIOCB *aiocb; + struct iovec iov; + QEMUIOVector qiov; + int64_t sector_num; + uint32_t nsector; + QEMUBH *bh; +} BMDMAState; + +typedef struct PCIIDEState { + PCIDevice dev; + IDEState ide_if[4]; + BMDMAState bmdma[2]; + int type; /* see IDE_TYPE_xxx */ +} PCIIDEState; + +void ide_set_irq(IDEState *s); +void ide_atapi_cmd_ok(IDEState *s); +void ide_transfer_stop(IDEState *s); +void ide_atapi_io_error(IDEState *s, int ret); +int dma_buf_rw(BMDMAState *bm, int is_write); +void ide_atapi_identify(IDEState *s); +void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func); +void ide_atapi_cmd_reply(IDEState *s, int size, int max_size); + +static inline void cpu_to_ube16(uint8_t *buf, int val) +{ + buf[0] = val >> 8; + buf[1] = val & 0xff; +} + +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val & 0xff; +} + +static inline int ube16_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 8) | buf[1]; +} + +static inline int ube32_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + + +#endif /* !IDE_H */ + -- 1.4.4.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-08-12 17:19 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-08-07 17:33 [Qemu-devel] ATAPI pass throug v4 Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 1/7] atapi: fix up a few comments Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 2/7] atapi: protocol define updates Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 3/7] atapi: guessing if the cdrom device is a scsi device Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 4/7] atapi: adds header guards to hw/pcmia.h Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 5/7] atapi: adds header guards to hw/mac_dbdma.h Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi Alexandre Bique 2009-08-07 17:33 ` [Qemu-devel] [PATCH 7/7] atapi: introducing atapi pass through Alexandre Bique 2009-08-10 20:09 ` [Qemu-devel] ATAPI pass throug v4 Anthony Liguori [not found] <<19074.63829.151234.423348@mariner.uk.xensource.com> 2009-08-12 16:38 ` [Qemu-devel] [PATCH 6/7] atapi: made some part of ide.c public and moved some part to atapi Ian Jackson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).