Patchwork [19/22] i8259: Convert to qdev

login
register
mail settings
Submitter Jan Kiszka
Date Sept. 28, 2011, 11:01 a.m.
Message ID <f72274fd2d05f546e961f1ced86c9bde7a9e712a.1317207666.git.jan.kiszka@siemens.com>
Download mbox | patch
Permalink /patch/116761/
State New
Headers show

Comments

Jan Kiszka - Sept. 28, 2011, 11:01 a.m.
This key cleanup step requires to move the IRQ debugging bit from
i8259_set_irq directly to the per-PIC pic_set_irq, to pass the PIC
parameters (I/O base, ELCR address and mask, master/slave mode) as
qdev properties, and to interconnect the PICs with their environment via
GPIO pins.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/i8259.c |  158 ++++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 100 insertions(+), 58 deletions(-)

Patch

diff --git a/hw/i8259.c b/hw/i8259.c
index cf0c6ed..ae6f784 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -41,6 +41,7 @@ 
 //#define DEBUG_IRQ_COUNT
 
 struct PicState {
+    ISADevice dev;
     uint8_t last_irr; /* edge detection */
     uint8_t irr; /* interrupt request register */
     uint8_t imr; /* interrupt mask register */
@@ -58,8 +59,10 @@  struct PicState {
     uint8_t single_mode; /* true if slave pic is not initialized */
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
-    qemu_irq int_out;
-    bool master; /* reflects /SP input pin */
+    qemu_irq int_out[1];
+    uint32_t master; /* reflects /SP input pin */
+    uint32_t iobase;
+    uint32_t elcr_addr;
     MemoryRegion base_io;
     MemoryRegion elcr_io;
 };
@@ -70,6 +73,9 @@  static int irq_level[16];
 #ifdef DEBUG_IRQ_COUNT
 static uint64_t irq_count[16];
 #endif
+#ifdef DEBUG_IRQ_LATENCY
+static int64_t irq_time[16];
+#endif
 PicState *isa_pic;
 static PicState *slave_pic;
 
@@ -122,17 +128,39 @@  static void pic_update_irq(PicState *s)
     if (irq >= 0) {
         DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
                 s->master ? 0 : 1, s->imr, s->irr, s->priority_add);
-        qemu_irq_raise(s->int_out);
+        qemu_irq_raise(s->int_out[0]);
     } else {
-        qemu_irq_lower(s->int_out);
+        qemu_irq_lower(s->int_out[0]);
     }
 }
 
 /* set irq level. If an edge is detected, then the IRR is set to 1 */
-static void pic_set_irq1(PicState *s, int irq, int level)
+static void pic_set_irq(void *opaque, int irq, int level)
 {
-    int mask;
-    mask = 1 << irq;
+    PicState *s = opaque;
+    int mask = 1 << irq;
+
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) || \
+    defined(DEBUG_IRQ_LATENCY)
+    int irq_index = s->master ? irq : irq + 8;
+#endif
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
+    if (level != irq_level[irq_index]) {
+        DPRINTF("pic_set_irq: irq=%d level=%d\n", irq_index, level);
+        irq_level[irq_index] = level;
+#ifdef DEBUG_IRQ_COUNT
+        if (level == 1) {
+            irq_count[irq_index]++;
+        }
+#endif
+    }
+#endif
+#ifdef DEBUG_IRQ_LATENCY
+    if (level) {
+        irq_time[irq_index] = qemu_get_clock_ns(vm_clock);
+    }
+#endif
+
     if (s->elcr & mask) {
         /* level triggered */
         if (level) {
@@ -156,32 +184,6 @@  static void pic_set_irq1(PicState *s, int irq, int level)
     pic_update_irq(s);
 }
 
-#ifdef DEBUG_IRQ_LATENCY
-int64_t irq_time[16];
-#endif
-
-static void i8259_set_irq(void *opaque, int irq, int level)
-{
-    PicState *s = irq <= 7 ? isa_pic : slave_pic;
-
-#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
-    if (level != irq_level[irq]) {
-        DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
-        irq_level[irq] = level;
-#ifdef DEBUG_IRQ_COUNT
-	if (level == 1)
-	    irq_count[irq]++;
-#endif
-    }
-#endif
-#ifdef DEBUG_IRQ_LATENCY
-    if (level) {
-        irq_time[irq] = qemu_get_clock_ns(vm_clock);
-    }
-#endif
-    pic_set_irq1(s, irq & 7, level);
-}
-
 /* acknowledge interrupt 'irq' */
 static void pic_intack(PicState *s, int irq)
 {
@@ -237,9 +239,9 @@  int pic_read_irq(PicState *s)
     return intno;
 }
 
-static void pic_reset(void *opaque)
+static void pic_reset(DeviceState *dev)
 {
-    PicState *s = opaque;
+    PicState *s = container_of(dev, PicState, dev.qdev);
 
     s->last_irr = 0;
     s->irr = 0;
@@ -272,7 +274,7 @@  static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
     if (addr == 0) {
         if (val & 0x10) {
             /* init */
-            pic_reset(s);
+            pic_reset(&s->dev.qdev);
             s->init_state = 1;
             s->init4 = val & 1;
             s->single_mode = val & 2;
@@ -443,22 +445,22 @@  static const MemoryRegionOps pic_elcr_ioport_ops = {
 };
 
 /* XXX: add generic master/slave system */
-static void pic_init(int io_addr, int elcr_addr, PicState *s, qemu_irq int_out,
-                     bool master)
+static int pic_initfn(ISADevice *dev)
 {
-    s->int_out = int_out;
-    s->master = master;
+    PicState *s = DO_UPCAST(PicState, dev, dev);
 
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
 
-    isa_register_ioport(NULL, &s->base_io, io_addr);
-    if (elcr_addr >= 0) {
-        isa_register_ioport(NULL, &s->elcr_io, elcr_addr);
-    }
+    isa_register_ioport(NULL, &s->base_io, s->iobase);
+    isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
+
+    qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out));
+    qdev_init_gpio_in(&dev->qdev, pic_set_irq, 8);
 
-    vmstate_register(NULL, io_addr, &vmstate_pic, s);
-    qemu_register_reset(pic_reset, s);
+    qdev_set_legacy_instance_id(&dev->qdev, s->iobase, 1);
+
+    return 0;
 }
 
 void pic_info(Monitor *mon)
@@ -498,20 +500,60 @@  void irq_info(Monitor *mon)
 
 qemu_irq *i8259_init(qemu_irq parent_irq)
 {
-    qemu_irq *irqs;
-    PicState *s;
+    qemu_irq *irq_set;
+    ISADevice *dev;
+    int i;
 
-    irqs = qemu_allocate_irqs(i8259_set_irq, NULL, 16);
+    irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
 
-    s = g_malloc0(sizeof(PicState));
-    pic_init(0x20, 0x4d0, s, parent_irq, true);
-    s->elcr_mask = 0xf8;
-    isa_pic = s;
+    dev = isa_create("isa-i8259");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
+    qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
+    qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
+    qdev_prop_set_bit(&dev->qdev, "master", true);
+    qdev_init_nofail(&dev->qdev);
 
-    s = g_malloc0(sizeof(PicState));
-    pic_init(0xa0, 0x4d1, s, irqs[2], false);
-    s->elcr_mask = 0xde;
-    slave_pic = s;
+    qdev_connect_gpio_out(&dev->qdev, 0, parent_irq);
+    for (i = 0 ; i < 8; i++) {
+        irq_set[i] = qdev_get_gpio_in(&dev->qdev, i);
+    }
+
+    isa_pic = DO_UPCAST(PicState, dev, dev);
+
+    dev = isa_create("isa-i8259");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
+    qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1);
+    qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde);
+    qdev_init_nofail(&dev->qdev);
+
+    qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]);
+    for (i = 0 ; i < 8; i++) {
+        irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i);
+    }
+
+    slave_pic = DO_UPCAST(PicState, dev, dev);
 
-    return irqs;
+    return irq_set;
+}
+
+static ISADeviceInfo i8259_info = {
+    .qdev.name     = "isa-i8259",
+    .qdev.size     = sizeof(PicState),
+    .qdev.vmsd     = &vmstate_pic,
+    .qdev.reset    = pic_reset,
+    .qdev.no_user  = 1,
+    .init          = pic_initfn,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_HEX32("iobase", PicState, iobase,  -1),
+        DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr,  -1),
+        DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask,  -1),
+        DEFINE_PROP_BIT("master", PicState, master,  0, false),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void pic_register(void)
+{
+    isa_qdev_register(&i8259_info);
 }
+device_init(pic_register)