Commit c2ff060fd4c7389de2016442e3327538a66696bd
1 parent
467d409f
LBA48 support (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1853 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
137 additions
and
20 deletions
hw/ide.c
| @@ -307,14 +307,24 @@ typedef struct IDEState { | @@ -307,14 +307,24 @@ typedef struct IDEState { | ||
| 307 | /* ide regs */ | 307 | /* ide regs */ |
| 308 | uint8_t feature; | 308 | uint8_t feature; |
| 309 | uint8_t error; | 309 | uint8_t error; |
| 310 | - uint16_t nsector; /* 0 is 256 to ease computations */ | 310 | + uint32_t nsector; |
| 311 | uint8_t sector; | 311 | uint8_t sector; |
| 312 | uint8_t lcyl; | 312 | uint8_t lcyl; |
| 313 | uint8_t hcyl; | 313 | uint8_t hcyl; |
| 314 | + /* other part of tf for lba48 support */ | ||
| 315 | + uint8_t hob_feature; | ||
| 316 | + uint8_t hob_nsector; | ||
| 317 | + uint8_t hob_sector; | ||
| 318 | + uint8_t hob_lcyl; | ||
| 319 | + uint8_t hob_hcyl; | ||
| 320 | + | ||
| 314 | uint8_t select; | 321 | uint8_t select; |
| 315 | uint8_t status; | 322 | uint8_t status; |
| 323 | + | ||
| 316 | /* 0x3f6 command, only meaningful for drive 0 */ | 324 | /* 0x3f6 command, only meaningful for drive 0 */ |
| 317 | uint8_t cmd; | 325 | uint8_t cmd; |
| 326 | + /* set for lba48 access */ | ||
| 327 | + uint8_t lba48; | ||
| 318 | /* depends on bit 4 in select, only meaningful for drive 0 */ | 328 | /* depends on bit 4 in select, only meaningful for drive 0 */ |
| 319 | struct IDEState *cur_drive; | 329 | struct IDEState *cur_drive; |
| 320 | BlockDriverState *bs; | 330 | BlockDriverState *bs; |
| @@ -463,13 +473,19 @@ static void ide_identify(IDEState *s) | @@ -463,13 +473,19 @@ static void ide_identify(IDEState *s) | ||
| 463 | put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */ | 473 | put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */ |
| 464 | put_le16(p + 81, 0x16); /* conforms to ata5 */ | 474 | put_le16(p + 81, 0x16); /* conforms to ata5 */ |
| 465 | put_le16(p + 82, (1 << 14)); | 475 | put_le16(p + 82, (1 << 14)); |
| 466 | - put_le16(p + 83, (1 << 14)); | 476 | + /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ |
| 477 | + put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); | ||
| 467 | put_le16(p + 84, (1 << 14)); | 478 | put_le16(p + 84, (1 << 14)); |
| 468 | put_le16(p + 85, (1 << 14)); | 479 | put_le16(p + 85, (1 << 14)); |
| 469 | - put_le16(p + 86, 0); | 480 | + /* 13=flush_cache_ext,12=flush_cache,10=lba48 */ |
| 481 | + put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10)); | ||
| 470 | put_le16(p + 87, (1 << 14)); | 482 | put_le16(p + 87, (1 << 14)); |
| 471 | put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ | 483 | put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ |
| 472 | put_le16(p + 93, 1 | (1 << 14) | 0x2000); | 484 | put_le16(p + 93, 1 | (1 << 14) | 0x2000); |
| 485 | + put_le16(p + 100, s->nb_sectors); | ||
| 486 | + put_le16(p + 101, s->nb_sectors >> 16); | ||
| 487 | + put_le16(p + 102, s->nb_sectors >> 32); | ||
| 488 | + put_le16(p + 103, s->nb_sectors >> 48); | ||
| 473 | 489 | ||
| 474 | memcpy(s->identify_data, p, sizeof(s->identify_data)); | 490 | memcpy(s->identify_data, p, sizeof(s->identify_data)); |
| 475 | s->identify_set = 1; | 491 | s->identify_set = 1; |
| @@ -573,12 +589,19 @@ static int64_t ide_get_sector(IDEState *s) | @@ -573,12 +589,19 @@ static int64_t ide_get_sector(IDEState *s) | ||
| 573 | int64_t sector_num; | 589 | int64_t sector_num; |
| 574 | if (s->select & 0x40) { | 590 | if (s->select & 0x40) { |
| 575 | /* lba */ | 591 | /* lba */ |
| 576 | - sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | | ||
| 577 | - (s->lcyl << 8) | s->sector; | 592 | + if (!s->lba48) { |
| 593 | + sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | | ||
| 594 | + (s->lcyl << 8) | s->sector; | ||
| 595 | + } else { | ||
| 596 | + sector_num = ((int64_t)s->hob_hcyl << 40) | | ||
| 597 | + ((int64_t) s->hob_lcyl << 32) | | ||
| 598 | + ((int64_t) s->hob_sector << 24) | | ||
| 599 | + ((int64_t) s->hcyl << 16) | | ||
| 600 | + ((int64_t) s->lcyl << 8) | s->sector; | ||
| 601 | + } | ||
| 578 | } else { | 602 | } else { |
| 579 | sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors + | 603 | sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors + |
| 580 | - (s->select & 0x0f) * s->sectors + | ||
| 581 | - (s->sector - 1); | 604 | + (s->select & 0x0f) * s->sectors + (s->sector - 1); |
| 582 | } | 605 | } |
| 583 | return sector_num; | 606 | return sector_num; |
| 584 | } | 607 | } |
| @@ -587,10 +610,19 @@ static void ide_set_sector(IDEState *s, int64_t sector_num) | @@ -587,10 +610,19 @@ static void ide_set_sector(IDEState *s, int64_t sector_num) | ||
| 587 | { | 610 | { |
| 588 | unsigned int cyl, r; | 611 | unsigned int cyl, r; |
| 589 | if (s->select & 0x40) { | 612 | if (s->select & 0x40) { |
| 590 | - s->select = (s->select & 0xf0) | (sector_num >> 24); | ||
| 591 | - s->hcyl = (sector_num >> 16); | ||
| 592 | - s->lcyl = (sector_num >> 8); | ||
| 593 | - s->sector = (sector_num); | 613 | + if (!s->lba48) { |
| 614 | + s->select = (s->select & 0xf0) | (sector_num >> 24); | ||
| 615 | + s->hcyl = (sector_num >> 16); | ||
| 616 | + s->lcyl = (sector_num >> 8); | ||
| 617 | + s->sector = (sector_num); | ||
| 618 | + } else { | ||
| 619 | + s->sector = sector_num; | ||
| 620 | + s->lcyl = sector_num >> 8; | ||
| 621 | + s->hcyl = sector_num >> 16; | ||
| 622 | + s->hob_sector = sector_num >> 24; | ||
| 623 | + s->hob_lcyl = sector_num >> 32; | ||
| 624 | + s->hob_hcyl = sector_num >> 40; | ||
| 625 | + } | ||
| 594 | } else { | 626 | } else { |
| 595 | cyl = sector_num / (s->heads * s->sectors); | 627 | cyl = sector_num / (s->heads * s->sectors); |
| 596 | r = sector_num % (s->heads * s->sectors); | 628 | r = sector_num % (s->heads * s->sectors); |
| @@ -1488,43 +1520,89 @@ static void cdrom_change_cb(void *opaque) | @@ -1488,43 +1520,89 @@ static void cdrom_change_cb(void *opaque) | ||
| 1488 | s->nb_sectors = nb_sectors; | 1520 | s->nb_sectors = nb_sectors; |
| 1489 | } | 1521 | } |
| 1490 | 1522 | ||
| 1523 | +static void ide_cmd_lba48_transform(IDEState *s, int lba48) | ||
| 1524 | +{ | ||
| 1525 | + s->lba48 = lba48; | ||
| 1526 | + | ||
| 1527 | + /* handle the 'magic' 0 nsector count conversion here. to avoid | ||
| 1528 | + * fiddling with the rest of the read logic, we just store the | ||
| 1529 | + * full sector count in ->nsector and ignore ->hob_nsector from now | ||
| 1530 | + */ | ||
| 1531 | + if (!s->lba48) { | ||
| 1532 | + if (!s->nsector) | ||
| 1533 | + s->nsector = 256; | ||
| 1534 | + } else { | ||
| 1535 | + if (!s->nsector && !s->hob_nsector) | ||
| 1536 | + s->nsector = 65536; | ||
| 1537 | + else { | ||
| 1538 | + int lo = s->nsector; | ||
| 1539 | + int hi = s->hob_nsector; | ||
| 1540 | + | ||
| 1541 | + s->nsector = (hi << 8) | lo; | ||
| 1542 | + } | ||
| 1543 | + } | ||
| 1544 | +} | ||
| 1545 | + | ||
| 1546 | +static void ide_clear_hob(IDEState *ide_if) | ||
| 1547 | +{ | ||
| 1548 | + /* any write clears HOB high bit of device control register */ | ||
| 1549 | + ide_if[0].select &= ~(1 << 7); | ||
| 1550 | + ide_if[1].select &= ~(1 << 7); | ||
| 1551 | +} | ||
| 1552 | + | ||
| 1491 | static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | 1553 | static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 1492 | { | 1554 | { |
| 1493 | IDEState *ide_if = opaque; | 1555 | IDEState *ide_if = opaque; |
| 1494 | IDEState *s; | 1556 | IDEState *s; |
| 1495 | int unit, n; | 1557 | int unit, n; |
| 1558 | + int lba48 = 0; | ||
| 1496 | 1559 | ||
| 1497 | #ifdef DEBUG_IDE | 1560 | #ifdef DEBUG_IDE |
| 1498 | printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); | 1561 | printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); |
| 1499 | #endif | 1562 | #endif |
| 1563 | + | ||
| 1500 | addr &= 7; | 1564 | addr &= 7; |
| 1501 | switch(addr) { | 1565 | switch(addr) { |
| 1502 | case 0: | 1566 | case 0: |
| 1503 | break; | 1567 | break; |
| 1504 | case 1: | 1568 | case 1: |
| 1569 | + ide_clear_hob(ide_if); | ||
| 1505 | /* NOTE: data is written to the two drives */ | 1570 | /* NOTE: data is written to the two drives */ |
| 1571 | + ide_if[0].hob_feature = ide_if[0].feature; | ||
| 1572 | + ide_if[1].hob_feature = ide_if[1].feature; | ||
| 1506 | ide_if[0].feature = val; | 1573 | ide_if[0].feature = val; |
| 1507 | ide_if[1].feature = val; | 1574 | ide_if[1].feature = val; |
| 1508 | break; | 1575 | break; |
| 1509 | case 2: | 1576 | case 2: |
| 1510 | - if (val == 0) | ||
| 1511 | - val = 256; | 1577 | + ide_clear_hob(ide_if); |
| 1578 | + ide_if[0].hob_nsector = ide_if[0].nsector; | ||
| 1579 | + ide_if[1].hob_nsector = ide_if[1].nsector; | ||
| 1512 | ide_if[0].nsector = val; | 1580 | ide_if[0].nsector = val; |
| 1513 | ide_if[1].nsector = val; | 1581 | ide_if[1].nsector = val; |
| 1514 | break; | 1582 | break; |
| 1515 | case 3: | 1583 | case 3: |
| 1584 | + ide_clear_hob(ide_if); | ||
| 1585 | + ide_if[0].hob_sector = ide_if[0].sector; | ||
| 1586 | + ide_if[1].hob_sector = ide_if[1].sector; | ||
| 1516 | ide_if[0].sector = val; | 1587 | ide_if[0].sector = val; |
| 1517 | ide_if[1].sector = val; | 1588 | ide_if[1].sector = val; |
| 1518 | break; | 1589 | break; |
| 1519 | case 4: | 1590 | case 4: |
| 1591 | + ide_clear_hob(ide_if); | ||
| 1592 | + ide_if[0].hob_lcyl = ide_if[0].lcyl; | ||
| 1593 | + ide_if[1].hob_lcyl = ide_if[1].lcyl; | ||
| 1520 | ide_if[0].lcyl = val; | 1594 | ide_if[0].lcyl = val; |
| 1521 | ide_if[1].lcyl = val; | 1595 | ide_if[1].lcyl = val; |
| 1522 | break; | 1596 | break; |
| 1523 | case 5: | 1597 | case 5: |
| 1598 | + ide_clear_hob(ide_if); | ||
| 1599 | + ide_if[0].hob_hcyl = ide_if[0].hcyl; | ||
| 1600 | + ide_if[1].hob_hcyl = ide_if[1].hcyl; | ||
| 1524 | ide_if[0].hcyl = val; | 1601 | ide_if[0].hcyl = val; |
| 1525 | ide_if[1].hcyl = val; | 1602 | ide_if[1].hcyl = val; |
| 1526 | break; | 1603 | break; |
| 1527 | case 6: | 1604 | case 6: |
| 1605 | + /* FIXME: HOB readback uses bit 7 */ | ||
| 1528 | ide_if[0].select = (val & ~0x10) | 0xa0; | 1606 | ide_if[0].select = (val & ~0x10) | 0xa0; |
| 1529 | ide_if[1].select = (val | 0x10) | 0xa0; | 1607 | ide_if[1].select = (val | 0x10) | 0xa0; |
| 1530 | /* select drive */ | 1608 | /* select drive */ |
| @@ -1542,6 +1620,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1542,6 +1620,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 1542 | /* ignore commands to non existant slave */ | 1620 | /* ignore commands to non existant slave */ |
| 1543 | if (s != ide_if && !s->bs) | 1621 | if (s != ide_if && !s->bs) |
| 1544 | break; | 1622 | break; |
| 1623 | + | ||
| 1545 | switch(val) { | 1624 | switch(val) { |
| 1546 | case WIN_IDENTIFY: | 1625 | case WIN_IDENTIFY: |
| 1547 | if (s->bs && !s->is_cdrom) { | 1626 | if (s->bs && !s->is_cdrom) { |
| @@ -1573,35 +1652,50 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1573,35 +1652,50 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 1573 | } | 1652 | } |
| 1574 | ide_set_irq(s); | 1653 | ide_set_irq(s); |
| 1575 | break; | 1654 | break; |
| 1655 | + case WIN_VERIFY_EXT: | ||
| 1656 | + lba48 = 1; | ||
| 1576 | case WIN_VERIFY: | 1657 | case WIN_VERIFY: |
| 1577 | case WIN_VERIFY_ONCE: | 1658 | case WIN_VERIFY_ONCE: |
| 1578 | /* do sector number check ? */ | 1659 | /* do sector number check ? */ |
| 1660 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1579 | s->status = READY_STAT; | 1661 | s->status = READY_STAT; |
| 1580 | ide_set_irq(s); | 1662 | ide_set_irq(s); |
| 1581 | break; | 1663 | break; |
| 1664 | + case WIN_READ_EXT: | ||
| 1665 | + lba48 = 1; | ||
| 1582 | case WIN_READ: | 1666 | case WIN_READ: |
| 1583 | case WIN_READ_ONCE: | 1667 | case WIN_READ_ONCE: |
| 1584 | if (!s->bs) | 1668 | if (!s->bs) |
| 1585 | goto abort_cmd; | 1669 | goto abort_cmd; |
| 1670 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1586 | s->req_nb_sectors = 1; | 1671 | s->req_nb_sectors = 1; |
| 1587 | ide_sector_read(s); | 1672 | ide_sector_read(s); |
| 1588 | break; | 1673 | break; |
| 1674 | + case WIN_WRITE_EXT: | ||
| 1675 | + lba48 = 1; | ||
| 1589 | case WIN_WRITE: | 1676 | case WIN_WRITE: |
| 1590 | case WIN_WRITE_ONCE: | 1677 | case WIN_WRITE_ONCE: |
| 1678 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1591 | s->error = 0; | 1679 | s->error = 0; |
| 1592 | s->status = SEEK_STAT | READY_STAT; | 1680 | s->status = SEEK_STAT | READY_STAT; |
| 1593 | s->req_nb_sectors = 1; | 1681 | s->req_nb_sectors = 1; |
| 1594 | ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); | 1682 | ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); |
| 1595 | break; | 1683 | break; |
| 1684 | + case WIN_MULTREAD_EXT: | ||
| 1685 | + lba48 = 1; | ||
| 1596 | case WIN_MULTREAD: | 1686 | case WIN_MULTREAD: |
| 1597 | if (!s->mult_sectors) | 1687 | if (!s->mult_sectors) |
| 1598 | goto abort_cmd; | 1688 | goto abort_cmd; |
| 1689 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1599 | s->req_nb_sectors = s->mult_sectors; | 1690 | s->req_nb_sectors = s->mult_sectors; |
| 1600 | ide_sector_read(s); | 1691 | ide_sector_read(s); |
| 1601 | break; | 1692 | break; |
| 1693 | + case WIN_MULTWRITE_EXT: | ||
| 1694 | + lba48 = 1; | ||
| 1602 | case WIN_MULTWRITE: | 1695 | case WIN_MULTWRITE: |
| 1603 | if (!s->mult_sectors) | 1696 | if (!s->mult_sectors) |
| 1604 | goto abort_cmd; | 1697 | goto abort_cmd; |
| 1698 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1605 | s->error = 0; | 1699 | s->error = 0; |
| 1606 | s->status = SEEK_STAT | READY_STAT; | 1700 | s->status = SEEK_STAT | READY_STAT; |
| 1607 | s->req_nb_sectors = s->mult_sectors; | 1701 | s->req_nb_sectors = s->mult_sectors; |
| @@ -1610,19 +1704,28 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1610,19 +1704,28 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 1610 | n = s->req_nb_sectors; | 1704 | n = s->req_nb_sectors; |
| 1611 | ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); | 1705 | ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); |
| 1612 | break; | 1706 | break; |
| 1707 | + case WIN_READDMA_EXT: | ||
| 1708 | + lba48 = 1; | ||
| 1613 | case WIN_READDMA: | 1709 | case WIN_READDMA: |
| 1614 | case WIN_READDMA_ONCE: | 1710 | case WIN_READDMA_ONCE: |
| 1615 | if (!s->bs) | 1711 | if (!s->bs) |
| 1616 | goto abort_cmd; | 1712 | goto abort_cmd; |
| 1713 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1617 | ide_sector_read_dma(s); | 1714 | ide_sector_read_dma(s); |
| 1618 | break; | 1715 | break; |
| 1716 | + case WIN_WRITEDMA_EXT: | ||
| 1717 | + lba48 = 1; | ||
| 1619 | case WIN_WRITEDMA: | 1718 | case WIN_WRITEDMA: |
| 1620 | case WIN_WRITEDMA_ONCE: | 1719 | case WIN_WRITEDMA_ONCE: |
| 1621 | if (!s->bs) | 1720 | if (!s->bs) |
| 1622 | goto abort_cmd; | 1721 | goto abort_cmd; |
| 1722 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1623 | ide_sector_write_dma(s); | 1723 | ide_sector_write_dma(s); |
| 1624 | break; | 1724 | break; |
| 1725 | + case WIN_READ_NATIVE_MAX_EXT: | ||
| 1726 | + lba48 = 1; | ||
| 1625 | case WIN_READ_NATIVE_MAX: | 1727 | case WIN_READ_NATIVE_MAX: |
| 1728 | + ide_cmd_lba48_transform(s, lba48); | ||
| 1626 | ide_set_sector(s, s->nb_sectors - 1); | 1729 | ide_set_sector(s, s->nb_sectors - 1); |
| 1627 | s->status = READY_STAT; | 1730 | s->status = READY_STAT; |
| 1628 | ide_set_irq(s); | 1731 | ide_set_irq(s); |
| @@ -1672,9 +1775,10 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1672,9 +1775,10 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 1672 | goto abort_cmd; | 1775 | goto abort_cmd; |
| 1673 | } | 1776 | } |
| 1674 | break; | 1777 | break; |
| 1778 | + case WIN_FLUSH_CACHE: | ||
| 1779 | + case WIN_FLUSH_CACHE_EXT: | ||
| 1675 | case WIN_STANDBYNOW1: | 1780 | case WIN_STANDBYNOW1: |
| 1676 | case WIN_IDLEIMMEDIATE: | 1781 | case WIN_IDLEIMMEDIATE: |
| 1677 | - case WIN_FLUSH_CACHE: | ||
| 1678 | s->status = READY_STAT; | 1782 | s->status = READY_STAT; |
| 1679 | ide_set_irq(s); | 1783 | ide_set_irq(s); |
| 1680 | break; | 1784 | break; |
| @@ -1726,9 +1830,12 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | @@ -1726,9 +1830,12 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | ||
| 1726 | IDEState *ide_if = opaque; | 1830 | IDEState *ide_if = opaque; |
| 1727 | IDEState *s = ide_if->cur_drive; | 1831 | IDEState *s = ide_if->cur_drive; |
| 1728 | uint32_t addr; | 1832 | uint32_t addr; |
| 1729 | - int ret; | 1833 | + int ret, hob; |
| 1730 | 1834 | ||
| 1731 | addr = addr1 & 7; | 1835 | addr = addr1 & 7; |
| 1836 | + /* FIXME: HOB readback uses bit 7, but it's always set right now */ | ||
| 1837 | + //hob = s->select & (1 << 7); | ||
| 1838 | + hob = 0; | ||
| 1732 | switch(addr) { | 1839 | switch(addr) { |
| 1733 | case 0: | 1840 | case 0: |
| 1734 | ret = 0xff; | 1841 | ret = 0xff; |
| @@ -1736,32 +1843,42 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | @@ -1736,32 +1843,42 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) | ||
| 1736 | case 1: | 1843 | case 1: |
| 1737 | if (!ide_if[0].bs && !ide_if[1].bs) | 1844 | if (!ide_if[0].bs && !ide_if[1].bs) |
| 1738 | ret = 0; | 1845 | ret = 0; |
| 1739 | - else | 1846 | + else if (!hob) |
| 1740 | ret = s->error; | 1847 | ret = s->error; |
| 1848 | + else | ||
| 1849 | + ret = s->hob_feature; | ||
| 1741 | break; | 1850 | break; |
| 1742 | case 2: | 1851 | case 2: |
| 1743 | if (!ide_if[0].bs && !ide_if[1].bs) | 1852 | if (!ide_if[0].bs && !ide_if[1].bs) |
| 1744 | ret = 0; | 1853 | ret = 0; |
| 1745 | - else | 1854 | + else if (!hob) |
| 1746 | ret = s->nsector & 0xff; | 1855 | ret = s->nsector & 0xff; |
| 1856 | + else | ||
| 1857 | + ret = s->hob_nsector; | ||
| 1747 | break; | 1858 | break; |
| 1748 | case 3: | 1859 | case 3: |
| 1749 | if (!ide_if[0].bs && !ide_if[1].bs) | 1860 | if (!ide_if[0].bs && !ide_if[1].bs) |
| 1750 | ret = 0; | 1861 | ret = 0; |
| 1751 | - else | 1862 | + else if (!hob) |
| 1752 | ret = s->sector; | 1863 | ret = s->sector; |
| 1864 | + else | ||
| 1865 | + ret = s->hob_sector; | ||
| 1753 | break; | 1866 | break; |
| 1754 | case 4: | 1867 | case 4: |
| 1755 | if (!ide_if[0].bs && !ide_if[1].bs) | 1868 | if (!ide_if[0].bs && !ide_if[1].bs) |
| 1756 | ret = 0; | 1869 | ret = 0; |
| 1757 | - else | 1870 | + else if (!hob) |
| 1758 | ret = s->lcyl; | 1871 | ret = s->lcyl; |
| 1872 | + else | ||
| 1873 | + ret = s->hob_lcyl; | ||
| 1759 | break; | 1874 | break; |
| 1760 | case 5: | 1875 | case 5: |
| 1761 | if (!ide_if[0].bs && !ide_if[1].bs) | 1876 | if (!ide_if[0].bs && !ide_if[1].bs) |
| 1762 | ret = 0; | 1877 | ret = 0; |
| 1763 | - else | 1878 | + else if (!hob) |
| 1764 | ret = s->hcyl; | 1879 | ret = s->hcyl; |
| 1880 | + else | ||
| 1881 | + ret = s->hob_hcyl; | ||
| 1765 | break; | 1882 | break; |
| 1766 | case 6: | 1883 | case 6: |
| 1767 | if (!ide_if[0].bs && !ide_if[1].bs) | 1884 | if (!ide_if[0].bs && !ide_if[1].bs) |