Commit 944588029809b29c800f081d812153f559ec523a
1 parent
8147cfca
correct DMA and transfer mode reporting (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1736 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
54 additions
and
7 deletions
hw/ide.c
... | ... | @@ -296,6 +296,8 @@ typedef struct IDEState { |
296 | 296 | int cylinders, heads, sectors; |
297 | 297 | int64_t nb_sectors; |
298 | 298 | int mult_sectors; |
299 | + int identify_set; | |
300 | + uint16_t identify_data[256]; | |
299 | 301 | SetIRQFunc *set_irq; |
300 | 302 | void *irq_opaque; |
301 | 303 | int irq; |
... | ... | @@ -414,6 +416,11 @@ static void ide_identify(IDEState *s) |
414 | 416 | unsigned int oldsize; |
415 | 417 | char buf[20]; |
416 | 418 | |
419 | + if (s->identify_set) { | |
420 | + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); | |
421 | + return; | |
422 | + } | |
423 | + | |
417 | 424 | memset(s->io_buffer, 0, 512); |
418 | 425 | p = (uint16_t *)s->io_buffer; |
419 | 426 | put_le16(p + 0, 0x0040); |
... | ... | @@ -433,10 +440,10 @@ static void ide_identify(IDEState *s) |
433 | 440 | put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); |
434 | 441 | #endif |
435 | 442 | put_le16(p + 48, 1); /* dword I/O */ |
436 | - put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */ | |
443 | + put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */ | |
437 | 444 | put_le16(p + 51, 0x200); /* PIO transfer cycle */ |
438 | 445 | put_le16(p + 52, 0x200); /* DMA transfer cycle */ |
439 | - put_le16(p + 53, 1 | 1 << 2); /* words 54-58,88 are valid */ | |
446 | + put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */ | |
440 | 447 | put_le16(p + 54, s->cylinders); |
441 | 448 | put_le16(p + 55, s->heads); |
442 | 449 | put_le16(p + 56, s->sectors); |
... | ... | @@ -447,15 +454,24 @@ static void ide_identify(IDEState *s) |
447 | 454 | put_le16(p + 59, 0x100 | s->mult_sectors); |
448 | 455 | put_le16(p + 60, s->nb_sectors); |
449 | 456 | put_le16(p + 61, s->nb_sectors >> 16); |
450 | - put_le16(p + 80, (1 << 1) | (1 << 2)); | |
457 | + put_le16(p + 63, 0x07); /* mdma0-2 supported */ | |
458 | + put_le16(p + 65, 120); | |
459 | + put_le16(p + 66, 120); | |
460 | + put_le16(p + 67, 120); | |
461 | + put_le16(p + 68, 120); | |
462 | + put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */ | |
463 | + put_le16(p + 81, 0x16); /* conforms to ata5 */ | |
451 | 464 | put_le16(p + 82, (1 << 14)); |
452 | 465 | put_le16(p + 83, (1 << 14)); |
453 | 466 | put_le16(p + 84, (1 << 14)); |
454 | 467 | put_le16(p + 85, (1 << 14)); |
455 | 468 | put_le16(p + 86, 0); |
456 | 469 | put_le16(p + 87, (1 << 14)); |
457 | - put_le16(p + 88, 0x1f | (1 << 13)); | |
458 | - put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000); | |
470 | + put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ | |
471 | + put_le16(p + 93, 1 | (1 << 14) | 0x2000); | |
472 | + | |
473 | + memcpy(s->identify_data, p, sizeof(s->identify_data)); | |
474 | + s->identify_set = 1; | |
459 | 475 | } |
460 | 476 | |
461 | 477 | static void ide_atapi_identify(IDEState *s) |
... | ... | @@ -463,6 +479,11 @@ static void ide_atapi_identify(IDEState *s) |
463 | 479 | uint16_t *p; |
464 | 480 | char buf[20]; |
465 | 481 | |
482 | + if (s->identify_set) { | |
483 | + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); | |
484 | + return; | |
485 | + } | |
486 | + | |
466 | 487 | memset(s->io_buffer, 0, 512); |
467 | 488 | p = (uint16_t *)s->io_buffer; |
468 | 489 | /* Removable CDROM, 50us response, 12 byte packets */ |
... | ... | @@ -483,11 +504,14 @@ static void ide_atapi_identify(IDEState *s) |
483 | 504 | put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ |
484 | 505 | put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ |
485 | 506 | put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ |
486 | - | |
507 | + | |
487 | 508 | put_le16(p + 71, 30); /* in ns */ |
488 | 509 | put_le16(p + 72, 30); /* in ns */ |
489 | 510 | |
490 | 511 | put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ |
512 | + | |
513 | + memcpy(s->identify_data, p, sizeof(s->identify_data)); | |
514 | + s->identify_set = 1; | |
491 | 515 | } |
492 | 516 | |
493 | 517 | static void ide_set_signature(IDEState *s) |
... | ... | @@ -1601,13 +1625,36 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
1601 | 1625 | /* XXX: valid for CDROM ? */ |
1602 | 1626 | switch(s->feature) { |
1603 | 1627 | case 0x02: /* write cache enable */ |
1604 | - case 0x03: /* set transfer mode */ | |
1605 | 1628 | case 0x82: /* write cache disable */ |
1606 | 1629 | case 0xaa: /* read look-ahead enable */ |
1607 | 1630 | case 0x55: /* read look-ahead disable */ |
1608 | 1631 | s->status = READY_STAT | SEEK_STAT; |
1609 | 1632 | ide_set_irq(s); |
1610 | 1633 | break; |
1634 | + case 0x03: { /* set transfer mode */ | |
1635 | + uint8_t val = s->nsector & 0x07; | |
1636 | + | |
1637 | + switch (s->nsector >> 3) { | |
1638 | + case 0x00: /* pio default */ | |
1639 | + case 0x01: /* pio mode */ | |
1640 | + put_le16(s->identify_data + 63,0x07); | |
1641 | + put_le16(s->identify_data + 88,0x3f); | |
1642 | + break; | |
1643 | + case 0x04: /* mdma mode */ | |
1644 | + put_le16(s->identify_data + 63,0x07 | (1 << (val + 8))); | |
1645 | + put_le16(s->identify_data + 88,0x3f); | |
1646 | + break; | |
1647 | + case 0x08: /* udma mode */ | |
1648 | + put_le16(s->identify_data + 63,0x07); | |
1649 | + put_le16(s->identify_data + 88,0x3f | (1 << (val + 8))); | |
1650 | + break; | |
1651 | + default: | |
1652 | + goto abort_cmd; | |
1653 | + } | |
1654 | + s->status = READY_STAT | SEEK_STAT; | |
1655 | + ide_set_irq(s); | |
1656 | + break; | |
1657 | + } | |
1611 | 1658 | default: |
1612 | 1659 | goto abort_cmd; |
1613 | 1660 | } | ... | ... |