I made further tests and I can confirm the issue is not fixed in 0.12.5.

I currently use a patch written by Bruce Rogers from Novell that applies 
directly on 0.12 branch. It probably isn't the best way to fix the problem, but 
it works. Could you take a look at it ?

Thank you,
-- 
Laurent Léonard
When specifying ide devices using -device, the cmos information
which the bios depends on is not written. This patch generalizes
the cmos hd data setting for the existing code path and adds the
ability to call that code on a per machine, per ide drive basis.

I needed to add an id to the IDEBus structure since there wasn't
a way to identify whether an ide bus was primary or secondary in
the lower level code.

Also, the ide bus naming wasn't working right for isa, so we now
explicitly pass in the name for the isa case.

Signed-off-by: Bruce Rogers <brog...@novell.com>

Index: qemu-kvm-0.12.3/hw/pc.c
===================================================================
--- qemu-kvm-0.12.3.orig/hw/pc.c
+++ qemu-kvm-0.12.3/hw/pc.c
@@ -212,6 +212,44 @@ static void cmos_init_hd(int type_ofs, i
     rtc_set_memory(s, info_ofs + 8, sectors);
 }
 
+static void set_cmos_hd_data(DriveInfo *dinfo)
+{
+    static int hd_type = 0;
+    static int hd_trans = 0;
+    RTCState *s = rtc_state;
+    int cylinders, heads, sectors, translation;
+
+    if (dinfo->bus == 0) {
+        if (dinfo->unit == 0) {
+            hd_type |= 0xf0;
+            cmos_init_hd(0x19, 0x1b, dinfo->bdrv);
+        } else {
+            hd_type |= 0x0f;
+            cmos_init_hd(0x1a, 0x24, dinfo->bdrv);
+        }
+        rtc_set_memory(s, 0x12, hd_type);
+    }
+    /* 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(dinfo->bdrv);
+    if (translation == BIOS_ATA_TRANSLATION_AUTO) {
+        bdrv_get_geometry_hint(dinfo->bdrv, &cylinders, &heads, &sectors);
+        if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
+            /* No translation. */
+            translation = 0;
+        } else {
+            /* LBA translation. */
+            translation = 1;
+        }
+    } else {
+        translation--;
+    }
+    hd_trans |= translation << ((dinfo->bus * 4) + (dinfo->unit * 2));
+    rtc_set_memory(s, 0x39, hd_trans);
+}
+
 /* convert boot_device letter to something recognizable by the bios */
 static int boot_device2nibble(char boot_device)
 {
@@ -348,37 +386,11 @@ static void cmos_init(ram_addr_t ram_siz
 
     /* hard drives */
 
-    rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
-    if (hd_table[0])
-        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv);
-    if (hd_table[1])
-        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv);
-
-    val = 0;
     for (i = 0; i < 4; i++) {
         if (hd_table[i]) {
-            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]->bdrv);
-            if (translation == BIOS_ATA_TRANSLATION_AUTO) {
-                bdrv_get_geometry_hint(hd_table[i]->bdrv, &cylinders, &heads, &sectors);
-                if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
-                    /* No translation. */
-                    translation = 0;
-                } else {
-                    /* LBA translation. */
-                    translation = 1;
-                }
-            } else {
-                translation--;
-            }
-            val |= translation << (i * 2);
+            set_cmos_hd_data(hd_table[i]);
         }
     }
-    rtc_set_memory(s, 0x39, val);
 }
 
 void ioport_set_a20(int enable)
@@ -1016,6 +1028,8 @@ static void pc_init1(ram_addr_t ram_size
     DriveInfo *fd[MAX_FD];
     void *fw_cfg;
 
+    machine_ide_finalize = set_cmos_hd_data;
+
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
         below_4g_mem_size = 0xe0000000;
Index: qemu-kvm-0.12.3/sysemu.h
===================================================================
--- qemu-kvm-0.12.3.orig/sysemu.h
+++ qemu-kvm-0.12.3/sysemu.h
@@ -265,5 +265,6 @@ void do_usb_del(Monitor *mon, const QDic
 void usb_info(Monitor *mon);
 
 void register_devices(void);
+extern void (*machine_ide_finalize)(DriveInfo *dinfo);
 
 #endif
Index: qemu-kvm-0.12.3/vl.c
===================================================================
--- qemu-kvm-0.12.3.orig/vl.c
+++ qemu-kvm-0.12.3/vl.c
@@ -260,6 +260,7 @@ const char *prom_envs[MAX_PROM_ENVS];
 #endif
 const char *nvram = NULL;
 int boot_menu;
+void (*machine_ide_finalize)(DriveInfo *dinfo);
 
 int nb_numa_nodes;
 uint64_t node_mem[MAX_NODES];
@@ -307,6 +308,10 @@ static struct {
     { .driver = "vmware-svga",          .flag = &default_vga       },
 };
 
+static void default_ide_finalize(DriveInfo *dinfo)
+{
+}
+
 static int default_driver_check(QemuOpts *opts, void *opaque)
 {
     const char *driver = qemu_opt_get(opts, "driver");
@@ -4975,6 +4980,7 @@ int main(int argc, char **argv, char **e
 
     module_call_init(MODULE_INIT_MACHINE);
     machine = find_default_machine();
+    machine_ide_finalize = default_ide_finalize;
     cpu_model = NULL;
     initrd_filename = NULL;
     ram_size = 0;
Index: qemu-kvm-0.12.3/hw/ide/internal.h
===================================================================
--- qemu-kvm-0.12.3.orig/hw/ide/internal.h
+++ qemu-kvm-0.12.3/hw/ide/internal.h
@@ -448,6 +448,7 @@ struct IDEBus {
     IDEState ifs[2];
     uint8_t unit;
     uint8_t cmd;
+    uint8_t id;
     qemu_irq irq;
 };
 
@@ -561,7 +562,7 @@ void ide_init2(IDEBus *bus, DriveInfo *h
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
 
 /* hw/ide/qdev.c */
-void ide_bus_new(IDEBus *idebus, DeviceState *dev);
+void ide_bus_new(IDEBus *idebus, DeviceState *dev, const char *name);
 IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
 
 #endif /* HW_IDE_INTERNAL_H */
Index: qemu-kvm-0.12.3/hw/ide/piix.c
===================================================================
--- qemu-kvm-0.12.3.orig/hw/ide/piix.c
+++ qemu-kvm-0.12.3/hw/ide/piix.c
@@ -127,11 +127,13 @@ static int pci_piix_ide_initfn(PCIIDESta
 
     vmstate_register(0, &vmstate_ide_pci, d);
 
-    ide_bus_new(&d->bus[0], &d->dev.qdev);
-    ide_bus_new(&d->bus[1], &d->dev.qdev);
+    ide_bus_new(&d->bus[0], &d->dev.qdev, NULL);
+    ide_bus_new(&d->bus[1], &d->dev.qdev, NULL);
     ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->bus[1], 0x170, 0x376);
 
+    d->bus[0].id = 0;
+    d->bus[1].id = 1;
     ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14));
     ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15));
     return 0;
Index: qemu-kvm-0.12.3/hw/ide/qdev.c
===================================================================
--- qemu-kvm-0.12.3.orig/hw/ide/qdev.c
+++ qemu-kvm-0.12.3/hw/ide/qdev.c
@@ -29,9 +29,9 @@ static struct BusInfo ide_bus_info = {
     .size  = sizeof(IDEBus),
 };
 
-void ide_bus_new(IDEBus *idebus, DeviceState *dev)
+void ide_bus_new(IDEBus *idebus, DeviceState *dev, const char *name)
 {
-    qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL);
+    qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, name);
 }
 
 static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
@@ -39,6 +39,7 @@ static int ide_qdev_init(DeviceState *qd
     IDEDevice *dev = DO_UPCAST(IDEDevice, qdev, qdev);
     IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base);
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
+    int i;
 
     if (!dev->dinfo) {
         fprintf(stderr, "%s: no drive specified\n", qdev->info->name);
@@ -65,7 +66,13 @@ static int ide_qdev_init(DeviceState *qd
     default:
         goto err;
     }
-    return info->init(dev);
+    dev->dinfo->bus = bus->id;
+    dev->dinfo->unit = dev->unit;
+    i = info->init(dev);
+    if (i >= 0) {
+        machine_ide_finalize(dev->dinfo);
+    }
+    return i;
 
 err:
     return -1;
Index: qemu-kvm-0.12.3/hw/ide/isa.c
===================================================================
--- qemu-kvm-0.12.3.orig/hw/ide/isa.c
+++ qemu-kvm-0.12.3/hw/ide/isa.c
@@ -67,7 +67,13 @@ static int isa_ide_initfn(ISADevice *dev
 {
     ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev);
 
-    ide_bus_new(&s->bus, &s->dev.qdev);
+    if (s->iobase == 0x1f0) {
+        ide_bus_new(&s->bus, &s->dev.qdev, "ide.0");
+        s->bus.id = 0;
+    } else {
+        ide_bus_new(&s->bus, &s->dev.qdev, "ide.1");
+        s->bus.id = 1;
+    }
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
     ide_init2(&s->bus, NULL, NULL, s->irq);

Reply via email to