qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Write cmos hd data for ide drives using -device par


From: Bruce Rogers
Subject: [Qemu-devel] [PATCH] Write cmos hd data for ide drives using -device parm
Date: Sat, 10 Apr 2010 10:36:03 -0600

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.


This is important for older guests, such as Windows XP, and Windows

Server 2003.


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.


Signed-off-by: Bruce Rogers <address@hidden>


Bruce


 hw/ide/internal.h |    1

 hw/ide/piix.c     |    2 +

 hw/ide/qdev.c     |    9 ++++++-

 hw/pc.c           |   68 ++++++++++++++++++++++++++++++++----------------------

 sysemu.h          |    1

 vl.c              |    6 ++++

 6 files changed, 59 insertions(+), 28 deletions(-)



diff --git a/hw/ide/internal.h b/hw/ide/internal.h

index 027029e..b04232c 100644

--- a/hw/ide/internal.h

+++ b/hw/ide/internal.h

@@ -450,6 +450,7 @@ struct IDEBus {

     IDEState ifs[2];

     uint8_t unit;

     uint8_t cmd;

+    uint8_t id;

     qemu_irq irq;

 };

 

diff --git a/hw/ide/piix.c b/hw/ide/piix.c

index 295a93d..f62aadb 100644

--- a/hw/ide/piix.c

+++ b/hw/ide/piix.c

@@ -136,6 +136,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)

     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;

diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c

index b18693d..632eccd 100644

--- a/hw/ide/qdev.c

+++ b/hw/ide/qdev.c

@@ -39,6 +39,7 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)

     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->conf.dinfo) {

         fprintf(stderr, "%s: no drive specified\n", qdev->info->name);

@@ -65,7 +66,13 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)

     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;

diff --git a/hw/pc.c b/hw/pc.c

index 69e597f..29f47d4 100644

--- a/hw/pc.c

+++ b/hw/pc.c

@@ -215,6 +215,44 @@ static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)

     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)

 {

@@ -338,37 +376,11 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,

 

     /* 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)

@@ -820,6 +832,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;

diff --git a/sysemu.h b/sysemu.h

index d0effa0..564d477 100644

--- a/sysemu.h

+++ b/sysemu.h

@@ -242,5 +242,6 @@ void usb_info(Monitor *mon);

 void rtc_change_mon_event(struct tm *tm);

 

 void register_devices(void);

+extern void (*machine_ide_finalize)(DriveInfo *dinfo);

 

 #endif

diff --git a/vl.c b/vl.c

index ea79ac4..8ab3349 100644

--- a/vl.c

+++ b/vl.c

@@ -228,6 +228,7 @@ int ctrl_grab = 0;

 unsigned int nb_prom_envs = 0;

 const char *prom_envs[MAX_PROM_ENVS];

 int boot_menu;

+void (*machine_ide_finalize)(DriveInfo *dinfo);

 

 int nb_numa_nodes;

 uint64_t node_mem[MAX_NODES];

@@ -275,6 +276,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");

@@ -2624,6 +2629,7 @@ int main(int argc, char **argv, char **envp)

 

     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;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]