Commit 36b486bb74ca651d07968372cebd6e742114e144
1 parent
4ad06a29
hardware level IDE CD-ROM emulation - added second IDE interface for up to 4 IDE…
… disks emulation - added -boot command to enable CD boot git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@444 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
744 additions
and
71 deletions
vl.c
... | ... | @@ -63,6 +63,7 @@ |
63 | 63 | |
64 | 64 | /* debug IDE devices */ |
65 | 65 | //#define DEBUG_IDE |
66 | +//#define DEBUG_IDE_ATAPI | |
66 | 67 | |
67 | 68 | /* debug PIC */ |
68 | 69 | //#define DEBUG_PIC |
... | ... | @@ -85,7 +86,7 @@ |
85 | 86 | |
86 | 87 | #define GUI_REFRESH_INTERVAL 30 |
87 | 88 | |
88 | -#define MAX_DISKS 2 | |
89 | +#define MAX_DISKS 4 | |
89 | 90 | |
90 | 91 | /* from plex86 (BSD license) */ |
91 | 92 | struct __attribute__ ((packed)) linux_params { |
... | ... | @@ -216,6 +217,7 @@ static DisplayState display_state; |
216 | 217 | int nographic; |
217 | 218 | int term_inited; |
218 | 219 | int64_t ticks_per_sec; |
220 | +int boot_device = 'c'; | |
219 | 221 | |
220 | 222 | /***********************************************************/ |
221 | 223 | /* x86 io ports */ |
... | ... | @@ -533,8 +535,19 @@ void cmos_init(void) |
533 | 535 | cmos_data[0x34] = val; |
534 | 536 | cmos_data[0x35] = val >> 8; |
535 | 537 | |
536 | - cmos_data[0x3d] = 0x02; /* hard drive boot */ | |
537 | - | |
538 | + switch(boot_device) { | |
539 | + case 'a': | |
540 | + cmos_data[0x3d] = 0x01; /* floppy boot */ | |
541 | + break; | |
542 | + default: | |
543 | + case 'c': | |
544 | + cmos_data[0x3d] = 0x02; /* hard drive boot */ | |
545 | + break; | |
546 | + case 'd': | |
547 | + cmos_data[0x3d] = 0x03; /* CD-ROM boot */ | |
548 | + break; | |
549 | + } | |
550 | + | |
538 | 551 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
539 | 552 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
540 | 553 | } |
... | ... | @@ -1045,7 +1058,7 @@ static inline void pit_load_count(PITChannelState *s, int val) |
1045 | 1058 | s->count = val; |
1046 | 1059 | if (s == &pit_channels[0] && val <= pit_min_timer_count) { |
1047 | 1060 | fprintf(stderr, |
1048 | - "\nWARNING: vl: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.5.xx Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n", | |
1061 | + "\nWARNING: qemu: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.5.xx Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n", | |
1049 | 1062 | PIT_FREQ / pit_min_timer_count); |
1050 | 1063 | } |
1051 | 1064 | } |
... | ... | @@ -2014,12 +2027,111 @@ void ne2000_init(void) |
2014 | 2027 | /* set to 1 set disable mult support */ |
2015 | 2028 | #define MAX_MULT_SECTORS 8 |
2016 | 2029 | |
2030 | +/* ATAPI defines */ | |
2031 | + | |
2032 | +#define ATAPI_PACKET_SIZE 12 | |
2033 | + | |
2034 | +/* The generic packet command opcodes for CD/DVD Logical Units, | |
2035 | + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ | |
2036 | +#define GPCMD_BLANK 0xa1 | |
2037 | +#define GPCMD_CLOSE_TRACK 0x5b | |
2038 | +#define GPCMD_FLUSH_CACHE 0x35 | |
2039 | +#define GPCMD_FORMAT_UNIT 0x04 | |
2040 | +#define GPCMD_GET_CONFIGURATION 0x46 | |
2041 | +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a | |
2042 | +#define GPCMD_GET_PERFORMANCE 0xac | |
2043 | +#define GPCMD_INQUIRY 0x12 | |
2044 | +#define GPCMD_LOAD_UNLOAD 0xa6 | |
2045 | +#define GPCMD_MECHANISM_STATUS 0xbd | |
2046 | +#define GPCMD_MODE_SELECT_10 0x55 | |
2047 | +#define GPCMD_MODE_SENSE_10 0x5a | |
2048 | +#define GPCMD_PAUSE_RESUME 0x4b | |
2049 | +#define GPCMD_PLAY_AUDIO_10 0x45 | |
2050 | +#define GPCMD_PLAY_AUDIO_MSF 0x47 | |
2051 | +#define GPCMD_PLAY_AUDIO_TI 0x48 | |
2052 | +#define GPCMD_PLAY_CD 0xbc | |
2053 | +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e | |
2054 | +#define GPCMD_READ_10 0x28 | |
2055 | +#define GPCMD_READ_12 0xa8 | |
2056 | +#define GPCMD_READ_CDVD_CAPACITY 0x25 | |
2057 | +#define GPCMD_READ_CD 0xbe | |
2058 | +#define GPCMD_READ_CD_MSF 0xb9 | |
2059 | +#define GPCMD_READ_DISC_INFO 0x51 | |
2060 | +#define GPCMD_READ_DVD_STRUCTURE 0xad | |
2061 | +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 | |
2062 | +#define GPCMD_READ_HEADER 0x44 | |
2063 | +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 | |
2064 | +#define GPCMD_READ_SUBCHANNEL 0x42 | |
2065 | +#define GPCMD_READ_TOC_PMA_ATIP 0x43 | |
2066 | +#define GPCMD_REPAIR_RZONE_TRACK 0x58 | |
2067 | +#define GPCMD_REPORT_KEY 0xa4 | |
2068 | +#define GPCMD_REQUEST_SENSE 0x03 | |
2069 | +#define GPCMD_RESERVE_RZONE_TRACK 0x53 | |
2070 | +#define GPCMD_SCAN 0xba | |
2071 | +#define GPCMD_SEEK 0x2b | |
2072 | +#define GPCMD_SEND_DVD_STRUCTURE 0xad | |
2073 | +#define GPCMD_SEND_EVENT 0xa2 | |
2074 | +#define GPCMD_SEND_KEY 0xa3 | |
2075 | +#define GPCMD_SEND_OPC 0x54 | |
2076 | +#define GPCMD_SET_READ_AHEAD 0xa7 | |
2077 | +#define GPCMD_SET_STREAMING 0xb6 | |
2078 | +#define GPCMD_START_STOP_UNIT 0x1b | |
2079 | +#define GPCMD_STOP_PLAY_SCAN 0x4e | |
2080 | +#define GPCMD_TEST_UNIT_READY 0x00 | |
2081 | +#define GPCMD_VERIFY_10 0x2f | |
2082 | +#define GPCMD_WRITE_10 0x2a | |
2083 | +#define GPCMD_WRITE_AND_VERIFY_10 0x2e | |
2084 | +/* This is listed as optional in ATAPI 2.6, but is (curiously) | |
2085 | + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji | |
2086 | + * Table 377 as an MMC command for SCSi devices though... Most ATAPI | |
2087 | + * drives support it. */ | |
2088 | +#define GPCMD_SET_SPEED 0xbb | |
2089 | +/* This seems to be a SCSI specific CD-ROM opcode | |
2090 | + * to play data at track/index */ | |
2091 | +#define GPCMD_PLAYAUDIO_TI 0x48 | |
2092 | +/* | |
2093 | + * From MS Media Status Notification Support Specification. For | |
2094 | + * older drives only. | |
2095 | + */ | |
2096 | +#define GPCMD_GET_MEDIA_STATUS 0xda | |
2097 | + | |
2098 | +/* Mode page codes for mode sense/set */ | |
2099 | +#define GPMODE_R_W_ERROR_PAGE 0x01 | |
2100 | +#define GPMODE_WRITE_PARMS_PAGE 0x05 | |
2101 | +#define GPMODE_AUDIO_CTL_PAGE 0x0e | |
2102 | +#define GPMODE_POWER_PAGE 0x1a | |
2103 | +#define GPMODE_FAULT_FAIL_PAGE 0x1c | |
2104 | +#define GPMODE_TO_PROTECT_PAGE 0x1d | |
2105 | +#define GPMODE_CAPABILITIES_PAGE 0x2a | |
2106 | +#define GPMODE_ALL_PAGES 0x3f | |
2107 | +/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor | |
2108 | + * of MODE_SENSE_POWER_PAGE */ | |
2109 | +#define GPMODE_CDROM_PAGE 0x0d | |
2110 | + | |
2111 | +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ | |
2112 | +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ | |
2113 | +#define ATAPI_INT_REASON_REL 0x04 | |
2114 | +#define ATAPI_INT_REASON_TAG 0xf8 | |
2115 | + | |
2116 | +/* same constants as bochs */ | |
2117 | +#define ASC_LOGICAL_BLOCK_OOR 0x21 | |
2118 | +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 | |
2119 | +#define ASC_MEDIUM_NOT_PRESENT 0x3a | |
2120 | +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 | |
2121 | + | |
2122 | +#define SENSE_NONE 0 | |
2123 | +#define SENSE_NOT_READY 2 | |
2124 | +#define SENSE_ILLEGAL_REQUEST 5 | |
2125 | +#define SENSE_UNIT_ATTENTION 6 | |
2126 | + | |
2017 | 2127 | struct IDEState; |
2018 | 2128 | |
2019 | 2129 | typedef void EndTransferFunc(struct IDEState *); |
2020 | 2130 | |
2021 | 2131 | typedef struct IDEState { |
2022 | 2132 | /* ide config */ |
2133 | + int is_cdrom; | |
2134 | + int cdrom_locked; | |
2023 | 2135 | int cylinders, heads, sectors; |
2024 | 2136 | int64_t nb_sectors; |
2025 | 2137 | int mult_sectors; |
... | ... | @@ -2038,6 +2150,14 @@ typedef struct IDEState { |
2038 | 2150 | /* depends on bit 4 in select, only meaningful for drive 0 */ |
2039 | 2151 | struct IDEState *cur_drive; |
2040 | 2152 | BlockDriverState *bs; |
2153 | + /* ATAPI specific */ | |
2154 | + uint8_t sense_key; | |
2155 | + uint8_t asc; | |
2156 | + int packet_transfer_size; | |
2157 | + int elementary_transfer_size; | |
2158 | + int io_buffer_index; | |
2159 | + int lba; | |
2160 | + /* transfer handling */ | |
2041 | 2161 | int req_nb_sectors; /* number of sectors per interrupt */ |
2042 | 2162 | EndTransferFunc *end_transfer_func; |
2043 | 2163 | uint8_t *data_ptr; |
... | ... | @@ -2046,6 +2166,12 @@ typedef struct IDEState { |
2046 | 2166 | } IDEState; |
2047 | 2167 | |
2048 | 2168 | IDEState ide_state[MAX_DISKS]; |
2169 | +IDEState *ide_table[0x400 >> 3]; | |
2170 | + | |
2171 | +static inline IDEState *get_ide_interface(uint32_t addr) | |
2172 | +{ | |
2173 | + return ide_table[addr >> 3]; | |
2174 | +} | |
2049 | 2175 | |
2050 | 2176 | static void padstr(char *str, const char *src, int len) |
2051 | 2177 | { |
... | ... | @@ -2073,10 +2199,12 @@ static void ide_identify(IDEState *s) |
2073 | 2199 | stw_raw(p + 4, 512 * s->sectors); /* sectors */ |
2074 | 2200 | stw_raw(p + 5, 512); /* sector size */ |
2075 | 2201 | stw_raw(p + 6, s->sectors); |
2202 | + padstr((uint8_t *)(p + 10), "QM00001", 20); /* serial number */ | |
2076 | 2203 | stw_raw(p + 20, 3); /* buffer type */ |
2077 | 2204 | stw_raw(p + 21, 512); /* cache size in sectors */ |
2078 | 2205 | stw_raw(p + 22, 4); /* ecc bytes */ |
2079 | - padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); | |
2206 | + padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */ | |
2207 | + padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */ | |
2080 | 2208 | #if MAX_MULT_SECTORS > 1 |
2081 | 2209 | stw_raw(p + 47, MAX_MULT_SECTORS); |
2082 | 2210 | #endif |
... | ... | @@ -2103,6 +2231,59 @@ static void ide_identify(IDEState *s) |
2103 | 2231 | stw_raw(p + 87, (1 << 14)); |
2104 | 2232 | } |
2105 | 2233 | |
2234 | +static void ide_atapi_identify(IDEState *s) | |
2235 | +{ | |
2236 | + uint16_t *p; | |
2237 | + | |
2238 | + memset(s->io_buffer, 0, 512); | |
2239 | + p = (uint16_t *)s->io_buffer; | |
2240 | + /* Removable CDROM, 50us response, 12 byte packets */ | |
2241 | + stw_raw(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0)); | |
2242 | + stw_raw(p + 1, s->cylinders); | |
2243 | + stw_raw(p + 3, s->heads); | |
2244 | + stw_raw(p + 4, 512 * s->sectors); /* sectors */ | |
2245 | + stw_raw(p + 5, 512); /* sector size */ | |
2246 | + stw_raw(p + 6, s->sectors); | |
2247 | + padstr((uint8_t *)(p + 10), "QM00001", 20); /* serial number */ | |
2248 | + stw_raw(p + 20, 3); /* buffer type */ | |
2249 | + stw_raw(p + 21, 512); /* cache size in sectors */ | |
2250 | + stw_raw(p + 22, 4); /* ecc bytes */ | |
2251 | + padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */ | |
2252 | + padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */ | |
2253 | + stw_raw(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */ | |
2254 | + stw_raw(p + 49, 1 << 9); /* LBA supported, no DMA */ | |
2255 | + stw_raw(p + 53, 3); /* words 64-70, 54-58 valid */ | |
2256 | + stw_raw(p + 63, 0x103); /* DMA modes XXX: may be incorrect */ | |
2257 | + stw_raw(p + 64, 1); /* PIO modes */ | |
2258 | + stw_raw(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */ | |
2259 | + stw_raw(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ | |
2260 | + stw_raw(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ | |
2261 | + stw_raw(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ | |
2262 | + | |
2263 | + stw_raw(p + 71, 30); /* in ns */ | |
2264 | + stw_raw(p + 72, 30); /* in ns */ | |
2265 | + | |
2266 | + stw_raw(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ | |
2267 | +} | |
2268 | + | |
2269 | +static void ide_set_signature(IDEState *s) | |
2270 | +{ | |
2271 | + s->select &= 0xf0; /* clear head */ | |
2272 | + /* put signature */ | |
2273 | + s->nsector = 1; | |
2274 | + s->sector = 1; | |
2275 | + if (s->is_cdrom) { | |
2276 | + s->lcyl = 0x14; | |
2277 | + s->hcyl = 0xeb; | |
2278 | + } else if (s->bs) { | |
2279 | + s->lcyl = 0; | |
2280 | + s->hcyl = 0; | |
2281 | + } else { | |
2282 | + s->lcyl = 0xff; | |
2283 | + s->hcyl = 0xff; | |
2284 | + } | |
2285 | +} | |
2286 | + | |
2106 | 2287 | static inline void ide_abort_command(IDEState *s) |
2107 | 2288 | { |
2108 | 2289 | s->status = READY_STAT | ERR_STAT; |
... | ... | @@ -2111,18 +2292,18 @@ static inline void ide_abort_command(IDEState *s) |
2111 | 2292 | |
2112 | 2293 | static inline void ide_set_irq(IDEState *s) |
2113 | 2294 | { |
2114 | - if (!(ide_state[0].cmd & IDE_CMD_DISABLE_IRQ)) { | |
2295 | + if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { | |
2115 | 2296 | pic_set_irq(s->irq, 1); |
2116 | 2297 | } |
2117 | 2298 | } |
2118 | 2299 | |
2119 | 2300 | /* prepare data transfer and tell what to do after */ |
2120 | -static void ide_transfer_start(IDEState *s, int size, | |
2301 | +static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, | |
2121 | 2302 | EndTransferFunc *end_transfer_func) |
2122 | 2303 | { |
2123 | 2304 | s->end_transfer_func = end_transfer_func; |
2124 | - s->data_ptr = s->io_buffer; | |
2125 | - s->data_end = s->io_buffer + size; | |
2305 | + s->data_ptr = buf; | |
2306 | + s->data_end = buf + size; | |
2126 | 2307 | s->status |= DRQ_STAT; |
2127 | 2308 | } |
2128 | 2309 | |
... | ... | @@ -2185,7 +2366,7 @@ static void ide_sector_read(IDEState *s) |
2185 | 2366 | if (n > s->req_nb_sectors) |
2186 | 2367 | n = s->req_nb_sectors; |
2187 | 2368 | ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); |
2188 | - ide_transfer_start(s, 512 * n, ide_sector_read); | |
2369 | + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); | |
2189 | 2370 | ide_set_irq(s); |
2190 | 2371 | ide_set_sector(s, sector_num + n); |
2191 | 2372 | s->nsector -= n; |
... | ... | @@ -2214,21 +2395,457 @@ static void ide_sector_write(IDEState *s) |
2214 | 2395 | n1 = s->nsector; |
2215 | 2396 | if (n1 > s->req_nb_sectors) |
2216 | 2397 | n1 = s->req_nb_sectors; |
2217 | - ide_transfer_start(s, 512 * n1, ide_sector_write); | |
2398 | + ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write); | |
2218 | 2399 | } |
2219 | 2400 | ide_set_sector(s, sector_num + n); |
2220 | 2401 | ide_set_irq(s); |
2221 | 2402 | } |
2222 | 2403 | |
2404 | +static void ide_atapi_cmd_ok(IDEState *s) | |
2405 | +{ | |
2406 | + s->error = 0; | |
2407 | + s->status = READY_STAT; | |
2408 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; | |
2409 | + ide_set_irq(s); | |
2410 | +} | |
2411 | + | |
2412 | +static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc) | |
2413 | +{ | |
2414 | +#ifdef DEBUG_IDE_ATAPI | |
2415 | + printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); | |
2416 | +#endif | |
2417 | + s->error = sense_key << 4; | |
2418 | + s->status = READY_STAT | ERR_STAT; | |
2419 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; | |
2420 | + s->sense_key = sense_key; | |
2421 | + s->asc = asc; | |
2422 | + ide_set_irq(s); | |
2423 | +} | |
2424 | + | |
2425 | +static inline void cpu_to_ube16(uint8_t *buf, int val) | |
2426 | +{ | |
2427 | + buf[0] = val >> 8; | |
2428 | + buf[1] = val; | |
2429 | +} | |
2430 | + | |
2431 | +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) | |
2432 | +{ | |
2433 | + buf[0] = val >> 24; | |
2434 | + buf[1] = val >> 16; | |
2435 | + buf[2] = val >> 8; | |
2436 | + buf[3] = val; | |
2437 | +} | |
2438 | + | |
2439 | +static inline int ube16_to_cpu(const uint8_t *buf) | |
2440 | +{ | |
2441 | + return (buf[0] << 8) | buf[1]; | |
2442 | +} | |
2443 | + | |
2444 | +static inline int ube32_to_cpu(const uint8_t *buf) | |
2445 | +{ | |
2446 | + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; | |
2447 | +} | |
2448 | + | |
2449 | +/* The whole ATAPI transfer logic is handled in this function */ | |
2450 | +static void ide_atapi_cmd_reply_end(IDEState *s) | |
2451 | +{ | |
2452 | + int byte_count_limit, size; | |
2453 | +#ifdef DEBUG_IDE_ATAPI | |
2454 | + printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", | |
2455 | + s->packet_transfer_size, | |
2456 | + s->elementary_transfer_size, | |
2457 | + s->io_buffer_index); | |
2458 | +#endif | |
2459 | + if (s->packet_transfer_size <= 0) { | |
2460 | + /* end of transfer */ | |
2461 | + ide_transfer_stop(s); | |
2462 | + s->status = READY_STAT; | |
2463 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; | |
2464 | + ide_set_irq(s); | |
2465 | +#ifdef DEBUG_IDE_ATAPI | |
2466 | + printf("status=0x%x\n", s->status); | |
2467 | +#endif | |
2468 | + } else { | |
2469 | + /* see if a new sector must be read */ | |
2470 | + if (s->lba != -1 && s->io_buffer_index >= 2048) { | |
2471 | + bdrv_read(s->bs, (int64_t)s->lba << 2, s->io_buffer, 4); | |
2472 | + s->lba++; | |
2473 | + s->io_buffer_index = 0; | |
2474 | + } | |
2475 | + if (s->elementary_transfer_size > 0) { | |
2476 | + /* there are some data left to transmit in this elementary | |
2477 | + transfer */ | |
2478 | + size = 2048 - s->io_buffer_index; | |
2479 | + if (size > s->elementary_transfer_size) | |
2480 | + size = s->elementary_transfer_size; | |
2481 | + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, | |
2482 | + size, ide_atapi_cmd_reply_end); | |
2483 | + s->packet_transfer_size -= size; | |
2484 | + s->elementary_transfer_size -= size; | |
2485 | + s->io_buffer_index += size; | |
2486 | + } else { | |
2487 | + /* a new transfer is needed */ | |
2488 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; | |
2489 | + byte_count_limit = s->lcyl | (s->hcyl << 8); | |
2490 | +#ifdef DEBUG_IDE_ATAPI | |
2491 | + printf("byte_count_limit=%d\n", byte_count_limit); | |
2492 | +#endif | |
2493 | + if (byte_count_limit == 0xffff) | |
2494 | + byte_count_limit--; | |
2495 | + size = s->packet_transfer_size; | |
2496 | + if (size > byte_count_limit) { | |
2497 | + /* byte count limit must be even if this case */ | |
2498 | + if (byte_count_limit & 1) | |
2499 | + byte_count_limit--; | |
2500 | + size = byte_count_limit; | |
2501 | + } else { | |
2502 | + s->lcyl = size; | |
2503 | + s->hcyl = size >> 8; | |
2504 | + } | |
2505 | + s->elementary_transfer_size = size; | |
2506 | + /* we cannot transmit more than one sector at a time */ | |
2507 | + if (s->lba != -1) { | |
2508 | + if (size > (2048 - s->io_buffer_index)) | |
2509 | + size = (2048 - s->io_buffer_index); | |
2510 | + } | |
2511 | + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, | |
2512 | + size, ide_atapi_cmd_reply_end); | |
2513 | + s->packet_transfer_size -= size; | |
2514 | + s->elementary_transfer_size -= size; | |
2515 | + s->io_buffer_index += size; | |
2516 | + ide_set_irq(s); | |
2517 | +#ifdef DEBUG_IDE_ATAPI | |
2518 | + printf("status=0x%x\n", s->status); | |
2519 | +#endif | |
2520 | + } | |
2521 | + } | |
2522 | +} | |
2523 | + | |
2524 | +/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ | |
2525 | +static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) | |
2526 | +{ | |
2527 | + if (size > max_size) | |
2528 | + size = max_size; | |
2529 | + s->lba = -1; /* no sector read */ | |
2530 | + s->packet_transfer_size = size; | |
2531 | + s->elementary_transfer_size = 0; | |
2532 | + s->io_buffer_index = 0; | |
2533 | + | |
2534 | + s->status = READY_STAT; | |
2535 | + ide_atapi_cmd_reply_end(s); | |
2536 | +} | |
2537 | + | |
2538 | +/* start a CD-CDROM read command */ | |
2539 | +static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors) | |
2540 | +{ | |
2541 | +#ifdef DEBUG_IDE_ATAPI | |
2542 | + printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors); | |
2543 | +#endif | |
2544 | + s->lba = lba; | |
2545 | + s->packet_transfer_size = nb_sectors * 2048; | |
2546 | + s->elementary_transfer_size = 0; | |
2547 | + s->io_buffer_index = 2048; | |
2548 | + | |
2549 | + s->status = READY_STAT; | |
2550 | + ide_atapi_cmd_reply_end(s); | |
2551 | +} | |
2552 | + | |
2553 | +/* same toc as bochs. Return -1 if error or the toc length */ | |
2554 | +static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | |
2555 | +{ | |
2556 | + uint8_t *q; | |
2557 | + int nb_sectors, len; | |
2558 | + | |
2559 | + if (start_track > 1 && start_track != 0xaa) | |
2560 | + return -1; | |
2561 | + q = buf + 2; | |
2562 | + *q++ = 1; | |
2563 | + *q++ = 1; | |
2564 | + if (start_track <= 1) { | |
2565 | + *q++ = 0; /* reserved */ | |
2566 | + *q++ = 0x14; /* ADR, control */ | |
2567 | + *q++ = 1; /* track number */ | |
2568 | + *q++ = 0; /* reserved */ | |
2569 | + if (msf) { | |
2570 | + *q++ = 0; /* reserved */ | |
2571 | + *q++ = 0; /* minute */ | |
2572 | + *q++ = 2; /* second */ | |
2573 | + *q++ = 0; /* frame */ | |
2574 | + } else { | |
2575 | + /* sector 0 */ | |
2576 | + cpu_to_ube32(q, 0); | |
2577 | + q += 4; | |
2578 | + } | |
2579 | + } | |
2580 | + /* lead out track */ | |
2581 | + *q++ = 0; /* reserved */ | |
2582 | + *q++ = 0x16; /* ADR, control */ | |
2583 | + *q++ = 0xaa; /* track number */ | |
2584 | + *q++ = 0; /* reserved */ | |
2585 | + nb_sectors = s->nb_sectors >> 2; | |
2586 | + if (msf) { | |
2587 | + *q++ = 0; /* reserved */ | |
2588 | + *q++ = ((nb_sectors + 150) / 75) / 60; | |
2589 | + *q++ = ((nb_sectors + 150) / 75) % 60; | |
2590 | + *q++ = (nb_sectors + 150) % 75; | |
2591 | + } else { | |
2592 | + cpu_to_ube32(q, nb_sectors); | |
2593 | + q += 4; | |
2594 | + } | |
2595 | + len = q - buf; | |
2596 | + cpu_to_ube16(buf, len - 2); | |
2597 | + return len; | |
2598 | +} | |
2599 | + | |
2600 | +static void ide_atapi_cmd(IDEState *s) | |
2601 | +{ | |
2602 | + const uint8_t *packet; | |
2603 | + uint8_t *buf; | |
2604 | + int max_len; | |
2605 | + | |
2606 | + packet = s->io_buffer; | |
2607 | + buf = s->io_buffer; | |
2608 | +#ifdef DEBUG_IDE_ATAPI | |
2609 | + { | |
2610 | + int i; | |
2611 | + printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8)); | |
2612 | + for(i = 0; i < ATAPI_PACKET_SIZE; i++) { | |
2613 | + printf(" %02x", packet[i]); | |
2614 | + } | |
2615 | + printf("\n"); | |
2616 | + } | |
2617 | +#endif | |
2618 | + switch(s->io_buffer[0]) { | |
2619 | + case GPCMD_TEST_UNIT_READY: | |
2620 | + if (s->bs) { | |
2621 | + ide_atapi_cmd_ok(s); | |
2622 | + } else { | |
2623 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2624 | + ASC_MEDIUM_NOT_PRESENT); | |
2625 | + } | |
2626 | + break; | |
2627 | + case GPCMD_MODE_SENSE_10: | |
2628 | + { | |
2629 | + int action, code; | |
2630 | + max_len = ube16_to_cpu(packet + 7); | |
2631 | + action = packet[2] >> 6; | |
2632 | + code = packet[2] & 0x3f; | |
2633 | + switch(action) { | |
2634 | + case 0: /* current values */ | |
2635 | + switch(code) { | |
2636 | + case 0x01: /* error recovery */ | |
2637 | + cpu_to_ube16(&buf[0], 16 + 6); | |
2638 | + buf[2] = 0x70; | |
2639 | + buf[3] = 0; | |
2640 | + buf[4] = 0; | |
2641 | + buf[5] = 0; | |
2642 | + buf[6] = 0; | |
2643 | + buf[7] = 0; | |
2644 | + | |
2645 | + buf[8] = 0x01; | |
2646 | + buf[9] = 0x06; | |
2647 | + buf[10] = 0x00; | |
2648 | + buf[11] = 0x05; | |
2649 | + buf[12] = 0x00; | |
2650 | + buf[13] = 0x00; | |
2651 | + buf[14] = 0x00; | |
2652 | + buf[15] = 0x00; | |
2653 | + ide_atapi_cmd_reply(s, 16, max_len); | |
2654 | + break; | |
2655 | + case 0x2a: | |
2656 | + cpu_to_ube16(&buf[0], 28 + 6); | |
2657 | + buf[2] = 0x70; | |
2658 | + buf[3] = 0; | |
2659 | + buf[4] = 0; | |
2660 | + buf[5] = 0; | |
2661 | + buf[6] = 0; | |
2662 | + buf[7] = 0; | |
2663 | + | |
2664 | + buf[8] = 0x2a; | |
2665 | + buf[9] = 0x12; | |
2666 | + buf[10] = 0x00; | |
2667 | + buf[11] = 0x00; | |
2668 | + | |
2669 | + buf[12] = 0x70; | |
2670 | + buf[13] = 3 << 5; | |
2671 | + buf[14] = (1 << 0) | (1 << 3) | (1 << 5); | |
2672 | + if (s->cdrom_locked) | |
2673 | + buf[6] |= 1 << 1; | |
2674 | + buf[15] = 0x00; | |
2675 | + cpu_to_ube16(&buf[16], 706); | |
2676 | + buf[18] = 0; | |
2677 | + buf[19] = 2; | |
2678 | + cpu_to_ube16(&buf[20], 512); | |
2679 | + cpu_to_ube16(&buf[22], 706); | |
2680 | + buf[24] = 0; | |
2681 | + buf[25] = 0; | |
2682 | + buf[26] = 0; | |
2683 | + buf[27] = 0; | |
2684 | + ide_atapi_cmd_reply(s, 28, max_len); | |
2685 | + break; | |
2686 | + default: | |
2687 | + goto error_cmd; | |
2688 | + } | |
2689 | + break; | |
2690 | + case 1: /* changeable values */ | |
2691 | + goto error_cmd; | |
2692 | + case 2: /* default values */ | |
2693 | + goto error_cmd; | |
2694 | + default: | |
2695 | + case 3: /* saved values */ | |
2696 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | |
2697 | + ASC_SAVING_PARAMETERS_NOT_SUPPORTED); | |
2698 | + break; | |
2699 | + } | |
2700 | + } | |
2701 | + break; | |
2702 | + case GPCMD_REQUEST_SENSE: | |
2703 | + max_len = packet[4]; | |
2704 | + memset(buf, 0, 18); | |
2705 | + buf[0] = 0x70 | (1 << 7); | |
2706 | + buf[2] = s->sense_key; | |
2707 | + buf[7] = 10; | |
2708 | + buf[12] = s->asc; | |
2709 | + ide_atapi_cmd_reply(s, 18, max_len); | |
2710 | + break; | |
2711 | + case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: | |
2712 | + if (s->bs) { | |
2713 | + s->cdrom_locked = packet[4] & 1; | |
2714 | + ide_atapi_cmd_ok(s); | |
2715 | + } else { | |
2716 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2717 | + ASC_MEDIUM_NOT_PRESENT); | |
2718 | + } | |
2719 | + break; | |
2720 | + case GPCMD_READ_10: | |
2721 | + case GPCMD_READ_12: | |
2722 | + { | |
2723 | + int nb_sectors, lba; | |
2724 | + | |
2725 | + if (!s->bs) { | |
2726 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2727 | + ASC_MEDIUM_NOT_PRESENT); | |
2728 | + break; | |
2729 | + } | |
2730 | + if (packet[0] == GPCMD_READ_10) | |
2731 | + nb_sectors = ube16_to_cpu(packet + 7); | |
2732 | + else | |
2733 | + nb_sectors = ube32_to_cpu(packet + 6); | |
2734 | + lba = ube32_to_cpu(packet + 2); | |
2735 | + if (nb_sectors == 0) { | |
2736 | + ide_atapi_cmd_ok(s); | |
2737 | + break; | |
2738 | + } | |
2739 | + if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { | |
2740 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | |
2741 | + ASC_LOGICAL_BLOCK_OOR); | |
2742 | + break; | |
2743 | + } | |
2744 | + ide_atapi_cmd_read(s, lba, nb_sectors); | |
2745 | + } | |
2746 | + break; | |
2747 | + case GPCMD_SEEK: | |
2748 | + { | |
2749 | + int lba; | |
2750 | + if (!s->bs) { | |
2751 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2752 | + ASC_MEDIUM_NOT_PRESENT); | |
2753 | + break; | |
2754 | + } | |
2755 | + lba = ube32_to_cpu(packet + 2); | |
2756 | + if (((int64_t)lba << 2) > s->nb_sectors) { | |
2757 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | |
2758 | + ASC_LOGICAL_BLOCK_OOR); | |
2759 | + break; | |
2760 | + } | |
2761 | + ide_atapi_cmd_ok(s); | |
2762 | + } | |
2763 | + break; | |
2764 | + case GPCMD_START_STOP_UNIT: | |
2765 | + { | |
2766 | + int start, eject; | |
2767 | + start = packet[4] & 1; | |
2768 | + eject = (packet[4] >> 1) & 1; | |
2769 | + | |
2770 | + /* XXX: currently none implemented */ | |
2771 | + ide_atapi_cmd_ok(s); | |
2772 | + } | |
2773 | + break; | |
2774 | + case GPCMD_MECHANISM_STATUS: | |
2775 | + { | |
2776 | + max_len = ube16_to_cpu(packet + 8); | |
2777 | + cpu_to_ube16(buf, 0); | |
2778 | + /* no current LBA */ | |
2779 | + buf[2] = 0; | |
2780 | + buf[3] = 0; | |
2781 | + buf[4] = 0; | |
2782 | + buf[5] = 1; | |
2783 | + cpu_to_ube16(buf + 6, 0); | |
2784 | + ide_atapi_cmd_reply(s, 8, max_len); | |
2785 | + } | |
2786 | + break; | |
2787 | + case GPCMD_READ_TOC_PMA_ATIP: | |
2788 | + { | |
2789 | + int format, msf, start_track, len; | |
2790 | + | |
2791 | + if (!s->bs) { | |
2792 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2793 | + ASC_MEDIUM_NOT_PRESENT); | |
2794 | + break; | |
2795 | + } | |
2796 | + max_len = ube16_to_cpu(packet + 7); | |
2797 | + format = packet[9] >> 6; | |
2798 | + msf = (packet[1] >> 1) & 1; | |
2799 | + start_track = packet[6]; | |
2800 | + switch(format) { | |
2801 | + case 0: | |
2802 | + len = cdrom_read_toc(s, buf, msf, start_track); | |
2803 | + if (len < 0) | |
2804 | + goto error_cmd; | |
2805 | + ide_atapi_cmd_reply(s, len, max_len); | |
2806 | + break; | |
2807 | + case 1: | |
2808 | + /* multi session : only a single session defined */ | |
2809 | + memset(buf, 0, 12); | |
2810 | + buf[1] = 0x0a; | |
2811 | + buf[2] = 0x01; | |
2812 | + buf[3] = 0x01; | |
2813 | + ide_atapi_cmd_reply(s, 12, max_len); | |
2814 | + break; | |
2815 | + default: | |
2816 | + goto error_cmd; | |
2817 | + } | |
2818 | + } | |
2819 | + break; | |
2820 | + case GPCMD_READ_CDVD_CAPACITY: | |
2821 | + if (!s->bs) { | |
2822 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | |
2823 | + ASC_MEDIUM_NOT_PRESENT); | |
2824 | + break; | |
2825 | + } | |
2826 | + /* NOTE: it is really the number of sectors minus 1 */ | |
2827 | + cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1); | |
2828 | + cpu_to_ube32(buf + 4, 2048); | |
2829 | + ide_atapi_cmd_reply(s, 8, 8); | |
2830 | + break; | |
2831 | + default: | |
2832 | + error_cmd: | |
2833 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | |
2834 | + ASC_INV_FIELD_IN_CMD_PACKET); | |
2835 | + break; | |
2836 | + } | |
2837 | +} | |
2838 | + | |
2223 | 2839 | void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2224 | 2840 | { |
2225 | - IDEState *s = ide_state[0].cur_drive; | |
2841 | + IDEState *ide_if = get_ide_interface(addr); | |
2842 | + IDEState *s = ide_if->cur_drive; | |
2226 | 2843 | int unit, n; |
2227 | 2844 | |
2228 | - addr &= 7; | |
2229 | 2845 | #ifdef DEBUG_IDE |
2230 | 2846 | printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); |
2231 | 2847 | #endif |
2848 | + addr &= 7; | |
2232 | 2849 | switch(addr) { |
2233 | 2850 | case 0: |
2234 | 2851 | break; |
... | ... | @@ -2252,8 +2869,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2252 | 2869 | case 6: |
2253 | 2870 | /* select drive */ |
2254 | 2871 | unit = (val >> 4) & 1; |
2255 | - s = &ide_state[unit]; | |
2256 | - ide_state[0].cur_drive = s; | |
2872 | + s = ide_if + unit; | |
2873 | + ide_if->cur_drive = s; | |
2257 | 2874 | s->select = val; |
2258 | 2875 | break; |
2259 | 2876 | default: |
... | ... | @@ -2263,13 +2880,15 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2263 | 2880 | printf("ide: CMD=%02x\n", val); |
2264 | 2881 | #endif |
2265 | 2882 | switch(val) { |
2266 | - case WIN_PIDENTIFY: | |
2267 | 2883 | case WIN_IDENTIFY: |
2268 | - if (s->bs) { | |
2884 | + if (s->bs && !s->is_cdrom) { | |
2269 | 2885 | ide_identify(s); |
2270 | 2886 | s->status = READY_STAT; |
2271 | - ide_transfer_start(s, 512, ide_transfer_stop); | |
2887 | + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); | |
2272 | 2888 | } else { |
2889 | + if (s->is_cdrom) { | |
2890 | + ide_set_signature(s); | |
2891 | + } | |
2273 | 2892 | ide_abort_command(s); |
2274 | 2893 | } |
2275 | 2894 | ide_set_irq(s); |
... | ... | @@ -2299,7 +2918,7 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2299 | 2918 | case WIN_WRITE_ONCE: |
2300 | 2919 | s->status = SEEK_STAT; |
2301 | 2920 | s->req_nb_sectors = 1; |
2302 | - ide_transfer_start(s, 512, ide_sector_write); | |
2921 | + ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); | |
2303 | 2922 | break; |
2304 | 2923 | case WIN_MULTREAD: |
2305 | 2924 | if (!s->mult_sectors) |
... | ... | @@ -2315,13 +2934,42 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2315 | 2934 | n = s->nsector; |
2316 | 2935 | if (n > s->req_nb_sectors) |
2317 | 2936 | n = s->req_nb_sectors; |
2318 | - ide_transfer_start(s, 512 * n, ide_sector_write); | |
2937 | + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); | |
2319 | 2938 | break; |
2320 | 2939 | case WIN_READ_NATIVE_MAX: |
2321 | 2940 | ide_set_sector(s, s->nb_sectors - 1); |
2322 | 2941 | s->status = READY_STAT; |
2323 | 2942 | ide_set_irq(s); |
2324 | 2943 | break; |
2944 | + | |
2945 | + /* ATAPI commands */ | |
2946 | + case WIN_PIDENTIFY: | |
2947 | + if (s->is_cdrom) { | |
2948 | + ide_atapi_identify(s); | |
2949 | + s->status = READY_STAT; | |
2950 | + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); | |
2951 | + } else { | |
2952 | + ide_abort_command(s); | |
2953 | + } | |
2954 | + ide_set_irq(s); | |
2955 | + break; | |
2956 | + case WIN_SRST: | |
2957 | + if (!s->is_cdrom) | |
2958 | + goto abort_cmd; | |
2959 | + ide_set_signature(s); | |
2960 | + s->status = READY_STAT; | |
2961 | + s->error = 0x01; | |
2962 | + break; | |
2963 | + case WIN_PACKETCMD: | |
2964 | + if (!s->is_cdrom) | |
2965 | + goto abort_cmd; | |
2966 | + /* DMA or overlapping commands not supported */ | |
2967 | + if ((s->feature & 0x03) != 0) | |
2968 | + goto abort_cmd; | |
2969 | + s->nsector = 1; | |
2970 | + ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, | |
2971 | + ide_atapi_cmd); | |
2972 | + break; | |
2325 | 2973 | default: |
2326 | 2974 | abort_cmd: |
2327 | 2975 | ide_abort_command(s); |
... | ... | @@ -2331,12 +2979,13 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2331 | 2979 | } |
2332 | 2980 | } |
2333 | 2981 | |
2334 | -uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) | |
2982 | +uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr1) | |
2335 | 2983 | { |
2336 | - IDEState *s = ide_state[0].cur_drive; | |
2984 | + IDEState *s = get_ide_interface(addr1)->cur_drive; | |
2985 | + uint32_t addr; | |
2337 | 2986 | int ret; |
2338 | 2987 | |
2339 | - addr &= 7; | |
2988 | + addr = addr1 & 7; | |
2340 | 2989 | switch(addr) { |
2341 | 2990 | case 0: |
2342 | 2991 | ret = 0xff; |
... | ... | @@ -2366,66 +3015,57 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) |
2366 | 3015 | break; |
2367 | 3016 | } |
2368 | 3017 | #ifdef DEBUG_IDE |
2369 | - printf("ide: read addr=0x%x val=%02x\n", addr, ret); | |
3018 | + printf("ide: read addr=0x%x val=%02x\n", addr1, ret); | |
2370 | 3019 | #endif |
2371 | 3020 | return ret; |
2372 | 3021 | } |
2373 | 3022 | |
2374 | 3023 | uint32_t ide_status_read(CPUX86State *env, uint32_t addr) |
2375 | 3024 | { |
2376 | - IDEState *s = ide_state[0].cur_drive; | |
3025 | + IDEState *s = get_ide_interface(addr)->cur_drive; | |
2377 | 3026 | int ret; |
2378 | 3027 | ret = s->status; |
2379 | 3028 | #ifdef DEBUG_IDE |
2380 | - printf("ide: read status val=%02x\n", ret); | |
3029 | + printf("ide: read status addr=0x%x val=%02x\n", addr, ret); | |
2381 | 3030 | #endif |
2382 | 3031 | return ret; |
2383 | 3032 | } |
2384 | 3033 | |
2385 | 3034 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2386 | 3035 | { |
3036 | + IDEState *ide_if = get_ide_interface(addr); | |
2387 | 3037 | IDEState *s; |
2388 | 3038 | int i; |
2389 | 3039 | |
2390 | 3040 | #ifdef DEBUG_IDE |
2391 | - printf("ide: write control val=%02x\n", val); | |
3041 | + printf("ide: write control addr=0x%x val=%02x\n", addr, val); | |
2392 | 3042 | #endif |
2393 | 3043 | /* common for both drives */ |
2394 | - if (!(ide_state[0].cmd & IDE_CMD_RESET) && | |
3044 | + if (!(ide_if[0].cmd & IDE_CMD_RESET) && | |
2395 | 3045 | (val & IDE_CMD_RESET)) { |
2396 | 3046 | /* reset low to high */ |
2397 | 3047 | for(i = 0;i < 2; i++) { |
2398 | - s = &ide_state[i]; | |
3048 | + s = &ide_if[i]; | |
2399 | 3049 | s->status = BUSY_STAT | SEEK_STAT; |
2400 | 3050 | s->error = 0x01; |
2401 | 3051 | } |
2402 | - } else if ((ide_state[0].cmd & IDE_CMD_RESET) && | |
3052 | + } else if ((ide_if[0].cmd & IDE_CMD_RESET) && | |
2403 | 3053 | !(val & IDE_CMD_RESET)) { |
2404 | 3054 | /* high to low */ |
2405 | 3055 | for(i = 0;i < 2; i++) { |
2406 | - s = &ide_state[i]; | |
3056 | + s = &ide_if[i]; | |
2407 | 3057 | s->status = READY_STAT; |
2408 | - /* set hard disk drive ID */ | |
2409 | - s->select &= 0xf0; /* clear head */ | |
2410 | - s->nsector = 1; | |
2411 | - s->sector = 1; | |
2412 | - if (s->nb_sectors == 0) { | |
2413 | - /* no disk present */ | |
2414 | - s->lcyl = 0x12; | |
2415 | - s->hcyl = 0x34; | |
2416 | - } else { | |
2417 | - s->lcyl = 0; | |
2418 | - s->hcyl = 0; | |
2419 | - } | |
3058 | + ide_set_signature(s); | |
2420 | 3059 | } |
2421 | 3060 | } |
2422 | 3061 | |
2423 | - ide_state[0].cmd = val; | |
3062 | + ide_if[0].cmd = val; | |
3063 | + ide_if[1].cmd = val; | |
2424 | 3064 | } |
2425 | 3065 | |
2426 | 3066 | void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
2427 | 3067 | { |
2428 | - IDEState *s = ide_state[0].cur_drive; | |
3068 | + IDEState *s = get_ide_interface(addr)->cur_drive; | |
2429 | 3069 | uint8_t *p; |
2430 | 3070 | |
2431 | 3071 | p = s->data_ptr; |
... | ... | @@ -2438,10 +3078,9 @@ void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
2438 | 3078 | |
2439 | 3079 | uint32_t ide_data_readw(CPUX86State *env, uint32_t addr) |
2440 | 3080 | { |
2441 | - IDEState *s = ide_state[0].cur_drive; | |
3081 | + IDEState *s = get_ide_interface(addr)->cur_drive; | |
2442 | 3082 | uint8_t *p; |
2443 | 3083 | int ret; |
2444 | - | |
2445 | 3084 | p = s->data_ptr; |
2446 | 3085 | ret = tswap16(*(uint16_t *)p); |
2447 | 3086 | p += 2; |
... | ... | @@ -2453,7 +3092,7 @@ uint32_t ide_data_readw(CPUX86State *env, uint32_t addr) |
2453 | 3092 | |
2454 | 3093 | void ide_data_writel(CPUX86State *env, uint32_t addr, uint32_t val) |
2455 | 3094 | { |
2456 | - IDEState *s = ide_state[0].cur_drive; | |
3095 | + IDEState *s = get_ide_interface(addr)->cur_drive; | |
2457 | 3096 | uint8_t *p; |
2458 | 3097 | |
2459 | 3098 | p = s->data_ptr; |
... | ... | @@ -2466,7 +3105,7 @@ void ide_data_writel(CPUX86State *env, uint32_t addr, uint32_t val) |
2466 | 3105 | |
2467 | 3106 | uint32_t ide_data_readl(CPUX86State *env, uint32_t addr) |
2468 | 3107 | { |
2469 | - IDEState *s = ide_state[0].cur_drive; | |
3108 | + IDEState *s = get_ide_interface(addr)->cur_drive; | |
2470 | 3109 | uint8_t *p; |
2471 | 3110 | int ret; |
2472 | 3111 | |
... | ... | @@ -2482,9 +3121,10 @@ uint32_t ide_data_readl(CPUX86State *env, uint32_t addr) |
2482 | 3121 | void ide_reset(IDEState *s) |
2483 | 3122 | { |
2484 | 3123 | s->mult_sectors = MAX_MULT_SECTORS; |
2485 | - s->status = READY_STAT; | |
2486 | 3124 | s->cur_drive = s; |
2487 | 3125 | s->select = 0xa0; |
3126 | + s->status = READY_STAT; | |
3127 | + ide_set_signature(s); | |
2488 | 3128 | } |
2489 | 3129 | |
2490 | 3130 | struct partition { |
... | ... | @@ -2536,8 +3176,11 @@ void ide_guess_geometry(IDEState *s) |
2536 | 3176 | void ide_init(void) |
2537 | 3177 | { |
2538 | 3178 | IDEState *s; |
2539 | - int i, cylinders; | |
3179 | + int i, cylinders, iobase, iobase2; | |
2540 | 3180 | int64_t nb_sectors; |
3181 | + static const int ide_iobase[2] = { 0x1f0, 0x170 }; | |
3182 | + static const int ide_iobase2[2] = { 0x3f6, 0x376 }; | |
3183 | + static const int ide_irq[2] = { 14, 15 }; | |
2541 | 3184 | |
2542 | 3185 | for(i = 0; i < MAX_DISKS; i++) { |
2543 | 3186 | s = &ide_state[i]; |
... | ... | @@ -2558,19 +3201,26 @@ void ide_init(void) |
2558 | 3201 | s->sectors = 63; |
2559 | 3202 | } |
2560 | 3203 | } |
2561 | - s->irq = 14; | |
3204 | + s->irq = ide_irq[i >> 1]; | |
2562 | 3205 | ide_reset(s); |
2563 | 3206 | } |
2564 | - register_ioport_write(0x1f0, 8, ide_ioport_write, 1); | |
2565 | - register_ioport_read(0x1f0, 8, ide_ioport_read, 1); | |
2566 | - register_ioport_read(0x3f6, 1, ide_status_read, 1); | |
2567 | - register_ioport_write(0x3f6, 1, ide_cmd_write, 1); | |
2568 | - | |
2569 | - /* data ports */ | |
2570 | - register_ioport_write(0x1f0, 2, ide_data_writew, 2); | |
2571 | - register_ioport_read(0x1f0, 2, ide_data_readw, 2); | |
2572 | - register_ioport_write(0x1f0, 4, ide_data_writel, 4); | |
2573 | - register_ioport_read(0x1f0, 4, ide_data_readl, 4); | |
3207 | + for(i = 0; i < (MAX_DISKS / 2); i++) { | |
3208 | + iobase = ide_iobase[i]; | |
3209 | + iobase2 = ide_iobase2[i]; | |
3210 | + ide_table[iobase >> 3] = &ide_state[2 * i]; | |
3211 | + if (ide_iobase2[i]) | |
3212 | + ide_table[iobase2 >> 3] = &ide_state[2 * i]; | |
3213 | + register_ioport_write(iobase, 8, ide_ioport_write, 1); | |
3214 | + register_ioport_read(iobase, 8, ide_ioport_read, 1); | |
3215 | + register_ioport_read(iobase2, 1, ide_status_read, 1); | |
3216 | + register_ioport_write(iobase2, 1, ide_cmd_write, 1); | |
3217 | + | |
3218 | + /* data ports */ | |
3219 | + register_ioport_write(iobase, 2, ide_data_writew, 2); | |
3220 | + register_ioport_read(iobase, 2, ide_data_readw, 2); | |
3221 | + register_ioport_write(iobase, 4, ide_data_writel, 4); | |
3222 | + register_ioport_read(iobase, 4, ide_data_readl, 4); | |
3223 | + } | |
2574 | 3224 | } |
2575 | 3225 | |
2576 | 3226 | /***********************************************************/ |
... | ... | @@ -2811,7 +3461,7 @@ void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
2811 | 3461 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
2812 | 3462 | break; |
2813 | 3463 | default: |
2814 | - fprintf(stderr, "vl: unsupported keyboard cmd=0x%02x\n", val); | |
3464 | + fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val); | |
2815 | 3465 | break; |
2816 | 3466 | } |
2817 | 3467 | } |
... | ... | @@ -3458,8 +4108,10 @@ void help(void) |
3458 | 4108 | "'disk_image' is a raw hard image image for IDE hard disk 0\n" |
3459 | 4109 | "\n" |
3460 | 4110 | "Standard options:\n" |
3461 | - "-hda file use 'file' as IDE hard disk 0 image\n" | |
3462 | - "-hdb file use 'file' as IDE hard disk 1 image\n" | |
4111 | + "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" | |
4112 | + "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" | |
4113 | + "-cdrom file use 'file' as IDE cdrom 2 image\n" | |
4114 | + "-boot [c|d] boot on hard disk or CD-ROM\n" | |
3463 | 4115 | "-snapshot write to temporary files instead of disk image files\n" |
3464 | 4116 | "-m megs set virtual RAM size to megs MB\n" |
3465 | 4117 | "-n script set network init script [default=%s]\n" |
... | ... | @@ -3506,6 +4158,10 @@ struct option long_options[] = { |
3506 | 4158 | { "kernel", 1, NULL, 0, }, |
3507 | 4159 | { "append", 1, NULL, 0, }, |
3508 | 4160 | { "tun-fd", 1, NULL, 0, }, |
4161 | + { "hdc", 1, NULL, 0, }, | |
4162 | + { "hdd", 1, NULL, 0, }, | |
4163 | + { "cdrom", 1, NULL, 0, }, | |
4164 | + { "boot", 1, NULL, 0, }, | |
3509 | 4165 | { NULL, 0, NULL, 0 }, |
3510 | 4166 | }; |
3511 | 4167 | |
... | ... | @@ -3601,6 +4257,23 @@ int main(int argc, char **argv) |
3601 | 4257 | case 8: |
3602 | 4258 | net_fd = atoi(optarg); |
3603 | 4259 | break; |
4260 | + case 9: | |
4261 | + hd_filename[2] = optarg; | |
4262 | + break; | |
4263 | + case 10: | |
4264 | + hd_filename[3] = optarg; | |
4265 | + break; | |
4266 | + case 11: | |
4267 | + hd_filename[2] = optarg; | |
4268 | + ide_state[2].is_cdrom = 1; | |
4269 | + break; | |
4270 | + case 12: | |
4271 | + boot_device = optarg[0]; | |
4272 | + if (boot_device != 'c' && boot_device != 'd') { | |
4273 | + fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device); | |
4274 | + exit(1); | |
4275 | + } | |
4276 | + break; | |
3604 | 4277 | } |
3605 | 4278 | break; |
3606 | 4279 | case 'h': |
... | ... | @@ -3611,7 +4284,7 @@ int main(int argc, char **argv) |
3611 | 4284 | if (phys_ram_size <= 0) |
3612 | 4285 | help(); |
3613 | 4286 | if (phys_ram_size > PHYS_RAM_MAX_SIZE) { |
3614 | - fprintf(stderr, "vl: at most %d MB RAM can be simulated\n", | |
4287 | + fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n", | |
3615 | 4288 | PHYS_RAM_MAX_SIZE / (1024 * 1024)); |
3616 | 4289 | exit(1); |
3617 | 4290 | } |
... | ... | @@ -3640,7 +4313,7 @@ int main(int argc, char **argv) |
3640 | 4313 | |
3641 | 4314 | linux_boot = (kernel_filename != NULL); |
3642 | 4315 | |
3643 | - if (!linux_boot && hd_filename[0] == '\0') | |
4316 | + if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0') | |
3644 | 4317 | help(); |
3645 | 4318 | |
3646 | 4319 | /* init debug */ |
... | ... | @@ -3698,7 +4371,7 @@ int main(int argc, char **argv) |
3698 | 4371 | if (hd_filename[i]) { |
3699 | 4372 | bs_table[i] = bdrv_open(hd_filename[i], snapshot); |
3700 | 4373 | if (!bs_table[i]) { |
3701 | - fprintf(stderr, "vl: could not open hard disk image '%s\n", | |
4374 | + fprintf(stderr, "qemu: could not open hard disk image '%s\n", | |
3702 | 4375 | hd_filename[i]); |
3703 | 4376 | exit(1); |
3704 | 4377 | } |
... | ... | @@ -3719,7 +4392,7 @@ int main(int argc, char **argv) |
3719 | 4392 | /* now we can load the kernel */ |
3720 | 4393 | ret = load_kernel(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); |
3721 | 4394 | if (ret < 0) { |
3722 | - fprintf(stderr, "vl: could not load kernel '%s'\n", | |
4395 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", | |
3723 | 4396 | kernel_filename); |
3724 | 4397 | exit(1); |
3725 | 4398 | } |
... | ... | @@ -3729,7 +4402,7 @@ int main(int argc, char **argv) |
3729 | 4402 | if (initrd_filename) { |
3730 | 4403 | initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); |
3731 | 4404 | if (initrd_size < 0) { |
3732 | - fprintf(stderr, "vl: could not load initial ram disk '%s'\n", | |
4405 | + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", | |
3733 | 4406 | initrd_filename); |
3734 | 4407 | exit(1); |
3735 | 4408 | } |
... | ... | @@ -3788,7 +4461,7 @@ int main(int argc, char **argv) |
3788 | 4461 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
3789 | 4462 | ret = load_image(buf, phys_ram_base + 0x000f0000); |
3790 | 4463 | if (ret != 0x10000) { |
3791 | - fprintf(stderr, "vl: could not load PC bios '%s'\n", buf); | |
4464 | + fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf); | |
3792 | 4465 | exit(1); |
3793 | 4466 | } |
3794 | 4467 | ... | ... |