qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 01/15] pci: add new bus functions


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH 01/15] pci: add new bus functions
Date: Tue, 9 Feb 2010 16:01:25 -0600

 - mapping and managing io regions
 - reading and writing physical memory

Signed-off-by: Anthony Liguori <address@hidden>
---
 hw/pci.c |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 hw/pci.h |   18 ++++++-
 2 files changed, 181 insertions(+), 9 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 9ad63dd..5460f27 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -664,6 +664,9 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
                                                          r->addr),
                                          r->filtered_size,
                                          IO_MEM_UNASSIGNED);
+            if (!r->map_func && r->read && r->write) {
+                cpu_unregister_io_memory(r->io_memory_addr);
+            }
         }
     }
 }
@@ -687,16 +690,15 @@ static int pci_unregister_device(DeviceState *dev)
     return 0;
 }
 
-void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            pcibus_t size, int type,
-                            PCIMapIORegionFunc *map_func)
+static PCIIORegion *do_pci_register_bar(PCIDevice *pci_dev, int region_num,
+                                        pcibus_t size, int type)
 {
     PCIIORegion *r;
     uint32_t addr;
     pcibus_t wmask;
 
     if ((unsigned int)region_num >= PCI_NUM_REGIONS)
-        return;
+        return NULL;
 
     if (size & (size-1)) {
         fprintf(stderr, "ERROR: PCI region size must be pow2 "
@@ -709,7 +711,6 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->size = size;
     r->filtered_size = size;
     r->type = type;
-    r->map_func = map_func;
 
     wmask = ~(size - 1);
     addr = pci_bar(pci_dev, region_num);
@@ -726,6 +727,100 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
         pci_set_long(pci_dev->cmask + addr, 0xffffffff);
     }
+
+    return r;
+}
+
+void pci_register_bar(PCIDevice *pci_dev, int region_num,
+                      pcibus_t size, int type,
+                      PCIMapIORegionFunc *map_func)
+{
+    PCIIORegion *r;
+    r = do_pci_register_bar(pci_dev, region_num, size, type);
+    if (r) {
+        r->map_func = map_func;
+    }
+}
+
+void pci_memory_read(PCIDevice *pci_dev, pcibus_t addr, void *buf, int len)
+{
+    cpu_physical_memory_read(addr, buf, len);
+}
+
+void pci_memory_write(PCIDevice *pci_dev, pcibus_t addr,
+                      const void *buf, int len)
+{
+    cpu_physical_memory_write(addr, buf, len);
+}
+
+static void pci_io_region_writeb(void *opaque, target_phys_addr_t addr,
+                                 uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, addr, 1, value);
+}
+
+static void pci_io_region_writew(void *opaque, target_phys_addr_t addr,
+                                 uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, addr, 2, value);
+}
+
+static void pci_io_region_writel(void *opaque, target_phys_addr_t addr,
+                                 uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, addr, 4, value);
+}
+
+static uint32_t pci_io_region_readb(void *opaque, target_phys_addr_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, addr, 1);
+}
+
+static uint32_t pci_io_region_readw(void *opaque, target_phys_addr_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, addr, 2);
+}
+
+static uint32_t pci_io_region_readl(void *opaque, target_phys_addr_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, addr, 4);
+}
+
+static CPUReadMemoryFunc * const pci_io_region_readfn[3] = {
+    pci_io_region_readb,
+    pci_io_region_readw,
+    pci_io_region_readl,
+};
+    
+static CPUWriteMemoryFunc * const pci_io_region_writefn[3] = {
+    pci_io_region_writeb,
+    pci_io_region_writew,
+    pci_io_region_writel,
+};
+
+void pci_register_io_region(PCIDevice *d, int region_num,
+                            pcibus_t size, int type,
+                            PCIIOReadFunc *readcb, PCIIOWriteFunc *writecb)
+{
+    PCIIORegion *r;
+    r = do_pci_register_bar(d, region_num, size, type);
+    if (r) {
+        r->map_func = NULL;
+        r->dev = d;
+        r->read = readcb;
+        r->write = writecb;
+        if (r->type != PCI_BASE_ADDRESS_SPACE_IO && r->read && r->write) {
+            r->io_memory_addr = cpu_register_io_memory(pci_io_region_readfn,
+                                                       pci_io_region_writefn,
+                                                       r);
+        }
+    }
 }
 
 static uint32_t pci_config_get_io_base(PCIDevice *d,
@@ -897,6 +992,45 @@ static pcibus_t pci_bar_address(PCIDevice *d,
     return new_addr;
 }
 
+static void pci_io_region_ioport_writeb(void *opaque, uint32_t addr,
+                                        uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, (addr - r->addr), 1, value);
+}
+
+static void pci_io_region_ioport_writew(void *opaque, uint32_t addr,
+                                        uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, (addr - r->addr), 2, value);
+}
+
+static void pci_io_region_ioport_writel(void *opaque, uint32_t addr,
+                                        uint32_t value)
+{
+    PCIIORegion *r = opaque;
+    r->write(r->dev, (addr - r->addr), 4, value);
+}
+
+static uint32_t pci_io_region_ioport_readb(void *opaque, uint32_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, (addr - r->addr), 1);
+}
+
+static uint32_t pci_io_region_ioport_readw(void *opaque, uint32_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, (addr - r->addr), 2);
+}
+
+static uint32_t pci_io_region_ioport_readl(void *opaque, uint32_t addr)
+{
+    PCIIORegion *r = opaque;
+    return r->read(r->dev, (addr - r->addr), 4);
+}
+
 static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
@@ -952,10 +1086,32 @@ static void pci_update_mappings(PCIDevice *d)
              * addr & (size - 1) != 0.
              */
             if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                r->map_func(d, i, r->addr, r->filtered_size, r->type);
+                if (r->map_func) {
+                    r->map_func(d, i, r->addr, r->filtered_size, r->type);
+                } else {
+                    register_ioport_write(r->addr, r->filtered_size, 1,
+                                          pci_io_region_ioport_writeb, r);
+                    register_ioport_write(r->addr, r->filtered_size, 2,
+                                          pci_io_region_ioport_writew, r);
+                    register_ioport_write(r->addr, r->filtered_size, 4,
+                                          pci_io_region_ioport_writel, r);
+                    register_ioport_read(r->addr, r->filtered_size, 1,
+                                         pci_io_region_ioport_readb, r);
+                    register_ioport_read(r->addr, r->filtered_size, 2,
+                                         pci_io_region_ioport_readw, r);
+                    register_ioport_read(r->addr, r->filtered_size, 4,
+                                         pci_io_region_ioport_readl, r);
+                }
             } else {
-                r->map_func(d, i, pci_to_cpu_addr(d->bus, r->addr),
-                            r->filtered_size, r->type);
+                if (r->map_func) {
+                    r->map_func(d, i, pci_to_cpu_addr(d->bus, r->addr),
+                                r->filtered_size, r->type);
+                } else if (r->read && r->write) {
+                    cpu_register_physical_memory(pci_to_cpu_addr(d->bus,
+                                                                 r->addr),
+                                                 r->filtered_size,
+                                                 r->io_memory_addr);
+                }
             }
         }
     }
diff --git a/hw/pci.h b/hw/pci.h
index 8b511d2..3edf28f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -81,13 +81,21 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int 
region_num,
                                 pcibus_t addr, pcibus_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
+typedef uint32_t (PCIIOReadFunc)(PCIDevice *pci_dev, pcibus_t addr, int size);
+typedef void (PCIIOWriteFunc)(PCIDevice *pci_dev, pcibus_t addr, int size,
+                              uint32_t value);
+
 typedef struct PCIIORegion {
+    PCIDevice *dev;
     pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
 #define PCI_BAR_UNMAPPED (~(pcibus_t)0)
     pcibus_t size;
     pcibus_t filtered_size;
     uint8_t type;
-    PCIMapIORegionFunc *map_func;
+    PCIMapIORegionFunc *map_func; /* legacy mapping function */
+    PCIIOReadFunc *read;
+    PCIIOWriteFunc *write;
+    int io_memory_addr;
 } PCIIORegion;
 
 #define PCI_ROM_SLOT 6
@@ -190,6 +198,14 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func);
 
+void pci_register_io_region(PCIDevice *d, int region_num,
+                            pcibus_t size, int type,
+                            PCIIOReadFunc *readcb, PCIIOWriteFunc *writecb);
+
+void pci_memory_read(PCIDevice *pci_dev, pcibus_t addr, void *buf, int len);
+void pci_memory_write(PCIDevice *pci_dev, pcibus_t addr,
+                      const void *buf, int len);
+
 int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
 
 void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
-- 
1.6.5.2





reply via email to

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