diff options
-rw-r--r-- | hw/ide.h | 2 | ||||
-rw-r--r-- | hw/ide/qdev.c | 7 | ||||
-rw-r--r-- | hw/pc.c | 94 | ||||
-rw-r--r-- | hw/pc.h | 3 | ||||
-rw-r--r-- | hw/pc_piix.c | 16 |
5 files changed, 81 insertions, 41 deletions
@@ -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 b34c473..2977a16 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 { @@ -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, §ors); + 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, §ors); - 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) @@ -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 f670fd7..519e8a5 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); |