1826 |
uint32_t nr_sects; /* nr of sectors in partition */ |
uint32_t nr_sects; /* nr of sectors in partition */ |
1827 |
} __attribute__((packed)); |
} __attribute__((packed)); |
1828 |
|
|
1829 |
/* try to guess the IDE physical geometry from the MSDOS partition table */ |
/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ |
1830 |
static void ide_guess_geometry(IDEState *s) |
static int guess_disk_lchs(IDEState *s, |
1831 |
|
int *pcylinders, int *pheads, int *psectors) |
1832 |
{ |
{ |
1833 |
uint8_t buf[512]; |
uint8_t buf[512]; |
1834 |
int ret, i, heads, sectors, cylinders; |
int ret, i, heads, sectors, cylinders; |
1835 |
struct partition *p; |
struct partition *p; |
1836 |
uint32_t nr_sects; |
uint32_t nr_sects; |
1837 |
|
|
|
if (s->cylinders != 0) |
|
|
return; |
|
1838 |
ret = bdrv_read(s->bs, 0, buf, 1); |
ret = bdrv_read(s->bs, 0, buf, 1); |
1839 |
if (ret < 0) |
if (ret < 0) |
1840 |
return; |
return -1; |
1841 |
/* test msdos magic */ |
/* test msdos magic */ |
1842 |
if (buf[510] != 0x55 || buf[511] != 0xaa) |
if (buf[510] != 0x55 || buf[511] != 0xaa) |
1843 |
return; |
return -1; |
1844 |
for(i = 0; i < 4; i++) { |
for(i = 0; i < 4; i++) { |
1845 |
p = ((struct partition *)(buf + 0x1be)) + i; |
p = ((struct partition *)(buf + 0x1be)) + i; |
1846 |
nr_sects = le32_to_cpu(p->nr_sects); |
nr_sects = le32_to_cpu(p->nr_sects); |
1848 |
/* We make the assumption that the partition terminates on |
/* We make the assumption that the partition terminates on |
1849 |
a cylinder boundary */ |
a cylinder boundary */ |
1850 |
heads = p->end_head + 1; |
heads = p->end_head + 1; |
|
if (heads < 1 || heads > 16) |
|
|
continue; |
|
1851 |
sectors = p->end_sector & 63; |
sectors = p->end_sector & 63; |
1852 |
if (sectors == 0) |
if (sectors == 0) |
1853 |
continue; |
continue; |
1854 |
cylinders = s->nb_sectors / (heads * sectors); |
cylinders = s->nb_sectors / (heads * sectors); |
1855 |
if (cylinders < 1 || cylinders > 16383) |
if (cylinders < 1 || cylinders > 16383) |
1856 |
continue; |
continue; |
1857 |
s->heads = heads; |
*pheads = heads; |
1858 |
s->sectors = sectors; |
*psectors = sectors; |
1859 |
s->cylinders = cylinders; |
*pcylinders = cylinders; |
1860 |
#if 0 |
#if 0 |
1861 |
printf("guessed partition: CHS=%d %d %d\n", |
printf("guessed geometry: LCHS=%d %d %d\n", |
1862 |
s->cylinders, s->heads, s->sectors); |
cylinders, heads, sectors); |
1863 |
#endif |
#endif |
1864 |
|
return 0; |
1865 |
} |
} |
1866 |
} |
} |
1867 |
|
return -1; |
1868 |
} |
} |
1869 |
|
|
1870 |
static void ide_init2(IDEState *ide_state, int irq, |
static void ide_init2(IDEState *ide_state, int irq, |
1872 |
{ |
{ |
1873 |
IDEState *s; |
IDEState *s; |
1874 |
static int drive_serial = 1; |
static int drive_serial = 1; |
1875 |
int i, cylinders, heads, secs; |
int i, cylinders, heads, secs, translation; |
1876 |
int64_t nb_sectors; |
int64_t nb_sectors; |
1877 |
|
|
1878 |
for(i = 0; i < 2; i++) { |
for(i = 0; i < 2; i++) { |
1891 |
s->heads = heads; |
s->heads = heads; |
1892 |
s->sectors = secs; |
s->sectors = secs; |
1893 |
} else { |
} else { |
1894 |
ide_guess_geometry(s); |
if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) { |
1895 |
if (s->cylinders == 0) { |
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: |
1914 |
/* if no geometry, use a standard physical disk geometry */ |
/* if no geometry, use a standard physical disk geometry */ |
1915 |
cylinders = nb_sectors / (16 * 63); |
cylinders = nb_sectors / (16 * 63); |
1916 |
if (cylinders > 16383) |
if (cylinders > 16383) |