diff --git a/hw/ide.h b/hw/ide.h
index 82b3c11283429feed6bd1d09af23794a31011701..2b5ae7c39e6e9a2147b86c787f8488a705136776 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -24,4 +24,6 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
                     qemu_irq irq, int shift,
                     DriveInfo *hd0, DriveInfo *hd1);
 
+void ide_get_bs(BlockDriverState *bs[], BusState *qbus);
+
 #endif /* HW_IDE_H */
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index b34c47333623586746586b9689fd0159c8125bb3..2977a168e5c3f9e1646eec9d11eb177587b2382d 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -88,6 +88,13 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
     return DO_UPCAST(IDEDevice, qdev, dev);
 }
 
+void ide_get_bs(BlockDriverState *bs[], BusState *qbus)
+{
+    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus);
+    bs[0] = bus->master ? bus->master->conf.bs : NULL;
+    bs[1] = bus->slave  ? bus->slave->conf.bs  : NULL;
+}
+
 /* --------------------------------- */
 
 typedef struct IDEDrive {
diff --git a/hw/pc.c b/hw/pc.c
index 25ebafac80e9dcfe9981cb6e66659ddfc33cad4f..b577fb1bc6b17a29bb6b1d8a88a146c082ca579d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -25,6 +25,7 @@
 #include "pc.h"
 #include "apic.h"
 #include "fdc.h"
+#include "ide.h"
 #include "pci.h"
 #include "vmware_vga.h"
 #include "monitor.h"
@@ -275,14 +276,65 @@ static int pc_boot_set(void *opaque, const char *boot_device)
     return set_boot_dev(opaque, boot_device, 0);
 }
 
-/* hd_table must contain 4 block drivers */
+typedef struct pc_cmos_init_late_arg {
+    ISADevice *rtc_state;
+    BusState *idebus0, *idebus1;
+} pc_cmos_init_late_arg;
+
+static void pc_cmos_init_late(void *opaque)
+{
+    pc_cmos_init_late_arg *arg = opaque;
+    ISADevice *s = arg->rtc_state;
+    int val;
+    BlockDriverState *hd_table[4];
+    int i;
+
+    ide_get_bs(hd_table, arg->idebus0);
+    ide_get_bs(hd_table + 2, arg->idebus1);
+
+    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], s);
+    if (hd_table[1])
+        cmos_init_hd(0x1a, 0x24, hd_table[1], s);
+
+    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]);
+            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 {
+                translation--;
+            }
+            val |= translation << (i * 2);
+        }
+    }
+    rtc_set_memory(s, 0x39, val);
+
+    qemu_unregister_reset(pc_cmos_init_late, opaque);
+}
+
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                  const char *boot_device, DriveInfo **hd_table,
+                  const char *boot_device,
+                  BusState *idebus0, BusState *idebus1,
                   FDCtrl *floppy_controller, ISADevice *s)
 {
     int val;
     int fd0, fd1, nb;
-    int i;
+    static pc_cmos_init_late_arg arg;
 
     /* various important CMOS locations needed by PC/Bochs bios */
 
@@ -351,38 +403,10 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
 
     /* 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, s);
-    if (hd_table[1])
-        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv, s);
-
-    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);
-        }
-    }
-    rtc_set_memory(s, 0x39, val);
+    arg.rtc_state = s;
+    arg.idebus0 = idebus0;
+    arg.idebus1 = idebus1;
+    qemu_register_reset(pc_cmos_init_late, &arg);
 }
 
 static void handle_a20_line_change(void *opaque, int irq, int level)
diff --git a/hw/pc.h b/hw/pc.h
index ccfd7add99c6c93b7cf746ac47c934319056cd88..63b0249f2fe2e997b8bbb9813b577b4d32effd19 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -104,7 +104,8 @@ void pc_init_ne2k_isa(NICInfo *nd);
 void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic);
 #endif
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                  const char *boot_device, DriveInfo **hd_table,
+                  const char *boot_device,
+                  BusState *ide0, BusState *ide1,
                   FDCtrl *floppy_controller, ISADevice *s);
 void pc_pci_device_init(PCIBus *pci_bus);
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index f670fd7a783c52a47c0b182f04f29e3b5995b8f0..519e8a5ccb2e8c22c0e2fb3fa801fcb41b5c0962 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -79,6 +79,7 @@ static void pc_init1(ram_addr_t ram_size,
     IsaIrqState *isa_irq_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     FDCtrl *floppy_controller;
+    BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
 
     pc_cpus_init(cpu_model);
@@ -132,18 +133,23 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        PCIDevice *dev;
+        dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
+        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
-	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+            ISADevice *dev;
+            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
         }
     }
 
     pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
 
-    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
-                 floppy_controller, rtc_state);
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                 idebus[0], idebus[1], floppy_controller, rtc_state);
 
     if (pci_enabled && usb_enabled) {
         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);