qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 10/11] Goldfish: Added switch device.


From: Patrick Jackson
Subject: [Qemu-devel] [PATCH 10/11] Goldfish: Added switch device.
Date: Mon, 22 Aug 2011 05:39:29 -0400


Signed-off-by: Patrick Jackson <address@hidden>
---
 Makefile.target      |    2 +-
 hw/android_arm.c     |   18 +++++
 hw/goldfish_device.h |    2 +
 hw/goldfish_switch.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 189 insertions(+), 1 deletions(-)
 create mode 100644 hw/goldfish_switch.c

diff --git a/Makefile.target b/Makefile.target
index 593594b..fbabd6d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -362,7 +362,7 @@ obj-arm-y += strongarm.o
 obj-arm-y += collie.o
 obj-arm-y += android_arm.o goldfish_device.o goldfish_interrupt.o goldfish_timer.o
 obj-arm-y += goldfish_tty.o goldfish_nand.o goldfish_fb.o goldfish_memlog.o
-obj-arm-y += goldfish_battery.o
+obj-arm-y += goldfish_battery.o goldfish_switch.o
 
 obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
 obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
diff --git a/hw/android_arm.c b/hw/android_arm.c
index 3fffc93..5d8372d 100644
--- a/hw/android_arm.c
+++ b/hw/android_arm.c
@@ -29,6 +29,15 @@ static struct arm_boot_info info = {
     .board_id = 1441,
 };
 
+#define TEST_SWITCH 0
+#if TEST_SWITCH
+static uint32_t switch_test_write(void *opaque, uint32_t state)
+{
+    goldfish_switch_set_state(opaque, state);
+    return state;
+}
+#endif
+
 static void android_arm_init_(ram_addr_t ram_size,
     const char *boot_device,
     const char *kernel_filename,
@@ -70,6 +79,15 @@ static void android_arm_init_(ram_addr_t ram_size,
     goldfish_battery_create(gbus);
     goldfish_nand_create(gbus);
 
+#if TEST_SWITCH
+    {
+        void *sw;
+        sw = goldfish_switch_create(gbus, "test", NULL, NULL, 0);
+        goldfish_switch_set_state(sw, 1);
+        goldfish_switch_create(gbus, "test2", switch_test_write, sw, 1);
+    }
+#endif
+
     info.ram_size        = ram_size;
     info.kernel_filename = kernel_filename;
     info.kernel_cmdline  = kernel_cmdline;
diff --git a/hw/goldfish_device.h b/hw/goldfish_device.h
index 19af64a..7e987c3 100644
--- a/hw/goldfish_device.h
+++ b/hw/goldfish_device.h
@@ -50,6 +50,7 @@ DeviceState *goldfish_nand_create(GoldfishBus *gbus);
 DeviceState *goldfish_fb_create(GoldfishBus *gbus, int id);
 DeviceState *goldfish_memlog_create(GoldfishBus *gbus, uint32_t base);
 DeviceState *goldfish_battery_create(GoldfishBus *gbus);
+DeviceState *goldfish_switch_create(GoldfishBus *gbus, const char *name_dev, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id);
 
 /* Global functions provided by Goldfish devices */
 void goldfish_bus_register_withprop(GoldfishDeviceInfo *info);
@@ -58,6 +59,7 @@ void goldfish_device_init(DeviceState *dev, uint32_t base, uint32_t irq);
 void goldfish_device_set_irq(GoldfishDevice *dev, int irq, int level);
 void goldfish_battery_set_prop(void *opaque, int ac, int property, int value);
 void goldfish_battery_display(void *opaque, void (* callback)(void *data, const char* string), void *data);
+void goldfish_switch_set_state(void *opaque, uint32_t state);
 
 /** TEMP FILE SUPPORT
  **
diff --git a/hw/goldfish_switch.c b/hw/goldfish_switch.c
new file mode 100644
index 0000000..0d08e50
--- /dev/null
+++ b/hw/goldfish_switch.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2007-2008 :The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#include "goldfish_device.h"
+
+enum {
+    SW_NAME_LEN     = 0x00,
+    SW_NAME_PTR     = 0x04,
+    SW_FLAGS        = 0x08,
+    SW_STATE        = 0x0c,
+    SW_INT_STATUS   = 0x10,
+    SW_INT_ENABLE   = 0x14,
+
+    SW_FLAGS_OUTPUT = 1U << 0
+};
+
+
+typedef struct GoldfishSwitchDevice {
+    GoldfishDevice dev;
+    char *name;
+    uint32_t state;
+    uint32_t state_changed : 1;
+    uint32_t int_enable : 1;
+    uint32_t (*writefn)(void *opaque, uint32_t state);
+    void *writeopaque;
+} GoldfishSwitchDevice;
+
+static uint32_t goldfish_switch_read(void *opaque, target_phys_addr_t offset)
+{
+    GoldfishSwitchDevice *s = (GoldfishSwitchDevice *)opaque;
+    offset -= 1024;
+
+    //printf("goldfish_switch_read %x %x\n", offset, size);
+
+    switch (offset) {
+        case SW_NAME_LEN:
+            return strlen(s->name);
+        case SW_FLAGS:
+            return s->writefn ? SW_FLAGS_OUTPUT : 0;
+        case SW_STATE:
+            return s->state;
+        case SW_INT_STATUS:
+            if(s->state_changed && s->int_enable) {
+                s->state_changed = 0;
+                goldfish_device_set_irq(&s->dev, 0, 0);
+                return 1;
+            }
+            return 0;
+    default:
+        cpu_abort (cpu_single_env, "goldfish_switch_read: Bad offset %x\n", offset);
+        return 0;
+    }
+}
+
+static void goldfish_switch_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+    GoldfishSwitchDevice *s = (GoldfishSwitchDevice *)opaque;
+    offset -= 1026;
+
+    //printf("goldfish_switch_read %x %x %x\n", offset, value, size);
+
+    switch(offset) {
+        case SW_NAME_PTR:
+            cpu_memory_rw_debug(cpu_single_env, value, (void*)s->name, strlen(s->name), 1);
+            break;
+
+        case SW_STATE:
+            if(s->writefn) {
+                uint32_t new_state;
+                new_state = s->writefn(s->writeopaque, value);
+                if(new_state != s->state) {
+                    goldfish_switch_set_state(s, new_state);
+                }
+            }
+            else
+                cpu_abort (cpu_single_env, "goldfish_switch_write: write to SW_STATE on input\n");
+            break;
+
+        case SW_INT_ENABLE:
+            value &= 1;
+            if(s->state_changed && s->int_enable != value)
+                goldfish_device_set_irq(&s->dev, 0, value);
+            s->int_enable = value;
+            break;
+
+        default:
+            cpu_abort (cpu_single_env, "goldfish_switch_write: Bad offset %x\n", offset);
+    }
+}
+
+static CPUReadMemoryFunc *goldfish_switch_readfn[] = {
+    goldfish_switch_read,
+    goldfish_switch_read,
+    goldfish_switch_read
+};
+
+static CPUWriteMemoryFunc *goldfish_switch_writefn[] = {
+    goldfish_switch_write,
+    goldfish_switch_write,
+    goldfish_switch_write
+};
+
+void goldfish_switch_set_state(void *opaque, uint32_t state)
+{
+    GoldfishSwitchDevice *s = (GoldfishSwitchDevice *)opaque;
+    s->state_changed = 1;
+    s->state = state;
+    if(s->int_enable)
+        goldfish_device_set_irq(&s->dev, 0, 1);
+}
+
+static int goldfish_switch_init(GoldfishDevice *dev)
+{
+    return 0;
+}
+
+DeviceState *goldfish_switch_create(GoldfishBus *gbus, const char *name_dev, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id)
+{
+    DeviceState *dev;
+    GoldfishDevice *gdev;
+    GoldfishSwitchDevice *sdev;
+    char *name = (char *)"goldfish-switch";
+
+    dev = qdev_create(&gbus->bus, name);
+    qdev_prop_set_string(dev, "name", name);
+    qdev_prop_set_string(dev, "name_dev", (char *)name_dev);
+    qdev_prop_set_uint32(dev, "id", id);
+    qdev_prop_set_ptr(dev, "writeopaque", writeopaque);
+    qdev_init_nofail(dev);
+    gdev = (GoldfishDevice *)dev;
+    sdev = DO_UPCAST(GoldfishSwitchDevice, dev, gdev);
+    sdev->writefn = writefn;
+
+    return dev;
+}
+
+static GoldfishDeviceInfo goldfish_switch_info = {
+    .init = goldfish_switch_init,
+    .readfn = goldfish_switch_readfn,
+    .writefn = goldfish_switch_writefn,
+    .qdev.name  = "goldfish-switch",
+    .qdev.size  = sizeof(GoldfishSwitchDevice),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("base", GoldfishDevice, base, 0),
+        DEFINE_PROP_UINT32("id", GoldfishDevice, id, -1),
+        DEFINE_PROP_UINT32("size", GoldfishDevice, size, 0x1000),
+        DEFINE_PROP_UINT32("irq", GoldfishDevice, irq, 0),
+        DEFINE_PROP_UINT32("irq_count", GoldfishDevice, irq_count, 1),
+        DEFINE_PROP_STRING("name", GoldfishDevice, name),
+        DEFINE_PROP_STRING("name_dev", GoldfishSwitchDevice, name),
+        DEFINE_PROP_PTR("writeopaque", GoldfishSwitchDevice, writeopaque),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void goldfish_switch_register(void)
+{
+    goldfish_bus_register_withprop(&goldfish_switch_info);
+}
+device_init(goldfish_switch_register);
-- 
1.7.4.1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]