]> git.proxmox.com Git - mirror_qemu.git/commitdiff
sh_intc: convert interrupt controller to memory API
authorBenoît Canet <benoit.canet@gmail.com>
Thu, 17 Nov 2011 13:23:01 +0000 (14:23 +0100)
committerAvi Kivity <avi@redhat.com>
Thu, 24 Nov 2011 16:32:03 +0000 (18:32 +0200)
Signed-off-by: Benoit Canet <benoit.canet@gmail.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
hw/sh7750.c
hw/sh_intc.c
hw/sh_intc.h
target-sh4/helper.c

index c659756970a27399f135f477c4cd8be2b3534d38..20ac605be700c848ba8433ee934b81bc8691f134 100644 (file)
@@ -756,7 +756,7 @@ SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
                           "cache-and-tlb", 0x08000000);
     memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
 
-    sh_intc_init(&s->intc, NR_SOURCES,
+    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
                 _INTC_ARRAY(mask_registers),
                 _INTC_ARRAY(prio_registers));
 
index e07424f2a1651b2d9bb0b740ae0dad0006acca09..b24ec7758295b10cd4f6dabd022431da60feac05 100644 (file)
@@ -219,7 +219,8 @@ static void sh_intc_toggle_mask(struct intc_desc *desc, intc_enum id,
 #endif
 }
 
-static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t sh_intc_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -238,7 +239,7 @@ static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void sh_intc_write(void *opaque, target_phys_addr_t offset,
-                         uint32_t value)
+                          uint64_t value, unsigned size)
 {
     struct intc_desc *desc = opaque;
     intc_enum *enum_ids = NULL;
@@ -282,16 +283,10 @@ static void sh_intc_write(void *opaque, target_phys_addr_t offset,
 #endif
 }
 
-static CPUReadMemoryFunc * const sh_intc_readfn[] = {
-    sh_intc_read,
-    sh_intc_read,
-    sh_intc_read
-};
-
-static CPUWriteMemoryFunc * const sh_intc_writefn[] = {
-    sh_intc_write,
-    sh_intc_write,
-    sh_intc_write
+static const struct MemoryRegionOps sh_intc_ops = {
+    .read = sh_intc_read,
+    .write = sh_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
@@ -302,15 +297,36 @@ struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id)
     return NULL;
 }
 
-static void sh_intc_register(struct intc_desc *desc, 
-                            unsigned long address)
+static unsigned int sh_intc_register(MemoryRegion *sysmem,
+                             struct intc_desc *desc,
+                             const unsigned long address,
+                             const char *type,
+                             const char *action,
+                             const unsigned int index)
 {
-    if (address) {
-        cpu_register_physical_memory_offset(P4ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
-        cpu_register_physical_memory_offset(A7ADDR(address), 4,
-                                            desc->iomemtype, INTC_A7(address));
+    char name[60];
+    MemoryRegion *iomem, *iomem_p4, *iomem_a7;
+
+    if (!address) {
+        return 0;
     }
+
+    iomem = &desc->iomem;
+    iomem_p4 = desc->iomem_aliases + index;
+    iomem_a7 = iomem_p4 + 1;
+
+#define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s"
+    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4");
+    memory_region_init_alias(iomem_p4, name, iomem, INTC_A7(address), 4);
+    memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4);
+
+    snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7");
+    memory_region_init_alias(iomem_a7, name, iomem, INTC_A7(address), 4);
+    memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7);
+#undef SH_INTC_IOMEM_FORMAT
+
+    /* used to increment aliases index */
+    return 2;
 }
 
 static void sh_intc_register_source(struct intc_desc *desc,
@@ -415,14 +431,15 @@ void sh_intc_register_sources(struct intc_desc *desc,
     }
 }
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+         struct intc_desc *desc,
                 int nr_sources,
                 struct intc_mask_reg *mask_regs,
                 int nr_mask_regs,
                 struct intc_prio_reg *prio_regs,
                 int nr_prio_regs)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     desc->pending = 0;
     desc->nr_sources = nr_sources;
@@ -430,7 +447,12 @@ int sh_intc_init(struct intc_desc *desc,
     desc->nr_mask_regs = nr_mask_regs;
     desc->prio_regs = prio_regs;
     desc->nr_prio_regs = nr_prio_regs;
+    /* Allocate 4 MemoryRegions per register (2 actions * 2 aliases).
+     **/
+    desc->iomem_aliases = g_new0(MemoryRegion,
+                                 (nr_mask_regs + nr_prio_regs) * 4);
 
+    j = 0;
     i = sizeof(struct intc_source) * nr_sources;
     desc->sources = g_malloc0(i);
 
@@ -442,15 +464,19 @@ int sh_intc_init(struct intc_desc *desc,
 
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
  
-    desc->iomemtype = cpu_register_io_memory(sh_intc_readfn,
-                                            sh_intc_writefn, desc,
-                                             DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&desc->iomem, &sh_intc_ops, desc,
+                          "interrupt-controller", 0x100000000ULL);
+
+#define INT_REG_PARAMS(reg_struct, type, action, j) \
+        reg_struct->action##_reg, #type, #action, j
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
            struct intc_mask_reg *mr = desc->mask_regs + i;
 
-           sh_intc_register(desc, mr->set_reg);
-           sh_intc_register(desc, mr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(mr, mask, clr, j));
        }
     }
 
@@ -458,10 +484,13 @@ int sh_intc_init(struct intc_desc *desc,
         for (i = 0; i < desc->nr_prio_regs; i++) {
            struct intc_prio_reg *pr = desc->prio_regs + i;
 
-           sh_intc_register(desc, pr->set_reg);
-           sh_intc_register(desc, pr->clr_reg);
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, set, j));
+            j += sh_intc_register(sysmem, desc,
+                                  INT_REG_PARAMS(pr, prio, clr, j));
        }
     }
+#undef INT_REG_PARAMS
 
     return 0;
 }
index c117d6fb8c0bf6fe8468555233a46b9599c7c77d..80c943057788ade1ae9a8df8941c379ac44c9943 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "qemu-common.h"
 #include "irq.h"
+#include "exec-memory.h"
 
 typedef unsigned char intc_enum;
 
@@ -46,6 +47,8 @@ struct intc_source {
 };
 
 struct intc_desc {
+    MemoryRegion iomem;
+    MemoryRegion *iomem_aliases;
     qemu_irq *irqs;
     struct intc_source *sources;
     int nr_sources;
@@ -53,7 +56,6 @@ struct intc_desc {
     int nr_mask_regs;
     struct intc_prio_reg *prio_regs;
     int nr_prio_regs;
-    int iomemtype;
     int pending; /* number of interrupt sources that has pending set */
 };
 
@@ -68,7 +70,8 @@ void sh_intc_register_sources(struct intc_desc *desc,
                              struct intc_group *groups,
                              int nr_groups);
 
-int sh_intc_init(struct intc_desc *desc,
+int sh_intc_init(MemoryRegion *sysmem,
+                 struct intc_desc *desc,
                 int nr_sources,
                 struct intc_mask_reg *mask_regs,
                 int nr_mask_regs,
index 5a1e15e63da0a64e2c883c2bd305e6cb2eaf1edd..f4dda48dd19152428d22fb0a725a7b4319b4f99d 100644 (file)
 #include <signal.h>
 
 #include "cpu.h"
+
+#if !defined(CONFIG_USER_ONLY)
 #include "hw/sh_intc.h"
+#endif
 
 #if defined(CONFIG_USER_ONLY)