Patchwork [RFC,v1,13/20] piix3, ich9: create pit through composition

login
register
mail settings
Submitter Hu Tao
Date May 22, 2013, 5:33 a.m.
Message ID <620c8720b238ce4c75825d8ec9a33f772d1954c4.1369193012.git.hutao@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/245520/
State New
Headers show

Comments

Hu Tao - May 22, 2013, 5:33 a.m.
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
---
 hw/i386/pc.c             | 16 +---------------
 hw/isa/lpc_ich9.c        | 30 ++++++++++++++++++++++++++++++
 hw/pci-host/piix.c       | 32 ++++++++++++++++++++++++++++++++
 include/hw/i386/ich9.h   |  1 +
 include/hw/timer/i8254.h |  3 +++
 5 files changed, 67 insertions(+), 15 deletions(-)

Patch

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 97bfad4..8438d0f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1128,9 +1128,8 @@  void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 {
     int i;
     DriveInfo *fd[MAX_FD];
-    DeviceState *hpet = NULL;
     qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
+    ISADevice *i8042, *port92, *vmmouse;
     qemu_irq *cpu_exit_irq;
     MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
     MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
@@ -1141,19 +1140,6 @@  void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
     memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
     memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
 
-    if (!xen_enabled()) {
-        if (kvm_irqchip_in_kernel()) {
-            pit = kvm_pit_init(isa_bus, 0x40);
-        } else {
-            pit = pit_init(isa_bus, 0x40, 0, NULL);
-        }
-        if (hpet) {
-            /* connect PIT to output control line of the HPET */
-            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
-        }
-        pcspk_init(isa_bus, pit);
-    }
-
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
             serial_isa_init(isa_bus, i, serial_hds[i]);
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index c50795a..42f60b9 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -46,6 +46,8 @@ 
 #include "sysemu/sysemu.h"
 #include "hw/timer/hpet.h"
 #include "hw/timer/mc146818rtc.h"
+#include "hw/audio/pcspk.h"
+#include "hw/timer/i8254.h"
 
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
 
@@ -530,6 +532,7 @@  static int ich9_lpc_realize(PCIDevice *d)
 {
     ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
     qemu_irq rtc_irq;
+    qemu_irq pit_irq = NULL;
     ISABus *isa_bus;
 
     isa_bus = isa_bus_new(&d->qdev, get_system_io());
@@ -572,12 +575,31 @@  static int ich9_lpc_realize(PCIDevice *d)
             sysbus_connect_irq(SYS_BUS_DEVICE(lpc->hpet), i, lpc->pic[i]);
         }
         rtc_irq = qdev_get_gpio_in(lpc->hpet, HPET_LEGACY_RTC_INT);
+        pit_irq = qdev_get_gpio_in(lpc->hpet, HPET_LEGACY_PIT_INT);
     } else {
         isa_init_irq(lpc->rtc, &rtc_irq, RTC_ISA_IRQ);
     }
 
     rtc_set_irq(lpc->rtc, rtc_irq);
 
+    /* Realize the PIT */
+    qdev_set_parent_bus(DEVICE(lpc->pit), BUS(lpc->isa_bus));
+    qdev_init_nofail(DEVICE(lpc->pit));
+
+    if (!pit_irq) {
+        pit_irq = isa_get_irq(lpc->pit, 0);
+    }
+    if (!kvm_irqchip_in_kernel()) {
+        qdev_connect_gpio_out(DEVICE(lpc->pit), 0, pit_irq);
+    }
+    if (lpc->hpet) {
+        qdev_connect_gpio_out(DEVICE(lpc->hpet), 0,
+                              qdev_get_gpio_in(DEVICE(lpc->pit), 0));
+    }
+
+    /* FIXME this should be refactored */
+    pcspk_init(lpc->isa_bus, lpc->pit);
+
     return 0;
 }
 
@@ -639,6 +661,14 @@  static void ich9_lpc_initfn(Object *obj)
     s->rtc = ISA_DEVICE(object_new(TYPE_MC146818_RTC));
     qdev_prop_set_int32(DEVICE(s->rtc), "base_year", 2000);
     object_property_add_child(obj, "rtc", OBJECT(s->rtc), NULL);
+
+    if (kvm_irqchip_in_kernel()) {
+        s->pit = ISA_DEVICE(object_new(TYPE_KVM_PIT));
+    } else {
+        s->pit = ISA_DEVICE(object_new(TYPE_PIT));
+    }
+    object_property_add_child(obj, "pit", OBJECT(s->pit), NULL);
+    qdev_prop_set_uint32(DEVICE(s->pit), "iobase", 0x40);
 }
 
 static void ich9_lpc_class_init(ObjectClass *klass, void *data)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 60b16d8..f3f3856 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -34,6 +34,8 @@ 
 #include "sysemu/sysemu.h"
 #include "hw/timer/hpet.h"
 #include "hw/timer/mc146818rtc.h"
+#include "hw/audio/pcspk.h"
+#include "hw/timer/i8254.h"
 
 /*
  * I440FX chipset data sheet.
@@ -74,6 +76,7 @@  typedef struct PIIX3State {
     ISABus *bus;
     DeviceState *hpet;
     ISADevice *rtc;
+    ISADevice *pit;
 
     qemu_irq *pic;
 
@@ -581,6 +584,7 @@  static const MemoryRegionOps rcr_ops = {
 static int piix3_realize(PCIDevice *dev)
 {
     PIIX3State *s = PIIX3(dev);
+    qemu_irq pit_irq = NULL;
     qemu_irq rtc_irq;
 
     s->bus = isa_bus_new(DEVICE(s), pci_address_space_io(dev));
@@ -603,12 +607,32 @@  static int piix3_realize(PCIDevice *dev)
             sysbus_connect_irq(SYS_BUS_DEVICE(s->hpet), i, s->pic[i]);
         }
         rtc_irq = qdev_get_gpio_in(s->hpet, HPET_LEGACY_RTC_INT);
+        pit_irq = qdev_get_gpio_in(s->hpet, HPET_LEGACY_PIT_INT);
     } else {
         isa_init_irq(s->rtc, &rtc_irq, RTC_ISA_IRQ);
     }
 
     rtc_set_irq(s->rtc, rtc_irq);
 
+    /* Realize the PIT */
+    qdev_set_parent_bus(DEVICE(s->pit), BUS(s->bus));
+    qdev_init_nofail(DEVICE(s->pit));
+
+    if (!pit_irq) {
+        pit_irq = isa_get_irq(s->pit, 0);
+    }
+    if (!kvm_irqchip_in_kernel()) {
+        qdev_connect_gpio_out(DEVICE(s->pit), 0, pit_irq);
+    }
+
+    if (s->hpet) {
+        qdev_connect_gpio_out(DEVICE(s->hpet), 0,
+                              qdev_get_gpio_in(DEVICE(s->pit), 0));
+    }
+
+    /* FIXME this should be refactored */
+    pcspk_init(s->bus, s->pit);
+
     memory_region_init_io(&s->rcr_mem, &rcr_ops, s, "piix3-reset-control", 1);
     memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
                                         &s->rcr_mem, 1);
@@ -634,6 +658,14 @@  static void piix3_initfn(Object *obj)
     s->rtc = ISA_DEVICE(object_new(TYPE_MC146818_RTC));
     qdev_prop_set_int32(DEVICE(s->rtc), "base_year", 2000);
     object_property_add_child(obj, "rtc", OBJECT(s->rtc), NULL);
+
+    if (kvm_irqchip_in_kernel()) {
+        s->pit = ISA_DEVICE(object_new(TYPE_KVM_PIT));
+    } else {
+        s->pit = ISA_DEVICE(object_new(TYPE_PIT));
+    }
+    object_property_add_child(obj, "pit", OBJECT(s->pit), NULL);
+    qdev_prop_set_uint32(DEVICE(s->pit), "iobase", 0x40);
 }
 
 static void piix3_class_init(ObjectClass *klass, void *data)
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index 1d9f26a..14ceafb 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -64,6 +64,7 @@  typedef struct ICH9LPCState {
 
     DeviceState *hpet;
     ISADevice *rtc;
+    ISADevice *pit;
 
     qemu_irq *pic;
     qemu_irq *ioapic;
diff --git a/include/hw/timer/i8254.h b/include/hw/timer/i8254.h
index 75bb530..10da2ea 100644
--- a/include/hw/timer/i8254.h
+++ b/include/hw/timer/i8254.h
@@ -30,6 +30,9 @@ 
 
 #define PIT_FREQ 1193182
 
+#define TYPE_PIT      "isa-pit"
+#define TYPE_KVM_PIT  "kvm-pit"
+
 typedef struct PITChannelInfo {
     int gate;
     int mode;