Commit c2ff060fd4c7389de2016442e3327538a66696bd

Authored by bellard
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 307 /* ide regs */
308 308 uint8_t feature;
309 309 uint8_t error;
310   - uint16_t nsector; /* 0 is 256 to ease computations */
  310 + uint32_t nsector;
311 311 uint8_t sector;
312 312 uint8_t lcyl;
313 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 321 uint8_t select;
315 322 uint8_t status;
  323 +
316 324 /* 0x3f6 command, only meaningful for drive 0 */
317 325 uint8_t cmd;
  326 + /* set for lba48 access */
  327 + uint8_t lba48;
318 328 /* depends on bit 4 in select, only meaningful for drive 0 */
319 329 struct IDEState *cur_drive;
320 330 BlockDriverState *bs;
... ... @@ -463,13 +473,19 @@ static void ide_identify(IDEState *s)
463 473 put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
464 474 put_le16(p + 81, 0x16); /* conforms to ata5 */
465 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 478 put_le16(p + 84, (1 << 14));
468 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 482 put_le16(p + 87, (1 << 14));
471 483 put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
472 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 490 memcpy(s->identify_data, p, sizeof(s->identify_data));
475 491 s->identify_set = 1;
... ... @@ -573,12 +589,19 @@ static int64_t ide_get_sector(IDEState *s)
573 589 int64_t sector_num;
574 590 if (s->select & 0x40) {
575 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 602 } else {
579 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 606 return sector_num;
584 607 }
... ... @@ -587,10 +610,19 @@ static void ide_set_sector(IDEState *s, int64_t sector_num)
587 610 {
588 611 unsigned int cyl, r;
589 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 626 } else {
595 627 cyl = sector_num / (s->heads * s->sectors);
596 628 r = sector_num % (s->heads * s->sectors);
... ... @@ -1488,43 +1520,89 @@ static void cdrom_change_cb(void *opaque)
1488 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 1553 static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1492 1554 {
1493 1555 IDEState *ide_if = opaque;
1494 1556 IDEState *s;
1495 1557 int unit, n;
  1558 + int lba48 = 0;
1496 1559  
1497 1560 #ifdef DEBUG_IDE
1498 1561 printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
1499 1562 #endif
  1563 +
1500 1564 addr &= 7;
1501 1565 switch(addr) {
1502 1566 case 0:
1503 1567 break;
1504 1568 case 1:
  1569 + ide_clear_hob(ide_if);
1505 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 1573 ide_if[0].feature = val;
1507 1574 ide_if[1].feature = val;
1508 1575 break;
1509 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 1580 ide_if[0].nsector = val;
1513 1581 ide_if[1].nsector = val;
1514 1582 break;
1515 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 1587 ide_if[0].sector = val;
1517 1588 ide_if[1].sector = val;
1518 1589 break;
1519 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 1594 ide_if[0].lcyl = val;
1521 1595 ide_if[1].lcyl = val;
1522 1596 break;
1523 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 1601 ide_if[0].hcyl = val;
1525 1602 ide_if[1].hcyl = val;
1526 1603 break;
1527 1604 case 6:
  1605 + /* FIXME: HOB readback uses bit 7 */
1528 1606 ide_if[0].select = (val & ~0x10) | 0xa0;
1529 1607 ide_if[1].select = (val | 0x10) | 0xa0;
1530 1608 /* select drive */
... ... @@ -1542,6 +1620,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1542 1620 /* ignore commands to non existant slave */
1543 1621 if (s != ide_if && !s->bs)
1544 1622 break;
  1623 +
1545 1624 switch(val) {
1546 1625 case WIN_IDENTIFY:
1547 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 1652 }
1574 1653 ide_set_irq(s);
1575 1654 break;
  1655 + case WIN_VERIFY_EXT:
  1656 + lba48 = 1;
1576 1657 case WIN_VERIFY:
1577 1658 case WIN_VERIFY_ONCE:
1578 1659 /* do sector number check ? */
  1660 + ide_cmd_lba48_transform(s, lba48);
1579 1661 s->status = READY_STAT;
1580 1662 ide_set_irq(s);
1581 1663 break;
  1664 + case WIN_READ_EXT:
  1665 + lba48 = 1;
1582 1666 case WIN_READ:
1583 1667 case WIN_READ_ONCE:
1584 1668 if (!s->bs)
1585 1669 goto abort_cmd;
  1670 + ide_cmd_lba48_transform(s, lba48);
1586 1671 s->req_nb_sectors = 1;
1587 1672 ide_sector_read(s);
1588 1673 break;
  1674 + case WIN_WRITE_EXT:
  1675 + lba48 = 1;
1589 1676 case WIN_WRITE:
1590 1677 case WIN_WRITE_ONCE:
  1678 + ide_cmd_lba48_transform(s, lba48);
1591 1679 s->error = 0;
1592 1680 s->status = SEEK_STAT | READY_STAT;
1593 1681 s->req_nb_sectors = 1;
1594 1682 ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
1595 1683 break;
  1684 + case WIN_MULTREAD_EXT:
  1685 + lba48 = 1;
1596 1686 case WIN_MULTREAD:
1597 1687 if (!s->mult_sectors)
1598 1688 goto abort_cmd;
  1689 + ide_cmd_lba48_transform(s, lba48);
1599 1690 s->req_nb_sectors = s->mult_sectors;
1600 1691 ide_sector_read(s);
1601 1692 break;
  1693 + case WIN_MULTWRITE_EXT:
  1694 + lba48 = 1;
1602 1695 case WIN_MULTWRITE:
1603 1696 if (!s->mult_sectors)
1604 1697 goto abort_cmd;
  1698 + ide_cmd_lba48_transform(s, lba48);
1605 1699 s->error = 0;
1606 1700 s->status = SEEK_STAT | READY_STAT;
1607 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 1704 n = s->req_nb_sectors;
1611 1705 ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
1612 1706 break;
  1707 + case WIN_READDMA_EXT:
  1708 + lba48 = 1;
1613 1709 case WIN_READDMA:
1614 1710 case WIN_READDMA_ONCE:
1615 1711 if (!s->bs)
1616 1712 goto abort_cmd;
  1713 + ide_cmd_lba48_transform(s, lba48);
1617 1714 ide_sector_read_dma(s);
1618 1715 break;
  1716 + case WIN_WRITEDMA_EXT:
  1717 + lba48 = 1;
1619 1718 case WIN_WRITEDMA:
1620 1719 case WIN_WRITEDMA_ONCE:
1621 1720 if (!s->bs)
1622 1721 goto abort_cmd;
  1722 + ide_cmd_lba48_transform(s, lba48);
1623 1723 ide_sector_write_dma(s);
1624 1724 break;
  1725 + case WIN_READ_NATIVE_MAX_EXT:
  1726 + lba48 = 1;
1625 1727 case WIN_READ_NATIVE_MAX:
  1728 + ide_cmd_lba48_transform(s, lba48);
1626 1729 ide_set_sector(s, s->nb_sectors - 1);
1627 1730 s->status = READY_STAT;
1628 1731 ide_set_irq(s);
... ... @@ -1672,9 +1775,10 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1672 1775 goto abort_cmd;
1673 1776 }
1674 1777 break;
  1778 + case WIN_FLUSH_CACHE:
  1779 + case WIN_FLUSH_CACHE_EXT:
1675 1780 case WIN_STANDBYNOW1:
1676 1781 case WIN_IDLEIMMEDIATE:
1677   - case WIN_FLUSH_CACHE:
1678 1782 s->status = READY_STAT;
1679 1783 ide_set_irq(s);
1680 1784 break;
... ... @@ -1726,9 +1830,12 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
1726 1830 IDEState *ide_if = opaque;
1727 1831 IDEState *s = ide_if->cur_drive;
1728 1832 uint32_t addr;
1729   - int ret;
  1833 + int ret, hob;
1730 1834  
1731 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 1839 switch(addr) {
1733 1840 case 0:
1734 1841 ret = 0xff;
... ... @@ -1736,32 +1843,42 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
1736 1843 case 1:
1737 1844 if (!ide_if[0].bs && !ide_if[1].bs)
1738 1845 ret = 0;
1739   - else
  1846 + else if (!hob)
1740 1847 ret = s->error;
  1848 + else
  1849 + ret = s->hob_feature;
1741 1850 break;
1742 1851 case 2:
1743 1852 if (!ide_if[0].bs && !ide_if[1].bs)
1744 1853 ret = 0;
1745   - else
  1854 + else if (!hob)
1746 1855 ret = s->nsector & 0xff;
  1856 + else
  1857 + ret = s->hob_nsector;
1747 1858 break;
1748 1859 case 3:
1749 1860 if (!ide_if[0].bs && !ide_if[1].bs)
1750 1861 ret = 0;
1751   - else
  1862 + else if (!hob)
1752 1863 ret = s->sector;
  1864 + else
  1865 + ret = s->hob_sector;
1753 1866 break;
1754 1867 case 4:
1755 1868 if (!ide_if[0].bs && !ide_if[1].bs)
1756 1869 ret = 0;
1757   - else
  1870 + else if (!hob)
1758 1871 ret = s->lcyl;
  1872 + else
  1873 + ret = s->hob_lcyl;
1759 1874 break;
1760 1875 case 5:
1761 1876 if (!ide_if[0].bs && !ide_if[1].bs)
1762 1877 ret = 0;
1763   - else
  1878 + else if (!hob)
1764 1879 ret = s->hcyl;
  1880 + else
  1881 + ret = s->hob_hcyl;
1765 1882 break;
1766 1883 case 6:
1767 1884 if (!ide_if[0].bs && !ide_if[1].bs)
... ...