]> Git Repo - qemu.git/blobdiff - hw/pl190.c
tmp105: QOM'ify
[qemu.git] / hw / pl190.c
index e04e6c17fb9c89d0122764ec457db0f3630ac3e9..76ac159374ca87670938d922b93db157d0563e9a 100644 (file)
@@ -4,7 +4,7 @@
  * 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"
 
 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,34 +195,30 @@ 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 const MemoryRegionOps pl190_ops = {
+    .read = pl190_read,
+    .write = pl190_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const pl190_writefn[] = {
-   pl190_write,
-   pl190_write,
-   pl190_write
-};
-
-static void pl190_reset(pl190_state *s)
+static void pl190_reset(DeviceState *d)
 {
+  pl190_state *s = DO_UPCAST(pl190_state, busdev.qdev, d);
   int i;
 
   for (i = 0; i < 16; i++)
@@ -230,23 +235,55 @@ static void pl190_reset(pl190_state *s)
 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);
-    pl190_reset(s);
-    /* ??? Save/restore.  */
     return 0;
 }
 
-static void pl190_register_devices(void)
+static const VMStateDescription vmstate_pl190 = {
+    .name = "pl190",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(level, pl190_state),
+        VMSTATE_UINT32(soft_level, pl190_state),
+        VMSTATE_UINT32(irq_enable, pl190_state),
+        VMSTATE_UINT32(fiq_select, 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),
+        VMSTATE_INT32(protected, pl190_state),
+        VMSTATE_INT32(priority, pl190_state),
+        VMSTATE_INT32_ARRAY(prev_prio, pl190_state, PL190_NUM_PRIO),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+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_types(void)
 {
-    sysbus_register_dev("pl190", sizeof(pl190_state), pl190_init);
+    type_register_static(&pl190_info);
 }
 
-device_init(pl190_register_devices)
+type_init(pl190_register_types)
This page took 0.02993 seconds and 4 git commands to generate.