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,6 +296,8 @@ typedef struct IDEState { | ||
| 296 | int cylinders, heads, sectors; | 296 | int cylinders, heads, sectors; |
| 297 | int64_t nb_sectors; | 297 | int64_t nb_sectors; |
| 298 | int mult_sectors; | 298 | int mult_sectors; |
| 299 | + int identify_set; | ||
| 300 | + uint16_t identify_data[256]; | ||
| 299 | SetIRQFunc *set_irq; | 301 | SetIRQFunc *set_irq; |
| 300 | void *irq_opaque; | 302 | void *irq_opaque; |
| 301 | int irq; | 303 | int irq; |
| @@ -414,6 +416,11 @@ static void ide_identify(IDEState *s) | @@ -414,6 +416,11 @@ static void ide_identify(IDEState *s) | ||
| 414 | unsigned int oldsize; | 416 | unsigned int oldsize; |
| 415 | char buf[20]; | 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 | memset(s->io_buffer, 0, 512); | 424 | memset(s->io_buffer, 0, 512); |
| 418 | p = (uint16_t *)s->io_buffer; | 425 | p = (uint16_t *)s->io_buffer; |
| 419 | put_le16(p + 0, 0x0040); | 426 | put_le16(p + 0, 0x0040); |
| @@ -433,10 +440,10 @@ static void ide_identify(IDEState *s) | @@ -433,10 +440,10 @@ static void ide_identify(IDEState *s) | ||
| 433 | put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); | 440 | put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); |
| 434 | #endif | 441 | #endif |
| 435 | put_le16(p + 48, 1); /* dword I/O */ | 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 | put_le16(p + 51, 0x200); /* PIO transfer cycle */ | 444 | put_le16(p + 51, 0x200); /* PIO transfer cycle */ |
| 438 | put_le16(p + 52, 0x200); /* DMA transfer cycle */ | 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 | put_le16(p + 54, s->cylinders); | 447 | put_le16(p + 54, s->cylinders); |
| 441 | put_le16(p + 55, s->heads); | 448 | put_le16(p + 55, s->heads); |
| 442 | put_le16(p + 56, s->sectors); | 449 | put_le16(p + 56, s->sectors); |
| @@ -447,15 +454,24 @@ static void ide_identify(IDEState *s) | @@ -447,15 +454,24 @@ static void ide_identify(IDEState *s) | ||
| 447 | put_le16(p + 59, 0x100 | s->mult_sectors); | 454 | put_le16(p + 59, 0x100 | s->mult_sectors); |
| 448 | put_le16(p + 60, s->nb_sectors); | 455 | put_le16(p + 60, s->nb_sectors); |
| 449 | put_le16(p + 61, s->nb_sectors >> 16); | 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 | put_le16(p + 82, (1 << 14)); | 464 | put_le16(p + 82, (1 << 14)); |
| 452 | put_le16(p + 83, (1 << 14)); | 465 | put_le16(p + 83, (1 << 14)); |
| 453 | put_le16(p + 84, (1 << 14)); | 466 | put_le16(p + 84, (1 << 14)); |
| 454 | put_le16(p + 85, (1 << 14)); | 467 | put_le16(p + 85, (1 << 14)); |
| 455 | put_le16(p + 86, 0); | 468 | put_le16(p + 86, 0); |
| 456 | put_le16(p + 87, (1 << 14)); | 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 | static void ide_atapi_identify(IDEState *s) | 477 | static void ide_atapi_identify(IDEState *s) |
| @@ -463,6 +479,11 @@ static void ide_atapi_identify(IDEState *s) | @@ -463,6 +479,11 @@ static void ide_atapi_identify(IDEState *s) | ||
| 463 | uint16_t *p; | 479 | uint16_t *p; |
| 464 | char buf[20]; | 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 | memset(s->io_buffer, 0, 512); | 487 | memset(s->io_buffer, 0, 512); |
| 467 | p = (uint16_t *)s->io_buffer; | 488 | p = (uint16_t *)s->io_buffer; |
| 468 | /* Removable CDROM, 50us response, 12 byte packets */ | 489 | /* Removable CDROM, 50us response, 12 byte packets */ |
| @@ -483,11 +504,14 @@ static void ide_atapi_identify(IDEState *s) | @@ -483,11 +504,14 @@ static void ide_atapi_identify(IDEState *s) | ||
| 483 | put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ | 504 | put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ |
| 484 | put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ | 505 | put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ |
| 485 | put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ | 506 | put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ |
| 486 | - | 507 | + |
| 487 | put_le16(p + 71, 30); /* in ns */ | 508 | put_le16(p + 71, 30); /* in ns */ |
| 488 | put_le16(p + 72, 30); /* in ns */ | 509 | put_le16(p + 72, 30); /* in ns */ |
| 489 | 510 | ||
| 490 | put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ | 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 | static void ide_set_signature(IDEState *s) | 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,13 +1625,36 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 1601 | /* XXX: valid for CDROM ? */ | 1625 | /* XXX: valid for CDROM ? */ |
| 1602 | switch(s->feature) { | 1626 | switch(s->feature) { |
| 1603 | case 0x02: /* write cache enable */ | 1627 | case 0x02: /* write cache enable */ |
| 1604 | - case 0x03: /* set transfer mode */ | ||
| 1605 | case 0x82: /* write cache disable */ | 1628 | case 0x82: /* write cache disable */ |
| 1606 | case 0xaa: /* read look-ahead enable */ | 1629 | case 0xaa: /* read look-ahead enable */ |
| 1607 | case 0x55: /* read look-ahead disable */ | 1630 | case 0x55: /* read look-ahead disable */ |
| 1608 | s->status = READY_STAT | SEEK_STAT; | 1631 | s->status = READY_STAT | SEEK_STAT; |
| 1609 | ide_set_irq(s); | 1632 | ide_set_irq(s); |
| 1610 | break; | 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 | default: | 1658 | default: |
| 1612 | goto abort_cmd; | 1659 | goto abort_cmd; |
| 1613 | } | 1660 | } |