Statistics
| Branch: | Revision:

root / hw / ide.c @ 7f777bf3

History | View | Annotate | Download (43.9 kB)

1 5391d806 bellard
/*
2 5391d806 bellard
 * QEMU IDE disk and CD-ROM Emulator
3 5391d806 bellard
 * 
4 5391d806 bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5391d806 bellard
 * 
6 5391d806 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 5391d806 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 5391d806 bellard
 * in the Software without restriction, including without limitation the rights
9 5391d806 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 5391d806 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 5391d806 bellard
 * furnished to do so, subject to the following conditions:
12 5391d806 bellard
 *
13 5391d806 bellard
 * The above copyright notice and this permission notice shall be included in
14 5391d806 bellard
 * all copies or substantial portions of the Software.
15 5391d806 bellard
 *
16 5391d806 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 5391d806 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 5391d806 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 5391d806 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 5391d806 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 5391d806 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 5391d806 bellard
 * THE SOFTWARE.
23 5391d806 bellard
 */
24 5391d806 bellard
#include <stdlib.h>
25 5391d806 bellard
#include <stdio.h>
26 5391d806 bellard
#include <stdarg.h>
27 5391d806 bellard
#include <string.h>
28 5391d806 bellard
#include <getopt.h>
29 5391d806 bellard
#include <inttypes.h>
30 5391d806 bellard
#include <unistd.h>
31 5391d806 bellard
#include <sys/mman.h>
32 5391d806 bellard
#include <fcntl.h>
33 5391d806 bellard
#include <signal.h>
34 5391d806 bellard
#include <time.h>
35 5391d806 bellard
#include <sys/time.h>
36 5391d806 bellard
#include <malloc.h>
37 5391d806 bellard
#include <termios.h>
38 5391d806 bellard
#include <sys/poll.h>
39 5391d806 bellard
#include <errno.h>
40 5391d806 bellard
#include <sys/wait.h>
41 5391d806 bellard
#include <netinet/in.h>
42 5391d806 bellard
43 6b136f9e bellard
#define NO_THUNK_TYPE_SIZE
44 6b136f9e bellard
#include "thunk.h"
45 6b136f9e bellard
46 5391d806 bellard
#include "cpu.h"
47 5391d806 bellard
#include "exec-all.h"
48 5391d806 bellard
49 5391d806 bellard
#include "vl.h"
50 5391d806 bellard
51 5391d806 bellard
/* debug IDE devices */
52 5391d806 bellard
//#define DEBUG_IDE
53 5391d806 bellard
//#define DEBUG_IDE_ATAPI
54 5391d806 bellard
55 5391d806 bellard
/* Bits of HD_STATUS */
56 5391d806 bellard
#define ERR_STAT                0x01
57 5391d806 bellard
#define INDEX_STAT                0x02
58 5391d806 bellard
#define ECC_STAT                0x04        /* Corrected error */
59 5391d806 bellard
#define DRQ_STAT                0x08
60 5391d806 bellard
#define SEEK_STAT                0x10
61 5391d806 bellard
#define SRV_STAT                0x10
62 5391d806 bellard
#define WRERR_STAT                0x20
63 5391d806 bellard
#define READY_STAT                0x40
64 5391d806 bellard
#define BUSY_STAT                0x80
65 5391d806 bellard
66 5391d806 bellard
/* Bits for HD_ERROR */
67 5391d806 bellard
#define MARK_ERR                0x01        /* Bad address mark */
68 5391d806 bellard
#define TRK0_ERR                0x02        /* couldn't find track 0 */
69 5391d806 bellard
#define ABRT_ERR                0x04        /* Command aborted */
70 5391d806 bellard
#define MCR_ERR                        0x08        /* media change request */
71 5391d806 bellard
#define ID_ERR                        0x10        /* ID field not found */
72 5391d806 bellard
#define MC_ERR                        0x20        /* media changed */
73 5391d806 bellard
#define ECC_ERR                        0x40        /* Uncorrectable ECC error */
74 5391d806 bellard
#define BBD_ERR                        0x80        /* pre-EIDE meaning:  block marked bad */
75 5391d806 bellard
#define ICRC_ERR                0x80        /* new meaning:  CRC error during transfer */
76 5391d806 bellard
77 5391d806 bellard
/* Bits of HD_NSECTOR */
78 5391d806 bellard
#define CD                        0x01
79 5391d806 bellard
#define IO                        0x02
80 5391d806 bellard
#define REL                        0x04
81 5391d806 bellard
#define TAG_MASK                0xf8
82 5391d806 bellard
83 5391d806 bellard
#define IDE_CMD_RESET           0x04
84 5391d806 bellard
#define IDE_CMD_DISABLE_IRQ     0x02
85 5391d806 bellard
86 5391d806 bellard
/* ATA/ATAPI Commands pre T13 Spec */
87 5391d806 bellard
#define WIN_NOP                                0x00
88 5391d806 bellard
/*
89 5391d806 bellard
 *        0x01->0x02 Reserved
90 5391d806 bellard
 */
91 5391d806 bellard
#define CFA_REQ_EXT_ERROR_CODE                0x03 /* CFA Request Extended Error Code */
92 5391d806 bellard
/*
93 5391d806 bellard
 *        0x04->0x07 Reserved
94 5391d806 bellard
 */
95 5391d806 bellard
#define WIN_SRST                        0x08 /* ATAPI soft reset command */
96 5391d806 bellard
#define WIN_DEVICE_RESET                0x08
97 5391d806 bellard
/*
98 5391d806 bellard
 *        0x09->0x0F Reserved
99 5391d806 bellard
 */
100 5391d806 bellard
#define WIN_RECAL                        0x10
101 5391d806 bellard
#define WIN_RESTORE                        WIN_RECAL
102 5391d806 bellard
/*
103 5391d806 bellard
 *        0x10->0x1F Reserved
104 5391d806 bellard
 */
105 5391d806 bellard
#define WIN_READ                        0x20 /* 28-Bit */
106 5391d806 bellard
#define WIN_READ_ONCE                        0x21 /* 28-Bit without retries */
107 5391d806 bellard
#define WIN_READ_LONG                        0x22 /* 28-Bit */
108 5391d806 bellard
#define WIN_READ_LONG_ONCE                0x23 /* 28-Bit without retries */
109 5391d806 bellard
#define WIN_READ_EXT                        0x24 /* 48-Bit */
110 5391d806 bellard
#define WIN_READDMA_EXT                        0x25 /* 48-Bit */
111 5391d806 bellard
#define WIN_READDMA_QUEUED_EXT                0x26 /* 48-Bit */
112 5391d806 bellard
#define WIN_READ_NATIVE_MAX_EXT                0x27 /* 48-Bit */
113 5391d806 bellard
/*
114 5391d806 bellard
 *        0x28
115 5391d806 bellard
 */
116 5391d806 bellard
#define WIN_MULTREAD_EXT                0x29 /* 48-Bit */
117 5391d806 bellard
/*
118 5391d806 bellard
 *        0x2A->0x2F Reserved
119 5391d806 bellard
 */
120 5391d806 bellard
#define WIN_WRITE                        0x30 /* 28-Bit */
121 5391d806 bellard
#define WIN_WRITE_ONCE                        0x31 /* 28-Bit without retries */
122 5391d806 bellard
#define WIN_WRITE_LONG                        0x32 /* 28-Bit */
123 5391d806 bellard
#define WIN_WRITE_LONG_ONCE                0x33 /* 28-Bit without retries */
124 5391d806 bellard
#define WIN_WRITE_EXT                        0x34 /* 48-Bit */
125 5391d806 bellard
#define WIN_WRITEDMA_EXT                0x35 /* 48-Bit */
126 5391d806 bellard
#define WIN_WRITEDMA_QUEUED_EXT                0x36 /* 48-Bit */
127 5391d806 bellard
#define WIN_SET_MAX_EXT                        0x37 /* 48-Bit */
128 5391d806 bellard
#define CFA_WRITE_SECT_WO_ERASE                0x38 /* CFA Write Sectors without erase */
129 5391d806 bellard
#define WIN_MULTWRITE_EXT                0x39 /* 48-Bit */
130 5391d806 bellard
/*
131 5391d806 bellard
 *        0x3A->0x3B Reserved
132 5391d806 bellard
 */
133 5391d806 bellard
#define WIN_WRITE_VERIFY                0x3C /* 28-Bit */
134 5391d806 bellard
/*
135 5391d806 bellard
 *        0x3D->0x3F Reserved
136 5391d806 bellard
 */
137 5391d806 bellard
#define WIN_VERIFY                        0x40 /* 28-Bit - Read Verify Sectors */
138 5391d806 bellard
#define WIN_VERIFY_ONCE                        0x41 /* 28-Bit - without retries */
139 5391d806 bellard
#define WIN_VERIFY_EXT                        0x42 /* 48-Bit */
140 5391d806 bellard
/*
141 5391d806 bellard
 *        0x43->0x4F Reserved
142 5391d806 bellard
 */
143 5391d806 bellard
#define WIN_FORMAT                        0x50
144 5391d806 bellard
/*
145 5391d806 bellard
 *        0x51->0x5F Reserved
146 5391d806 bellard
 */
147 5391d806 bellard
#define WIN_INIT                        0x60
148 5391d806 bellard
/*
149 5391d806 bellard
 *        0x61->0x5F Reserved
150 5391d806 bellard
 */
151 5391d806 bellard
#define WIN_SEEK                        0x70 /* 0x70-0x7F Reserved */
152 5391d806 bellard
#define CFA_TRANSLATE_SECTOR                0x87 /* CFA Translate Sector */
153 5391d806 bellard
#define WIN_DIAGNOSE                        0x90
154 5391d806 bellard
#define WIN_SPECIFY                        0x91 /* set drive geometry translation */
155 5391d806 bellard
#define WIN_DOWNLOAD_MICROCODE                0x92
156 5391d806 bellard
#define WIN_STANDBYNOW2                        0x94
157 5391d806 bellard
#define WIN_STANDBY2                        0x96
158 5391d806 bellard
#define WIN_SETIDLE2                        0x97
159 5391d806 bellard
#define WIN_CHECKPOWERMODE2                0x98
160 5391d806 bellard
#define WIN_SLEEPNOW2                        0x99
161 5391d806 bellard
/*
162 5391d806 bellard
 *        0x9A VENDOR
163 5391d806 bellard
 */
164 5391d806 bellard
#define WIN_PACKETCMD                        0xA0 /* Send a packet command. */
165 5391d806 bellard
#define WIN_PIDENTIFY                        0xA1 /* identify ATAPI device        */
166 5391d806 bellard
#define WIN_QUEUED_SERVICE                0xA2
167 5391d806 bellard
#define WIN_SMART                        0xB0 /* self-monitoring and reporting */
168 5391d806 bellard
#define CFA_ERASE_SECTORS               0xC0
169 5391d806 bellard
#define WIN_MULTREAD                        0xC4 /* read sectors using multiple mode*/
170 5391d806 bellard
#define WIN_MULTWRITE                        0xC5 /* write sectors using multiple mode */
171 5391d806 bellard
#define WIN_SETMULT                        0xC6 /* enable/disable multiple mode */
172 5391d806 bellard
#define WIN_READDMA_QUEUED                0xC7 /* read sectors using Queued DMA transfers */
173 5391d806 bellard
#define WIN_READDMA                        0xC8 /* read sectors using DMA transfers */
174 5391d806 bellard
#define WIN_READDMA_ONCE                0xC9 /* 28-Bit - without retries */
175 5391d806 bellard
#define WIN_WRITEDMA                        0xCA /* write sectors using DMA transfers */
176 5391d806 bellard
#define WIN_WRITEDMA_ONCE                0xCB /* 28-Bit - without retries */
177 5391d806 bellard
#define WIN_WRITEDMA_QUEUED                0xCC /* write sectors using Queued DMA transfers */
178 5391d806 bellard
#define CFA_WRITE_MULTI_WO_ERASE        0xCD /* CFA Write multiple without erase */
179 5391d806 bellard
#define WIN_GETMEDIASTATUS                0xDA        
180 5391d806 bellard
#define WIN_ACKMEDIACHANGE                0xDB /* ATA-1, ATA-2 vendor */
181 5391d806 bellard
#define WIN_POSTBOOT                        0xDC
182 5391d806 bellard
#define WIN_PREBOOT                        0xDD
183 5391d806 bellard
#define WIN_DOORLOCK                        0xDE /* lock door on removable drives */
184 5391d806 bellard
#define WIN_DOORUNLOCK                        0xDF /* unlock door on removable drives */
185 5391d806 bellard
#define WIN_STANDBYNOW1                        0xE0
186 5391d806 bellard
#define WIN_IDLEIMMEDIATE                0xE1 /* force drive to become "ready" */
187 5391d806 bellard
#define WIN_STANDBY                     0xE2 /* Set device in Standby Mode */
188 5391d806 bellard
#define WIN_SETIDLE1                        0xE3
189 5391d806 bellard
#define WIN_READ_BUFFER                        0xE4 /* force read only 1 sector */
190 5391d806 bellard
#define WIN_CHECKPOWERMODE1                0xE5
191 5391d806 bellard
#define WIN_SLEEPNOW1                        0xE6
192 5391d806 bellard
#define WIN_FLUSH_CACHE                        0xE7
193 5391d806 bellard
#define WIN_WRITE_BUFFER                0xE8 /* force write only 1 sector */
194 5391d806 bellard
#define WIN_WRITE_SAME                        0xE9 /* read ata-2 to use */
195 5391d806 bellard
        /* SET_FEATURES 0x22 or 0xDD */
196 5391d806 bellard
#define WIN_FLUSH_CACHE_EXT                0xEA /* 48-Bit */
197 5391d806 bellard
#define WIN_IDENTIFY                        0xEC /* ask drive to identify itself        */
198 5391d806 bellard
#define WIN_MEDIAEJECT                        0xED
199 5391d806 bellard
#define WIN_IDENTIFY_DMA                0xEE /* same as WIN_IDENTIFY, but DMA */
200 5391d806 bellard
#define WIN_SETFEATURES                        0xEF /* set special drive features */
201 5391d806 bellard
#define EXABYTE_ENABLE_NEST                0xF0
202 5391d806 bellard
#define WIN_SECURITY_SET_PASS                0xF1
203 5391d806 bellard
#define WIN_SECURITY_UNLOCK                0xF2
204 5391d806 bellard
#define WIN_SECURITY_ERASE_PREPARE        0xF3
205 5391d806 bellard
#define WIN_SECURITY_ERASE_UNIT                0xF4
206 5391d806 bellard
#define WIN_SECURITY_FREEZE_LOCK        0xF5
207 5391d806 bellard
#define WIN_SECURITY_DISABLE                0xF6
208 5391d806 bellard
#define WIN_READ_NATIVE_MAX                0xF8 /* return the native maximum address */
209 5391d806 bellard
#define WIN_SET_MAX                        0xF9
210 5391d806 bellard
#define DISABLE_SEAGATE                        0xFB
211 5391d806 bellard
212 5391d806 bellard
/* set to 1 set disable mult support */
213 5391d806 bellard
#define MAX_MULT_SECTORS 8
214 5391d806 bellard
215 5391d806 bellard
/* ATAPI defines */
216 5391d806 bellard
217 5391d806 bellard
#define ATAPI_PACKET_SIZE 12
218 5391d806 bellard
219 5391d806 bellard
/* The generic packet command opcodes for CD/DVD Logical Units,
220 5391d806 bellard
 * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
221 5391d806 bellard
#define GPCMD_BLANK                            0xa1
222 5391d806 bellard
#define GPCMD_CLOSE_TRACK                    0x5b
223 5391d806 bellard
#define GPCMD_FLUSH_CACHE                    0x35
224 5391d806 bellard
#define GPCMD_FORMAT_UNIT                    0x04
225 5391d806 bellard
#define GPCMD_GET_CONFIGURATION                    0x46
226 5391d806 bellard
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
227 5391d806 bellard
#define GPCMD_GET_PERFORMANCE                    0xac
228 5391d806 bellard
#define GPCMD_INQUIRY                            0x12
229 5391d806 bellard
#define GPCMD_LOAD_UNLOAD                    0xa6
230 5391d806 bellard
#define GPCMD_MECHANISM_STATUS                    0xbd
231 5391d806 bellard
#define GPCMD_MODE_SELECT_10                    0x55
232 5391d806 bellard
#define GPCMD_MODE_SENSE_10                    0x5a
233 5391d806 bellard
#define GPCMD_PAUSE_RESUME                    0x4b
234 5391d806 bellard
#define GPCMD_PLAY_AUDIO_10                    0x45
235 5391d806 bellard
#define GPCMD_PLAY_AUDIO_MSF                    0x47
236 5391d806 bellard
#define GPCMD_PLAY_AUDIO_TI                    0x48
237 5391d806 bellard
#define GPCMD_PLAY_CD                            0xbc
238 5391d806 bellard
#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
239 5391d806 bellard
#define GPCMD_READ_10                            0x28
240 5391d806 bellard
#define GPCMD_READ_12                            0xa8
241 5391d806 bellard
#define GPCMD_READ_CDVD_CAPACITY            0x25
242 5391d806 bellard
#define GPCMD_READ_CD                            0xbe
243 5391d806 bellard
#define GPCMD_READ_CD_MSF                    0xb9
244 5391d806 bellard
#define GPCMD_READ_DISC_INFO                    0x51
245 5391d806 bellard
#define GPCMD_READ_DVD_STRUCTURE            0xad
246 5391d806 bellard
#define GPCMD_READ_FORMAT_CAPACITIES            0x23
247 5391d806 bellard
#define GPCMD_READ_HEADER                    0x44
248 5391d806 bellard
#define GPCMD_READ_TRACK_RZONE_INFO            0x52
249 5391d806 bellard
#define GPCMD_READ_SUBCHANNEL                    0x42
250 5391d806 bellard
#define GPCMD_READ_TOC_PMA_ATIP                    0x43
251 5391d806 bellard
#define GPCMD_REPAIR_RZONE_TRACK            0x58
252 5391d806 bellard
#define GPCMD_REPORT_KEY                    0xa4
253 5391d806 bellard
#define GPCMD_REQUEST_SENSE                    0x03
254 5391d806 bellard
#define GPCMD_RESERVE_RZONE_TRACK            0x53
255 5391d806 bellard
#define GPCMD_SCAN                            0xba
256 5391d806 bellard
#define GPCMD_SEEK                            0x2b
257 5391d806 bellard
#define GPCMD_SEND_DVD_STRUCTURE            0xad
258 5391d806 bellard
#define GPCMD_SEND_EVENT                    0xa2
259 5391d806 bellard
#define GPCMD_SEND_KEY                            0xa3
260 5391d806 bellard
#define GPCMD_SEND_OPC                            0x54
261 5391d806 bellard
#define GPCMD_SET_READ_AHEAD                    0xa7
262 5391d806 bellard
#define GPCMD_SET_STREAMING                    0xb6
263 5391d806 bellard
#define GPCMD_START_STOP_UNIT                    0x1b
264 5391d806 bellard
#define GPCMD_STOP_PLAY_SCAN                    0x4e
265 5391d806 bellard
#define GPCMD_TEST_UNIT_READY                    0x00
266 5391d806 bellard
#define GPCMD_VERIFY_10                            0x2f
267 5391d806 bellard
#define GPCMD_WRITE_10                            0x2a
268 5391d806 bellard
#define GPCMD_WRITE_AND_VERIFY_10            0x2e
269 5391d806 bellard
/* This is listed as optional in ATAPI 2.6, but is (curiously) 
270 5391d806 bellard
 * missing from Mt. Fuji, Table 57.  It _is_ mentioned in Mt. Fuji
271 5391d806 bellard
 * Table 377 as an MMC command for SCSi devices though...  Most ATAPI
272 5391d806 bellard
 * drives support it. */
273 5391d806 bellard
#define GPCMD_SET_SPEED                            0xbb
274 5391d806 bellard
/* This seems to be a SCSI specific CD-ROM opcode 
275 5391d806 bellard
 * to play data at track/index */
276 5391d806 bellard
#define GPCMD_PLAYAUDIO_TI                    0x48
277 5391d806 bellard
/*
278 5391d806 bellard
 * From MS Media Status Notification Support Specification. For
279 5391d806 bellard
 * older drives only.
280 5391d806 bellard
 */
281 5391d806 bellard
#define GPCMD_GET_MEDIA_STATUS                    0xda
282 5391d806 bellard
283 5391d806 bellard
/* Mode page codes for mode sense/set */
284 5391d806 bellard
#define GPMODE_R_W_ERROR_PAGE                0x01
285 5391d806 bellard
#define GPMODE_WRITE_PARMS_PAGE                0x05
286 5391d806 bellard
#define GPMODE_AUDIO_CTL_PAGE                0x0e
287 5391d806 bellard
#define GPMODE_POWER_PAGE                0x1a
288 5391d806 bellard
#define GPMODE_FAULT_FAIL_PAGE                0x1c
289 5391d806 bellard
#define GPMODE_TO_PROTECT_PAGE                0x1d
290 5391d806 bellard
#define GPMODE_CAPABILITIES_PAGE        0x2a
291 5391d806 bellard
#define GPMODE_ALL_PAGES                0x3f
292 5391d806 bellard
/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
293 5391d806 bellard
 * of MODE_SENSE_POWER_PAGE */
294 5391d806 bellard
#define GPMODE_CDROM_PAGE                0x0d
295 5391d806 bellard
296 5391d806 bellard
#define ATAPI_INT_REASON_CD             0x01 /* 0 = data transfer */
297 5391d806 bellard
#define ATAPI_INT_REASON_IO             0x02 /* 1 = transfer to the host */
298 5391d806 bellard
#define ATAPI_INT_REASON_REL            0x04
299 5391d806 bellard
#define ATAPI_INT_REASON_TAG            0xf8
300 5391d806 bellard
301 5391d806 bellard
/* same constants as bochs */
302 7f777bf3 bellard
#define ASC_ILLEGAL_OPCODE                   0x20
303 5391d806 bellard
#define ASC_LOGICAL_BLOCK_OOR                0x21
304 5391d806 bellard
#define ASC_INV_FIELD_IN_CMD_PACKET          0x24
305 5391d806 bellard
#define ASC_MEDIUM_NOT_PRESENT               0x3a
306 5391d806 bellard
#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED  0x39
307 5391d806 bellard
308 5391d806 bellard
#define SENSE_NONE            0
309 5391d806 bellard
#define SENSE_NOT_READY       2
310 5391d806 bellard
#define SENSE_ILLEGAL_REQUEST 5
311 5391d806 bellard
#define SENSE_UNIT_ATTENTION  6
312 5391d806 bellard
313 5391d806 bellard
struct IDEState;
314 5391d806 bellard
315 5391d806 bellard
typedef void EndTransferFunc(struct IDEState *);
316 5391d806 bellard
317 5391d806 bellard
typedef struct IDEState {
318 5391d806 bellard
    /* ide config */
319 5391d806 bellard
    int is_cdrom;
320 5391d806 bellard
    int cdrom_locked;
321 5391d806 bellard
    int cylinders, heads, sectors;
322 5391d806 bellard
    int64_t nb_sectors;
323 5391d806 bellard
    int mult_sectors;
324 5391d806 bellard
    int irq;
325 5391d806 bellard
    /* ide regs */
326 5391d806 bellard
    uint8_t feature;
327 5391d806 bellard
    uint8_t error;
328 5391d806 bellard
    uint16_t nsector; /* 0 is 256 to ease computations */
329 5391d806 bellard
    uint8_t sector;
330 5391d806 bellard
    uint8_t lcyl;
331 5391d806 bellard
    uint8_t hcyl;
332 5391d806 bellard
    uint8_t select;
333 5391d806 bellard
    uint8_t status;
334 5391d806 bellard
    /* 0x3f6 command, only meaningful for drive 0 */
335 5391d806 bellard
    uint8_t cmd;
336 5391d806 bellard
    /* depends on bit 4 in select, only meaningful for drive 0 */
337 5391d806 bellard
    struct IDEState *cur_drive; 
338 5391d806 bellard
    BlockDriverState *bs;
339 5391d806 bellard
    /* ATAPI specific */
340 5391d806 bellard
    uint8_t sense_key;
341 5391d806 bellard
    uint8_t asc;
342 5391d806 bellard
    int packet_transfer_size;
343 5391d806 bellard
    int elementary_transfer_size;
344 5391d806 bellard
    int io_buffer_index;
345 5391d806 bellard
    int lba;
346 5391d806 bellard
    /* transfer handling */
347 5391d806 bellard
    int req_nb_sectors; /* number of sectors per interrupt */
348 5391d806 bellard
    EndTransferFunc *end_transfer_func;
349 5391d806 bellard
    uint8_t *data_ptr;
350 5391d806 bellard
    uint8_t *data_end;
351 5391d806 bellard
    uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
352 5391d806 bellard
} IDEState;
353 5391d806 bellard
354 5391d806 bellard
IDEState ide_state[MAX_DISKS];
355 5391d806 bellard
IDEState *ide_table[0x400 >> 3];
356 5391d806 bellard
357 5391d806 bellard
static inline IDEState *get_ide_interface(uint32_t addr)
358 5391d806 bellard
{
359 5391d806 bellard
    return ide_table[addr >> 3];
360 5391d806 bellard
}
361 5391d806 bellard
362 5391d806 bellard
static void padstr(char *str, const char *src, int len)
363 5391d806 bellard
{
364 5391d806 bellard
    int i, v;
365 5391d806 bellard
    for(i = 0; i < len; i++) {
366 5391d806 bellard
        if (*src)
367 5391d806 bellard
            v = *src++;
368 5391d806 bellard
        else
369 5391d806 bellard
            v = ' ';
370 5391d806 bellard
        *(char *)((long)str ^ 1) = v;
371 5391d806 bellard
        str++;
372 5391d806 bellard
    }
373 5391d806 bellard
}
374 5391d806 bellard
375 bd0d90b2 bellard
static void padstr8(uint8_t *buf, int buf_size, const char *src)
376 bd0d90b2 bellard
{
377 bd0d90b2 bellard
    int i;
378 bd0d90b2 bellard
    for(i = 0; i < buf_size; i++) {
379 bd0d90b2 bellard
        if (*src)
380 bd0d90b2 bellard
            buf[i] = *src++;
381 bd0d90b2 bellard
        else
382 bd0d90b2 bellard
            buf[i] = ' ';
383 bd0d90b2 bellard
    }
384 bd0d90b2 bellard
}
385 bd0d90b2 bellard
386 5391d806 bellard
static void ide_identify(IDEState *s)
387 5391d806 bellard
{
388 5391d806 bellard
    uint16_t *p;
389 5391d806 bellard
    unsigned int oldsize;
390 5391d806 bellard
391 5391d806 bellard
    memset(s->io_buffer, 0, 512);
392 5391d806 bellard
    p = (uint16_t *)s->io_buffer;
393 5391d806 bellard
    stw_raw(p + 0, 0x0040);
394 5391d806 bellard
    stw_raw(p + 1, s->cylinders); 
395 5391d806 bellard
    stw_raw(p + 3, s->heads);
396 5391d806 bellard
    stw_raw(p + 4, 512 * s->sectors); /* sectors */
397 5391d806 bellard
    stw_raw(p + 5, 512); /* sector size */
398 5391d806 bellard
    stw_raw(p + 6, s->sectors); 
399 5391d806 bellard
    padstr((uint8_t *)(p + 10), "QM00001", 20); /* serial number */
400 5391d806 bellard
    stw_raw(p + 20, 3); /* buffer type */
401 5391d806 bellard
    stw_raw(p + 21, 512); /* cache size in sectors */
402 5391d806 bellard
    stw_raw(p + 22, 4); /* ecc bytes */
403 5391d806 bellard
    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
404 5391d806 bellard
    padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */
405 5391d806 bellard
#if MAX_MULT_SECTORS > 1    
406 5391d806 bellard
    stw_raw(p + 47, MAX_MULT_SECTORS);
407 5391d806 bellard
#endif
408 5391d806 bellard
    stw_raw(p + 48, 1); /* dword I/O */
409 5391d806 bellard
    stw_raw(p + 49, 1 << 9); /* LBA supported, no DMA */
410 5391d806 bellard
    stw_raw(p + 51, 0x200); /* PIO transfer cycle */
411 5391d806 bellard
    stw_raw(p + 52, 0x200); /* DMA transfer cycle */
412 5391d806 bellard
    stw_raw(p + 54, s->cylinders);
413 5391d806 bellard
    stw_raw(p + 55, s->heads);
414 5391d806 bellard
    stw_raw(p + 56, s->sectors);
415 5391d806 bellard
    oldsize = s->cylinders * s->heads * s->sectors;
416 5391d806 bellard
    stw_raw(p + 57, oldsize);
417 5391d806 bellard
    stw_raw(p + 58, oldsize >> 16);
418 5391d806 bellard
    if (s->mult_sectors)
419 5391d806 bellard
        stw_raw(p + 59, 0x100 | s->mult_sectors);
420 5391d806 bellard
    stw_raw(p + 60, s->nb_sectors);
421 5391d806 bellard
    stw_raw(p + 61, s->nb_sectors >> 16);
422 5391d806 bellard
    stw_raw(p + 80, (1 << 1) | (1 << 2));
423 5391d806 bellard
    stw_raw(p + 82, (1 << 14));
424 5391d806 bellard
    stw_raw(p + 83, (1 << 14));
425 5391d806 bellard
    stw_raw(p + 84, (1 << 14));
426 5391d806 bellard
    stw_raw(p + 85, (1 << 14));
427 5391d806 bellard
    stw_raw(p + 86, 0);
428 5391d806 bellard
    stw_raw(p + 87, (1 << 14));
429 5391d806 bellard
}
430 5391d806 bellard
431 5391d806 bellard
static void ide_atapi_identify(IDEState *s)
432 5391d806 bellard
{
433 5391d806 bellard
    uint16_t *p;
434 5391d806 bellard
435 5391d806 bellard
    memset(s->io_buffer, 0, 512);
436 5391d806 bellard
    p = (uint16_t *)s->io_buffer;
437 5391d806 bellard
    /* Removable CDROM, 50us response, 12 byte packets */
438 5391d806 bellard
    stw_raw(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
439 5391d806 bellard
    stw_raw(p + 1, s->cylinders); 
440 5391d806 bellard
    stw_raw(p + 3, s->heads);
441 5391d806 bellard
    stw_raw(p + 4, 512 * s->sectors); /* sectors */
442 5391d806 bellard
    stw_raw(p + 5, 512); /* sector size */
443 5391d806 bellard
    stw_raw(p + 6, s->sectors); 
444 5391d806 bellard
    padstr((uint8_t *)(p + 10), "QM00001", 20); /* serial number */
445 5391d806 bellard
    stw_raw(p + 20, 3); /* buffer type */
446 5391d806 bellard
    stw_raw(p + 21, 512); /* cache size in sectors */
447 5391d806 bellard
    stw_raw(p + 22, 4); /* ecc bytes */
448 5391d806 bellard
    padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
449 5391d806 bellard
    padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
450 5391d806 bellard
    stw_raw(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
451 5391d806 bellard
    stw_raw(p + 49, 1 << 9); /* LBA supported, no DMA */
452 5391d806 bellard
    stw_raw(p + 53, 3); /* words 64-70, 54-58 valid */
453 5391d806 bellard
    stw_raw(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
454 5391d806 bellard
    stw_raw(p + 64, 1); /* PIO modes */
455 5391d806 bellard
    stw_raw(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
456 5391d806 bellard
    stw_raw(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
457 5391d806 bellard
    stw_raw(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
458 5391d806 bellard
    stw_raw(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
459 5391d806 bellard
    
460 5391d806 bellard
    stw_raw(p + 71, 30); /* in ns */
461 5391d806 bellard
    stw_raw(p + 72, 30); /* in ns */
462 5391d806 bellard
463 5391d806 bellard
    stw_raw(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
464 5391d806 bellard
}
465 5391d806 bellard
466 5391d806 bellard
static void ide_set_signature(IDEState *s)
467 5391d806 bellard
{
468 5391d806 bellard
    s->select &= 0xf0; /* clear head */
469 5391d806 bellard
    /* put signature */
470 5391d806 bellard
    s->nsector = 1;
471 5391d806 bellard
    s->sector = 1;
472 5391d806 bellard
    if (s->is_cdrom) {
473 5391d806 bellard
        s->lcyl = 0x14;
474 5391d806 bellard
        s->hcyl = 0xeb;
475 5391d806 bellard
    } else if (s->bs) {
476 5391d806 bellard
        s->lcyl = 0;
477 5391d806 bellard
        s->hcyl = 0;
478 5391d806 bellard
    } else {
479 5391d806 bellard
        s->lcyl = 0xff;
480 5391d806 bellard
        s->hcyl = 0xff;
481 5391d806 bellard
    }
482 5391d806 bellard
}
483 5391d806 bellard
484 5391d806 bellard
static inline void ide_abort_command(IDEState *s)
485 5391d806 bellard
{
486 5391d806 bellard
    s->status = READY_STAT | ERR_STAT;
487 5391d806 bellard
    s->error = ABRT_ERR;
488 5391d806 bellard
}
489 5391d806 bellard
490 5391d806 bellard
static inline void ide_set_irq(IDEState *s)
491 5391d806 bellard
{
492 5391d806 bellard
    if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
493 5391d806 bellard
        pic_set_irq(s->irq, 1);
494 5391d806 bellard
    }
495 5391d806 bellard
}
496 5391d806 bellard
497 5391d806 bellard
/* prepare data transfer and tell what to do after */
498 5391d806 bellard
static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, 
499 5391d806 bellard
                               EndTransferFunc *end_transfer_func)
500 5391d806 bellard
{
501 5391d806 bellard
    s->end_transfer_func = end_transfer_func;
502 5391d806 bellard
    s->data_ptr = buf;
503 5391d806 bellard
    s->data_end = buf + size;
504 5391d806 bellard
    s->status |= DRQ_STAT;
505 5391d806 bellard
}
506 5391d806 bellard
507 5391d806 bellard
static void ide_transfer_stop(IDEState *s)
508 5391d806 bellard
{
509 5391d806 bellard
    s->end_transfer_func = ide_transfer_stop;
510 5391d806 bellard
    s->data_ptr = s->io_buffer;
511 5391d806 bellard
    s->data_end = s->io_buffer;
512 5391d806 bellard
    s->status &= ~DRQ_STAT;
513 5391d806 bellard
}
514 5391d806 bellard
515 5391d806 bellard
static int64_t ide_get_sector(IDEState *s)
516 5391d806 bellard
{
517 5391d806 bellard
    int64_t sector_num;
518 5391d806 bellard
    if (s->select & 0x40) {
519 5391d806 bellard
        /* lba */
520 5391d806 bellard
        sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | 
521 5391d806 bellard
            (s->lcyl << 8) | s->sector;
522 5391d806 bellard
    } else {
523 5391d806 bellard
        sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
524 5391d806 bellard
            (s->select & 0x0f) * s->sectors + 
525 5391d806 bellard
            (s->sector - 1);
526 5391d806 bellard
    }
527 5391d806 bellard
    return sector_num;
528 5391d806 bellard
}
529 5391d806 bellard
530 5391d806 bellard
static void ide_set_sector(IDEState *s, int64_t sector_num)
531 5391d806 bellard
{
532 5391d806 bellard
    unsigned int cyl, r;
533 5391d806 bellard
    if (s->select & 0x40) {
534 5391d806 bellard
        s->select = (s->select & 0xf0) | (sector_num >> 24);
535 5391d806 bellard
        s->hcyl = (sector_num >> 16);
536 5391d806 bellard
        s->lcyl = (sector_num >> 8);
537 5391d806 bellard
        s->sector = (sector_num);
538 5391d806 bellard
    } else {
539 5391d806 bellard
        cyl = sector_num / (s->heads * s->sectors);
540 5391d806 bellard
        r = sector_num % (s->heads * s->sectors);
541 5391d806 bellard
        s->hcyl = cyl >> 8;
542 5391d806 bellard
        s->lcyl = cyl;
543 5391d806 bellard
        s->select = (s->select & 0xf0) | (r / s->sectors);
544 5391d806 bellard
        s->sector = (r % s->sectors) + 1;
545 5391d806 bellard
    }
546 5391d806 bellard
}
547 5391d806 bellard
548 5391d806 bellard
static void ide_sector_read(IDEState *s)
549 5391d806 bellard
{
550 5391d806 bellard
    int64_t sector_num;
551 5391d806 bellard
    int ret, n;
552 5391d806 bellard
553 5391d806 bellard
    s->status = READY_STAT | SEEK_STAT;
554 a136e5a8 bellard
    s->error = 0; /* not needed by IDE spec, but needed by Windows */
555 5391d806 bellard
    sector_num = ide_get_sector(s);
556 5391d806 bellard
    n = s->nsector;
557 5391d806 bellard
    if (n == 0) {
558 5391d806 bellard
        /* no more sector to read from disk */
559 5391d806 bellard
        ide_transfer_stop(s);
560 5391d806 bellard
    } else {
561 5391d806 bellard
#if defined(DEBUG_IDE)
562 5391d806 bellard
        printf("read sector=%Ld\n", sector_num);
563 5391d806 bellard
#endif
564 5391d806 bellard
        if (n > s->req_nb_sectors)
565 5391d806 bellard
            n = s->req_nb_sectors;
566 5391d806 bellard
        ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
567 5391d806 bellard
        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
568 5391d806 bellard
        ide_set_irq(s);
569 5391d806 bellard
        ide_set_sector(s, sector_num + n);
570 5391d806 bellard
        s->nsector -= n;
571 5391d806 bellard
    }
572 5391d806 bellard
}
573 5391d806 bellard
574 5391d806 bellard
static void ide_sector_write(IDEState *s)
575 5391d806 bellard
{
576 5391d806 bellard
    int64_t sector_num;
577 5391d806 bellard
    int ret, n, n1;
578 5391d806 bellard
579 5391d806 bellard
    s->status = READY_STAT | SEEK_STAT;
580 5391d806 bellard
    sector_num = ide_get_sector(s);
581 5391d806 bellard
#if defined(DEBUG_IDE)
582 5391d806 bellard
    printf("write sector=%Ld\n", sector_num);
583 5391d806 bellard
#endif
584 5391d806 bellard
    n = s->nsector;
585 5391d806 bellard
    if (n > s->req_nb_sectors)
586 5391d806 bellard
        n = s->req_nb_sectors;
587 5391d806 bellard
    ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
588 5391d806 bellard
    s->nsector -= n;
589 5391d806 bellard
    if (s->nsector == 0) {
590 5391d806 bellard
        /* no more sector to write */
591 5391d806 bellard
        ide_transfer_stop(s);
592 5391d806 bellard
    } else {
593 5391d806 bellard
        n1 = s->nsector;
594 5391d806 bellard
        if (n1 > s->req_nb_sectors)
595 5391d806 bellard
            n1 = s->req_nb_sectors;
596 5391d806 bellard
        ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
597 5391d806 bellard
    }
598 5391d806 bellard
    ide_set_sector(s, sector_num + n);
599 5391d806 bellard
    ide_set_irq(s);
600 5391d806 bellard
}
601 5391d806 bellard
602 5391d806 bellard
static void ide_atapi_cmd_ok(IDEState *s)
603 5391d806 bellard
{
604 5391d806 bellard
    s->error = 0;
605 5391d806 bellard
    s->status = READY_STAT;
606 5391d806 bellard
    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
607 5391d806 bellard
    ide_set_irq(s);
608 5391d806 bellard
}
609 5391d806 bellard
610 5391d806 bellard
static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
611 5391d806 bellard
{
612 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
613 5391d806 bellard
    printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
614 5391d806 bellard
#endif
615 5391d806 bellard
    s->error = sense_key << 4;
616 5391d806 bellard
    s->status = READY_STAT | ERR_STAT;
617 5391d806 bellard
    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
618 5391d806 bellard
    s->sense_key = sense_key;
619 5391d806 bellard
    s->asc = asc;
620 5391d806 bellard
    ide_set_irq(s);
621 5391d806 bellard
}
622 5391d806 bellard
623 5391d806 bellard
static inline void cpu_to_ube16(uint8_t *buf, int val)
624 5391d806 bellard
{
625 5391d806 bellard
    buf[0] = val >> 8;
626 5391d806 bellard
    buf[1] = val;
627 5391d806 bellard
}
628 5391d806 bellard
629 5391d806 bellard
static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
630 5391d806 bellard
{
631 5391d806 bellard
    buf[0] = val >> 24;
632 5391d806 bellard
    buf[1] = val >> 16;
633 5391d806 bellard
    buf[2] = val >> 8;
634 5391d806 bellard
    buf[3] = val;
635 5391d806 bellard
}
636 5391d806 bellard
637 5391d806 bellard
static inline int ube16_to_cpu(const uint8_t *buf)
638 5391d806 bellard
{
639 5391d806 bellard
    return (buf[0] << 8) | buf[1];
640 5391d806 bellard
}
641 5391d806 bellard
642 5391d806 bellard
static inline int ube32_to_cpu(const uint8_t *buf)
643 5391d806 bellard
{
644 5391d806 bellard
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
645 5391d806 bellard
}
646 5391d806 bellard
647 5391d806 bellard
/* The whole ATAPI transfer logic is handled in this function */
648 5391d806 bellard
static void ide_atapi_cmd_reply_end(IDEState *s)
649 5391d806 bellard
{
650 5391d806 bellard
    int byte_count_limit, size;
651 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
652 5391d806 bellard
    printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", 
653 5391d806 bellard
           s->packet_transfer_size,
654 5391d806 bellard
           s->elementary_transfer_size,
655 5391d806 bellard
           s->io_buffer_index);
656 5391d806 bellard
#endif
657 5391d806 bellard
    if (s->packet_transfer_size <= 0) {
658 5391d806 bellard
        /* end of transfer */
659 5391d806 bellard
        ide_transfer_stop(s);
660 5391d806 bellard
        s->status = READY_STAT;
661 5391d806 bellard
        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
662 5391d806 bellard
        ide_set_irq(s);
663 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
664 5391d806 bellard
        printf("status=0x%x\n", s->status);
665 5391d806 bellard
#endif
666 5391d806 bellard
    } else {
667 5391d806 bellard
        /* see if a new sector must be read */
668 5391d806 bellard
        if (s->lba != -1 && s->io_buffer_index >= 2048) {
669 5391d806 bellard
            bdrv_read(s->bs, (int64_t)s->lba << 2, s->io_buffer, 4);
670 5391d806 bellard
            s->lba++;
671 5391d806 bellard
            s->io_buffer_index = 0;
672 5391d806 bellard
        }
673 5391d806 bellard
        if (s->elementary_transfer_size > 0) {
674 5391d806 bellard
            /* there are some data left to transmit in this elementary
675 5391d806 bellard
               transfer */
676 5391d806 bellard
            size = 2048 - s->io_buffer_index;
677 5391d806 bellard
            if (size > s->elementary_transfer_size)
678 5391d806 bellard
                size = s->elementary_transfer_size;
679 5391d806 bellard
            ide_transfer_start(s, s->io_buffer + s->io_buffer_index, 
680 5391d806 bellard
                               size, ide_atapi_cmd_reply_end);
681 5391d806 bellard
            s->packet_transfer_size -= size;
682 5391d806 bellard
            s->elementary_transfer_size -= size;
683 5391d806 bellard
            s->io_buffer_index += size;
684 5391d806 bellard
        } else {
685 5391d806 bellard
            /* a new transfer is needed */
686 5391d806 bellard
            s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
687 5391d806 bellard
            byte_count_limit = s->lcyl | (s->hcyl << 8);
688 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
689 5391d806 bellard
            printf("byte_count_limit=%d\n", byte_count_limit);
690 5391d806 bellard
#endif
691 5391d806 bellard
            if (byte_count_limit == 0xffff)
692 5391d806 bellard
                byte_count_limit--;
693 5391d806 bellard
            size = s->packet_transfer_size;
694 5391d806 bellard
            if (size > byte_count_limit) {
695 5391d806 bellard
                /* byte count limit must be even if this case */
696 5391d806 bellard
                if (byte_count_limit & 1)
697 5391d806 bellard
                    byte_count_limit--;
698 5391d806 bellard
                size = byte_count_limit;
699 5391d806 bellard
            }
700 a136e5a8 bellard
            s->lcyl = size;
701 a136e5a8 bellard
            s->hcyl = size >> 8;
702 5391d806 bellard
            s->elementary_transfer_size = size;
703 5391d806 bellard
            /* we cannot transmit more than one sector at a time */
704 5391d806 bellard
            if (s->lba != -1) {
705 5391d806 bellard
                if (size > (2048 - s->io_buffer_index))
706 5391d806 bellard
                    size = (2048 - s->io_buffer_index);
707 5391d806 bellard
            }
708 5391d806 bellard
            ide_transfer_start(s, s->io_buffer + s->io_buffer_index, 
709 5391d806 bellard
                               size, ide_atapi_cmd_reply_end);
710 5391d806 bellard
            s->packet_transfer_size -= size;
711 5391d806 bellard
            s->elementary_transfer_size -= size;
712 5391d806 bellard
            s->io_buffer_index += size;
713 5391d806 bellard
            ide_set_irq(s);
714 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
715 5391d806 bellard
            printf("status=0x%x\n", s->status);
716 5391d806 bellard
#endif
717 5391d806 bellard
        }
718 5391d806 bellard
    }
719 5391d806 bellard
}
720 5391d806 bellard
721 5391d806 bellard
/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
722 5391d806 bellard
static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
723 5391d806 bellard
{
724 5391d806 bellard
    if (size > max_size)
725 5391d806 bellard
        size = max_size;
726 5391d806 bellard
    s->lba = -1; /* no sector read */
727 5391d806 bellard
    s->packet_transfer_size = size;
728 5391d806 bellard
    s->elementary_transfer_size = 0;
729 5391d806 bellard
    s->io_buffer_index = 0;
730 5391d806 bellard
731 5391d806 bellard
    s->status = READY_STAT;
732 5391d806 bellard
    ide_atapi_cmd_reply_end(s);
733 5391d806 bellard
}
734 5391d806 bellard
735 5391d806 bellard
/* start a CD-CDROM read command */
736 5391d806 bellard
static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors)
737 5391d806 bellard
{
738 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
739 5391d806 bellard
    printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
740 5391d806 bellard
#endif
741 5391d806 bellard
    s->lba = lba;
742 5391d806 bellard
    s->packet_transfer_size = nb_sectors * 2048;
743 5391d806 bellard
    s->elementary_transfer_size = 0;
744 5391d806 bellard
    s->io_buffer_index = 2048;
745 5391d806 bellard
746 5391d806 bellard
    s->status = READY_STAT;
747 5391d806 bellard
    ide_atapi_cmd_reply_end(s);
748 5391d806 bellard
}
749 5391d806 bellard
750 5391d806 bellard
/* same toc as bochs. Return -1 if error or the toc length */
751 5391d806 bellard
static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)
752 5391d806 bellard
{
753 5391d806 bellard
    uint8_t *q;
754 5391d806 bellard
    int nb_sectors, len;
755 5391d806 bellard
    
756 5391d806 bellard
    if (start_track > 1 && start_track != 0xaa)
757 5391d806 bellard
        return -1;
758 5391d806 bellard
    q = buf + 2;
759 5391d806 bellard
    *q++ = 1;
760 5391d806 bellard
    *q++ = 1;
761 5391d806 bellard
    if (start_track <= 1) {
762 5391d806 bellard
        *q++ = 0; /* reserved */
763 5391d806 bellard
        *q++ = 0x14; /* ADR, control */
764 5391d806 bellard
        *q++ = 1;    /* track number */
765 5391d806 bellard
        *q++ = 0; /* reserved */
766 5391d806 bellard
        if (msf) {
767 5391d806 bellard
            *q++ = 0; /* reserved */
768 5391d806 bellard
            *q++ = 0; /* minute */
769 5391d806 bellard
            *q++ = 2; /* second */
770 5391d806 bellard
            *q++ = 0; /* frame */
771 5391d806 bellard
        } else {
772 5391d806 bellard
            /* sector 0 */
773 5391d806 bellard
            cpu_to_ube32(q, 0);
774 5391d806 bellard
            q += 4;
775 5391d806 bellard
        }
776 5391d806 bellard
    }
777 5391d806 bellard
    /* lead out track */
778 5391d806 bellard
    *q++ = 0; /* reserved */
779 5391d806 bellard
    *q++ = 0x16; /* ADR, control */
780 5391d806 bellard
    *q++ = 0xaa; /* track number */
781 5391d806 bellard
    *q++ = 0; /* reserved */
782 5391d806 bellard
    nb_sectors = s->nb_sectors >> 2;
783 5391d806 bellard
    if (msf) {
784 5391d806 bellard
        *q++ = 0; /* reserved */
785 5391d806 bellard
        *q++ = ((nb_sectors + 150) / 75) / 60;
786 5391d806 bellard
        *q++ = ((nb_sectors + 150) / 75) % 60;
787 5391d806 bellard
        *q++ = (nb_sectors + 150) % 75;
788 5391d806 bellard
    } else {
789 5391d806 bellard
        cpu_to_ube32(q, nb_sectors);
790 5391d806 bellard
        q += 4;
791 5391d806 bellard
    }
792 5391d806 bellard
    len = q - buf;
793 5391d806 bellard
    cpu_to_ube16(buf, len - 2);
794 5391d806 bellard
    return len;
795 5391d806 bellard
}
796 5391d806 bellard
797 5391d806 bellard
static void ide_atapi_cmd(IDEState *s)
798 5391d806 bellard
{
799 5391d806 bellard
    const uint8_t *packet;
800 5391d806 bellard
    uint8_t *buf;
801 5391d806 bellard
    int max_len;
802 5391d806 bellard
803 5391d806 bellard
    packet = s->io_buffer;
804 5391d806 bellard
    buf = s->io_buffer;
805 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
806 5391d806 bellard
    {
807 5391d806 bellard
        int i;
808 5391d806 bellard
        printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
809 5391d806 bellard
        for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
810 5391d806 bellard
            printf(" %02x", packet[i]);
811 5391d806 bellard
        }
812 5391d806 bellard
        printf("\n");
813 5391d806 bellard
    }
814 5391d806 bellard
#endif
815 5391d806 bellard
    switch(s->io_buffer[0]) {
816 5391d806 bellard
    case GPCMD_TEST_UNIT_READY:
817 5391d806 bellard
        if (s->bs) {
818 5391d806 bellard
            ide_atapi_cmd_ok(s);
819 5391d806 bellard
        } else {
820 5391d806 bellard
            ide_atapi_cmd_error(s, SENSE_NOT_READY, 
821 5391d806 bellard
                                ASC_MEDIUM_NOT_PRESENT);
822 5391d806 bellard
        }
823 5391d806 bellard
        break;
824 5391d806 bellard
    case GPCMD_MODE_SENSE_10:
825 5391d806 bellard
        {
826 5391d806 bellard
            int action, code;
827 5391d806 bellard
            max_len = ube16_to_cpu(packet + 7);
828 5391d806 bellard
            action = packet[2] >> 6;
829 5391d806 bellard
            code = packet[2] & 0x3f;
830 5391d806 bellard
            switch(action) {
831 5391d806 bellard
            case 0: /* current values */
832 5391d806 bellard
                switch(code) {
833 5391d806 bellard
                case 0x01: /* error recovery */
834 5391d806 bellard
                    cpu_to_ube16(&buf[0], 16 + 6);
835 5391d806 bellard
                    buf[2] = 0x70;
836 5391d806 bellard
                    buf[3] = 0;
837 5391d806 bellard
                    buf[4] = 0;
838 5391d806 bellard
                    buf[5] = 0;
839 5391d806 bellard
                    buf[6] = 0;
840 5391d806 bellard
                    buf[7] = 0;
841 5391d806 bellard
842 5391d806 bellard
                    buf[8] = 0x01;
843 5391d806 bellard
                    buf[9] = 0x06;
844 5391d806 bellard
                    buf[10] = 0x00;
845 5391d806 bellard
                    buf[11] = 0x05;
846 5391d806 bellard
                    buf[12] = 0x00;
847 5391d806 bellard
                    buf[13] = 0x00;
848 5391d806 bellard
                    buf[14] = 0x00;
849 5391d806 bellard
                    buf[15] = 0x00;
850 5391d806 bellard
                    ide_atapi_cmd_reply(s, 16, max_len);
851 5391d806 bellard
                    break;
852 5391d806 bellard
                case 0x2a:
853 5391d806 bellard
                    cpu_to_ube16(&buf[0], 28 + 6);
854 5391d806 bellard
                    buf[2] = 0x70;
855 5391d806 bellard
                    buf[3] = 0;
856 5391d806 bellard
                    buf[4] = 0;
857 5391d806 bellard
                    buf[5] = 0;
858 5391d806 bellard
                    buf[6] = 0;
859 5391d806 bellard
                    buf[7] = 0;
860 5391d806 bellard
861 5391d806 bellard
                    buf[8] = 0x2a;
862 5391d806 bellard
                    buf[9] = 0x12;
863 5391d806 bellard
                    buf[10] = 0x00;
864 5391d806 bellard
                    buf[11] = 0x00;
865 5391d806 bellard
                    
866 5391d806 bellard
                    buf[12] = 0x70;
867 5391d806 bellard
                    buf[13] = 3 << 5;
868 5391d806 bellard
                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
869 5391d806 bellard
                    if (s->cdrom_locked)
870 5391d806 bellard
                        buf[6] |= 1 << 1;
871 5391d806 bellard
                    buf[15] = 0x00;
872 5391d806 bellard
                    cpu_to_ube16(&buf[16], 706);
873 5391d806 bellard
                    buf[18] = 0;
874 5391d806 bellard
                    buf[19] = 2;
875 5391d806 bellard
                    cpu_to_ube16(&buf[20], 512);
876 5391d806 bellard
                    cpu_to_ube16(&buf[22], 706);
877 5391d806 bellard
                    buf[24] = 0;
878 5391d806 bellard
                    buf[25] = 0;
879 5391d806 bellard
                    buf[26] = 0;
880 5391d806 bellard
                    buf[27] = 0;
881 5391d806 bellard
                    ide_atapi_cmd_reply(s, 28, max_len);
882 5391d806 bellard
                    break;
883 5391d806 bellard
                default:
884 5391d806 bellard
                    goto error_cmd;
885 5391d806 bellard
                }
886 5391d806 bellard
                break;
887 5391d806 bellard
            case 1: /* changeable values */
888 5391d806 bellard
                goto error_cmd;
889 5391d806 bellard
            case 2: /* default values */
890 5391d806 bellard
                goto error_cmd;
891 5391d806 bellard
            default:
892 5391d806 bellard
            case 3: /* saved values */
893 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
894 5391d806 bellard
                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
895 5391d806 bellard
                break;
896 5391d806 bellard
            }
897 5391d806 bellard
        }
898 5391d806 bellard
        break;
899 5391d806 bellard
    case GPCMD_REQUEST_SENSE:
900 5391d806 bellard
        max_len = packet[4];
901 5391d806 bellard
        memset(buf, 0, 18);
902 5391d806 bellard
        buf[0] = 0x70 | (1 << 7);
903 5391d806 bellard
        buf[2] = s->sense_key;
904 5391d806 bellard
        buf[7] = 10;
905 5391d806 bellard
        buf[12] = s->asc;
906 5391d806 bellard
        ide_atapi_cmd_reply(s, 18, max_len);
907 5391d806 bellard
        break;
908 5391d806 bellard
    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
909 5391d806 bellard
        if (s->bs) {
910 5391d806 bellard
            s->cdrom_locked = packet[4] & 1;
911 5391d806 bellard
            ide_atapi_cmd_ok(s);
912 5391d806 bellard
        } else {
913 5391d806 bellard
            ide_atapi_cmd_error(s, SENSE_NOT_READY, 
914 5391d806 bellard
                                ASC_MEDIUM_NOT_PRESENT);
915 5391d806 bellard
        }
916 5391d806 bellard
        break;
917 5391d806 bellard
    case GPCMD_READ_10:
918 5391d806 bellard
    case GPCMD_READ_12:
919 5391d806 bellard
        {
920 5391d806 bellard
            int nb_sectors, lba;
921 5391d806 bellard
922 5391d806 bellard
            if (!s->bs) {
923 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
924 5391d806 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
925 5391d806 bellard
                break;
926 5391d806 bellard
            }
927 5391d806 bellard
            if (packet[0] == GPCMD_READ_10)
928 5391d806 bellard
                nb_sectors = ube16_to_cpu(packet + 7);
929 5391d806 bellard
            else
930 5391d806 bellard
                nb_sectors = ube32_to_cpu(packet + 6);
931 5391d806 bellard
            lba = ube32_to_cpu(packet + 2);
932 5391d806 bellard
            if (nb_sectors == 0) {
933 5391d806 bellard
                ide_atapi_cmd_ok(s);
934 5391d806 bellard
                break;
935 5391d806 bellard
            }
936 5391d806 bellard
            if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
937 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
938 5391d806 bellard
                                    ASC_LOGICAL_BLOCK_OOR);
939 5391d806 bellard
                break;
940 5391d806 bellard
            }
941 5391d806 bellard
            ide_atapi_cmd_read(s, lba, nb_sectors);
942 5391d806 bellard
        }
943 5391d806 bellard
        break;
944 5391d806 bellard
    case GPCMD_SEEK:
945 5391d806 bellard
        {
946 5391d806 bellard
            int lba;
947 5391d806 bellard
            if (!s->bs) {
948 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
949 5391d806 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
950 5391d806 bellard
                break;
951 5391d806 bellard
            }
952 5391d806 bellard
            lba = ube32_to_cpu(packet + 2);
953 5391d806 bellard
            if (((int64_t)lba << 2) > s->nb_sectors) {
954 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
955 5391d806 bellard
                                    ASC_LOGICAL_BLOCK_OOR);
956 5391d806 bellard
                break;
957 5391d806 bellard
            }
958 5391d806 bellard
            ide_atapi_cmd_ok(s);
959 5391d806 bellard
        }
960 5391d806 bellard
        break;
961 5391d806 bellard
    case GPCMD_START_STOP_UNIT:
962 5391d806 bellard
        {
963 5391d806 bellard
            int start, eject;
964 5391d806 bellard
            start = packet[4] & 1;
965 5391d806 bellard
            eject = (packet[4] >> 1) & 1;
966 5391d806 bellard
            
967 5391d806 bellard
            /* XXX: currently none implemented */
968 5391d806 bellard
            ide_atapi_cmd_ok(s);
969 5391d806 bellard
        }
970 5391d806 bellard
        break;
971 5391d806 bellard
    case GPCMD_MECHANISM_STATUS:
972 5391d806 bellard
        {
973 5391d806 bellard
            max_len = ube16_to_cpu(packet + 8);
974 5391d806 bellard
            cpu_to_ube16(buf, 0);
975 5391d806 bellard
            /* no current LBA */
976 5391d806 bellard
            buf[2] = 0;
977 5391d806 bellard
            buf[3] = 0;
978 5391d806 bellard
            buf[4] = 0;
979 5391d806 bellard
            buf[5] = 1;
980 5391d806 bellard
            cpu_to_ube16(buf + 6, 0);
981 5391d806 bellard
            ide_atapi_cmd_reply(s, 8, max_len);
982 5391d806 bellard
        }
983 5391d806 bellard
        break;
984 5391d806 bellard
    case GPCMD_READ_TOC_PMA_ATIP:
985 5391d806 bellard
        {
986 5391d806 bellard
            int format, msf, start_track, len;
987 5391d806 bellard
988 5391d806 bellard
            if (!s->bs) {
989 5391d806 bellard
                ide_atapi_cmd_error(s, SENSE_NOT_READY, 
990 5391d806 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
991 5391d806 bellard
                break;
992 5391d806 bellard
            }
993 5391d806 bellard
            max_len = ube16_to_cpu(packet + 7);
994 5391d806 bellard
            format = packet[9] >> 6;
995 5391d806 bellard
            msf = (packet[1] >> 1) & 1;
996 5391d806 bellard
            start_track = packet[6];
997 5391d806 bellard
            switch(format) {
998 5391d806 bellard
            case 0:
999 5391d806 bellard
                len = cdrom_read_toc(s, buf, msf, start_track);
1000 5391d806 bellard
                if (len < 0)
1001 5391d806 bellard
                    goto error_cmd;
1002 5391d806 bellard
                ide_atapi_cmd_reply(s, len, max_len);
1003 5391d806 bellard
                break;
1004 5391d806 bellard
            case 1:
1005 5391d806 bellard
                /* multi session : only a single session defined */
1006 5391d806 bellard
                memset(buf, 0, 12);
1007 5391d806 bellard
                buf[1] = 0x0a;
1008 5391d806 bellard
                buf[2] = 0x01;
1009 5391d806 bellard
                buf[3] = 0x01;
1010 5391d806 bellard
                ide_atapi_cmd_reply(s, 12, max_len);
1011 5391d806 bellard
                break;
1012 5391d806 bellard
            default:
1013 7f777bf3 bellard
            error_cmd:
1014 7f777bf3 bellard
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
1015 7f777bf3 bellard
                                    ASC_INV_FIELD_IN_CMD_PACKET);
1016 7f777bf3 bellard
                break;
1017 5391d806 bellard
            }
1018 5391d806 bellard
        }
1019 5391d806 bellard
        break;
1020 5391d806 bellard
    case GPCMD_READ_CDVD_CAPACITY:
1021 5391d806 bellard
        if (!s->bs) {
1022 5391d806 bellard
            ide_atapi_cmd_error(s, SENSE_NOT_READY, 
1023 5391d806 bellard
                                ASC_MEDIUM_NOT_PRESENT);
1024 5391d806 bellard
            break;
1025 5391d806 bellard
        }
1026 5391d806 bellard
        /* NOTE: it is really the number of sectors minus 1 */
1027 5391d806 bellard
        cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1);
1028 5391d806 bellard
        cpu_to_ube32(buf + 4, 2048);
1029 5391d806 bellard
        ide_atapi_cmd_reply(s, 8, 8);
1030 5391d806 bellard
        break;
1031 bd0d90b2 bellard
    case GPCMD_INQUIRY:
1032 bd0d90b2 bellard
        max_len = packet[4];
1033 bd0d90b2 bellard
        buf[0] = 0x05; /* CD-ROM */
1034 bd0d90b2 bellard
        buf[1] = 0x80; /* removable */
1035 bd0d90b2 bellard
        buf[2] = 0x00; /* ISO */
1036 bd0d90b2 bellard
        buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
1037 bd0d90b2 bellard
        buf[4] = 31; /* additionnal length */
1038 bd0d90b2 bellard
        buf[5] = 0; /* reserved */
1039 bd0d90b2 bellard
        buf[6] = 0; /* reserved */
1040 bd0d90b2 bellard
        buf[7] = 0; /* reserved */
1041 bd0d90b2 bellard
        padstr8(buf + 8, 8, "QEMU");
1042 bd0d90b2 bellard
        padstr8(buf + 16, 16, "QEMU CD-ROM");
1043 bd0d90b2 bellard
        padstr8(buf + 32, 4, QEMU_VERSION);
1044 bd0d90b2 bellard
        ide_atapi_cmd_reply(s, 36, max_len);
1045 bd0d90b2 bellard
        break;
1046 5391d806 bellard
    default:
1047 5391d806 bellard
        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, 
1048 7f777bf3 bellard
                            ASC_ILLEGAL_OPCODE);
1049 5391d806 bellard
        break;
1050 5391d806 bellard
    }
1051 5391d806 bellard
}
1052 5391d806 bellard
1053 7138fcfb bellard
static void ide_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
1054 5391d806 bellard
{
1055 5391d806 bellard
    IDEState *ide_if = get_ide_interface(addr);
1056 5391d806 bellard
    IDEState *s = ide_if->cur_drive;
1057 5391d806 bellard
    int unit, n;
1058 5391d806 bellard
1059 5391d806 bellard
#ifdef DEBUG_IDE
1060 5391d806 bellard
    printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
1061 5391d806 bellard
#endif
1062 5391d806 bellard
    addr &= 7;
1063 5391d806 bellard
    switch(addr) {
1064 5391d806 bellard
    case 0:
1065 5391d806 bellard
        break;
1066 5391d806 bellard
    case 1:
1067 5391d806 bellard
        s->feature = val;
1068 5391d806 bellard
        break;
1069 5391d806 bellard
    case 2:
1070 5391d806 bellard
        if (val == 0)
1071 5391d806 bellard
            val = 256;
1072 5391d806 bellard
        s->nsector = val;
1073 5391d806 bellard
        break;
1074 5391d806 bellard
    case 3:
1075 5391d806 bellard
        s->sector = val;
1076 5391d806 bellard
        break;
1077 5391d806 bellard
    case 4:
1078 5391d806 bellard
        s->lcyl = val;
1079 5391d806 bellard
        break;
1080 5391d806 bellard
    case 5:
1081 5391d806 bellard
        s->hcyl = val;
1082 5391d806 bellard
        break;
1083 5391d806 bellard
    case 6:
1084 5391d806 bellard
        /* select drive */
1085 5391d806 bellard
        unit = (val >> 4) & 1;
1086 5391d806 bellard
        s = ide_if + unit;
1087 5391d806 bellard
        ide_if->cur_drive = s;
1088 5391d806 bellard
        s->select = val;
1089 5391d806 bellard
        break;
1090 5391d806 bellard
    default:
1091 5391d806 bellard
    case 7:
1092 5391d806 bellard
        /* command */
1093 5391d806 bellard
#if defined(DEBUG_IDE)
1094 5391d806 bellard
        printf("ide: CMD=%02x\n", val);
1095 5391d806 bellard
#endif
1096 5391d806 bellard
        switch(val) {
1097 5391d806 bellard
        case WIN_IDENTIFY:
1098 5391d806 bellard
            if (s->bs && !s->is_cdrom) {
1099 5391d806 bellard
                ide_identify(s);
1100 5391d806 bellard
                s->status = READY_STAT;
1101 5391d806 bellard
                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1102 5391d806 bellard
            } else {
1103 5391d806 bellard
                if (s->is_cdrom) {
1104 5391d806 bellard
                    ide_set_signature(s);
1105 5391d806 bellard
                }
1106 5391d806 bellard
                ide_abort_command(s);
1107 5391d806 bellard
            }
1108 5391d806 bellard
            ide_set_irq(s);
1109 5391d806 bellard
            break;
1110 5391d806 bellard
        case WIN_SPECIFY:
1111 5391d806 bellard
        case WIN_RECAL:
1112 a136e5a8 bellard
            s->error = 0;
1113 5391d806 bellard
            s->status = READY_STAT;
1114 5391d806 bellard
            ide_set_irq(s);
1115 5391d806 bellard
            break;
1116 5391d806 bellard
        case WIN_SETMULT:
1117 5391d806 bellard
            if (s->nsector > MAX_MULT_SECTORS || 
1118 5391d806 bellard
                s->nsector == 0 ||
1119 5391d806 bellard
                (s->nsector & (s->nsector - 1)) != 0) {
1120 5391d806 bellard
                ide_abort_command(s);
1121 5391d806 bellard
            } else {
1122 5391d806 bellard
                s->mult_sectors = s->nsector;
1123 5391d806 bellard
                s->status = READY_STAT;
1124 5391d806 bellard
            }
1125 5391d806 bellard
            ide_set_irq(s);
1126 5391d806 bellard
            break;
1127 4ce900b4 bellard
        case WIN_VERIFY:
1128 4ce900b4 bellard
        case WIN_VERIFY_ONCE:
1129 4ce900b4 bellard
            /* do sector number check ? */
1130 4ce900b4 bellard
            s->status = READY_STAT;
1131 4ce900b4 bellard
            ide_set_irq(s);
1132 4ce900b4 bellard
            break;
1133 5391d806 bellard
        case WIN_READ:
1134 5391d806 bellard
        case WIN_READ_ONCE:
1135 6b136f9e bellard
            if (!s->bs) 
1136 6b136f9e bellard
                goto abort_cmd;
1137 5391d806 bellard
            s->req_nb_sectors = 1;
1138 5391d806 bellard
            ide_sector_read(s);
1139 5391d806 bellard
            break;
1140 5391d806 bellard
        case WIN_WRITE:
1141 5391d806 bellard
        case WIN_WRITE_ONCE:
1142 a136e5a8 bellard
            s->error = 0;
1143 5391d806 bellard
            s->status = SEEK_STAT;
1144 5391d806 bellard
            s->req_nb_sectors = 1;
1145 5391d806 bellard
            ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
1146 5391d806 bellard
            break;
1147 5391d806 bellard
        case WIN_MULTREAD:
1148 5391d806 bellard
            if (!s->mult_sectors)
1149 5391d806 bellard
                goto abort_cmd;
1150 5391d806 bellard
            s->req_nb_sectors = s->mult_sectors;
1151 5391d806 bellard
            ide_sector_read(s);
1152 5391d806 bellard
            break;
1153 5391d806 bellard
        case WIN_MULTWRITE:
1154 5391d806 bellard
            if (!s->mult_sectors)
1155 5391d806 bellard
                goto abort_cmd;
1156 a136e5a8 bellard
            s->error = 0;
1157 5391d806 bellard
            s->status = SEEK_STAT;
1158 5391d806 bellard
            s->req_nb_sectors = s->mult_sectors;
1159 5391d806 bellard
            n = s->nsector;
1160 5391d806 bellard
            if (n > s->req_nb_sectors)
1161 5391d806 bellard
                n = s->req_nb_sectors;
1162 5391d806 bellard
            ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
1163 5391d806 bellard
            break;
1164 5391d806 bellard
        case WIN_READ_NATIVE_MAX:
1165 5391d806 bellard
            ide_set_sector(s, s->nb_sectors - 1);
1166 5391d806 bellard
            s->status = READY_STAT;
1167 5391d806 bellard
            ide_set_irq(s);
1168 5391d806 bellard
            break;
1169 a136e5a8 bellard
        case WIN_CHECKPOWERMODE1:
1170 a136e5a8 bellard
            s->nsector = 0xff; /* device active or idle */
1171 a136e5a8 bellard
            s->status = READY_STAT;
1172 a136e5a8 bellard
            ide_set_irq(s);
1173 a136e5a8 bellard
            break;
1174 5391d806 bellard
1175 5391d806 bellard
            /* ATAPI commands */
1176 5391d806 bellard
        case WIN_PIDENTIFY:
1177 5391d806 bellard
            if (s->is_cdrom) {
1178 5391d806 bellard
                ide_atapi_identify(s);
1179 5391d806 bellard
                s->status = READY_STAT;
1180 5391d806 bellard
                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1181 5391d806 bellard
            } else {
1182 5391d806 bellard
                ide_abort_command(s);
1183 5391d806 bellard
            }
1184 5391d806 bellard
            ide_set_irq(s);
1185 5391d806 bellard
            break;
1186 5391d806 bellard
        case WIN_SRST:
1187 5391d806 bellard
            if (!s->is_cdrom)
1188 5391d806 bellard
                goto abort_cmd;
1189 5391d806 bellard
            ide_set_signature(s);
1190 6b136f9e bellard
            s->status = 0x00; /* NOTE: READY is _not_ set */
1191 5391d806 bellard
            s->error = 0x01;
1192 5391d806 bellard
            break;
1193 5391d806 bellard
        case WIN_PACKETCMD:
1194 5391d806 bellard
            if (!s->is_cdrom)
1195 5391d806 bellard
                goto abort_cmd;
1196 5391d806 bellard
            /* DMA or overlapping commands not supported */
1197 5391d806 bellard
            if ((s->feature & 0x03) != 0)
1198 5391d806 bellard
                goto abort_cmd;
1199 5391d806 bellard
            s->nsector = 1;
1200 5391d806 bellard
            ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, 
1201 5391d806 bellard
                               ide_atapi_cmd);
1202 5391d806 bellard
            break;
1203 5391d806 bellard
        default:
1204 5391d806 bellard
        abort_cmd:
1205 5391d806 bellard
            ide_abort_command(s);
1206 5391d806 bellard
            ide_set_irq(s);
1207 5391d806 bellard
            break;
1208 5391d806 bellard
        }
1209 5391d806 bellard
    }
1210 5391d806 bellard
}
1211 5391d806 bellard
1212 7138fcfb bellard
static uint32_t ide_ioport_read(CPUState *env, uint32_t addr1)
1213 5391d806 bellard
{
1214 5391d806 bellard
    IDEState *s = get_ide_interface(addr1)->cur_drive;
1215 5391d806 bellard
    uint32_t addr;
1216 5391d806 bellard
    int ret;
1217 5391d806 bellard
1218 5391d806 bellard
    addr = addr1 & 7;
1219 5391d806 bellard
    switch(addr) {
1220 5391d806 bellard
    case 0:
1221 5391d806 bellard
        ret = 0xff;
1222 5391d806 bellard
        break;
1223 5391d806 bellard
    case 1:
1224 5391d806 bellard
        ret = s->error;
1225 5391d806 bellard
        break;
1226 5391d806 bellard
    case 2:
1227 5391d806 bellard
        ret = s->nsector & 0xff;
1228 5391d806 bellard
        break;
1229 5391d806 bellard
    case 3:
1230 5391d806 bellard
        ret = s->sector;
1231 5391d806 bellard
        break;
1232 5391d806 bellard
    case 4:
1233 5391d806 bellard
        ret = s->lcyl;
1234 5391d806 bellard
        break;
1235 5391d806 bellard
    case 5:
1236 5391d806 bellard
        ret = s->hcyl;
1237 5391d806 bellard
        break;
1238 5391d806 bellard
    case 6:
1239 5391d806 bellard
        ret = s->select;
1240 5391d806 bellard
        break;
1241 5391d806 bellard
    default:
1242 5391d806 bellard
    case 7:
1243 5391d806 bellard
        ret = s->status;
1244 5391d806 bellard
        pic_set_irq(s->irq, 0);
1245 5391d806 bellard
        break;
1246 5391d806 bellard
    }
1247 5391d806 bellard
#ifdef DEBUG_IDE
1248 5391d806 bellard
    printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
1249 5391d806 bellard
#endif
1250 5391d806 bellard
    return ret;
1251 5391d806 bellard
}
1252 5391d806 bellard
1253 7138fcfb bellard
static uint32_t ide_status_read(CPUState *env, uint32_t addr)
1254 5391d806 bellard
{
1255 5391d806 bellard
    IDEState *s = get_ide_interface(addr)->cur_drive;
1256 5391d806 bellard
    int ret;
1257 5391d806 bellard
    ret = s->status;
1258 5391d806 bellard
#ifdef DEBUG_IDE
1259 5391d806 bellard
    printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
1260 5391d806 bellard
#endif
1261 5391d806 bellard
    return ret;
1262 5391d806 bellard
}
1263 5391d806 bellard
1264 7138fcfb bellard
static void ide_cmd_write(CPUState *env, uint32_t addr, uint32_t val)
1265 5391d806 bellard
{
1266 5391d806 bellard
    IDEState *ide_if = get_ide_interface(addr);
1267 5391d806 bellard
    IDEState *s;
1268 5391d806 bellard
    int i;
1269 5391d806 bellard
1270 5391d806 bellard
#ifdef DEBUG_IDE
1271 5391d806 bellard
    printf("ide: write control addr=0x%x val=%02x\n", addr, val);
1272 5391d806 bellard
#endif
1273 5391d806 bellard
    /* common for both drives */
1274 5391d806 bellard
    if (!(ide_if[0].cmd & IDE_CMD_RESET) &&
1275 5391d806 bellard
        (val & IDE_CMD_RESET)) {
1276 5391d806 bellard
        /* reset low to high */
1277 5391d806 bellard
        for(i = 0;i < 2; i++) {
1278 5391d806 bellard
            s = &ide_if[i];
1279 5391d806 bellard
            s->status = BUSY_STAT | SEEK_STAT;
1280 5391d806 bellard
            s->error = 0x01;
1281 5391d806 bellard
        }
1282 5391d806 bellard
    } else if ((ide_if[0].cmd & IDE_CMD_RESET) &&
1283 5391d806 bellard
               !(val & IDE_CMD_RESET)) {
1284 5391d806 bellard
        /* high to low */
1285 5391d806 bellard
        for(i = 0;i < 2; i++) {
1286 5391d806 bellard
            s = &ide_if[i];
1287 6b136f9e bellard
            if (s->is_cdrom)
1288 6b136f9e bellard
                s->status = 0x00; /* NOTE: READY is _not_ set */
1289 6b136f9e bellard
            else
1290 56bf1d37 bellard
                s->status = READY_STAT | SEEK_STAT;
1291 5391d806 bellard
            ide_set_signature(s);
1292 5391d806 bellard
        }
1293 5391d806 bellard
    }
1294 5391d806 bellard
1295 5391d806 bellard
    ide_if[0].cmd = val;
1296 5391d806 bellard
    ide_if[1].cmd = val;
1297 5391d806 bellard
}
1298 5391d806 bellard
1299 7138fcfb bellard
static void ide_data_writew(CPUState *env, uint32_t addr, uint32_t val)
1300 5391d806 bellard
{
1301 5391d806 bellard
    IDEState *s = get_ide_interface(addr)->cur_drive;
1302 5391d806 bellard
    uint8_t *p;
1303 5391d806 bellard
1304 5391d806 bellard
    p = s->data_ptr;
1305 5391d806 bellard
    *(uint16_t *)p = tswap16(val);
1306 5391d806 bellard
    p += 2;
1307 5391d806 bellard
    s->data_ptr = p;
1308 5391d806 bellard
    if (p >= s->data_end)
1309 5391d806 bellard
        s->end_transfer_func(s);
1310 5391d806 bellard
}
1311 5391d806 bellard
1312 7138fcfb bellard
static uint32_t ide_data_readw(CPUState *env, uint32_t addr)
1313 5391d806 bellard
{
1314 5391d806 bellard
    IDEState *s = get_ide_interface(addr)->cur_drive;
1315 5391d806 bellard
    uint8_t *p;
1316 5391d806 bellard
    int ret;
1317 5391d806 bellard
    p = s->data_ptr;
1318 5391d806 bellard
    ret = tswap16(*(uint16_t *)p);
1319 5391d806 bellard
    p += 2;
1320 5391d806 bellard
    s->data_ptr = p;
1321 5391d806 bellard
    if (p >= s->data_end)
1322 5391d806 bellard
        s->end_transfer_func(s);
1323 5391d806 bellard
    return ret;
1324 5391d806 bellard
}
1325 5391d806 bellard
1326 7138fcfb bellard
static void ide_data_writel(CPUState *env, uint32_t addr, uint32_t val)
1327 5391d806 bellard
{
1328 5391d806 bellard
    IDEState *s = get_ide_interface(addr)->cur_drive;
1329 5391d806 bellard
    uint8_t *p;
1330 5391d806 bellard
1331 5391d806 bellard
    p = s->data_ptr;
1332 5391d806 bellard
    *(uint32_t *)p = tswap32(val);
1333 5391d806 bellard
    p += 4;
1334 5391d806 bellard
    s->data_ptr = p;
1335 5391d806 bellard
    if (p >= s->data_end)
1336 5391d806 bellard
        s->end_transfer_func(s);
1337 5391d806 bellard
}
1338 5391d806 bellard
1339 7138fcfb bellard
static uint32_t ide_data_readl(CPUState *env, uint32_t addr)
1340 5391d806 bellard
{
1341 5391d806 bellard
    IDEState *s = get_ide_interface(addr)->cur_drive;
1342 5391d806 bellard
    uint8_t *p;
1343 5391d806 bellard
    int ret;
1344 5391d806 bellard
    
1345 5391d806 bellard
    p = s->data_ptr;
1346 5391d806 bellard
    ret = tswap32(*(uint32_t *)p);
1347 5391d806 bellard
    p += 4;
1348 5391d806 bellard
    s->data_ptr = p;
1349 5391d806 bellard
    if (p >= s->data_end)
1350 5391d806 bellard
        s->end_transfer_func(s);
1351 5391d806 bellard
    return ret;
1352 5391d806 bellard
}
1353 5391d806 bellard
1354 5391d806 bellard
static void ide_reset(IDEState *s)
1355 5391d806 bellard
{
1356 5391d806 bellard
    s->mult_sectors = MAX_MULT_SECTORS;
1357 5391d806 bellard
    s->cur_drive = s;
1358 5391d806 bellard
    s->select = 0xa0;
1359 5391d806 bellard
    s->status = READY_STAT;
1360 5391d806 bellard
    ide_set_signature(s);
1361 5391d806 bellard
}
1362 5391d806 bellard
1363 5391d806 bellard
struct partition {
1364 5391d806 bellard
        uint8_t boot_ind;                /* 0x80 - active */
1365 5391d806 bellard
        uint8_t head;                /* starting head */
1366 5391d806 bellard
        uint8_t sector;                /* starting sector */
1367 5391d806 bellard
        uint8_t cyl;                /* starting cylinder */
1368 5391d806 bellard
        uint8_t sys_ind;                /* What partition type */
1369 5391d806 bellard
        uint8_t end_head;                /* end head */
1370 5391d806 bellard
        uint8_t end_sector;        /* end sector */
1371 5391d806 bellard
        uint8_t end_cyl;                /* end cylinder */
1372 5391d806 bellard
        uint32_t start_sect;        /* starting sector counting from 0 */
1373 5391d806 bellard
        uint32_t nr_sects;                /* nr of sectors in partition */
1374 5391d806 bellard
} __attribute__((packed));
1375 5391d806 bellard
1376 5391d806 bellard
/* try to guess the IDE geometry from the MSDOS partition table */
1377 5391d806 bellard
static void ide_guess_geometry(IDEState *s)
1378 5391d806 bellard
{
1379 5391d806 bellard
    uint8_t buf[512];
1380 5391d806 bellard
    int ret, i;
1381 5391d806 bellard
    struct partition *p;
1382 5391d806 bellard
    uint32_t nr_sects;
1383 5391d806 bellard
1384 5391d806 bellard
    if (s->cylinders != 0)
1385 5391d806 bellard
        return;
1386 5391d806 bellard
    ret = bdrv_read(s->bs, 0, buf, 1);
1387 5391d806 bellard
    if (ret < 0)
1388 5391d806 bellard
        return;
1389 5391d806 bellard
    /* test msdos magic */
1390 5391d806 bellard
    if (buf[510] != 0x55 || buf[511] != 0xaa)
1391 5391d806 bellard
        return;
1392 5391d806 bellard
    for(i = 0; i < 4; i++) {
1393 5391d806 bellard
        p = ((struct partition *)(buf + 0x1be)) + i;
1394 5391d806 bellard
        nr_sects = tswap32(p->nr_sects);
1395 5391d806 bellard
        if (nr_sects && p->end_head) {
1396 5391d806 bellard
            /* We make the assumption that the partition terminates on
1397 5391d806 bellard
               a cylinder boundary */
1398 5391d806 bellard
            s->heads = p->end_head + 1;
1399 5391d806 bellard
            s->sectors = p->end_sector & 63;
1400 5391d806 bellard
            s->cylinders = s->nb_sectors / (s->heads * s->sectors);
1401 5391d806 bellard
#if 0
1402 5391d806 bellard
            printf("guessed partition: CHS=%d %d %d\n", 
1403 5391d806 bellard
                   s->cylinders, s->heads, s->sectors);
1404 5391d806 bellard
#endif
1405 5391d806 bellard
        }
1406 5391d806 bellard
    }
1407 5391d806 bellard
}
1408 5391d806 bellard
1409 5391d806 bellard
void ide_init(void)
1410 5391d806 bellard
{
1411 5391d806 bellard
    IDEState *s;
1412 5391d806 bellard
    int i, cylinders, iobase, iobase2;
1413 5391d806 bellard
    int64_t nb_sectors;
1414 5391d806 bellard
    static const int ide_iobase[2] = { 0x1f0, 0x170 };
1415 5391d806 bellard
    static const int ide_iobase2[2] = { 0x3f6, 0x376 };
1416 5391d806 bellard
    static const int ide_irq[2] = { 14, 15 };
1417 5391d806 bellard
1418 5391d806 bellard
    for(i = 0; i < MAX_DISKS; i++) {
1419 5391d806 bellard
        s = &ide_state[i];
1420 5391d806 bellard
        s->bs = bs_table[i];
1421 5391d806 bellard
        if (s->bs) {
1422 5391d806 bellard
            bdrv_get_geometry(s->bs, &nb_sectors);
1423 5391d806 bellard
            s->nb_sectors = nb_sectors;
1424 5391d806 bellard
            ide_guess_geometry(s);
1425 5391d806 bellard
            if (s->cylinders == 0) {
1426 5391d806 bellard
                /* if no geometry, use a LBA compatible one */
1427 5391d806 bellard
                cylinders = nb_sectors / (16 * 63);
1428 5391d806 bellard
                if (cylinders > 16383)
1429 5391d806 bellard
                    cylinders = 16383;
1430 5391d806 bellard
                else if (cylinders < 2)
1431 5391d806 bellard
                    cylinders = 2;
1432 5391d806 bellard
                s->cylinders = cylinders;
1433 5391d806 bellard
                s->heads = 16;
1434 5391d806 bellard
                s->sectors = 63;
1435 5391d806 bellard
            }
1436 5391d806 bellard
        }
1437 5391d806 bellard
        s->irq = ide_irq[i >> 1];
1438 5391d806 bellard
        ide_reset(s);
1439 5391d806 bellard
    }
1440 5391d806 bellard
    for(i = 0; i < (MAX_DISKS / 2); i++) {
1441 5391d806 bellard
        iobase = ide_iobase[i];
1442 5391d806 bellard
        iobase2 = ide_iobase2[i];
1443 5391d806 bellard
        ide_table[iobase >> 3] = &ide_state[2 * i];
1444 5391d806 bellard
        if (ide_iobase2[i]) 
1445 5391d806 bellard
            ide_table[iobase2 >> 3] = &ide_state[2 * i];
1446 5391d806 bellard
        register_ioport_write(iobase, 8, ide_ioport_write, 1);
1447 5391d806 bellard
        register_ioport_read(iobase, 8, ide_ioport_read, 1);
1448 5391d806 bellard
        register_ioport_read(iobase2, 1, ide_status_read, 1);
1449 5391d806 bellard
        register_ioport_write(iobase2, 1, ide_cmd_write, 1);
1450 5391d806 bellard
        
1451 5391d806 bellard
        /* data ports */
1452 5391d806 bellard
        register_ioport_write(iobase, 2, ide_data_writew, 2);
1453 5391d806 bellard
        register_ioport_read(iobase, 2, ide_data_readw, 2);
1454 5391d806 bellard
        register_ioport_write(iobase, 4, ide_data_writel, 4);
1455 5391d806 bellard
        register_ioport_read(iobase, 4, ide_data_readl, 4);
1456 5391d806 bellard
    }
1457 5391d806 bellard
}
1458 5391d806 bellard
1459 5391d806 bellard
void ide_set_geometry(int n, int cyls, int heads, int secs)
1460 5391d806 bellard
{
1461 5391d806 bellard
    ide_state[n].cylinders = cyls;
1462 5391d806 bellard
    ide_state[n].heads = heads;
1463 5391d806 bellard
    ide_state[n].sectors = secs;
1464 5391d806 bellard
}
1465 5391d806 bellard
1466 5391d806 bellard
void ide_set_cdrom(int n, int is_cdrom)
1467 5391d806 bellard
{
1468 5391d806 bellard
    ide_state[n].is_cdrom = is_cdrom;
1469 5391d806 bellard
}