summaryrefslogtreecommitdiff
path: root/rwhandler.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-01-14 16:00:14 +0200
committerMichael S. Tsirkin <mst@redhat.com>2010-02-14 16:10:53 +0200
commit049f7adbd547969ba013fed13c0a26c1f62a4a71 (patch)
tree0c173dc801f22831a061199887c2ee0135691e89 /rwhandler.c
parente73d6e3a028c777e642c687d433db914d8be8679 (diff)
downloadqemu-049f7adbd547969ba013fed13c0a26c1f62a4a71.tar.gz
rwhandler: simplified way to register for mem/io
Some users prefer a single callback with length passed as parameter to using b/w/l callbacks. It would maybe be cleaner to just pass length to existing callbacks but that's a lot of churn. So for now add a wrapper. For convenience use pcibus_t for address so a single callback can be used for pci io and pci memory. I did have to resort to preprocessor to reduce code duplication. It is however slightly more straightforward, and better contained than what we had with pci_host_template.h. Again, it would go away if we just passed len to existing callbacks. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'rwhandler.c')
-rw-r--r--rwhandler.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/rwhandler.c b/rwhandler.c
new file mode 100644
index 0000000000..c50c4bf603
--- /dev/null
+++ b/rwhandler.c
@@ -0,0 +1,91 @@
+#include "rwhandler.h"
+#include "ioport.h"
+#include "cpu-all.h"
+
+#if !defined(CONFIG_USER_ONLY)
+
+#define RWHANDLER_WRITE(name, len, type) \
+static void name(void *opaque, type addr, uint32_t value) \
+{\
+ struct ReadWriteHandler *handler = opaque;\
+ handler->write(handler, addr, value, len);\
+}
+
+#define RWHANDLER_READ(name, len, type) \
+static uint32_t name(void *opaque, type addr) \
+{ \
+ struct ReadWriteHandler *handler = opaque; \
+ return handler->read(handler, addr, len); \
+}
+
+RWHANDLER_WRITE(cpu_io_memory_simple_writeb, 1, target_phys_addr_t);
+RWHANDLER_READ(cpu_io_memory_simple_readb, 1, target_phys_addr_t);
+RWHANDLER_WRITE(cpu_io_memory_simple_writew, 2, target_phys_addr_t);
+RWHANDLER_READ(cpu_io_memory_simple_readw, 2, target_phys_addr_t);
+RWHANDLER_WRITE(cpu_io_memory_simple_writel, 4, target_phys_addr_t);
+RWHANDLER_READ(cpu_io_memory_simple_readl, 4, target_phys_addr_t);
+
+static CPUWriteMemoryFunc * const cpu_io_memory_simple_write[] = {
+ &cpu_io_memory_simple_writeb,
+ &cpu_io_memory_simple_writew,
+ &cpu_io_memory_simple_writel,
+};
+
+static CPUReadMemoryFunc * const cpu_io_memory_simple_read[] = {
+ &cpu_io_memory_simple_readb,
+ &cpu_io_memory_simple_readw,
+ &cpu_io_memory_simple_readl,
+};
+
+int cpu_register_io_memory_simple(struct ReadWriteHandler *handler)
+{
+ if (!handler->read || !handler->write) {
+ return -1;
+ }
+ return cpu_register_io_memory(cpu_io_memory_simple_read,
+ cpu_io_memory_simple_write,
+ handler);
+}
+
+RWHANDLER_WRITE(ioport_simple_writeb, 1, uint32_t);
+RWHANDLER_READ(ioport_simple_readb, 1, uint32_t);
+RWHANDLER_WRITE(ioport_simple_writew, 2, uint32_t);
+RWHANDLER_READ(ioport_simple_readw, 2, uint32_t);
+RWHANDLER_WRITE(ioport_simple_writel, 4, uint32_t);
+RWHANDLER_READ(ioport_simple_readl, 4, uint32_t);
+
+int register_ioport_simple(ReadWriteHandler* handler,
+ pio_addr_t start, int length, int size)
+{
+ IOPortWriteFunc *write;
+ IOPortReadFunc *read;
+ int r;
+ switch (size) {
+ case 1:
+ write = ioport_simple_writeb;
+ read = ioport_simple_readb;
+ break;
+ case 2:
+ write = ioport_simple_writew;
+ read = ioport_simple_readw;
+ break;
+ default:
+ write = ioport_simple_writel;
+ read = ioport_simple_readl;
+ }
+ if (handler->write) {
+ r = register_ioport_write(start, length, size, write, handler);
+ if (r < 0) {
+ return r;
+ }
+ }
+ if (handler->read) {
+ r = register_ioport_read(start, length, size, read, handler);
+ if (r < 0) {
+ return r;
+ }
+ }
+ return 0;
+}
+
+#endif