Commit bf1b938fce39c8837899d11d074e2df983592a5b
1 parent
46d4767d
disable automatic BIOS translation if the logical disk geometry implies it
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1154 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
33 additions
and
16 deletions
hw/ide.c
| @@ -1826,22 +1826,21 @@ struct partition { | @@ -1826,22 +1826,21 @@ struct partition { | ||
| 1826 | uint32_t nr_sects; /* nr of sectors in partition */ | 1826 | uint32_t nr_sects; /* nr of sectors in partition */ |
| 1827 | } __attribute__((packed)); | 1827 | } __attribute__((packed)); |
| 1828 | 1828 | ||
| 1829 | -/* try to guess the IDE physical geometry from the MSDOS partition table */ | ||
| 1830 | -static void ide_guess_geometry(IDEState *s) | 1829 | +/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ |
| 1830 | +static int guess_disk_lchs(IDEState *s, | ||
| 1831 | + int *pcylinders, int *pheads, int *psectors) | ||
| 1831 | { | 1832 | { |
| 1832 | uint8_t buf[512]; | 1833 | uint8_t buf[512]; |
| 1833 | int ret, i, heads, sectors, cylinders; | 1834 | int ret, i, heads, sectors, cylinders; |
| 1834 | struct partition *p; | 1835 | struct partition *p; |
| 1835 | uint32_t nr_sects; | 1836 | uint32_t nr_sects; |
| 1836 | 1837 | ||
| 1837 | - if (s->cylinders != 0) | ||
| 1838 | - return; | ||
| 1839 | ret = bdrv_read(s->bs, 0, buf, 1); | 1838 | ret = bdrv_read(s->bs, 0, buf, 1); |
| 1840 | if (ret < 0) | 1839 | if (ret < 0) |
| 1841 | - return; | 1840 | + return -1; |
| 1842 | /* test msdos magic */ | 1841 | /* test msdos magic */ |
| 1843 | if (buf[510] != 0x55 || buf[511] != 0xaa) | 1842 | if (buf[510] != 0x55 || buf[511] != 0xaa) |
| 1844 | - return; | 1843 | + return -1; |
| 1845 | for(i = 0; i < 4; i++) { | 1844 | for(i = 0; i < 4; i++) { |
| 1846 | p = ((struct partition *)(buf + 0x1be)) + i; | 1845 | p = ((struct partition *)(buf + 0x1be)) + i; |
| 1847 | nr_sects = le32_to_cpu(p->nr_sects); | 1846 | nr_sects = le32_to_cpu(p->nr_sects); |
| @@ -1849,23 +1848,23 @@ static void ide_guess_geometry(IDEState *s) | @@ -1849,23 +1848,23 @@ static void ide_guess_geometry(IDEState *s) | ||
| 1849 | /* We make the assumption that the partition terminates on | 1848 | /* We make the assumption that the partition terminates on |
| 1850 | a cylinder boundary */ | 1849 | a cylinder boundary */ |
| 1851 | heads = p->end_head + 1; | 1850 | heads = p->end_head + 1; |
| 1852 | - if (heads < 1 || heads > 16) | ||
| 1853 | - continue; | ||
| 1854 | sectors = p->end_sector & 63; | 1851 | sectors = p->end_sector & 63; |
| 1855 | if (sectors == 0) | 1852 | if (sectors == 0) |
| 1856 | continue; | 1853 | continue; |
| 1857 | cylinders = s->nb_sectors / (heads * sectors); | 1854 | cylinders = s->nb_sectors / (heads * sectors); |
| 1858 | if (cylinders < 1 || cylinders > 16383) | 1855 | if (cylinders < 1 || cylinders > 16383) |
| 1859 | continue; | 1856 | continue; |
| 1860 | - s->heads = heads; | ||
| 1861 | - s->sectors = sectors; | ||
| 1862 | - s->cylinders = cylinders; | 1857 | + *pheads = heads; |
| 1858 | + *psectors = sectors; | ||
| 1859 | + *pcylinders = cylinders; | ||
| 1863 | #if 0 | 1860 | #if 0 |
| 1864 | - printf("guessed partition: CHS=%d %d %d\n", | ||
| 1865 | - s->cylinders, s->heads, s->sectors); | 1861 | + printf("guessed geometry: LCHS=%d %d %d\n", |
| 1862 | + cylinders, heads, sectors); | ||
| 1866 | #endif | 1863 | #endif |
| 1864 | + return 0; | ||
| 1867 | } | 1865 | } |
| 1868 | } | 1866 | } |
| 1867 | + return -1; | ||
| 1869 | } | 1868 | } |
| 1870 | 1869 | ||
| 1871 | static void ide_init2(IDEState *ide_state, int irq, | 1870 | static void ide_init2(IDEState *ide_state, int irq, |
| @@ -1873,7 +1872,7 @@ static void ide_init2(IDEState *ide_state, int irq, | @@ -1873,7 +1872,7 @@ static void ide_init2(IDEState *ide_state, int irq, | ||
| 1873 | { | 1872 | { |
| 1874 | IDEState *s; | 1873 | IDEState *s; |
| 1875 | static int drive_serial = 1; | 1874 | static int drive_serial = 1; |
| 1876 | - int i, cylinders, heads, secs; | 1875 | + int i, cylinders, heads, secs, translation; |
| 1877 | int64_t nb_sectors; | 1876 | int64_t nb_sectors; |
| 1878 | 1877 | ||
| 1879 | for(i = 0; i < 2; i++) { | 1878 | for(i = 0; i < 2; i++) { |
| @@ -1892,8 +1891,26 @@ static void ide_init2(IDEState *ide_state, int irq, | @@ -1892,8 +1891,26 @@ static void ide_init2(IDEState *ide_state, int irq, | ||
| 1892 | s->heads = heads; | 1891 | s->heads = heads; |
| 1893 | s->sectors = secs; | 1892 | s->sectors = secs; |
| 1894 | } else { | 1893 | } else { |
| 1895 | - ide_guess_geometry(s); | ||
| 1896 | - if (s->cylinders == 0) { | 1894 | + if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) { |
| 1895 | + if (heads > 16) { | ||
| 1896 | + /* if heads > 16, it means that a BIOS LBA | ||
| 1897 | + translation was active, so the default | ||
| 1898 | + hardware geometry is OK */ | ||
| 1899 | + goto default_geometry; | ||
| 1900 | + } else { | ||
| 1901 | + s->cylinders = cylinders; | ||
| 1902 | + s->heads = heads; | ||
| 1903 | + s->sectors = secs; | ||
| 1904 | + /* disable any translation to be in sync with | ||
| 1905 | + the logical geometry */ | ||
| 1906 | + translation = bdrv_get_translation_hint(s->bs); | ||
| 1907 | + if (translation == BIOS_ATA_TRANSLATION_AUTO) { | ||
| 1908 | + bdrv_set_translation_hint(s->bs, | ||
| 1909 | + BIOS_ATA_TRANSLATION_NONE); | ||
| 1910 | + } | ||
| 1911 | + } | ||
| 1912 | + } else { | ||
| 1913 | + default_geometry: | ||
| 1897 | /* if no geometry, use a standard physical disk geometry */ | 1914 | /* if no geometry, use a standard physical disk geometry */ |
| 1898 | cylinders = nb_sectors / (16 * 63); | 1915 | cylinders = nb_sectors / (16 * 63); |
| 1899 | if (cylinders > 16383) | 1916 | if (cylinders > 16383) |