]> git.proxmox.com Git - qemu.git/blobdiff - hw/pl190.c
cpu: Move halted and interrupt_request fields to CPUState
[qemu.git] / hw / pl190.c
index 17c279bed778bbc19a95412da5f908260e6cc2b7..9610673d946fd2d8240effef3645920b38c99c92 100644 (file)
@@ -4,10 +4,10 @@
  * Copyright (c) 2006 CodeSourcery.
  * Written by Paul Brook
  *
- * This code is licenced under the GPL.
+ * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* The number of virtual priority levels.  16 user vectors plus the
    unvectored IRQ.  Chained interrupts would require an additional level
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t level;
     uint32_t soft_level;
     uint32_t irq_enable;
     uint32_t fiq_select;
-    uint32_t default_addr;
     uint8_t vect_control[16];
     uint32_t vect_addr[PL190_NUM_PRIO];
     /* Mask containing interrupts with higher priority than this one.  */
@@ -85,7 +85,8 @@ static void pl190_update_vectors(pl190_state *s)
     pl190_update(s);
 }
 
-static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
+static uint64_t pl190_read(void *opaque, hwaddr offset,
+                           unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
     int i;
@@ -116,12 +117,18 @@ static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
         return s->protected;
     case 12: /* VECTADDR */
         /* Read vector address at the start of an ISR.  Increases the
-           current priority level to that of the current interrupt.  */
-        for (i = 0; i < s->priority; i++)
-          {
-            if ((s->level | s->soft_level) & s->prio_mask[i])
-              break;
-          }
+         * current priority level to that of the current interrupt.
+         *
+         * Since an enabled interrupt X at priority P causes prio_mask[Y]
+         * to have bit X set for all Y > P, this loop will stop with
+         * i == the priority of the highest priority set interrupt.
+         */
+        for (i = 0; i < s->priority; i++) {
+            if ((s->level | s->soft_level) & s->prio_mask[i + 1]) {
+                break;
+            }
+        }
+
         /* Reading this value with no pending interrupts is undefined.
            We return the default address.  */
         if (i == PL190_NUM_PRIO)
@@ -136,12 +143,14 @@ static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
     case 13: /* DEFVECTADDR */
         return s->vect_addr[16];
     default:
-        hw_error("pl190_read: Bad offset %x\n", (int)offset);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "pl190_read: Bad offset %x\n", (int)offset);
         return 0;
     }
 }
 
-static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+static void pl190_write(void *opaque, hwaddr offset,
+                        uint64_t val, unsigned size)
 {
     pl190_state *s = (pl190_state *)opaque;
 
@@ -186,30 +195,25 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
             s->priority = s->prev_prio[s->priority];
         break;
     case 13: /* DEFVECTADDR */
-        s->default_addr = val;
+        s->vect_addr[16] = val;
         break;
     case 0xc0: /* ITCR */
         if (val) {
-            hw_error("pl190: Test mode not implemented\n");
+            qemu_log_mask(LOG_UNIMP, "pl190: Test mode not implemented\n");
         }
         break;
     default:
-        hw_error("pl190_write: Bad offset %x\n", (int)offset);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                     "pl190_write: Bad offset %x\n", (int)offset);
         return;
     }
     pl190_update(s);
 }
 
-static CPUReadMemoryFunc * const pl190_readfn[] = {
-   pl190_read,
-   pl190_read,
-   pl190_read
-};
-
-static CPUWriteMemoryFunc * const pl190_writefn[] = {
-   pl190_write,
-   pl190_write,
-   pl190_write
+static const MemoryRegionOps pl190_ops = {
+    .read = pl190_read,
+    .write = pl190_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pl190_reset(DeviceState *d)
@@ -231,12 +235,9 @@ static void pl190_reset(DeviceState *d)
 static int pl190_init(SysBusDevice *dev)
 {
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(pl190_readfn,
-                                       pl190_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pl190_ops, s, "pl190", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
     qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
@@ -252,7 +253,6 @@ static const VMStateDescription vmstate_pl190 = {
         VMSTATE_UINT32(soft_level, pl190_state),
         VMSTATE_UINT32(irq_enable, pl190_state),
         VMSTATE_UINT32(fiq_select, pl190_state),
-        VMSTATE_UINT32(default_addr, pl190_state),
         VMSTATE_UINT8_ARRAY(vect_control, pl190_state, 16),
         VMSTATE_UINT32_ARRAY(vect_addr, pl190_state, PL190_NUM_PRIO),
         VMSTATE_UINT32_ARRAY(prio_mask, pl190_state, PL190_NUM_PRIO+1),
@@ -263,18 +263,27 @@ static const VMStateDescription vmstate_pl190 = {
     }
 };
 
-static SysBusDeviceInfo pl190_info = {
-    .init = pl190_init,
-    .qdev.name = "pl190",
-    .qdev.size = sizeof(pl190_state),
-    .qdev.vmsd = &vmstate_pl190,
-    .qdev.reset = pl190_reset,
-    .qdev.no_user = 1,
+static void pl190_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pl190_init;
+    dc->no_user = 1;
+    dc->reset = pl190_reset;
+    dc->vmsd = &vmstate_pl190;
+}
+
+static const TypeInfo pl190_info = {
+    .name          = "pl190",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(pl190_state),
+    .class_init    = pl190_class_init,
 };
 
-static void pl190_register_devices(void)
+static void pl190_register_types(void)
 {
-    sysbus_register_withprop(&pl190_info);
+    type_register_static(&pl190_info);
 }
 
-device_init(pl190_register_devices)
+type_init(pl190_register_types)