aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ide.h2
-rw-r--r--hw/ide/qdev.c7
-rw-r--r--hw/pc.c94
-rw-r--r--hw/pc.h3
-rw-r--r--hw/pc_piix.c16
5 files changed, 81 insertions, 41 deletions
diff --git a/hw/ide.h b/hw/ide.h
index 82b3c11283..2b5ae7c39e 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 b34c473336..2977a168e5 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 25ebafac80..b577fb1bc6 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 ccfd7add99..63b0249f2f 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 f670fd7a78..519e8a5ccb 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);