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,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)