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,6 +63,7 @@ | ||
63 | 63 | ||
64 | /* debug IDE devices */ | 64 | /* debug IDE devices */ |
65 | //#define DEBUG_IDE | 65 | //#define DEBUG_IDE |
66 | +//#define DEBUG_IDE_ATAPI | ||
66 | 67 | ||
67 | /* debug PIC */ | 68 | /* debug PIC */ |
68 | //#define DEBUG_PIC | 69 | //#define DEBUG_PIC |
@@ -85,7 +86,7 @@ | @@ -85,7 +86,7 @@ | ||
85 | 86 | ||
86 | #define GUI_REFRESH_INTERVAL 30 | 87 | #define GUI_REFRESH_INTERVAL 30 |
87 | 88 | ||
88 | -#define MAX_DISKS 2 | 89 | +#define MAX_DISKS 4 |
89 | 90 | ||
90 | /* from plex86 (BSD license) */ | 91 | /* from plex86 (BSD license) */ |
91 | struct __attribute__ ((packed)) linux_params { | 92 | struct __attribute__ ((packed)) linux_params { |
@@ -216,6 +217,7 @@ static DisplayState display_state; | @@ -216,6 +217,7 @@ static DisplayState display_state; | ||
216 | int nographic; | 217 | int nographic; |
217 | int term_inited; | 218 | int term_inited; |
218 | int64_t ticks_per_sec; | 219 | int64_t ticks_per_sec; |
220 | +int boot_device = 'c'; | ||
219 | 221 | ||
220 | /***********************************************************/ | 222 | /***********************************************************/ |
221 | /* x86 io ports */ | 223 | /* x86 io ports */ |
@@ -533,8 +535,19 @@ void cmos_init(void) | @@ -533,8 +535,19 @@ void cmos_init(void) | ||
533 | cmos_data[0x34] = val; | 535 | cmos_data[0x34] = val; |
534 | cmos_data[0x35] = val >> 8; | 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 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); | 551 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
539 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); | 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,7 +1058,7 @@ static inline void pit_load_count(PITChannelState *s, int val) | ||
1045 | s->count = val; | 1058 | s->count = val; |
1046 | if (s == &pit_channels[0] && val <= pit_min_timer_count) { | 1059 | if (s == &pit_channels[0] && val <= pit_min_timer_count) { |
1047 | fprintf(stderr, | 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 | PIT_FREQ / pit_min_timer_count); | 1062 | PIT_FREQ / pit_min_timer_count); |
1050 | } | 1063 | } |
1051 | } | 1064 | } |
@@ -2014,12 +2027,111 @@ void ne2000_init(void) | @@ -2014,12 +2027,111 @@ void ne2000_init(void) | ||
2014 | /* set to 1 set disable mult support */ | 2027 | /* set to 1 set disable mult support */ |
2015 | #define MAX_MULT_SECTORS 8 | 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 | struct IDEState; | 2127 | struct IDEState; |
2018 | 2128 | ||
2019 | typedef void EndTransferFunc(struct IDEState *); | 2129 | typedef void EndTransferFunc(struct IDEState *); |
2020 | 2130 | ||
2021 | typedef struct IDEState { | 2131 | typedef struct IDEState { |
2022 | /* ide config */ | 2132 | /* ide config */ |
2133 | + int is_cdrom; | ||
2134 | + int cdrom_locked; | ||
2023 | int cylinders, heads, sectors; | 2135 | int cylinders, heads, sectors; |
2024 | int64_t nb_sectors; | 2136 | int64_t nb_sectors; |
2025 | int mult_sectors; | 2137 | int mult_sectors; |
@@ -2038,6 +2150,14 @@ typedef struct IDEState { | @@ -2038,6 +2150,14 @@ typedef struct IDEState { | ||
2038 | /* depends on bit 4 in select, only meaningful for drive 0 */ | 2150 | /* depends on bit 4 in select, only meaningful for drive 0 */ |
2039 | struct IDEState *cur_drive; | 2151 | struct IDEState *cur_drive; |
2040 | BlockDriverState *bs; | 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 | int req_nb_sectors; /* number of sectors per interrupt */ | 2161 | int req_nb_sectors; /* number of sectors per interrupt */ |
2042 | EndTransferFunc *end_transfer_func; | 2162 | EndTransferFunc *end_transfer_func; |
2043 | uint8_t *data_ptr; | 2163 | uint8_t *data_ptr; |
@@ -2046,6 +2166,12 @@ typedef struct IDEState { | @@ -2046,6 +2166,12 @@ typedef struct IDEState { | ||
2046 | } IDEState; | 2166 | } IDEState; |
2047 | 2167 | ||
2048 | IDEState ide_state[MAX_DISKS]; | 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 | static void padstr(char *str, const char *src, int len) | 2176 | static void padstr(char *str, const char *src, int len) |
2051 | { | 2177 | { |
@@ -2073,10 +2199,12 @@ static void ide_identify(IDEState *s) | @@ -2073,10 +2199,12 @@ static void ide_identify(IDEState *s) | ||
2073 | stw_raw(p + 4, 512 * s->sectors); /* sectors */ | 2199 | stw_raw(p + 4, 512 * s->sectors); /* sectors */ |
2074 | stw_raw(p + 5, 512); /* sector size */ | 2200 | stw_raw(p + 5, 512); /* sector size */ |
2075 | stw_raw(p + 6, s->sectors); | 2201 | stw_raw(p + 6, s->sectors); |
2202 | + padstr((uint8_t *)(p + 10), "QM00001", 20); /* serial number */ | ||
2076 | stw_raw(p + 20, 3); /* buffer type */ | 2203 | stw_raw(p + 20, 3); /* buffer type */ |
2077 | stw_raw(p + 21, 512); /* cache size in sectors */ | 2204 | stw_raw(p + 21, 512); /* cache size in sectors */ |
2078 | stw_raw(p + 22, 4); /* ecc bytes */ | 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 | #if MAX_MULT_SECTORS > 1 | 2208 | #if MAX_MULT_SECTORS > 1 |
2081 | stw_raw(p + 47, MAX_MULT_SECTORS); | 2209 | stw_raw(p + 47, MAX_MULT_SECTORS); |
2082 | #endif | 2210 | #endif |
@@ -2103,6 +2231,59 @@ static void ide_identify(IDEState *s) | @@ -2103,6 +2231,59 @@ static void ide_identify(IDEState *s) | ||
2103 | stw_raw(p + 87, (1 << 14)); | 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 | static inline void ide_abort_command(IDEState *s) | 2287 | static inline void ide_abort_command(IDEState *s) |
2107 | { | 2288 | { |
2108 | s->status = READY_STAT | ERR_STAT; | 2289 | s->status = READY_STAT | ERR_STAT; |
@@ -2111,18 +2292,18 @@ static inline void ide_abort_command(IDEState *s) | @@ -2111,18 +2292,18 @@ static inline void ide_abort_command(IDEState *s) | ||
2111 | 2292 | ||
2112 | static inline void ide_set_irq(IDEState *s) | 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 | pic_set_irq(s->irq, 1); | 2296 | pic_set_irq(s->irq, 1); |
2116 | } | 2297 | } |
2117 | } | 2298 | } |
2118 | 2299 | ||
2119 | /* prepare data transfer and tell what to do after */ | 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 | EndTransferFunc *end_transfer_func) | 2302 | EndTransferFunc *end_transfer_func) |
2122 | { | 2303 | { |
2123 | s->end_transfer_func = end_transfer_func; | 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 | s->status |= DRQ_STAT; | 2307 | s->status |= DRQ_STAT; |
2127 | } | 2308 | } |
2128 | 2309 | ||
@@ -2185,7 +2366,7 @@ static void ide_sector_read(IDEState *s) | @@ -2185,7 +2366,7 @@ static void ide_sector_read(IDEState *s) | ||
2185 | if (n > s->req_nb_sectors) | 2366 | if (n > s->req_nb_sectors) |
2186 | n = s->req_nb_sectors; | 2367 | n = s->req_nb_sectors; |
2187 | ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); | 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 | ide_set_irq(s); | 2370 | ide_set_irq(s); |
2190 | ide_set_sector(s, sector_num + n); | 2371 | ide_set_sector(s, sector_num + n); |
2191 | s->nsector -= n; | 2372 | s->nsector -= n; |
@@ -2214,21 +2395,457 @@ static void ide_sector_write(IDEState *s) | @@ -2214,21 +2395,457 @@ static void ide_sector_write(IDEState *s) | ||
2214 | n1 = s->nsector; | 2395 | n1 = s->nsector; |
2215 | if (n1 > s->req_nb_sectors) | 2396 | if (n1 > s->req_nb_sectors) |
2216 | n1 = s->req_nb_sectors; | 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 | ide_set_sector(s, sector_num + n); | 2400 | ide_set_sector(s, sector_num + n); |
2220 | ide_set_irq(s); | 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 | void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | 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 | int unit, n; | 2843 | int unit, n; |
2227 | 2844 | ||
2228 | - addr &= 7; | ||
2229 | #ifdef DEBUG_IDE | 2845 | #ifdef DEBUG_IDE |
2230 | printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); | 2846 | printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); |
2231 | #endif | 2847 | #endif |
2848 | + addr &= 7; | ||
2232 | switch(addr) { | 2849 | switch(addr) { |
2233 | case 0: | 2850 | case 0: |
2234 | break; | 2851 | break; |
@@ -2252,8 +2869,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2252,8 +2869,8 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2252 | case 6: | 2869 | case 6: |
2253 | /* select drive */ | 2870 | /* select drive */ |
2254 | unit = (val >> 4) & 1; | 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 | s->select = val; | 2874 | s->select = val; |
2258 | break; | 2875 | break; |
2259 | default: | 2876 | default: |
@@ -2263,13 +2880,15 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2263,13 +2880,15 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2263 | printf("ide: CMD=%02x\n", val); | 2880 | printf("ide: CMD=%02x\n", val); |
2264 | #endif | 2881 | #endif |
2265 | switch(val) { | 2882 | switch(val) { |
2266 | - case WIN_PIDENTIFY: | ||
2267 | case WIN_IDENTIFY: | 2883 | case WIN_IDENTIFY: |
2268 | - if (s->bs) { | 2884 | + if (s->bs && !s->is_cdrom) { |
2269 | ide_identify(s); | 2885 | ide_identify(s); |
2270 | s->status = READY_STAT; | 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 | } else { | 2888 | } else { |
2889 | + if (s->is_cdrom) { | ||
2890 | + ide_set_signature(s); | ||
2891 | + } | ||
2273 | ide_abort_command(s); | 2892 | ide_abort_command(s); |
2274 | } | 2893 | } |
2275 | ide_set_irq(s); | 2894 | ide_set_irq(s); |
@@ -2299,7 +2918,7 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2299,7 +2918,7 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2299 | case WIN_WRITE_ONCE: | 2918 | case WIN_WRITE_ONCE: |
2300 | s->status = SEEK_STAT; | 2919 | s->status = SEEK_STAT; |
2301 | s->req_nb_sectors = 1; | 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 | break; | 2922 | break; |
2304 | case WIN_MULTREAD: | 2923 | case WIN_MULTREAD: |
2305 | if (!s->mult_sectors) | 2924 | if (!s->mult_sectors) |
@@ -2315,13 +2934,42 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2315,13 +2934,42 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2315 | n = s->nsector; | 2934 | n = s->nsector; |
2316 | if (n > s->req_nb_sectors) | 2935 | if (n > s->req_nb_sectors) |
2317 | n = s->req_nb_sectors; | 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 | break; | 2938 | break; |
2320 | case WIN_READ_NATIVE_MAX: | 2939 | case WIN_READ_NATIVE_MAX: |
2321 | ide_set_sector(s, s->nb_sectors - 1); | 2940 | ide_set_sector(s, s->nb_sectors - 1); |
2322 | s->status = READY_STAT; | 2941 | s->status = READY_STAT; |
2323 | ide_set_irq(s); | 2942 | ide_set_irq(s); |
2324 | break; | 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 | default: | 2973 | default: |
2326 | abort_cmd: | 2974 | abort_cmd: |
2327 | ide_abort_command(s); | 2975 | ide_abort_command(s); |
@@ -2331,12 +2979,13 @@ void ide_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -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 | int ret; | 2986 | int ret; |
2338 | 2987 | ||
2339 | - addr &= 7; | 2988 | + addr = addr1 & 7; |
2340 | switch(addr) { | 2989 | switch(addr) { |
2341 | case 0: | 2990 | case 0: |
2342 | ret = 0xff; | 2991 | ret = 0xff; |
@@ -2366,66 +3015,57 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) | @@ -2366,66 +3015,57 @@ uint32_t ide_ioport_read(CPUX86State *env, uint32_t addr) | ||
2366 | break; | 3015 | break; |
2367 | } | 3016 | } |
2368 | #ifdef DEBUG_IDE | 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 | #endif | 3019 | #endif |
2371 | return ret; | 3020 | return ret; |
2372 | } | 3021 | } |
2373 | 3022 | ||
2374 | uint32_t ide_status_read(CPUX86State *env, uint32_t addr) | 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 | int ret; | 3026 | int ret; |
2378 | ret = s->status; | 3027 | ret = s->status; |
2379 | #ifdef DEBUG_IDE | 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 | #endif | 3030 | #endif |
2382 | return ret; | 3031 | return ret; |
2383 | } | 3032 | } |
2384 | 3033 | ||
2385 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) | 3034 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2386 | { | 3035 | { |
3036 | + IDEState *ide_if = get_ide_interface(addr); | ||
2387 | IDEState *s; | 3037 | IDEState *s; |
2388 | int i; | 3038 | int i; |
2389 | 3039 | ||
2390 | #ifdef DEBUG_IDE | 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 | #endif | 3042 | #endif |
2393 | /* common for both drives */ | 3043 | /* common for both drives */ |
2394 | - if (!(ide_state[0].cmd & IDE_CMD_RESET) && | 3044 | + if (!(ide_if[0].cmd & IDE_CMD_RESET) && |
2395 | (val & IDE_CMD_RESET)) { | 3045 | (val & IDE_CMD_RESET)) { |
2396 | /* reset low to high */ | 3046 | /* reset low to high */ |
2397 | for(i = 0;i < 2; i++) { | 3047 | for(i = 0;i < 2; i++) { |
2398 | - s = &ide_state[i]; | 3048 | + s = &ide_if[i]; |
2399 | s->status = BUSY_STAT | SEEK_STAT; | 3049 | s->status = BUSY_STAT | SEEK_STAT; |
2400 | s->error = 0x01; | 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 | !(val & IDE_CMD_RESET)) { | 3053 | !(val & IDE_CMD_RESET)) { |
2404 | /* high to low */ | 3054 | /* high to low */ |
2405 | for(i = 0;i < 2; i++) { | 3055 | for(i = 0;i < 2; i++) { |
2406 | - s = &ide_state[i]; | 3056 | + s = &ide_if[i]; |
2407 | s->status = READY_STAT; | 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 | void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) | 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 | uint8_t *p; | 3069 | uint8_t *p; |
2430 | 3070 | ||
2431 | p = s->data_ptr; | 3071 | p = s->data_ptr; |
@@ -2438,10 +3078,9 @@ void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2438,10 +3078,9 @@ void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2438 | 3078 | ||
2439 | uint32_t ide_data_readw(CPUX86State *env, uint32_t addr) | 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 | uint8_t *p; | 3082 | uint8_t *p; |
2443 | int ret; | 3083 | int ret; |
2444 | - | ||
2445 | p = s->data_ptr; | 3084 | p = s->data_ptr; |
2446 | ret = tswap16(*(uint16_t *)p); | 3085 | ret = tswap16(*(uint16_t *)p); |
2447 | p += 2; | 3086 | p += 2; |
@@ -2453,7 +3092,7 @@ uint32_t ide_data_readw(CPUX86State *env, uint32_t addr) | @@ -2453,7 +3092,7 @@ uint32_t ide_data_readw(CPUX86State *env, uint32_t addr) | ||
2453 | 3092 | ||
2454 | void ide_data_writel(CPUX86State *env, uint32_t addr, uint32_t val) | 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 | uint8_t *p; | 3096 | uint8_t *p; |
2458 | 3097 | ||
2459 | p = s->data_ptr; | 3098 | p = s->data_ptr; |
@@ -2466,7 +3105,7 @@ void ide_data_writel(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -2466,7 +3105,7 @@ void ide_data_writel(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2466 | 3105 | ||
2467 | uint32_t ide_data_readl(CPUX86State *env, uint32_t addr) | 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 | uint8_t *p; | 3109 | uint8_t *p; |
2471 | int ret; | 3110 | int ret; |
2472 | 3111 | ||
@@ -2482,9 +3121,10 @@ uint32_t ide_data_readl(CPUX86State *env, uint32_t addr) | @@ -2482,9 +3121,10 @@ uint32_t ide_data_readl(CPUX86State *env, uint32_t addr) | ||
2482 | void ide_reset(IDEState *s) | 3121 | void ide_reset(IDEState *s) |
2483 | { | 3122 | { |
2484 | s->mult_sectors = MAX_MULT_SECTORS; | 3123 | s->mult_sectors = MAX_MULT_SECTORS; |
2485 | - s->status = READY_STAT; | ||
2486 | s->cur_drive = s; | 3124 | s->cur_drive = s; |
2487 | s->select = 0xa0; | 3125 | s->select = 0xa0; |
3126 | + s->status = READY_STAT; | ||
3127 | + ide_set_signature(s); | ||
2488 | } | 3128 | } |
2489 | 3129 | ||
2490 | struct partition { | 3130 | struct partition { |
@@ -2536,8 +3176,11 @@ void ide_guess_geometry(IDEState *s) | @@ -2536,8 +3176,11 @@ void ide_guess_geometry(IDEState *s) | ||
2536 | void ide_init(void) | 3176 | void ide_init(void) |
2537 | { | 3177 | { |
2538 | IDEState *s; | 3178 | IDEState *s; |
2539 | - int i, cylinders; | 3179 | + int i, cylinders, iobase, iobase2; |
2540 | int64_t nb_sectors; | 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 | for(i = 0; i < MAX_DISKS; i++) { | 3185 | for(i = 0; i < MAX_DISKS; i++) { |
2543 | s = &ide_state[i]; | 3186 | s = &ide_state[i]; |
@@ -2558,19 +3201,26 @@ void ide_init(void) | @@ -2558,19 +3201,26 @@ void ide_init(void) | ||
2558 | s->sectors = 63; | 3201 | s->sectors = 63; |
2559 | } | 3202 | } |
2560 | } | 3203 | } |
2561 | - s->irq = 14; | 3204 | + s->irq = ide_irq[i >> 1]; |
2562 | ide_reset(s); | 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,7 +3461,7 @@ void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2811 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | 3461 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
2812 | break; | 3462 | break; |
2813 | default: | 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 | break; | 3465 | break; |
2816 | } | 3466 | } |
2817 | } | 3467 | } |
@@ -3458,8 +4108,10 @@ void help(void) | @@ -3458,8 +4108,10 @@ void help(void) | ||
3458 | "'disk_image' is a raw hard image image for IDE hard disk 0\n" | 4108 | "'disk_image' is a raw hard image image for IDE hard disk 0\n" |
3459 | "\n" | 4109 | "\n" |
3460 | "Standard options:\n" | 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 | "-snapshot write to temporary files instead of disk image files\n" | 4115 | "-snapshot write to temporary files instead of disk image files\n" |
3464 | "-m megs set virtual RAM size to megs MB\n" | 4116 | "-m megs set virtual RAM size to megs MB\n" |
3465 | "-n script set network init script [default=%s]\n" | 4117 | "-n script set network init script [default=%s]\n" |
@@ -3506,6 +4158,10 @@ struct option long_options[] = { | @@ -3506,6 +4158,10 @@ struct option long_options[] = { | ||
3506 | { "kernel", 1, NULL, 0, }, | 4158 | { "kernel", 1, NULL, 0, }, |
3507 | { "append", 1, NULL, 0, }, | 4159 | { "append", 1, NULL, 0, }, |
3508 | { "tun-fd", 1, NULL, 0, }, | 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 | { NULL, 0, NULL, 0 }, | 4165 | { NULL, 0, NULL, 0 }, |
3510 | }; | 4166 | }; |
3511 | 4167 | ||
@@ -3601,6 +4257,23 @@ int main(int argc, char **argv) | @@ -3601,6 +4257,23 @@ int main(int argc, char **argv) | ||
3601 | case 8: | 4257 | case 8: |
3602 | net_fd = atoi(optarg); | 4258 | net_fd = atoi(optarg); |
3603 | break; | 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 | break; | 4278 | break; |
3606 | case 'h': | 4279 | case 'h': |
@@ -3611,7 +4284,7 @@ int main(int argc, char **argv) | @@ -3611,7 +4284,7 @@ int main(int argc, char **argv) | ||
3611 | if (phys_ram_size <= 0) | 4284 | if (phys_ram_size <= 0) |
3612 | help(); | 4285 | help(); |
3613 | if (phys_ram_size > PHYS_RAM_MAX_SIZE) { | 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 | PHYS_RAM_MAX_SIZE / (1024 * 1024)); | 4288 | PHYS_RAM_MAX_SIZE / (1024 * 1024)); |
3616 | exit(1); | 4289 | exit(1); |
3617 | } | 4290 | } |
@@ -3640,7 +4313,7 @@ int main(int argc, char **argv) | @@ -3640,7 +4313,7 @@ int main(int argc, char **argv) | ||
3640 | 4313 | ||
3641 | linux_boot = (kernel_filename != NULL); | 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 | help(); | 4317 | help(); |
3645 | 4318 | ||
3646 | /* init debug */ | 4319 | /* init debug */ |
@@ -3698,7 +4371,7 @@ int main(int argc, char **argv) | @@ -3698,7 +4371,7 @@ int main(int argc, char **argv) | ||
3698 | if (hd_filename[i]) { | 4371 | if (hd_filename[i]) { |
3699 | bs_table[i] = bdrv_open(hd_filename[i], snapshot); | 4372 | bs_table[i] = bdrv_open(hd_filename[i], snapshot); |
3700 | if (!bs_table[i]) { | 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 | hd_filename[i]); | 4375 | hd_filename[i]); |
3703 | exit(1); | 4376 | exit(1); |
3704 | } | 4377 | } |
@@ -3719,7 +4392,7 @@ int main(int argc, char **argv) | @@ -3719,7 +4392,7 @@ int main(int argc, char **argv) | ||
3719 | /* now we can load the kernel */ | 4392 | /* now we can load the kernel */ |
3720 | ret = load_kernel(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); | 4393 | ret = load_kernel(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); |
3721 | if (ret < 0) { | 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 | kernel_filename); | 4396 | kernel_filename); |
3724 | exit(1); | 4397 | exit(1); |
3725 | } | 4398 | } |
@@ -3729,7 +4402,7 @@ int main(int argc, char **argv) | @@ -3729,7 +4402,7 @@ int main(int argc, char **argv) | ||
3729 | if (initrd_filename) { | 4402 | if (initrd_filename) { |
3730 | initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | 4403 | initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); |
3731 | if (initrd_size < 0) { | 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 | initrd_filename); | 4406 | initrd_filename); |
3734 | exit(1); | 4407 | exit(1); |
3735 | } | 4408 | } |
@@ -3788,7 +4461,7 @@ int main(int argc, char **argv) | @@ -3788,7 +4461,7 @@ int main(int argc, char **argv) | ||
3788 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); | 4461 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
3789 | ret = load_image(buf, phys_ram_base + 0x000f0000); | 4462 | ret = load_image(buf, phys_ram_base + 0x000f0000); |
3790 | if (ret != 0x10000) { | 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 | exit(1); | 4465 | exit(1); |
3793 | } | 4466 | } |
3794 | 4467 |