Statistics
| Branch: | Revision:

root / hw / ide / core.c @ 3b2e3dc9

History | View | Annotate | Download (89.4 kB)

1 5391d806 bellard
/*
2 38cdea7c balrog
 * QEMU IDE disk and CD/DVD-ROM Emulator
3 5fafdf24 ths
 *
4 5391d806 bellard
 * Copyright (c) 2003 Fabrice Bellard
5 201a51fc balrog
 * Copyright (c) 2006 Openedhand Ltd.
6 5fafdf24 ths
 *
7 5391d806 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 5391d806 bellard
 * of this software and associated documentation files (the "Software"), to deal
9 5391d806 bellard
 * in the Software without restriction, including without limitation the rights
10 5391d806 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 5391d806 bellard
 * copies of the Software, and to permit persons to whom the Software is
12 5391d806 bellard
 * furnished to do so, subject to the following conditions:
13 5391d806 bellard
 *
14 5391d806 bellard
 * The above copyright notice and this permission notice shall be included in
15 5391d806 bellard
 * all copies or substantial portions of the Software.
16 5391d806 bellard
 *
17 5391d806 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 5391d806 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 5391d806 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 5391d806 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 5391d806 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 5391d806 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 5391d806 bellard
 * THE SOFTWARE.
24 5391d806 bellard
 */
25 59f2a787 Gerd Hoffmann
#include <hw/hw.h>
26 59f2a787 Gerd Hoffmann
#include <hw/pc.h>
27 59f2a787 Gerd Hoffmann
#include <hw/pci.h>
28 43b443b6 Gerd Hoffmann
#include <hw/scsi.h>
29 c4d74df7 Markus Armbruster
#include "qemu-error.h"
30 87ecb68b pbrook
#include "qemu-timer.h"
31 87ecb68b pbrook
#include "sysemu.h"
32 1fb8648d aliguori
#include "dma.h"
33 2446333c Blue Swirl
#include "blockdev.h"
34 59f2a787 Gerd Hoffmann
35 59f2a787 Gerd Hoffmann
#include <hw/ide/internal.h>
36 e8b54394 Brian Wheeler
37 6450a334 Blue Swirl
#define IDE_PAGE_SIZE 4096
38 6450a334 Blue Swirl
39 117e1e82 Blue Swirl
static const int smart_attributes[][5] = {
40 e8b54394 Brian Wheeler
    /* id,  flags, val, wrst, thrsh */
41 e8b54394 Brian Wheeler
    { 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
42 e8b54394 Brian Wheeler
    { 0x03, 0x03, 0x64, 0x64, 0x46}, /* spin up */
43 e8b54394 Brian Wheeler
    { 0x04, 0x02, 0x64, 0x64, 0x14}, /* start stop count */
44 e8b54394 Brian Wheeler
    { 0x05, 0x03, 0x64, 0x64, 0x36}, /* remapped sectors */
45 e8b54394 Brian Wheeler
    { 0x00, 0x00, 0x00, 0x00, 0x00}
46 e8b54394 Brian Wheeler
};
47 e8b54394 Brian Wheeler
48 8114e9e8 ths
/* XXX: DVDs that could fit on a CD will be reported as a CD */
49 8114e9e8 ths
static inline int media_present(IDEState *s)
50 8114e9e8 ths
{
51 8114e9e8 ths
    return (s->nb_sectors > 0);
52 8114e9e8 ths
}
53 8114e9e8 ths
54 8114e9e8 ths
static inline int media_is_dvd(IDEState *s)
55 8114e9e8 ths
{
56 8114e9e8 ths
    return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS);
57 8114e9e8 ths
}
58 8114e9e8 ths
59 8114e9e8 ths
static inline int media_is_cd(IDEState *s)
60 8114e9e8 ths
{
61 8114e9e8 ths
    return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS);
62 8114e9e8 ths
}
63 8114e9e8 ths
64 8ccad811 bellard
static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
65 ce4b6522 Kevin Wolf
static void ide_dma_restart(IDEState *s, int is_read);
66 5f12ab4b ths
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
67 ce4b6522 Kevin Wolf
static int ide_handle_rw_error(IDEState *s, int error, int op);
68 98087450 bellard
69 5391d806 bellard
static void padstr(char *str, const char *src, int len)
70 5391d806 bellard
{
71 5391d806 bellard
    int i, v;
72 5391d806 bellard
    for(i = 0; i < len; i++) {
73 5391d806 bellard
        if (*src)
74 5391d806 bellard
            v = *src++;
75 5391d806 bellard
        else
76 5391d806 bellard
            v = ' ';
77 69b34976 ths
        str[i^1] = v;
78 5391d806 bellard
    }
79 5391d806 bellard
}
80 5391d806 bellard
81 bd0d90b2 bellard
static void padstr8(uint8_t *buf, int buf_size, const char *src)
82 bd0d90b2 bellard
{
83 bd0d90b2 bellard
    int i;
84 bd0d90b2 bellard
    for(i = 0; i < buf_size; i++) {
85 bd0d90b2 bellard
        if (*src)
86 bd0d90b2 bellard
            buf[i] = *src++;
87 bd0d90b2 bellard
        else
88 bd0d90b2 bellard
            buf[i] = ' ';
89 bd0d90b2 bellard
    }
90 bd0d90b2 bellard
}
91 bd0d90b2 bellard
92 67b915a5 bellard
static void put_le16(uint16_t *p, unsigned int v)
93 67b915a5 bellard
{
94 0c4ad8dc bellard
    *p = cpu_to_le16(v);
95 67b915a5 bellard
}
96 67b915a5 bellard
97 5391d806 bellard
static void ide_identify(IDEState *s)
98 5391d806 bellard
{
99 5391d806 bellard
    uint16_t *p;
100 5391d806 bellard
    unsigned int oldsize;
101 57dac7ef Markus Armbruster
    IDEDevice *dev;
102 5391d806 bellard
103 94458802 bellard
    if (s->identify_set) {
104 94458802 bellard
        memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
105 94458802 bellard
        return;
106 94458802 bellard
    }
107 94458802 bellard
108 5391d806 bellard
    memset(s->io_buffer, 0, 512);
109 5391d806 bellard
    p = (uint16_t *)s->io_buffer;
110 67b915a5 bellard
    put_le16(p + 0, 0x0040);
111 5fafdf24 ths
    put_le16(p + 1, s->cylinders);
112 67b915a5 bellard
    put_le16(p + 3, s->heads);
113 67b915a5 bellard
    put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
114 67b915a5 bellard
    put_le16(p + 5, 512); /* XXX: retired, remove ? */
115 5fafdf24 ths
    put_le16(p + 6, s->sectors);
116 fa879c64 aliguori
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
117 67b915a5 bellard
    put_le16(p + 20, 3); /* XXX: retired, remove ? */
118 67b915a5 bellard
    put_le16(p + 21, 512); /* cache size in sectors */
119 67b915a5 bellard
    put_le16(p + 22, 4); /* ecc bytes */
120 47c06340 Gerd Hoffmann
    padstr((char *)(p + 23), s->version, 8); /* firmware version */
121 60fe76f3 ths
    padstr((char *)(p + 27), "QEMU HARDDISK", 40); /* model */
122 3b46e624 ths
#if MAX_MULT_SECTORS > 1
123 67b915a5 bellard
    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
124 5391d806 bellard
#endif
125 67b915a5 bellard
    put_le16(p + 48, 1); /* dword I/O */
126 94458802 bellard
    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
127 67b915a5 bellard
    put_le16(p + 51, 0x200); /* PIO transfer cycle */
128 67b915a5 bellard
    put_le16(p + 52, 0x200); /* DMA transfer cycle */
129 94458802 bellard
    put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */
130 67b915a5 bellard
    put_le16(p + 54, s->cylinders);
131 67b915a5 bellard
    put_le16(p + 55, s->heads);
132 67b915a5 bellard
    put_le16(p + 56, s->sectors);
133 5391d806 bellard
    oldsize = s->cylinders * s->heads * s->sectors;
134 67b915a5 bellard
    put_le16(p + 57, oldsize);
135 67b915a5 bellard
    put_le16(p + 58, oldsize >> 16);
136 5391d806 bellard
    if (s->mult_sectors)
137 67b915a5 bellard
        put_le16(p + 59, 0x100 | s->mult_sectors);
138 67b915a5 bellard
    put_le16(p + 60, s->nb_sectors);
139 67b915a5 bellard
    put_le16(p + 61, s->nb_sectors >> 16);
140 d1b5c20d ths
    put_le16(p + 62, 0x07); /* single word dma0-2 supported */
141 94458802 bellard
    put_le16(p + 63, 0x07); /* mdma0-2 supported */
142 79d1d331 Jonathan A. Kollasch
    put_le16(p + 64, 0x03); /* pio3-4 supported */
143 94458802 bellard
    put_le16(p + 65, 120);
144 94458802 bellard
    put_le16(p + 66, 120);
145 94458802 bellard
    put_le16(p + 67, 120);
146 94458802 bellard
    put_le16(p + 68, 120);
147 94458802 bellard
    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
148 94458802 bellard
    put_le16(p + 81, 0x16); /* conforms to ata5 */
149 e8b54394 Brian Wheeler
    /* 14=NOP supported, 0=SMART supported */
150 e8b54394 Brian Wheeler
    put_le16(p + 82, (1 << 14) | 1);
151 c2ff060f bellard
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
152 c2ff060f bellard
    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
153 e8b54394 Brian Wheeler
    /* 14=set to 1, 1=SMART self test, 0=SMART error logging */
154 e8b54394 Brian Wheeler
    put_le16(p + 84, (1 << 14) | 0);
155 e900a7b7 Christoph Hellwig
    /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */
156 e900a7b7 Christoph Hellwig
    if (bdrv_enable_write_cache(s->bs))
157 e900a7b7 Christoph Hellwig
         put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
158 e900a7b7 Christoph Hellwig
    else
159 e900a7b7 Christoph Hellwig
         put_le16(p + 85, (1 << 14) | 1);
160 c2ff060f bellard
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
161 c2ff060f bellard
    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
162 e8b54394 Brian Wheeler
    /* 14=set to 1, 1=smart self test, 0=smart error logging */
163 e8b54394 Brian Wheeler
    put_le16(p + 87, (1 << 14) | 0);
164 94458802 bellard
    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
165 94458802 bellard
    put_le16(p + 93, 1 | (1 << 14) | 0x2000);
166 c2ff060f bellard
    put_le16(p + 100, s->nb_sectors);
167 c2ff060f bellard
    put_le16(p + 101, s->nb_sectors >> 16);
168 c2ff060f bellard
    put_le16(p + 102, s->nb_sectors >> 32);
169 c2ff060f bellard
    put_le16(p + 103, s->nb_sectors >> 48);
170 57dac7ef Markus Armbruster
    dev = s->unit ? s->bus->slave : s->bus->master;
171 57dac7ef Markus Armbruster
    if (dev && dev->conf.physical_block_size)
172 57dac7ef Markus Armbruster
        put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
173 94458802 bellard
174 94458802 bellard
    memcpy(s->identify_data, p, sizeof(s->identify_data));
175 94458802 bellard
    s->identify_set = 1;
176 5391d806 bellard
}
177 5391d806 bellard
178 5391d806 bellard
static void ide_atapi_identify(IDEState *s)
179 5391d806 bellard
{
180 5391d806 bellard
    uint16_t *p;
181 5391d806 bellard
182 94458802 bellard
    if (s->identify_set) {
183 94458802 bellard
        memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
184 94458802 bellard
        return;
185 94458802 bellard
    }
186 94458802 bellard
187 5391d806 bellard
    memset(s->io_buffer, 0, 512);
188 5391d806 bellard
    p = (uint16_t *)s->io_buffer;
189 5391d806 bellard
    /* Removable CDROM, 50us response, 12 byte packets */
190 67b915a5 bellard
    put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
191 fa879c64 aliguori
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
192 67b915a5 bellard
    put_le16(p + 20, 3); /* buffer type */
193 67b915a5 bellard
    put_le16(p + 21, 512); /* cache size in sectors */
194 67b915a5 bellard
    put_le16(p + 22, 4); /* ecc bytes */
195 47c06340 Gerd Hoffmann
    padstr((char *)(p + 23), s->version, 8); /* firmware version */
196 38cdea7c balrog
    padstr((char *)(p + 27), "QEMU DVD-ROM", 40); /* model */
197 67b915a5 bellard
    put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
198 8ccad811 bellard
#ifdef USE_DMA_CDROM
199 8ccad811 bellard
    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
200 8ccad811 bellard
    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
201 d1b5c20d ths
    put_le16(p + 62, 7);  /* single word dma0-2 supported */
202 8ccad811 bellard
    put_le16(p + 63, 7);  /* mdma0-2 supported */
203 8ccad811 bellard
#else
204 67b915a5 bellard
    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
205 67b915a5 bellard
    put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
206 67b915a5 bellard
    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
207 8ccad811 bellard
#endif
208 79d1d331 Jonathan A. Kollasch
    put_le16(p + 64, 3); /* pio3-4 supported */
209 67b915a5 bellard
    put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
210 67b915a5 bellard
    put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
211 67b915a5 bellard
    put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
212 67b915a5 bellard
    put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
213 94458802 bellard
214 67b915a5 bellard
    put_le16(p + 71, 30); /* in ns */
215 67b915a5 bellard
    put_le16(p + 72, 30); /* in ns */
216 5391d806 bellard
217 67b915a5 bellard
    put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
218 8ccad811 bellard
#ifdef USE_DMA_CDROM
219 8ccad811 bellard
    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
220 8ccad811 bellard
#endif
221 94458802 bellard
    memcpy(s->identify_data, p, sizeof(s->identify_data));
222 94458802 bellard
    s->identify_set = 1;
223 5391d806 bellard
}
224 5391d806 bellard
225 201a51fc balrog
static void ide_cfata_identify(IDEState *s)
226 201a51fc balrog
{
227 201a51fc balrog
    uint16_t *p;
228 201a51fc balrog
    uint32_t cur_sec;
229 201a51fc balrog
230 201a51fc balrog
    p = (uint16_t *) s->identify_data;
231 201a51fc balrog
    if (s->identify_set)
232 201a51fc balrog
        goto fill_buffer;
233 201a51fc balrog
234 201a51fc balrog
    memset(p, 0, sizeof(s->identify_data));
235 201a51fc balrog
236 201a51fc balrog
    cur_sec = s->cylinders * s->heads * s->sectors;
237 201a51fc balrog
238 201a51fc balrog
    put_le16(p + 0, 0x848a);                        /* CF Storage Card signature */
239 201a51fc balrog
    put_le16(p + 1, s->cylinders);                /* Default cylinders */
240 201a51fc balrog
    put_le16(p + 3, s->heads);                        /* Default heads */
241 201a51fc balrog
    put_le16(p + 6, s->sectors);                /* Default sectors per track */
242 201a51fc balrog
    put_le16(p + 7, s->nb_sectors >> 16);        /* Sectors per card */
243 201a51fc balrog
    put_le16(p + 8, s->nb_sectors);                /* Sectors per card */
244 fa879c64 aliguori
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
245 201a51fc balrog
    put_le16(p + 22, 0x0004);                        /* ECC bytes */
246 47c06340 Gerd Hoffmann
    padstr((char *) (p + 23), s->version, 8);        /* Firmware Revision */
247 60fe76f3 ths
    padstr((char *) (p + 27), "QEMU MICRODRIVE", 40);/* Model number */
248 201a51fc balrog
#if MAX_MULT_SECTORS > 1
249 201a51fc balrog
    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
250 201a51fc balrog
#else
251 201a51fc balrog
    put_le16(p + 47, 0x0000);
252 201a51fc balrog
#endif
253 201a51fc balrog
    put_le16(p + 49, 0x0f00);                        /* Capabilities */
254 201a51fc balrog
    put_le16(p + 51, 0x0002);                        /* PIO cycle timing mode */
255 201a51fc balrog
    put_le16(p + 52, 0x0001);                        /* DMA cycle timing mode */
256 201a51fc balrog
    put_le16(p + 53, 0x0003);                        /* Translation params valid */
257 201a51fc balrog
    put_le16(p + 54, s->cylinders);                /* Current cylinders */
258 201a51fc balrog
    put_le16(p + 55, s->heads);                        /* Current heads */
259 201a51fc balrog
    put_le16(p + 56, s->sectors);                /* Current sectors */
260 201a51fc balrog
    put_le16(p + 57, cur_sec);                        /* Current capacity */
261 201a51fc balrog
    put_le16(p + 58, cur_sec >> 16);                /* Current capacity */
262 201a51fc balrog
    if (s->mult_sectors)                        /* Multiple sector setting */
263 201a51fc balrog
        put_le16(p + 59, 0x100 | s->mult_sectors);
264 201a51fc balrog
    put_le16(p + 60, s->nb_sectors);                /* Total LBA sectors */
265 201a51fc balrog
    put_le16(p + 61, s->nb_sectors >> 16);        /* Total LBA sectors */
266 201a51fc balrog
    put_le16(p + 63, 0x0203);                        /* Multiword DMA capability */
267 201a51fc balrog
    put_le16(p + 64, 0x0001);                        /* Flow Control PIO support */
268 201a51fc balrog
    put_le16(p + 65, 0x0096);                        /* Min. Multiword DMA cycle */
269 201a51fc balrog
    put_le16(p + 66, 0x0096);                        /* Rec. Multiword DMA cycle */
270 201a51fc balrog
    put_le16(p + 68, 0x00b4);                        /* Min. PIO cycle time */
271 201a51fc balrog
    put_le16(p + 82, 0x400c);                        /* Command Set supported */
272 201a51fc balrog
    put_le16(p + 83, 0x7068);                        /* Command Set supported */
273 201a51fc balrog
    put_le16(p + 84, 0x4000);                        /* Features supported */
274 201a51fc balrog
    put_le16(p + 85, 0x000c);                        /* Command Set enabled */
275 201a51fc balrog
    put_le16(p + 86, 0x7044);                        /* Command Set enabled */
276 201a51fc balrog
    put_le16(p + 87, 0x4000);                        /* Features enabled */
277 201a51fc balrog
    put_le16(p + 91, 0x4060);                        /* Current APM level */
278 201a51fc balrog
    put_le16(p + 129, 0x0002);                        /* Current features option */
279 201a51fc balrog
    put_le16(p + 130, 0x0005);                        /* Reassigned sectors */
280 201a51fc balrog
    put_le16(p + 131, 0x0001);                        /* Initial power mode */
281 201a51fc balrog
    put_le16(p + 132, 0x0000);                        /* User signature */
282 201a51fc balrog
    put_le16(p + 160, 0x8100);                        /* Power requirement */
283 201a51fc balrog
    put_le16(p + 161, 0x8001);                        /* CF command set */
284 201a51fc balrog
285 201a51fc balrog
    s->identify_set = 1;
286 201a51fc balrog
287 201a51fc balrog
fill_buffer:
288 201a51fc balrog
    memcpy(s->io_buffer, p, sizeof(s->identify_data));
289 201a51fc balrog
}
290 201a51fc balrog
291 5391d806 bellard
static void ide_set_signature(IDEState *s)
292 5391d806 bellard
{
293 5391d806 bellard
    s->select &= 0xf0; /* clear head */
294 5391d806 bellard
    /* put signature */
295 5391d806 bellard
    s->nsector = 1;
296 5391d806 bellard
    s->sector = 1;
297 cd8722bb Markus Armbruster
    if (s->drive_kind == IDE_CD) {
298 5391d806 bellard
        s->lcyl = 0x14;
299 5391d806 bellard
        s->hcyl = 0xeb;
300 5391d806 bellard
    } else if (s->bs) {
301 5391d806 bellard
        s->lcyl = 0;
302 5391d806 bellard
        s->hcyl = 0;
303 5391d806 bellard
    } else {
304 5391d806 bellard
        s->lcyl = 0xff;
305 5391d806 bellard
        s->hcyl = 0xff;
306 5391d806 bellard
    }
307 5391d806 bellard
}
308 5391d806 bellard
309 5391d806 bellard
static inline void ide_abort_command(IDEState *s)
310 5391d806 bellard
{
311 5391d806 bellard
    s->status = READY_STAT | ERR_STAT;
312 5391d806 bellard
    s->error = ABRT_ERR;
313 5391d806 bellard
}
314 5391d806 bellard
315 5604e090 balrog
static inline void ide_dma_submit_check(IDEState *s,
316 5604e090 balrog
          BlockDriverCompletionFunc *dma_cb, BMDMAState *bm)
317 5604e090 balrog
{
318 5604e090 balrog
    if (bm->aiocb)
319 5604e090 balrog
        return;
320 5604e090 balrog
    dma_cb(bm, -1);
321 5604e090 balrog
}
322 5604e090 balrog
323 5391d806 bellard
/* prepare data transfer and tell what to do after */
324 5fafdf24 ths
static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
325 5391d806 bellard
                               EndTransferFunc *end_transfer_func)
326 5391d806 bellard
{
327 5391d806 bellard
    s->end_transfer_func = end_transfer_func;
328 5391d806 bellard
    s->data_ptr = buf;
329 5391d806 bellard
    s->data_end = buf + size;
330 7603d156 ths
    if (!(s->status & ERR_STAT))
331 7603d156 ths
        s->status |= DRQ_STAT;
332 5391d806 bellard
}
333 5391d806 bellard
334 5391d806 bellard
static void ide_transfer_stop(IDEState *s)
335 5391d806 bellard
{
336 5391d806 bellard
    s->end_transfer_func = ide_transfer_stop;
337 5391d806 bellard
    s->data_ptr = s->io_buffer;
338 5391d806 bellard
    s->data_end = s->io_buffer;
339 5391d806 bellard
    s->status &= ~DRQ_STAT;
340 5391d806 bellard
}
341 5391d806 bellard
342 356721ae Gerd Hoffmann
int64_t ide_get_sector(IDEState *s)
343 5391d806 bellard
{
344 5391d806 bellard
    int64_t sector_num;
345 5391d806 bellard
    if (s->select & 0x40) {
346 5391d806 bellard
        /* lba */
347 c2ff060f bellard
        if (!s->lba48) {
348 c2ff060f bellard
            sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
349 c2ff060f bellard
                (s->lcyl << 8) | s->sector;
350 c2ff060f bellard
        } else {
351 c2ff060f bellard
            sector_num = ((int64_t)s->hob_hcyl << 40) |
352 c2ff060f bellard
                ((int64_t) s->hob_lcyl << 32) |
353 c2ff060f bellard
                ((int64_t) s->hob_sector << 24) |
354 c2ff060f bellard
                ((int64_t) s->hcyl << 16) |
355 c2ff060f bellard
                ((int64_t) s->lcyl << 8) | s->sector;
356 c2ff060f bellard
        }
357 5391d806 bellard
    } else {
358 5391d806 bellard
        sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
359 c2ff060f bellard
            (s->select & 0x0f) * s->sectors + (s->sector - 1);
360 5391d806 bellard
    }
361 5391d806 bellard
    return sector_num;
362 5391d806 bellard
}
363 5391d806 bellard
364 356721ae Gerd Hoffmann
void ide_set_sector(IDEState *s, int64_t sector_num)
365 5391d806 bellard
{
366 5391d806 bellard
    unsigned int cyl, r;
367 5391d806 bellard
    if (s->select & 0x40) {
368 c2ff060f bellard
        if (!s->lba48) {
369 c2ff060f bellard
            s->select = (s->select & 0xf0) | (sector_num >> 24);
370 c2ff060f bellard
            s->hcyl = (sector_num >> 16);
371 c2ff060f bellard
            s->lcyl = (sector_num >> 8);
372 c2ff060f bellard
            s->sector = (sector_num);
373 c2ff060f bellard
        } else {
374 c2ff060f bellard
            s->sector = sector_num;
375 c2ff060f bellard
            s->lcyl = sector_num >> 8;
376 c2ff060f bellard
            s->hcyl = sector_num >> 16;
377 c2ff060f bellard
            s->hob_sector = sector_num >> 24;
378 c2ff060f bellard
            s->hob_lcyl = sector_num >> 32;
379 c2ff060f bellard
            s->hob_hcyl = sector_num >> 40;
380 c2ff060f bellard
        }
381 5391d806 bellard
    } else {
382 5391d806 bellard
        cyl = sector_num / (s->heads * s->sectors);
383 5391d806 bellard
        r = sector_num % (s->heads * s->sectors);
384 5391d806 bellard
        s->hcyl = cyl >> 8;
385 5391d806 bellard
        s->lcyl = cyl;
386 1b8eb456 bellard
        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
387 5391d806 bellard
        s->sector = (r % s->sectors) + 1;
388 5391d806 bellard
    }
389 5391d806 bellard
}
390 5391d806 bellard
391 e162cfb0 balrog
static void ide_rw_error(IDEState *s) {
392 e162cfb0 balrog
    ide_abort_command(s);
393 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
394 e162cfb0 balrog
}
395 e162cfb0 balrog
396 5391d806 bellard
static void ide_sector_read(IDEState *s)
397 5391d806 bellard
{
398 5391d806 bellard
    int64_t sector_num;
399 5391d806 bellard
    int ret, n;
400 5391d806 bellard
401 5391d806 bellard
    s->status = READY_STAT | SEEK_STAT;
402 a136e5a8 bellard
    s->error = 0; /* not needed by IDE spec, but needed by Windows */
403 5391d806 bellard
    sector_num = ide_get_sector(s);
404 5391d806 bellard
    n = s->nsector;
405 5391d806 bellard
    if (n == 0) {
406 5391d806 bellard
        /* no more sector to read from disk */
407 5391d806 bellard
        ide_transfer_stop(s);
408 5391d806 bellard
    } else {
409 5391d806 bellard
#if defined(DEBUG_IDE)
410 18c5f8ea balrog
        printf("read sector=%" PRId64 "\n", sector_num);
411 5391d806 bellard
#endif
412 5391d806 bellard
        if (n > s->req_nb_sectors)
413 5391d806 bellard
            n = s->req_nb_sectors;
414 5391d806 bellard
        ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
415 e162cfb0 balrog
        if (ret != 0) {
416 ce4b6522 Kevin Wolf
            if (ide_handle_rw_error(s, -ret,
417 ce4b6522 Kevin Wolf
                BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ))
418 ce4b6522 Kevin Wolf
            {
419 ce4b6522 Kevin Wolf
                return;
420 ce4b6522 Kevin Wolf
            }
421 e162cfb0 balrog
        }
422 5391d806 bellard
        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
423 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
424 5391d806 bellard
        ide_set_sector(s, sector_num + n);
425 5391d806 bellard
        s->nsector -= n;
426 5391d806 bellard
    }
427 5391d806 bellard
}
428 5391d806 bellard
429 7aea4412 aliguori
430 7aea4412 aliguori
/* return 0 if buffer completed */
431 7aea4412 aliguori
static int dma_buf_prepare(BMDMAState *bm, int is_write)
432 7aea4412 aliguori
{
433 bcbdc4d3 Gerd Hoffmann
    IDEState *s = bmdma_active_if(bm);
434 7aea4412 aliguori
    struct {
435 7aea4412 aliguori
        uint32_t addr;
436 7aea4412 aliguori
        uint32_t size;
437 7aea4412 aliguori
    } prd;
438 7aea4412 aliguori
    int l, len;
439 7aea4412 aliguori
440 6450a334 Blue Swirl
    qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1);
441 7aea4412 aliguori
    s->io_buffer_size = 0;
442 7aea4412 aliguori
    for(;;) {
443 7aea4412 aliguori
        if (bm->cur_prd_len == 0) {
444 7aea4412 aliguori
            /* end of table (with a fail safe of one page) */
445 7aea4412 aliguori
            if (bm->cur_prd_last ||
446 6450a334 Blue Swirl
                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
447 7aea4412 aliguori
                return s->io_buffer_size != 0;
448 7aea4412 aliguori
            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
449 7aea4412 aliguori
            bm->cur_addr += 8;
450 7aea4412 aliguori
            prd.addr = le32_to_cpu(prd.addr);
451 7aea4412 aliguori
            prd.size = le32_to_cpu(prd.size);
452 7aea4412 aliguori
            len = prd.size & 0xfffe;
453 7aea4412 aliguori
            if (len == 0)
454 7aea4412 aliguori
                len = 0x10000;
455 7aea4412 aliguori
            bm->cur_prd_len = len;
456 7aea4412 aliguori
            bm->cur_prd_addr = prd.addr;
457 7aea4412 aliguori
            bm->cur_prd_last = (prd.size & 0x80000000);
458 7aea4412 aliguori
        }
459 7aea4412 aliguori
        l = bm->cur_prd_len;
460 7aea4412 aliguori
        if (l > 0) {
461 1fb8648d aliguori
            qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
462 1fb8648d aliguori
            bm->cur_prd_addr += l;
463 1fb8648d aliguori
            bm->cur_prd_len -= l;
464 1fb8648d aliguori
            s->io_buffer_size += l;
465 7aea4412 aliguori
        }
466 7aea4412 aliguori
    }
467 7aea4412 aliguori
    return 1;
468 7aea4412 aliguori
}
469 7aea4412 aliguori
470 7aea4412 aliguori
static void dma_buf_commit(IDEState *s, int is_write)
471 7aea4412 aliguori
{
472 1fb8648d aliguori
    qemu_sglist_destroy(&s->sg);
473 7aea4412 aliguori
}
474 7aea4412 aliguori
475 356721ae Gerd Hoffmann
void ide_dma_error(IDEState *s)
476 e162cfb0 balrog
{
477 e162cfb0 balrog
    ide_transfer_stop(s);
478 e162cfb0 balrog
    s->error = ABRT_ERR;
479 e162cfb0 balrog
    s->status = READY_STAT | ERR_STAT;
480 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
481 e162cfb0 balrog
}
482 e162cfb0 balrog
483 ce4b6522 Kevin Wolf
static int ide_handle_rw_error(IDEState *s, int error, int op)
484 428c5705 aliguori
{
485 ce4b6522 Kevin Wolf
    int is_read = (op & BM_STATUS_RETRY_READ);
486 abd7f68d Markus Armbruster
    BlockErrorAction action = bdrv_get_on_error(s->bs, is_read);
487 428c5705 aliguori
488 7ad7e3c3 Luiz Capitulino
    if (action == BLOCK_ERR_IGNORE) {
489 7ad7e3c3 Luiz Capitulino
        bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read);
490 428c5705 aliguori
        return 0;
491 7ad7e3c3 Luiz Capitulino
    }
492 428c5705 aliguori
493 428c5705 aliguori
    if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
494 428c5705 aliguori
            || action == BLOCK_ERR_STOP_ANY) {
495 bcbdc4d3 Gerd Hoffmann
        s->bus->bmdma->unit = s->unit;
496 bcbdc4d3 Gerd Hoffmann
        s->bus->bmdma->status |= op;
497 7ad7e3c3 Luiz Capitulino
        bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read);
498 554a310b Luiz Capitulino
        vm_stop(0);
499 428c5705 aliguori
    } else {
500 ce4b6522 Kevin Wolf
        if (op & BM_STATUS_DMA_RETRY) {
501 7aea4412 aliguori
            dma_buf_commit(s, 0);
502 428c5705 aliguori
            ide_dma_error(s);
503 7aea4412 aliguori
        } else {
504 428c5705 aliguori
            ide_rw_error(s);
505 7aea4412 aliguori
        }
506 7ad7e3c3 Luiz Capitulino
        bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read);
507 428c5705 aliguori
    }
508 428c5705 aliguori
509 428c5705 aliguori
    return 1;
510 428c5705 aliguori
}
511 428c5705 aliguori
512 8ccad811 bellard
/* return 0 if buffer completed */
513 8ccad811 bellard
static int dma_buf_rw(BMDMAState *bm, int is_write)
514 98087450 bellard
{
515 bcbdc4d3 Gerd Hoffmann
    IDEState *s = bmdma_active_if(bm);
516 8ccad811 bellard
    struct {
517 8ccad811 bellard
        uint32_t addr;
518 8ccad811 bellard
        uint32_t size;
519 8ccad811 bellard
    } prd;
520 8ccad811 bellard
    int l, len;
521 98087450 bellard
522 8ccad811 bellard
    for(;;) {
523 8ccad811 bellard
        l = s->io_buffer_size - s->io_buffer_index;
524 5fafdf24 ths
        if (l <= 0)
525 8ccad811 bellard
            break;
526 8ccad811 bellard
        if (bm->cur_prd_len == 0) {
527 8ccad811 bellard
            /* end of table (with a fail safe of one page) */
528 8ccad811 bellard
            if (bm->cur_prd_last ||
529 6450a334 Blue Swirl
                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
530 8ccad811 bellard
                return 0;
531 8ccad811 bellard
            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
532 8ccad811 bellard
            bm->cur_addr += 8;
533 8ccad811 bellard
            prd.addr = le32_to_cpu(prd.addr);
534 8ccad811 bellard
            prd.size = le32_to_cpu(prd.size);
535 8ccad811 bellard
            len = prd.size & 0xfffe;
536 8ccad811 bellard
            if (len == 0)
537 8ccad811 bellard
                len = 0x10000;
538 8ccad811 bellard
            bm->cur_prd_len = len;
539 8ccad811 bellard
            bm->cur_prd_addr = prd.addr;
540 8ccad811 bellard
            bm->cur_prd_last = (prd.size & 0x80000000);
541 8ccad811 bellard
        }
542 8ccad811 bellard
        if (l > bm->cur_prd_len)
543 8ccad811 bellard
            l = bm->cur_prd_len;
544 8ccad811 bellard
        if (l > 0) {
545 8ccad811 bellard
            if (is_write) {
546 5fafdf24 ths
                cpu_physical_memory_write(bm->cur_prd_addr,
547 8ccad811 bellard
                                          s->io_buffer + s->io_buffer_index, l);
548 8ccad811 bellard
            } else {
549 5fafdf24 ths
                cpu_physical_memory_read(bm->cur_prd_addr,
550 8ccad811 bellard
                                          s->io_buffer + s->io_buffer_index, l);
551 8ccad811 bellard
            }
552 8ccad811 bellard
            bm->cur_prd_addr += l;
553 8ccad811 bellard
            bm->cur_prd_len -= l;
554 8ccad811 bellard
            s->io_buffer_index += l;
555 98087450 bellard
        }
556 98087450 bellard
    }
557 8ccad811 bellard
    return 1;
558 8ccad811 bellard
}
559 8ccad811 bellard
560 8ccad811 bellard
static void ide_read_dma_cb(void *opaque, int ret)
561 8ccad811 bellard
{
562 8ccad811 bellard
    BMDMAState *bm = opaque;
563 bcbdc4d3 Gerd Hoffmann
    IDEState *s = bmdma_active_if(bm);
564 8ccad811 bellard
    int n;
565 8ccad811 bellard
    int64_t sector_num;
566 8ccad811 bellard
567 e162cfb0 balrog
    if (ret < 0) {
568 ce4b6522 Kevin Wolf
        if (ide_handle_rw_error(s, -ret,
569 ce4b6522 Kevin Wolf
            BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ))
570 ce4b6522 Kevin Wolf
        {
571 ce4b6522 Kevin Wolf
            return;
572 ce4b6522 Kevin Wolf
        }
573 e162cfb0 balrog
    }
574 e162cfb0 balrog
575 8ccad811 bellard
    n = s->io_buffer_size >> 9;
576 8ccad811 bellard
    sector_num = ide_get_sector(s);
577 8ccad811 bellard
    if (n > 0) {
578 7aea4412 aliguori
        dma_buf_commit(s, 1);
579 8ccad811 bellard
        sector_num += n;
580 8ccad811 bellard
        ide_set_sector(s, sector_num);
581 8ccad811 bellard
        s->nsector -= n;
582 8ccad811 bellard
    }
583 8ccad811 bellard
584 8ccad811 bellard
    /* end of transfer ? */
585 8ccad811 bellard
    if (s->nsector == 0) {
586 98087450 bellard
        s->status = READY_STAT | SEEK_STAT;
587 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
588 8ccad811 bellard
    eot:
589 8ccad811 bellard
        bm->status &= ~BM_STATUS_DMAING;
590 8ccad811 bellard
        bm->status |= BM_STATUS_INT;
591 8ccad811 bellard
        bm->dma_cb = NULL;
592 bcbdc4d3 Gerd Hoffmann
        bm->unit = -1;
593 8ccad811 bellard
        bm->aiocb = NULL;
594 8ccad811 bellard
        return;
595 98087450 bellard
    }
596 8ccad811 bellard
597 8ccad811 bellard
    /* launch next transfer */
598 8ccad811 bellard
    n = s->nsector;
599 8ccad811 bellard
    s->io_buffer_index = 0;
600 8ccad811 bellard
    s->io_buffer_size = n * 512;
601 7aea4412 aliguori
    if (dma_buf_prepare(bm, 1) == 0)
602 7aea4412 aliguori
        goto eot;
603 8ccad811 bellard
#ifdef DEBUG_AIO
604 5df23f53 blueswir1
    printf("aio_read: sector_num=%" PRId64 " n=%d\n", sector_num, n);
605 8ccad811 bellard
#endif
606 1fb8648d aliguori
    bm->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, ide_read_dma_cb, bm);
607 5604e090 balrog
    ide_dma_submit_check(s, ide_read_dma_cb, bm);
608 98087450 bellard
}
609 98087450 bellard
610 98087450 bellard
static void ide_sector_read_dma(IDEState *s)
611 98087450 bellard
{
612 8ccad811 bellard
    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
613 98087450 bellard
    s->io_buffer_index = 0;
614 98087450 bellard
    s->io_buffer_size = 0;
615 e3007e66 aurel32
    s->is_read = 1;
616 98087450 bellard
    ide_dma_start(s, ide_read_dma_cb);
617 98087450 bellard
}
618 98087450 bellard
619 a09db21f bellard
static void ide_sector_write_timer_cb(void *opaque)
620 a09db21f bellard
{
621 a09db21f bellard
    IDEState *s = opaque;
622 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
623 a09db21f bellard
}
624 a09db21f bellard
625 5391d806 bellard
static void ide_sector_write(IDEState *s)
626 5391d806 bellard
{
627 5391d806 bellard
    int64_t sector_num;
628 31c2a146 ths
    int ret, n, n1;
629 5391d806 bellard
630 5391d806 bellard
    s->status = READY_STAT | SEEK_STAT;
631 5391d806 bellard
    sector_num = ide_get_sector(s);
632 5391d806 bellard
#if defined(DEBUG_IDE)
633 18c5f8ea balrog
    printf("write sector=%" PRId64 "\n", sector_num);
634 5391d806 bellard
#endif
635 5391d806 bellard
    n = s->nsector;
636 5391d806 bellard
    if (n > s->req_nb_sectors)
637 5391d806 bellard
        n = s->req_nb_sectors;
638 31c2a146 ths
    ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
639 428c5705 aliguori
640 e162cfb0 balrog
    if (ret != 0) {
641 ce4b6522 Kevin Wolf
        if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY))
642 428c5705 aliguori
            return;
643 e162cfb0 balrog
    }
644 e162cfb0 balrog
645 5391d806 bellard
    s->nsector -= n;
646 5391d806 bellard
    if (s->nsector == 0) {
647 292eef5a ths
        /* no more sectors to write */
648 5391d806 bellard
        ide_transfer_stop(s);
649 5391d806 bellard
    } else {
650 5391d806 bellard
        n1 = s->nsector;
651 5391d806 bellard
        if (n1 > s->req_nb_sectors)
652 5391d806 bellard
            n1 = s->req_nb_sectors;
653 5391d806 bellard
        ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
654 5391d806 bellard
    }
655 5391d806 bellard
    ide_set_sector(s, sector_num + n);
656 3b46e624 ths
657 31c2a146 ths
    if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
658 31c2a146 ths
        /* It seems there is a bug in the Windows 2000 installer HDD
659 31c2a146 ths
           IDE driver which fills the disk with empty logs when the
660 31c2a146 ths
           IDE write IRQ comes too early. This hack tries to correct
661 31c2a146 ths
           that at the expense of slower write performances. Use this
662 31c2a146 ths
           option _only_ to install Windows 2000. You must disable it
663 31c2a146 ths
           for normal use. */
664 f7736b91 Blue Swirl
        qemu_mod_timer(s->sector_write_timer,
665 6ee093c9 Juan Quintela
                       qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 1000));
666 f7736b91 Blue Swirl
    } else {
667 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
668 31c2a146 ths
    }
669 5391d806 bellard
}
670 5391d806 bellard
671 213189ab Markus Armbruster
static void ide_dma_restart_bh(void *opaque)
672 428c5705 aliguori
{
673 428c5705 aliguori
    BMDMAState *bm = opaque;
674 ce4b6522 Kevin Wolf
    int is_read;
675 213189ab Markus Armbruster
676 213189ab Markus Armbruster
    qemu_bh_delete(bm->bh);
677 213189ab Markus Armbruster
    bm->bh = NULL;
678 213189ab Markus Armbruster
679 ce4b6522 Kevin Wolf
    is_read = !!(bm->status & BM_STATUS_RETRY_READ);
680 ce4b6522 Kevin Wolf
681 428c5705 aliguori
    if (bm->status & BM_STATUS_DMA_RETRY) {
682 ce4b6522 Kevin Wolf
        bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ);
683 ce4b6522 Kevin Wolf
        ide_dma_restart(bmdma_active_if(bm), is_read);
684 428c5705 aliguori
    } else if (bm->status & BM_STATUS_PIO_RETRY) {
685 ce4b6522 Kevin Wolf
        bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ);
686 ce4b6522 Kevin Wolf
        if (is_read) {
687 ce4b6522 Kevin Wolf
            ide_sector_read(bmdma_active_if(bm));
688 ce4b6522 Kevin Wolf
        } else {
689 ce4b6522 Kevin Wolf
            ide_sector_write(bmdma_active_if(bm));
690 ce4b6522 Kevin Wolf
        }
691 428c5705 aliguori
    }
692 428c5705 aliguori
}
693 428c5705 aliguori
694 356721ae Gerd Hoffmann
void ide_dma_restart_cb(void *opaque, int running, int reason)
695 213189ab Markus Armbruster
{
696 213189ab Markus Armbruster
    BMDMAState *bm = opaque;
697 213189ab Markus Armbruster
698 213189ab Markus Armbruster
    if (!running)
699 213189ab Markus Armbruster
        return;
700 213189ab Markus Armbruster
701 213189ab Markus Armbruster
    if (!bm->bh) {
702 213189ab Markus Armbruster
        bm->bh = qemu_bh_new(ide_dma_restart_bh, bm);
703 213189ab Markus Armbruster
        qemu_bh_schedule(bm->bh);
704 213189ab Markus Armbruster
    }
705 213189ab Markus Armbruster
}
706 213189ab Markus Armbruster
707 8ccad811 bellard
static void ide_write_dma_cb(void *opaque, int ret)
708 98087450 bellard
{
709 8ccad811 bellard
    BMDMAState *bm = opaque;
710 bcbdc4d3 Gerd Hoffmann
    IDEState *s = bmdma_active_if(bm);
711 8ccad811 bellard
    int n;
712 98087450 bellard
    int64_t sector_num;
713 98087450 bellard
714 e162cfb0 balrog
    if (ret < 0) {
715 ce4b6522 Kevin Wolf
        if (ide_handle_rw_error(s, -ret,  BM_STATUS_DMA_RETRY))
716 428c5705 aliguori
            return;
717 e162cfb0 balrog
    }
718 e162cfb0 balrog
719 8ccad811 bellard
    n = s->io_buffer_size >> 9;
720 8ccad811 bellard
    sector_num = ide_get_sector(s);
721 8ccad811 bellard
    if (n > 0) {
722 7aea4412 aliguori
        dma_buf_commit(s, 0);
723 8ccad811 bellard
        sector_num += n;
724 8ccad811 bellard
        ide_set_sector(s, sector_num);
725 8ccad811 bellard
        s->nsector -= n;
726 98087450 bellard
    }
727 98087450 bellard
728 8ccad811 bellard
    /* end of transfer ? */
729 8ccad811 bellard
    if (s->nsector == 0) {
730 8ccad811 bellard
        s->status = READY_STAT | SEEK_STAT;
731 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
732 8ccad811 bellard
    eot:
733 8ccad811 bellard
        bm->status &= ~BM_STATUS_DMAING;
734 8ccad811 bellard
        bm->status |= BM_STATUS_INT;
735 8ccad811 bellard
        bm->dma_cb = NULL;
736 bcbdc4d3 Gerd Hoffmann
        bm->unit = -1;
737 8ccad811 bellard
        bm->aiocb = NULL;
738 8ccad811 bellard
        return;
739 8ccad811 bellard
    }
740 8ccad811 bellard
741 98087450 bellard
    n = s->nsector;
742 98087450 bellard
    s->io_buffer_size = n * 512;
743 7aea4412 aliguori
    /* launch next transfer */
744 7aea4412 aliguori
    if (dma_buf_prepare(bm, 0) == 0)
745 8ccad811 bellard
        goto eot;
746 8ccad811 bellard
#ifdef DEBUG_AIO
747 5df23f53 blueswir1
    printf("aio_write: sector_num=%" PRId64 " n=%d\n", sector_num, n);
748 8ccad811 bellard
#endif
749 1fb8648d aliguori
    bm->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, ide_write_dma_cb, bm);
750 5604e090 balrog
    ide_dma_submit_check(s, ide_write_dma_cb, bm);
751 8ccad811 bellard
}
752 8ccad811 bellard
753 8ccad811 bellard
static void ide_sector_write_dma(IDEState *s)
754 8ccad811 bellard
{
755 8ccad811 bellard
    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
756 8ccad811 bellard
    s->io_buffer_index = 0;
757 8ccad811 bellard
    s->io_buffer_size = 0;
758 e3007e66 aurel32
    s->is_read = 0;
759 98087450 bellard
    ide_dma_start(s, ide_write_dma_cb);
760 98087450 bellard
}
761 98087450 bellard
762 356721ae Gerd Hoffmann
void ide_atapi_cmd_ok(IDEState *s)
763 5391d806 bellard
{
764 5391d806 bellard
    s->error = 0;
765 41a2b959 aliguori
    s->status = READY_STAT | SEEK_STAT;
766 5391d806 bellard
    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
767 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
768 5391d806 bellard
}
769 5391d806 bellard
770 356721ae Gerd Hoffmann
void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
771 5391d806 bellard
{
772 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
773 5391d806 bellard
    printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
774 5391d806 bellard
#endif
775 5391d806 bellard
    s->error = sense_key << 4;
776 5391d806 bellard
    s->status = READY_STAT | ERR_STAT;
777 5391d806 bellard
    s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
778 5391d806 bellard
    s->sense_key = sense_key;
779 5391d806 bellard
    s->asc = asc;
780 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
781 5391d806 bellard
}
782 5391d806 bellard
783 9118e7f0 aliguori
static void ide_atapi_cmd_check_status(IDEState *s)
784 9118e7f0 aliguori
{
785 9118e7f0 aliguori
#ifdef DEBUG_IDE_ATAPI
786 9118e7f0 aliguori
    printf("atapi_cmd_check_status\n");
787 9118e7f0 aliguori
#endif
788 9118e7f0 aliguori
    s->error = MC_ERR | (SENSE_UNIT_ATTENTION << 4);
789 9118e7f0 aliguori
    s->status = ERR_STAT;
790 9118e7f0 aliguori
    s->nsector = 0;
791 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
792 9118e7f0 aliguori
}
793 9118e7f0 aliguori
794 b0484ae4 Christoph Hellwig
static void ide_flush_cb(void *opaque, int ret)
795 b0484ae4 Christoph Hellwig
{
796 b0484ae4 Christoph Hellwig
    IDEState *s = opaque;
797 b0484ae4 Christoph Hellwig
798 b0484ae4 Christoph Hellwig
    /* XXX: how do we signal I/O errors here? */
799 b0484ae4 Christoph Hellwig
800 b0484ae4 Christoph Hellwig
    s->status = READY_STAT | SEEK_STAT;
801 b0484ae4 Christoph Hellwig
    ide_set_irq(s->bus);
802 b0484ae4 Christoph Hellwig
}
803 b0484ae4 Christoph Hellwig
804 5391d806 bellard
static inline void cpu_to_ube16(uint8_t *buf, int val)
805 5391d806 bellard
{
806 5391d806 bellard
    buf[0] = val >> 8;
807 9e622b15 blueswir1
    buf[1] = val & 0xff;
808 5391d806 bellard
}
809 5391d806 bellard
810 5391d806 bellard
static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
811 5391d806 bellard
{
812 5391d806 bellard
    buf[0] = val >> 24;
813 5391d806 bellard
    buf[1] = val >> 16;
814 5391d806 bellard
    buf[2] = val >> 8;
815 9e622b15 blueswir1
    buf[3] = val & 0xff;
816 5391d806 bellard
}
817 5391d806 bellard
818 5391d806 bellard
static inline int ube16_to_cpu(const uint8_t *buf)
819 5391d806 bellard
{
820 5391d806 bellard
    return (buf[0] << 8) | buf[1];
821 5391d806 bellard
}
822 5391d806 bellard
823 5391d806 bellard
static inline int ube32_to_cpu(const uint8_t *buf)
824 5391d806 bellard
{
825 5391d806 bellard
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
826 5391d806 bellard
}
827 5391d806 bellard
828 98087450 bellard
static void lba_to_msf(uint8_t *buf, int lba)
829 98087450 bellard
{
830 98087450 bellard
    lba += 150;
831 98087450 bellard
    buf[0] = (lba / 75) / 60;
832 98087450 bellard
    buf[1] = (lba / 75) % 60;
833 98087450 bellard
    buf[2] = lba % 75;
834 98087450 bellard
}
835 98087450 bellard
836 8ccad811 bellard
static void cd_data_to_raw(uint8_t *buf, int lba)
837 8ccad811 bellard
{
838 8ccad811 bellard
    /* sync bytes */
839 8ccad811 bellard
    buf[0] = 0x00;
840 8ccad811 bellard
    memset(buf + 1, 0xff, 10);
841 8ccad811 bellard
    buf[11] = 0x00;
842 8ccad811 bellard
    buf += 12;
843 8ccad811 bellard
    /* MSF */
844 8ccad811 bellard
    lba_to_msf(buf, lba);
845 8ccad811 bellard
    buf[3] = 0x01; /* mode 1 data */
846 8ccad811 bellard
    buf += 4;
847 8ccad811 bellard
    /* data */
848 8ccad811 bellard
    buf += 2048;
849 8ccad811 bellard
    /* XXX: ECC not computed */
850 8ccad811 bellard
    memset(buf, 0, 288);
851 8ccad811 bellard
}
852 8ccad811 bellard
853 5fafdf24 ths
static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
854 98087450 bellard
                           int sector_size)
855 98087450 bellard
{
856 66c6ef76 bellard
    int ret;
857 66c6ef76 bellard
858 98087450 bellard
    switch(sector_size) {
859 98087450 bellard
    case 2048:
860 66c6ef76 bellard
        ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
861 98087450 bellard
        break;
862 98087450 bellard
    case 2352:
863 66c6ef76 bellard
        ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
864 66c6ef76 bellard
        if (ret < 0)
865 66c6ef76 bellard
            return ret;
866 8ccad811 bellard
        cd_data_to_raw(buf, lba);
867 98087450 bellard
        break;
868 98087450 bellard
    default:
869 66c6ef76 bellard
        ret = -EIO;
870 98087450 bellard
        break;
871 98087450 bellard
    }
872 66c6ef76 bellard
    return ret;
873 66c6ef76 bellard
}
874 66c6ef76 bellard
875 356721ae Gerd Hoffmann
void ide_atapi_io_error(IDEState *s, int ret)
876 66c6ef76 bellard
{
877 66c6ef76 bellard
    /* XXX: handle more errors */
878 66c6ef76 bellard
    if (ret == -ENOMEDIUM) {
879 5fafdf24 ths
        ide_atapi_cmd_error(s, SENSE_NOT_READY,
880 66c6ef76 bellard
                            ASC_MEDIUM_NOT_PRESENT);
881 66c6ef76 bellard
    } else {
882 5fafdf24 ths
        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
883 66c6ef76 bellard
                            ASC_LOGICAL_BLOCK_OOR);
884 66c6ef76 bellard
    }
885 98087450 bellard
}
886 98087450 bellard
887 5391d806 bellard
/* The whole ATAPI transfer logic is handled in this function */
888 5391d806 bellard
static void ide_atapi_cmd_reply_end(IDEState *s)
889 5391d806 bellard
{
890 66c6ef76 bellard
    int byte_count_limit, size, ret;
891 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
892 5fafdf24 ths
    printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
893 5391d806 bellard
           s->packet_transfer_size,
894 5391d806 bellard
           s->elementary_transfer_size,
895 5391d806 bellard
           s->io_buffer_index);
896 5391d806 bellard
#endif
897 5391d806 bellard
    if (s->packet_transfer_size <= 0) {
898 5391d806 bellard
        /* end of transfer */
899 5391d806 bellard
        ide_transfer_stop(s);
900 41a2b959 aliguori
        s->status = READY_STAT | SEEK_STAT;
901 5391d806 bellard
        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
902 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
903 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
904 5391d806 bellard
        printf("status=0x%x\n", s->status);
905 5391d806 bellard
#endif
906 5391d806 bellard
    } else {
907 5391d806 bellard
        /* see if a new sector must be read */
908 98087450 bellard
        if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
909 66c6ef76 bellard
            ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
910 66c6ef76 bellard
            if (ret < 0) {
911 66c6ef76 bellard
                ide_transfer_stop(s);
912 66c6ef76 bellard
                ide_atapi_io_error(s, ret);
913 66c6ef76 bellard
                return;
914 66c6ef76 bellard
            }
915 5391d806 bellard
            s->lba++;
916 5391d806 bellard
            s->io_buffer_index = 0;
917 5391d806 bellard
        }
918 5391d806 bellard
        if (s->elementary_transfer_size > 0) {
919 5391d806 bellard
            /* there are some data left to transmit in this elementary
920 5391d806 bellard
               transfer */
921 98087450 bellard
            size = s->cd_sector_size - s->io_buffer_index;
922 5391d806 bellard
            if (size > s->elementary_transfer_size)
923 5391d806 bellard
                size = s->elementary_transfer_size;
924 5fafdf24 ths
            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
925 5391d806 bellard
                               size, ide_atapi_cmd_reply_end);
926 5391d806 bellard
            s->packet_transfer_size -= size;
927 5391d806 bellard
            s->elementary_transfer_size -= size;
928 5391d806 bellard
            s->io_buffer_index += size;
929 5391d806 bellard
        } else {
930 5391d806 bellard
            /* a new transfer is needed */
931 5391d806 bellard
            s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
932 5391d806 bellard
            byte_count_limit = s->lcyl | (s->hcyl << 8);
933 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
934 5391d806 bellard
            printf("byte_count_limit=%d\n", byte_count_limit);
935 5391d806 bellard
#endif
936 5391d806 bellard
            if (byte_count_limit == 0xffff)
937 5391d806 bellard
                byte_count_limit--;
938 5391d806 bellard
            size = s->packet_transfer_size;
939 5391d806 bellard
            if (size > byte_count_limit) {
940 5391d806 bellard
                /* byte count limit must be even if this case */
941 5391d806 bellard
                if (byte_count_limit & 1)
942 5391d806 bellard
                    byte_count_limit--;
943 5391d806 bellard
                size = byte_count_limit;
944 5391d806 bellard
            }
945 a136e5a8 bellard
            s->lcyl = size;
946 a136e5a8 bellard
            s->hcyl = size >> 8;
947 5391d806 bellard
            s->elementary_transfer_size = size;
948 5391d806 bellard
            /* we cannot transmit more than one sector at a time */
949 5391d806 bellard
            if (s->lba != -1) {
950 98087450 bellard
                if (size > (s->cd_sector_size - s->io_buffer_index))
951 98087450 bellard
                    size = (s->cd_sector_size - s->io_buffer_index);
952 5391d806 bellard
            }
953 5fafdf24 ths
            ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
954 5391d806 bellard
                               size, ide_atapi_cmd_reply_end);
955 5391d806 bellard
            s->packet_transfer_size -= size;
956 5391d806 bellard
            s->elementary_transfer_size -= size;
957 5391d806 bellard
            s->io_buffer_index += size;
958 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
959 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
960 5391d806 bellard
            printf("status=0x%x\n", s->status);
961 5391d806 bellard
#endif
962 5391d806 bellard
        }
963 5391d806 bellard
    }
964 5391d806 bellard
}
965 5391d806 bellard
966 5391d806 bellard
/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
967 5391d806 bellard
static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
968 5391d806 bellard
{
969 5391d806 bellard
    if (size > max_size)
970 5391d806 bellard
        size = max_size;
971 5391d806 bellard
    s->lba = -1; /* no sector read */
972 5391d806 bellard
    s->packet_transfer_size = size;
973 5f12ab4b ths
    s->io_buffer_size = size;    /* dma: send the reply data as one chunk */
974 5391d806 bellard
    s->elementary_transfer_size = 0;
975 5391d806 bellard
    s->io_buffer_index = 0;
976 5391d806 bellard
977 5f12ab4b ths
    if (s->atapi_dma) {
978 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
979 5f12ab4b ths
        ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
980 5f12ab4b ths
    } else {
981 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
982 5f12ab4b ths
            ide_atapi_cmd_reply_end(s);
983 5f12ab4b ths
    }
984 5391d806 bellard
}
985 5391d806 bellard
986 5391d806 bellard
/* start a CD-CDROM read command */
987 98087450 bellard
static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
988 98087450 bellard
                                   int sector_size)
989 5391d806 bellard
{
990 5391d806 bellard
    s->lba = lba;
991 98087450 bellard
    s->packet_transfer_size = nb_sectors * sector_size;
992 5391d806 bellard
    s->elementary_transfer_size = 0;
993 98087450 bellard
    s->io_buffer_index = sector_size;
994 98087450 bellard
    s->cd_sector_size = sector_size;
995 5391d806 bellard
996 41a2b959 aliguori
    s->status = READY_STAT | SEEK_STAT;
997 5391d806 bellard
    ide_atapi_cmd_reply_end(s);
998 5391d806 bellard
}
999 5391d806 bellard
1000 98087450 bellard
/* ATAPI DMA support */
1001 8ccad811 bellard
1002 8ccad811 bellard
/* XXX: handle read errors */
1003 8ccad811 bellard
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
1004 98087450 bellard
{
1005 8ccad811 bellard
    BMDMAState *bm = opaque;
1006 bcbdc4d3 Gerd Hoffmann
    IDEState *s = bmdma_active_if(bm);
1007 8ccad811 bellard
    int data_offset, n;
1008 8ccad811 bellard
1009 66c6ef76 bellard
    if (ret < 0) {
1010 66c6ef76 bellard
        ide_atapi_io_error(s, ret);
1011 66c6ef76 bellard
        goto eot;
1012 66c6ef76 bellard
    }
1013 66c6ef76 bellard
1014 8ccad811 bellard
    if (s->io_buffer_size > 0) {
1015 5f12ab4b ths
        /*
1016 5f12ab4b ths
         * For a cdrom read sector command (s->lba != -1),
1017 5f12ab4b ths
         * adjust the lba for the next s->io_buffer_size chunk
1018 5f12ab4b ths
         * and dma the current chunk.
1019 5f12ab4b ths
         * For a command != read (s->lba == -1), just transfer
1020 5f12ab4b ths
         * the reply data.
1021 5f12ab4b ths
         */
1022 5f12ab4b ths
        if (s->lba != -1) {
1023 5f12ab4b ths
            if (s->cd_sector_size == 2352) {
1024 5f12ab4b ths
                n = 1;
1025 5f12ab4b ths
                cd_data_to_raw(s->io_buffer, s->lba);
1026 5f12ab4b ths
            } else {
1027 5f12ab4b ths
                n = s->io_buffer_size >> 11;
1028 5f12ab4b ths
            }
1029 5f12ab4b ths
            s->lba += n;
1030 5f12ab4b ths
        }
1031 8ccad811 bellard
        s->packet_transfer_size -= s->io_buffer_size;
1032 8ccad811 bellard
        if (dma_buf_rw(bm, 1) == 0)
1033 8ccad811 bellard
            goto eot;
1034 98087450 bellard
    }
1035 8ccad811 bellard
1036 98087450 bellard
    if (s->packet_transfer_size <= 0) {
1037 41a2b959 aliguori
        s->status = READY_STAT | SEEK_STAT;
1038 98087450 bellard
        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
1039 9cdd03a7 Gerd Hoffmann
        ide_set_irq(s->bus);
1040 8ccad811 bellard
    eot:
1041 8ccad811 bellard
        bm->status &= ~BM_STATUS_DMAING;
1042 8ccad811 bellard
        bm->status |= BM_STATUS_INT;
1043 8ccad811 bellard
        bm->dma_cb = NULL;
1044 bcbdc4d3 Gerd Hoffmann
        bm->unit = -1;
1045 8ccad811 bellard
        bm->aiocb = NULL;
1046 8ccad811 bellard
        return;
1047 8ccad811 bellard
    }
1048 3b46e624 ths
1049 8ccad811 bellard
    s->io_buffer_index = 0;
1050 8ccad811 bellard
    if (s->cd_sector_size == 2352) {
1051 8ccad811 bellard
        n = 1;
1052 8ccad811 bellard
        s->io_buffer_size = s->cd_sector_size;
1053 8ccad811 bellard
        data_offset = 16;
1054 8ccad811 bellard
    } else {
1055 8ccad811 bellard
        n = s->packet_transfer_size >> 11;
1056 1d8cde5b aurel32
        if (n > (IDE_DMA_BUF_SECTORS / 4))
1057 1d8cde5b aurel32
            n = (IDE_DMA_BUF_SECTORS / 4);
1058 8ccad811 bellard
        s->io_buffer_size = n * 2048;
1059 8ccad811 bellard
        data_offset = 0;
1060 98087450 bellard
    }
1061 8ccad811 bellard
#ifdef DEBUG_AIO
1062 8ccad811 bellard
    printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
1063 8ccad811 bellard
#endif
1064 3f4cb3d3 blueswir1
    bm->iov.iov_base = (void *)(s->io_buffer + data_offset);
1065 c87c0672 aliguori
    bm->iov.iov_len = n * 4 * 512;
1066 c87c0672 aliguori
    qemu_iovec_init_external(&bm->qiov, &bm->iov, 1);
1067 c87c0672 aliguori
    bm->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2, &bm->qiov,
1068 c87c0672 aliguori
                               n * 4, ide_atapi_cmd_read_dma_cb, bm);
1069 66c6ef76 bellard
    if (!bm->aiocb) {
1070 66c6ef76 bellard
        /* Note: media not present is the most likely case */
1071 5fafdf24 ths
        ide_atapi_cmd_error(s, SENSE_NOT_READY,
1072 66c6ef76 bellard
                            ASC_MEDIUM_NOT_PRESENT);
1073 66c6ef76 bellard
        goto eot;
1074 66c6ef76 bellard
    }
1075 98087450 bellard
}
1076 98087450 bellard
1077 98087450 bellard
/* start a CD-CDROM read command with DMA */
1078 98087450 bellard
/* XXX: test if DMA is available */
1079 98087450 bellard
static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
1080 98087450 bellard
                                   int sector_size)
1081 98087450 bellard
{
1082 98087450 bellard
    s->lba = lba;
1083 98087450 bellard
    s->packet_transfer_size = nb_sectors * sector_size;
1084 8ccad811 bellard
    s->io_buffer_index = 0;
1085 8ccad811 bellard
    s->io_buffer_size = 0;
1086 98087450 bellard
    s->cd_sector_size = sector_size;
1087 98087450 bellard
1088 8ccad811 bellard
    /* XXX: check if BUSY_STAT should be set */
1089 41a2b959 aliguori
    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
1090 98087450 bellard
    ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
1091 98087450 bellard
}
1092 98087450 bellard
1093 5fafdf24 ths
static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
1094 98087450 bellard
                               int sector_size)
1095 98087450 bellard
{
1096 98087450 bellard
#ifdef DEBUG_IDE_ATAPI
1097 5f12ab4b ths
    printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
1098 5f12ab4b ths
        lba, nb_sectors);
1099 98087450 bellard
#endif
1100 98087450 bellard
    if (s->atapi_dma) {
1101 98087450 bellard
        ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
1102 98087450 bellard
    } else {
1103 98087450 bellard
        ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
1104 98087450 bellard
    }
1105 98087450 bellard
}
1106 98087450 bellard
1107 38cdea7c balrog
static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
1108 38cdea7c balrog
                                            uint16_t profile)
1109 38cdea7c balrog
{
1110 38cdea7c balrog
    uint8_t *buf_profile = buf + 12; /* start of profiles */
1111 38cdea7c balrog
1112 38cdea7c balrog
    buf_profile += ((*index) * 4); /* start of indexed profile */
1113 38cdea7c balrog
    cpu_to_ube16 (buf_profile, profile);
1114 38cdea7c balrog
    buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7]));
1115 38cdea7c balrog
1116 38cdea7c balrog
    /* each profile adds 4 bytes to the response */
1117 38cdea7c balrog
    (*index)++;
1118 38cdea7c balrog
    buf[11] += 4; /* Additional Length */
1119 38cdea7c balrog
1120 38cdea7c balrog
    return 4;
1121 38cdea7c balrog
}
1122 38cdea7c balrog
1123 8114e9e8 ths
static int ide_dvd_read_structure(IDEState *s, int format,
1124 8114e9e8 ths
                                  const uint8_t *packet, uint8_t *buf)
1125 8114e9e8 ths
{
1126 8114e9e8 ths
    switch (format) {
1127 8114e9e8 ths
        case 0x0: /* Physical format information */
1128 8114e9e8 ths
            {
1129 8114e9e8 ths
                int layer = packet[6];
1130 8114e9e8 ths
                uint64_t total_sectors;
1131 8114e9e8 ths
1132 8114e9e8 ths
                if (layer != 0)
1133 8114e9e8 ths
                    return -ASC_INV_FIELD_IN_CMD_PACKET;
1134 8114e9e8 ths
1135 8114e9e8 ths
                bdrv_get_geometry(s->bs, &total_sectors);
1136 8114e9e8 ths
                total_sectors >>= 2;
1137 8114e9e8 ths
                if (total_sectors == 0)
1138 8114e9e8 ths
                    return -ASC_MEDIUM_NOT_PRESENT;
1139 8114e9e8 ths
1140 8114e9e8 ths
                buf[4] = 1;   /* DVD-ROM, part version 1 */
1141 8114e9e8 ths
                buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
1142 8114e9e8 ths
                buf[6] = 1;   /* one layer, read-only (per MMC-2 spec) */
1143 8114e9e8 ths
                buf[7] = 0;   /* default densities */
1144 8114e9e8 ths
1145 8114e9e8 ths
                /* FIXME: 0x30000 per spec? */
1146 8114e9e8 ths
                cpu_to_ube32(buf + 8, 0); /* start sector */
1147 8114e9e8 ths
                cpu_to_ube32(buf + 12, total_sectors - 1); /* end sector */
1148 8114e9e8 ths
                cpu_to_ube32(buf + 16, total_sectors - 1); /* l0 end sector */
1149 8114e9e8 ths
1150 8114e9e8 ths
                /* Size of buffer, not including 2 byte size field */
1151 8114e9e8 ths
                cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
1152 8114e9e8 ths
1153 8114e9e8 ths
                /* 2k data + 4 byte header */
1154 8114e9e8 ths
                return (2048 + 4);
1155 8114e9e8 ths
            }
1156 8114e9e8 ths
1157 8114e9e8 ths
        case 0x01: /* DVD copyright information */
1158 8114e9e8 ths
            buf[4] = 0; /* no copyright data */
1159 8114e9e8 ths
            buf[5] = 0; /* no region restrictions */
1160 8114e9e8 ths
1161 8114e9e8 ths
            /* Size of buffer, not including 2 byte size field */
1162 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)buf, 4 + 2);
1163 8114e9e8 ths
1164 8114e9e8 ths
            /* 4 byte header + 4 byte data */
1165 8114e9e8 ths
            return (4 + 4);
1166 8114e9e8 ths
1167 8114e9e8 ths
        case 0x03: /* BCA information - invalid field for no BCA info */
1168 8114e9e8 ths
            return -ASC_INV_FIELD_IN_CMD_PACKET;
1169 8114e9e8 ths
1170 8114e9e8 ths
        case 0x04: /* DVD disc manufacturing information */
1171 8114e9e8 ths
            /* Size of buffer, not including 2 byte size field */
1172 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)buf, 2048 + 2);
1173 8114e9e8 ths
1174 8114e9e8 ths
            /* 2k data + 4 byte header */
1175 8114e9e8 ths
            return (2048 + 4);
1176 8114e9e8 ths
1177 8114e9e8 ths
        case 0xff:
1178 8114e9e8 ths
            /*
1179 8114e9e8 ths
             * This lists all the command capabilities above.  Add new ones
1180 8114e9e8 ths
             * in order and update the length and buffer return values.
1181 8114e9e8 ths
             */
1182 8114e9e8 ths
1183 8114e9e8 ths
            buf[4] = 0x00; /* Physical format */
1184 8114e9e8 ths
            buf[5] = 0x40; /* Not writable, is readable */
1185 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)(buf + 6), 2048 + 4);
1186 8114e9e8 ths
1187 8114e9e8 ths
            buf[8] = 0x01; /* Copyright info */
1188 8114e9e8 ths
            buf[9] = 0x40; /* Not writable, is readable */
1189 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)(buf + 10), 4 + 4);
1190 8114e9e8 ths
1191 8114e9e8 ths
            buf[12] = 0x03; /* BCA info */
1192 8114e9e8 ths
            buf[13] = 0x40; /* Not writable, is readable */
1193 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)(buf + 14), 188 + 4);
1194 8114e9e8 ths
1195 8114e9e8 ths
            buf[16] = 0x04; /* Manufacturing info */
1196 8114e9e8 ths
            buf[17] = 0x40; /* Not writable, is readable */
1197 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)(buf + 18), 2048 + 4);
1198 8114e9e8 ths
1199 8114e9e8 ths
            /* Size of buffer, not including 2 byte size field */
1200 8114e9e8 ths
            cpu_to_be16wu((uint16_t *)buf, 16 + 2);
1201 8114e9e8 ths
1202 8114e9e8 ths
            /* data written + 4 byte header */
1203 8114e9e8 ths
            return (16 + 4);
1204 8114e9e8 ths
1205 8114e9e8 ths
        default: /* TODO: formats beyond DVD-ROM requires */
1206 8114e9e8 ths
            return -ASC_INV_FIELD_IN_CMD_PACKET;
1207 8114e9e8 ths
    }
1208 8114e9e8 ths
}
1209 8114e9e8 ths
1210 5391d806 bellard
static void ide_atapi_cmd(IDEState *s)
1211 5391d806 bellard
{
1212 5391d806 bellard
    const uint8_t *packet;
1213 5391d806 bellard
    uint8_t *buf;
1214 5391d806 bellard
    int max_len;
1215 5391d806 bellard
1216 5391d806 bellard
    packet = s->io_buffer;
1217 5391d806 bellard
    buf = s->io_buffer;
1218 5391d806 bellard
#ifdef DEBUG_IDE_ATAPI
1219 5391d806 bellard
    {
1220 5391d806 bellard
        int i;
1221 5391d806 bellard
        printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
1222 5391d806 bellard
        for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
1223 5391d806 bellard
            printf(" %02x", packet[i]);
1224 5391d806 bellard
        }
1225 5391d806 bellard
        printf("\n");
1226 5391d806 bellard
    }
1227 5391d806 bellard
#endif
1228 9118e7f0 aliguori
    /* If there's a UNIT_ATTENTION condition pending, only
1229 9118e7f0 aliguori
       REQUEST_SENSE and INQUIRY commands are allowed to complete. */
1230 9118e7f0 aliguori
    if (s->sense_key == SENSE_UNIT_ATTENTION &&
1231 9118e7f0 aliguori
        s->io_buffer[0] != GPCMD_REQUEST_SENSE &&
1232 9118e7f0 aliguori
        s->io_buffer[0] != GPCMD_INQUIRY) {
1233 9118e7f0 aliguori
        ide_atapi_cmd_check_status(s);
1234 9118e7f0 aliguori
        return;
1235 9118e7f0 aliguori
    }
1236 5391d806 bellard
    switch(s->io_buffer[0]) {
1237 5391d806 bellard
    case GPCMD_TEST_UNIT_READY:
1238 93c8cfd9 Gleb Natapov
        if (bdrv_is_inserted(s->bs) && !s->cdrom_changed) {
1239 5391d806 bellard
            ide_atapi_cmd_ok(s);
1240 5391d806 bellard
        } else {
1241 93c8cfd9 Gleb Natapov
            s->cdrom_changed = 0;
1242 5fafdf24 ths
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
1243 5391d806 bellard
                                ASC_MEDIUM_NOT_PRESENT);
1244 5391d806 bellard
        }
1245 5391d806 bellard
        break;
1246 d14049ea ths
    case GPCMD_MODE_SENSE_6:
1247 5391d806 bellard
    case GPCMD_MODE_SENSE_10:
1248 5391d806 bellard
        {
1249 5391d806 bellard
            int action, code;
1250 d14049ea ths
            if (packet[0] == GPCMD_MODE_SENSE_10)
1251 d14049ea ths
                max_len = ube16_to_cpu(packet + 7);
1252 d14049ea ths
            else
1253 d14049ea ths
                max_len = packet[4];
1254 5391d806 bellard
            action = packet[2] >> 6;
1255 5391d806 bellard
            code = packet[2] & 0x3f;
1256 5391d806 bellard
            switch(action) {
1257 5391d806 bellard
            case 0: /* current values */
1258 5391d806 bellard
                switch(code) {
1259 a70089ce Thadeu Lima de Souza Cascardo
                case GPMODE_R_W_ERROR_PAGE: /* error recovery */
1260 5391d806 bellard
                    cpu_to_ube16(&buf[0], 16 + 6);
1261 5391d806 bellard
                    buf[2] = 0x70;
1262 5391d806 bellard
                    buf[3] = 0;
1263 5391d806 bellard
                    buf[4] = 0;
1264 5391d806 bellard
                    buf[5] = 0;
1265 5391d806 bellard
                    buf[6] = 0;
1266 5391d806 bellard
                    buf[7] = 0;
1267 5391d806 bellard
1268 5391d806 bellard
                    buf[8] = 0x01;
1269 5391d806 bellard
                    buf[9] = 0x06;
1270 5391d806 bellard
                    buf[10] = 0x00;
1271 5391d806 bellard
                    buf[11] = 0x05;
1272 5391d806 bellard
                    buf[12] = 0x00;
1273 5391d806 bellard
                    buf[13] = 0x00;
1274 5391d806 bellard
                    buf[14] = 0x00;
1275 5391d806 bellard
                    buf[15] = 0x00;
1276 5391d806 bellard
                    ide_atapi_cmd_reply(s, 16, max_len);
1277 5391d806 bellard
                    break;
1278 fe0d6123 Thadeu Lima de Souza Cascardo
                case GPMODE_AUDIO_CTL_PAGE:
1279 fe0d6123 Thadeu Lima de Souza Cascardo
                    cpu_to_ube16(&buf[0], 24 + 6);
1280 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[2] = 0x70;
1281 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[3] = 0;
1282 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[4] = 0;
1283 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[5] = 0;
1284 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[6] = 0;
1285 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[7] = 0;
1286 fe0d6123 Thadeu Lima de Souza Cascardo
1287 fe0d6123 Thadeu Lima de Souza Cascardo
                    /* Fill with CDROM audio volume */
1288 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[17] = 0;
1289 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[19] = 0;
1290 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[21] = 0;
1291 fe0d6123 Thadeu Lima de Souza Cascardo
                    buf[23] = 0;
1292 fe0d6123 Thadeu Lima de Souza Cascardo
1293 fe0d6123 Thadeu Lima de Souza Cascardo
                    ide_atapi_cmd_reply(s, 24, max_len);
1294 fe0d6123 Thadeu Lima de Souza Cascardo
                    break;
1295 a70089ce Thadeu Lima de Souza Cascardo
                case GPMODE_CAPABILITIES_PAGE:
1296 5391d806 bellard
                    cpu_to_ube16(&buf[0], 28 + 6);
1297 5391d806 bellard
                    buf[2] = 0x70;
1298 5391d806 bellard
                    buf[3] = 0;
1299 5391d806 bellard
                    buf[4] = 0;
1300 5391d806 bellard
                    buf[5] = 0;
1301 5391d806 bellard
                    buf[6] = 0;
1302 5391d806 bellard
                    buf[7] = 0;
1303 5391d806 bellard
1304 5391d806 bellard
                    buf[8] = 0x2a;
1305 5391d806 bellard
                    buf[9] = 0x12;
1306 0d4a05a1 ths
                    buf[10] = 0x00;
1307 5391d806 bellard
                    buf[11] = 0x00;
1308 3b46e624 ths
1309 d5b4eb40 aliguori
                    /* Claim PLAY_AUDIO capability (0x01) since some Linux
1310 d5b4eb40 aliguori
                       code checks for this to automount media. */
1311 d5b4eb40 aliguori
                    buf[12] = 0x71;
1312 5391d806 bellard
                    buf[13] = 3 << 5;
1313 5391d806 bellard
                    buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
1314 caed8802 bellard
                    if (bdrv_is_locked(s->bs))
1315 5391d806 bellard
                        buf[6] |= 1 << 1;
1316 5391d806 bellard
                    buf[15] = 0x00;
1317 5391d806 bellard
                    cpu_to_ube16(&buf[16], 706);
1318 5391d806 bellard
                    buf[18] = 0;
1319 5391d806 bellard
                    buf[19] = 2;
1320 5391d806 bellard
                    cpu_to_ube16(&buf[20], 512);
1321 5391d806 bellard
                    cpu_to_ube16(&buf[22], 706);
1322 5391d806 bellard
                    buf[24] = 0;
1323 5391d806 bellard
                    buf[25] = 0;
1324 5391d806 bellard
                    buf[26] = 0;
1325 5391d806 bellard
                    buf[27] = 0;
1326 5391d806 bellard
                    ide_atapi_cmd_reply(s, 28, max_len);
1327 5391d806 bellard
                    break;
1328 5391d806 bellard
                default:
1329 5391d806 bellard
                    goto error_cmd;
1330 5391d806 bellard
                }
1331 5391d806 bellard
                break;
1332 5391d806 bellard
            case 1: /* changeable values */
1333 5391d806 bellard
                goto error_cmd;
1334 5391d806 bellard
            case 2: /* default values */
1335 5391d806 bellard
                goto error_cmd;
1336 5391d806 bellard
            default:
1337 5391d806 bellard
            case 3: /* saved values */
1338 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1339 5391d806 bellard
                                    ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
1340 5391d806 bellard
                break;
1341 5391d806 bellard
            }
1342 5391d806 bellard
        }
1343 5391d806 bellard
        break;
1344 5391d806 bellard
    case GPCMD_REQUEST_SENSE:
1345 5391d806 bellard
        max_len = packet[4];
1346 5391d806 bellard
        memset(buf, 0, 18);
1347 5391d806 bellard
        buf[0] = 0x70 | (1 << 7);
1348 5391d806 bellard
        buf[2] = s->sense_key;
1349 5391d806 bellard
        buf[7] = 10;
1350 5391d806 bellard
        buf[12] = s->asc;
1351 9118e7f0 aliguori
        if (s->sense_key == SENSE_UNIT_ATTENTION)
1352 9118e7f0 aliguori
            s->sense_key = SENSE_NONE;
1353 5391d806 bellard
        ide_atapi_cmd_reply(s, 18, max_len);
1354 5391d806 bellard
        break;
1355 5391d806 bellard
    case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
1356 caed8802 bellard
        if (bdrv_is_inserted(s->bs)) {
1357 caed8802 bellard
            bdrv_set_locked(s->bs, packet[4] & 1);
1358 5391d806 bellard
            ide_atapi_cmd_ok(s);
1359 5391d806 bellard
        } else {
1360 5fafdf24 ths
            ide_atapi_cmd_error(s, SENSE_NOT_READY,
1361 5391d806 bellard
                                ASC_MEDIUM_NOT_PRESENT);
1362 5391d806 bellard
        }
1363 5391d806 bellard
        break;
1364 5391d806 bellard
    case GPCMD_READ_10:
1365 5391d806 bellard
    case GPCMD_READ_12:
1366 5391d806 bellard
        {
1367 5391d806 bellard
            int nb_sectors, lba;
1368 5391d806 bellard
1369 5391d806 bellard
            if (packet[0] == GPCMD_READ_10)
1370 5391d806 bellard
                nb_sectors = ube16_to_cpu(packet + 7);
1371 5391d806 bellard
            else
1372 5391d806 bellard
                nb_sectors = ube32_to_cpu(packet + 6);
1373 5391d806 bellard
            lba = ube32_to_cpu(packet + 2);
1374 5391d806 bellard
            if (nb_sectors == 0) {
1375 5391d806 bellard
                ide_atapi_cmd_ok(s);
1376 5391d806 bellard
                break;
1377 5391d806 bellard
            }
1378 98087450 bellard
            ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
1379 98087450 bellard
        }
1380 98087450 bellard
        break;
1381 98087450 bellard
    case GPCMD_READ_CD:
1382 98087450 bellard
        {
1383 98087450 bellard
            int nb_sectors, lba, transfer_request;
1384 98087450 bellard
1385 98087450 bellard
            nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
1386 98087450 bellard
            lba = ube32_to_cpu(packet + 2);
1387 98087450 bellard
            if (nb_sectors == 0) {
1388 98087450 bellard
                ide_atapi_cmd_ok(s);
1389 98087450 bellard
                break;
1390 98087450 bellard
            }
1391 98087450 bellard
            transfer_request = packet[9];
1392 98087450 bellard
            switch(transfer_request & 0xf8) {
1393 98087450 bellard
            case 0x00:
1394 98087450 bellard
                /* nothing */
1395 98087450 bellard
                ide_atapi_cmd_ok(s);
1396 98087450 bellard
                break;
1397 98087450 bellard
            case 0x10:
1398 98087450 bellard
                /* normal read */
1399 98087450 bellard
                ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
1400 98087450 bellard
                break;
1401 98087450 bellard
            case 0xf8:
1402 98087450 bellard
                /* read all data */
1403 98087450 bellard
                ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
1404 98087450 bellard
                break;
1405 98087450 bellard
            default:
1406 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1407 98087450 bellard
                                    ASC_INV_FIELD_IN_CMD_PACKET);
1408 98087450 bellard
                break;
1409 98087450 bellard
            }
1410 5391d806 bellard
        }
1411 5391d806 bellard
        break;
1412 5391d806 bellard
    case GPCMD_SEEK:
1413 5391d806 bellard
        {
1414 96b8f136 ths
            unsigned int lba;
1415 96b8f136 ths
            uint64_t total_sectors;
1416 66c6ef76 bellard
1417 66c6ef76 bellard
            bdrv_get_geometry(s->bs, &total_sectors);
1418 66c6ef76 bellard
            total_sectors >>= 2;
1419 96b8f136 ths
            if (total_sectors == 0) {
1420 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
1421 5391d806 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
1422 5391d806 bellard
                break;
1423 5391d806 bellard
            }
1424 5391d806 bellard
            lba = ube32_to_cpu(packet + 2);
1425 66c6ef76 bellard
            if (lba >= total_sectors) {
1426 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1427 5391d806 bellard
                                    ASC_LOGICAL_BLOCK_OOR);
1428 5391d806 bellard
                break;
1429 5391d806 bellard
            }
1430 5391d806 bellard
            ide_atapi_cmd_ok(s);
1431 5391d806 bellard
        }
1432 5391d806 bellard
        break;
1433 5391d806 bellard
    case GPCMD_START_STOP_UNIT:
1434 5391d806 bellard
        {
1435 aea2a33c Mark McLoughlin
            int start, eject, err = 0;
1436 5391d806 bellard
            start = packet[4] & 1;
1437 5391d806 bellard
            eject = (packet[4] >> 1) & 1;
1438 3b46e624 ths
1439 aea2a33c Mark McLoughlin
            if (eject) {
1440 aea2a33c Mark McLoughlin
                err = bdrv_eject(s->bs, !start);
1441 aea2a33c Mark McLoughlin
            }
1442 aea2a33c Mark McLoughlin
1443 aea2a33c Mark McLoughlin
            switch (err) {
1444 aea2a33c Mark McLoughlin
            case 0:
1445 aea2a33c Mark McLoughlin
                ide_atapi_cmd_ok(s);
1446 aea2a33c Mark McLoughlin
                break;
1447 aea2a33c Mark McLoughlin
            case -EBUSY:
1448 aea2a33c Mark McLoughlin
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
1449 aea2a33c Mark McLoughlin
                                    ASC_MEDIA_REMOVAL_PREVENTED);
1450 aea2a33c Mark McLoughlin
                break;
1451 aea2a33c Mark McLoughlin
            default:
1452 aea2a33c Mark McLoughlin
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
1453 aea2a33c Mark McLoughlin
                                    ASC_MEDIUM_NOT_PRESENT);
1454 aea2a33c Mark McLoughlin
                break;
1455 caed8802 bellard
            }
1456 5391d806 bellard
        }
1457 5391d806 bellard
        break;
1458 5391d806 bellard
    case GPCMD_MECHANISM_STATUS:
1459 5391d806 bellard
        {
1460 5391d806 bellard
            max_len = ube16_to_cpu(packet + 8);
1461 5391d806 bellard
            cpu_to_ube16(buf, 0);
1462 5391d806 bellard
            /* no current LBA */
1463 5391d806 bellard
            buf[2] = 0;
1464 5391d806 bellard
            buf[3] = 0;
1465 5391d806 bellard
            buf[4] = 0;
1466 5391d806 bellard
            buf[5] = 1;
1467 5391d806 bellard
            cpu_to_ube16(buf + 6, 0);
1468 5391d806 bellard
            ide_atapi_cmd_reply(s, 8, max_len);
1469 5391d806 bellard
        }
1470 5391d806 bellard
        break;
1471 5391d806 bellard
    case GPCMD_READ_TOC_PMA_ATIP:
1472 5391d806 bellard
        {
1473 5391d806 bellard
            int format, msf, start_track, len;
1474 96b8f136 ths
            uint64_t total_sectors;
1475 5391d806 bellard
1476 66c6ef76 bellard
            bdrv_get_geometry(s->bs, &total_sectors);
1477 66c6ef76 bellard
            total_sectors >>= 2;
1478 96b8f136 ths
            if (total_sectors == 0) {
1479 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
1480 5391d806 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
1481 5391d806 bellard
                break;
1482 5391d806 bellard
            }
1483 5391d806 bellard
            max_len = ube16_to_cpu(packet + 7);
1484 5391d806 bellard
            format = packet[9] >> 6;
1485 5391d806 bellard
            msf = (packet[1] >> 1) & 1;
1486 5391d806 bellard
            start_track = packet[6];
1487 5391d806 bellard
            switch(format) {
1488 5391d806 bellard
            case 0:
1489 66c6ef76 bellard
                len = cdrom_read_toc(total_sectors, buf, msf, start_track);
1490 5391d806 bellard
                if (len < 0)
1491 5391d806 bellard
                    goto error_cmd;
1492 5391d806 bellard
                ide_atapi_cmd_reply(s, len, max_len);
1493 5391d806 bellard
                break;
1494 5391d806 bellard
            case 1:
1495 5391d806 bellard
                /* multi session : only a single session defined */
1496 5391d806 bellard
                memset(buf, 0, 12);
1497 5391d806 bellard
                buf[1] = 0x0a;
1498 5391d806 bellard
                buf[2] = 0x01;
1499 5391d806 bellard
                buf[3] = 0x01;
1500 5391d806 bellard
                ide_atapi_cmd_reply(s, 12, max_len);
1501 5391d806 bellard
                break;
1502 98087450 bellard
            case 2:
1503 66c6ef76 bellard
                len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
1504 98087450 bellard
                if (len < 0)
1505 98087450 bellard
                    goto error_cmd;
1506 98087450 bellard
                ide_atapi_cmd_reply(s, len, max_len);
1507 98087450 bellard
                break;
1508 5391d806 bellard
            default:
1509 7f777bf3 bellard
            error_cmd:
1510 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1511 7f777bf3 bellard
                                    ASC_INV_FIELD_IN_CMD_PACKET);
1512 7f777bf3 bellard
                break;
1513 5391d806 bellard
            }
1514 5391d806 bellard
        }
1515 5391d806 bellard
        break;
1516 5391d806 bellard
    case GPCMD_READ_CDVD_CAPACITY:
1517 66c6ef76 bellard
        {
1518 96b8f136 ths
            uint64_t total_sectors;
1519 66c6ef76 bellard
1520 66c6ef76 bellard
            bdrv_get_geometry(s->bs, &total_sectors);
1521 66c6ef76 bellard
            total_sectors >>= 2;
1522 96b8f136 ths
            if (total_sectors == 0) {
1523 5fafdf24 ths
                ide_atapi_cmd_error(s, SENSE_NOT_READY,
1524 66c6ef76 bellard
                                    ASC_MEDIUM_NOT_PRESENT);
1525 66c6ef76 bellard
                break;
1526 66c6ef76 bellard
            }
1527 66c6ef76 bellard
            /* NOTE: it is really the number of sectors minus 1 */
1528 66c6ef76 bellard
            cpu_to_ube32(buf, total_sectors - 1);
1529 66c6ef76 bellard
            cpu_to_ube32(buf + 4, 2048);
1530 66c6ef76 bellard
            ide_atapi_cmd_reply(s, 8, 8);
1531 5391d806 bellard
        }
1532 5391d806 bellard
        break;
1533 d14049ea ths
    case GPCMD_READ_DVD_STRUCTURE:
1534 d14049ea ths
        {
1535 d14049ea ths
            int media = packet[1];
1536 8114e9e8 ths
            int format = packet[7];
1537 8114e9e8 ths
            int ret;
1538 d14049ea ths
1539 8114e9e8 ths
            max_len = ube16_to_cpu(packet + 8);
1540 d14049ea ths
1541 8114e9e8 ths
            if (format < 0xff) {
1542 8114e9e8 ths
                if (media_is_cd(s)) {
1543 8114e9e8 ths
                    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1544 8114e9e8 ths
                                        ASC_INCOMPATIBLE_FORMAT);
1545 8114e9e8 ths
                    break;
1546 8114e9e8 ths
                } else if (!media_present(s)) {
1547 8114e9e8 ths
                    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1548 8114e9e8 ths
                                        ASC_INV_FIELD_IN_CMD_PACKET);
1549 8114e9e8 ths
                    break;
1550 8114e9e8 ths
                }
1551 8114e9e8 ths
            }
1552 d14049ea ths
1553 8114e9e8 ths
            memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
1554 8114e9e8 ths
                   IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
1555 d14049ea ths
1556 8114e9e8 ths
            switch (format) {
1557 8114e9e8 ths
                case 0x00 ... 0x7f:
1558 8114e9e8 ths
                case 0xff:
1559 8114e9e8 ths
                    if (media == 0) {
1560 8114e9e8 ths
                        ret = ide_dvd_read_structure(s, format, packet, buf);
1561 d14049ea ths
1562 8114e9e8 ths
                        if (ret < 0)
1563 8114e9e8 ths
                            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, -ret);
1564 8114e9e8 ths
                        else
1565 8114e9e8 ths
                            ide_atapi_cmd_reply(s, ret, max_len);
1566 d14049ea ths
1567 8114e9e8 ths
                        break;
1568 8114e9e8 ths
                    }
1569 8114e9e8 ths
                    /* TODO: BD support, fall through for now */
1570 8114e9e8 ths
1571 8114e9e8 ths
                /* Generic disk structures */
1572 8114e9e8 ths
                case 0x80: /* TODO: AACS volume identifier */
1573 8114e9e8 ths
                case 0x81: /* TODO: AACS media serial number */
1574 8114e9e8 ths
                case 0x82: /* TODO: AACS media identifier */
1575 8114e9e8 ths
                case 0x83: /* TODO: AACS media key block */
1576 8114e9e8 ths
                case 0x90: /* TODO: List of recognized format layers */
1577 8114e9e8 ths
                case 0xc0: /* TODO: Write protection status */
1578 d14049ea ths
                default:
1579 d14049ea ths
                    ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1580 d14049ea ths
                                        ASC_INV_FIELD_IN_CMD_PACKET);
1581 d14049ea ths
                    break;
1582 d14049ea ths
            }
1583 d14049ea ths
        }
1584 d14049ea ths
        break;
1585 d14049ea ths
    case GPCMD_SET_SPEED:
1586 d14049ea ths
        ide_atapi_cmd_ok(s);
1587 d14049ea ths
        break;
1588 bd0d90b2 bellard
    case GPCMD_INQUIRY:
1589 bd0d90b2 bellard
        max_len = packet[4];
1590 bd0d90b2 bellard
        buf[0] = 0x05; /* CD-ROM */
1591 bd0d90b2 bellard
        buf[1] = 0x80; /* removable */
1592 bd0d90b2 bellard
        buf[2] = 0x00; /* ISO */
1593 bd0d90b2 bellard
        buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
1594 aa1f17c1 ths
        buf[4] = 31; /* additional length */
1595 bd0d90b2 bellard
        buf[5] = 0; /* reserved */
1596 bd0d90b2 bellard
        buf[6] = 0; /* reserved */
1597 bd0d90b2 bellard
        buf[7] = 0; /* reserved */
1598 bd0d90b2 bellard
        padstr8(buf + 8, 8, "QEMU");
1599 38cdea7c balrog
        padstr8(buf + 16, 16, "QEMU DVD-ROM");
1600 47c06340 Gerd Hoffmann
        padstr8(buf + 32, 4, s->version);
1601 bd0d90b2 bellard
        ide_atapi_cmd_reply(s, 36, max_len);
1602 bd0d90b2 bellard
        break;
1603 d14049ea ths
    case GPCMD_GET_CONFIGURATION:
1604 d14049ea ths
        {
1605 38cdea7c balrog
            uint32_t len;
1606 091d055b balrog
            uint8_t index = 0;
1607 d14049ea ths
1608 d14049ea ths
            /* only feature 0 is supported */
1609 d14049ea ths
            if (packet[2] != 0 || packet[3] != 0) {
1610 d14049ea ths
                ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1611 d14049ea ths
                                    ASC_INV_FIELD_IN_CMD_PACKET);
1612 d14049ea ths
                break;
1613 d14049ea ths
            }
1614 38cdea7c balrog
1615 38cdea7c balrog
            /* XXX: could result in alignment problems in some architectures */
1616 38cdea7c balrog
            max_len = ube16_to_cpu(packet + 7);
1617 091d055b balrog
1618 38cdea7c balrog
            /*
1619 091d055b balrog
             * XXX: avoid overflow for io_buffer if max_len is bigger than
1620 091d055b balrog
             *      the size of that buffer (dimensioned to max number of
1621 091d055b balrog
             *      sectors to transfer at once)
1622 38cdea7c balrog
             *
1623 091d055b balrog
             *      Only a problem if the feature/profiles grow.
1624 38cdea7c balrog
             */
1625 38cdea7c balrog
            if (max_len > 512) /* XXX: assume 1 sector */
1626 38cdea7c balrog
                max_len = 512;
1627 38cdea7c balrog
1628 38cdea7c balrog
            memset(buf, 0, max_len);
1629 38cdea7c balrog
            /* 
1630 38cdea7c balrog
             * the number of sectors from the media tells us which profile
1631 38cdea7c balrog
             * to use as current.  0 means there is no media
1632 38cdea7c balrog
             */
1633 8114e9e8 ths
            if (media_is_dvd(s))
1634 8114e9e8 ths
                cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
1635 8114e9e8 ths
            else if (media_is_cd(s))
1636 8114e9e8 ths
                cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
1637 38cdea7c balrog
1638 091d055b balrog
            buf[10] = 0x02 | 0x01; /* persistent and current */
1639 091d055b balrog
            len = 12; /* headers: 8 + 4 */
1640 091d055b balrog
            len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
1641 091d055b balrog
            len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
1642 38cdea7c balrog
            cpu_to_ube32(buf, len - 4); /* data length */
1643 38cdea7c balrog
1644 38cdea7c balrog
            ide_atapi_cmd_reply(s, len, max_len);
1645 d14049ea ths
            break;
1646 d14049ea ths
        }
1647 253cb7b9 Aurelien Jarno
    case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
1648 253cb7b9 Aurelien Jarno
        max_len = ube16_to_cpu(packet + 7);
1649 253cb7b9 Aurelien Jarno
1650 253cb7b9 Aurelien Jarno
        if (packet[1] & 0x01) { /* polling */
1651 253cb7b9 Aurelien Jarno
            /* We don't support any event class (yet). */
1652 253cb7b9 Aurelien Jarno
            cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
1653 253cb7b9 Aurelien Jarno
            buf[2] = 0x80;           /* No Event Available (NEA) */
1654 253cb7b9 Aurelien Jarno
            buf[3] = 0x00;           /* Empty supported event classes */
1655 253cb7b9 Aurelien Jarno
            ide_atapi_cmd_reply(s, 4, max_len);
1656 253cb7b9 Aurelien Jarno
        } else { /* asynchronous mode */
1657 253cb7b9 Aurelien Jarno
            /* Only polling is supported, asynchronous mode is not. */
1658 253cb7b9 Aurelien Jarno
            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1659 253cb7b9 Aurelien Jarno
                                ASC_INV_FIELD_IN_CMD_PACKET);
1660 253cb7b9 Aurelien Jarno
        }
1661 253cb7b9 Aurelien Jarno
        break;
1662 5391d806 bellard
    default:
1663 5fafdf24 ths
        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
1664 7f777bf3 bellard
                            ASC_ILLEGAL_OPCODE);
1665 5391d806 bellard
        break;
1666 5391d806 bellard
    }
1667 5391d806 bellard
}
1668 5391d806 bellard
1669 201a51fc balrog
static void ide_cfata_metadata_inquiry(IDEState *s)
1670 201a51fc balrog
{
1671 201a51fc balrog
    uint16_t *p;
1672 201a51fc balrog
    uint32_t spd;
1673 201a51fc balrog
1674 201a51fc balrog
    p = (uint16_t *) s->io_buffer;
1675 201a51fc balrog
    memset(p, 0, 0x200);
1676 201a51fc balrog
    spd = ((s->mdata_size - 1) >> 9) + 1;
1677 201a51fc balrog
1678 201a51fc balrog
    put_le16(p + 0, 0x0001);                        /* Data format revision */
1679 201a51fc balrog
    put_le16(p + 1, 0x0000);                        /* Media property: silicon */
1680 201a51fc balrog
    put_le16(p + 2, s->media_changed);                /* Media status */
1681 201a51fc balrog
    put_le16(p + 3, s->mdata_size & 0xffff);        /* Capacity in bytes (low) */
1682 201a51fc balrog
    put_le16(p + 4, s->mdata_size >> 16);        /* Capacity in bytes (high) */
1683 201a51fc balrog
    put_le16(p + 5, spd & 0xffff);                /* Sectors per device (low) */
1684 201a51fc balrog
    put_le16(p + 6, spd >> 16);                        /* Sectors per device (high) */
1685 201a51fc balrog
}
1686 201a51fc balrog
1687 201a51fc balrog
static void ide_cfata_metadata_read(IDEState *s)
1688 201a51fc balrog
{
1689 201a51fc balrog
    uint16_t *p;
1690 201a51fc balrog
1691 201a51fc balrog
    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
1692 201a51fc balrog
        s->status = ERR_STAT;
1693 201a51fc balrog
        s->error = ABRT_ERR;
1694 201a51fc balrog
        return;
1695 201a51fc balrog
    }
1696 201a51fc balrog
1697 201a51fc balrog
    p = (uint16_t *) s->io_buffer;
1698 201a51fc balrog
    memset(p, 0, 0x200);
1699 201a51fc balrog
1700 201a51fc balrog
    put_le16(p + 0, s->media_changed);                /* Media status */
1701 201a51fc balrog
    memcpy(p + 1, s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
1702 201a51fc balrog
                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
1703 201a51fc balrog
                                    s->nsector << 9), 0x200 - 2));
1704 201a51fc balrog
}
1705 201a51fc balrog
1706 201a51fc balrog
static void ide_cfata_metadata_write(IDEState *s)
1707 201a51fc balrog
{
1708 201a51fc balrog
    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
1709 201a51fc balrog
        s->status = ERR_STAT;
1710 201a51fc balrog
        s->error = ABRT_ERR;
1711 201a51fc balrog
        return;
1712 201a51fc balrog
    }
1713 201a51fc balrog
1714 201a51fc balrog
    s->media_changed = 0;
1715 201a51fc balrog
1716 201a51fc balrog
    memcpy(s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
1717 201a51fc balrog
                    s->io_buffer + 2,
1718 201a51fc balrog
                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
1719 201a51fc balrog
                                    s->nsector << 9), 0x200 - 2));
1720 201a51fc balrog
}
1721 201a51fc balrog
1722 bd491d6a ths
/* called when the inserted state of the media has changed */
1723 bd491d6a ths
static void cdrom_change_cb(void *opaque)
1724 bd491d6a ths
{
1725 bd491d6a ths
    IDEState *s = opaque;
1726 96b8f136 ths
    uint64_t nb_sectors;
1727 bd491d6a ths
1728 bd491d6a ths
    bdrv_get_geometry(s->bs, &nb_sectors);
1729 bd491d6a ths
    s->nb_sectors = nb_sectors;
1730 9118e7f0 aliguori
1731 9118e7f0 aliguori
    s->sense_key = SENSE_UNIT_ATTENTION;
1732 9118e7f0 aliguori
    s->asc = ASC_MEDIUM_MAY_HAVE_CHANGED;
1733 93c8cfd9 Gleb Natapov
    s->cdrom_changed = 1;
1734 9cdd03a7 Gerd Hoffmann
    ide_set_irq(s->bus);
1735 bd491d6a ths
}
1736 bd491d6a ths
1737 c2ff060f bellard
static void ide_cmd_lba48_transform(IDEState *s, int lba48)
1738 c2ff060f bellard
{
1739 c2ff060f bellard
    s->lba48 = lba48;
1740 c2ff060f bellard
1741 c2ff060f bellard
    /* handle the 'magic' 0 nsector count conversion here. to avoid
1742 c2ff060f bellard
     * fiddling with the rest of the read logic, we just store the
1743 c2ff060f bellard
     * full sector count in ->nsector and ignore ->hob_nsector from now
1744 c2ff060f bellard
     */
1745 c2ff060f bellard
    if (!s->lba48) {
1746 c2ff060f bellard
        if (!s->nsector)
1747 c2ff060f bellard
            s->nsector = 256;
1748 c2ff060f bellard
    } else {
1749 c2ff060f bellard
        if (!s->nsector && !s->hob_nsector)
1750 c2ff060f bellard
            s->nsector = 65536;
1751 c2ff060f bellard
        else {
1752 c2ff060f bellard
            int lo = s->nsector;
1753 c2ff060f bellard
            int hi = s->hob_nsector;
1754 c2ff060f bellard
1755 c2ff060f bellard
            s->nsector = (hi << 8) | lo;
1756 c2ff060f bellard
        }
1757 c2ff060f bellard
    }
1758 c2ff060f bellard
}
1759 c2ff060f bellard
1760 bcbdc4d3 Gerd Hoffmann
static void ide_clear_hob(IDEBus *bus)
1761 c2ff060f bellard
{
1762 c2ff060f bellard
    /* any write clears HOB high bit of device control register */
1763 bcbdc4d3 Gerd Hoffmann
    bus->ifs[0].select &= ~(1 << 7);
1764 bcbdc4d3 Gerd Hoffmann
    bus->ifs[1].select &= ~(1 << 7);
1765 c2ff060f bellard
}
1766 c2ff060f bellard
1767 356721ae Gerd Hoffmann
void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1768 caed8802 bellard
{
1769 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
1770 c45c3d00 bellard
    IDEState *s;
1771 bcbdc4d3 Gerd Hoffmann
    int n;
1772 c2ff060f bellard
    int lba48 = 0;
1773 5391d806 bellard
1774 5391d806 bellard
#ifdef DEBUG_IDE
1775 5391d806 bellard
    printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
1776 5391d806 bellard
#endif
1777 c2ff060f bellard
1778 5391d806 bellard
    addr &= 7;
1779 fcdd25ab aliguori
1780 fcdd25ab aliguori
    /* ignore writes to command block while busy with previous command */
1781 bcbdc4d3 Gerd Hoffmann
    if (addr != 7 && (idebus_active_if(bus)->status & (BUSY_STAT|DRQ_STAT)))
1782 fcdd25ab aliguori
        return;
1783 fcdd25ab aliguori
1784 5391d806 bellard
    switch(addr) {
1785 5391d806 bellard
    case 0:
1786 5391d806 bellard
        break;
1787 5391d806 bellard
    case 1:
1788 bcbdc4d3 Gerd Hoffmann
        ide_clear_hob(bus);
1789 c45c3d00 bellard
        /* NOTE: data is written to the two drives */
1790 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hob_feature = bus->ifs[0].feature;
1791 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hob_feature = bus->ifs[1].feature;
1792 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].feature = val;
1793 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].feature = val;
1794 5391d806 bellard
        break;
1795 5391d806 bellard
    case 2:
1796 bcbdc4d3 Gerd Hoffmann
        ide_clear_hob(bus);
1797 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hob_nsector = bus->ifs[0].nsector;
1798 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hob_nsector = bus->ifs[1].nsector;
1799 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].nsector = val;
1800 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].nsector = val;
1801 5391d806 bellard
        break;
1802 5391d806 bellard
    case 3:
1803 bcbdc4d3 Gerd Hoffmann
        ide_clear_hob(bus);
1804 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hob_sector = bus->ifs[0].sector;
1805 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hob_sector = bus->ifs[1].sector;
1806 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].sector = val;
1807 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].sector = val;
1808 5391d806 bellard
        break;
1809 5391d806 bellard
    case 4:
1810 bcbdc4d3 Gerd Hoffmann
        ide_clear_hob(bus);
1811 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hob_lcyl = bus->ifs[0].lcyl;
1812 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hob_lcyl = bus->ifs[1].lcyl;
1813 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].lcyl = val;
1814 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].lcyl = val;
1815 5391d806 bellard
        break;
1816 5391d806 bellard
    case 5:
1817 bcbdc4d3 Gerd Hoffmann
        ide_clear_hob(bus);
1818 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hob_hcyl = bus->ifs[0].hcyl;
1819 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hob_hcyl = bus->ifs[1].hcyl;
1820 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].hcyl = val;
1821 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].hcyl = val;
1822 5391d806 bellard
        break;
1823 5391d806 bellard
    case 6:
1824 c2ff060f bellard
        /* FIXME: HOB readback uses bit 7 */
1825 bcbdc4d3 Gerd Hoffmann
        bus->ifs[0].select = (val & ~0x10) | 0xa0;
1826 bcbdc4d3 Gerd Hoffmann
        bus->ifs[1].select = (val | 0x10) | 0xa0;
1827 5391d806 bellard
        /* select drive */
1828 bcbdc4d3 Gerd Hoffmann
        bus->unit = (val >> 4) & 1;
1829 5391d806 bellard
        break;
1830 5391d806 bellard
    default:
1831 5391d806 bellard
    case 7:
1832 5391d806 bellard
        /* command */
1833 5391d806 bellard
#if defined(DEBUG_IDE)
1834 5391d806 bellard
        printf("ide: CMD=%02x\n", val);
1835 5391d806 bellard
#endif
1836 bcbdc4d3 Gerd Hoffmann
        s = idebus_active_if(bus);
1837 66201e2d bellard
        /* ignore commands to non existant slave */
1838 bcbdc4d3 Gerd Hoffmann
        if (s != bus->ifs && !s->bs)
1839 66201e2d bellard
            break;
1840 c2ff060f bellard
1841 fcdd25ab aliguori
        /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */
1842 fcdd25ab aliguori
        if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)
1843 fcdd25ab aliguori
            break;
1844 fcdd25ab aliguori
1845 5391d806 bellard
        switch(val) {
1846 5391d806 bellard
        case WIN_IDENTIFY:
1847 cd8722bb Markus Armbruster
            if (s->bs && s->drive_kind != IDE_CD) {
1848 cd8722bb Markus Armbruster
                if (s->drive_kind != IDE_CFATA)
1849 201a51fc balrog
                    ide_identify(s);
1850 201a51fc balrog
                else
1851 201a51fc balrog
                    ide_cfata_identify(s);
1852 2a282056 bellard
                s->status = READY_STAT | SEEK_STAT;
1853 5391d806 bellard
                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1854 5391d806 bellard
            } else {
1855 cd8722bb Markus Armbruster
                if (s->drive_kind == IDE_CD) {
1856 5391d806 bellard
                    ide_set_signature(s);
1857 5391d806 bellard
                }
1858 5391d806 bellard
                ide_abort_command(s);
1859 5391d806 bellard
            }
1860 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1861 5391d806 bellard
            break;
1862 5391d806 bellard
        case WIN_SPECIFY:
1863 5391d806 bellard
        case WIN_RECAL:
1864 a136e5a8 bellard
            s->error = 0;
1865 769bec72 bellard
            s->status = READY_STAT | SEEK_STAT;
1866 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1867 5391d806 bellard
            break;
1868 5391d806 bellard
        case WIN_SETMULT:
1869 cd8722bb Markus Armbruster
            if (s->drive_kind == IDE_CFATA && s->nsector == 0) {
1870 201a51fc balrog
                /* Disable Read and Write Multiple */
1871 201a51fc balrog
                s->mult_sectors = 0;
1872 41a2b959 aliguori
                s->status = READY_STAT | SEEK_STAT;
1873 201a51fc balrog
            } else if ((s->nsector & 0xff) != 0 &&
1874 39dfc926 ths
                ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
1875 39dfc926 ths
                 (s->nsector & (s->nsector - 1)) != 0)) {
1876 5391d806 bellard
                ide_abort_command(s);
1877 5391d806 bellard
            } else {
1878 292eef5a ths
                s->mult_sectors = s->nsector & 0xff;
1879 41a2b959 aliguori
                s->status = READY_STAT | SEEK_STAT;
1880 5391d806 bellard
            }
1881 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1882 5391d806 bellard
            break;
1883 c2ff060f bellard
        case WIN_VERIFY_EXT:
1884 c2ff060f bellard
            lba48 = 1;
1885 4ce900b4 bellard
        case WIN_VERIFY:
1886 4ce900b4 bellard
        case WIN_VERIFY_ONCE:
1887 4ce900b4 bellard
            /* do sector number check ? */
1888 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1889 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
1890 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1891 4ce900b4 bellard
            break;
1892 c2ff060f bellard
        case WIN_READ_EXT:
1893 c2ff060f bellard
            lba48 = 1;
1894 5391d806 bellard
        case WIN_READ:
1895 5391d806 bellard
        case WIN_READ_ONCE:
1896 5fafdf24 ths
            if (!s->bs)
1897 6b136f9e bellard
                goto abort_cmd;
1898 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1899 5391d806 bellard
            s->req_nb_sectors = 1;
1900 5391d806 bellard
            ide_sector_read(s);
1901 5391d806 bellard
            break;
1902 c2ff060f bellard
        case WIN_WRITE_EXT:
1903 c2ff060f bellard
            lba48 = 1;
1904 5391d806 bellard
        case WIN_WRITE:
1905 5391d806 bellard
        case WIN_WRITE_ONCE:
1906 201a51fc balrog
        case CFA_WRITE_SECT_WO_ERASE:
1907 201a51fc balrog
        case WIN_WRITE_VERIFY:
1908 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1909 a136e5a8 bellard
            s->error = 0;
1910 f66723fa bellard
            s->status = SEEK_STAT | READY_STAT;
1911 5391d806 bellard
            s->req_nb_sectors = 1;
1912 5391d806 bellard
            ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
1913 201a51fc balrog
            s->media_changed = 1;
1914 5391d806 bellard
            break;
1915 c2ff060f bellard
        case WIN_MULTREAD_EXT:
1916 c2ff060f bellard
            lba48 = 1;
1917 5391d806 bellard
        case WIN_MULTREAD:
1918 5391d806 bellard
            if (!s->mult_sectors)
1919 5391d806 bellard
                goto abort_cmd;
1920 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1921 5391d806 bellard
            s->req_nb_sectors = s->mult_sectors;
1922 5391d806 bellard
            ide_sector_read(s);
1923 5391d806 bellard
            break;
1924 c2ff060f bellard
        case WIN_MULTWRITE_EXT:
1925 c2ff060f bellard
            lba48 = 1;
1926 5391d806 bellard
        case WIN_MULTWRITE:
1927 201a51fc balrog
        case CFA_WRITE_MULTI_WO_ERASE:
1928 5391d806 bellard
            if (!s->mult_sectors)
1929 5391d806 bellard
                goto abort_cmd;
1930 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1931 a136e5a8 bellard
            s->error = 0;
1932 f66723fa bellard
            s->status = SEEK_STAT | READY_STAT;
1933 5391d806 bellard
            s->req_nb_sectors = s->mult_sectors;
1934 5391d806 bellard
            n = s->nsector;
1935 5391d806 bellard
            if (n > s->req_nb_sectors)
1936 5391d806 bellard
                n = s->req_nb_sectors;
1937 5391d806 bellard
            ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
1938 201a51fc balrog
            s->media_changed = 1;
1939 5391d806 bellard
            break;
1940 c2ff060f bellard
        case WIN_READDMA_EXT:
1941 c2ff060f bellard
            lba48 = 1;
1942 98087450 bellard
        case WIN_READDMA:
1943 98087450 bellard
        case WIN_READDMA_ONCE:
1944 5fafdf24 ths
            if (!s->bs)
1945 98087450 bellard
                goto abort_cmd;
1946 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1947 98087450 bellard
            ide_sector_read_dma(s);
1948 98087450 bellard
            break;
1949 c2ff060f bellard
        case WIN_WRITEDMA_EXT:
1950 c2ff060f bellard
            lba48 = 1;
1951 98087450 bellard
        case WIN_WRITEDMA:
1952 98087450 bellard
        case WIN_WRITEDMA_ONCE:
1953 5fafdf24 ths
            if (!s->bs)
1954 98087450 bellard
                goto abort_cmd;
1955 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1956 98087450 bellard
            ide_sector_write_dma(s);
1957 201a51fc balrog
            s->media_changed = 1;
1958 98087450 bellard
            break;
1959 c2ff060f bellard
        case WIN_READ_NATIVE_MAX_EXT:
1960 c2ff060f bellard
            lba48 = 1;
1961 5391d806 bellard
        case WIN_READ_NATIVE_MAX:
1962 c2ff060f bellard
            ide_cmd_lba48_transform(s, lba48);
1963 5391d806 bellard
            ide_set_sector(s, s->nb_sectors - 1);
1964 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
1965 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1966 5391d806 bellard
            break;
1967 a136e5a8 bellard
        case WIN_CHECKPOWERMODE1:
1968 201a51fc balrog
        case WIN_CHECKPOWERMODE2:
1969 a136e5a8 bellard
            s->nsector = 0xff; /* device active or idle */
1970 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
1971 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
1972 a136e5a8 bellard
            break;
1973 34e538ae bellard
        case WIN_SETFEATURES:
1974 34e538ae bellard
            if (!s->bs)
1975 34e538ae bellard
                goto abort_cmd;
1976 34e538ae bellard
            /* XXX: valid for CDROM ? */
1977 34e538ae bellard
            switch(s->feature) {
1978 e1f63470 ths
            case 0xcc: /* reverting to power-on defaults enable */
1979 e1f63470 ths
            case 0x66: /* reverting to power-on defaults disable */
1980 34e538ae bellard
            case 0x02: /* write cache enable */
1981 34e538ae bellard
            case 0x82: /* write cache disable */
1982 34e538ae bellard
            case 0xaa: /* read look-ahead enable */
1983 34e538ae bellard
            case 0x55: /* read look-ahead disable */
1984 201a51fc balrog
            case 0x05: /* set advanced power management mode */
1985 201a51fc balrog
            case 0x85: /* disable advanced power management mode */
1986 201a51fc balrog
            case 0x69: /* NOP */
1987 201a51fc balrog
            case 0x67: /* NOP */
1988 201a51fc balrog
            case 0x96: /* NOP */
1989 201a51fc balrog
            case 0x9a: /* NOP */
1990 c3e88d8c ths
            case 0x42: /* enable Automatic Acoustic Mode */
1991 c3e88d8c ths
            case 0xc2: /* disable Automatic Acoustic Mode */
1992 e0fe67aa bellard
                s->status = READY_STAT | SEEK_STAT;
1993 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
1994 34e538ae bellard
                break;
1995 94458802 bellard
            case 0x03: { /* set transfer mode */
1996 94458802 bellard
                uint8_t val = s->nsector & 0x07;
1997 96c35ceb Juan Quintela
                uint16_t *identify_data = (uint16_t *)s->identify_data;
1998 94458802 bellard
1999 94458802 bellard
                switch (s->nsector >> 3) {
2000 94458802 bellard
                    case 0x00: /* pio default */
2001 94458802 bellard
                    case 0x01: /* pio mode */
2002 96c35ceb Juan Quintela
                        put_le16(identify_data + 62,0x07);
2003 96c35ceb Juan Quintela
                        put_le16(identify_data + 63,0x07);
2004 96c35ceb Juan Quintela
                        put_le16(identify_data + 88,0x3f);
2005 d1b5c20d ths
                        break;
2006 d1b5c20d ths
                    case 0x02: /* sigle word dma mode*/
2007 96c35ceb Juan Quintela
                        put_le16(identify_data + 62,0x07 | (1 << (val + 8)));
2008 96c35ceb Juan Quintela
                        put_le16(identify_data + 63,0x07);
2009 96c35ceb Juan Quintela
                        put_le16(identify_data + 88,0x3f);
2010 94458802 bellard
                        break;
2011 94458802 bellard
                    case 0x04: /* mdma mode */
2012 96c35ceb Juan Quintela
                        put_le16(identify_data + 62,0x07);
2013 96c35ceb Juan Quintela
                        put_le16(identify_data + 63,0x07 | (1 << (val + 8)));
2014 96c35ceb Juan Quintela
                        put_le16(identify_data + 88,0x3f);
2015 94458802 bellard
                        break;
2016 94458802 bellard
                    case 0x08: /* udma mode */
2017 96c35ceb Juan Quintela
                        put_le16(identify_data + 62,0x07);
2018 96c35ceb Juan Quintela
                        put_le16(identify_data + 63,0x07);
2019 96c35ceb Juan Quintela
                        put_le16(identify_data + 88,0x3f | (1 << (val + 8)));
2020 94458802 bellard
                        break;
2021 94458802 bellard
                    default:
2022 94458802 bellard
                        goto abort_cmd;
2023 94458802 bellard
                }
2024 94458802 bellard
                s->status = READY_STAT | SEEK_STAT;
2025 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2026 94458802 bellard
                break;
2027 94458802 bellard
            }
2028 34e538ae bellard
            default:
2029 34e538ae bellard
                goto abort_cmd;
2030 34e538ae bellard
            }
2031 34e538ae bellard
            break;
2032 c2ff060f bellard
        case WIN_FLUSH_CACHE:
2033 c2ff060f bellard
        case WIN_FLUSH_CACHE_EXT:
2034 7a6cba61 pbrook
            if (s->bs)
2035 b0484ae4 Christoph Hellwig
                bdrv_aio_flush(s->bs, ide_flush_cb, s);
2036 b0484ae4 Christoph Hellwig
            else
2037 b0484ae4 Christoph Hellwig
                ide_flush_cb(s, 0);
2038 7a6cba61 pbrook
            break;
2039 c3e88d8c ths
        case WIN_STANDBY:
2040 c3e88d8c ths
        case WIN_STANDBY2:
2041 c3e88d8c ths
        case WIN_STANDBYNOW1:
2042 201a51fc balrog
        case WIN_STANDBYNOW2:
2043 c451ee71 bellard
        case WIN_IDLEIMMEDIATE:
2044 201a51fc balrog
        case CFA_IDLEIMMEDIATE:
2045 201a51fc balrog
        case WIN_SETIDLE1:
2046 201a51fc balrog
        case WIN_SETIDLE2:
2047 c3e88d8c ths
        case WIN_SLEEPNOW1:
2048 c3e88d8c ths
        case WIN_SLEEPNOW2:
2049 c3e88d8c ths
            s->status = READY_STAT;
2050 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2051 a7dfe172 bellard
            break;
2052 4fbfcd6d aurel32
        case WIN_SEEK:
2053 cd8722bb Markus Armbruster
            if(s->drive_kind == IDE_CD)
2054 4fbfcd6d aurel32
                goto abort_cmd;
2055 4fbfcd6d aurel32
            /* XXX: Check that seek is within bounds */
2056 4fbfcd6d aurel32
            s->status = READY_STAT | SEEK_STAT;
2057 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2058 4fbfcd6d aurel32
            break;
2059 5391d806 bellard
            /* ATAPI commands */
2060 5391d806 bellard
        case WIN_PIDENTIFY:
2061 cd8722bb Markus Armbruster
            if (s->drive_kind == IDE_CD) {
2062 5391d806 bellard
                ide_atapi_identify(s);
2063 1298fe63 bellard
                s->status = READY_STAT | SEEK_STAT;
2064 5391d806 bellard
                ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
2065 5391d806 bellard
            } else {
2066 5391d806 bellard
                ide_abort_command(s);
2067 5391d806 bellard
            }
2068 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2069 5391d806 bellard
            break;
2070 c451ee71 bellard
        case WIN_DIAGNOSE:
2071 c451ee71 bellard
            ide_set_signature(s);
2072 cd8722bb Markus Armbruster
            if (s->drive_kind == IDE_CD)
2073 33256a25 aliguori
                s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet
2074 33256a25 aliguori
                                * devices to return a clear status register
2075 33256a25 aliguori
                                * with READY_STAT *not* set. */
2076 33256a25 aliguori
            else
2077 33256a25 aliguori
                s->status = READY_STAT | SEEK_STAT;
2078 33256a25 aliguori
            s->error = 0x01; /* Device 0 passed, Device 1 passed or not
2079 33256a25 aliguori
                              * present. 
2080 33256a25 aliguori
                              */
2081 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2082 c451ee71 bellard
            break;
2083 5391d806 bellard
        case WIN_SRST:
2084 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CD)
2085 5391d806 bellard
                goto abort_cmd;
2086 5391d806 bellard
            ide_set_signature(s);
2087 6b136f9e bellard
            s->status = 0x00; /* NOTE: READY is _not_ set */
2088 5391d806 bellard
            s->error = 0x01;
2089 5391d806 bellard
            break;
2090 5391d806 bellard
        case WIN_PACKETCMD:
2091 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CD)
2092 5391d806 bellard
                goto abort_cmd;
2093 98087450 bellard
            /* overlapping commands not supported */
2094 98087450 bellard
            if (s->feature & 0x02)
2095 5391d806 bellard
                goto abort_cmd;
2096 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
2097 98087450 bellard
            s->atapi_dma = s->feature & 1;
2098 5391d806 bellard
            s->nsector = 1;
2099 5fafdf24 ths
            ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
2100 5391d806 bellard
                               ide_atapi_cmd);
2101 5391d806 bellard
            break;
2102 201a51fc balrog
        /* CF-ATA commands */
2103 201a51fc balrog
        case CFA_REQ_EXT_ERROR_CODE:
2104 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CFATA)
2105 201a51fc balrog
                goto abort_cmd;
2106 201a51fc balrog
            s->error = 0x09;    /* miscellaneous error */
2107 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
2108 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2109 201a51fc balrog
            break;
2110 201a51fc balrog
        case CFA_ERASE_SECTORS:
2111 201a51fc balrog
        case CFA_WEAR_LEVEL:
2112 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CFATA)
2113 201a51fc balrog
                goto abort_cmd;
2114 201a51fc balrog
            if (val == CFA_WEAR_LEVEL)
2115 201a51fc balrog
                s->nsector = 0;
2116 201a51fc balrog
            if (val == CFA_ERASE_SECTORS)
2117 201a51fc balrog
                s->media_changed = 1;
2118 201a51fc balrog
            s->error = 0x00;
2119 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
2120 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2121 201a51fc balrog
            break;
2122 201a51fc balrog
        case CFA_TRANSLATE_SECTOR:
2123 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CFATA)
2124 201a51fc balrog
                goto abort_cmd;
2125 201a51fc balrog
            s->error = 0x00;
2126 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
2127 201a51fc balrog
            memset(s->io_buffer, 0, 0x200);
2128 201a51fc balrog
            s->io_buffer[0x00] = s->hcyl;                        /* Cyl MSB */
2129 201a51fc balrog
            s->io_buffer[0x01] = s->lcyl;                        /* Cyl LSB */
2130 201a51fc balrog
            s->io_buffer[0x02] = s->select;                        /* Head */
2131 201a51fc balrog
            s->io_buffer[0x03] = s->sector;                        /* Sector */
2132 201a51fc balrog
            s->io_buffer[0x04] = ide_get_sector(s) >> 16;        /* LBA MSB */
2133 201a51fc balrog
            s->io_buffer[0x05] = ide_get_sector(s) >> 8;        /* LBA */
2134 201a51fc balrog
            s->io_buffer[0x06] = ide_get_sector(s) >> 0;        /* LBA LSB */
2135 201a51fc balrog
            s->io_buffer[0x13] = 0x00;                                /* Erase flag */
2136 201a51fc balrog
            s->io_buffer[0x18] = 0x00;                                /* Hot count */
2137 201a51fc balrog
            s->io_buffer[0x19] = 0x00;                                /* Hot count */
2138 201a51fc balrog
            s->io_buffer[0x1a] = 0x01;                                /* Hot count */
2139 201a51fc balrog
            ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2140 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2141 201a51fc balrog
            break;
2142 201a51fc balrog
        case CFA_ACCESS_METADATA_STORAGE:
2143 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CFATA)
2144 201a51fc balrog
                goto abort_cmd;
2145 201a51fc balrog
            switch (s->feature) {
2146 201a51fc balrog
            case 0x02:        /* Inquiry Metadata Storage */
2147 201a51fc balrog
                ide_cfata_metadata_inquiry(s);
2148 201a51fc balrog
                break;
2149 201a51fc balrog
            case 0x03:        /* Read Metadata Storage */
2150 201a51fc balrog
                ide_cfata_metadata_read(s);
2151 201a51fc balrog
                break;
2152 201a51fc balrog
            case 0x04:        /* Write Metadata Storage */
2153 201a51fc balrog
                ide_cfata_metadata_write(s);
2154 201a51fc balrog
                break;
2155 201a51fc balrog
            default:
2156 201a51fc balrog
                goto abort_cmd;
2157 201a51fc balrog
            }
2158 201a51fc balrog
            ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2159 201a51fc balrog
            s->status = 0x00; /* NOTE: READY is _not_ set */
2160 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2161 201a51fc balrog
            break;
2162 201a51fc balrog
        case IBM_SENSE_CONDITION:
2163 cd8722bb Markus Armbruster
            if (s->drive_kind != IDE_CFATA)
2164 201a51fc balrog
                goto abort_cmd;
2165 201a51fc balrog
            switch (s->feature) {
2166 201a51fc balrog
            case 0x01:  /* sense temperature in device */
2167 201a51fc balrog
                s->nsector = 0x50;      /* +20 C */
2168 201a51fc balrog
                break;
2169 201a51fc balrog
            default:
2170 201a51fc balrog
                goto abort_cmd;
2171 201a51fc balrog
            }
2172 41a2b959 aliguori
            s->status = READY_STAT | SEEK_STAT;
2173 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2174 201a51fc balrog
            break;
2175 e8b54394 Brian Wheeler
2176 e8b54394 Brian Wheeler
        case WIN_SMART:
2177 cd8722bb Markus Armbruster
            if (s->drive_kind == IDE_CD)
2178 e8b54394 Brian Wheeler
                goto abort_cmd;
2179 e8b54394 Brian Wheeler
            if (s->hcyl != 0xc2 || s->lcyl != 0x4f)
2180 e8b54394 Brian Wheeler
                goto abort_cmd;
2181 e8b54394 Brian Wheeler
            if (!s->smart_enabled && s->feature != SMART_ENABLE)
2182 e8b54394 Brian Wheeler
                goto abort_cmd;
2183 e8b54394 Brian Wheeler
            switch (s->feature) {
2184 e8b54394 Brian Wheeler
            case SMART_DISABLE:
2185 e8b54394 Brian Wheeler
                s->smart_enabled = 0;
2186 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2187 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2188 e8b54394 Brian Wheeler
                break;
2189 e8b54394 Brian Wheeler
            case SMART_ENABLE:
2190 e8b54394 Brian Wheeler
                s->smart_enabled = 1;
2191 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2192 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2193 e8b54394 Brian Wheeler
                break;
2194 e8b54394 Brian Wheeler
            case SMART_ATTR_AUTOSAVE:
2195 e8b54394 Brian Wheeler
                switch (s->sector) {
2196 e8b54394 Brian Wheeler
                case 0x00:
2197 e8b54394 Brian Wheeler
                    s->smart_autosave = 0;
2198 e8b54394 Brian Wheeler
                    break;
2199 e8b54394 Brian Wheeler
                case 0xf1:
2200 e8b54394 Brian Wheeler
                    s->smart_autosave = 1;
2201 e8b54394 Brian Wheeler
                    break;
2202 e8b54394 Brian Wheeler
                default:
2203 e8b54394 Brian Wheeler
                    goto abort_cmd;
2204 e8b54394 Brian Wheeler
                }
2205 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2206 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2207 e8b54394 Brian Wheeler
                break;
2208 e8b54394 Brian Wheeler
            case SMART_STATUS:
2209 e8b54394 Brian Wheeler
                if (!s->smart_errors) {
2210 e8b54394 Brian Wheeler
                    s->hcyl = 0xc2;
2211 e8b54394 Brian Wheeler
                    s->lcyl = 0x4f;
2212 e8b54394 Brian Wheeler
                } else {
2213 e8b54394 Brian Wheeler
                    s->hcyl = 0x2c;
2214 e8b54394 Brian Wheeler
                    s->lcyl = 0xf4;
2215 e8b54394 Brian Wheeler
                }
2216 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2217 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2218 e8b54394 Brian Wheeler
                break;
2219 e8b54394 Brian Wheeler
            case SMART_READ_THRESH:
2220 e8b54394 Brian Wheeler
                memset(s->io_buffer, 0, 0x200);
2221 e8b54394 Brian Wheeler
                s->io_buffer[0] = 0x01; /* smart struct version */
2222 e8b54394 Brian Wheeler
                for (n=0; n<30; n++) {
2223 e8b54394 Brian Wheeler
                    if (smart_attributes[n][0] == 0)
2224 e8b54394 Brian Wheeler
                        break;
2225 e8b54394 Brian Wheeler
                    s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
2226 e8b54394 Brian Wheeler
                    s->io_buffer[2+1+(n*12)] = smart_attributes[n][4];
2227 e8b54394 Brian Wheeler
                }
2228 e8b54394 Brian Wheeler
                for (n=0; n<511; n++) /* checksum */
2229 e8b54394 Brian Wheeler
                    s->io_buffer[511] += s->io_buffer[n];
2230 e8b54394 Brian Wheeler
                s->io_buffer[511] = 0x100 - s->io_buffer[511];
2231 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2232 e8b54394 Brian Wheeler
                ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2233 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2234 e8b54394 Brian Wheeler
                break;
2235 e8b54394 Brian Wheeler
            case SMART_READ_DATA:
2236 e8b54394 Brian Wheeler
                memset(s->io_buffer, 0, 0x200);
2237 e8b54394 Brian Wheeler
                s->io_buffer[0] = 0x01; /* smart struct version */
2238 e8b54394 Brian Wheeler
                for (n=0; n<30; n++) {
2239 e8b54394 Brian Wheeler
                    if (smart_attributes[n][0] == 0)
2240 e8b54394 Brian Wheeler
                        break;
2241 e8b54394 Brian Wheeler
                    s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
2242 e8b54394 Brian Wheeler
                    s->io_buffer[2+1+(n*12)] = smart_attributes[n][1];
2243 e8b54394 Brian Wheeler
                    s->io_buffer[2+3+(n*12)] = smart_attributes[n][2];
2244 e8b54394 Brian Wheeler
                    s->io_buffer[2+4+(n*12)] = smart_attributes[n][3];
2245 e8b54394 Brian Wheeler
                }
2246 e8b54394 Brian Wheeler
                s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
2247 e8b54394 Brian Wheeler
                if (s->smart_selftest_count == 0) {
2248 e8b54394 Brian Wheeler
                    s->io_buffer[363] = 0;
2249 e8b54394 Brian Wheeler
                } else {
2250 e8b54394 Brian Wheeler
                    s->io_buffer[363] = 
2251 e8b54394 Brian Wheeler
                        s->smart_selftest_data[3 + 
2252 e8b54394 Brian Wheeler
                                               (s->smart_selftest_count - 1) * 
2253 e8b54394 Brian Wheeler
                                               24];
2254 e8b54394 Brian Wheeler
                }
2255 e8b54394 Brian Wheeler
                s->io_buffer[364] = 0x20; 
2256 e8b54394 Brian Wheeler
                s->io_buffer[365] = 0x01; 
2257 e8b54394 Brian Wheeler
                /* offline data collection capacity: execute + self-test*/
2258 e8b54394 Brian Wheeler
                s->io_buffer[367] = (1<<4 | 1<<3 | 1); 
2259 e8b54394 Brian Wheeler
                s->io_buffer[368] = 0x03; /* smart capability (1) */
2260 e8b54394 Brian Wheeler
                s->io_buffer[369] = 0x00; /* smart capability (2) */
2261 e8b54394 Brian Wheeler
                s->io_buffer[370] = 0x01; /* error logging supported */
2262 e8b54394 Brian Wheeler
                s->io_buffer[372] = 0x02; /* minutes for poll short test */
2263 e8b54394 Brian Wheeler
                s->io_buffer[373] = 0x36; /* minutes for poll ext test */
2264 e8b54394 Brian Wheeler
                s->io_buffer[374] = 0x01; /* minutes for poll conveyance */
2265 e8b54394 Brian Wheeler
2266 e8b54394 Brian Wheeler
                for (n=0; n<511; n++) 
2267 e8b54394 Brian Wheeler
                    s->io_buffer[511] += s->io_buffer[n];
2268 e8b54394 Brian Wheeler
                s->io_buffer[511] = 0x100 - s->io_buffer[511];
2269 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2270 e8b54394 Brian Wheeler
                ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2271 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2272 e8b54394 Brian Wheeler
                break;
2273 e8b54394 Brian Wheeler
            case SMART_READ_LOG:
2274 e8b54394 Brian Wheeler
                switch (s->sector) {
2275 e8b54394 Brian Wheeler
                case 0x01: /* summary smart error log */
2276 e8b54394 Brian Wheeler
                    memset(s->io_buffer, 0, 0x200);
2277 e8b54394 Brian Wheeler
                    s->io_buffer[0] = 0x01;
2278 e8b54394 Brian Wheeler
                    s->io_buffer[1] = 0x00; /* no error entries */
2279 e8b54394 Brian Wheeler
                    s->io_buffer[452] = s->smart_errors & 0xff;
2280 e8b54394 Brian Wheeler
                    s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;
2281 e8b54394 Brian Wheeler
2282 e8b54394 Brian Wheeler
                    for (n=0; n<511; n++)
2283 e8b54394 Brian Wheeler
                        s->io_buffer[511] += s->io_buffer[n];
2284 e8b54394 Brian Wheeler
                    s->io_buffer[511] = 0x100 - s->io_buffer[511];
2285 e8b54394 Brian Wheeler
                    break;
2286 e8b54394 Brian Wheeler
                case 0x06: /* smart self test log */
2287 e8b54394 Brian Wheeler
                    memset(s->io_buffer, 0, 0x200);
2288 e8b54394 Brian Wheeler
                    s->io_buffer[0] = 0x01; 
2289 e8b54394 Brian Wheeler
                    if (s->smart_selftest_count == 0) {
2290 e8b54394 Brian Wheeler
                        s->io_buffer[508] = 0;
2291 e8b54394 Brian Wheeler
                    } else {
2292 e8b54394 Brian Wheeler
                        s->io_buffer[508] = s->smart_selftest_count;
2293 e8b54394 Brian Wheeler
                        for (n=2; n<506; n++) 
2294 e8b54394 Brian Wheeler
                            s->io_buffer[n] = s->smart_selftest_data[n];
2295 e8b54394 Brian Wheeler
                    }                    
2296 e8b54394 Brian Wheeler
                    for (n=0; n<511; n++)
2297 e8b54394 Brian Wheeler
                        s->io_buffer[511] += s->io_buffer[n];
2298 e8b54394 Brian Wheeler
                    s->io_buffer[511] = 0x100 - s->io_buffer[511];
2299 e8b54394 Brian Wheeler
                    break;
2300 e8b54394 Brian Wheeler
                default:
2301 e8b54394 Brian Wheeler
                    goto abort_cmd;
2302 e8b54394 Brian Wheeler
                }
2303 e8b54394 Brian Wheeler
                s->status = READY_STAT | SEEK_STAT;
2304 e8b54394 Brian Wheeler
                ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2305 9cdd03a7 Gerd Hoffmann
                ide_set_irq(s->bus);
2306 e8b54394 Brian Wheeler
                break;
2307 e8b54394 Brian Wheeler
            case SMART_EXECUTE_OFFLINE:
2308 e8b54394 Brian Wheeler
                switch (s->sector) {
2309 e8b54394 Brian Wheeler
                case 0: /* off-line routine */
2310 e8b54394 Brian Wheeler
                case 1: /* short self test */
2311 e8b54394 Brian Wheeler
                case 2: /* extended self test */
2312 e8b54394 Brian Wheeler
                    s->smart_selftest_count++;
2313 e8b54394 Brian Wheeler
                    if(s->smart_selftest_count > 21)
2314 e8b54394 Brian Wheeler
                        s->smart_selftest_count = 0;
2315 e8b54394 Brian Wheeler
                    n = 2 + (s->smart_selftest_count - 1) * 24;
2316 e8b54394 Brian Wheeler
                    s->smart_selftest_data[n] = s->sector;
2317 e8b54394 Brian Wheeler
                    s->smart_selftest_data[n+1] = 0x00; /* OK and finished */
2318 e8b54394 Brian Wheeler
                    s->smart_selftest_data[n+2] = 0x34; /* hour count lsb */
2319 e8b54394 Brian Wheeler
                    s->smart_selftest_data[n+3] = 0x12; /* hour count msb */
2320 e8b54394 Brian Wheeler
                    s->status = READY_STAT | SEEK_STAT;
2321 9cdd03a7 Gerd Hoffmann
                    ide_set_irq(s->bus);
2322 e8b54394 Brian Wheeler
                    break;
2323 e8b54394 Brian Wheeler
                default:
2324 e8b54394 Brian Wheeler
                    goto abort_cmd;
2325 e8b54394 Brian Wheeler
                }
2326 e8b54394 Brian Wheeler
                break;
2327 e8b54394 Brian Wheeler
            default:
2328 e8b54394 Brian Wheeler
                goto abort_cmd;
2329 e8b54394 Brian Wheeler
            }
2330 e8b54394 Brian Wheeler
            break;
2331 5391d806 bellard
        default:
2332 5391d806 bellard
        abort_cmd:
2333 5391d806 bellard
            ide_abort_command(s);
2334 9cdd03a7 Gerd Hoffmann
            ide_set_irq(s->bus);
2335 5391d806 bellard
            break;
2336 5391d806 bellard
        }
2337 5391d806 bellard
    }
2338 5391d806 bellard
}
2339 5391d806 bellard
2340 356721ae Gerd Hoffmann
uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
2341 5391d806 bellard
{
2342 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2343 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2344 5391d806 bellard
    uint32_t addr;
2345 c2ff060f bellard
    int ret, hob;
2346 5391d806 bellard
2347 5391d806 bellard
    addr = addr1 & 7;
2348 c2ff060f bellard
    /* FIXME: HOB readback uses bit 7, but it's always set right now */
2349 c2ff060f bellard
    //hob = s->select & (1 << 7);
2350 c2ff060f bellard
    hob = 0;
2351 5391d806 bellard
    switch(addr) {
2352 5391d806 bellard
    case 0:
2353 5391d806 bellard
        ret = 0xff;
2354 5391d806 bellard
        break;
2355 5391d806 bellard
    case 1:
2356 bcbdc4d3 Gerd Hoffmann
        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
2357 bcbdc4d3 Gerd Hoffmann
            (s != bus->ifs && !s->bs))
2358 c45c3d00 bellard
            ret = 0;
2359 c2ff060f bellard
        else if (!hob)
2360 c45c3d00 bellard
            ret = s->error;
2361 c2ff060f bellard
        else
2362 c2ff060f bellard
            ret = s->hob_feature;
2363 5391d806 bellard
        break;
2364 5391d806 bellard
    case 2:
2365 bcbdc4d3 Gerd Hoffmann
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
2366 c45c3d00 bellard
            ret = 0;
2367 c2ff060f bellard
        else if (!hob)
2368 c45c3d00 bellard
            ret = s->nsector & 0xff;
2369 c2ff060f bellard
        else
2370 c2ff060f bellard
            ret = s->hob_nsector;
2371 5391d806 bellard
        break;
2372 5391d806 bellard
    case 3:
2373 bcbdc4d3 Gerd Hoffmann
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
2374 c45c3d00 bellard
            ret = 0;
2375 c2ff060f bellard
        else if (!hob)
2376 c45c3d00 bellard
            ret = s->sector;
2377 c2ff060f bellard
        else
2378 c2ff060f bellard
            ret = s->hob_sector;
2379 5391d806 bellard
        break;
2380 5391d806 bellard
    case 4:
2381 bcbdc4d3 Gerd Hoffmann
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
2382 c45c3d00 bellard
            ret = 0;
2383 c2ff060f bellard
        else if (!hob)
2384 c45c3d00 bellard
            ret = s->lcyl;
2385 c2ff060f bellard
        else
2386 c2ff060f bellard
            ret = s->hob_lcyl;
2387 5391d806 bellard
        break;
2388 5391d806 bellard
    case 5:
2389 bcbdc4d3 Gerd Hoffmann
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
2390 c45c3d00 bellard
            ret = 0;
2391 c2ff060f bellard
        else if (!hob)
2392 c45c3d00 bellard
            ret = s->hcyl;
2393 c2ff060f bellard
        else
2394 c2ff060f bellard
            ret = s->hob_hcyl;
2395 5391d806 bellard
        break;
2396 5391d806 bellard
    case 6:
2397 bcbdc4d3 Gerd Hoffmann
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
2398 c45c3d00 bellard
            ret = 0;
2399 c45c3d00 bellard
        else
2400 7ae98627 bellard
            ret = s->select;
2401 5391d806 bellard
        break;
2402 5391d806 bellard
    default:
2403 5391d806 bellard
    case 7:
2404 bcbdc4d3 Gerd Hoffmann
        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
2405 bcbdc4d3 Gerd Hoffmann
            (s != bus->ifs && !s->bs))
2406 c45c3d00 bellard
            ret = 0;
2407 c45c3d00 bellard
        else
2408 c45c3d00 bellard
            ret = s->status;
2409 9cdd03a7 Gerd Hoffmann
        qemu_irq_lower(bus->irq);
2410 5391d806 bellard
        break;
2411 5391d806 bellard
    }
2412 5391d806 bellard
#ifdef DEBUG_IDE
2413 5391d806 bellard
    printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
2414 5391d806 bellard
#endif
2415 5391d806 bellard
    return ret;
2416 5391d806 bellard
}
2417 5391d806 bellard
2418 356721ae Gerd Hoffmann
uint32_t ide_status_read(void *opaque, uint32_t addr)
2419 5391d806 bellard
{
2420 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2421 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2422 5391d806 bellard
    int ret;
2423 7ae98627 bellard
2424 bcbdc4d3 Gerd Hoffmann
    if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
2425 bcbdc4d3 Gerd Hoffmann
        (s != bus->ifs && !s->bs))
2426 7ae98627 bellard
        ret = 0;
2427 7ae98627 bellard
    else
2428 7ae98627 bellard
        ret = s->status;
2429 5391d806 bellard
#ifdef DEBUG_IDE
2430 5391d806 bellard
    printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
2431 5391d806 bellard
#endif
2432 5391d806 bellard
    return ret;
2433 5391d806 bellard
}
2434 5391d806 bellard
2435 356721ae Gerd Hoffmann
void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
2436 5391d806 bellard
{
2437 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2438 5391d806 bellard
    IDEState *s;
2439 5391d806 bellard
    int i;
2440 5391d806 bellard
2441 5391d806 bellard
#ifdef DEBUG_IDE
2442 5391d806 bellard
    printf("ide: write control addr=0x%x val=%02x\n", addr, val);
2443 5391d806 bellard
#endif
2444 5391d806 bellard
    /* common for both drives */
2445 9cdd03a7 Gerd Hoffmann
    if (!(bus->cmd & IDE_CMD_RESET) &&
2446 5391d806 bellard
        (val & IDE_CMD_RESET)) {
2447 5391d806 bellard
        /* reset low to high */
2448 5391d806 bellard
        for(i = 0;i < 2; i++) {
2449 bcbdc4d3 Gerd Hoffmann
            s = &bus->ifs[i];
2450 5391d806 bellard
            s->status = BUSY_STAT | SEEK_STAT;
2451 5391d806 bellard
            s->error = 0x01;
2452 5391d806 bellard
        }
2453 9cdd03a7 Gerd Hoffmann
    } else if ((bus->cmd & IDE_CMD_RESET) &&
2454 5391d806 bellard
               !(val & IDE_CMD_RESET)) {
2455 5391d806 bellard
        /* high to low */
2456 5391d806 bellard
        for(i = 0;i < 2; i++) {
2457 bcbdc4d3 Gerd Hoffmann
            s = &bus->ifs[i];
2458 cd8722bb Markus Armbruster
            if (s->drive_kind == IDE_CD)
2459 6b136f9e bellard
                s->status = 0x00; /* NOTE: READY is _not_ set */
2460 6b136f9e bellard
            else
2461 56bf1d37 bellard
                s->status = READY_STAT | SEEK_STAT;
2462 5391d806 bellard
            ide_set_signature(s);
2463 5391d806 bellard
        }
2464 5391d806 bellard
    }
2465 5391d806 bellard
2466 9cdd03a7 Gerd Hoffmann
    bus->cmd = val;
2467 5391d806 bellard
}
2468 5391d806 bellard
2469 356721ae Gerd Hoffmann
void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
2470 5391d806 bellard
{
2471 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2472 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2473 5391d806 bellard
    uint8_t *p;
2474 5391d806 bellard
2475 fcdd25ab aliguori
    /* PIO data access allowed only when DRQ bit is set */
2476 fcdd25ab aliguori
    if (!(s->status & DRQ_STAT))
2477 fcdd25ab aliguori
        return;
2478 fcdd25ab aliguori
2479 5391d806 bellard
    p = s->data_ptr;
2480 0c4ad8dc bellard
    *(uint16_t *)p = le16_to_cpu(val);
2481 5391d806 bellard
    p += 2;
2482 5391d806 bellard
    s->data_ptr = p;
2483 5391d806 bellard
    if (p >= s->data_end)
2484 5391d806 bellard
        s->end_transfer_func(s);
2485 5391d806 bellard
}
2486 5391d806 bellard
2487 356721ae Gerd Hoffmann
uint32_t ide_data_readw(void *opaque, uint32_t addr)
2488 5391d806 bellard
{
2489 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2490 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2491 5391d806 bellard
    uint8_t *p;
2492 5391d806 bellard
    int ret;
2493 fcdd25ab aliguori
2494 fcdd25ab aliguori
    /* PIO data access allowed only when DRQ bit is set */
2495 fcdd25ab aliguori
    if (!(s->status & DRQ_STAT))
2496 fcdd25ab aliguori
        return 0;
2497 fcdd25ab aliguori
2498 5391d806 bellard
    p = s->data_ptr;
2499 0c4ad8dc bellard
    ret = cpu_to_le16(*(uint16_t *)p);
2500 5391d806 bellard
    p += 2;
2501 5391d806 bellard
    s->data_ptr = p;
2502 5391d806 bellard
    if (p >= s->data_end)
2503 5391d806 bellard
        s->end_transfer_func(s);
2504 5391d806 bellard
    return ret;
2505 5391d806 bellard
}
2506 5391d806 bellard
2507 356721ae Gerd Hoffmann
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
2508 5391d806 bellard
{
2509 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2510 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2511 5391d806 bellard
    uint8_t *p;
2512 5391d806 bellard
2513 fcdd25ab aliguori
    /* PIO data access allowed only when DRQ bit is set */
2514 fcdd25ab aliguori
    if (!(s->status & DRQ_STAT))
2515 fcdd25ab aliguori
        return;
2516 fcdd25ab aliguori
2517 5391d806 bellard
    p = s->data_ptr;
2518 0c4ad8dc bellard
    *(uint32_t *)p = le32_to_cpu(val);
2519 5391d806 bellard
    p += 4;
2520 5391d806 bellard
    s->data_ptr = p;
2521 5391d806 bellard
    if (p >= s->data_end)
2522 5391d806 bellard
        s->end_transfer_func(s);
2523 5391d806 bellard
}
2524 5391d806 bellard
2525 356721ae Gerd Hoffmann
uint32_t ide_data_readl(void *opaque, uint32_t addr)
2526 5391d806 bellard
{
2527 bcbdc4d3 Gerd Hoffmann
    IDEBus *bus = opaque;
2528 bcbdc4d3 Gerd Hoffmann
    IDEState *s = idebus_active_if(bus);
2529 5391d806 bellard
    uint8_t *p;
2530 5391d806 bellard
    int ret;
2531 3b46e624 ths
2532 fcdd25ab aliguori
    /* PIO data access allowed only when DRQ bit is set */
2533 fcdd25ab aliguori
    if (!(s->status & DRQ_STAT))
2534 fcdd25ab aliguori
        return 0;
2535 fcdd25ab aliguori
2536 5391d806 bellard
    p = s->data_ptr;
2537 0c4ad8dc bellard
    ret = cpu_to_le32(*(uint32_t *)p);
2538 5391d806 bellard
    p += 4;
2539 5391d806 bellard
    s->data_ptr = p;
2540 5391d806 bellard
    if (p >= s->data_end)
2541 5391d806 bellard
        s->end_transfer_func(s);
2542 5391d806 bellard
    return ret;
2543 5391d806 bellard
}
2544 5391d806 bellard
2545 a7dfe172 bellard
static void ide_dummy_transfer_stop(IDEState *s)
2546 a7dfe172 bellard
{
2547 a7dfe172 bellard
    s->data_ptr = s->io_buffer;
2548 a7dfe172 bellard
    s->data_end = s->io_buffer;
2549 a7dfe172 bellard
    s->io_buffer[0] = 0xff;
2550 a7dfe172 bellard
    s->io_buffer[1] = 0xff;
2551 a7dfe172 bellard
    s->io_buffer[2] = 0xff;
2552 a7dfe172 bellard
    s->io_buffer[3] = 0xff;
2553 a7dfe172 bellard
}
2554 a7dfe172 bellard
2555 4a643563 Blue Swirl
static void ide_reset(IDEState *s)
2556 5391d806 bellard
{
2557 4a643563 Blue Swirl
#ifdef DEBUG_IDE
2558 4a643563 Blue Swirl
    printf("ide: reset\n");
2559 4a643563 Blue Swirl
#endif
2560 cd8722bb Markus Armbruster
    if (s->drive_kind == IDE_CFATA)
2561 201a51fc balrog
        s->mult_sectors = 0;
2562 201a51fc balrog
    else
2563 201a51fc balrog
        s->mult_sectors = MAX_MULT_SECTORS;
2564 4a643563 Blue Swirl
    /* ide regs */
2565 4a643563 Blue Swirl
    s->feature = 0;
2566 4a643563 Blue Swirl
    s->error = 0;
2567 4a643563 Blue Swirl
    s->nsector = 0;
2568 4a643563 Blue Swirl
    s->sector = 0;
2569 4a643563 Blue Swirl
    s->lcyl = 0;
2570 4a643563 Blue Swirl
    s->hcyl = 0;
2571 4a643563 Blue Swirl
2572 4a643563 Blue Swirl
    /* lba48 */
2573 4a643563 Blue Swirl
    s->hob_feature = 0;
2574 4a643563 Blue Swirl
    s->hob_sector = 0;
2575 4a643563 Blue Swirl
    s->hob_nsector = 0;
2576 4a643563 Blue Swirl
    s->hob_lcyl = 0;
2577 4a643563 Blue Swirl
    s->hob_hcyl = 0;
2578 4a643563 Blue Swirl
2579 5391d806 bellard
    s->select = 0xa0;
2580 41a2b959 aliguori
    s->status = READY_STAT | SEEK_STAT;
2581 4a643563 Blue Swirl
2582 4a643563 Blue Swirl
    s->lba48 = 0;
2583 4a643563 Blue Swirl
2584 4a643563 Blue Swirl
    /* ATAPI specific */
2585 4a643563 Blue Swirl
    s->sense_key = 0;
2586 4a643563 Blue Swirl
    s->asc = 0;
2587 4a643563 Blue Swirl
    s->cdrom_changed = 0;
2588 4a643563 Blue Swirl
    s->packet_transfer_size = 0;
2589 4a643563 Blue Swirl
    s->elementary_transfer_size = 0;
2590 4a643563 Blue Swirl
    s->io_buffer_index = 0;
2591 4a643563 Blue Swirl
    s->cd_sector_size = 0;
2592 4a643563 Blue Swirl
    s->atapi_dma = 0;
2593 4a643563 Blue Swirl
    /* ATA DMA state */
2594 4a643563 Blue Swirl
    s->io_buffer_size = 0;
2595 4a643563 Blue Swirl
    s->req_nb_sectors = 0;
2596 4a643563 Blue Swirl
2597 5391d806 bellard
    ide_set_signature(s);
2598 a7dfe172 bellard
    /* init the transfer handler so that 0xffff is returned on data
2599 a7dfe172 bellard
       accesses */
2600 a7dfe172 bellard
    s->end_transfer_func = ide_dummy_transfer_stop;
2601 a7dfe172 bellard
    ide_dummy_transfer_stop(s);
2602 201a51fc balrog
    s->media_changed = 0;
2603 5391d806 bellard
}
2604 5391d806 bellard
2605 4a643563 Blue Swirl
void ide_bus_reset(IDEBus *bus)
2606 4a643563 Blue Swirl
{
2607 4a643563 Blue Swirl
    bus->unit = 0;
2608 4a643563 Blue Swirl
    bus->cmd = 0;
2609 4a643563 Blue Swirl
    ide_reset(&bus->ifs[0]);
2610 4a643563 Blue Swirl
    ide_reset(&bus->ifs[1]);
2611 4a643563 Blue Swirl
    ide_clear_hob(bus);
2612 4a643563 Blue Swirl
}
2613 4a643563 Blue Swirl
2614 c4d74df7 Markus Armbruster
int ide_init_drive(IDEState *s, BlockDriverState *bs,
2615 c4d74df7 Markus Armbruster
                   const char *version, const char *serial)
2616 88804180 Gerd Hoffmann
{
2617 88804180 Gerd Hoffmann
    int cylinders, heads, secs;
2618 88804180 Gerd Hoffmann
    uint64_t nb_sectors;
2619 88804180 Gerd Hoffmann
2620 f8b6cc00 Markus Armbruster
    s->bs = bs;
2621 f8b6cc00 Markus Armbruster
    bdrv_get_geometry(bs, &nb_sectors);
2622 f8b6cc00 Markus Armbruster
    bdrv_guess_geometry(bs, &cylinders, &heads, &secs);
2623 dce9e928 Markus Armbruster
    if (cylinders < 1 || cylinders > 16383) {
2624 dce9e928 Markus Armbruster
        error_report("cyls must be between 1 and 16383");
2625 dce9e928 Markus Armbruster
        return -1;
2626 dce9e928 Markus Armbruster
    }
2627 dce9e928 Markus Armbruster
    if (heads < 1 || heads > 16) {
2628 dce9e928 Markus Armbruster
        error_report("heads must be between 1 and 16");
2629 dce9e928 Markus Armbruster
        return -1;
2630 dce9e928 Markus Armbruster
    }
2631 dce9e928 Markus Armbruster
    if (secs < 1 || secs > 63) {
2632 dce9e928 Markus Armbruster
        error_report("secs must be between 1 and 63");
2633 dce9e928 Markus Armbruster
        return -1;
2634 dce9e928 Markus Armbruster
    }
2635 870111c8 Markus Armbruster
    s->cylinders = cylinders;
2636 870111c8 Markus Armbruster
    s->heads = heads;
2637 870111c8 Markus Armbruster
    s->sectors = secs;
2638 870111c8 Markus Armbruster
    s->nb_sectors = nb_sectors;
2639 870111c8 Markus Armbruster
    /* The SMART values should be preserved across power cycles
2640 870111c8 Markus Armbruster
       but they aren't.  */
2641 870111c8 Markus Armbruster
    s->smart_enabled = 1;
2642 870111c8 Markus Armbruster
    s->smart_autosave = 1;
2643 870111c8 Markus Armbruster
    s->smart_errors = 0;
2644 870111c8 Markus Armbruster
    s->smart_selftest_count = 0;
2645 f8b6cc00 Markus Armbruster
    if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
2646 cd8722bb Markus Armbruster
        s->drive_kind = IDE_CD;
2647 f8b6cc00 Markus Armbruster
        bdrv_set_change_cb(bs, cdrom_change_cb, s);
2648 1b2adf28 Christoph Hellwig
        bs->buffer_alignment = 2048;
2649 7aa9c811 Markus Armbruster
    } else {
2650 98f28ad7 Markus Armbruster
        if (!bdrv_is_inserted(s->bs)) {
2651 98f28ad7 Markus Armbruster
            error_report("Device needs media, but drive is empty");
2652 98f28ad7 Markus Armbruster
            return -1;
2653 98f28ad7 Markus Armbruster
        }
2654 7aa9c811 Markus Armbruster
        if (bdrv_is_read_only(bs)) {
2655 7aa9c811 Markus Armbruster
            error_report("Can't use a read-only drive");
2656 7aa9c811 Markus Armbruster
            return -1;
2657 7aa9c811 Markus Armbruster
        }
2658 88804180 Gerd Hoffmann
    }
2659 f8b6cc00 Markus Armbruster
    if (serial) {
2660 6ced55a5 Markus Armbruster
        strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
2661 6ced55a5 Markus Armbruster
    } else {
2662 88804180 Gerd Hoffmann
        snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
2663 88804180 Gerd Hoffmann
                 "QM%05d", s->drive_serial);
2664 870111c8 Markus Armbruster
    }
2665 47c06340 Gerd Hoffmann
    if (version) {
2666 47c06340 Gerd Hoffmann
        pstrcpy(s->version, sizeof(s->version), version);
2667 47c06340 Gerd Hoffmann
    } else {
2668 47c06340 Gerd Hoffmann
        pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
2669 47c06340 Gerd Hoffmann
    }
2670 88804180 Gerd Hoffmann
    ide_reset(s);
2671 cd8722bb Markus Armbruster
    bdrv_set_removable(bs, s->drive_kind == IDE_CD);
2672 c4d74df7 Markus Armbruster
    return 0;
2673 88804180 Gerd Hoffmann
}
2674 88804180 Gerd Hoffmann
2675 57234ee4 Markus Armbruster
static void ide_init1(IDEBus *bus, int unit)
2676 d459da0e Markus Armbruster
{
2677 d459da0e Markus Armbruster
    static int drive_serial = 1;
2678 d459da0e Markus Armbruster
    IDEState *s = &bus->ifs[unit];
2679 d459da0e Markus Armbruster
2680 d459da0e Markus Armbruster
    s->bus = bus;
2681 d459da0e Markus Armbruster
    s->unit = unit;
2682 d459da0e Markus Armbruster
    s->drive_serial = drive_serial++;
2683 1b2adf28 Christoph Hellwig
    /* we need at least 2k alignment for accessing CDROMs using O_DIRECT */
2684 1b2adf28 Christoph Hellwig
    s->io_buffer = qemu_memalign(2048, IDE_DMA_BUF_SECTORS*512 + 4);
2685 50641c5c Juan Quintela
    s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
2686 d459da0e Markus Armbruster
    s->smart_selftest_data = qemu_blockalign(s->bs, 512);
2687 d459da0e Markus Armbruster
    s->sector_write_timer = qemu_new_timer(vm_clock,
2688 d459da0e Markus Armbruster
                                           ide_sector_write_timer_cb, s);
2689 57234ee4 Markus Armbruster
}
2690 57234ee4 Markus Armbruster
2691 57234ee4 Markus Armbruster
void ide_init2(IDEBus *bus, qemu_irq irq)
2692 57234ee4 Markus Armbruster
{
2693 57234ee4 Markus Armbruster
    int i;
2694 57234ee4 Markus Armbruster
2695 57234ee4 Markus Armbruster
    for(i = 0; i < 2; i++) {
2696 57234ee4 Markus Armbruster
        ide_init1(bus, i);
2697 57234ee4 Markus Armbruster
        ide_reset(&bus->ifs[i]);
2698 870111c8 Markus Armbruster
    }
2699 57234ee4 Markus Armbruster
    bus->irq = irq;
2700 d459da0e Markus Armbruster
}
2701 d459da0e Markus Armbruster
2702 57234ee4 Markus Armbruster
/* TODO convert users to qdev and remove */
2703 57234ee4 Markus Armbruster
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
2704 57234ee4 Markus Armbruster
                                    DriveInfo *hd1, qemu_irq irq)
2705 5391d806 bellard
{
2706 88804180 Gerd Hoffmann
    int i;
2707 57234ee4 Markus Armbruster
    DriveInfo *dinfo;
2708 5391d806 bellard
2709 caed8802 bellard
    for(i = 0; i < 2; i++) {
2710 57234ee4 Markus Armbruster
        dinfo = i == 0 ? hd0 : hd1;
2711 57234ee4 Markus Armbruster
        ide_init1(bus, i);
2712 57234ee4 Markus Armbruster
        if (dinfo) {
2713 c4d74df7 Markus Armbruster
            if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL,
2714 c4d74df7 Markus Armbruster
                               *dinfo->serial ? dinfo->serial : NULL) < 0) {
2715 c4d74df7 Markus Armbruster
                error_report("Can't set up IDE drive %s", dinfo->id);
2716 c4d74df7 Markus Armbruster
                exit(1);
2717 c4d74df7 Markus Armbruster
            }
2718 57234ee4 Markus Armbruster
        } else {
2719 57234ee4 Markus Armbruster
            ide_reset(&bus->ifs[i]);
2720 57234ee4 Markus Armbruster
        }
2721 5391d806 bellard
    }
2722 9cdd03a7 Gerd Hoffmann
    bus->irq = irq;
2723 69b91039 bellard
}
2724 69b91039 bellard
2725 356721ae Gerd Hoffmann
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2)
2726 69b91039 bellard
{
2727 bcbdc4d3 Gerd Hoffmann
    register_ioport_write(iobase, 8, 1, ide_ioport_write, bus);
2728 bcbdc4d3 Gerd Hoffmann
    register_ioport_read(iobase, 8, 1, ide_ioport_read, bus);
2729 caed8802 bellard
    if (iobase2) {
2730 bcbdc4d3 Gerd Hoffmann
        register_ioport_read(iobase2, 1, 1, ide_status_read, bus);
2731 bcbdc4d3 Gerd Hoffmann
        register_ioport_write(iobase2, 1, 1, ide_cmd_write, bus);
2732 5391d806 bellard
    }
2733 3b46e624 ths
2734 caed8802 bellard
    /* data ports */
2735 bcbdc4d3 Gerd Hoffmann
    register_ioport_write(iobase, 2, 2, ide_data_writew, bus);
2736 bcbdc4d3 Gerd Hoffmann
    register_ioport_read(iobase, 2, 2, ide_data_readw, bus);
2737 bcbdc4d3 Gerd Hoffmann
    register_ioport_write(iobase, 4, 4, ide_data_writel, bus);
2738 bcbdc4d3 Gerd Hoffmann
    register_ioport_read(iobase, 4, 4, ide_data_readl, bus);
2739 5391d806 bellard
}
2740 69b91039 bellard
2741 37159f13 Juan Quintela
static bool is_identify_set(void *opaque, int version_id)
2742 aa941b94 balrog
{
2743 37159f13 Juan Quintela
    IDEState *s = opaque;
2744 37159f13 Juan Quintela
2745 37159f13 Juan Quintela
    return s->identify_set != 0;
2746 37159f13 Juan Quintela
}
2747 37159f13 Juan Quintela
2748 50641c5c Juan Quintela
static EndTransferFunc* transfer_end_table[] = {
2749 50641c5c Juan Quintela
        ide_sector_read,
2750 50641c5c Juan Quintela
        ide_sector_write,
2751 50641c5c Juan Quintela
        ide_transfer_stop,
2752 50641c5c Juan Quintela
        ide_atapi_cmd_reply_end,
2753 50641c5c Juan Quintela
        ide_atapi_cmd,
2754 50641c5c Juan Quintela
        ide_dummy_transfer_stop,
2755 50641c5c Juan Quintela
};
2756 50641c5c Juan Quintela
2757 50641c5c Juan Quintela
static int transfer_end_table_idx(EndTransferFunc *fn)
2758 50641c5c Juan Quintela
{
2759 50641c5c Juan Quintela
    int i;
2760 50641c5c Juan Quintela
2761 50641c5c Juan Quintela
    for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
2762 50641c5c Juan Quintela
        if (transfer_end_table[i] == fn)
2763 50641c5c Juan Quintela
            return i;
2764 50641c5c Juan Quintela
2765 50641c5c Juan Quintela
    return -1;
2766 50641c5c Juan Quintela
}
2767 50641c5c Juan Quintela
2768 37159f13 Juan Quintela
static int ide_drive_post_load(void *opaque, int version_id)
2769 aa941b94 balrog
{
2770 37159f13 Juan Quintela
    IDEState *s = opaque;
2771 37159f13 Juan Quintela
2772 37159f13 Juan Quintela
    if (version_id < 3) {
2773 93c8cfd9 Gleb Natapov
        if (s->sense_key == SENSE_UNIT_ATTENTION &&
2774 37159f13 Juan Quintela
            s->asc == ASC_MEDIUM_MAY_HAVE_CHANGED) {
2775 93c8cfd9 Gleb Natapov
            s->cdrom_changed = 1;
2776 37159f13 Juan Quintela
        }
2777 93c8cfd9 Gleb Natapov
    }
2778 37159f13 Juan Quintela
    return 0;
2779 aa941b94 balrog
}
2780 aa941b94 balrog
2781 50641c5c Juan Quintela
static int ide_drive_pio_post_load(void *opaque, int version_id)
2782 50641c5c Juan Quintela
{
2783 50641c5c Juan Quintela
    IDEState *s = opaque;
2784 50641c5c Juan Quintela
2785 7bccf573 Blue Swirl
    if (s->end_transfer_fn_idx > ARRAY_SIZE(transfer_end_table)) {
2786 50641c5c Juan Quintela
        return -EINVAL;
2787 50641c5c Juan Quintela
    }
2788 50641c5c Juan Quintela
    s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
2789 50641c5c Juan Quintela
    s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
2790 50641c5c Juan Quintela
    s->data_end = s->data_ptr + s->cur_io_buffer_len;
2791 50641c5c Juan Quintela
2792 50641c5c Juan Quintela
    return 0;
2793 50641c5c Juan Quintela
}
2794 50641c5c Juan Quintela
2795 50641c5c Juan Quintela
static void ide_drive_pio_pre_save(void *opaque)
2796 50641c5c Juan Quintela
{
2797 50641c5c Juan Quintela
    IDEState *s = opaque;
2798 50641c5c Juan Quintela
    int idx;
2799 50641c5c Juan Quintela
2800 50641c5c Juan Quintela
    s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
2801 50641c5c Juan Quintela
    s->cur_io_buffer_len = s->data_end - s->data_ptr;
2802 50641c5c Juan Quintela
2803 50641c5c Juan Quintela
    idx = transfer_end_table_idx(s->end_transfer_func);
2804 50641c5c Juan Quintela
    if (idx == -1) {
2805 50641c5c Juan Quintela
        fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
2806 50641c5c Juan Quintela
                        __func__);
2807 50641c5c Juan Quintela
        s->end_transfer_fn_idx = 2;
2808 50641c5c Juan Quintela
    } else {
2809 50641c5c Juan Quintela
        s->end_transfer_fn_idx = idx;
2810 50641c5c Juan Quintela
    }
2811 50641c5c Juan Quintela
}
2812 50641c5c Juan Quintela
2813 50641c5c Juan Quintela
static bool ide_drive_pio_state_needed(void *opaque)
2814 50641c5c Juan Quintela
{
2815 50641c5c Juan Quintela
    IDEState *s = opaque;
2816 50641c5c Juan Quintela
2817 50641c5c Juan Quintela
    return (s->status & DRQ_STAT) != 0;
2818 50641c5c Juan Quintela
}
2819 50641c5c Juan Quintela
2820 50641c5c Juan Quintela
const VMStateDescription vmstate_ide_drive_pio_state = {
2821 50641c5c Juan Quintela
    .name = "ide_drive/pio_state",
2822 50641c5c Juan Quintela
    .version_id = 1,
2823 50641c5c Juan Quintela
    .minimum_version_id = 1,
2824 50641c5c Juan Quintela
    .minimum_version_id_old = 1,
2825 50641c5c Juan Quintela
    .pre_save = ide_drive_pio_pre_save,
2826 50641c5c Juan Quintela
    .post_load = ide_drive_pio_post_load,
2827 50641c5c Juan Quintela
    .fields      = (VMStateField []) {
2828 50641c5c Juan Quintela
        VMSTATE_INT32(req_nb_sectors, IDEState),
2829 50641c5c Juan Quintela
        VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
2830 50641c5c Juan Quintela
                             vmstate_info_uint8, uint8_t),
2831 50641c5c Juan Quintela
        VMSTATE_INT32(cur_io_buffer_offset, IDEState),
2832 50641c5c Juan Quintela
        VMSTATE_INT32(cur_io_buffer_len, IDEState),
2833 50641c5c Juan Quintela
        VMSTATE_UINT8(end_transfer_fn_idx, IDEState),
2834 50641c5c Juan Quintela
        VMSTATE_INT32(elementary_transfer_size, IDEState),
2835 50641c5c Juan Quintela
        VMSTATE_INT32(packet_transfer_size, IDEState),
2836 50641c5c Juan Quintela
        VMSTATE_END_OF_LIST()
2837 50641c5c Juan Quintela
    }
2838 50641c5c Juan Quintela
};
2839 50641c5c Juan Quintela
2840 37159f13 Juan Quintela
const VMStateDescription vmstate_ide_drive = {
2841 37159f13 Juan Quintela
    .name = "ide_drive",
2842 3abb6260 Juan Quintela
    .version_id = 3,
2843 37159f13 Juan Quintela
    .minimum_version_id = 0,
2844 37159f13 Juan Quintela
    .minimum_version_id_old = 0,
2845 37159f13 Juan Quintela
    .post_load = ide_drive_post_load,
2846 37159f13 Juan Quintela
    .fields      = (VMStateField []) {
2847 37159f13 Juan Quintela
        VMSTATE_INT32(mult_sectors, IDEState),
2848 37159f13 Juan Quintela
        VMSTATE_INT32(identify_set, IDEState),
2849 37159f13 Juan Quintela
        VMSTATE_BUFFER_TEST(identify_data, IDEState, is_identify_set),
2850 37159f13 Juan Quintela
        VMSTATE_UINT8(feature, IDEState),
2851 37159f13 Juan Quintela
        VMSTATE_UINT8(error, IDEState),
2852 37159f13 Juan Quintela
        VMSTATE_UINT32(nsector, IDEState),
2853 37159f13 Juan Quintela
        VMSTATE_UINT8(sector, IDEState),
2854 37159f13 Juan Quintela
        VMSTATE_UINT8(lcyl, IDEState),
2855 37159f13 Juan Quintela
        VMSTATE_UINT8(hcyl, IDEState),
2856 37159f13 Juan Quintela
        VMSTATE_UINT8(hob_feature, IDEState),
2857 37159f13 Juan Quintela
        VMSTATE_UINT8(hob_sector, IDEState),
2858 37159f13 Juan Quintela
        VMSTATE_UINT8(hob_nsector, IDEState),
2859 37159f13 Juan Quintela
        VMSTATE_UINT8(hob_lcyl, IDEState),
2860 37159f13 Juan Quintela
        VMSTATE_UINT8(hob_hcyl, IDEState),
2861 37159f13 Juan Quintela
        VMSTATE_UINT8(select, IDEState),
2862 37159f13 Juan Quintela
        VMSTATE_UINT8(status, IDEState),
2863 37159f13 Juan Quintela
        VMSTATE_UINT8(lba48, IDEState),
2864 37159f13 Juan Quintela
        VMSTATE_UINT8(sense_key, IDEState),
2865 37159f13 Juan Quintela
        VMSTATE_UINT8(asc, IDEState),
2866 37159f13 Juan Quintela
        VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
2867 37159f13 Juan Quintela
        VMSTATE_END_OF_LIST()
2868 50641c5c Juan Quintela
    },
2869 50641c5c Juan Quintela
    .subsections = (VMStateSubsection []) {
2870 50641c5c Juan Quintela
        {
2871 50641c5c Juan Quintela
            .vmsd = &vmstate_ide_drive_pio_state,
2872 50641c5c Juan Quintela
            .needed = ide_drive_pio_state_needed,
2873 50641c5c Juan Quintela
        }, {
2874 50641c5c Juan Quintela
            /* empty */
2875 50641c5c Juan Quintela
        }
2876 37159f13 Juan Quintela
    }
2877 37159f13 Juan Quintela
};
2878 37159f13 Juan Quintela
2879 6521dc62 Juan Quintela
const VMStateDescription vmstate_ide_bus = {
2880 6521dc62 Juan Quintela
    .name = "ide_bus",
2881 6521dc62 Juan Quintela
    .version_id = 1,
2882 6521dc62 Juan Quintela
    .minimum_version_id = 1,
2883 6521dc62 Juan Quintela
    .minimum_version_id_old = 1,
2884 6521dc62 Juan Quintela
    .fields      = (VMStateField []) {
2885 6521dc62 Juan Quintela
        VMSTATE_UINT8(cmd, IDEBus),
2886 6521dc62 Juan Quintela
        VMSTATE_UINT8(unit, IDEBus),
2887 6521dc62 Juan Quintela
        VMSTATE_END_OF_LIST()
2888 6521dc62 Juan Quintela
    }
2889 6521dc62 Juan Quintela
};
2890 6521dc62 Juan Quintela
2891 69b91039 bellard
/***********************************************************/
2892 69b91039 bellard
/* PCI IDE definitions */
2893 69b91039 bellard
2894 8ccad811 bellard
static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
2895 98087450 bellard
{
2896 bcbdc4d3 Gerd Hoffmann
    BMDMAState *bm = s->bus->bmdma;
2897 98087450 bellard
    if(!bm)
2898 98087450 bellard
        return;
2899 bcbdc4d3 Gerd Hoffmann
    bm->unit = s->unit;
2900 98087450 bellard
    bm->dma_cb = dma_cb;
2901 8ccad811 bellard
    bm->cur_prd_last = 0;
2902 8ccad811 bellard
    bm->cur_prd_addr = 0;
2903 8ccad811 bellard
    bm->cur_prd_len = 0;
2904 428c5705 aliguori
    bm->sector_num = ide_get_sector(s);
2905 428c5705 aliguori
    bm->nsector = s->nsector;
2906 98087450 bellard
    if (bm->status & BM_STATUS_DMAING) {
2907 8ccad811 bellard
        bm->dma_cb(bm, 0);
2908 98087450 bellard
    }
2909 98087450 bellard
}
2910 98087450 bellard
2911 ce4b6522 Kevin Wolf
static void ide_dma_restart(IDEState *s, int is_read)
2912 428c5705 aliguori
{
2913 bcbdc4d3 Gerd Hoffmann
    BMDMAState *bm = s->bus->bmdma;
2914 428c5705 aliguori
    ide_set_sector(s, bm->sector_num);
2915 428c5705 aliguori
    s->io_buffer_index = 0;
2916 428c5705 aliguori
    s->io_buffer_size = 0;
2917 428c5705 aliguori
    s->nsector = bm->nsector;
2918 428c5705 aliguori
    bm->cur_addr = bm->addr;
2919 ce4b6522 Kevin Wolf
2920 ce4b6522 Kevin Wolf
    if (is_read) {
2921 ce4b6522 Kevin Wolf
        bm->dma_cb = ide_read_dma_cb;
2922 ce4b6522 Kevin Wolf
    } else {
2923 ce4b6522 Kevin Wolf
        bm->dma_cb = ide_write_dma_cb;
2924 ce4b6522 Kevin Wolf
    }
2925 ce4b6522 Kevin Wolf
2926 428c5705 aliguori
    ide_dma_start(s, bm->dma_cb);
2927 428c5705 aliguori
}
2928 428c5705 aliguori
2929 356721ae Gerd Hoffmann
void ide_dma_cancel(BMDMAState *bm)
2930 72c7b06c aliguori
{
2931 72c7b06c aliguori
    if (bm->status & BM_STATUS_DMAING) {
2932 72c7b06c aliguori
        if (bm->aiocb) {
2933 72c7b06c aliguori
#ifdef DEBUG_AIO
2934 72c7b06c aliguori
            printf("aio_cancel\n");
2935 72c7b06c aliguori
#endif
2936 72c7b06c aliguori
            bdrv_aio_cancel(bm->aiocb);
2937 72c7b06c aliguori
            bm->aiocb = NULL;
2938 72c7b06c aliguori
        }
2939 38d8dfa1 Kevin Wolf
        bm->status &= ~BM_STATUS_DMAING;
2940 38d8dfa1 Kevin Wolf
        /* cancel DMA request */
2941 38d8dfa1 Kevin Wolf
        bm->unit = -1;
2942 38d8dfa1 Kevin Wolf
        bm->dma_cb = NULL;
2943 72c7b06c aliguori
    }
2944 72c7b06c aliguori
}
2945 72c7b06c aliguori
2946 4a643563 Blue Swirl
void ide_dma_reset(BMDMAState *bm)
2947 4a643563 Blue Swirl
{
2948 4a643563 Blue Swirl
#ifdef DEBUG_IDE
2949 4a643563 Blue Swirl
    printf("ide: dma_reset\n");
2950 4a643563 Blue Swirl
#endif
2951 4a643563 Blue Swirl
    ide_dma_cancel(bm);
2952 4a643563 Blue Swirl
    bm->cmd = 0;
2953 4a643563 Blue Swirl
    bm->status = 0;
2954 4a643563 Blue Swirl
    bm->addr = 0;
2955 4a643563 Blue Swirl
    bm->cur_addr = 0;
2956 4a643563 Blue Swirl
    bm->cur_prd_last = 0;
2957 4a643563 Blue Swirl
    bm->cur_prd_addr = 0;
2958 4a643563 Blue Swirl
    bm->cur_prd_len = 0;
2959 4a643563 Blue Swirl
    bm->sector_num = 0;
2960 4a643563 Blue Swirl
    bm->nsector = 0;
2961 4a643563 Blue Swirl
}