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, §ors); + 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, §ors); - 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);