1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "hw/hw.h"
28#include "hw/isa/isa.h"
29#include "qemu/error-report.h"
30#include "qemu/timer.h"
31#include "sysemu/sysemu.h"
32#include "sysemu/blockdev.h"
33#include "sysemu/dma.h"
34#include "hw/block/block.h"
35#include "sysemu/block-backend.h"
36#include "qapi/error.h"
37#include "qemu/cutils.h"
38#include "sysemu/replay.h"
39
40#include "hw/ide/internal.h"
41#include "trace.h"
42
43
44
45static const int smart_attributes[][12] = {
46
47
48 { 0x01, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06},
49
50 { 0x03, 0x03, 0x00, 0x64, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
51
52 { 0x04, 0x02, 0x00, 0x64, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14},
53
54 { 0x05, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24},
55
56 { 0x09, 0x03, 0x00, 0x64, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
57
58 { 0x0c, 0x03, 0x00, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
59
60 { 190, 0x03, 0x00, 0x45, 0x45, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x32},
61};
62
63const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT] = {
64 [IDE_DMA_READ] = "DMA READ",
65 [IDE_DMA_WRITE] = "DMA WRITE",
66 [IDE_DMA_TRIM] = "DMA TRIM",
67 [IDE_DMA_ATAPI] = "DMA ATAPI"
68};
69
70static const char *IDE_DMA_CMD_str(enum ide_dma_cmd enval)
71{
72 if ((unsigned)enval < IDE_DMA__COUNT) {
73 return IDE_DMA_CMD_lookup[enval];
74 }
75 return "DMA UNKNOWN CMD";
76}
77
78static void ide_dummy_transfer_stop(IDEState *s);
79
80static void padstr(char *str, const char *src, int len)
81{
82 int i, v;
83 for(i = 0; i < len; i++) {
84 if (*src)
85 v = *src++;
86 else
87 v = ' ';
88 str[i^1] = v;
89 }
90}
91
92static void put_le16(uint16_t *p, unsigned int v)
93{
94 *p = cpu_to_le16(v);
95}
96
97static void ide_identify_size(IDEState *s)
98{
99 uint16_t *p = (uint16_t *)s->identify_data;
100 put_le16(p + 60, s->nb_sectors);
101 put_le16(p + 61, s->nb_sectors >> 16);
102 put_le16(p + 100, s->nb_sectors);
103 put_le16(p + 101, s->nb_sectors >> 16);
104 put_le16(p + 102, s->nb_sectors >> 32);
105 put_le16(p + 103, s->nb_sectors >> 48);
106}
107
108static void ide_identify(IDEState *s)
109{
110 uint16_t *p;
111 unsigned int oldsize;
112 IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
113
114 p = (uint16_t *)s->identify_data;
115 if (s->identify_set) {
116 goto fill_buffer;
117 }
118 memset(p, 0, sizeof(s->identify_data));
119
120 put_le16(p + 0, 0x0040);
121 put_le16(p + 1, s->cylinders);
122 put_le16(p + 3, s->heads);
123 put_le16(p + 4, 512 * s->sectors);
124 put_le16(p + 5, 512);
125 put_le16(p + 6, s->sectors);
126 padstr((char *)(p + 10), s->drive_serial_str, 20);
127 put_le16(p + 20, 3);
128 put_le16(p + 21, 512);
129 put_le16(p + 22, 4);
130 padstr((char *)(p + 23), s->version, 8);
131 padstr((char *)(p + 27), s->drive_model_str, 40);
132#if MAX_MULT_SECTORS > 1
133 put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
134#endif
135 put_le16(p + 48, 1);
136 put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8));
137 put_le16(p + 51, 0x200);
138 put_le16(p + 52, 0x200);
139 put_le16(p + 53, 1 | (1 << 1) | (1 << 2));
140 put_le16(p + 54, s->cylinders);
141 put_le16(p + 55, s->heads);
142 put_le16(p + 56, s->sectors);
143 oldsize = s->cylinders * s->heads * s->sectors;
144 put_le16(p + 57, oldsize);
145 put_le16(p + 58, oldsize >> 16);
146 if (s->mult_sectors)
147 put_le16(p + 59, 0x100 | s->mult_sectors);
148
149
150 put_le16(p + 62, 0x07);
151 put_le16(p + 63, 0x07);
152 put_le16(p + 64, 0x03);
153 put_le16(p + 65, 120);
154 put_le16(p + 66, 120);
155 put_le16(p + 67, 120);
156 put_le16(p + 68, 120);
157 if (dev && dev->conf.discard_granularity) {
158 put_le16(p + 69, (1 << 14));
159 }
160
161 if (s->ncq_queues) {
162 put_le16(p + 75, s->ncq_queues - 1);
163
164 put_le16(p + 76, (1 << 8));
165 }
166
167 put_le16(p + 80, 0xf0);
168 put_le16(p + 81, 0x16);
169
170 put_le16(p + 82, (1 << 14) | (1 << 5) | 1);
171
172 put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
173
174 if (s->wwn) {
175 put_le16(p + 84, (1 << 14) | (1 << 8) | 0);
176 } else {
177 put_le16(p + 84, (1 << 14) | 0);
178 }
179
180 if (blk_enable_write_cache(s->blk)) {
181 put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
182 } else {
183 put_le16(p + 85, (1 << 14) | 1);
184 }
185
186 put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10));
187
188 if (s->wwn) {
189 put_le16(p + 87, (1 << 14) | (1 << 8) | 0);
190 } else {
191 put_le16(p + 87, (1 << 14) | 0);
192 }
193 put_le16(p + 88, 0x3f | (1 << 13));
194 put_le16(p + 93, 1 | (1 << 14) | 0x2000);
195
196
197
198
199
200 if (dev && dev->conf.physical_block_size)
201 put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
202 if (s->wwn) {
203
204 put_le16(p + 108, s->wwn >> 48);
205 put_le16(p + 109, s->wwn >> 32);
206 put_le16(p + 110, s->wwn >> 16);
207 put_le16(p + 111, s->wwn);
208 }
209 if (dev && dev->conf.discard_granularity) {
210 put_le16(p + 169, 1);
211 }
212 if (dev) {
213 put_le16(p + 217, dev->rotation_rate);
214 }
215
216 ide_identify_size(s);
217 s->identify_set = 1;
218
219fill_buffer:
220 memcpy(s->io_buffer, p, sizeof(s->identify_data));
221}
222
223static void ide_atapi_identify(IDEState *s)
224{
225 uint16_t *p;
226
227 p = (uint16_t *)s->identify_data;
228 if (s->identify_set) {
229 goto fill_buffer;
230 }
231 memset(p, 0, sizeof(s->identify_data));
232
233
234 put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
235 padstr((char *)(p + 10), s->drive_serial_str, 20);
236 put_le16(p + 20, 3);
237 put_le16(p + 21, 512);
238 put_le16(p + 22, 4);
239 padstr((char *)(p + 23), s->version, 8);
240 padstr((char *)(p + 27), s->drive_model_str, 40);
241 put_le16(p + 48, 1);
242#ifdef USE_DMA_CDROM
243 put_le16(p + 49, 1 << 9 | 1 << 8);
244 put_le16(p + 53, 7);
245 put_le16(p + 62, 7);
246 put_le16(p + 63, 7);
247#else
248 put_le16(p + 49, 1 << 9);
249 put_le16(p + 53, 3);
250 put_le16(p + 63, 0x103);
251#endif
252 put_le16(p + 64, 3);
253 put_le16(p + 65, 0xb4);
254 put_le16(p + 66, 0xb4);
255 put_le16(p + 67, 0x12c);
256 put_le16(p + 68, 0xb4);
257
258 put_le16(p + 71, 30);
259 put_le16(p + 72, 30);
260
261 if (s->ncq_queues) {
262 put_le16(p + 75, s->ncq_queues - 1);
263
264 put_le16(p + 76, (1 << 8));
265 }
266
267 put_le16(p + 80, 0x1e);
268 if (s->wwn) {
269 put_le16(p + 84, (1 << 8));
270 put_le16(p + 87, (1 << 8));
271 }
272
273#ifdef USE_DMA_CDROM
274 put_le16(p + 88, 0x3f | (1 << 13));
275#endif
276
277 if (s->wwn) {
278
279 put_le16(p + 108, s->wwn >> 48);
280 put_le16(p + 109, s->wwn >> 32);
281 put_le16(p + 110, s->wwn >> 16);
282 put_le16(p + 111, s->wwn);
283 }
284
285 s->identify_set = 1;
286
287fill_buffer:
288 memcpy(s->io_buffer, p, sizeof(s->identify_data));
289}
290
291static void ide_cfata_identify_size(IDEState *s)
292{
293 uint16_t *p = (uint16_t *)s->identify_data;
294 put_le16(p + 7, s->nb_sectors >> 16);
295 put_le16(p + 8, s->nb_sectors);
296 put_le16(p + 60, s->nb_sectors);
297 put_le16(p + 61, s->nb_sectors >> 16);
298}
299
300static void ide_cfata_identify(IDEState *s)
301{
302 uint16_t *p;
303 uint32_t cur_sec;
304
305 p = (uint16_t *)s->identify_data;
306 if (s->identify_set) {
307 goto fill_buffer;
308 }
309 memset(p, 0, sizeof(s->identify_data));
310
311 cur_sec = s->cylinders * s->heads * s->sectors;
312
313 put_le16(p + 0, 0x848a);
314 put_le16(p + 1, s->cylinders);
315 put_le16(p + 3, s->heads);
316 put_le16(p + 6, s->sectors);
317
318
319 padstr((char *)(p + 10), s->drive_serial_str, 20);
320 put_le16(p + 22, 0x0004);
321 padstr((char *) (p + 23), s->version, 8);
322 padstr((char *) (p + 27), s->drive_model_str, 40);
323#if MAX_MULT_SECTORS > 1
324 put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
325#else
326 put_le16(p + 47, 0x0000);
327#endif
328 put_le16(p + 49, 0x0f00);
329 put_le16(p + 51, 0x0002);
330 put_le16(p + 52, 0x0001);
331 put_le16(p + 53, 0x0003);
332 put_le16(p + 54, s->cylinders);
333 put_le16(p + 55, s->heads);
334 put_le16(p + 56, s->sectors);
335 put_le16(p + 57, cur_sec);
336 put_le16(p + 58, cur_sec >> 16);
337 if (s->mult_sectors)
338 put_le16(p + 59, 0x100 | s->mult_sectors);
339
340
341 put_le16(p + 63, 0x0203);
342 put_le16(p + 64, 0x0001);
343 put_le16(p + 65, 0x0096);
344 put_le16(p + 66, 0x0096);
345 put_le16(p + 68, 0x00b4);
346 put_le16(p + 82, 0x400c);
347 put_le16(p + 83, 0x7068);
348 put_le16(p + 84, 0x4000);
349 put_le16(p + 85, 0x000c);
350 put_le16(p + 86, 0x7044);
351 put_le16(p + 87, 0x4000);
352 put_le16(p + 91, 0x4060);
353 put_le16(p + 129, 0x0002);
354 put_le16(p + 130, 0x0005);
355 put_le16(p + 131, 0x0001);
356 put_le16(p + 132, 0x0000);
357 put_le16(p + 160, 0x8100);
358 put_le16(p + 161, 0x8001);
359
360 ide_cfata_identify_size(s);
361 s->identify_set = 1;
362
363fill_buffer:
364 memcpy(s->io_buffer, p, sizeof(s->identify_data));
365}
366
367static void ide_set_signature(IDEState *s)
368{
369 s->select &= 0xf0;
370
371 s->nsector = 1;
372 s->sector = 1;
373 if (s->drive_kind == IDE_CD) {
374 s->lcyl = 0x14;
375 s->hcyl = 0xeb;
376 } else if (s->blk) {
377 s->lcyl = 0;
378 s->hcyl = 0;
379 } else {
380 s->lcyl = 0xff;
381 s->hcyl = 0xff;
382 }
383}
384
385static bool ide_sect_range_ok(IDEState *s,
386 uint64_t sector, uint64_t nb_sectors)
387{
388 uint64_t total_sectors;
389
390 blk_get_geometry(s->blk, &total_sectors);
391 if (sector > total_sectors || nb_sectors > total_sectors - sector) {
392 return false;
393 }
394 return true;
395}
396
397typedef struct TrimAIOCB {
398 BlockAIOCB common;
399 IDEState *s;
400 QEMUBH *bh;
401 int ret;
402 QEMUIOVector *qiov;
403 BlockAIOCB *aiocb;
404 int i, j;
405} TrimAIOCB;
406
407static void trim_aio_cancel(BlockAIOCB *acb)
408{
409 TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
410
411
412 iocb->j = iocb->qiov->niov - 1;
413 iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
414
415 iocb->ret = -ECANCELED;
416
417 if (iocb->aiocb) {
418 blk_aio_cancel_async(iocb->aiocb);
419 iocb->aiocb = NULL;
420 }
421}
422
423static const AIOCBInfo trim_aiocb_info = {
424 .aiocb_size = sizeof(TrimAIOCB),
425 .cancel_async = trim_aio_cancel,
426};
427
428static void ide_trim_bh_cb(void *opaque)
429{
430 TrimAIOCB *iocb = opaque;
431
432 iocb->common.cb(iocb->common.opaque, iocb->ret);
433
434 qemu_bh_delete(iocb->bh);
435 iocb->bh = NULL;
436 qemu_aio_unref(iocb);
437}
438
439static void ide_issue_trim_cb(void *opaque, int ret)
440{
441 TrimAIOCB *iocb = opaque;
442 IDEState *s = iocb->s;
443
444 if (ret >= 0) {
445 while (iocb->j < iocb->qiov->niov) {
446 int j = iocb->j;
447 while (++iocb->i < iocb->qiov->iov[j].iov_len / 8) {
448 int i = iocb->i;
449 uint64_t *buffer = iocb->qiov->iov[j].iov_base;
450
451
452 uint64_t entry = le64_to_cpu(buffer[i]);
453 uint64_t sector = entry & 0x0000ffffffffffffULL;
454 uint16_t count = entry >> 48;
455
456 if (count == 0) {
457 continue;
458 }
459
460 if (!ide_sect_range_ok(s, sector, count)) {
461 iocb->ret = -EINVAL;
462 goto done;
463 }
464
465
466 iocb->aiocb = blk_aio_pdiscard(s->blk,
467 sector << BDRV_SECTOR_BITS,
468 count << BDRV_SECTOR_BITS,
469 ide_issue_trim_cb, opaque);
470 return;
471 }
472
473 iocb->j++;
474 iocb->i = -1;
475 }
476 } else {
477 iocb->ret = ret;
478 }
479
480done:
481 iocb->aiocb = NULL;
482 if (iocb->bh) {
483 replay_bh_schedule_event(iocb->bh);
484 }
485}
486
487BlockAIOCB *ide_issue_trim(
488 int64_t offset, QEMUIOVector *qiov,
489 BlockCompletionFunc *cb, void *cb_opaque, void *opaque)
490{
491 IDEState *s = opaque;
492 TrimAIOCB *iocb;
493
494 iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
495 iocb->s = s;
496 iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
497 iocb->ret = 0;
498 iocb->qiov = qiov;
499 iocb->i = -1;
500 iocb->j = 0;
501 ide_issue_trim_cb(iocb, 0);
502 return &iocb->common;
503}
504
505void ide_abort_command(IDEState *s)
506{
507 ide_transfer_stop(s);
508 s->status = READY_STAT | ERR_STAT;
509 s->error = ABRT_ERR;
510}
511
512static void ide_set_retry(IDEState *s)
513{
514 s->bus->retry_unit = s->unit;
515 s->bus->retry_sector_num = ide_get_sector(s);
516 s->bus->retry_nsector = s->nsector;
517}
518
519static void ide_clear_retry(IDEState *s)
520{
521 s->bus->retry_unit = -1;
522 s->bus->retry_sector_num = 0;
523 s->bus->retry_nsector = 0;
524}
525
526
527bool ide_transfer_start_norecurse(IDEState *s, uint8_t *buf, int size,
528 EndTransferFunc *end_transfer_func)
529{
530 s->data_ptr = buf;
531 s->data_end = buf + size;
532 ide_set_retry(s);
533 if (!(s->status & ERR_STAT)) {
534 s->status |= DRQ_STAT;
535 }
536 if (!s->bus->dma->ops->pio_transfer) {
537 s->end_transfer_func = end_transfer_func;
538 return false;
539 }
540 s->bus->dma->ops->pio_transfer(s->bus->dma);
541 return true;
542}
543
544void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
545 EndTransferFunc *end_transfer_func)
546{
547 if (ide_transfer_start_norecurse(s, buf, size, end_transfer_func)) {
548 end_transfer_func(s);
549 }
550}
551
552static void ide_cmd_done(IDEState *s)
553{
554 if (s->bus->dma->ops->cmd_done) {
555 s->bus->dma->ops->cmd_done(s->bus->dma);
556 }
557}
558
559static void ide_transfer_halt(IDEState *s)
560{
561 s->end_transfer_func = ide_transfer_stop;
562 s->data_ptr = s->io_buffer;
563 s->data_end = s->io_buffer;
564 s->status &= ~DRQ_STAT;
565}
566
567void ide_transfer_stop(IDEState *s)
568{
569 ide_transfer_halt(s);
570 ide_cmd_done(s);
571}
572
573int64_t ide_get_sector(IDEState *s)
574{
575 int64_t sector_num;
576 if (s->select & 0x40) {
577
578 if (!s->lba48) {
579 sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
580 (s->lcyl << 8) | s->sector;
581 } else {
582 sector_num = ((int64_t)s->hob_hcyl << 40) |
583 ((int64_t) s->hob_lcyl << 32) |
584 ((int64_t) s->hob_sector << 24) |
585 ((int64_t) s->hcyl << 16) |
586 ((int64_t) s->lcyl << 8) | s->sector;
587 }
588 } else {
589 sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
590 (s->select & 0x0f) * s->sectors + (s->sector - 1);
591 }
592 return sector_num;
593}
594
595void ide_set_sector(IDEState *s, int64_t sector_num)
596{
597 unsigned int cyl, r;
598 if (s->select & 0x40) {
599 if (!s->lba48) {
600 s->select = (s->select & 0xf0) | (sector_num >> 24);
601 s->hcyl = (sector_num >> 16);
602 s->lcyl = (sector_num >> 8);
603 s->sector = (sector_num);
604 } else {
605 s->sector = sector_num;
606 s->lcyl = sector_num >> 8;
607 s->hcyl = sector_num >> 16;
608 s->hob_sector = sector_num >> 24;
609 s->hob_lcyl = sector_num >> 32;
610 s->hob_hcyl = sector_num >> 40;
611 }
612 } else {
613 cyl = sector_num / (s->heads * s->sectors);
614 r = sector_num % (s->heads * s->sectors);
615 s->hcyl = cyl >> 8;
616 s->lcyl = cyl;
617 s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
618 s->sector = (r % s->sectors) + 1;
619 }
620}
621
622static void ide_rw_error(IDEState *s) {
623 ide_abort_command(s);
624 ide_set_irq(s->bus);
625}
626
627static void ide_buffered_readv_cb(void *opaque, int ret)
628{
629 IDEBufferedRequest *req = opaque;
630 if (!req->orphaned) {
631 if (!ret) {
632 assert(req->qiov.size == req->original_qiov->size);
633 qemu_iovec_from_buf(req->original_qiov, 0,
634 req->qiov.local_iov.iov_base,
635 req->original_qiov->size);
636 }
637 req->original_cb(req->original_opaque, ret);
638 }
639 QLIST_REMOVE(req, list);
640 qemu_vfree(qemu_iovec_buf(&req->qiov));
641 g_free(req);
642}
643
644#define MAX_BUFFERED_REQS 16
645
646BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num,
647 QEMUIOVector *iov, int nb_sectors,
648 BlockCompletionFunc *cb, void *opaque)
649{
650 BlockAIOCB *aioreq;
651 IDEBufferedRequest *req;
652 int c = 0;
653
654 QLIST_FOREACH(req, &s->buffered_requests, list) {
655 c++;
656 }
657 if (c > MAX_BUFFERED_REQS) {
658 return blk_abort_aio_request(s->blk, cb, opaque, -EIO);
659 }
660
661 req = g_new0(IDEBufferedRequest, 1);
662 req->original_qiov = iov;
663 req->original_cb = cb;
664 req->original_opaque = opaque;
665 qemu_iovec_init_buf(&req->qiov, blk_blockalign(s->blk, iov->size),
666 iov->size);
667
668 aioreq = blk_aio_preadv(s->blk, sector_num << BDRV_SECTOR_BITS,
669 &req->qiov, 0, ide_buffered_readv_cb, req);
670
671 QLIST_INSERT_HEAD(&s->buffered_requests, req, list);
672 return aioreq;
673}
674
675
676
677
678
679
680void ide_cancel_dma_sync(IDEState *s)
681{
682 IDEBufferedRequest *req;
683
684
685
686
687
688 QLIST_FOREACH(req, &s->buffered_requests, list) {
689 if (!req->orphaned) {
690 trace_ide_cancel_dma_sync_buffered(req->original_cb, req);
691 req->original_cb(req->original_opaque, -ECANCELED);
692 }
693 req->orphaned = true;
694 }
695
696
697
698
699
700
701
702
703
704
705
706
707
708 if (s->bus->dma->aiocb) {
709 trace_ide_cancel_dma_sync_remaining();
710 blk_drain(s->blk);
711 assert(s->bus->dma->aiocb == NULL);
712 }
713}
714
715static void ide_sector_read(IDEState *s);
716
717static void ide_sector_read_cb(void *opaque, int ret)
718{
719 IDEState *s = opaque;
720 int n;
721
722 s->pio_aiocb = NULL;
723 s->status &= ~BUSY_STAT;
724
725 if (ret != 0) {
726 if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO |
727 IDE_RETRY_READ)) {
728 return;
729 }
730 }
731
732 block_acct_done(blk_get_stats(s->blk), &s->acct);
733
734 n = s->nsector;
735 if (n > s->req_nb_sectors) {
736 n = s->req_nb_sectors;
737 }
738
739 ide_set_sector(s, ide_get_sector(s) + n);
740 s->nsector -= n;
741
742 ide_transfer_start(s, s->io_buffer, n * BDRV_SECTOR_SIZE, ide_sector_read);
743 ide_set_irq(s->bus);
744}
745
746static void ide_sector_read(IDEState *s)
747{
748 int64_t sector_num;
749 int n;
750
751 s->status = READY_STAT | SEEK_STAT;
752 s->error = 0;
753 sector_num = ide_get_sector(s);
754 n = s->nsector;
755
756 if (n == 0) {
757 ide_transfer_stop(s);
758 return;
759 }
760
761 s->status |= BUSY_STAT;
762
763 if (n > s->req_nb_sectors) {
764 n = s->req_nb_sectors;
765 }
766
767 trace_ide_sector_read(sector_num, n);
768
769 if (!ide_sect_range_ok(s, sector_num, n)) {
770 ide_rw_error(s);
771 block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
772 return;
773 }
774
775 qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
776
777 block_acct_start(blk_get_stats(s->blk), &s->acct,
778 n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
779 s->pio_aiocb = ide_buffered_readv(s, sector_num, &s->qiov, n,
780 ide_sector_read_cb, s);
781}
782
783void dma_buf_commit(IDEState *s, uint32_t tx_bytes)
784{
785 if (s->bus->dma->ops->commit_buf) {
786 s->bus->dma->ops->commit_buf(s->bus->dma, tx_bytes);
787 }
788 s->io_buffer_offset += tx_bytes;
789 qemu_sglist_destroy(&s->sg);
790}
791
792void ide_set_inactive(IDEState *s, bool more)
793{
794 s->bus->dma->aiocb = NULL;
795 ide_clear_retry(s);
796 if (s->bus->dma->ops->set_inactive) {
797 s->bus->dma->ops->set_inactive(s->bus->dma, more);
798 }
799 ide_cmd_done(s);
800}
801
802void ide_dma_error(IDEState *s)
803{
804 dma_buf_commit(s, 0);
805 ide_abort_command(s);
806 ide_set_inactive(s, false);
807 ide_set_irq(s->bus);
808}
809
810int ide_handle_rw_error(IDEState *s, int error, int op)
811{
812 bool is_read = (op & IDE_RETRY_READ) != 0;
813 BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
814
815 if (action == BLOCK_ERROR_ACTION_STOP) {
816 assert(s->bus->retry_unit == s->unit);
817 s->bus->error_status = op;
818 } else if (action == BLOCK_ERROR_ACTION_REPORT) {
819 block_acct_failed(blk_get_stats(s->blk), &s->acct);
820 if (IS_IDE_RETRY_DMA(op)) {
821 ide_dma_error(s);
822 } else if (IS_IDE_RETRY_ATAPI(op)) {
823 ide_atapi_io_error(s, -error);
824 } else {
825 ide_rw_error(s);
826 }
827 }
828 blk_error_action(s->blk, action, is_read, error);
829 return action != BLOCK_ERROR_ACTION_IGNORE;
830}
831
832static void ide_dma_cb(void *opaque, int ret)
833{
834 IDEState *s = opaque;
835 int n;
836 int64_t sector_num;
837 uint64_t offset;
838 bool stay_active = false;
839
840 if (ret == -EINVAL) {
841 ide_dma_error(s);
842 return;
843 }
844
845 if (ret < 0) {
846 if (ide_handle_rw_error(s, -ret, ide_dma_cmd_to_retry(s->dma_cmd))) {
847 s->bus->dma->aiocb = NULL;
848 dma_buf_commit(s, 0);
849 return;
850 }
851 }
852
853 n = s->io_buffer_size >> 9;
854 if (n > s->nsector) {
855
856
857
858 n = s->nsector;
859 stay_active = true;
860 }
861
862 sector_num = ide_get_sector(s);
863 if (n > 0) {
864 assert(n * 512 == s->sg.size);
865 dma_buf_commit(s, s->sg.size);
866 sector_num += n;
867 ide_set_sector(s, sector_num);
868 s->nsector -= n;
869 }
870
871
872 if (s->nsector == 0) {
873 s->status = READY_STAT | SEEK_STAT;
874 ide_set_irq(s->bus);
875 goto eot;
876 }
877
878
879 n = s->nsector;
880 s->io_buffer_index = 0;
881 s->io_buffer_size = n * 512;
882 if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) {
883
884
885 s->status = READY_STAT | SEEK_STAT;
886 dma_buf_commit(s, 0);
887 goto eot;
888 }
889
890 trace_ide_dma_cb(s, sector_num, n, IDE_DMA_CMD_str(s->dma_cmd));
891
892 if ((s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) &&
893 !ide_sect_range_ok(s, sector_num, n)) {
894 ide_dma_error(s);
895 block_acct_invalid(blk_get_stats(s->blk), s->acct.type);
896 return;
897 }
898
899 offset = sector_num << BDRV_SECTOR_BITS;
900 switch (s->dma_cmd) {
901 case IDE_DMA_READ:
902 s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset,
903 BDRV_SECTOR_SIZE, ide_dma_cb, s);
904 break;
905 case IDE_DMA_WRITE:
906 s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset,
907 BDRV_SECTOR_SIZE, ide_dma_cb, s);
908 break;
909 case IDE_DMA_TRIM:
910 s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk),
911 &s->sg, offset, BDRV_SECTOR_SIZE,
912 ide_issue_trim, s, ide_dma_cb, s,
913 DMA_DIRECTION_TO_DEVICE);
914 break;
915 default:
916 abort();
917 }
918 return;
919
920eot:
921 if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
922 block_acct_done(blk_get_stats(s->blk), &s->acct);
923 }
924 ide_set_inactive(s, stay_active);
925}
926
927static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
928{
929 s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
930 s->io_buffer_size = 0;
931 s->dma_cmd = dma_cmd;
932
933 switch (dma_cmd) {
934 case IDE_DMA_READ:
935 block_acct_start(blk_get_stats(s->blk), &s->acct,
936 s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
937 break;
938 case IDE_DMA_WRITE:
939 block_acct_start(blk_get_stats(s->blk), &s->acct,
940 s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
941 break;
942 default:
943 break;
944 }
945
946 ide_start_dma(s, ide_dma_cb);
947}
948
949void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
950{
951 s->io_buffer_index = 0;
952 ide_set_retry(s);
953 if (s->bus->dma->ops->start_dma) {
954 s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
955 }
956}
957
958static void ide_sector_write(IDEState *s);
959
960static void ide_sector_write_timer_cb(void *opaque)
961{
962 IDEState *s = opaque;
963 ide_set_irq(s->bus);
964}
965
966static void ide_sector_write_cb(void *opaque, int ret)
967{
968 IDEState *s = opaque;
969 int n;
970
971 s->pio_aiocb = NULL;
972 s->status &= ~BUSY_STAT;
973
974 if (ret != 0) {
975 if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO)) {
976 return;
977 }
978 }
979
980 block_acct_done(blk_get_stats(s->blk), &s->acct);
981
982 n = s->nsector;
983 if (n > s->req_nb_sectors) {
984 n = s->req_nb_sectors;
985 }
986 s->nsector -= n;
987
988 ide_set_sector(s, ide_get_sector(s) + n);
989 if (s->nsector == 0) {
990
991 ide_transfer_stop(s);
992 } else {
993 int n1 = s->nsector;
994 if (n1 > s->req_nb_sectors) {
995 n1 = s->req_nb_sectors;
996 }
997 ide_transfer_start(s, s->io_buffer, n1 * BDRV_SECTOR_SIZE,
998 ide_sector_write);
999 }
1000
1001 if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
1002
1003
1004
1005
1006
1007
1008 timer_mod(s->sector_write_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
1009 (NANOSECONDS_PER_SECOND / 1000));
1010 } else {
1011 ide_set_irq(s->bus);
1012 }
1013}
1014
1015static void ide_sector_write(IDEState *s)
1016{
1017 int64_t sector_num;
1018 int n;
1019
1020 s->status = READY_STAT | SEEK_STAT | BUSY_STAT;
1021 sector_num = ide_get_sector(s);
1022
1023 n = s->nsector;
1024 if (n > s->req_nb_sectors) {
1025 n = s->req_nb_sectors;
1026 }
1027
1028 trace_ide_sector_write(sector_num, n);
1029
1030 if (!ide_sect_range_ok(s, sector_num, n)) {
1031 ide_rw_error(s);
1032 block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
1033 return;
1034 }
1035
1036 qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
1037
1038 block_acct_start(blk_get_stats(s->blk), &s->acct,
1039 n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
1040 s->pio_aiocb = blk_aio_pwritev(s->blk, sector_num << BDRV_SECTOR_BITS,
1041 &s->qiov, 0, ide_sector_write_cb, s);
1042}
1043
1044static void ide_flush_cb(void *opaque, int ret)
1045{
1046 IDEState *s = opaque;
1047
1048 s->pio_aiocb = NULL;
1049
1050 if (ret < 0) {
1051
1052 if (ide_handle_rw_error(s, -ret, IDE_RETRY_FLUSH)) {
1053 return;
1054 }
1055 }
1056
1057 if (s->blk) {
1058 block_acct_done(blk_get_stats(s->blk), &s->acct);
1059 }
1060 s->status = READY_STAT | SEEK_STAT;
1061 ide_cmd_done(s);
1062 ide_set_irq(s->bus);
1063}
1064
1065static void ide_flush_cache(IDEState *s)
1066{
1067 if (s->blk == NULL) {
1068 ide_flush_cb(s, 0);
1069 return;
1070 }
1071
1072 s->status |= BUSY_STAT;
1073 ide_set_retry(s);
1074 block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
1075 s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
1076}
1077
1078static void ide_cfata_metadata_inquiry(IDEState *s)
1079{
1080 uint16_t *p;
1081 uint32_t spd;
1082
1083 p = (uint16_t *) s->io_buffer;
1084 memset(p, 0, 0x200);
1085 spd = ((s->mdata_size - 1) >> 9) + 1;
1086
1087 put_le16(p + 0, 0x0001);
1088 put_le16(p + 1, 0x0000);
1089 put_le16(p + 2, s->media_changed);
1090 put_le16(p + 3, s->mdata_size & 0xffff);
1091 put_le16(p + 4, s->mdata_size >> 16);
1092 put_le16(p + 5, spd & 0xffff);
1093 put_le16(p + 6, spd >> 16);
1094}
1095
1096static void ide_cfata_metadata_read(IDEState *s)
1097{
1098 uint16_t *p;
1099
1100 if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
1101 s->status = ERR_STAT;
1102 s->error = ABRT_ERR;
1103 return;
1104 }
1105
1106 p = (uint16_t *) s->io_buffer;
1107 memset(p, 0, 0x200);
1108
1109 put_le16(p + 0, s->media_changed);
1110 memcpy(p + 1, s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
1111 MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
1112 s->nsector << 9), 0x200 - 2));
1113}
1114
1115static void ide_cfata_metadata_write(IDEState *s)
1116{
1117 if (((s->hcyl << 16) | s->lcyl) << 9 > s->mdata_size + 2) {
1118 s->status = ERR_STAT;
1119 s->error = ABRT_ERR;
1120 return;
1121 }
1122
1123 s->media_changed = 0;
1124
1125 memcpy(s->mdata_storage + (((s->hcyl << 16) | s->lcyl) << 9),
1126 s->io_buffer + 2,
1127 MIN(MIN(s->mdata_size - (((s->hcyl << 16) | s->lcyl) << 9),
1128 s->nsector << 9), 0x200 - 2));
1129}
1130
1131
1132static void ide_cd_change_cb(void *opaque, bool load, Error **errp)
1133{
1134 IDEState *s = opaque;
1135 uint64_t nb_sectors;
1136
1137 s->tray_open = !load;
1138 blk_get_geometry(s->blk, &nb_sectors);
1139 s->nb_sectors = nb_sectors;
1140
1141
1142
1143
1144
1145
1146
1147
1148 s->cdrom_changed = 1;
1149 s->events.new_media = true;
1150 s->events.eject_request = false;
1151 ide_set_irq(s->bus);
1152}
1153
1154static void ide_cd_eject_request_cb(void *opaque, bool force)
1155{
1156 IDEState *s = opaque;
1157
1158 s->events.eject_request = true;
1159 if (force) {
1160 s->tray_locked = false;
1161 }
1162 ide_set_irq(s->bus);
1163}
1164
1165static void ide_cmd_lba48_transform(IDEState *s, int lba48)
1166{
1167 s->lba48 = lba48;
1168
1169
1170
1171
1172
1173 if (!s->lba48) {
1174 if (!s->nsector)
1175 s->nsector = 256;
1176 } else {
1177 if (!s->nsector && !s->hob_nsector)
1178 s->nsector = 65536;
1179 else {
1180 int lo = s->nsector;
1181 int hi = s->hob_nsector;
1182
1183 s->nsector = (hi << 8) | lo;
1184 }
1185 }
1186}
1187
1188static void ide_clear_hob(IDEBus *bus)
1189{
1190
1191 bus->ifs[0].select &= ~(1 << 7);
1192 bus->ifs[1].select &= ~(1 << 7);
1193}
1194
1195
1196enum ATA_IOPORT_WR {
1197 ATA_IOPORT_WR_DATA = 0,
1198 ATA_IOPORT_WR_FEATURES = 1,
1199 ATA_IOPORT_WR_SECTOR_COUNT = 2,
1200 ATA_IOPORT_WR_SECTOR_NUMBER = 3,
1201 ATA_IOPORT_WR_CYLINDER_LOW = 4,
1202 ATA_IOPORT_WR_CYLINDER_HIGH = 5,
1203 ATA_IOPORT_WR_DEVICE_HEAD = 6,
1204 ATA_IOPORT_WR_COMMAND = 7,
1205 ATA_IOPORT_WR_NUM_REGISTERS,
1206};
1207
1208const char *ATA_IOPORT_WR_lookup[ATA_IOPORT_WR_NUM_REGISTERS] = {
1209 [ATA_IOPORT_WR_DATA] = "Data",
1210 [ATA_IOPORT_WR_FEATURES] = "Features",
1211 [ATA_IOPORT_WR_SECTOR_COUNT] = "Sector Count",
1212 [ATA_IOPORT_WR_SECTOR_NUMBER] = "Sector Number",
1213 [ATA_IOPORT_WR_CYLINDER_LOW] = "Cylinder Low",
1214 [ATA_IOPORT_WR_CYLINDER_HIGH] = "Cylinder High",
1215 [ATA_IOPORT_WR_DEVICE_HEAD] = "Device/Head",
1216 [ATA_IOPORT_WR_COMMAND] = "Command"
1217};
1218
1219void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1220{
1221 IDEBus *bus = opaque;
1222 IDEState *s = idebus_active_if(bus);
1223 int reg_num = addr & 7;
1224
1225 trace_ide_ioport_write(addr, ATA_IOPORT_WR_lookup[reg_num], val, bus, s);
1226
1227
1228 if (reg_num != 7 && (s->status & (BUSY_STAT|DRQ_STAT))) {
1229 return;
1230 }
1231
1232 switch (reg_num) {
1233 case 0:
1234 break;
1235 case ATA_IOPORT_WR_FEATURES:
1236 ide_clear_hob(bus);
1237
1238 bus->ifs[0].hob_feature = bus->ifs[0].feature;
1239 bus->ifs[1].hob_feature = bus->ifs[1].feature;
1240 bus->ifs[0].feature = val;
1241 bus->ifs[1].feature = val;
1242 break;
1243 case ATA_IOPORT_WR_SECTOR_COUNT:
1244 ide_clear_hob(bus);
1245 bus->ifs[0].hob_nsector = bus->ifs[0].nsector;
1246 bus->ifs[1].hob_nsector = bus->ifs[1].nsector;
1247 bus->ifs[0].nsector = val;
1248 bus->ifs[1].nsector = val;
1249 break;
1250 case ATA_IOPORT_WR_SECTOR_NUMBER:
1251 ide_clear_hob(bus);
1252 bus->ifs[0].hob_sector = bus->ifs[0].sector;
1253 bus->ifs[1].hob_sector = bus->ifs[1].sector;
1254 bus->ifs[0].sector = val;
1255 bus->ifs[1].sector = val;
1256 break;
1257 case ATA_IOPORT_WR_CYLINDER_LOW:
1258 ide_clear_hob(bus);
1259 bus->ifs[0].hob_lcyl = bus->ifs[0].lcyl;
1260 bus->ifs[1].hob_lcyl = bus->ifs[1].lcyl;
1261 bus->ifs[0].lcyl = val;
1262 bus->ifs[1].lcyl = val;
1263 break;
1264 case ATA_IOPORT_WR_CYLINDER_HIGH:
1265 ide_clear_hob(bus);
1266 bus->ifs[0].hob_hcyl = bus->ifs[0].hcyl;
1267 bus->ifs[1].hob_hcyl = bus->ifs[1].hcyl;
1268 bus->ifs[0].hcyl = val;
1269 bus->ifs[1].hcyl = val;
1270 break;
1271 case ATA_IOPORT_WR_DEVICE_HEAD:
1272
1273 bus->ifs[0].select = (val & ~0x10) | 0xa0;
1274 bus->ifs[1].select = (val | 0x10) | 0xa0;
1275
1276 bus->unit = (val >> 4) & 1;
1277 break;
1278 default:
1279 case ATA_IOPORT_WR_COMMAND:
1280
1281 ide_exec_cmd(bus, val);
1282 break;
1283 }
1284}
1285
1286static void ide_reset(IDEState *s)
1287{
1288 trace_ide_reset(s);
1289
1290 if (s->pio_aiocb) {
1291 blk_aio_cancel(s->pio_aiocb);
1292 s->pio_aiocb = NULL;
1293 }
1294
1295 if (s->drive_kind == IDE_CFATA)
1296 s->mult_sectors = 0;
1297 else
1298 s->mult_sectors = MAX_MULT_SECTORS;
1299
1300 s->feature = 0;
1301 s->error = 0;
1302 s->nsector = 0;
1303 s->sector = 0;
1304 s->lcyl = 0;
1305 s->hcyl = 0;
1306
1307
1308 s->hob_feature = 0;
1309 s->hob_sector = 0;
1310 s->hob_nsector = 0;
1311 s->hob_lcyl = 0;
1312 s->hob_hcyl = 0;
1313
1314 s->select = 0xa0;
1315 s->status = READY_STAT | SEEK_STAT;
1316
1317 s->lba48 = 0;
1318
1319
1320 s->sense_key = 0;
1321 s->asc = 0;
1322 s->cdrom_changed = 0;
1323 s->packet_transfer_size = 0;
1324 s->elementary_transfer_size = 0;
1325 s->io_buffer_index = 0;
1326 s->cd_sector_size = 0;
1327 s->atapi_dma = 0;
1328 s->tray_locked = 0;
1329 s->tray_open = 0;
1330
1331 s->io_buffer_size = 0;
1332 s->req_nb_sectors = 0;
1333
1334 ide_set_signature(s);
1335
1336
1337 s->end_transfer_func = ide_dummy_transfer_stop;
1338 ide_dummy_transfer_stop(s);
1339 s->media_changed = 0;
1340}
1341
1342static bool cmd_nop(IDEState *s, uint8_t cmd)
1343{
1344 return true;
1345}
1346
1347static bool cmd_device_reset(IDEState *s, uint8_t cmd)
1348{
1349
1350 ide_transfer_halt(s);
1351 ide_cancel_dma_sync(s);
1352
1353
1354 ide_reset(s);
1355
1356
1357
1358 s->status = 0x00;
1359
1360
1361 return false;
1362}
1363
1364static bool cmd_data_set_management(IDEState *s, uint8_t cmd)
1365{
1366 switch (s->feature) {
1367 case DSM_TRIM:
1368 if (s->blk) {
1369 ide_sector_start_dma(s, IDE_DMA_TRIM);
1370 return false;
1371 }
1372 break;
1373 }
1374
1375 ide_abort_command(s);
1376 return true;
1377}
1378
1379static bool cmd_identify(IDEState *s, uint8_t cmd)
1380{
1381 if (s->blk && s->drive_kind != IDE_CD) {
1382 if (s->drive_kind != IDE_CFATA) {
1383 ide_identify(s);
1384 } else {
1385 ide_cfata_identify(s);
1386 }
1387 s->status = READY_STAT | SEEK_STAT;
1388 ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1389 ide_set_irq(s->bus);
1390 return false;
1391 } else {
1392 if (s->drive_kind == IDE_CD) {
1393 ide_set_signature(s);
1394 }
1395 ide_abort_command(s);
1396 }
1397
1398 return true;
1399}
1400
1401static bool cmd_verify(IDEState *s, uint8_t cmd)
1402{
1403 bool lba48 = (cmd == WIN_VERIFY_EXT);
1404
1405
1406 ide_cmd_lba48_transform(s, lba48);
1407
1408 return true;
1409}
1410
1411static bool cmd_set_multiple_mode(IDEState *s, uint8_t cmd)
1412{
1413 if (s->drive_kind == IDE_CFATA && s->nsector == 0) {
1414
1415 s->mult_sectors = 0;
1416 } else if ((s->nsector & 0xff) != 0 &&
1417 ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
1418 (s->nsector & (s->nsector - 1)) != 0)) {
1419 ide_abort_command(s);
1420 } else {
1421 s->mult_sectors = s->nsector & 0xff;
1422 }
1423
1424 return true;
1425}
1426
1427static bool cmd_read_multiple(IDEState *s, uint8_t cmd)
1428{
1429 bool lba48 = (cmd == WIN_MULTREAD_EXT);
1430
1431 if (!s->blk || !s->mult_sectors) {
1432 ide_abort_command(s);
1433 return true;
1434 }
1435
1436 ide_cmd_lba48_transform(s, lba48);
1437 s->req_nb_sectors = s->mult_sectors;
1438 ide_sector_read(s);
1439 return false;
1440}
1441
1442static bool cmd_write_multiple(IDEState *s, uint8_t cmd)
1443{
1444 bool lba48 = (cmd == WIN_MULTWRITE_EXT);
1445 int n;
1446
1447 if (!s->blk || !s->mult_sectors) {
1448 ide_abort_command(s);
1449 return true;
1450 }
1451
1452 ide_cmd_lba48_transform(s, lba48);
1453
1454 s->req_nb_sectors = s->mult_sectors;
1455 n = MIN(s->nsector, s->req_nb_sectors);
1456
1457 s->status = SEEK_STAT | READY_STAT;
1458 ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
1459
1460 s->media_changed = 1;
1461
1462 return false;
1463}
1464
1465static bool cmd_read_pio(IDEState *s, uint8_t cmd)
1466{
1467 bool lba48 = (cmd == WIN_READ_EXT);
1468
1469 if (s->drive_kind == IDE_CD) {
1470 ide_set_signature(s);
1471 ide_abort_command(s);
1472 return true;
1473 }
1474
1475 if (!s->blk) {
1476 ide_abort_command(s);
1477 return true;
1478 }
1479
1480 ide_cmd_lba48_transform(s, lba48);
1481 s->req_nb_sectors = 1;
1482 ide_sector_read(s);
1483
1484 return false;
1485}
1486
1487static bool cmd_write_pio(IDEState *s, uint8_t cmd)
1488{
1489 bool lba48 = (cmd == WIN_WRITE_EXT);
1490
1491 if (!s->blk) {
1492 ide_abort_command(s);
1493 return true;
1494 }
1495
1496 ide_cmd_lba48_transform(s, lba48);
1497
1498 s->req_nb_sectors = 1;
1499 s->status = SEEK_STAT | READY_STAT;
1500 ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
1501
1502 s->media_changed = 1;
1503
1504 return false;
1505}
1506
1507static bool cmd_read_dma(IDEState *s, uint8_t cmd)
1508{
1509 bool lba48 = (cmd == WIN_READDMA_EXT);
1510
1511 if (!s->blk) {
1512 ide_abort_command(s);
1513 return true;
1514 }
1515
1516 ide_cmd_lba48_transform(s, lba48);
1517 ide_sector_start_dma(s, IDE_DMA_READ);
1518
1519 return false;
1520}
1521
1522static bool cmd_write_dma(IDEState *s, uint8_t cmd)
1523{
1524 bool lba48 = (cmd == WIN_WRITEDMA_EXT);
1525
1526 if (!s->blk) {
1527 ide_abort_command(s);
1528 return true;
1529 }
1530
1531 ide_cmd_lba48_transform(s, lba48);
1532 ide_sector_start_dma(s, IDE_DMA_WRITE);
1533
1534 s->media_changed = 1;
1535
1536 return false;
1537}
1538
1539static bool cmd_flush_cache(IDEState *s, uint8_t cmd)
1540{
1541 ide_flush_cache(s);
1542 return false;
1543}
1544
1545static bool cmd_seek(IDEState *s, uint8_t cmd)
1546{
1547
1548 return true;
1549}
1550
1551static bool cmd_read_native_max(IDEState *s, uint8_t cmd)
1552{
1553 bool lba48 = (cmd == WIN_READ_NATIVE_MAX_EXT);
1554
1555
1556 if (s->nb_sectors == 0) {
1557 ide_abort_command(s);
1558 return true;
1559 }
1560
1561 ide_cmd_lba48_transform(s, lba48);
1562 ide_set_sector(s, s->nb_sectors - 1);
1563
1564 return true;
1565}
1566
1567static bool cmd_check_power_mode(IDEState *s, uint8_t cmd)
1568{
1569 s->nsector = 0xff;
1570 return true;
1571}
1572
1573static bool cmd_set_features(IDEState *s, uint8_t cmd)
1574{
1575 uint16_t *identify_data;
1576
1577 if (!s->blk) {
1578 ide_abort_command(s);
1579 return true;
1580 }
1581
1582
1583 switch (s->feature) {
1584 case 0x02:
1585 blk_set_enable_write_cache(s->blk, true);
1586 identify_data = (uint16_t *)s->identify_data;
1587 put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1);
1588 return true;
1589 case 0x82:
1590 blk_set_enable_write_cache(s->blk, false);
1591 identify_data = (uint16_t *)s->identify_data;
1592 put_le16(identify_data + 85, (1 << 14) | 1);
1593 ide_flush_cache(s);
1594 return false;
1595 case 0xcc:
1596 case 0x66:
1597 case 0xaa:
1598 case 0x55:
1599 case 0x05:
1600 case 0x85:
1601 case 0x69:
1602 case 0x67:
1603 case 0x96:
1604 case 0x9a:
1605 case 0x42:
1606 case 0xc2:
1607 return true;
1608 case 0x03:
1609 {
1610 uint8_t val = s->nsector & 0x07;
1611 identify_data = (uint16_t *)s->identify_data;
1612
1613 switch (s->nsector >> 3) {
1614 case 0x00:
1615 case 0x01:
1616 put_le16(identify_data + 62, 0x07);
1617 put_le16(identify_data + 63, 0x07);
1618 put_le16(identify_data + 88, 0x3f);
1619 break;
1620 case 0x02:
1621 put_le16(identify_data + 62, 0x07 | (1 << (val + 8)));
1622 put_le16(identify_data + 63, 0x07);
1623 put_le16(identify_data + 88, 0x3f);
1624 break;
1625 case 0x04:
1626 put_le16(identify_data + 62, 0x07);
1627 put_le16(identify_data + 63, 0x07 | (1 << (val + 8)));
1628 put_le16(identify_data + 88, 0x3f);
1629 break;
1630 case 0x08:
1631 put_le16(identify_data + 62, 0x07);
1632 put_le16(identify_data + 63, 0x07);
1633 put_le16(identify_data + 88, 0x3f | (1 << (val + 8)));
1634 break;
1635 default:
1636 goto abort_cmd;
1637 }
1638 return true;
1639 }
1640 }
1641
1642abort_cmd:
1643 ide_abort_command(s);
1644 return true;
1645}
1646
1647
1648
1649
1650static bool cmd_identify_packet(IDEState *s, uint8_t cmd)
1651{
1652 ide_atapi_identify(s);
1653 s->status = READY_STAT | SEEK_STAT;
1654 ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
1655 ide_set_irq(s->bus);
1656 return false;
1657}
1658
1659static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd)
1660{
1661 ide_set_signature(s);
1662
1663 if (s->drive_kind == IDE_CD) {
1664 s->status = 0;
1665
1666
1667 s->error = 0x01;
1668 } else {
1669 s->status = READY_STAT | SEEK_STAT;
1670
1671
1672
1673 s->error = 0x01;
1674 ide_set_irq(s->bus);
1675 }
1676
1677 return false;
1678}
1679
1680static bool cmd_packet(IDEState *s, uint8_t cmd)
1681{
1682
1683 if (s->feature & 0x02) {
1684 ide_abort_command(s);
1685 return true;
1686 }
1687
1688 s->status = READY_STAT | SEEK_STAT;
1689 s->atapi_dma = s->feature & 1;
1690 if (s->atapi_dma) {
1691 s->dma_cmd = IDE_DMA_ATAPI;
1692 }
1693 s->nsector = 1;
1694 ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
1695 ide_atapi_cmd);
1696 return false;
1697}
1698
1699
1700
1701
1702static bool cmd_cfa_req_ext_error_code(IDEState *s, uint8_t cmd)
1703{
1704 s->error = 0x09;
1705 s->status = READY_STAT | SEEK_STAT;
1706 ide_set_irq(s->bus);
1707
1708 return false;
1709}
1710
1711static bool cmd_cfa_erase_sectors(IDEState *s, uint8_t cmd)
1712{
1713
1714
1715
1716 if (cmd == CFA_WEAR_LEVEL) {
1717 s->nsector = 0;
1718 }
1719
1720 if (cmd == CFA_ERASE_SECTORS) {
1721 s->media_changed = 1;
1722 }
1723
1724 return true;
1725}
1726
1727static bool cmd_cfa_translate_sector(IDEState *s, uint8_t cmd)
1728{
1729 s->status = READY_STAT | SEEK_STAT;
1730
1731 memset(s->io_buffer, 0, 0x200);
1732 s->io_buffer[0x00] = s->hcyl;
1733 s->io_buffer[0x01] = s->lcyl;
1734 s->io_buffer[0x02] = s->select;
1735 s->io_buffer[0x03] = s->sector;
1736 s->io_buffer[0x04] = ide_get_sector(s) >> 16;
1737 s->io_buffer[0x05] = ide_get_sector(s) >> 8;
1738 s->io_buffer[0x06] = ide_get_sector(s) >> 0;
1739 s->io_buffer[0x13] = 0x00;
1740 s->io_buffer[0x18] = 0x00;
1741 s->io_buffer[0x19] = 0x00;
1742 s->io_buffer[0x1a] = 0x01;
1743
1744 ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1745 ide_set_irq(s->bus);
1746
1747 return false;
1748}
1749
1750static bool cmd_cfa_access_metadata_storage(IDEState *s, uint8_t cmd)
1751{
1752 switch (s->feature) {
1753 case 0x02:
1754 ide_cfata_metadata_inquiry(s);
1755 break;
1756 case 0x03:
1757 ide_cfata_metadata_read(s);
1758 break;
1759 case 0x04:
1760 ide_cfata_metadata_write(s);
1761 break;
1762 default:
1763 ide_abort_command(s);
1764 return true;
1765 }
1766
1767 ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1768 s->status = 0x00;
1769 ide_set_irq(s->bus);
1770
1771 return false;
1772}
1773
1774static bool cmd_ibm_sense_condition(IDEState *s, uint8_t cmd)
1775{
1776 switch (s->feature) {
1777 case 0x01:
1778 s->nsector = 0x50;
1779 break;
1780 default:
1781 ide_abort_command(s);
1782 return true;
1783 }
1784
1785 return true;
1786}
1787
1788
1789
1790
1791static bool cmd_smart(IDEState *s, uint8_t cmd)
1792{
1793 int n;
1794
1795 if (s->hcyl != 0xc2 || s->lcyl != 0x4f) {
1796 goto abort_cmd;
1797 }
1798
1799 if (!s->smart_enabled && s->feature != SMART_ENABLE) {
1800 goto abort_cmd;
1801 }
1802
1803 switch (s->feature) {
1804 case SMART_DISABLE:
1805 s->smart_enabled = 0;
1806 return true;
1807
1808 case SMART_ENABLE:
1809 s->smart_enabled = 1;
1810 return true;
1811
1812 case SMART_ATTR_AUTOSAVE:
1813 switch (s->sector) {
1814 case 0x00:
1815 s->smart_autosave = 0;
1816 break;
1817 case 0xf1:
1818 s->smart_autosave = 1;
1819 break;
1820 default:
1821 goto abort_cmd;
1822 }
1823 return true;
1824
1825 case SMART_STATUS:
1826 if (!s->smart_errors) {
1827 s->hcyl = 0xc2;
1828 s->lcyl = 0x4f;
1829 } else {
1830 s->hcyl = 0x2c;
1831 s->lcyl = 0xf4;
1832 }
1833 return true;
1834
1835 case SMART_READ_THRESH:
1836 memset(s->io_buffer, 0, 0x200);
1837 s->io_buffer[0] = 0x01;
1838
1839 for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
1840 s->io_buffer[2 + 0 + (n * 12)] = smart_attributes[n][0];
1841 s->io_buffer[2 + 1 + (n * 12)] = smart_attributes[n][11];
1842 }
1843
1844
1845 for (n = 0; n < 511; n++) {
1846 s->io_buffer[511] += s->io_buffer[n];
1847 }
1848 s->io_buffer[511] = 0x100 - s->io_buffer[511];
1849
1850 s->status = READY_STAT | SEEK_STAT;
1851 ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1852 ide_set_irq(s->bus);
1853 return false;
1854
1855 case SMART_READ_DATA:
1856 memset(s->io_buffer, 0, 0x200);
1857 s->io_buffer[0] = 0x01;
1858
1859 for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {
1860 int i;
1861 for (i = 0; i < 11; i++) {
1862 s->io_buffer[2 + i + (n * 12)] = smart_attributes[n][i];
1863 }
1864 }
1865
1866 s->io_buffer[362] = 0x02 | (s->smart_autosave ? 0x80 : 0x00);
1867 if (s->smart_selftest_count == 0) {
1868 s->io_buffer[363] = 0;
1869 } else {
1870 s->io_buffer[363] =
1871 s->smart_selftest_data[3 +
1872 (s->smart_selftest_count - 1) *
1873 24];
1874 }
1875 s->io_buffer[364] = 0x20;
1876 s->io_buffer[365] = 0x01;
1877
1878 s->io_buffer[367] = (1 << 4 | 1 << 3 | 1);
1879 s->io_buffer[368] = 0x03;
1880 s->io_buffer[369] = 0x00;
1881 s->io_buffer[370] = 0x01;
1882 s->io_buffer[372] = 0x02;
1883 s->io_buffer[373] = 0x36;
1884 s->io_buffer[374] = 0x01;
1885
1886 for (n = 0; n < 511; n++) {
1887 s->io_buffer[511] += s->io_buffer[n];
1888 }
1889 s->io_buffer[511] = 0x100 - s->io_buffer[511];
1890
1891 s->status = READY_STAT | SEEK_STAT;
1892 ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1893 ide_set_irq(s->bus);
1894 return false;
1895
1896 case SMART_READ_LOG:
1897 switch (s->sector) {
1898 case 0x01:
1899 memset(s->io_buffer, 0, 0x200);
1900 s->io_buffer[0] = 0x01;
1901 s->io_buffer[1] = 0x00;
1902 s->io_buffer[452] = s->smart_errors & 0xff;
1903 s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;
1904
1905 for (n = 0; n < 511; n++) {
1906 s->io_buffer[511] += s->io_buffer[n];
1907 }
1908 s->io_buffer[511] = 0x100 - s->io_buffer[511];
1909 break;
1910 case 0x06:
1911 memset(s->io_buffer, 0, 0x200);
1912 s->io_buffer[0] = 0x01;
1913 if (s->smart_selftest_count == 0) {
1914 s->io_buffer[508] = 0;
1915 } else {
1916 s->io_buffer[508] = s->smart_selftest_count;
1917 for (n = 2; n < 506; n++) {
1918 s->io_buffer[n] = s->smart_selftest_data[n];
1919 }
1920 }
1921
1922 for (n = 0; n < 511; n++) {
1923 s->io_buffer[511] += s->io_buffer[n];
1924 }
1925 s->io_buffer[511] = 0x100 - s->io_buffer[511];
1926 break;
1927 default:
1928 goto abort_cmd;
1929 }
1930 s->status = READY_STAT | SEEK_STAT;
1931 ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
1932 ide_set_irq(s->bus);
1933 return false;
1934
1935 case SMART_EXECUTE_OFFLINE:
1936 switch (s->sector) {
1937 case 0:
1938 case 1:
1939 case 2:
1940 s->smart_selftest_count++;
1941 if (s->smart_selftest_count > 21) {
1942 s->smart_selftest_count = 1;
1943 }
1944 n = 2 + (s->smart_selftest_count - 1) * 24;
1945 s->smart_selftest_data[n] = s->sector;
1946 s->smart_selftest_data[n + 1] = 0x00;
1947 s->smart_selftest_data[n + 2] = 0x34;
1948 s->smart_selftest_data[n + 3] = 0x12;
1949 break;
1950 default:
1951 goto abort_cmd;
1952 }
1953 return true;
1954 }
1955
1956abort_cmd:
1957 ide_abort_command(s);
1958 return true;
1959}
1960
1961#define HD_OK (1u << IDE_HD)
1962#define CD_OK (1u << IDE_CD)
1963#define CFA_OK (1u << IDE_CFATA)
1964#define HD_CFA_OK (HD_OK | CFA_OK)
1965#define ALL_OK (HD_OK | CD_OK | CFA_OK)
1966
1967
1968#define SET_DSC (1u << 8)
1969
1970
1971static const struct {
1972
1973 bool (*handler)(IDEState *s, uint8_t cmd);
1974 int flags;
1975} ide_cmd_table[0x100] = {
1976
1977 [CFA_REQ_EXT_ERROR_CODE] = { cmd_cfa_req_ext_error_code, CFA_OK },
1978 [WIN_DSM] = { cmd_data_set_management, HD_CFA_OK },
1979 [WIN_DEVICE_RESET] = { cmd_device_reset, CD_OK },
1980 [WIN_RECAL] = { cmd_nop, HD_CFA_OK | SET_DSC},
1981 [WIN_READ] = { cmd_read_pio, ALL_OK },
1982 [WIN_READ_ONCE] = { cmd_read_pio, HD_CFA_OK },
1983 [WIN_READ_EXT] = { cmd_read_pio, HD_CFA_OK },
1984 [WIN_READDMA_EXT] = { cmd_read_dma, HD_CFA_OK },
1985 [WIN_READ_NATIVE_MAX_EXT] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
1986 [WIN_MULTREAD_EXT] = { cmd_read_multiple, HD_CFA_OK },
1987 [WIN_WRITE] = { cmd_write_pio, HD_CFA_OK },
1988 [WIN_WRITE_ONCE] = { cmd_write_pio, HD_CFA_OK },
1989 [WIN_WRITE_EXT] = { cmd_write_pio, HD_CFA_OK },
1990 [WIN_WRITEDMA_EXT] = { cmd_write_dma, HD_CFA_OK },
1991 [CFA_WRITE_SECT_WO_ERASE] = { cmd_write_pio, CFA_OK },
1992 [WIN_MULTWRITE_EXT] = { cmd_write_multiple, HD_CFA_OK },
1993 [WIN_WRITE_VERIFY] = { cmd_write_pio, HD_CFA_OK },
1994 [WIN_VERIFY] = { cmd_verify, HD_CFA_OK | SET_DSC },
1995 [WIN_VERIFY_ONCE] = { cmd_verify, HD_CFA_OK | SET_DSC },
1996 [WIN_VERIFY_EXT] = { cmd_verify, HD_CFA_OK | SET_DSC },
1997 [WIN_SEEK] = { cmd_seek, HD_CFA_OK | SET_DSC },
1998 [CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK },
1999 [WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK },
2000 [WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC },
2001 [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK },
2002 [WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK },
2003 [WIN_STANDBY2] = { cmd_nop, HD_CFA_OK },
2004 [WIN_SETIDLE2] = { cmd_nop, HD_CFA_OK },
2005 [WIN_CHECKPOWERMODE2] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
2006 [WIN_SLEEPNOW2] = { cmd_nop, HD_CFA_OK },
2007 [WIN_PACKETCMD] = { cmd_packet, CD_OK },
2008 [WIN_PIDENTIFY] = { cmd_identify_packet, CD_OK },
2009 [WIN_SMART] = { cmd_smart, HD_CFA_OK | SET_DSC },
2010 [CFA_ACCESS_METADATA_STORAGE] = { cmd_cfa_access_metadata_storage, CFA_OK },
2011 [CFA_ERASE_SECTORS] = { cmd_cfa_erase_sectors, CFA_OK | SET_DSC },
2012 [WIN_MULTREAD] = { cmd_read_multiple, HD_CFA_OK },
2013 [WIN_MULTWRITE] = { cmd_write_multiple, HD_CFA_OK },
2014 [WIN_SETMULT] = { cmd_set_multiple_mode, HD_CFA_OK | SET_DSC },
2015 [WIN_READDMA] = { cmd_read_dma, HD_CFA_OK },
2016 [WIN_READDMA_ONCE] = { cmd_read_dma, HD_CFA_OK },
2017 [WIN_WRITEDMA] = { cmd_write_dma, HD_CFA_OK },
2018 [WIN_WRITEDMA_ONCE] = { cmd_write_dma, HD_CFA_OK },
2019 [CFA_WRITE_MULTI_WO_ERASE] = { cmd_write_multiple, CFA_OK },
2020 [WIN_STANDBYNOW1] = { cmd_nop, HD_CFA_OK },
2021 [WIN_IDLEIMMEDIATE] = { cmd_nop, HD_CFA_OK },
2022 [WIN_STANDBY] = { cmd_nop, HD_CFA_OK },
2023 [WIN_SETIDLE1] = { cmd_nop, HD_CFA_OK },
2024 [WIN_CHECKPOWERMODE1] = { cmd_check_power_mode, HD_CFA_OK | SET_DSC },
2025 [WIN_SLEEPNOW1] = { cmd_nop, HD_CFA_OK },
2026 [WIN_FLUSH_CACHE] = { cmd_flush_cache, ALL_OK },
2027 [WIN_FLUSH_CACHE_EXT] = { cmd_flush_cache, HD_CFA_OK },
2028 [WIN_IDENTIFY] = { cmd_identify, ALL_OK },
2029 [WIN_SETFEATURES] = { cmd_set_features, ALL_OK | SET_DSC },
2030 [IBM_SENSE_CONDITION] = { cmd_ibm_sense_condition, CFA_OK | SET_DSC },
2031 [CFA_WEAR_LEVEL] = { cmd_cfa_erase_sectors, HD_CFA_OK | SET_DSC },
2032 [WIN_READ_NATIVE_MAX] = { cmd_read_native_max, HD_CFA_OK | SET_DSC },
2033};
2034
2035static bool ide_cmd_permitted(IDEState *s, uint32_t cmd)
2036{
2037 return cmd < ARRAY_SIZE(ide_cmd_table)
2038 && (ide_cmd_table[cmd].flags & (1u << s->drive_kind));
2039}
2040
2041void ide_exec_cmd(IDEBus *bus, uint32_t val)
2042{
2043 IDEState *s;
2044 bool complete;
2045
2046 s = idebus_active_if(bus);
2047 trace_ide_exec_cmd(bus, s, val);
2048
2049
2050 if (s != bus->ifs && !s->blk) {
2051 return;
2052 }
2053
2054
2055
2056 if (s->status & (BUSY_STAT|DRQ_STAT)) {
2057 if (val != WIN_DEVICE_RESET || s->drive_kind != IDE_CD) {
2058 return;
2059 }
2060 }
2061
2062 if (!ide_cmd_permitted(s, val)) {
2063 ide_abort_command(s);
2064 ide_set_irq(s->bus);
2065 return;
2066 }
2067
2068 s->status = READY_STAT | BUSY_STAT;
2069 s->error = 0;
2070 s->io_buffer_offset = 0;
2071
2072 complete = ide_cmd_table[val].handler(s, val);
2073 if (complete) {
2074 s->status &= ~BUSY_STAT;
2075 assert(!!s->error == !!(s->status & ERR_STAT));
2076
2077 if ((ide_cmd_table[val].flags & SET_DSC) && !s->error) {
2078 s->status |= SEEK_STAT;
2079 }
2080
2081 ide_cmd_done(s);
2082 ide_set_irq(s->bus);
2083 }
2084}
2085
2086
2087enum ATA_IOPORT_RR {
2088 ATA_IOPORT_RR_DATA = 0,
2089 ATA_IOPORT_RR_ERROR = 1,
2090 ATA_IOPORT_RR_SECTOR_COUNT = 2,
2091 ATA_IOPORT_RR_SECTOR_NUMBER = 3,
2092 ATA_IOPORT_RR_CYLINDER_LOW = 4,
2093 ATA_IOPORT_RR_CYLINDER_HIGH = 5,
2094 ATA_IOPORT_RR_DEVICE_HEAD = 6,
2095 ATA_IOPORT_RR_STATUS = 7,
2096 ATA_IOPORT_RR_NUM_REGISTERS,
2097};
2098
2099const char *ATA_IOPORT_RR_lookup[ATA_IOPORT_RR_NUM_REGISTERS] = {
2100 [ATA_IOPORT_RR_DATA] = "Data",
2101 [ATA_IOPORT_RR_ERROR] = "Error",
2102 [ATA_IOPORT_RR_SECTOR_COUNT] = "Sector Count",
2103 [ATA_IOPORT_RR_SECTOR_NUMBER] = "Sector Number",
2104 [ATA_IOPORT_RR_CYLINDER_LOW] = "Cylinder Low",
2105 [ATA_IOPORT_RR_CYLINDER_HIGH] = "Cylinder High",
2106 [ATA_IOPORT_RR_DEVICE_HEAD] = "Device/Head",
2107 [ATA_IOPORT_RR_STATUS] = "Status"
2108};
2109
2110uint32_t ide_ioport_read(void *opaque, uint32_t addr)
2111{
2112 IDEBus *bus = opaque;
2113 IDEState *s = idebus_active_if(bus);
2114 uint32_t reg_num;
2115 int ret, hob;
2116
2117 reg_num = addr & 7;
2118
2119
2120 hob = 0;
2121 switch (reg_num) {
2122 case ATA_IOPORT_RR_DATA:
2123 ret = 0xff;
2124 break;
2125 case ATA_IOPORT_RR_ERROR:
2126 if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
2127 (s != bus->ifs && !s->blk)) {
2128 ret = 0;
2129 } else if (!hob) {
2130 ret = s->error;
2131 } else {
2132 ret = s->hob_feature;
2133 }
2134 break;
2135 case ATA_IOPORT_RR_SECTOR_COUNT:
2136 if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
2137 ret = 0;
2138 } else if (!hob) {
2139 ret = s->nsector & 0xff;
2140 } else {
2141 ret = s->hob_nsector;
2142 }
2143 break;
2144 case ATA_IOPORT_RR_SECTOR_NUMBER:
2145 if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
2146 ret = 0;
2147 } else if (!hob) {
2148 ret = s->sector;
2149 } else {
2150 ret = s->hob_sector;
2151 }
2152 break;
2153 case ATA_IOPORT_RR_CYLINDER_LOW:
2154 if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
2155 ret = 0;
2156 } else if (!hob) {
2157 ret = s->lcyl;
2158 } else {
2159 ret = s->hob_lcyl;
2160 }
2161 break;
2162 case ATA_IOPORT_RR_CYLINDER_HIGH:
2163 if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
2164 ret = 0;
2165 } else if (!hob) {
2166 ret = s->hcyl;
2167 } else {
2168 ret = s->hob_hcyl;
2169 }
2170 break;
2171 case ATA_IOPORT_RR_DEVICE_HEAD:
2172 if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
2173 ret = 0;
2174 } else {
2175 ret = s->select;
2176 }
2177 break;
2178 default:
2179 case ATA_IOPORT_RR_STATUS:
2180 if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
2181 (s != bus->ifs && !s->blk)) {
2182 ret = 0;
2183 } else {
2184 ret = s->status;
2185 }
2186 qemu_irq_lower(bus->irq);
2187 break;
2188 }
2189
2190 trace_ide_ioport_read(addr, ATA_IOPORT_RR_lookup[reg_num], ret, bus, s);
2191 return ret;
2192}
2193
2194uint32_t ide_status_read(void *opaque, uint32_t addr)
2195{
2196 IDEBus *bus = opaque;
2197 IDEState *s = idebus_active_if(bus);
2198 int ret;
2199
2200 if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
2201 (s != bus->ifs && !s->blk)) {
2202 ret = 0;
2203 } else {
2204 ret = s->status;
2205 }
2206
2207 trace_ide_status_read(addr, ret, bus, s);
2208 return ret;
2209}
2210
2211void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
2212{
2213 IDEBus *bus = opaque;
2214 IDEState *s;
2215 int i;
2216
2217 trace_ide_cmd_write(addr, val, bus);
2218
2219
2220 if (!(bus->cmd & IDE_CMD_RESET) &&
2221 (val & IDE_CMD_RESET)) {
2222
2223 for(i = 0;i < 2; i++) {
2224 s = &bus->ifs[i];
2225 s->status = BUSY_STAT | SEEK_STAT;
2226 s->error = 0x01;
2227 }
2228 } else if ((bus->cmd & IDE_CMD_RESET) &&
2229 !(val & IDE_CMD_RESET)) {
2230
2231 for(i = 0;i < 2; i++) {
2232 s = &bus->ifs[i];
2233 if (s->drive_kind == IDE_CD)
2234 s->status = 0x00;
2235 else
2236 s->status = READY_STAT | SEEK_STAT;
2237 ide_set_signature(s);
2238 }
2239 }
2240
2241 bus->cmd = val;
2242}
2243
2244
2245
2246
2247
2248static bool ide_is_pio_out(IDEState *s)
2249{
2250 if (s->end_transfer_func == ide_sector_write ||
2251 s->end_transfer_func == ide_atapi_cmd) {
2252 return false;
2253 } else if (s->end_transfer_func == ide_sector_read ||
2254 s->end_transfer_func == ide_transfer_stop ||
2255 s->end_transfer_func == ide_atapi_cmd_reply_end ||
2256 s->end_transfer_func == ide_dummy_transfer_stop) {
2257 return true;
2258 }
2259
2260 abort();
2261}
2262
2263void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
2264{
2265 IDEBus *bus = opaque;
2266 IDEState *s = idebus_active_if(bus);
2267 uint8_t *p;
2268
2269 trace_ide_data_writew(addr, val, bus, s);
2270
2271
2272
2273 if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
2274 return;
2275 }
2276
2277 p = s->data_ptr;
2278 if (p + 2 > s->data_end) {
2279 return;
2280 }
2281
2282 *(uint16_t *)p = le16_to_cpu(val);
2283 p += 2;
2284 s->data_ptr = p;
2285 if (p >= s->data_end) {
2286 s->status &= ~DRQ_STAT;
2287 s->end_transfer_func(s);
2288 }
2289}
2290
2291uint32_t ide_data_readw(void *opaque, uint32_t addr)
2292{
2293 IDEBus *bus = opaque;
2294 IDEState *s = idebus_active_if(bus);
2295 uint8_t *p;
2296 int ret;
2297
2298
2299
2300 if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
2301 return 0;
2302 }
2303
2304 p = s->data_ptr;
2305 if (p + 2 > s->data_end) {
2306 return 0;
2307 }
2308
2309 ret = cpu_to_le16(*(uint16_t *)p);
2310 p += 2;
2311 s->data_ptr = p;
2312 if (p >= s->data_end) {
2313 s->status &= ~DRQ_STAT;
2314 s->end_transfer_func(s);
2315 }
2316
2317 trace_ide_data_readw(addr, ret, bus, s);
2318 return ret;
2319}
2320
2321void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
2322{
2323 IDEBus *bus = opaque;
2324 IDEState *s = idebus_active_if(bus);
2325 uint8_t *p;
2326
2327 trace_ide_data_writel(addr, val, bus, s);
2328
2329
2330
2331 if (!(s->status & DRQ_STAT) || ide_is_pio_out(s)) {
2332 return;
2333 }
2334
2335 p = s->data_ptr;
2336 if (p + 4 > s->data_end) {
2337 return;
2338 }
2339
2340 *(uint32_t *)p = le32_to_cpu(val);
2341 p += 4;
2342 s->data_ptr = p;
2343 if (p >= s->data_end) {
2344 s->status &= ~DRQ_STAT;
2345 s->end_transfer_func(s);
2346 }
2347}
2348
2349uint32_t ide_data_readl(void *opaque, uint32_t addr)
2350{
2351 IDEBus *bus = opaque;
2352 IDEState *s = idebus_active_if(bus);
2353 uint8_t *p;
2354 int ret;
2355
2356
2357
2358 if (!(s->status & DRQ_STAT) || !ide_is_pio_out(s)) {
2359 ret = 0;
2360 goto out;
2361 }
2362
2363 p = s->data_ptr;
2364 if (p + 4 > s->data_end) {
2365 return 0;
2366 }
2367
2368 ret = cpu_to_le32(*(uint32_t *)p);
2369 p += 4;
2370 s->data_ptr = p;
2371 if (p >= s->data_end) {
2372 s->status &= ~DRQ_STAT;
2373 s->end_transfer_func(s);
2374 }
2375
2376out:
2377 trace_ide_data_readl(addr, ret, bus, s);
2378 return ret;
2379}
2380
2381static void ide_dummy_transfer_stop(IDEState *s)
2382{
2383 s->data_ptr = s->io_buffer;
2384 s->data_end = s->io_buffer;
2385 s->io_buffer[0] = 0xff;
2386 s->io_buffer[1] = 0xff;
2387 s->io_buffer[2] = 0xff;
2388 s->io_buffer[3] = 0xff;
2389}
2390
2391void ide_bus_reset(IDEBus *bus)
2392{
2393 bus->unit = 0;
2394 bus->cmd = 0;
2395 ide_reset(&bus->ifs[0]);
2396 ide_reset(&bus->ifs[1]);
2397 ide_clear_hob(bus);
2398
2399
2400 if (bus->dma->aiocb) {
2401 trace_ide_bus_reset_aio();
2402 blk_aio_cancel(bus->dma->aiocb);
2403 bus->dma->aiocb = NULL;
2404 }
2405
2406
2407 if (bus->dma->ops->reset) {
2408 bus->dma->ops->reset(bus->dma);
2409 }
2410}
2411
2412static bool ide_cd_is_tray_open(void *opaque)
2413{
2414 return ((IDEState *)opaque)->tray_open;
2415}
2416
2417static bool ide_cd_is_medium_locked(void *opaque)
2418{
2419 return ((IDEState *)opaque)->tray_locked;
2420}
2421
2422static void ide_resize_cb(void *opaque)
2423{
2424 IDEState *s = opaque;
2425 uint64_t nb_sectors;
2426
2427 if (!s->identify_set) {
2428 return;
2429 }
2430
2431 blk_get_geometry(s->blk, &nb_sectors);
2432 s->nb_sectors = nb_sectors;
2433
2434
2435 if (s->drive_kind == IDE_CFATA) {
2436 ide_cfata_identify_size(s);
2437 } else {
2438
2439 assert(s->drive_kind != IDE_CD);
2440 ide_identify_size(s);
2441 }
2442}
2443
2444static const BlockDevOps ide_cd_block_ops = {
2445 .change_media_cb = ide_cd_change_cb,
2446 .eject_request_cb = ide_cd_eject_request_cb,
2447 .is_tray_open = ide_cd_is_tray_open,
2448 .is_medium_locked = ide_cd_is_medium_locked,
2449};
2450
2451static const BlockDevOps ide_hd_block_ops = {
2452 .resize_cb = ide_resize_cb,
2453};
2454
2455int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
2456 const char *version, const char *serial, const char *model,
2457 uint64_t wwn,
2458 uint32_t cylinders, uint32_t heads, uint32_t secs,
2459 int chs_trans, Error **errp)
2460{
2461 uint64_t nb_sectors;
2462
2463 s->blk = blk;
2464 s->drive_kind = kind;
2465
2466 blk_get_geometry(blk, &nb_sectors);
2467 s->cylinders = cylinders;
2468 s->heads = heads;
2469 s->sectors = secs;
2470 s->chs_trans = chs_trans;
2471 s->nb_sectors = nb_sectors;
2472 s->wwn = wwn;
2473
2474
2475 s->smart_enabled = 1;
2476 s->smart_autosave = 1;
2477 s->smart_errors = 0;
2478 s->smart_selftest_count = 0;
2479 if (kind == IDE_CD) {
2480 blk_set_dev_ops(blk, &ide_cd_block_ops, s);
2481 blk_set_guest_block_size(blk, 2048);
2482 } else {
2483 if (!blk_is_inserted(s->blk)) {
2484 error_setg(errp, "Device needs media, but drive is empty");
2485 return -1;
2486 }
2487 if (blk_is_read_only(blk)) {
2488 error_setg(errp, "Can't use a read-only drive");
2489 return -1;
2490 }
2491 blk_set_dev_ops(blk, &ide_hd_block_ops, s);
2492 }
2493 if (serial) {
2494 pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial);
2495 } else {
2496 snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
2497 "QM%05d", s->drive_serial);
2498 }
2499 if (model) {
2500 pstrcpy(s->drive_model_str, sizeof(s->drive_model_str), model);
2501 } else {
2502 switch (kind) {
2503 case IDE_CD:
2504 strcpy(s->drive_model_str, "QEMU DVD-ROM");
2505 break;
2506 case IDE_CFATA:
2507 strcpy(s->drive_model_str, "QEMU MICRODRIVE");
2508 break;
2509 default:
2510 strcpy(s->drive_model_str, "QEMU HARDDISK");
2511 break;
2512 }
2513 }
2514
2515 if (version) {
2516 pstrcpy(s->version, sizeof(s->version), version);
2517 } else {
2518 pstrcpy(s->version, sizeof(s->version), qemu_hw_version());
2519 }
2520
2521 ide_reset(s);
2522 blk_iostatus_enable(blk);
2523 return 0;
2524}
2525
2526static void ide_init1(IDEBus *bus, int unit)
2527{
2528 static int drive_serial = 1;
2529 IDEState *s = &bus->ifs[unit];
2530
2531 s->bus = bus;
2532 s->unit = unit;
2533 s->drive_serial = drive_serial++;
2534
2535 s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
2536 s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len);
2537 memset(s->io_buffer, 0, s->io_buffer_total_len);
2538
2539 s->smart_selftest_data = blk_blockalign(s->blk, 512);
2540 memset(s->smart_selftest_data, 0, 512);
2541
2542 s->sector_write_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
2543 ide_sector_write_timer_cb, s);
2544}
2545
2546static int ide_nop_int(IDEDMA *dma, int x)
2547{
2548 return 0;
2549}
2550
2551static void ide_nop(IDEDMA *dma)
2552{
2553}
2554
2555static int32_t ide_nop_int32(IDEDMA *dma, int32_t l)
2556{
2557 return 0;
2558}
2559
2560static const IDEDMAOps ide_dma_nop_ops = {
2561 .prepare_buf = ide_nop_int32,
2562 .restart_dma = ide_nop,
2563 .rw_buf = ide_nop_int,
2564};
2565
2566static void ide_restart_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
2567{
2568 s->unit = s->bus->retry_unit;
2569 ide_set_sector(s, s->bus->retry_sector_num);
2570 s->nsector = s->bus->retry_nsector;
2571 s->bus->dma->ops->restart_dma(s->bus->dma);
2572 s->io_buffer_size = 0;
2573 s->dma_cmd = dma_cmd;
2574 ide_start_dma(s, ide_dma_cb);
2575}
2576
2577static void ide_restart_bh(void *opaque)
2578{
2579 IDEBus *bus = opaque;
2580 IDEState *s;
2581 bool is_read;
2582 int error_status;
2583
2584 qemu_bh_delete(bus->bh);
2585 bus->bh = NULL;
2586
2587 error_status = bus->error_status;
2588 if (bus->error_status == 0) {
2589 return;
2590 }
2591
2592 s = idebus_active_if(bus);
2593 is_read = (bus->error_status & IDE_RETRY_READ) != 0;
2594
2595
2596
2597
2598 bus->error_status = 0;
2599
2600
2601 if (error_status & IDE_RETRY_HBA) {
2602 if (s->bus->dma->ops->restart) {
2603 s->bus->dma->ops->restart(s->bus->dma);
2604 }
2605 } else if (IS_IDE_RETRY_DMA(error_status)) {
2606 if (error_status & IDE_RETRY_TRIM) {
2607 ide_restart_dma(s, IDE_DMA_TRIM);
2608 } else {
2609 ide_restart_dma(s, is_read ? IDE_DMA_READ : IDE_DMA_WRITE);
2610 }
2611 } else if (IS_IDE_RETRY_PIO(error_status)) {
2612 if (is_read) {
2613 ide_sector_read(s);
2614 } else {
2615 ide_sector_write(s);
2616 }
2617 } else if (error_status & IDE_RETRY_FLUSH) {
2618 ide_flush_cache(s);
2619 } else if (IS_IDE_RETRY_ATAPI(error_status)) {
2620 assert(s->end_transfer_func == ide_atapi_cmd);
2621 ide_atapi_dma_restart(s);
2622 } else {
2623 abort();
2624 }
2625}
2626
2627static void ide_restart_cb(void *opaque, int running, RunState state)
2628{
2629 IDEBus *bus = opaque;
2630
2631 if (!running)
2632 return;
2633
2634 if (!bus->bh) {
2635 bus->bh = qemu_bh_new(ide_restart_bh, bus);
2636 qemu_bh_schedule(bus->bh);
2637 }
2638}
2639
2640void ide_register_restart_cb(IDEBus *bus)
2641{
2642 if (bus->dma->ops->restart_dma) {
2643 bus->vmstate = qemu_add_vm_change_state_handler(ide_restart_cb, bus);
2644 }
2645}
2646
2647static IDEDMA ide_dma_nop = {
2648 .ops = &ide_dma_nop_ops,
2649 .aiocb = NULL,
2650};
2651
2652void ide_init2(IDEBus *bus, qemu_irq irq)
2653{
2654 int i;
2655
2656 for(i = 0; i < 2; i++) {
2657 ide_init1(bus, i);
2658 ide_reset(&bus->ifs[i]);
2659 }
2660 bus->irq = irq;
2661 bus->dma = &ide_dma_nop;
2662}
2663
2664void ide_exit(IDEState *s)
2665{
2666 timer_del(s->sector_write_timer);
2667 timer_free(s->sector_write_timer);
2668 qemu_vfree(s->smart_selftest_data);
2669 qemu_vfree(s->io_buffer);
2670}
2671
2672static bool is_identify_set(void *opaque, int version_id)
2673{
2674 IDEState *s = opaque;
2675
2676 return s->identify_set != 0;
2677}
2678
2679static EndTransferFunc* transfer_end_table[] = {
2680 ide_sector_read,
2681 ide_sector_write,
2682 ide_transfer_stop,
2683 ide_atapi_cmd_reply_end,
2684 ide_atapi_cmd,
2685 ide_dummy_transfer_stop,
2686};
2687
2688static int transfer_end_table_idx(EndTransferFunc *fn)
2689{
2690 int i;
2691
2692 for (i = 0; i < ARRAY_SIZE(transfer_end_table); i++)
2693 if (transfer_end_table[i] == fn)
2694 return i;
2695
2696 return -1;
2697}
2698
2699static int ide_drive_post_load(void *opaque, int version_id)
2700{
2701 IDEState *s = opaque;
2702
2703 if (s->blk && s->identify_set) {
2704 blk_set_enable_write_cache(s->blk, !!(s->identify_data[85] & (1 << 5)));
2705 }
2706 return 0;
2707}
2708
2709static int ide_drive_pio_post_load(void *opaque, int version_id)
2710{
2711 IDEState *s = opaque;
2712
2713 if (s->end_transfer_fn_idx >= ARRAY_SIZE(transfer_end_table)) {
2714 return -EINVAL;
2715 }
2716 s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx];
2717 s->data_ptr = s->io_buffer + s->cur_io_buffer_offset;
2718 s->data_end = s->data_ptr + s->cur_io_buffer_len;
2719 s->atapi_dma = s->feature & 1;
2720
2721 return 0;
2722}
2723
2724static int ide_drive_pio_pre_save(void *opaque)
2725{
2726 IDEState *s = opaque;
2727 int idx;
2728
2729 s->cur_io_buffer_offset = s->data_ptr - s->io_buffer;
2730 s->cur_io_buffer_len = s->data_end - s->data_ptr;
2731
2732 idx = transfer_end_table_idx(s->end_transfer_func);
2733 if (idx == -1) {
2734 fprintf(stderr, "%s: invalid end_transfer_func for DRQ_STAT\n",
2735 __func__);
2736 s->end_transfer_fn_idx = 2;
2737 } else {
2738 s->end_transfer_fn_idx = idx;
2739 }
2740
2741 return 0;
2742}
2743
2744static bool ide_drive_pio_state_needed(void *opaque)
2745{
2746 IDEState *s = opaque;
2747
2748 return ((s->status & DRQ_STAT) != 0)
2749 || (s->bus->error_status & IDE_RETRY_PIO);
2750}
2751
2752static bool ide_tray_state_needed(void *opaque)
2753{
2754 IDEState *s = opaque;
2755
2756 return s->tray_open || s->tray_locked;
2757}
2758
2759static bool ide_atapi_gesn_needed(void *opaque)
2760{
2761 IDEState *s = opaque;
2762
2763 return s->events.new_media || s->events.eject_request;
2764}
2765
2766static bool ide_error_needed(void *opaque)
2767{
2768 IDEBus *bus = opaque;
2769
2770 return (bus->error_status != 0);
2771}
2772
2773
2774static const VMStateDescription vmstate_ide_atapi_gesn_state = {
2775 .name ="ide_drive/atapi/gesn_state",
2776 .version_id = 1,
2777 .minimum_version_id = 1,
2778 .needed = ide_atapi_gesn_needed,
2779 .fields = (VMStateField[]) {
2780 VMSTATE_BOOL(events.new_media, IDEState),
2781 VMSTATE_BOOL(events.eject_request, IDEState),
2782 VMSTATE_END_OF_LIST()
2783 }
2784};
2785
2786static const VMStateDescription vmstate_ide_tray_state = {
2787 .name = "ide_drive/tray_state",
2788 .version_id = 1,
2789 .minimum_version_id = 1,
2790 .needed = ide_tray_state_needed,
2791 .fields = (VMStateField[]) {
2792 VMSTATE_BOOL(tray_open, IDEState),
2793 VMSTATE_BOOL(tray_locked, IDEState),
2794 VMSTATE_END_OF_LIST()
2795 }
2796};
2797
2798static const VMStateDescription vmstate_ide_drive_pio_state = {
2799 .name = "ide_drive/pio_state",
2800 .version_id = 1,
2801 .minimum_version_id = 1,
2802 .pre_save = ide_drive_pio_pre_save,
2803 .post_load = ide_drive_pio_post_load,
2804 .needed = ide_drive_pio_state_needed,
2805 .fields = (VMStateField[]) {
2806 VMSTATE_INT32(req_nb_sectors, IDEState),
2807 VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
2808 vmstate_info_uint8, uint8_t),
2809 VMSTATE_INT32(cur_io_buffer_offset, IDEState),
2810 VMSTATE_INT32(cur_io_buffer_len, IDEState),
2811 VMSTATE_UINT8(end_transfer_fn_idx, IDEState),
2812 VMSTATE_INT32(elementary_transfer_size, IDEState),
2813 VMSTATE_INT32(packet_transfer_size, IDEState),
2814 VMSTATE_END_OF_LIST()
2815 }
2816};
2817
2818const VMStateDescription vmstate_ide_drive = {
2819 .name = "ide_drive",
2820 .version_id = 3,
2821 .minimum_version_id = 0,
2822 .post_load = ide_drive_post_load,
2823 .fields = (VMStateField[]) {
2824 VMSTATE_INT32(mult_sectors, IDEState),
2825 VMSTATE_INT32(identify_set, IDEState),
2826 VMSTATE_BUFFER_TEST(identify_data, IDEState, is_identify_set),
2827 VMSTATE_UINT8(feature, IDEState),
2828 VMSTATE_UINT8(error, IDEState),
2829 VMSTATE_UINT32(nsector, IDEState),
2830 VMSTATE_UINT8(sector, IDEState),
2831 VMSTATE_UINT8(lcyl, IDEState),
2832 VMSTATE_UINT8(hcyl, IDEState),
2833 VMSTATE_UINT8(hob_feature, IDEState),
2834 VMSTATE_UINT8(hob_sector, IDEState),
2835 VMSTATE_UINT8(hob_nsector, IDEState),
2836 VMSTATE_UINT8(hob_lcyl, IDEState),
2837 VMSTATE_UINT8(hob_hcyl, IDEState),
2838 VMSTATE_UINT8(select, IDEState),
2839 VMSTATE_UINT8(status, IDEState),
2840 VMSTATE_UINT8(lba48, IDEState),
2841 VMSTATE_UINT8(sense_key, IDEState),
2842 VMSTATE_UINT8(asc, IDEState),
2843 VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
2844 VMSTATE_END_OF_LIST()
2845 },
2846 .subsections = (const VMStateDescription*[]) {
2847 &vmstate_ide_drive_pio_state,
2848 &vmstate_ide_tray_state,
2849 &vmstate_ide_atapi_gesn_state,
2850 NULL
2851 }
2852};
2853
2854static const VMStateDescription vmstate_ide_error_status = {
2855 .name ="ide_bus/error",
2856 .version_id = 2,
2857 .minimum_version_id = 1,
2858 .needed = ide_error_needed,
2859 .fields = (VMStateField[]) {
2860 VMSTATE_INT32(error_status, IDEBus),
2861 VMSTATE_INT64_V(retry_sector_num, IDEBus, 2),
2862 VMSTATE_UINT32_V(retry_nsector, IDEBus, 2),
2863 VMSTATE_UINT8_V(retry_unit, IDEBus, 2),
2864 VMSTATE_END_OF_LIST()
2865 }
2866};
2867
2868const VMStateDescription vmstate_ide_bus = {
2869 .name = "ide_bus",
2870 .version_id = 1,
2871 .minimum_version_id = 1,
2872 .fields = (VMStateField[]) {
2873 VMSTATE_UINT8(cmd, IDEBus),
2874 VMSTATE_UINT8(unit, IDEBus),
2875 VMSTATE_END_OF_LIST()
2876 },
2877 .subsections = (const VMStateDescription*[]) {
2878 &vmstate_ide_error_status,
2879 NULL
2880 }
2881};
2882
2883void ide_drive_get(DriveInfo **hd, int n)
2884{
2885 int i;
2886
2887 for (i = 0; i < n; i++) {
2888 hd[i] = drive_get_by_index(IF_IDE, i);
2889 }
2890}
2891