Patchwork [04/20,MIPS] rc4030: convert to qdev

login
register
mail settings
Submitter Hervé Poussineau
Date Aug. 1, 2010, 5:37 p.m.
Message ID <1280684242-19611-4-git-send-email-hpoussin@reactos.org>
Download mbox | patch
Permalink /patch/60471/
State New
Headers show

Comments

Hervé Poussineau - Aug. 1, 2010, 5:37 p.m.
rc4030_init() function will be removed later, once all rc4030 devices are converted to qdev

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
 hw/mips.h      |    9 ---
 hw/mips_jazz.c |    3 +-
 hw/rc4030.c    |  170 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 hw/rc4030.h    |   41 ++++++++++++++
 4 files changed, 199 insertions(+), 24 deletions(-)
 create mode 100644 hw/rc4030.h

Patch

diff --git a/hw/mips.h b/hw/mips.h
index 617ea10..55fb701 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -23,15 +23,6 @@  void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
 /* jazz_led.c */
 extern void jazz_led_init(target_phys_addr_t base);
 
-/* rc4030.c */
-typedef struct rc4030DMAState *rc4030_dma;
-void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
-void rc4030_dma_read(void *dma, uint8_t *buf, int len);
-void rc4030_dma_write(void *dma, uint8_t *buf, int len);
-
-void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas);
-
 /* dp8393x.c */
 void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
                   qemu_irq irq, void* mem_opaque,
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 78ef8f0..c000fd3 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -36,6 +36,7 @@ 
 #include "mips-bios.h"
 #include "loader.h"
 #include "mc146818rtc.h"
+#include "rc4030.h"
 
 enum jazz_model_e
 {
@@ -178,7 +179,7 @@  void mips_jazz_init (ram_addr_t ram_size,
     }
 
     /* Chipset */
-    rc4030_opaque = rc4030_init(qdev_get_gpio_in(cpu->parent, 6), qdev_get_gpio_in(cpu->parent, 3), &rc4030, &dmas);
+    rc4030_opaque = rc4030_init(cpu, &rc4030, &dmas);
     s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
     cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
 
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2231373..3c8cdfa 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -23,8 +23,12 @@ 
  */
 
 #include "hw.h"
-#include "mips.h"
+#include "monitor.h"
 #include "qemu-timer.h"
+#include "rc4030.h"
+
+/* As long as we can't include mips_cpudevs.h ... */
+void cpu_mips_register(DeviceInfo *info);
 
 /********************************************************/
 /* debug rc4030 */
@@ -47,6 +51,13 @@  do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } whi
 /********************************************************/
 /* rc4030 emulation                                     */
 
+struct RC4030Bus {
+    BusState qbus;
+    rc4030_dma *dmas;
+    uint32_t assigned;
+};
+static RC4030Bus *rc4030bus;
+
 typedef struct dma_pagetable_entry {
     int32_t frame;
     int32_t owner;
@@ -65,6 +76,9 @@  typedef struct dma_pagetable_entry {
 
 typedef struct rc4030State
 {
+    DeviceState busdev;
+    RC4030Bus bus;
+
     uint32_t config; /* 0x0000: RC4030 config register */
     uint32_t revision; /* 0x0008: RC4030 Revision register */
     uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
@@ -461,7 +475,8 @@  static void update_jazz_irq(rc4030State *s)
 
 static void rc4030_irq_jazz_request(void *opaque, int irq, int level)
 {
-    rc4030State *s = opaque;
+    DeviceState *dev = opaque;
+    rc4030State *s = container_of(dev, rc4030State, busdev);
 
     if (level) {
         s->isr_jazz |= 1 << irq;
@@ -585,9 +600,9 @@  static CPUWriteMemoryFunc * const jazzio_write[3] = {
     jazzio_writel,
 };
 
-static void rc4030_reset(void *opaque)
+static void rc4030_reset(DeviceState *d)
 {
-    rc4030State *s = opaque;
+    rc4030State *s = container_of(d, rc4030State, busdev);
     int i;
 
     s->config = 0x410; /* some boards seem to accept 0x104 too */
@@ -797,29 +812,156 @@  static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
     return s;
 }
 
-void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
-                  qemu_irq **irqs, rc4030_dma **dmas)
+void *rc4030_get_opaque(void)
 {
     rc4030State *s;
+
+    if (!rc4030bus) {
+        hw_error("Tried to get rc4030 pointer with no rc4030 bus present.\n");
+    }
+    s = container_of(rc4030bus, rc4030State, bus);
+
+    return s;
+}
+
+rc4030_dma rc4030_get_dma(int dma)
+{
+    if (!rc4030bus) {
+        hw_error("Tried to get rc4030 dma channel %d with no rc4030 bus present.\n",
+                 dma);
+    }
+    return rc4030bus->dmas[dma];
+}
+
+static void rc4030bus_dev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+    RC4030Device *d = DO_UPCAST(RC4030Device, qdev, dev);
+
+    if (d->rc4030irq[1] != -1) {
+        monitor_printf(mon, "%*src4030 irqs %d,%d\n", indent, "",
+                       d->rc4030irq[0], d->rc4030irq[1]);
+    } else if (d->rc4030irq[0] != -1) {
+        monitor_printf(mon, "%*src4030 irq %d\n", indent, "",
+                       d->rc4030irq[0]);
+    }
+}
+
+static struct BusInfo rc4030_bus_info = {
+    .name      = "rc4030",
+    .size      = sizeof(RC4030Bus),
+    .print_dev = rc4030bus_dev_print,
+};
+
+static int rc4030_init1(DeviceState *dev, DeviceInfo *base)
+{
+    rc4030State *s = container_of(dev, rc4030State, busdev);
     int s_chipset, s_jazzio;
 
-    s = qemu_mallocz(sizeof(rc4030State));
+    if (rc4030bus) {
+        return 1;
+    }
 
-    *irqs = qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
-    *dmas = rc4030_allocate_dmas(s, 4);
+    qbus_create_inplace(&s->bus.qbus, &rc4030_bus_info, dev, NULL);
+    qdev_init_gpio_in(dev, rc4030_irq_jazz_request, 16);
+    s->bus.dmas = rc4030_allocate_dmas(s, 4);
 
     s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
-    s->timer_irq = timer;
-    s->jazz_bus_irq = jazz_bus;
+    s->timer_irq = qdev_get_gpio_in(qdev_get_parent_bus(dev)->parent, 6);
+    s->jazz_bus_irq = qdev_get_gpio_in(qdev_get_parent_bus(dev)->parent, 3);
 
-    qemu_register_reset(rc4030_reset, s);
     register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
-    rc4030_reset(s);
 
     s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
     cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
     s_jazzio = cpu_register_io_memory(jazzio_read, jazzio_write, s);
     cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
 
-    return s;
+    rc4030bus = &s->bus;
+
+    return 0;
+}
+
+void rc4030_init_irq(RC4030Device *dev, qemu_irq *p, int rc4030irq)
+{
+    assert(dev->nirqs < ARRAY_SIZE(dev->rc4030irq));
+    if (rc4030bus->assigned & (1 << rc4030irq)) {
+        RC4030_ERROR("rc4030 irq %d already assigned\n", rc4030irq);
+        exit(1);
+    }
+    rc4030bus->assigned |= (1 << rc4030irq);
+    dev->rc4030irq[dev->nirqs] = rc4030irq;
+    *p = qdev_get_gpio_in(rc4030bus->qbus.parent, rc4030irq);
+    dev->nirqs++;
 }
+
+static int rc4030_qdev_init(DeviceState *qdev, DeviceInfo *base)
+{
+    RC4030Device *dev = DO_UPCAST(RC4030Device, qdev, qdev);
+    RC4030DeviceInfo *info = DO_UPCAST(RC4030DeviceInfo, qdev, base);
+
+    dev->rc4030irq[0] = -1;
+    dev->rc4030irq[1] = -1;
+
+    return info->init(dev);
+}
+
+void rc4030_qdev_register(RC4030DeviceInfo *info)
+{
+    info->qdev.init = rc4030_qdev_init;
+    info->qdev.bus_info = &rc4030_bus_info;
+    qdev_register(&info->qdev);
+}
+
+RC4030Device *rc4030_create(const char *name)
+{
+    DeviceState *dev;
+
+    if (!rc4030bus) {
+        hw_error("Tried to create rc4030 device %s with no rc4030 bus present.\n",
+                 name);
+    }
+    dev = qdev_create(&rc4030bus->qbus, name);
+    return DO_UPCAST(RC4030Device, qdev, dev);
+}
+
+RC4030Device *rc4030_create_simple(const char *name)
+{
+    RC4030Device *dev;
+
+    dev = rc4030_create(name);
+    qdev_init_nofail(&dev->qdev);
+    return dev;
+}
+
+extern struct BusInfo cpu_bus_info;
+static DeviceInfo rc4030_info = {
+    .name    = "rc4030",
+    .size    = sizeof(rc4030State),
+    .reset   = rc4030_reset,
+    .init    = rc4030_init1,
+};
+
+static void rc4030_register_devices(void)
+{
+    cpu_mips_register(&rc4030_info);
+}
+
+device_init(rc4030_register_devices)
+
+void *rc4030_init(BusState *bus,
+                  qemu_irq **irqs, rc4030_dma **dmas)
+{
+    DeviceState *dev;
+    rc4030State* rc4030;
+
+    dev = qdev_create(bus, "rc4030");
+    qdev_init_nofail(dev);
+
+    rc4030 = DO_UPCAST(rc4030State, busdev, dev);
+
+    *irqs = rc4030->busdev.gpio_in;
+    *dmas = rc4030->bus.dmas;
+
+    return rc4030;
+}
+
diff --git a/hw/rc4030.h b/hw/rc4030.h
new file mode 100644
index 0000000..58522f3
--- /dev/null
+++ b/hw/rc4030.h
@@ -0,0 +1,41 @@ 
+#ifndef HW_RC4030_H
+#define HW_RC4030_H
+
+/* RC4030 bus */
+
+#include "qdev.h"
+
+typedef struct RC4030Bus RC4030Bus;
+typedef struct RC4030Device RC4030Device;
+typedef struct RC4030DeviceInfo RC4030DeviceInfo;
+
+struct RC4030Device {
+    DeviceState qdev;
+    uint32_t rc4030irq[2];
+    int nirqs;
+};
+
+typedef int (*rc4030_qdev_initfn)(RC4030Device *dev);
+struct RC4030DeviceInfo {
+    DeviceInfo qdev;
+    rc4030_qdev_initfn init;
+};
+
+void rc4030_init_irq(RC4030Device *dev, qemu_irq *p, int rc4030irq);
+void rc4030_qdev_register(RC4030DeviceInfo *info);
+RC4030Device *rc4030_create(const char *name);
+RC4030Device *rc4030_create_simple(const char *name);
+
+typedef struct rc4030DMAState *rc4030_dma;
+void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
+void rc4030_dma_read(void *dma, uint8_t *buf, int len);
+void rc4030_dma_write(void *dma, uint8_t *buf, int len);
+
+void *rc4030_get_opaque(void);
+rc4030_dma rc4030_get_dma(int dma);
+
+/* Non-qdev compatibility stuff... */
+void *rc4030_init(BusState *parent,
+                  qemu_irq **irqs, rc4030_dma **dmas);
+
+#endif