core.c 68.4 KB
Newer Older
B
bellard 已提交
1
/*
2
 * QEMU IDE disk and CD/DVD-ROM Emulator
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003 Fabrice Bellard
5
 * Copyright (c) 2006 Openedhand Ltd.
6
 *
B
bellard 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
G
Gerd Hoffmann 已提交
25 26 27
#include <hw/hw.h>
#include <hw/pc.h>
#include <hw/pci.h>
28
#include <hw/isa.h>
29
#include "qemu-error.h"
P
pbrook 已提交
30 31
#include "qemu-timer.h"
#include "sysemu.h"
32
#include "dma.h"
33
#include "hw/block-common.h"
B
Blue Swirl 已提交
34
#include "blockdev.h"
G
Gerd Hoffmann 已提交
35 36

#include <hw/ide/internal.h>
B
Brian Wheeler 已提交
37

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/* These values were based on a Seagate ST3500418AS but have been modified
   to make more sense in QEMU */
static const int smart_attributes[][12] = {
    /* id,  flags, hflags, val, wrst, raw (6 bytes), threshold */
    /* raw read error rate*/
    { 0x01, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06},
    /* spin up */
    { 0x03, 0x03, 0x00, 0x64, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    /* start stop count */
    { 0x04, 0x02, 0x00, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14},
    /* remapped sectors */
    { 0x05, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24},
    /* power on hours */
    { 0x09, 0x03, 0x00, 0x64, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    /* power cycle count */
    { 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    /* airflow-temperature-celsius */
    { 190,  0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
B
Brian Wheeler 已提交
56 57
};

K
Kevin Wolf 已提交
58
static int ide_handle_rw_error(IDEState *s, int error, int op);
59
static void ide_dummy_transfer_stop(IDEState *s);
B
bellard 已提交
60

B
bellard 已提交
61 62 63 64 65 66 67 68
static void padstr(char *str, const char *src, int len)
{
    int i, v;
    for(i = 0; i < len; i++) {
        if (*src)
            v = *src++;
        else
            v = ' ';
69
        str[i^1] = v;
B
bellard 已提交
70 71 72
    }
}

B
bellard 已提交
73 74
static void put_le16(uint16_t *p, unsigned int v)
{
B
bellard 已提交
75
    *p = cpu_to_le16(v);
B
bellard 已提交
76 77
}

B
bellard 已提交
78 79 80 81
static void ide_identify(IDEState *s)
{
    uint16_t *p;
    unsigned int oldsize;
C
Christoph Hellwig 已提交
82
    IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
B
bellard 已提交
83

84 85 86 87 88
    if (s->identify_set) {
	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
	return;
    }

B
bellard 已提交
89 90
    memset(s->io_buffer, 0, 512);
    p = (uint16_t *)s->io_buffer;
B
bellard 已提交
91
    put_le16(p + 0, 0x0040);
92
    put_le16(p + 1, s->cylinders);
B
bellard 已提交
93 94 95
    put_le16(p + 3, s->heads);
    put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
    put_le16(p + 5, 512); /* XXX: retired, remove ? */
96
    put_le16(p + 6, s->sectors);
97
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
B
bellard 已提交
98 99 100
    put_le16(p + 20, 3); /* XXX: retired, remove ? */
    put_le16(p + 21, 512); /* cache size in sectors */
    put_le16(p + 22, 4); /* ecc bytes */
G
Gerd Hoffmann 已提交
101
    padstr((char *)(p + 23), s->version, 8); /* firmware version */
F
Floris Bos 已提交
102
    padstr((char *)(p + 27), s->drive_model_str, 40); /* model */
103
#if MAX_MULT_SECTORS > 1
B
bellard 已提交
104
    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
B
bellard 已提交
105
#endif
B
bellard 已提交
106
    put_le16(p + 48, 1); /* dword I/O */
107
    put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
B
bellard 已提交
108 109
    put_le16(p + 51, 0x200); /* PIO transfer cycle */
    put_le16(p + 52, 0x200); /* DMA transfer cycle */
110
    put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */
B
bellard 已提交
111 112 113
    put_le16(p + 54, s->cylinders);
    put_le16(p + 55, s->heads);
    put_le16(p + 56, s->sectors);
B
bellard 已提交
114
    oldsize = s->cylinders * s->heads * s->sectors;
B
bellard 已提交
115 116
    put_le16(p + 57, oldsize);
    put_le16(p + 58, oldsize >> 16);
B
bellard 已提交
117
    if (s->mult_sectors)
B
bellard 已提交
118 119 120
        put_le16(p + 59, 0x100 | s->mult_sectors);
    put_le16(p + 60, s->nb_sectors);
    put_le16(p + 61, s->nb_sectors >> 16);
121
    put_le16(p + 62, 0x07); /* single word dma0-2 supported */
122
    put_le16(p + 63, 0x07); /* mdma0-2 supported */
123
    put_le16(p + 64, 0x03); /* pio3-4 supported */
124 125 126 127
    put_le16(p + 65, 120);
    put_le16(p + 66, 120);
    put_le16(p + 67, 120);
    put_le16(p + 68, 120);
C
Christoph Hellwig 已提交
128 129 130
    if (dev && dev->conf.discard_granularity) {
        put_le16(p + 69, (1 << 14)); /* determinate TRIM behavior */
    }
131 132 133 134 135 136 137

    if (s->ncq_queues) {
        put_le16(p + 75, s->ncq_queues - 1);
        /* NCQ supported */
        put_le16(p + 76, (1 << 8));
    }

138 139
    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
    put_le16(p + 81, 0x16); /* conforms to ata5 */
140 141
    /* 14=NOP supported, 5=WCACHE supported, 0=SMART supported */
    put_le16(p + 82, (1 << 14) | (1 << 5) | 1);
B
bellard 已提交
142 143
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
F
Floris Bos 已提交
144 145 146 147 148 149
    /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */
    if (s->wwn) {
        put_le16(p + 84, (1 << 14) | (1 << 8) | 0);
    } else {
        put_le16(p + 84, (1 << 14) | 0);
    }
150 151 152 153 154
    /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */
    if (bdrv_enable_write_cache(s->bs))
         put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
    else
         put_le16(p + 85, (1 << 14) | 1);
B
bellard 已提交
155
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
156
    put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10));
F
Floris Bos 已提交
157 158 159 160 161 162
    /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */
    if (s->wwn) {
        put_le16(p + 87, (1 << 14) | (1 << 8) | 0);
    } else {
        put_le16(p + 87, (1 << 14) | 0);
    }
163 164
    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
    put_le16(p + 93, 1 | (1 << 14) | 0x2000);
B
bellard 已提交
165 166 167 168
    put_le16(p + 100, s->nb_sectors);
    put_le16(p + 101, s->nb_sectors >> 16);
    put_le16(p + 102, s->nb_sectors >> 32);
    put_le16(p + 103, s->nb_sectors >> 48);
C
Christoph Hellwig 已提交
169

170 171
    if (dev && dev->conf.physical_block_size)
        put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
F
Floris Bos 已提交
172 173 174 175 176 177 178
    if (s->wwn) {
        /* LE 16-bit words 111-108 contain 64-bit World Wide Name */
        put_le16(p + 108, s->wwn >> 48);
        put_le16(p + 109, s->wwn >> 32);
        put_le16(p + 110, s->wwn >> 16);
        put_le16(p + 111, s->wwn);
    }
C
Christoph Hellwig 已提交
179 180 181
    if (dev && dev->conf.discard_granularity) {
        put_le16(p + 169, 1); /* TRIM support */
    }
182 183 184

    memcpy(s->identify_data, p, sizeof(s->identify_data));
    s->identify_set = 1;
B
bellard 已提交
185 186 187 188 189 190
}

static void ide_atapi_identify(IDEState *s)
{
    uint16_t *p;

191 192 193 194 195
    if (s->identify_set) {
	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
	return;
    }

B
bellard 已提交
196 197 198
    memset(s->io_buffer, 0, 512);
    p = (uint16_t *)s->io_buffer;
    /* Removable CDROM, 50us response, 12 byte packets */
B
bellard 已提交
199
    put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
200
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
B
bellard 已提交
201 202 203
    put_le16(p + 20, 3); /* buffer type */
    put_le16(p + 21, 512); /* cache size in sectors */
    put_le16(p + 22, 4); /* ecc bytes */
G
Gerd Hoffmann 已提交
204
    padstr((char *)(p + 23), s->version, 8); /* firmware version */
F
Floris Bos 已提交
205
    padstr((char *)(p + 27), s->drive_model_str, 40); /* model */
B
bellard 已提交
206
    put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
207 208 209
#ifdef USE_DMA_CDROM
    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
210
    put_le16(p + 62, 7);  /* single word dma0-2 supported */
211 212
    put_le16(p + 63, 7);  /* mdma0-2 supported */
#else
B
bellard 已提交
213 214 215
    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
    put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
216
#endif
217
    put_le16(p + 64, 3); /* pio3-4 supported */
B
bellard 已提交
218 219 220 221
    put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
    put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
    put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
    put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
222

B
bellard 已提交
223 224
    put_le16(p + 71, 30); /* in ns */
    put_le16(p + 72, 30); /* in ns */
B
bellard 已提交
225

A
Alexander Graf 已提交
226 227 228 229 230 231
    if (s->ncq_queues) {
        put_le16(p + 75, s->ncq_queues - 1);
        /* NCQ supported */
        put_le16(p + 76, (1 << 8));
    }

B
bellard 已提交
232
    put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
233 234 235
#ifdef USE_DMA_CDROM
    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
#endif
236 237
    memcpy(s->identify_data, p, sizeof(s->identify_data));
    s->identify_set = 1;
B
bellard 已提交
238 239
}

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
static void ide_cfata_identify(IDEState *s)
{
    uint16_t *p;
    uint32_t cur_sec;

    p = (uint16_t *) s->identify_data;
    if (s->identify_set)
        goto fill_buffer;

    memset(p, 0, sizeof(s->identify_data));

    cur_sec = s->cylinders * s->heads * s->sectors;

    put_le16(p + 0, 0x848a);			/* CF Storage Card signature */
    put_le16(p + 1, s->cylinders);		/* Default cylinders */
    put_le16(p + 3, s->heads);			/* Default heads */
    put_le16(p + 6, s->sectors);		/* Default sectors per track */
    put_le16(p + 7, s->nb_sectors >> 16);	/* Sectors per card */
    put_le16(p + 8, s->nb_sectors);		/* Sectors per card */
259
    padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
260
    put_le16(p + 22, 0x0004);			/* ECC bytes */
G
Gerd Hoffmann 已提交
261
    padstr((char *) (p + 23), s->version, 8);	/* Firmware Revision */
F
Floris Bos 已提交
262
    padstr((char *) (p + 27), s->drive_model_str, 40);/* Model number */
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
#if MAX_MULT_SECTORS > 1
    put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
#else
    put_le16(p + 47, 0x0000);
#endif
    put_le16(p + 49, 0x0f00);			/* Capabilities */
    put_le16(p + 51, 0x0002);			/* PIO cycle timing mode */
    put_le16(p + 52, 0x0001);			/* DMA cycle timing mode */
    put_le16(p + 53, 0x0003);			/* Translation params valid */
    put_le16(p + 54, s->cylinders);		/* Current cylinders */
    put_le16(p + 55, s->heads);			/* Current heads */
    put_le16(p + 56, s->sectors);		/* Current sectors */
    put_le16(p + 57, cur_sec);			/* Current capacity */
    put_le16(p + 58, cur_sec >> 16);		/* Current capacity */
    if (s->mult_sectors)			/* Multiple sector setting */
        put_le16(p + 59, 0x100 | s->mult_sectors);
    put_le16(p + 60, s->nb_sectors);		/* Total LBA sectors */
    put_le16(p + 61, s->nb_sectors >> 16);	/* Total LBA sectors */
    put_le16(p + 63, 0x0203);			/* Multiword DMA capability */
    put_le16(p + 64, 0x0001);			/* Flow Control PIO support */
    put_le16(p + 65, 0x0096);			/* Min. Multiword DMA cycle */
    put_le16(p + 66, 0x0096);			/* Rec. Multiword DMA cycle */
    put_le16(p + 68, 0x00b4);			/* Min. PIO cycle time */
    put_le16(p + 82, 0x400c);			/* Command Set supported */
    put_le16(p + 83, 0x7068);			/* Command Set supported */
    put_le16(p + 84, 0x4000);			/* Features supported */
    put_le16(p + 85, 0x000c);			/* Command Set enabled */
    put_le16(p + 86, 0x7044);			/* Command Set enabled */
    put_le16(p + 87, 0x4000);			/* Features enabled */
    put_le16(p + 91, 0x4060);			/* Current APM level */
    put_le16(p + 129, 0x0002);			/* Current features option */
    put_le16(p + 130, 0x0005);			/* Reassigned sectors */
    put_le16(p + 131, 0x0001);			/* Initial power mode */
    put_le16(p + 132, 0x0000);			/* User signature */
    put_le16(p + 160, 0x8100);			/* Power requirement */
    put_le16(p + 161, 0x8001);			/* CF command set */

    s->identify_set = 1;

fill_buffer:
    memcpy(s->io_buffer, p, sizeof(s->identify_data));
}

B
bellard 已提交
306 307 308 309 310 311
static void ide_set_signature(IDEState *s)
{
    s->select &= 0xf0; /* clear head */
    /* put signature */
    s->nsector = 1;
    s->sector = 1;
312
    if (s->drive_kind == IDE_CD) {
B
bellard 已提交
313 314 315 316 317 318 319 320 321 322 323
        s->lcyl = 0x14;
        s->hcyl = 0xeb;
    } else if (s->bs) {
        s->lcyl = 0;
        s->hcyl = 0;
    } else {
        s->lcyl = 0xff;
        s->hcyl = 0xff;
    }
}

C
Christoph Hellwig 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
typedef struct TrimAIOCB {
    BlockDriverAIOCB common;
    QEMUBH *bh;
    int ret;
} TrimAIOCB;

static void trim_aio_cancel(BlockDriverAIOCB *acb)
{
    TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);

    qemu_bh_delete(iocb->bh);
    iocb->bh = NULL;
    qemu_aio_release(iocb);
}

static AIOPool trim_aio_pool = {
    .aiocb_size         = sizeof(TrimAIOCB),
    .cancel             = trim_aio_cancel,
};

static void ide_trim_bh_cb(void *opaque)
{
    TrimAIOCB *iocb = opaque;

    iocb->common.cb(iocb->common.opaque, iocb->ret);

    qemu_bh_delete(iocb->bh);
    iocb->bh = NULL;

    qemu_aio_release(iocb);
}

BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        BlockDriverCompletionFunc *cb, void *opaque)
{
    TrimAIOCB *iocb;
    int i, j, ret;

    iocb = qemu_aio_get(&trim_aio_pool, bs, cb, opaque);
    iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
    iocb->ret = 0;

    for (j = 0; j < qiov->niov; j++) {
        uint64_t *buffer = qiov->iov[j].iov_base;

        for (i = 0; i < qiov->iov[j].iov_len / 8; i++) {
            /* 6-byte LBA + 2-byte range per entry */
            uint64_t entry = le64_to_cpu(buffer[i]);
            uint64_t sector = entry & 0x0000ffffffffffffULL;
            uint16_t count = entry >> 48;

            if (count == 0) {
                break;
            }

            ret = bdrv_discard(bs, sector, count);
            if (!iocb->ret) {
                iocb->ret = ret;
            }
        }
    }

    qemu_bh_schedule(iocb->bh);

    return &iocb->common;
}

B
bellard 已提交
392 393 394 395 396 397 398
static inline void ide_abort_command(IDEState *s)
{
    s->status = READY_STAT | ERR_STAT;
    s->error = ABRT_ERR;
}

/* prepare data transfer and tell what to do after */
K
Kevin Wolf 已提交
399 400
void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                        EndTransferFunc *end_transfer_func)
B
bellard 已提交
401 402 403 404
{
    s->end_transfer_func = end_transfer_func;
    s->data_ptr = buf;
    s->data_end = buf + size;
405
    if (!(s->status & ERR_STAT)) {
406
        s->status |= DRQ_STAT;
407 408
    }
    s->bus->dma->ops->start_transfer(s->bus->dma);
B
bellard 已提交
409 410
}

K
Kevin Wolf 已提交
411
void ide_transfer_stop(IDEState *s)
B
bellard 已提交
412 413 414 415 416 417 418
{
    s->end_transfer_func = ide_transfer_stop;
    s->data_ptr = s->io_buffer;
    s->data_end = s->io_buffer;
    s->status &= ~DRQ_STAT;
}

G
Gerd Hoffmann 已提交
419
int64_t ide_get_sector(IDEState *s)
B
bellard 已提交
420 421 422 423
{
    int64_t sector_num;
    if (s->select & 0x40) {
        /* lba */
B
bellard 已提交
424 425 426 427 428 429 430 431 432 433
	if (!s->lba48) {
	    sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
		(s->lcyl << 8) | s->sector;
	} else {
	    sector_num = ((int64_t)s->hob_hcyl << 40) |
		((int64_t) s->hob_lcyl << 32) |
		((int64_t) s->hob_sector << 24) |
		((int64_t) s->hcyl << 16) |
		((int64_t) s->lcyl << 8) | s->sector;
	}
B
bellard 已提交
434 435
    } else {
        sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
B
bellard 已提交
436
            (s->select & 0x0f) * s->sectors + (s->sector - 1);
B
bellard 已提交
437 438 439 440
    }
    return sector_num;
}

G
Gerd Hoffmann 已提交
441
void ide_set_sector(IDEState *s, int64_t sector_num)
B
bellard 已提交
442 443 444
{
    unsigned int cyl, r;
    if (s->select & 0x40) {
B
bellard 已提交
445 446 447 448 449 450 451 452 453 454 455 456 457
	if (!s->lba48) {
            s->select = (s->select & 0xf0) | (sector_num >> 24);
            s->hcyl = (sector_num >> 16);
            s->lcyl = (sector_num >> 8);
            s->sector = (sector_num);
	} else {
	    s->sector = sector_num;
	    s->lcyl = sector_num >> 8;
	    s->hcyl = sector_num >> 16;
	    s->hob_sector = sector_num >> 24;
	    s->hob_lcyl = sector_num >> 32;
	    s->hob_hcyl = sector_num >> 40;
	}
B
bellard 已提交
458 459 460 461 462
    } else {
        cyl = sector_num / (s->heads * s->sectors);
        r = sector_num % (s->heads * s->sectors);
        s->hcyl = cyl >> 8;
        s->lcyl = cyl;
463
        s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
B
bellard 已提交
464 465 466 467
        s->sector = (r % s->sectors) + 1;
    }
}

468 469
static void ide_rw_error(IDEState *s) {
    ide_abort_command(s);
470
    ide_set_irq(s->bus);
471 472
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
static void ide_sector_read_cb(void *opaque, int ret)
{
    IDEState *s = opaque;
    int n;

    s->pio_aiocb = NULL;
    s->status &= ~BUSY_STAT;

    bdrv_acct_done(s->bs, &s->acct);
    if (ret != 0) {
        if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY |
                                BM_STATUS_RETRY_READ)) {
            return;
        }
    }

    n = s->nsector;
    if (n > s->req_nb_sectors) {
        n = s->req_nb_sectors;
    }

    /* Allow the guest to read the io_buffer */
    ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read);

    ide_set_irq(s->bus);

    ide_set_sector(s, ide_get_sector(s) + n);
    s->nsector -= n;
}

503
void ide_sector_read(IDEState *s)
B
bellard 已提交
504 505
{
    int64_t sector_num;
506
    int n;
B
bellard 已提交
507 508

    s->status = READY_STAT | SEEK_STAT;
509
    s->error = 0; /* not needed by IDE spec, but needed by Windows */
B
bellard 已提交
510 511
    sector_num = ide_get_sector(s);
    n = s->nsector;
512

B
bellard 已提交
513 514
    if (n == 0) {
        ide_transfer_stop(s);
515 516 517 518 519 520 521 522 523
        return;
    }

    s->status |= BUSY_STAT;

    if (n > s->req_nb_sectors) {
        n = s->req_nb_sectors;
    }

B
bellard 已提交
524
#if defined(DEBUG_IDE)
525
    printf("sector=%" PRId64 "\n", sector_num);
B
bellard 已提交
526
#endif
527

528 529 530 531 532 533 534
    s->iov.iov_base = s->io_buffer;
    s->iov.iov_len  = n * BDRV_SECTOR_SIZE;
    qemu_iovec_init_external(&s->qiov, &s->iov, 1);

    bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
    s->pio_aiocb = bdrv_aio_readv(s->bs, sector_num, &s->qiov, n,
                                  ide_sector_read_cb, s);
B
bellard 已提交
535 536
}

537
static void dma_buf_commit(IDEState *s)
538
{
539
    qemu_sglist_destroy(&s->sg);
540 541
}

K
Kevin Wolf 已提交
542
void ide_set_inactive(IDEState *s)
K
Kevin Wolf 已提交
543
{
544 545
    s->bus->dma->aiocb = NULL;
    s->bus->dma->ops->set_inactive(s->bus->dma);
K
Kevin Wolf 已提交
546 547
}

G
Gerd Hoffmann 已提交
548
void ide_dma_error(IDEState *s)
549 550 551 552
{
    ide_transfer_stop(s);
    s->error = ABRT_ERR;
    s->status = READY_STAT | ERR_STAT;
553
    ide_set_inactive(s);
554
    ide_set_irq(s->bus);
555 556
}

K
Kevin Wolf 已提交
557
static int ide_handle_rw_error(IDEState *s, int error, int op)
558
{
559
    bool is_read = (op & BM_STATUS_RETRY_READ) != 0;
560
    BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error);
561

562
    if (action == BDRV_ACTION_STOP) {
563
        s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
564
        s->bus->error_status = op;
565
    } else if (action == BDRV_ACTION_REPORT) {
K
Kevin Wolf 已提交
566
        if (op & BM_STATUS_DMA_RETRY) {
567
            dma_buf_commit(s);
568
            ide_dma_error(s);
569
        } else {
570
            ide_rw_error(s);
571
        }
572
    }
573 574
    bdrv_error_action(s->bs, action, is_read, error);
    return action != BDRV_ACTION_IGNORE;
575 576
}

577
void ide_dma_cb(void *opaque, int ret)
B
bellard 已提交
578
{
579
    IDEState *s = opaque;
580 581 582
    int n;
    int64_t sector_num;

583
    if (ret < 0) {
584 585
        int op = BM_STATUS_DMA_RETRY;

586
        if (s->dma_cmd == IDE_DMA_READ)
587
            op |= BM_STATUS_RETRY_READ;
C
Christoph Hellwig 已提交
588 589 590
        else if (s->dma_cmd == IDE_DMA_TRIM)
            op |= BM_STATUS_RETRY_TRIM;

591
        if (ide_handle_rw_error(s, -ret, op)) {
K
Kevin Wolf 已提交
592 593
            return;
        }
594 595
    }

596 597 598
    n = s->io_buffer_size >> 9;
    sector_num = ide_get_sector(s);
    if (n > 0) {
599
        dma_buf_commit(s);
600 601 602 603 604 605 606
        sector_num += n;
        ide_set_sector(s, sector_num);
        s->nsector -= n;
    }

    /* end of transfer ? */
    if (s->nsector == 0) {
B
bellard 已提交
607
        s->status = READY_STAT | SEEK_STAT;
608
        ide_set_irq(s->bus);
609
        goto eot;
B
bellard 已提交
610
    }
611 612 613

    /* launch next transfer */
    n = s->nsector;
614
    s->io_buffer_index = 0;
615
    s->io_buffer_size = n * 512;
616
    if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) {
617 618
        /* The PRDs were too short. Reset the Active bit, but don't raise an
         * interrupt. */
619
        goto eot;
620
    }
621

622
#ifdef DEBUG_AIO
623 624
    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, cmd_cmd=%d\n",
           sector_num, n, s->dma_cmd);
625
#endif
626

627 628
    switch (s->dma_cmd) {
    case IDE_DMA_READ:
629 630
        s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
                                           ide_dma_cb, s);
631 632
        break;
    case IDE_DMA_WRITE:
633 634
        s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                            ide_dma_cb, s);
635
        break;
C
Christoph Hellwig 已提交
636 637
    case IDE_DMA_TRIM:
        s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
638 639
                                         ide_issue_trim, ide_dma_cb, s,
                                         DMA_DIRECTION_TO_DEVICE);
C
Christoph Hellwig 已提交
640
        break;
641 642 643 644
    }
    return;

eot:
645 646 647 648
    if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
        bdrv_acct_done(s->bs, &s->acct);
    }
    ide_set_inactive(s);
B
bellard 已提交
649 650
}

651
static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
B
bellard 已提交
652
{
653
    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
B
bellard 已提交
654 655
    s->io_buffer_index = 0;
    s->io_buffer_size = 0;
656
    s->dma_cmd = dma_cmd;
657 658 659 660 661 662 663 664 665 666 667 668 669 670

    switch (dma_cmd) {
    case IDE_DMA_READ:
        bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
                        BDRV_ACCT_READ);
        break;
    case IDE_DMA_WRITE:
        bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
                        BDRV_ACCT_WRITE);
        break;
    default:
        break;
    }

671
    s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb);
B
bellard 已提交
672 673
}

674 675 676
static void ide_sector_write_timer_cb(void *opaque)
{
    IDEState *s = opaque;
677
    ide_set_irq(s->bus);
678 679
}

680
static void ide_sector_write_cb(void *opaque, int ret)
B
bellard 已提交
681
{
682 683
    IDEState *s = opaque;
    int n;
684 685

    bdrv_acct_done(s->bs, &s->acct);
686

687 688 689
    s->pio_aiocb = NULL;
    s->status &= ~BUSY_STAT;

690
    if (ret != 0) {
691
        if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) {
692
            return;
693
        }
694 695
    }

696 697 698 699
    n = s->nsector;
    if (n > s->req_nb_sectors) {
        n = s->req_nb_sectors;
    }
B
bellard 已提交
700 701
    s->nsector -= n;
    if (s->nsector == 0) {
T
ths 已提交
702
        /* no more sectors to write */
B
bellard 已提交
703 704
        ide_transfer_stop(s);
    } else {
705 706
        int n1 = s->nsector;
        if (n1 > s->req_nb_sectors) {
B
bellard 已提交
707
            n1 = s->req_nb_sectors;
708 709 710
        }
        ide_transfer_start(s, s->io_buffer, n1 * BDRV_SECTOR_SIZE,
                           ide_sector_write);
B
bellard 已提交
711
    }
712
    ide_set_sector(s, ide_get_sector(s) + n);
713

714 715 716 717 718 719 720
    if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
        /* It seems there is a bug in the Windows 2000 installer HDD
           IDE driver which fills the disk with empty logs when the
           IDE write IRQ comes too early. This hack tries to correct
           that at the expense of slower write performances. Use this
           option _only_ to install Windows 2000. You must disable it
           for normal use. */
B
Blue Swirl 已提交
721
        qemu_mod_timer(s->sector_write_timer,
722
                       qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 1000));
B
Blue Swirl 已提交
723
    } else {
724
        ide_set_irq(s->bus);
725
    }
B
bellard 已提交
726 727
}

728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
void ide_sector_write(IDEState *s)
{
    int64_t sector_num;
    int n;

    s->status = READY_STAT | SEEK_STAT | BUSY_STAT;
    sector_num = ide_get_sector(s);
#if defined(DEBUG_IDE)
    printf("sector=%" PRId64 "\n", sector_num);
#endif
    n = s->nsector;
    if (n > s->req_nb_sectors) {
        n = s->req_nb_sectors;
    }

    s->iov.iov_base = s->io_buffer;
    s->iov.iov_len  = n * BDRV_SECTOR_SIZE;
    qemu_iovec_init_external(&s->qiov, &s->iov, 1);

    bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
    s->pio_aiocb = bdrv_aio_writev(s->bs, sector_num, &s->qiov, n,
                                   ide_sector_write_cb, s);
}

C
Christoph Hellwig 已提交
752 753 754 755
static void ide_flush_cb(void *opaque, int ret)
{
    IDEState *s = opaque;

K
Kevin Wolf 已提交
756 757 758 759 760 761
    if (ret < 0) {
        /* XXX: What sector number to set here? */
        if (ide_handle_rw_error(s, -ret, BM_STATUS_RETRY_FLUSH)) {
            return;
        }
    }
C
Christoph Hellwig 已提交
762

763
    bdrv_acct_done(s->bs, &s->acct);
C
Christoph Hellwig 已提交
764 765 766 767
    s->status = READY_STAT | SEEK_STAT;
    ide_set_irq(s->bus);
}

768
void ide_flush_cache(IDEState *s)
K
Kevin Wolf 已提交
769
{
770
    if (s->bs == NULL) {
K
Kevin Wolf 已提交
771
        ide_flush_cb(s, 0);
772 773 774
        return;
    }

775
    bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
776
    bdrv_aio_flush(s->bs, ide_flush_cb, s);
K
Kevin Wolf 已提交
777 778
}

779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
static void ide_cfata_metadata_inquiry(IDEState *s)
{
    uint16_t *p;
    uint32_t spd;

    p = (uint16_t *) s->io_buffer;
    memset(p, 0, 0x200);
    spd = ((s->mdata_size - 1) >> 9) + 1;

    put_le16(p + 0, 0x0001);			/* Data format revision */
    put_le16(p + 1, 0x0000);			/* Media property: silicon */
    put_le16(p + 2, s->media_changed);		/* Media status */
    put_le16(p + 3, s->mdata_size & 0xffff);	/* Capacity in bytes (low) */
    put_le16(p + 4, s->mdata_size >> 16);	/* Capacity in bytes (high) */
    put_le16(p + 5, spd & 0xffff);		/* Sectors per device (low) */
    put_le16(p + 6, spd >> 16);			/* Sectors per device (high) */
}

static void ide_cfata_metadata_read(IDEState *s)
{
    uint16_t *p;

    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
        s->status = ERR_STAT;
        s->error = ABRT_ERR;
        return;
    }

    p = (uint16_t *) s->io_buffer;
    memset(p, 0, 0x200);

    put_le16(p + 0, s->media_changed);		/* Media status */
    memcpy(p + 1, s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
                                    s->nsector << 9), 0x200 - 2));
}

static void ide_cfata_metadata_write(IDEState *s)
{
    if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
        s->status = ERR_STAT;
        s->error = ABRT_ERR;
        return;
    }

    s->media_changed = 0;

    memcpy(s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
                    s->io_buffer + 2,
                    MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
                                    s->nsector << 9), 0x200 - 2));
}

T
ths 已提交
832
/* called when the inserted state of the media has changed */
833
static void ide_cd_change_cb(void *opaque, bool load)
T
ths 已提交
834 835
{
    IDEState *s = opaque;
836
    uint64_t nb_sectors;
T
ths 已提交
837

838
    s->tray_open = !load;
T
ths 已提交
839 840
    bdrv_get_geometry(s->bs, &nb_sectors);
    s->nb_sectors = nb_sectors;
841

842 843 844 845
    /*
     * First indicate to the guest that a CD has been removed.  That's
     * done on the next command the guest sends us.
     *
846
     * Then we set UNIT_ATTENTION, by which the guest will
847 848
     * detect a new CD in the drive.  See ide_atapi_cmd() for details.
     */
G
Gleb Natapov 已提交
849
    s->cdrom_changed = 1;
850
    s->events.new_media = true;
P
Paolo Bonzini 已提交
851 852 853 854 855 856 857 858 859 860 861 862
    s->events.eject_request = false;
    ide_set_irq(s->bus);
}

static void ide_cd_eject_request_cb(void *opaque, bool force)
{
    IDEState *s = opaque;

    s->events.eject_request = true;
    if (force) {
        s->tray_locked = false;
    }
863
    ide_set_irq(s->bus);
T
ths 已提交
864 865
}

B
bellard 已提交
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
static void ide_cmd_lba48_transform(IDEState *s, int lba48)
{
    s->lba48 = lba48;

    /* handle the 'magic' 0 nsector count conversion here. to avoid
     * fiddling with the rest of the read logic, we just store the
     * full sector count in ->nsector and ignore ->hob_nsector from now
     */
    if (!s->lba48) {
	if (!s->nsector)
	    s->nsector = 256;
    } else {
	if (!s->nsector && !s->hob_nsector)
	    s->nsector = 65536;
	else {
	    int lo = s->nsector;
	    int hi = s->hob_nsector;

	    s->nsector = (hi << 8) | lo;
	}
    }
}

G
Gerd Hoffmann 已提交
889
static void ide_clear_hob(IDEBus *bus)
B
bellard 已提交
890 891
{
    /* any write clears HOB high bit of device control register */
G
Gerd Hoffmann 已提交
892 893
    bus->ifs[0].select &= ~(1 << 7);
    bus->ifs[1].select &= ~(1 << 7);
B
bellard 已提交
894 895
}

G
Gerd Hoffmann 已提交
896
void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
897
{
G
Gerd Hoffmann 已提交
898
    IDEBus *bus = opaque;
B
bellard 已提交
899 900 901 902

#ifdef DEBUG_IDE
    printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
#endif
B
bellard 已提交
903

B
bellard 已提交
904
    addr &= 7;
905 906

    /* ignore writes to command block while busy with previous command */
G
Gerd Hoffmann 已提交
907
    if (addr != 7 && (idebus_active_if(bus)->status & (BUSY_STAT|DRQ_STAT)))
908 909
        return;

B
bellard 已提交
910 911 912 913
    switch(addr) {
    case 0:
        break;
    case 1:
G
Gerd Hoffmann 已提交
914
	ide_clear_hob(bus);
915
        /* NOTE: data is written to the two drives */
G
Gerd Hoffmann 已提交
916 917 918 919
	bus->ifs[0].hob_feature = bus->ifs[0].feature;
	bus->ifs[1].hob_feature = bus->ifs[1].feature;
        bus->ifs[0].feature = val;
        bus->ifs[1].feature = val;
B
bellard 已提交
920 921
        break;
    case 2:
G
Gerd Hoffmann 已提交
922 923 924 925 926
	ide_clear_hob(bus);
	bus->ifs[0].hob_nsector = bus->ifs[0].nsector;
	bus->ifs[1].hob_nsector = bus->ifs[1].nsector;
        bus->ifs[0].nsector = val;
        bus->ifs[1].nsector = val;
B
bellard 已提交
927 928
        break;
    case 3:
G
Gerd Hoffmann 已提交
929 930 931 932 933
	ide_clear_hob(bus);
	bus->ifs[0].hob_sector = bus->ifs[0].sector;
	bus->ifs[1].hob_sector = bus->ifs[1].sector;
        bus->ifs[0].sector = val;
        bus->ifs[1].sector = val;
B
bellard 已提交
934 935
        break;
    case 4:
G
Gerd Hoffmann 已提交
936 937 938 939 940
	ide_clear_hob(bus);
	bus->ifs[0].hob_lcyl = bus->ifs[0].lcyl;
	bus->ifs[1].hob_lcyl = bus->ifs[1].lcyl;
        bus->ifs[0].lcyl = val;
        bus->ifs[1].lcyl = val;
B
bellard 已提交
941 942
        break;
    case 5:
G
Gerd Hoffmann 已提交
943 944 945 946 947
	ide_clear_hob(bus);
	bus->ifs[0].hob_hcyl = bus->ifs[0].hcyl;
	bus->ifs[1].hob_hcyl = bus->ifs[1].hcyl;
        bus->ifs[0].hcyl = val;
        bus->ifs[1].hcyl = val;
B
bellard 已提交
948 949
        break;
    case 6:
B
bellard 已提交
950
	/* FIXME: HOB readback uses bit 7 */
G
Gerd Hoffmann 已提交
951 952
        bus->ifs[0].select = (val & ~0x10) | 0xa0;
        bus->ifs[1].select = (val | 0x10) | 0xa0;
B
bellard 已提交
953
        /* select drive */
G
Gerd Hoffmann 已提交
954
        bus->unit = (val >> 4) & 1;
B
bellard 已提交
955 956 957 958
        break;
    default:
    case 7:
        /* command */
959 960 961 962 963
        ide_exec_cmd(bus, val);
        break;
    }
}

964 965 966 967 968 969 970 971 972 973 974 975
#define HD_OK (1u << IDE_HD)
#define CD_OK (1u << IDE_CD)
#define CFA_OK (1u << IDE_CFATA)
#define HD_CFA_OK (HD_OK | CFA_OK)
#define ALL_OK (HD_OK | CD_OK | CFA_OK)

/* See ACS-2 T13/2015-D Table B.2 Command codes */
static const uint8_t ide_cmd_table[0x100] = {
    /* NOP not implemented, mandatory for CD */
    [CFA_REQ_EXT_ERROR_CODE]            = CFA_OK,
    [WIN_DSM]                           = ALL_OK,
    [WIN_DEVICE_RESET]                  = CD_OK,
976
    [WIN_RECAL]                         = HD_CFA_OK,
977 978
    [WIN_READ]                          = ALL_OK,
    [WIN_READ_ONCE]                     = ALL_OK,
979 980 981 982 983 984 985 986 987 988 989 990 991 992
    [WIN_READ_EXT]                      = HD_CFA_OK,
    [WIN_READDMA_EXT]                   = HD_CFA_OK,
    [WIN_READ_NATIVE_MAX_EXT]           = HD_CFA_OK,
    [WIN_MULTREAD_EXT]                  = HD_CFA_OK,
    [WIN_WRITE]                         = HD_CFA_OK,
    [WIN_WRITE_ONCE]                    = HD_CFA_OK,
    [WIN_WRITE_EXT]                     = HD_CFA_OK,
    [WIN_WRITEDMA_EXT]                  = HD_CFA_OK,
    [CFA_WRITE_SECT_WO_ERASE]           = CFA_OK,
    [WIN_MULTWRITE_EXT]                 = HD_CFA_OK,
    [WIN_WRITE_VERIFY]                  = HD_CFA_OK,
    [WIN_VERIFY]                        = HD_CFA_OK,
    [WIN_VERIFY_ONCE]                   = HD_CFA_OK,
    [WIN_VERIFY_EXT]                    = HD_CFA_OK,
993 994 995
    [WIN_SEEK]                          = HD_CFA_OK,
    [CFA_TRANSLATE_SECTOR]              = CFA_OK,
    [WIN_DIAGNOSE]                      = ALL_OK,
996
    [WIN_SPECIFY]                       = HD_CFA_OK,
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
    [WIN_STANDBYNOW2]                   = ALL_OK,
    [WIN_IDLEIMMEDIATE2]                = ALL_OK,
    [WIN_STANDBY2]                      = ALL_OK,
    [WIN_SETIDLE2]                      = ALL_OK,
    [WIN_CHECKPOWERMODE2]               = ALL_OK,
    [WIN_SLEEPNOW2]                     = ALL_OK,
    [WIN_PACKETCMD]                     = CD_OK,
    [WIN_PIDENTIFY]                     = CD_OK,
    [WIN_SMART]                         = HD_CFA_OK,
    [CFA_ACCESS_METADATA_STORAGE]       = CFA_OK,
    [CFA_ERASE_SECTORS]                 = CFA_OK,
1008 1009 1010 1011 1012 1013 1014 1015
    [WIN_MULTREAD]                      = HD_CFA_OK,
    [WIN_MULTWRITE]                     = HD_CFA_OK,
    [WIN_SETMULT]                       = HD_CFA_OK,
    [WIN_READDMA]                       = HD_CFA_OK,
    [WIN_READDMA_ONCE]                  = HD_CFA_OK,
    [WIN_WRITEDMA]                      = HD_CFA_OK,
    [WIN_WRITEDMA_ONCE]                 = HD_CFA_OK,
    [CFA_WRITE_MULTI_WO_ERASE]          = CFA_OK,
1016 1017 1018 1019 1020 1021 1022
    [WIN_STANDBYNOW1]                   = ALL_OK,
    [WIN_IDLEIMMEDIATE]                 = ALL_OK,
    [WIN_STANDBY]                       = ALL_OK,
    [WIN_SETIDLE1]                      = ALL_OK,
    [WIN_CHECKPOWERMODE1]               = ALL_OK,
    [WIN_SLEEPNOW1]                     = ALL_OK,
    [WIN_FLUSH_CACHE]                   = ALL_OK,
1023
    [WIN_FLUSH_CACHE_EXT]               = HD_CFA_OK,
1024 1025 1026
    [WIN_IDENTIFY]                      = ALL_OK,
    [WIN_SETFEATURES]                   = ALL_OK,
    [IBM_SENSE_CONDITION]               = CFA_OK,
1027
    [CFA_WEAR_LEVEL]                    = HD_CFA_OK,
1028 1029 1030 1031 1032 1033 1034 1035
    [WIN_READ_NATIVE_MAX]               = ALL_OK,
};

static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
{
    return cmd < ARRAY_SIZE(ide_cmd_table)
        && (ide_cmd_table[cmd] & (1u << s->drive_kind));
}
1036 1037 1038

void ide_exec_cmd(IDEBus *bus, uint32_t val)
{
1039
    uint16_t *identify_data;
1040 1041 1042 1043
    IDEState *s;
    int n;
    int lba48 = 0;

B
bellard 已提交
1044
#if defined(DEBUG_IDE)
1045
    printf("ide: CMD=%02x\n", val);
B
bellard 已提交
1046
#endif
1047
    s = idebus_active_if(bus);
D
Dong Xu Wang 已提交
1048
    /* ignore commands to non existent slave */
1049 1050
    if (s != bus->ifs && !s->bs)
        return;
B
bellard 已提交
1051

1052 1053 1054
    /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */
    if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)
        return;
1055

1056 1057 1058 1059
    if (!ide_cmd_permitted(s, val)) {
        goto abort_cmd;
    }

1060
    switch(val) {
C
Christoph Hellwig 已提交
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
    case WIN_DSM:
        switch (s->feature) {
        case DSM_TRIM:
            if (!s->bs) {
                goto abort_cmd;
            }
            ide_sector_start_dma(s, IDE_DMA_TRIM);
            break;
        default:
            goto abort_cmd;
        }
        break;
1073 1074 1075 1076 1077 1078
    case WIN_IDENTIFY:
        if (s->bs && s->drive_kind != IDE_CD) {
            if (s->drive_kind != IDE_CFATA)
                ide_identify(s);
            else
                ide_cfata_identify(s);
B
bellard 已提交
1079
            s->status = READY_STAT | SEEK_STAT;
1080 1081 1082 1083
            ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
        } else {
            if (s->drive_kind == IDE_CD) {
                ide_set_signature(s);
B
bellard 已提交
1084
            }
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
            ide_abort_command(s);
        }
        ide_set_irq(s->bus);
        break;
    case WIN_SPECIFY:
    case WIN_RECAL:
        s->error = 0;
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
    case WIN_SETMULT:
        if (s->drive_kind == IDE_CFATA && s->nsector == 0) {
            /* Disable Read and Write Multiple */
            s->mult_sectors = 0;
A
aliguori 已提交
1099
            s->status = READY_STAT | SEEK_STAT;
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
        } else if ((s->nsector & 0xff) != 0 &&
            ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
             (s->nsector & (s->nsector - 1)) != 0)) {
            ide_abort_command(s);
        } else {
            s->mult_sectors = s->nsector & 0xff;
            s->status = READY_STAT | SEEK_STAT;
        }
        ide_set_irq(s->bus);
        break;
    case WIN_VERIFY_EXT:
	lba48 = 1;
    case WIN_VERIFY:
    case WIN_VERIFY_ONCE:
        /* do sector number check ? */
	ide_cmd_lba48_transform(s, lba48);
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
1119
    case WIN_READ_EXT:
1120 1121 1122
	lba48 = 1;
    case WIN_READ:
    case WIN_READ_ONCE:
1123 1124
        if (s->drive_kind == IDE_CD) {
            ide_set_signature(s); /* odd, but ATA4 8.27.5.2 requires it */
1125
            goto abort_cmd;
1126
        }
P
Paolo Bonzini 已提交
1127 1128 1129
        if (!s->bs) {
            goto abort_cmd;
        }
1130 1131 1132 1133
	ide_cmd_lba48_transform(s, lba48);
        s->req_nb_sectors = 1;
        ide_sector_read(s);
        break;
1134
    case WIN_WRITE_EXT:
1135 1136 1137 1138 1139
	lba48 = 1;
    case WIN_WRITE:
    case WIN_WRITE_ONCE:
    case CFA_WRITE_SECT_WO_ERASE:
    case WIN_WRITE_VERIFY:
P
Paolo Bonzini 已提交
1140 1141 1142
        if (!s->bs) {
            goto abort_cmd;
        }
1143 1144 1145 1146 1147 1148 1149
	ide_cmd_lba48_transform(s, lba48);
        s->error = 0;
        s->status = SEEK_STAT | READY_STAT;
        s->req_nb_sectors = 1;
        ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
        s->media_changed = 1;
        break;
1150
    case WIN_MULTREAD_EXT:
1151 1152
	lba48 = 1;
    case WIN_MULTREAD:
P
Paolo Bonzini 已提交
1153 1154 1155 1156
        if (!s->bs) {
            goto abort_cmd;
        }
        if (!s->mult_sectors) {
1157
            goto abort_cmd;
P
Paolo Bonzini 已提交
1158
        }
1159 1160 1161 1162 1163 1164 1165 1166
	ide_cmd_lba48_transform(s, lba48);
        s->req_nb_sectors = s->mult_sectors;
        ide_sector_read(s);
        break;
    case WIN_MULTWRITE_EXT:
	lba48 = 1;
    case WIN_MULTWRITE:
    case CFA_WRITE_MULTI_WO_ERASE:
P
Paolo Bonzini 已提交
1167 1168 1169 1170
        if (!s->bs) {
            goto abort_cmd;
        }
        if (!s->mult_sectors) {
1171
            goto abort_cmd;
P
Paolo Bonzini 已提交
1172
        }
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
	ide_cmd_lba48_transform(s, lba48);
        s->error = 0;
        s->status = SEEK_STAT | READY_STAT;
        s->req_nb_sectors = s->mult_sectors;
        n = s->nsector;
        if (n > s->req_nb_sectors)
            n = s->req_nb_sectors;
        ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
        s->media_changed = 1;
        break;
1183
    case WIN_READDMA_EXT:
1184 1185 1186
	lba48 = 1;
    case WIN_READDMA:
    case WIN_READDMA_ONCE:
P
Paolo Bonzini 已提交
1187
        if (!s->bs) {
1188
            goto abort_cmd;
P
Paolo Bonzini 已提交
1189
        }
1190
	ide_cmd_lba48_transform(s, lba48);
1191
        ide_sector_start_dma(s, IDE_DMA_READ);
1192
        break;
1193
    case WIN_WRITEDMA_EXT:
1194 1195 1196
	lba48 = 1;
    case WIN_WRITEDMA:
    case WIN_WRITEDMA_ONCE:
P
Paolo Bonzini 已提交
1197
        if (!s->bs) {
1198
            goto abort_cmd;
P
Paolo Bonzini 已提交
1199
        }
1200
	ide_cmd_lba48_transform(s, lba48);
1201
        ide_sector_start_dma(s, IDE_DMA_WRITE);
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
        s->media_changed = 1;
        break;
    case WIN_READ_NATIVE_MAX_EXT:
	lba48 = 1;
    case WIN_READ_NATIVE_MAX:
	ide_cmd_lba48_transform(s, lba48);
        ide_set_sector(s, s->nb_sectors - 1);
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
    case WIN_CHECKPOWERMODE1:
    case WIN_CHECKPOWERMODE2:
1214
        s->error = 0;
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
        s->nsector = 0xff; /* device active or idle */
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
    case WIN_SETFEATURES:
        if (!s->bs)
            goto abort_cmd;
        /* XXX: valid for CDROM ? */
        switch(s->feature) {
        case 0x02: /* write cache enable */
1225 1226 1227 1228 1229 1230
            bdrv_set_enable_write_cache(s->bs, true);
            identify_data = (uint16_t *)s->identify_data;
            put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1);
            s->status = READY_STAT | SEEK_STAT;
            ide_set_irq(s->bus);
            break;
1231
        case 0x82: /* write cache disable */
1232 1233 1234 1235 1236 1237 1238
            bdrv_set_enable_write_cache(s->bs, false);
            identify_data = (uint16_t *)s->identify_data;
            put_le16(identify_data + 85, (1 << 14) | 1);
            ide_flush_cache(s);
            break;
        case 0xcc: /* reverting to power-on defaults enable */
        case 0x66: /* reverting to power-on defaults disable */
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
        case 0xaa: /* read look-ahead enable */
        case 0x55: /* read look-ahead disable */
        case 0x05: /* set advanced power management mode */
        case 0x85: /* disable advanced power management mode */
        case 0x69: /* NOP */
        case 0x67: /* NOP */
        case 0x96: /* NOP */
        case 0x9a: /* NOP */
        case 0x42: /* enable Automatic Acoustic Mode */
        case 0xc2: /* disable Automatic Acoustic Mode */
A
aliguori 已提交
1249
            s->status = READY_STAT | SEEK_STAT;
1250
            ide_set_irq(s->bus);
1251
            break;
1252
        case 0x03: { /* set transfer mode */
1253
		uint8_t val = s->nsector & 0x07;
1254
		identify_data = (uint16_t *)s->identify_data;
1255 1256

		switch (s->nsector >> 3) {
1257 1258
		case 0x00: /* pio default */
		case 0x01: /* pio mode */
1259 1260 1261
			put_le16(identify_data + 62,0x07);
			put_le16(identify_data + 63,0x07);
			put_le16(identify_data + 88,0x3f);
1262
			break;
1263
                case 0x02: /* sigle word dma mode*/
1264 1265 1266
			put_le16(identify_data + 62,0x07 | (1 << (val + 8)));
			put_le16(identify_data + 63,0x07);
			put_le16(identify_data + 88,0x3f);
1267
			break;
1268
		case 0x04: /* mdma mode */
1269 1270 1271
			put_le16(identify_data + 62,0x07);
			put_le16(identify_data + 63,0x07 | (1 << (val + 8)));
			put_le16(identify_data + 88,0x3f);
1272
			break;
1273
		case 0x08: /* udma mode */
1274 1275 1276
			put_le16(identify_data + 62,0x07);
			put_le16(identify_data + 63,0x07);
			put_le16(identify_data + 88,0x3f | (1 << (val + 8)));
1277
			break;
1278
		default:
1279 1280
			goto abort_cmd;
		}
A
aurel32 已提交
1281
            s->status = READY_STAT | SEEK_STAT;
1282
            ide_set_irq(s->bus);
A
aurel32 已提交
1283
            break;
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
	}
        default:
            goto abort_cmd;
        }
        break;
    case WIN_FLUSH_CACHE:
    case WIN_FLUSH_CACHE_EXT:
        ide_flush_cache(s);
        break;
    case WIN_STANDBY:
    case WIN_STANDBY2:
    case WIN_STANDBYNOW1:
    case WIN_STANDBYNOW2:
    case WIN_IDLEIMMEDIATE:
1298
    case WIN_IDLEIMMEDIATE2:
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
    case WIN_SETIDLE1:
    case WIN_SETIDLE2:
    case WIN_SLEEPNOW1:
    case WIN_SLEEPNOW2:
        s->status = READY_STAT;
        ide_set_irq(s->bus);
        break;
    case WIN_SEEK:
        /* XXX: Check that seek is within bounds */
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
        /* ATAPI commands */
    case WIN_PIDENTIFY:
1313 1314 1315
        ide_atapi_identify(s);
        s->status = READY_STAT | SEEK_STAT;
        ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1316 1317 1318 1319 1320 1321 1322 1323 1324
        ide_set_irq(s->bus);
        break;
    case WIN_DIAGNOSE:
        ide_set_signature(s);
        if (s->drive_kind == IDE_CD)
            s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet
                            * devices to return a clear status register
                            * with READY_STAT *not* set. */
        else
A
aliguori 已提交
1325
            s->status = READY_STAT | SEEK_STAT;
1326 1327 1328 1329 1330
        s->error = 0x01; /* Device 0 passed, Device 1 passed or not
                          * present.
                          */
        ide_set_irq(s->bus);
        break;
1331
    case WIN_DEVICE_RESET:
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
        ide_set_signature(s);
        s->status = 0x00; /* NOTE: READY is _not_ set */
        s->error = 0x01;
        break;
    case WIN_PACKETCMD:
        /* overlapping commands not supported */
        if (s->feature & 0x02)
            goto abort_cmd;
        s->status = READY_STAT | SEEK_STAT;
        s->atapi_dma = s->feature & 1;
        s->nsector = 1;
        ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
                           ide_atapi_cmd);
        break;
    /* CF-ATA commands */
    case CFA_REQ_EXT_ERROR_CODE:
        s->error = 0x09;    /* miscellaneous error */
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
    case CFA_ERASE_SECTORS:
    case CFA_WEAR_LEVEL:
1354 1355 1356 1357 1358
#if 0
    /* This one has the same ID as CFA_WEAR_LEVEL and is required for
       Windows 8 to work with AHCI */
    case WIN_SECURITY_FREEZE_LOCK:
#endif
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
        if (val == CFA_WEAR_LEVEL)
            s->nsector = 0;
        if (val == CFA_ERASE_SECTORS)
            s->media_changed = 1;
        s->error = 0x00;
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
    case CFA_TRANSLATE_SECTOR:
        s->error = 0x00;
        s->status = READY_STAT | SEEK_STAT;
        memset(s->io_buffer, 0, 0x200);
        s->io_buffer[0x00] = s->hcyl;			/* Cyl MSB */
        s->io_buffer[0x01] = s->lcyl;			/* Cyl LSB */
        s->io_buffer[0x02] = s->select;			/* Head */
        s->io_buffer[0x03] = s->sector;			/* Sector */
        s->io_buffer[0x04] = ide_get_sector(s) >> 16;	/* LBA MSB */
        s->io_buffer[0x05] = ide_get_sector(s) >> 8;	/* LBA */
        s->io_buffer[0x06] = ide_get_sector(s) >> 0;	/* LBA LSB */
        s->io_buffer[0x13] = 0x00;				/* Erase flag */
        s->io_buffer[0x18] = 0x00;				/* Hot count */
        s->io_buffer[0x19] = 0x00;				/* Hot count */
        s->io_buffer[0x1a] = 0x01;				/* Hot count */
        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
        ide_set_irq(s->bus);
        break;
    case CFA_ACCESS_METADATA_STORAGE:
        switch (s->feature) {
        case 0x02:	/* Inquiry Metadata Storage */
            ide_cfata_metadata_inquiry(s);
1389
            break;
1390 1391
        case 0x03:	/* Read Metadata Storage */
            ide_cfata_metadata_read(s);
1392
            break;
1393 1394
        case 0x04:	/* Write Metadata Storage */
            ide_cfata_metadata_write(s);
1395
            break;
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
        default:
            goto abort_cmd;
        }
        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
        s->status = 0x00; /* NOTE: READY is _not_ set */
        ide_set_irq(s->bus);
        break;
    case IBM_SENSE_CONDITION:
        switch (s->feature) {
        case 0x01:  /* sense temperature in device */
            s->nsector = 0x50;      /* +20 C */
1407
            break;
1408 1409 1410 1411 1412 1413
        default:
            goto abort_cmd;
        }
        s->status = READY_STAT | SEEK_STAT;
        ide_set_irq(s->bus);
        break;
B
Brian Wheeler 已提交
1414

1415
    case WIN_SMART:
1416
	if (s->hcyl != 0xc2 || s->lcyl != 0x4f)
B
Brian Wheeler 已提交
1417
		goto abort_cmd;
1418
	if (!s->smart_enabled && s->feature != SMART_ENABLE)
B
Brian Wheeler 已提交
1419
		goto abort_cmd;
1420 1421
	switch (s->feature) {
	case SMART_DISABLE:
B
Brian Wheeler 已提交
1422 1423
		s->smart_enabled = 0;
		s->status = READY_STAT | SEEK_STAT;
1424
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1425
		break;
1426
	case SMART_ENABLE:
B
Brian Wheeler 已提交
1427 1428
		s->smart_enabled = 1;
		s->status = READY_STAT | SEEK_STAT;
1429
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1430
		break;
1431
	case SMART_ATTR_AUTOSAVE:
B
Brian Wheeler 已提交
1432 1433
		switch (s->sector) {
		case 0x00:
1434 1435
		s->smart_autosave = 0;
		break;
B
Brian Wheeler 已提交
1436
		case 0xf1:
1437 1438
		s->smart_autosave = 1;
		break;
B
Brian Wheeler 已提交
1439
		default:
1440
		goto abort_cmd;
B
Brian Wheeler 已提交
1441 1442
		}
		s->status = READY_STAT | SEEK_STAT;
1443
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1444
		break;
1445
	case SMART_STATUS:
B
Brian Wheeler 已提交
1446
		if (!s->smart_errors) {
1447 1448
		s->hcyl = 0xc2;
		s->lcyl = 0x4f;
B
Brian Wheeler 已提交
1449
		} else {
1450 1451
		s->hcyl = 0x2c;
		s->lcyl = 0xf4;
B
Brian Wheeler 已提交
1452 1453
		}
		s->status = READY_STAT | SEEK_STAT;
1454
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1455
		break;
1456
	case SMART_READ_THRESH:
B
Brian Wheeler 已提交
1457 1458
		memset(s->io_buffer, 0, 0x200);
		s->io_buffer[0] = 0x01; /* smart struct version */
1459
		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
1460
		s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
1461
		s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];
B
Brian Wheeler 已提交
1462 1463
		}
		for (n=0; n<511; n++) /* checksum */
1464
		s->io_buffer[511] += s->io_buffer[n];
B
Brian Wheeler 已提交
1465 1466 1467
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
		s->status = READY_STAT | SEEK_STAT;
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1468
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1469
		break;
1470
	case SMART_READ_DATA:
B
Brian Wheeler 已提交
1471 1472
		memset(s->io_buffer, 0, 0x200);
		s->io_buffer[0] = 0x01; /* smart struct version */
1473
		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
1474 1475 1476 1477
		    int i;
		    for(i = 0; i < 11; i++) {
			s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];
		    }
B
Brian Wheeler 已提交
1478 1479 1480
		}
		s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
		if (s->smart_selftest_count == 0) {
1481
		s->io_buffer[363] = 0;
B
Brian Wheeler 已提交
1482
		} else {
1483
		s->io_buffer[363] =
B
Brian Wheeler 已提交
1484
			s->smart_selftest_data[3 + 
1485 1486
					   (s->smart_selftest_count - 1) *
					   24];
B
Brian Wheeler 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
		}
		s->io_buffer[364] = 0x20; 
		s->io_buffer[365] = 0x01; 
		/* offline data collection capacity: execute + self-test*/
		s->io_buffer[367] = (1<<4 | 1<<3 | 1); 
		s->io_buffer[368] = 0x03; /* smart capability (1) */
		s->io_buffer[369] = 0x00; /* smart capability (2) */
		s->io_buffer[370] = 0x01; /* error logging supported */
		s->io_buffer[372] = 0x02; /* minutes for poll short test */
		s->io_buffer[373] = 0x36; /* minutes for poll ext test */
		s->io_buffer[374] = 0x01; /* minutes for poll conveyance */

		for (n=0; n<511; n++) 
1500
		s->io_buffer[511] += s->io_buffer[n];
B
Brian Wheeler 已提交
1501 1502 1503
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
		s->status = READY_STAT | SEEK_STAT;
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1504
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1505
		break;
1506
	case SMART_READ_LOG:
B
Brian Wheeler 已提交
1507 1508
		switch (s->sector) {
		case 0x01: /* summary smart error log */
1509 1510 1511 1512 1513
		memset(s->io_buffer, 0, 0x200);
		s->io_buffer[0] = 0x01;
		s->io_buffer[1] = 0x00; /* no error entries */
		s->io_buffer[452] = s->smart_errors & 0xff;
		s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;
B
Brian Wheeler 已提交
1514

1515
		for (n=0; n<511; n++)
B
Brian Wheeler 已提交
1516
			s->io_buffer[511] += s->io_buffer[n];
1517 1518
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
		break;
B
Brian Wheeler 已提交
1519
		case 0x06: /* smart self test log */
1520 1521 1522
		memset(s->io_buffer, 0, 0x200);
		s->io_buffer[0] = 0x01;
		if (s->smart_selftest_count == 0) {
B
Brian Wheeler 已提交
1523
			s->io_buffer[508] = 0;
1524
		} else {
B
Brian Wheeler 已提交
1525 1526
			s->io_buffer[508] = s->smart_selftest_count;
			for (n=2; n<506; n++) 
1527 1528 1529
			s->io_buffer[n] = s->smart_selftest_data[n];
		}
		for (n=0; n<511; n++)
B
Brian Wheeler 已提交
1530
			s->io_buffer[511] += s->io_buffer[n];
1531 1532
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
		break;
B
Brian Wheeler 已提交
1533
		default:
1534
		goto abort_cmd;
B
Brian Wheeler 已提交
1535 1536 1537
		}
		s->status = READY_STAT | SEEK_STAT;
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1538
		ide_set_irq(s->bus);
B
Brian Wheeler 已提交
1539
		break;
1540
	case SMART_EXECUTE_OFFLINE:
B
Brian Wheeler 已提交
1541 1542 1543 1544
		switch (s->sector) {
		case 0: /* off-line routine */
		case 1: /* short self test */
		case 2: /* extended self test */
1545 1546
		s->smart_selftest_count++;
		if(s->smart_selftest_count > 21)
B
Brian Wheeler 已提交
1547
			s->smart_selftest_count = 0;
1548 1549 1550 1551 1552 1553 1554 1555
		n = 2 + (s->smart_selftest_count - 1) * 24;
		s->smart_selftest_data[n] = s->sector;
		s->smart_selftest_data[n+1] = 0x00; /* OK and finished */
		s->smart_selftest_data[n+2] = 0x34; /* hour count lsb */
		s->smart_selftest_data[n+3] = 0x12; /* hour count msb */
		s->status = READY_STAT | SEEK_STAT;
		ide_set_irq(s->bus);
		break;
B
Brian Wheeler 已提交
1556
		default:
1557
		goto abort_cmd;
B
Brian Wheeler 已提交
1558 1559
		}
		break;
1560
	default:
B
Brian Wheeler 已提交
1561
		goto abort_cmd;
1562 1563 1564
	}
	break;
    default:
1565
        /* should not be reachable */
1566 1567 1568 1569 1570
    abort_cmd:
        ide_abort_command(s);
        ide_set_irq(s->bus);
        break;
    }
B
bellard 已提交
1571 1572
}

G
Gerd Hoffmann 已提交
1573
uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
B
bellard 已提交
1574
{
G
Gerd Hoffmann 已提交
1575 1576
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1577
    uint32_t addr;
B
bellard 已提交
1578
    int ret, hob;
B
bellard 已提交
1579 1580

    addr = addr1 & 7;
B
bellard 已提交
1581 1582 1583
    /* FIXME: HOB readback uses bit 7, but it's always set right now */
    //hob = s->select & (1 << 7);
    hob = 0;
B
bellard 已提交
1584 1585 1586 1587 1588
    switch(addr) {
    case 0:
        ret = 0xff;
        break;
    case 1:
G
Gerd Hoffmann 已提交
1589 1590
        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
            (s != bus->ifs && !s->bs))
1591
            ret = 0;
B
bellard 已提交
1592
        else if (!hob)
1593
            ret = s->error;
B
bellard 已提交
1594 1595
	else
	    ret = s->hob_feature;
B
bellard 已提交
1596 1597
        break;
    case 2:
G
Gerd Hoffmann 已提交
1598
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
1599
            ret = 0;
B
bellard 已提交
1600
        else if (!hob)
1601
            ret = s->nsector & 0xff;
B
bellard 已提交
1602 1603
	else
	    ret = s->hob_nsector;
B
bellard 已提交
1604 1605
        break;
    case 3:
G
Gerd Hoffmann 已提交
1606
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
1607
            ret = 0;
B
bellard 已提交
1608
        else if (!hob)
1609
            ret = s->sector;
B
bellard 已提交
1610 1611
	else
	    ret = s->hob_sector;
B
bellard 已提交
1612 1613
        break;
    case 4:
G
Gerd Hoffmann 已提交
1614
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
1615
            ret = 0;
B
bellard 已提交
1616
        else if (!hob)
1617
            ret = s->lcyl;
B
bellard 已提交
1618 1619
	else
	    ret = s->hob_lcyl;
B
bellard 已提交
1620 1621
        break;
    case 5:
G
Gerd Hoffmann 已提交
1622
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
1623
            ret = 0;
B
bellard 已提交
1624
        else if (!hob)
1625
            ret = s->hcyl;
B
bellard 已提交
1626 1627
	else
	    ret = s->hob_hcyl;
B
bellard 已提交
1628 1629
        break;
    case 6:
G
Gerd Hoffmann 已提交
1630
        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
1631 1632
            ret = 0;
        else
B
bellard 已提交
1633
            ret = s->select;
B
bellard 已提交
1634 1635 1636
        break;
    default:
    case 7:
G
Gerd Hoffmann 已提交
1637 1638
        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
            (s != bus->ifs && !s->bs))
1639 1640 1641
            ret = 0;
        else
            ret = s->status;
1642
        qemu_irq_lower(bus->irq);
B
bellard 已提交
1643 1644 1645 1646 1647 1648 1649 1650
        break;
    }
#ifdef DEBUG_IDE
    printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
#endif
    return ret;
}

G
Gerd Hoffmann 已提交
1651
uint32_t ide_status_read(void *opaque, uint32_t addr)
B
bellard 已提交
1652
{
G
Gerd Hoffmann 已提交
1653 1654
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1655
    int ret;
B
bellard 已提交
1656

G
Gerd Hoffmann 已提交
1657 1658
    if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
        (s != bus->ifs && !s->bs))
B
bellard 已提交
1659 1660 1661
        ret = 0;
    else
        ret = s->status;
B
bellard 已提交
1662 1663 1664 1665 1666 1667
#ifdef DEBUG_IDE
    printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
#endif
    return ret;
}

G
Gerd Hoffmann 已提交
1668
void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
B
bellard 已提交
1669
{
G
Gerd Hoffmann 已提交
1670
    IDEBus *bus = opaque;
B
bellard 已提交
1671 1672 1673 1674 1675 1676 1677
    IDEState *s;
    int i;

#ifdef DEBUG_IDE
    printf("ide: write control addr=0x%x val=%02x\n", addr, val);
#endif
    /* common for both drives */
1678
    if (!(bus->cmd & IDE_CMD_RESET) &&
B
bellard 已提交
1679 1680 1681
        (val & IDE_CMD_RESET)) {
        /* reset low to high */
        for(i = 0;i < 2; i++) {
G
Gerd Hoffmann 已提交
1682
            s = &bus->ifs[i];
B
bellard 已提交
1683 1684 1685
            s->status = BUSY_STAT | SEEK_STAT;
            s->error = 0x01;
        }
1686
    } else if ((bus->cmd & IDE_CMD_RESET) &&
B
bellard 已提交
1687 1688 1689
               !(val & IDE_CMD_RESET)) {
        /* high to low */
        for(i = 0;i < 2; i++) {
G
Gerd Hoffmann 已提交
1690
            s = &bus->ifs[i];
1691
            if (s->drive_kind == IDE_CD)
B
bellard 已提交
1692 1693
                s->status = 0x00; /* NOTE: READY is _not_ set */
            else
1694
                s->status = READY_STAT | SEEK_STAT;
B
bellard 已提交
1695 1696 1697 1698
            ide_set_signature(s);
        }
    }

1699
    bus->cmd = val;
B
bellard 已提交
1700 1701
}

1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720
/*
 * Returns true if the running PIO transfer is a PIO out (i.e. data is
 * transferred from the device to the guest), false if it's a PIO in
 */
static bool ide_is_pio_out(IDEState *s)
{
    if (s->end_transfer_func == ide_sector_write ||
        s->end_transfer_func == ide_atapi_cmd) {
        return false;
    } else if (s->end_transfer_func == ide_sector_read ||
               s->end_transfer_func == ide_transfer_stop ||
               s->end_transfer_func == ide_atapi_cmd_reply_end ||
               s->end_transfer_func == ide_dummy_transfer_stop) {
        return true;
    }

    abort();
}

G
Gerd Hoffmann 已提交
1721
void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
B
bellard 已提交
1722
{
G
Gerd Hoffmann 已提交
1723 1724
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1725 1726
    uint8_t *p;

1727 1728 1729
    /* PIO data access allowed only when DRQ bit is set. The result of a write
     * during PIO out is indeterminate, just ignore it. */
    if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
1730
        return;
1731
    }
1732

B
bellard 已提交
1733
    p = s->data_ptr;
B
bellard 已提交
1734
    *(uint16_t *)p = le16_to_cpu(val);
B
bellard 已提交
1735 1736 1737 1738 1739 1740
    p += 2;
    s->data_ptr = p;
    if (p >= s->data_end)
        s->end_transfer_func(s);
}

G
Gerd Hoffmann 已提交
1741
uint32_t ide_data_readw(void *opaque, uint32_t addr)
B
bellard 已提交
1742
{
G
Gerd Hoffmann 已提交
1743 1744
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1745 1746
    uint8_t *p;
    int ret;
1747

1748 1749 1750
    /* PIO data access allowed only when DRQ bit is set. The result of a read
     * during PIO in is indeterminate, return 0 and don't move forward. */
    if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
1751
        return 0;
1752
    }
1753

B
bellard 已提交
1754
    p = s->data_ptr;
B
bellard 已提交
1755
    ret = cpu_to_le16(*(uint16_t *)p);
B
bellard 已提交
1756 1757 1758 1759 1760 1761 1762
    p += 2;
    s->data_ptr = p;
    if (p >= s->data_end)
        s->end_transfer_func(s);
    return ret;
}

G
Gerd Hoffmann 已提交
1763
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
B
bellard 已提交
1764
{
G
Gerd Hoffmann 已提交
1765 1766
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1767 1768
    uint8_t *p;

1769 1770 1771
    /* PIO data access allowed only when DRQ bit is set. The result of a write
     * during PIO out is indeterminate, just ignore it. */
    if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
1772
        return;
1773
    }
1774

B
bellard 已提交
1775
    p = s->data_ptr;
B
bellard 已提交
1776
    *(uint32_t *)p = le32_to_cpu(val);
B
bellard 已提交
1777 1778 1779 1780 1781 1782
    p += 4;
    s->data_ptr = p;
    if (p >= s->data_end)
        s->end_transfer_func(s);
}

G
Gerd Hoffmann 已提交
1783
uint32_t ide_data_readl(void *opaque, uint32_t addr)
B
bellard 已提交
1784
{
G
Gerd Hoffmann 已提交
1785 1786
    IDEBus *bus = opaque;
    IDEState *s = idebus_active_if(bus);
B
bellard 已提交
1787 1788
    uint8_t *p;
    int ret;
1789

1790 1791 1792
    /* PIO data access allowed only when DRQ bit is set. The result of a read
     * during PIO in is indeterminate, return 0 and don't move forward. */
    if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
1793
        return 0;
1794
    }
1795

B
bellard 已提交
1796
    p = s->data_ptr;
B
bellard 已提交
1797
    ret = cpu_to_le32(*(uint32_t *)p);
B
bellard 已提交
1798 1799 1800 1801 1802 1803 1804
    p += 4;
    s->data_ptr = p;
    if (p >= s->data_end)
        s->end_transfer_func(s);
    return ret;
}

1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
static void ide_dummy_transfer_stop(IDEState *s)
{
    s->data_ptr = s->io_buffer;
    s->data_end = s->io_buffer;
    s->io_buffer[0] = 0xff;
    s->io_buffer[1] = 0xff;
    s->io_buffer[2] = 0xff;
    s->io_buffer[3] = 0xff;
}

B
Blue Swirl 已提交
1815
static void ide_reset(IDEState *s)
B
bellard 已提交
1816
{
B
Blue Swirl 已提交
1817 1818 1819
#ifdef DEBUG_IDE
    printf("ide: reset\n");
#endif
1820 1821 1822 1823 1824 1825

    if (s->pio_aiocb) {
        bdrv_aio_cancel(s->pio_aiocb);
        s->pio_aiocb = NULL;
    }

1826
    if (s->drive_kind == IDE_CFATA)
1827 1828 1829
        s->mult_sectors = 0;
    else
        s->mult_sectors = MAX_MULT_SECTORS;
B
Blue Swirl 已提交
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844
    /* ide regs */
    s->feature = 0;
    s->error = 0;
    s->nsector = 0;
    s->sector = 0;
    s->lcyl = 0;
    s->hcyl = 0;

    /* lba48 */
    s->hob_feature = 0;
    s->hob_sector = 0;
    s->hob_nsector = 0;
    s->hob_lcyl = 0;
    s->hob_hcyl = 0;

B
bellard 已提交
1845
    s->select = 0xa0;
A
aliguori 已提交
1846
    s->status = READY_STAT | SEEK_STAT;
B
Blue Swirl 已提交
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862

    s->lba48 = 0;

    /* ATAPI specific */
    s->sense_key = 0;
    s->asc = 0;
    s->cdrom_changed = 0;
    s->packet_transfer_size = 0;
    s->elementary_transfer_size = 0;
    s->io_buffer_index = 0;
    s->cd_sector_size = 0;
    s->atapi_dma = 0;
    /* ATA DMA state */
    s->io_buffer_size = 0;
    s->req_nb_sectors = 0;

B
bellard 已提交
1863
    ide_set_signature(s);
1864 1865 1866 1867
    /* init the transfer handler so that 0xffff is returned on data
       accesses */
    s->end_transfer_func = ide_dummy_transfer_stop;
    ide_dummy_transfer_stop(s);
1868
    s->media_changed = 0;
B
bellard 已提交
1869 1870
}

B
Blue Swirl 已提交
1871 1872 1873 1874 1875 1876 1877
void ide_bus_reset(IDEBus *bus)
{
    bus->unit = 0;
    bus->cmd = 0;
    ide_reset(&bus->ifs[0]);
    ide_reset(&bus->ifs[1]);
    ide_clear_hob(bus);
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889

    /* pending async DMA */
    if (bus->dma->aiocb) {
#ifdef DEBUG_AIO
        printf("aio_cancel\n");
#endif
        bdrv_aio_cancel(bus->dma->aiocb);
        bus->dma->aiocb = NULL;
    }

    /* reset dma provider too */
    bus->dma->ops->reset(bus->dma);
B
Blue Swirl 已提交
1890 1891
}

1892 1893 1894 1895 1896
static bool ide_cd_is_tray_open(void *opaque)
{
    return ((IDEState *)opaque)->tray_open;
}

1897 1898 1899 1900 1901
static bool ide_cd_is_medium_locked(void *opaque)
{
    return ((IDEState *)opaque)->tray_locked;
}

1902
static const BlockDevOps ide_cd_block_ops = {
1903
    .change_media_cb = ide_cd_change_cb,
P
Paolo Bonzini 已提交
1904
    .eject_request_cb = ide_cd_eject_request_cb,
1905
    .is_tray_open = ide_cd_is_tray_open,
1906
    .is_medium_locked = ide_cd_is_medium_locked,
1907 1908
};

1909
int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
F
Floris Bos 已提交
1910
                   const char *version, const char *serial, const char *model,
1911 1912 1913
                   uint64_t wwn,
                   uint32_t cylinders, uint32_t heads, uint32_t secs,
                   int chs_trans)
1914 1915 1916
{
    uint64_t nb_sectors;

1917
    s->bs = bs;
1918 1919
    s->drive_kind = kind;

1920
    bdrv_get_geometry(bs, &nb_sectors);
1921 1922 1923
    s->cylinders = cylinders;
    s->heads = heads;
    s->sectors = secs;
1924
    s->chs_trans = chs_trans;
1925
    s->nb_sectors = nb_sectors;
F
Floris Bos 已提交
1926
    s->wwn = wwn;
1927 1928 1929 1930 1931 1932
    /* The SMART values should be preserved across power cycles
       but they aren't.  */
    s->smart_enabled = 1;
    s->smart_autosave = 1;
    s->smart_errors = 0;
    s->smart_selftest_count = 0;
1933
    if (kind == IDE_CD) {
1934
        bdrv_set_dev_ops(bs, &ide_cd_block_ops, s);
1935
        bdrv_set_buffer_alignment(bs, 2048);
1936
    } else {
1937 1938 1939 1940
        if (!bdrv_is_inserted(s->bs)) {
            error_report("Device needs media, but drive is empty");
            return -1;
        }
1941 1942 1943 1944
        if (bdrv_is_read_only(bs)) {
            error_report("Can't use a read-only drive");
            return -1;
        }
1945
    }
1946
    if (serial) {
1947
        pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial);
1948
    } else {
1949 1950
        snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
                 "QM%05d", s->drive_serial);
1951
    }
F
Floris Bos 已提交
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967
    if (model) {
        pstrcpy(s->drive_model_str, sizeof(s->drive_model_str), model);
    } else {
        switch (kind) {
        case IDE_CD:
            strcpy(s->drive_model_str, "QEMU DVD-ROM");
            break;
        case IDE_CFATA:
            strcpy(s->drive_model_str, "QEMU MICRODRIVE");
            break;
        default:
            strcpy(s->drive_model_str, "QEMU HARDDISK");
            break;
        }
    }

G
Gerd Hoffmann 已提交
1968 1969 1970
    if (version) {
        pstrcpy(s->version, sizeof(s->version), version);
    } else {
1971
        pstrcpy(s->version, sizeof(s->version), qemu_get_version());
G
Gerd Hoffmann 已提交
1972
    }
1973

1974
    ide_reset(s);
L
Luiz Capitulino 已提交
1975
    bdrv_iostatus_enable(bs);
1976
    return 0;
1977 1978
}

1979
static void ide_init1(IDEBus *bus, int unit)
1980 1981 1982 1983 1984 1985 1986
{
    static int drive_serial = 1;
    IDEState *s = &bus->ifs[unit];

    s->bus = bus;
    s->unit = unit;
    s->drive_serial = drive_serial++;
1987
    /* we need at least 2k alignment for accessing CDROMs using O_DIRECT */
1988
    s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
K
Kevin Wolf 已提交
1989 1990 1991
    s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len);
    memset(s->io_buffer, 0, s->io_buffer_total_len);

1992
    s->smart_selftest_data = qemu_blockalign(s->bs, 512);
K
Kevin Wolf 已提交
1993 1994
    memset(s->smart_selftest_data, 0, 512);

1995
    s->sector_write_timer = qemu_new_timer_ns(vm_clock,
1996
                                           ide_sector_write_timer_cb, s);
1997 1998
}

1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
static void ide_nop_start(IDEDMA *dma, IDEState *s,
                          BlockDriverCompletionFunc *cb)
{
}

static int ide_nop(IDEDMA *dma)
{
    return 0;
}

static int ide_nop_int(IDEDMA *dma, int x)
{
    return 0;
}

2014
static void ide_nop_restart(void *opaque, int x, RunState y)
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034
{
}

static const IDEDMAOps ide_dma_nop_ops = {
    .start_dma      = ide_nop_start,
    .start_transfer = ide_nop,
    .prepare_buf    = ide_nop_int,
    .rw_buf         = ide_nop_int,
    .set_unit       = ide_nop_int,
    .add_status     = ide_nop_int,
    .set_inactive   = ide_nop,
    .restart_cb     = ide_nop_restart,
    .reset          = ide_nop,
};

static IDEDMA ide_dma_nop = {
    .ops = &ide_dma_nop_ops,
    .aiocb = NULL,
};

2035 2036 2037 2038 2039 2040 2041
void ide_init2(IDEBus *bus, qemu_irq irq)
{
    int i;

    for(i = 0; i < 2; i++) {
        ide_init1(bus, i);
        ide_reset(&bus->ifs[i]);
2042
    }
2043
    bus->irq = irq;
2044
    bus->dma = &ide_dma_nop;
2045 2046
}

2047 2048 2049
/* TODO convert users to qdev and remove */
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
                                    DriveInfo *hd1, qemu_irq irq)
B
bellard 已提交
2050
{
2051
    int i, trans;
2052
    DriveInfo *dinfo;
2053
    uint32_t cyls, heads, secs;
B
bellard 已提交
2054

2055
    for(i = 0; i < 2; i++) {
2056 2057 2058
        dinfo = i == 0 ? hd0 : hd1;
        ide_init1(bus, i);
        if (dinfo) {
2059 2060 2061 2062 2063 2064
            cyls  = dinfo->cyls;
            heads = dinfo->heads;
            secs  = dinfo->secs;
            trans = dinfo->trans;
            if (!cyls && !heads && !secs) {
                hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans);
2065 2066
            } else if (trans == BIOS_ATA_TRANSLATION_AUTO) {
                trans = hd_bios_chs_auto_trans(cyls, heads, secs);
2067
            }
2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
            if (cyls < 1 || cyls > 65535) {
                error_report("cyls must be between 1 and 65535");
                exit(1);
            }
            if (heads < 1 || heads > 16) {
                error_report("heads must be between 1 and 16");
                exit(1);
            }
            if (secs < 1 || secs > 255) {
                error_report("secs must be between 1 and 255");
                exit(1);
            }
2080
            if (ide_init_drive(&bus->ifs[i], dinfo->bdrv,
2081 2082 2083
                               dinfo->media_cd ? IDE_CD : IDE_HD,
                               NULL, dinfo->serial, NULL, 0,
                               cyls, heads, secs, trans) < 0) {
2084 2085 2086
                error_report("Can't set up IDE drive %s", dinfo->id);
                exit(1);
            }
2087
            bdrv_attach_dev_nofail(dinfo->bdrv, &bus->ifs[i]);
2088 2089 2090
        } else {
            ide_reset(&bus->ifs[i]);
        }
B
bellard 已提交
2091
    }
2092
    bus->irq = irq;
2093
    bus->dma = &ide_dma_nop;
B
bellard 已提交
2094 2095
}

2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
static const MemoryRegionPortio ide_portio_list[] = {
    { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
    { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew },
    { 0, 4, 4, .read = ide_data_readl, .write = ide_data_writel },
    PORTIO_END_OF_LIST(),
};

static const MemoryRegionPortio ide_portio2_list[] = {
    { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write },
    PORTIO_END_OF_LIST(),
};

void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
B
bellard 已提交
2109
{
2110 2111 2112 2113
    /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA
       bridge has been setup properly to always register with ISA.  */
    isa_register_portio_list(dev, iobase, ide_portio_list, bus, "ide");

2114
    if (iobase2) {
2115
        isa_register_portio_list(dev, iobase2, ide_portio2_list, bus, "ide");
B
bellard 已提交
2116 2117
    }
}
B
bellard 已提交
2118

J
Juan Quintela 已提交
2119
static bool is_identify_set(void *opaque, int version_id)
2120
{
J
Juan Quintela 已提交
2121 2122 2123 2124 2125
    IDEState *s = opaque;

    return s->identify_set != 0;
}

2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145
static EndTransferFunc* transfer_end_table[] = {
        ide_sector_read,
        ide_sector_write,
        ide_transfer_stop,
        ide_atapi_cmd_reply_end,
        ide_atapi_cmd,
        ide_dummy_transfer_stop,
};

static int transfer_end_table_idx(EndTransferFunc *fn)
{
    int i;

    for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
        if (transfer_end_table[i] == fn)
            return i;

    return -1;
}

J
Juan Quintela 已提交
2146
static int ide_drive_post_load(void *opaque, int version_id)
2147
{
J
Juan Quintela 已提交
2148 2149 2150
    IDEState *s = opaque;

    if (version_id < 3) {
2151
        if (s->sense_key == UNIT_ATTENTION &&
J
Juan Quintela 已提交
2152
            s->asc == ASC_MEDIUM_MAY_HAVE_CHANGED) {
G
Gleb Natapov 已提交
2153
            s->cdrom_changed = 1;
J
Juan Quintela 已提交
2154
        }
G
Gleb Natapov 已提交
2155
    }
2156 2157 2158
    if (s->identify_set) {
        bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5)));
    }
J
Juan Quintela 已提交
2159
    return 0;
2160 2161
}

2162 2163 2164 2165
static int ide_drive_pio_post_load(void *opaque, int version_id)
{
    IDEState *s = opaque;

2166
    if (s->end_transfer_fn_idx >= ARRAY_SIZE(transfer_end_table)) {
2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
        return -EINVAL;
    }
    s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
    s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
    s->data_end = s->data_ptr + s->cur_io_buffer_len;

    return 0;
}

static void ide_drive_pio_pre_save(void *opaque)
{
    IDEState *s = opaque;
    int idx;

    s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
    s->cur_io_buffer_len = s->data_end - s->data_ptr;

    idx = transfer_end_table_idx(s->end_transfer_func);
    if (idx == -1) {
        fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
                        __func__);
        s->end_transfer_fn_idx = 2;
    } else {
        s->end_transfer_fn_idx = idx;
    }
}

static bool ide_drive_pio_state_needed(void *opaque)
{
    IDEState *s = opaque;

2198 2199
    return ((s->status & DRQ_STAT) != 0)
        || (s->bus->error_status & BM_STATUS_PIO_RETRY);
2200 2201
}

2202 2203 2204 2205 2206 2207 2208
static bool ide_tray_state_needed(void *opaque)
{
    IDEState *s = opaque;

    return s->tray_open || s->tray_locked;
}

2209 2210 2211 2212 2213 2214 2215
static bool ide_atapi_gesn_needed(void *opaque)
{
    IDEState *s = opaque;

    return s->events.new_media || s->events.eject_request;
}

2216 2217 2218 2219 2220 2221 2222
static bool ide_error_needed(void *opaque)
{
    IDEBus *bus = opaque;

    return (bus->error_status != 0);
}

2223
/* Fields for GET_EVENT_STATUS_NOTIFICATION ATAPI command */
2224
static const VMStateDescription vmstate_ide_atapi_gesn_state = {
2225 2226 2227 2228 2229 2230 2231
    .name ="ide_drive/atapi/gesn_state",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields = (VMStateField []) {
        VMSTATE_BOOL(events.new_media, IDEState),
        VMSTATE_BOOL(events.eject_request, IDEState),
2232
        VMSTATE_END_OF_LIST()
2233 2234 2235
    }
};

2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247
static const VMStateDescription vmstate_ide_tray_state = {
    .name = "ide_drive/tray_state",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields = (VMStateField[]) {
        VMSTATE_BOOL(tray_open, IDEState),
        VMSTATE_BOOL(tray_locked, IDEState),
        VMSTATE_END_OF_LIST()
    }
};

2248
static const VMStateDescription vmstate_ide_drive_pio_state = {
2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
    .name = "ide_drive/pio_state",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .pre_save = ide_drive_pio_pre_save,
    .post_load = ide_drive_pio_post_load,
    .fields      = (VMStateField []) {
        VMSTATE_INT32(req_nb_sectors, IDEState),
        VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
			     vmstate_info_uint8, uint8_t),
        VMSTATE_INT32(cur_io_buffer_offset, IDEState),
        VMSTATE_INT32(cur_io_buffer_len, IDEState),
        VMSTATE_UINT8(end_transfer_fn_idx, IDEState),
        VMSTATE_INT32(elementary_transfer_size, IDEState),
        VMSTATE_INT32(packet_transfer_size, IDEState),
        VMSTATE_END_OF_LIST()
    }
};

J
Juan Quintela 已提交
2268 2269
const VMStateDescription vmstate_ide_drive = {
    .name = "ide_drive",
2270
    .version_id = 3,
J
Juan Quintela 已提交
2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295
    .minimum_version_id = 0,
    .minimum_version_id_old = 0,
    .post_load = ide_drive_post_load,
    .fields      = (VMStateField []) {
        VMSTATE_INT32(mult_sectors, IDEState),
        VMSTATE_INT32(identify_set, IDEState),
        VMSTATE_BUFFER_TEST(identify_data, IDEState, is_identify_set),
        VMSTATE_UINT8(feature, IDEState),
        VMSTATE_UINT8(error, IDEState),
        VMSTATE_UINT32(nsector, IDEState),
        VMSTATE_UINT8(sector, IDEState),
        VMSTATE_UINT8(lcyl, IDEState),
        VMSTATE_UINT8(hcyl, IDEState),
        VMSTATE_UINT8(hob_feature, IDEState),
        VMSTATE_UINT8(hob_sector, IDEState),
        VMSTATE_UINT8(hob_nsector, IDEState),
        VMSTATE_UINT8(hob_lcyl, IDEState),
        VMSTATE_UINT8(hob_hcyl, IDEState),
        VMSTATE_UINT8(select, IDEState),
        VMSTATE_UINT8(status, IDEState),
        VMSTATE_UINT8(lba48, IDEState),
        VMSTATE_UINT8(sense_key, IDEState),
        VMSTATE_UINT8(asc, IDEState),
        VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
        VMSTATE_END_OF_LIST()
2296 2297 2298 2299 2300
    },
    .subsections = (VMStateSubsection []) {
        {
            .vmsd = &vmstate_ide_drive_pio_state,
            .needed = ide_drive_pio_state_needed,
2301 2302 2303
        }, {
            .vmsd = &vmstate_ide_tray_state,
            .needed = ide_tray_state_needed,
2304 2305 2306
        }, {
            .vmsd = &vmstate_ide_atapi_gesn_state,
            .needed = ide_atapi_gesn_needed,
2307 2308 2309
        }, {
            /* empty */
        }
J
Juan Quintela 已提交
2310 2311 2312
    }
};

2313
static const VMStateDescription vmstate_ide_error_status = {
2314 2315 2316 2317 2318 2319 2320 2321 2322 2323
    .name ="ide_bus/error",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields = (VMStateField []) {
        VMSTATE_INT32(error_status, IDEBus),
        VMSTATE_END_OF_LIST()
    }
};

J
Juan Quintela 已提交
2324 2325 2326 2327 2328 2329 2330 2331 2332
const VMStateDescription vmstate_ide_bus = {
    .name = "ide_bus",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields      = (VMStateField []) {
        VMSTATE_UINT8(cmd, IDEBus),
        VMSTATE_UINT8(unit, IDEBus),
        VMSTATE_END_OF_LIST()
2333 2334 2335 2336 2337 2338 2339 2340
    },
    .subsections = (VMStateSubsection []) {
        {
            .vmsd = &vmstate_ide_error_status,
            .needed = ide_error_needed,
        }, {
            /* empty */
        }
J
Juan Quintela 已提交
2341 2342
    }
};
2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356

void ide_drive_get(DriveInfo **hd, int max_bus)
{
    int i;

    if (drive_get_max_bus(IF_IDE) >= max_bus) {
        fprintf(stderr, "qemu: too many IDE bus: %d\n", max_bus);
        exit(1);
    }

    for(i = 0; i < max_bus * MAX_IDE_DEVS; i++) {
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
    }
}