summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-11-16 01:45:27 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-11-16 01:45:27 +0000
commit46d4767d93bcb2e84869ba6d2344ebff4382be86 (patch)
treeec07dcd1af4aaab9db64547e0b4cf36558caf772 /hw
parente35c55fe38faea68eb9356163f52a426e533d79b (diff)
downloadqemu-46d4767d93bcb2e84869ba6d2344ebff4382be86.tar.gz
better BIOS ATA translation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1153 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r--hw/ide.c21
-rw-r--r--hw/pc.c28
2 files changed, 31 insertions, 18 deletions
diff --git a/hw/ide.c b/hw/ide.c
index bc7ebd3205..e922e7ba7c 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -1826,11 +1826,11 @@ struct partition {
uint32_t nr_sects; /* nr of sectors in partition */
} __attribute__((packed));
-/* try to guess the IDE geometry from the MSDOS partition table */
+/* try to guess the IDE physical geometry from the MSDOS partition table */
static void ide_guess_geometry(IDEState *s)
{
uint8_t buf[512];
- int ret, i;
+ int ret, i, heads, sectors, cylinders;
struct partition *p;
uint32_t nr_sects;
@@ -1848,9 +1848,18 @@ static void ide_guess_geometry(IDEState *s)
if (nr_sects && p->end_head) {
/* We make the assumption that the partition terminates on
a cylinder boundary */
- s->heads = p->end_head + 1;
- s->sectors = p->end_sector & 63;
- s->cylinders = s->nb_sectors / (s->heads * s->sectors);
+ heads = p->end_head + 1;
+ if (heads < 1 || heads > 16)
+ continue;
+ sectors = p->end_sector & 63;
+ if (sectors == 0)
+ continue;
+ cylinders = s->nb_sectors / (heads * sectors);
+ if (cylinders < 1 || cylinders > 16383)
+ continue;
+ s->heads = heads;
+ s->sectors = sectors;
+ s->cylinders = cylinders;
#if 0
printf("guessed partition: CHS=%d %d %d\n",
s->cylinders, s->heads, s->sectors);
@@ -1885,7 +1894,7 @@ static void ide_init2(IDEState *ide_state, int irq,
} else {
ide_guess_geometry(s);
if (s->cylinders == 0) {
- /* if no geometry, use a LBA compatible one */
+ /* if no geometry, use a standard physical disk geometry */
cylinders = nb_sectors / (16 * 63);
if (cylinders > 16383)
cylinders = 16383;
diff --git a/hw/pc.c b/hw/pc.c
index 06ec7b1b69..64b6180a3d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -217,19 +217,23 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
val = 0;
for (i = 0; i < 4; i++) {
if (hd_table[i]) {
- int cylinders, heads, sectors;
- uint8_t translation;
- /* NOTE: bdrv_get_geometry_hint() returns the geometry
- that the hard disk returns. It is always such that: 1 <=
- sects <= 63, 1 <= heads <= 16, 1 <= cylinders <=
- 16383. The BIOS geometry can be different. */
- bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
- if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
- /* No translation. */
- translation = 0;
+ int cylinders, heads, sectors, translation;
+ /* NOTE: bdrv_get_geometry_hint() returns the physical
+ geometry. It is always such that: 1 <= sects <= 63, 1
+ <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
+ geometry can be different if a translation is done. */
+ translation = bdrv_get_translation_hint(hd_table[i]);
+ if (translation == BIOS_ATA_TRANSLATION_AUTO) {
+ bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
+ if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
+ /* No translation. */
+ translation = 0;
+ } else {
+ /* LBA translation. */
+ translation = 1;
+ }
} else {
- /* LBA translation. */
- translation = 1;
+ translation--;
}
val |= translation << (i * 2);
}