qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2
@ 2009-10-02 10:31 Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 01/25] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
                   ` (25 more replies)
  0 siblings, 26 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch set is preliminary for q35 based chipset support.
This patch sets does various pci related clean ups and 
64bit bar, pciemmconfig and pci bridge support.

I'm aware that some of patches are already conflicting with
other's patch. It is appriciated to merge some first part of
patches which doesn't conflict.

thanks,


changes from V1:
- introduced pcibus_t
- dropped pci_config_[sg]et_xxx()
- many code clean up
- reworked pci_host.h
- reworked pci bus search to introduce tree representation for pci bus
- dropped some non essential patches


Isaku Yamahata (25):
  pci: fix PCI_DPRINTF() wrt variadic macro.
  pci: use appropriate PRIs in PCI_DPRINTF() for portability.
  pci: introduce constant PCI_NUM_PINS for the number of interrupt
    pins, 4.
  pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  pci: use PCI_SLOT() and PCI_FUNC().
  pci: define a constant to represent a unmapped bar and use it.
  pci: helper functions to access PCIDevice::config
  pci: use helper functions to access pci config space.
  pci: introduce pcibus_t to represent pci bus address/size instead of
    uint32_t
  pci: introduce FMT_pcibus for printf format for pcibus_t.
  pci: typedef pcibus_t as uint64_t instead of uint32_t.
  pci: 64bit bar support.
  pci: make pci configuration transaction more accurate.
  pci: factor out the logic to get pci device from address.
  pci_host.h: split non-inline static function in pci_host.h into
    pci_host.c
  pci: pcie host and mmcfg support.
  pci: fix pci_default_write_config()
  pci: add helper functions for pci config write function.
  pci: use helper function in pci_default_write_config()
  pci: factor out config update logic.
  pci: make bar update function aware of pci bridge.
  pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  pci: add helper function to initialize wmask.
  pci: initialize wmask according to pci header type.
  pci/monitor: print out bridge's filtering values and so on.

 Makefile.target               |    8 +-
 hw/ac97.c                     |    2 +-
 hw/apb_pci.c                  |   31 +-
 hw/cirrus_vga.c               |    8 +-
 hw/e1000.c                    |   12 +-
 hw/eepro100.c                 |   10 +-
 hw/es1370.c                   |    2 +-
 hw/grackle_pci.c              |   24 +-
 hw/gt64xxx.c                  |   11 +-
 hw/hw.h                       |   12 +
 hw/ide/pci.c                  |    4 +-
 hw/lsi53c895a.c               |    6 +-
 hw/macio.c                    |    2 +-
 hw/msix.c                     |    2 +-
 hw/msix.h                     |    3 +-
 hw/ne2000.c                   |    2 +-
 hw/openpic.c                  |    2 +-
 hw/pci-hotplug.c              |    6 +-
 hw/pci.c                      |  920 +++++++++++++++++++++++++++++++++--------
 hw/pci.h                      |  194 ++++++++-
 hw/{pci_host.h => pci_host.c} |   61 +++-
 hw/pci_host.h                 |  110 ++----
 hw/pcnet.c                    |    9 +-
 hw/piix_pci.c                 |   16 +-
 hw/ppc4xx_pci.c               |   18 +-
 hw/ppce500_pci.c              |   17 +-
 hw/prep_pci.c                 |   14 +-
 hw/rtl8139.c                  |    4 +-
 hw/sun4u.c                    |    2 +-
 hw/unin_pci.c                 |   47 +--
 hw/usb-ohci.c                 |    2 +-
 hw/usb-uhci.c                 |    2 +-
 hw/vga-pci.c                  |    2 +-
 hw/virtio-pci.c               |    2 +-
 hw/vmware_vga.c               |    4 +-
 hw/wdt_i6300esb.c             |    5 +-
 36 files changed, 1110 insertions(+), 466 deletions(-)
 copy hw/{pci_host.h => pci_host.c} (69%)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 01/25] pci: fix PCI_DPRINTF() wrt variadic macro.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 02/25] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add missing ## in PCI_DPRINTF() to compile.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 64d70ed..4392574 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -29,7 +29,7 @@
 
 //#define DEBUG_PCI
 #ifdef DEBUG_PCI
-# define PCI_DPRINTF(format, ...)       printf(format, __VA_ARGS__)
+# define PCI_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
 #else
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 02/25] pci: use appropriate PRIs in PCI_DPRINTF() for portability.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 01/25] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 03/25] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use appropriate PRIs in PCI_DPRINTF() to print pci config space offset
and value for portability.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 4392574..d281ee2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -561,7 +561,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     int config_addr, bus_num;
 
 #if 0
-    PCI_DPRINTF("pci_data_write: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
@@ -573,7 +573,8 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
     if (!pci_dev)
         return;
     config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_write: %s: "
+                "addr=%02x val=%08"PRI32x" len=%d\n",
                 pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
@@ -609,11 +610,12 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     }
     config_addr = addr & 0xff;
     val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_config_read: %s: "
+                "addr=%02x val=%08"PRIx32" len=%d\n",
                 pci_dev->name, config_addr, val, len);
  the_end:
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08x val=%08x len=%d\n",
+    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
                 addr, val, len);
 #endif
     return val;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 03/25] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 01/25] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 02/25] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 04/25] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

introduce constant PCI_NUM_PINS for the number of interrupt pins, 4.
and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    4 ++--
 hw/pci.h |    4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index d281ee2..40035e6 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -177,7 +177,7 @@ const VMStateDescription vmstate_pci_device = {
         VMSTATE_INT32_LE(version_id, PCIDevice),
         VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
                        typeof_field(PCIDevice,config)),
-        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, 4, 2),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -337,7 +337,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->config_read = config_read;
     pci_dev->config_write = config_write;
     bus->devices[devfn] = pci_dev;
-    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
     pci_dev->version_id = 2; /* Current pci device vmstate version */
     return pci_dev;
 }
diff --git a/hw/pci.h b/hw/pci.h
index caba5c8..aa3090e 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -156,6 +156,8 @@ typedef struct PCIIORegion {
 /* Size of the standard PCI config space */
 #define PCI_CONFIG_SPACE_SIZE 0x100
 
+#define PCI_NUM_PINS            4       /* A-D */
+
 /* Bits in cap_present field. */
 enum {
     QEMU_PCI_CAP_MSIX = 0x1,
@@ -191,7 +193,7 @@ struct PCIDevice {
     qemu_irq *irq;
 
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
-    int irq_state[4];
+    int irq_state[PCI_NUM_PINS];
 
     /* Capability bits */
     uint32_t cap_present;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 04/25] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 03/25] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 05/25] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    2 +-
 hw/pci.h |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 40035e6..1016893 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -422,7 +422,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     if (region_num == PCI_ROM_SLOT) {
         addr = 0x30;
         /* ROM enable bit is writeable */
-        wmask |= 1;
+        wmask |= PCI_ROM_ADDRESS_ENABLE;
     } else {
         addr = 0x10 + region_num * 4;
     }
diff --git a/hw/pci.h b/hw/pci.h
index aa3090e..def45ae 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -131,6 +131,8 @@ typedef struct PCIIORegion {
 #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
 #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
 
+#define  PCI_ROM_ADDRESS_ENABLE 0x01
+
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
 #define PCI_STATUS_RESERVED1	0x007
 #define PCI_STATUS_INT_STATUS	0x008
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 05/25] pci: use PCI_SLOT() and PCI_FUNC().
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (3 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 04/25] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 06/25] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use PCI_SLOT() and PCI_FUNC() where appropriate instead of
direct use of bit operation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 1016893..3bbc7e3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -703,7 +703,7 @@ static void pci_info_device(PCIDevice *d)
     const pci_class_desc *desc;
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
@@ -1039,7 +1039,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
                    "pci id %04x:%04x (sub %04x:%04x)\n",
                    indent, "", ctxt,
-                   d->bus->bus_num, d->devfn >> 3, d->devfn & 7,
+                   d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
                    le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 06/25] pci: define a constant to represent a unmapped bar and use it.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (4 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 05/25] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 07/25] pci: helper functions to access PCIDevice::config Isaku Yamahata
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

define a constant to represent a unmapped bar instead of -1 and use it.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |   18 +++++++++---------
 hw/pci.h        |    1 +
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7e95f10..fd2367a 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3206,7 +3206,7 @@ static void pci_cirrus_write_config(PCIDevice *d,
     CirrusVGAState *s = &pvs->cirrus_vga;
 
     pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == -1)
+    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED)
         s->vga.map_addr = 0;
     cirrus_update_memory_access(s);
 }
diff --git a/hw/pci.c b/hw/pci.c
index 3bbc7e3..39791d0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -366,7 +366,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
 
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &pci_dev->io_regions[i];
-        if (!r->size || r->addr == -1)
+        if (!r->size || r->addr == PCI_BAR_UNMAPPED)
             continue;
         if (r->type == PCI_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->size);
@@ -413,7 +413,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     }
 
     r = &pci_dev->io_regions[region_num];
-    r->addr = -1;
+    r->addr = PCI_BAR_UNMAPPED;
     r->size = size;
     r->type = type;
     r->map_func = map_func;
@@ -455,10 +455,10 @@ static void pci_update_mappings(PCIDevice *d)
                     /* NOTE: we have only 64K ioports on PC */
                     if (last_addr <= new_addr || new_addr == 0 ||
                         last_addr >= 0x10000) {
-                        new_addr = -1;
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
@@ -474,17 +474,17 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == -1) {
-                        new_addr = -1;
+                        last_addr == PCI_BAR_UNMAPPED) {
+                        new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
                 no_mem_map:
-                    new_addr = -1;
+                    new_addr = PCI_BAR_UNMAPPED;
                 }
             }
             /* now do the real mapping */
             if (new_addr != r->addr) {
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     if (r->type & PCI_ADDRESS_SPACE_IO) {
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
@@ -503,7 +503,7 @@ static void pci_update_mappings(PCIDevice *d)
                     }
                 }
                 r->addr = new_addr;
-                if (r->addr != -1) {
+                if (r->addr != PCI_BAR_UNMAPPED) {
                     r->map_func(d, i, r->addr, r->size, r->type);
                 }
             }
diff --git a/hw/pci.h b/hw/pci.h
index def45ae..00c8947 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -85,6 +85,7 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 typedef struct PCIIORegion {
     uint32_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED        (~(uint32_t)0)
     uint32_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 07/25] pci: helper functions to access PCIDevice::config
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (5 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 06/25] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 08/25] pci: use helper functions to access pci config space Isaku Yamahata
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper functions to get/set PCIDevice::config
Those will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 00c8947..e79540a 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -310,6 +310,18 @@ pci_get_long(uint8_t *config)
 }
 
 static inline void
+pci_set_quad(uint8_t *config, uint64_t val)
+{
+    cpu_to_le64w((uint64_t *)config, val);
+}
+
+static inline uint64_t
+pci_get_quad(uint8_t *config)
+{
+    return le64_to_cpup((uint64_t *)config);
+}
+
+static inline void
 pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
 {
     pci_set_word(&pci_config[PCI_VENDOR_ID], val);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 08/25] pci: use helper functions to access pci config space.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (6 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 07/25] pci: helper functions to access PCIDevice::config Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 09/25] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

use pci_[gs]et_{byte, word, long}() to access pci configuration
space.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   38 ++++++++++++++++++--------------------
 1 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 39791d0..21e23b0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -426,9 +426,9 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     } else {
         addr = 0x10 + region_num * 4;
     }
-    *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
-    *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask);
-    *(uint32_t *)(pci_dev->cmask + addr) = 0xffffffff;
+    pci_set_long(pci_dev->config + addr, type);
+    pci_set_long(pci_dev->wmask + addr, wmask);
+    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -437,7 +437,7 @@ static void pci_update_mappings(PCIDevice *d)
     int cmd, i;
     uint32_t last_addr, new_addr, config_ofs;
 
-    cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
+    cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (i == PCI_ROM_SLOT) {
@@ -448,8 +448,7 @@ static void pci_update_mappings(PCIDevice *d)
         if (r->size != 0) {
             if (r->type & PCI_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
+                    new_addr = pci_get_long(d->config + config_ofs);
                     new_addr = new_addr & ~(r->size - 1);
                     last_addr = new_addr + r->size - 1;
                     /* NOTE: we have only 64K ioports on PC */
@@ -462,8 +461,7 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = le32_to_cpu(*(uint32_t *)(d->config +
-                                                         config_ofs));
+                    new_addr = pci_get_long(d->config + config_ofs);
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                         goto no_mem_map;
@@ -489,7 +487,7 @@ static void pci_update_mappings(PCIDevice *d)
                         int class;
                         /* NOTE: specific hack for IDE in PC case:
                            only one byte must be mapped. */
-                        class = d->config[0x0a] | (d->config[0x0b] << 8);
+                        class = pci_get_word(d->config + PCI_CLASS_DEVICE);
                         if (class == 0x0101 && r->size == 4) {
                             isa_unassign_ioport(r->addr + 2, 1);
                         } else {
@@ -520,18 +518,18 @@ uint32_t pci_default_read_config(PCIDevice *d,
     default:
     case 4:
 	if (address <= 0xfc) {
-	    val = le32_to_cpu(*(uint32_t *)(d->config + address));
+            val = pci_get_long(d->config + address);
 	    break;
 	}
 	/* fall through */
     case 2:
         if (address <= 0xfe) {
-	    val = le16_to_cpu(*(uint16_t *)(d->config + address));
+            val = pci_get_word(d->config + address);
 	    break;
 	}
 	/* fall through */
     case 1:
-        val = d->config[address];
+        val = pci_get_byte(d->config + address);
         break;
     }
     return val;
@@ -704,7 +702,7 @@ static void pci_info_device(PCIDevice *d)
 
     monitor_printf(mon, "  Bus %2d, device %3d, function %d:\n",
                    d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
-    class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
     monitor_printf(mon, "    ");
     desc = pci_class_descriptions;
     while (desc->desc && class != desc->class)
@@ -715,8 +713,8 @@ static void pci_info_device(PCIDevice *d)
         monitor_printf(mon, "Class %04x", class);
     }
     monitor_printf(mon, ": PCI device %04x:%04x\n",
-           le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
-           le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
+           pci_get_word(d->config + PCI_VENDOR_ID),
+           pci_get_word(d->config + PCI_DEVICE_ID));
 
     if (d->config[PCI_INTERRUPT_PIN] != 0) {
         monitor_printf(mon, "      IRQ %d.\n",
@@ -1026,7 +1024,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     PCIIORegion *r;
     int i, class;
 
-    class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
     desc = pci_class_descriptions;
     while (desc->desc && class != desc->class)
         desc++;
@@ -1040,10 +1038,10 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
                    "pci id %04x:%04x (sub %04x:%04x)\n",
                    indent, "", ctxt,
                    d->bus->bus_num, PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_VENDOR_ID))),
-                   le16_to_cpu(*((uint16_t *)(d->config + PCI_SUBSYSTEM_ID))));
+                   pci_get_word(d->config + PCI_VENDOR_ID),
+                   pci_get_word(d->config + PCI_DEVICE_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_ID));
     for (i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
         if (!r->size)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 09/25] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (7 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 08/25] pci: use helper functions to access pci config space Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 10/25] pci: introduce FMT_pcibus for printf format for pcibus_t Isaku Yamahata
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch is preliminary for 64 bit BAR support.
Introduce dedicated type, pcibus_t, to represent pci bus address/size
instead of uint32_t.
Later this type will be changed to uint64_t.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ac97.c         |    2 +-
 hw/cirrus_vga.c   |    4 ++--
 hw/e1000.c        |    6 +++---
 hw/eepro100.c     |    4 ++--
 hw/es1370.c       |    2 +-
 hw/ide/pci.c      |    4 ++--
 hw/lsi53c895a.c   |    6 +++---
 hw/macio.c        |    2 +-
 hw/msix.c         |    2 +-
 hw/msix.h         |    3 ++-
 hw/ne2000.c       |    2 +-
 hw/openpic.c      |    2 +-
 hw/pci.c          |    7 ++++---
 hw/pci.h          |   12 +++++++-----
 hw/pcnet.c        |    4 ++--
 hw/rtl8139.c      |    4 ++--
 hw/sun4u.c        |    2 +-
 hw/usb-ohci.c     |    2 +-
 hw/usb-uhci.c     |    2 +-
 hw/vga-pci.c      |    2 +-
 hw/virtio-pci.c   |    2 +-
 hw/vmware_vga.c   |    4 ++--
 hw/wdt_i6300esb.c |    2 +-
 23 files changed, 43 insertions(+), 39 deletions(-)

diff --git a/hw/ac97.c b/hw/ac97.c
index 610ca60..e3f0dbc 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1250,7 +1250,7 @@ static int ac97_load (QEMUFile *f, void *opaque, int version_id)
 }
 
 static void ac97_map (PCIDevice *pci_dev, int region_num,
-                      uint32_t addr, uint32_t size, int type)
+                      pcibus_t addr, pcibus_t size, int type)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, pci_dev);
     PCIDevice *d = &s->dev;
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index fd2367a..2a6aba8 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3170,7 +3170,7 @@ void isa_cirrus_vga_init(void)
  ***************************************/
 
 static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-			       uint32_t addr, uint32_t size, int type)
+			       pcibus_t addr, pcibus_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
@@ -3191,7 +3191,7 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
 }
 
 static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
-				uint32_t addr, uint32_t size, int type)
+				pcibus_t addr, pcibus_t size, int type)
 {
     CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
 
diff --git a/hw/e1000.c b/hw/e1000.c
index 95c471c..c07eb42 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -142,8 +142,8 @@ static const char phy_regcap[0x20] = {
 };
 
 static void
-ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
-           uint32_t size, int type)
+ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
+           pcibus_t size, int type)
 {
     DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
 }
@@ -1030,7 +1030,7 @@ static CPUReadMemoryFunc * const e1000_mmio_read[] = {
 
 static void
 e1000_mmio_map(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
     int i;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 3f84e26..1a1a0da 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1374,7 +1374,7 @@ static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
 /* PCI EEPRO100 definitions */
 
 static void pci_map(PCIDevice * pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
@@ -1453,7 +1453,7 @@ static CPUReadMemoryFunc * const pci_mmio_read[] = {
 };
 
 static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         pcibus_t addr, pcibus_t size, int type)
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
diff --git a/hw/es1370.c b/hw/es1370.c
index 9071a48..b42809d 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -907,7 +907,7 @@ static void es1370_adc_callback (void *opaque, int avail)
 }
 
 static void es1370_map (PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        pcibus_t addr, pcibus_t size, int type)
 {
     ES1370State *s = DO_UPCAST (ES1370State, dev, pci_dev);
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 89ecd44..125f04d 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -60,7 +60,7 @@ typedef struct PCIIDEState {
 static void cmd646_update_irq(PCIIDEState *d);
 
 static void ide_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     IDEBus *bus;
@@ -245,7 +245,7 @@ static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIIDEState *d = (PCIIDEState *)pci_dev;
     int i;
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 62bdca8..d62581a 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1926,7 +1926,7 @@ static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
-                           uint32_t addr, uint32_t size, int type)
+                           pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1941,7 +1941,7 @@ static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
@@ -1951,7 +1951,7 @@ static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
 }
 
 static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             pcibus_t addr, pcibus_t size, int type)
 {
     LSIState *s = DO_UPCAST(LSIState, dev, pci_dev);
 
diff --git a/hw/macio.c b/hw/macio.c
index 8cfadfc..f3340da 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -40,7 +40,7 @@ struct macio_state_t {
 };
 
 static void macio_map (PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     macio_state_t *macio_state;
     int i;
diff --git a/hw/msix.c b/hw/msix.c
index 3782994..4300c4e 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -201,7 +201,7 @@ static CPUReadMemoryFunc * const msix_mmio_read[] = {
 
 /* Should be called from device's map method. */
 void msix_mmio_map(PCIDevice *d, int region_num,
-                   uint32_t addr, uint32_t size, int type)
+                   pcibus_t addr, pcibus_t size, int type)
 {
     uint8_t *config = d->config + d->msix_cap;
     uint32_t table = pci_get_long(config + MSIX_TABLE_OFFSET);
diff --git a/hw/msix.h b/hw/msix.h
index 9367ba3..2ff754a 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -2,6 +2,7 @@
 #define QEMU_MSIX_H
 
 #include "qemu-common.h"
+#include "pci.h"
 
 int msix_init(struct PCIDevice *dev, unsigned short nentries,
               unsigned bar_nr, unsigned bar_size,
@@ -11,7 +12,7 @@ void msix_write_config(PCIDevice *pci_dev, uint32_t address,
                        uint32_t val, int len);
 
 void msix_mmio_map(PCIDevice *pci_dev, int region_num,
-                   uint32_t addr, uint32_t size, int type);
+                   pcibus_t addr, pcibus_t size, int type);
 
 int msix_uninit(PCIDevice *d);
 
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 87f1e59..d77ea73 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -715,7 +715,7 @@ static int pci_ne2000_load(QEMUFile* f, void* opaque, int version_id)
 /* PCI NE2000 definitions */
 
 static void ne2000_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
     NE2000State *s = &d->ne2000;
diff --git a/hw/openpic.c b/hw/openpic.c
index 74dde6d..a2f3990 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1026,7 +1026,7 @@ static CPUReadMemoryFunc * const openpic_read[] = {
 };
 
 static void openpic_map(PCIDevice *pci_dev, int region_num,
-                        uint32_t addr, uint32_t size, int type)
+                        pcibus_t addr, pcibus_t size, int type)
 {
     openpic_t *opp;
 
diff --git a/hw/pci.c b/hw/pci.c
index 21e23b0..674daba 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -396,12 +396,12 @@ int pci_unregister_device(PCIDevice *pci_dev)
 }
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
 {
     PCIIORegion *r;
     uint32_t addr;
-    uint32_t wmask;
+    pcibus_t wmask;
 
     if ((unsigned int)region_num >= PCI_NUM_REGIONS)
         return;
@@ -435,7 +435,8 @@ static void pci_update_mappings(PCIDevice *d)
 {
     PCIIORegion *r;
     int cmd, i;
-    uint32_t last_addr, new_addr, config_ofs;
+    pcibus_t last_addr, new_addr;
+    uint32_t config_ofs;
 
     cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
diff --git a/hw/pci.h b/hw/pci.h
index e79540a..8e46aba 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -71,12 +71,14 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
+typedef uint32_t pcibus_t;
+
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
 typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
                                    uint32_t address, int len);
 typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
-                                uint32_t addr, uint32_t size, int type);
+                                pcibus_t addr, pcibus_t size, int type);
 typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
@@ -84,9 +86,9 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
-    uint32_t addr; /* current PCI mapping address. -1 means not mapped */
-#define PCI_BAR_UNMAPPED        (~(uint32_t)0)
-    uint32_t size;
+    pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED        (~(pcibus_t)0)
+    pcibus_t size;
     uint8_t type;
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
@@ -232,7 +234,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 int pci_unregister_device(PCIDevice *pci_dev);
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                            uint32_t size, int type,
+                            pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func);
 
 int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index ae98a20..2789574 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1761,7 +1761,7 @@ static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
 }
 
 static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
-                             uint32_t addr, uint32_t size, int type)
+                             pcibus_t addr, pcibus_t size, int type)
 {
     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
 
@@ -1989,7 +1989,7 @@ static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
 };
 
 static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
-                            uint32_t addr, uint32_t size, int type)
+                            pcibus_t addr, pcibus_t size, int type)
 {
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
 
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 83cb1ff..6856b23 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3324,7 +3324,7 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
 /* PCI RTL8139 definitions */
 
 static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
@@ -3332,7 +3332,7 @@ static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
 }
 
 static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     RTL8139State *s = DO_UPCAST(RTL8139State, dev, pci_dev);
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 2c97d9d..5812782 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -344,7 +344,7 @@ static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
-                              uint32_t addr, uint32_t size, int type)
+                              pcibus_t addr, pcibus_t size, int type)
 {
     DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
     switch (region_num) {
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 6e428c4..7a92efd 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1707,7 +1707,7 @@ typedef struct {
 } OHCIPCIState;
 
 static void ohci_mapfunc(PCIDevice *pci_dev, int i,
-            uint32_t addr, uint32_t size, int type)
+            pcibus_t addr, pcibus_t size, int type)
 {
     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, pci_dev);
     cpu_register_physical_memory(addr, size, ohci->state.mem);
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6807413..abeb552 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1059,7 +1059,7 @@ static void uhci_frame_timer(void *opaque)
 }
 
 static void uhci_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     UHCIState *s = (UHCIState *)pci_dev;
 
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 6038cec..b0e4262 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -71,7 +71,7 @@ void vga_dirty_log_start(VGACommonState *s)
 }
 
 static void vga_map(PCIDevice *pci_dev, int region_num,
-                    uint32_t addr, uint32_t size, int type)
+                    pcibus_t addr, pcibus_t size, int type)
 {
     PCIVGAState *d = (PCIVGAState *)pci_dev;
     VGACommonState *s = &d->vga;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index bd5a7c4..e68823a 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -342,7 +342,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
 }
 
 static void virtio_map(PCIDevice *pci_dev, int region_num,
-                       uint32_t addr, uint32_t size, int type)
+                       pcibus_t addr, pcibus_t size, int type)
 {
     VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index a273f35..945d57e 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1174,7 +1174,7 @@ static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
@@ -1194,7 +1194,7 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
 }
 
 static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                uint32_t addr, uint32_t size, int type)
+                pcibus_t addr, pcibus_t size, int type)
 {
     struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
     struct vmsvga_state_s *s = &d->chip;
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 3abaa87..d3ab3c8 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -347,7 +347,7 @@ static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val)
 }
 
 static void i6300esb_map(PCIDevice *dev, int region_num,
-                         uint32_t addr, uint32_t size, int type)
+                         pcibus_t addr, pcibus_t size, int type)
 {
     static CPUReadMemoryFunc * const mem_read[3] = {
         i6300esb_mem_readb,
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 10/25] pci: introduce FMT_pcibus for printf format for pcibus_t.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (8 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 09/25] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 11/25] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch is preliminary for 64bit BAR.
Later pcibus_t will be changed from uint32_t to uint64_t.
Introduce FMT_pcibus for printf format for pcibus_t.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/e1000.c        |    6 ++++--
 hw/eepro100.c     |    6 ++++--
 hw/pci.c          |   17 +++++++++++------
 hw/pci.h          |    1 +
 hw/pcnet.c        |    5 +++--
 hw/wdt_i6300esb.c |    3 ++-
 6 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/hw/e1000.c b/hw/e1000.c
index c07eb42..cb88f7a 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -145,7 +145,8 @@ static void
 ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr,
            pcibus_t size, int type)
 {
-    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
+    DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_pcibus" size=0x%08"FMT_pcibus"\n",
+           addr, size);
 }
 
 static void
@@ -1040,7 +1041,8 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
     };
 
 
-    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_pcibus" 0x%08"FMT_pcibus"\n",
+           addr, size);
 
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
     qemu_register_coalesced_mmio(addr, excluded_regs[0]);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 1a1a0da..e54b129 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1378,7 +1378,8 @@ static void pci_map(PCIDevice * pci_dev, int region_num,
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_pcibus", "
+          "size=0x%08"FMT_pcibus", type=%d\n",
           region_num, addr, size, type));
 
     assert(region_num == 1);
@@ -1457,7 +1458,8 @@ static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
 {
     EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
 
-    TRACE(OTHER, logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_pcibus", "
+          "size=0x%08"FMT_pcibus", type=%d\n",
           region_num, addr, size, type));
 
     if (region_num == 0) {
diff --git a/hw/pci.c b/hw/pci.c
index 674daba..510fad2 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -408,7 +408,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
 
     if (size & (size-1)) {
         fprintf(stderr, "ERROR: PCI region size must be pow2 "
-                    "type=0x%x, size=0x%x\n", type, size);
+                    "type=0x%x, size=0x%"FMT_pcibus"\n", type, size);
         exit(1);
     }
 
@@ -427,7 +427,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
-    pci_set_long(pci_dev->wmask + addr, wmask);
+    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
     pci_set_long(pci_dev->cmask + addr, 0xffffffff);
 }
 
@@ -473,7 +473,11 @@ static void pci_update_mappings(PCIDevice *d)
                        mappings, we handle specific values as invalid
                        mappings. */
                     if (last_addr <= new_addr || new_addr == 0 ||
-                        last_addr == PCI_BAR_UNMAPPED) {
+                        last_addr == PCI_BAR_UNMAPPED ||
+
+                        /* keep old behaviour
+                         * without this, PC ide doesn't work well. */
+                        last_addr >= UINT32_MAX) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -729,10 +733,10 @@ static void pci_info_device(PCIDevice *d)
         if (r->size != 0) {
             monitor_printf(mon, "      BAR%d: ", i);
             if (r->type & PCI_ADDRESS_SPACE_IO) {
-                monitor_printf(mon, "I/O at 0x%04x [0x%04x].\n",
+                monitor_printf(mon, "I/O at 0x%04"FMT_pcibus" [0x%04"FMT_pcibus"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08x [0x%08x].\n",
+                monitor_printf(mon, "32 bit memory at 0x%08"FMT_pcibus" [0x%08"FMT_pcibus"].\n",
                                r->addr, r->addr + r->size - 1);
             }
         }
@@ -1047,7 +1051,8 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
         r = &d->io_regions[i];
         if (!r->size)
             continue;
-        monitor_printf(mon, "%*sbar %d: %s at 0x%x [0x%x]\n", indent, "",
+        monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_pcibus" [0x%"FMT_pcibus"]\n",
+                       indent, "",
                        i, r->type & PCI_ADDRESS_SPACE_IO ? "i/o" : "mem",
                        r->addr, r->addr + r->size - 1);
     }
diff --git a/hw/pci.h b/hw/pci.h
index 8e46aba..d75b3b3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -72,6 +72,7 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
 typedef uint32_t pcibus_t;
+#define FMT_pcibus                      PRIx32
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 2789574..0af9a9f 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1766,7 +1766,8 @@ static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+    printf("pcnet_ioport_map addr=0x%04"FMT_pcibus" size=0x%04"FMT_pcibus"\n",
+           addr, size);
 #endif
 
     register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
@@ -1994,7 +1995,7 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
 
 #ifdef PCNET_DEBUG_IO
-    printf("pcnet_mmio_map addr=0x%08x 0x%08x\n", addr, size);
+    printf("pcnet_mmio_map addr=0x%08"FMT_pcibus" 0x%08"FMT_pcibus"\n", addr, size);
 #endif
 
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index d3ab3c8..93e657b 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -362,7 +362,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
     int io_mem;
 
-    i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type);
+    i6300esb_debug("addr = %"FMT_pcibus", size = %"FMT_pcibus", type = %d\n",
+                   addr, size, type);
 
     io_mem = cpu_register_io_memory(mem_read, mem_write, d);
     cpu_register_physical_memory (addr, 0x10, io_mem);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 11/25] pci: typedef pcibus_t as uint64_t instead of uint32_t.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (9 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 10/25] pci: introduce FMT_pcibus for printf format for pcibus_t Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 12/25] pci: 64bit bar support Isaku Yamahata
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch is preliminary for 64bit bar.
For 64bit bar support, change pcibus_t which represents
pci bus addr/size from uint32_t to uint64_t.
And also change FMT_pcibus for printf.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index d75b3b3..c209f34 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -71,8 +71,8 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
 
-typedef uint32_t pcibus_t;
-#define FMT_pcibus                      PRIx32
+typedef uint64_t pcibus_t;
+#define FMT_pcibus                      PRIx64
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 12/25] pci: 64bit bar support.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (10 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 11/25] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 13/25] pci: make pci configuration transaction more accurate Isaku Yamahata
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

implemented pci 64bit bar support.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   41 ++++++++++++++++++++++++++++++++++++-----
 hw/pci.h |    9 +++++++++
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 510fad2..75af2cd 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -427,8 +427,13 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
-    pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
-    pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    if (pci_bar_is_64bit(r)) {
+        pci_set_quad(pci_dev->wmask + addr, wmask);
+        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
+    } else {
+        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
+        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    }
 }
 
 static void pci_update_mappings(PCIDevice *d)
@@ -462,7 +467,11 @@ static void pci_update_mappings(PCIDevice *d)
                 }
             } else {
                 if (cmd & PCI_COMMAND_MEMORY) {
-                    new_addr = pci_get_long(d->config + config_ofs);
+                    if (pci_bar_is_64bit(r)) {
+                        new_addr = pci_get_quad(d->config + config_ofs);
+                    } else {
+                        new_addr = pci_get_long(d->config + config_ofs);
+                    }
                     /* the ROM slot has a specific enable bit */
                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                         goto no_mem_map;
@@ -477,7 +486,7 @@ static void pci_update_mappings(PCIDevice *d)
 
                         /* keep old behaviour
                          * without this, PC ide doesn't work well. */
-                        last_addr >= UINT32_MAX) {
+                        (!pci_bar_is_64bit(r) && last_addr >= UINT32_MAX)) {
                         new_addr = PCI_BAR_UNMAPPED;
                     }
                 } else {
@@ -736,7 +745,29 @@ static void pci_info_device(PCIDevice *d)
                 monitor_printf(mon, "I/O at 0x%04"FMT_pcibus" [0x%04"FMT_pcibus"].\n",
                                r->addr, r->addr + r->size - 1);
             } else {
-                monitor_printf(mon, "32 bit memory at 0x%08"FMT_pcibus" [0x%08"FMT_pcibus"].\n",
+                const char *type;
+                const char* prefetch;
+
+                switch (r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) {
+                case PCI_ADDRESS_SPACE_MEM:
+                    type = "32 bit";
+                    break;
+                case PCI_ADDRESS_SPACE_MEM_64:
+                    type = "64 bit";
+                    break;
+                default:
+                    type = "unknown";
+                    break;
+                }
+
+                prefetch = "";
+                if (r->type & PCI_ADDRESS_SPACE_MEM_PREFETCH) {
+                    prefetch = " prefetchable";
+                }
+
+                monitor_printf(mon, "%s%s memory at "
+                               "0x%08"FMT_pcibus" [0x%08"FMT_pcibus"].\n",
+                               type, prefetch,
                                r->addr, r->addr + r->size - 1);
             }
         }
diff --git a/hw/pci.h b/hw/pci.h
index c209f34..0455b30 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -84,6 +84,8 @@ typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
 
 #define PCI_ADDRESS_SPACE_MEM		0x00
 #define PCI_ADDRESS_SPACE_IO		0x01
+#define PCI_ADDRESS_SPACE_MEM_64        0x04    /* 64 bit address */
+#define PCI_ADDRESS_SPACE_MEM_TYPE_MASK 0x06
 #define PCI_ADDRESS_SPACE_MEM_PREFETCH	0x08
 
 typedef struct PCIIORegion {
@@ -94,6 +96,13 @@ typedef struct PCIIORegion {
     PCIMapIORegionFunc *map_func;
 } PCIIORegion;
 
+static inline int pci_bar_is_64bit(const PCIIORegion *r)
+{
+    return !(r->type & PCI_ADDRESS_SPACE_IO) &&
+        ((r->type & PCI_ADDRESS_SPACE_MEM_TYPE_MASK) ==
+         PCI_ADDRESS_SPACE_MEM_64);
+}
+
 #define PCI_ROM_SLOT 6
 #define PCI_NUM_REGIONS 7
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 13/25] pci: make pci configuration transaction more accurate.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (11 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 12/25] pci: 64bit bar support Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 14/25] pci: factor out the logic to get pci device from address Isaku Yamahata
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch sorts out/enhances pci code to track pci bus topology
accurately.
- Track host bus bridge with pci domain number. Although the
  current qemu support only pci domian 0 yet.
- Track pci bridge parent-child relationship.
When looking down from pci host bus for pci sub bus, be aware of
secondary bus/subordinate bus.
Thus pci configuration transaction is more accurately emulated.

This patch adds new member to PCIBus to track pci bus topology.
Since qdev already tracks down bus relationship, those new member
wouldn't be necessary.
However it would be addressed later because not all the pci device
isn't converted to qdev yet.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c     |    4 +-
 hw/pci-hotplug.c |    6 +-
 hw/pci.c         |  120 ++++++++++++++++++++++++++++++++++++++++--------------
 hw/pci.h         |   11 ++++-
 4 files changed, 102 insertions(+), 39 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index eb77042..599e354 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -253,10 +253,10 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_create_simple(d->host_state.bus, 0, "pbm");
     /* APB secondary busses */
     *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+                            PCI_DEVICE_ID_SUN_SIMBA, 1, 1, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 1");
     *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+                            PCI_DEVICE_ID_SUN_SIMBA, 2, 2, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 2");
 
     return d->host_state.bus;
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index f3dc421..890ecc3 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -65,7 +65,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    dev = pci_find_device(pci_bus, slot, 0);
+    dev = pci_find_device(pci_find_host_bus(0), pci_bus, slot, 0);
     if (!dev) {
         monitor_printf(mon, "no pci device with address %s\n", pci_addr);
         return;
@@ -201,7 +201,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
         return;
     }
 
-    d = pci_find_device(bus, slot, 0);
+    d = pci_find_device(pci_find_host_bus(0), bus, slot, 0);
     if (!d) {
         monitor_printf(mon, "slot %d empty\n", slot);
         return;
@@ -228,7 +228,7 @@ static int pci_match_fn(void *dev_private, void *arg)
  */
 void pci_device_hot_remove_success(int pcibus, int slot)
 {
-    PCIDevice *d = pci_find_device(pcibus, slot, 0);
+    PCIDevice *d = pci_find_device(pci_find_host_bus(0), pcibus, slot, 0);
     int class_code;
 
     if (!d) {
diff --git a/hw/pci.c b/hw/pci.c
index 75af2cd..7620bb5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -34,9 +34,12 @@
 # define PCI_DPRINTF(format, ...)       do { } while (0)
 #endif
 
+#define PCI_BUS_NUM_MAX 255
 struct PCIBus {
     BusState qbus;
     int bus_num;
+    int sub_bus;
+
     int devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
@@ -44,7 +47,10 @@ struct PCIBus {
     void *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
-    PCIBus *next;
+
+    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
+    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
+
     /* The bus IRQ state is the logical OR of the connected devices.
        Keep a count of the number of devices with raised IRQs.  */
     int nirq;
@@ -69,7 +75,13 @@ static void pci_set_irq(void *opaque, int irq_num, int level);
 target_phys_addr_t pci_mem_base;
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-static PCIBus *first_bus;
+
+struct PCIHostBus {
+    int domain;
+    struct PCIBus *bus;
+    QLIST_ENTRY(PCIHostBus) next;
+};
+static QLIST_HEAD(, PCIHostBus) host_buses;
 
 static const VMStateDescription vmstate_pcibus = {
     .name = "PCIBUS",
@@ -98,6 +110,28 @@ static void pci_bus_reset(void *opaque)
     }
 }
 
+static void pci_host_bus_register(int domain, PCIBus *bus)
+{
+    struct PCIHostBus *host;
+    host = qemu_mallocz(sizeof(*host));
+    host->domain = domain;
+    host->bus = bus;
+    QLIST_INSERT_HEAD(&host_buses, host, next);
+}
+
+PCIBus *pci_find_host_bus(int domain)
+{
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        if (host->domain == domain) {
+            return host->bus;
+        }
+    }
+
+    return NULL;
+}
+
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq)
@@ -112,14 +146,20 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     bus->devfn_min = devfn_min;
     bus->nirq = nirq;
     bus->irq_count = qemu_mallocz(nirq * sizeof(bus->irq_count[0]));
-    bus->next = first_bus;
-    first_bus = bus;
+
+    /* host bridge */
+    bus->bus_num = 0;
+    bus->sub_bus = PCI_BUS_NUM_MAX;
+    QLIST_INIT(&bus->child);
+    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+
     vmstate_register(nbus++, &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
     return bus;
 }
 
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
+static PCIBus *pci_register_secondary_bus(PCIBus *parent,
+                                          PCIDevice *dev,
                                           pci_map_irq_fn map_irq,
                                           const char *name)
 {
@@ -128,8 +168,11 @@ static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
     bus->parent_dev = dev;
-    bus->next = dev->bus->next;
-    dev->bus->next = bus;
+
+    bus->bus_num = dev->config[PCI_SECONDARY_BUS];
+    bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
+    QLIST_INIT(&bus->child);
+    QLIST_INSERT_HEAD(&parent->child, bus, sibling);
     return bus;
 }
 
@@ -242,7 +285,7 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *s
 	return -1;
 
     /* Note: QEMU doesn't implement domains other than 0 */
-    if (dom != 0 || pci_find_bus(bus) == NULL)
+    if (dom != 0 || pci_find_bus(pci_find_host_bus(0), bus) == NULL)
 	return -1;
 
     *domp = dom;
@@ -272,7 +315,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 
     if (!devaddr) {
         *devfnp = -1;
-        return pci_find_bus(0);
+        return pci_find_bus(pci_find_host_bus(0), 0);
     }
 
     if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) {
@@ -280,7 +323,7 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
     }
 
     *devfnp = slot << 3;
-    return pci_find_bus(bus);
+    return pci_find_bus(pci_find_host_bus(0), bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
@@ -577,8 +620,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
                 addr, val, len);
 #endif
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s = s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         return;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -599,8 +641,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     uint32_t val;
 
     bus_num = (addr >> 16) & 0xff;
-    while (s && s->bus_num != bus_num)
-        s= s->next;
+    s = pci_find_bus(s, bus_num);
     if (!s)
         goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];
@@ -707,7 +748,7 @@ static const pci_class_desc pci_class_descriptions[] =
     { 0, NULL}
 };
 
-static void pci_info_device(PCIDevice *d)
+static void pci_info_device(PCIBus *bus, PCIDevice *d)
 {
     Monitor *mon = cur_mon;
     int i, class;
@@ -774,30 +815,32 @@ static void pci_info_device(PCIDevice *d)
     }
     monitor_printf(mon, "      id \"%s\"\n", d->qdev.id ? d->qdev.id : "");
     if (class == 0x0604 && d->config[0x19] != 0) {
-        pci_for_each_device(d->config[0x19], pci_info_device);
+        pci_for_each_device(bus, d->config[0x19], pci_info_device);
     }
 }
 
-void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *b, PCIDevice *d))
 {
-    PCIBus *bus = first_bus;
     PCIDevice *d;
     int devfn;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    bus = pci_find_bus(bus, bus_num);
     if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];
             if (d)
-                fn(d);
+                fn(bus, d);
         }
     }
 }
 
 void pci_info(Monitor *mon)
 {
-    pci_for_each_device(0, pci_info_device);
+    struct PCIHostBus *host;
+    QLIST_FOREACH(host, &host_buses, next) {
+        pci_for_each_device(host->bus, 0, pci_info_device);
+    }
 }
 
 PCIDevice *pci_create(const char *name, const char *devaddr)
@@ -881,22 +924,32 @@ static void pci_bridge_write_config(PCIDevice *d,
 
     pci_default_write_config(d, address, val, len);
     s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
 }
 
-PCIBus *pci_find_bus(int bus_num)
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
 {
-    PCIBus *bus = first_bus;
+    PCIBus *sec;
 
-    while (bus && bus->bus_num != bus_num)
-        bus = bus->next;
+    if (!bus)
+        return NULL;
 
-    return bus;
+    if (bus->bus_num == bus_num) {
+        return bus;
+    }
+
+    /* try child bus */
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        if (sec->bus_num <= bus_num && bus_num <= sec->sub_bus) {
+            return pci_find_bus(sec, bus_num);
+        }
+    }
+
+    return NULL;
 }
 
-PCIDevice *pci_find_device(int bus_num, int slot, int function)
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
 {
-    PCIBus *bus = pci_find_bus(bus_num);
-
     if (!bus)
         return NULL;
 
@@ -904,6 +957,7 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
 }
 
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
+                        uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name)
 {
     PCIBridge *s;
@@ -925,7 +979,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
     s->dev.config[0x1E] = 0xa0; // secondary status
 
-    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
+    assert(sec_bus <= sub_bus);
+    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
+    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;
+
+    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
     return s->bus;
 }
 
diff --git a/hw/pci.h b/hw/pci.h
index 0455b30..2737440 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -166,6 +166,9 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 
 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
 /* Size of the standard PCI config space */
@@ -274,15 +277,17 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
-void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d));
-PCIBus *pci_find_bus(int bus_num);
-PCIDevice *pci_find_device(int bus_num, int slot, int function);
+void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
+PCIBus *pci_find_host_bus(int domain);
+PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
 
 int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
                      unsigned *slotp);
 
 void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
+                        uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name);
 
 static inline void
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 14/25] pci: factor out the logic to get pci device from address.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (12 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 13/25] pci: make pci configuration transaction more accurate Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 15/25] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

factor out conversion logic from io port address into bus+dev+func
with bit shift operation and conversion bus+dev+func into pci device.
They will be used later by pcie support.
This patch also eliminates the logic duplication.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   84 ++++++++++++++++++++++++++++++++++---------------------------
 1 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7620bb5..b11f5c3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -609,44 +609,25 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_mappings(d);
 }
 
-void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+static void pci_data_write_common(PCIDevice *pci_dev,
+                                  uint32_t config_addr, uint32_t val, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
-
-#if 0
-    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
-#endif
-    bus_num = (addr >> 16) & 0xff;
-    s = pci_find_bus(s, bus_num);
-    if (!s)
-        return;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev)
         return;
-    config_addr = addr & 0xff;
-    PCI_DPRINTF("pci_config_write: %s: "
-                "addr=%02x val=%08"PRI32x" len=%d\n",
-                pci_dev->name, config_addr, val, len);
+
+    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
     pci_dev->config_write(pci_dev, config_addr, val, len);
 }
 
-uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+static uint32_t pci_data_read_common(PCIDevice *pci_dev,
+                                     uint32_t config_addr, int len)
 {
-    PCIBus *s = opaque;
-    PCIDevice *pci_dev;
-    int config_addr, bus_num;
     uint32_t val;
 
-    bus_num = (addr >> 16) & 0xff;
-    s = pci_find_bus(s, bus_num);
-    if (!s)
-        goto fail;
-    pci_dev = s->devices[(addr >> 8) & 0xff];
+    assert(len == 1 || len == 2 || len == 4);
     if (!pci_dev) {
-    fail:
         switch(len) {
         case 1:
             val = 0xff;
@@ -659,21 +640,50 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
             val = 0xffffffff;
             break;
         }
-        goto the_end;
+    } else {
+        val = pci_dev->config_read(pci_dev, config_addr, len);
+        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
+                    __func__, pci_dev->name, config_addr, val, len);
     }
-    config_addr = addr & 0xff;
-    val = pci_dev->config_read(pci_dev, config_addr, len);
-    PCI_DPRINTF("pci_config_read: %s: "
-                "addr=%02x val=%08"PRIx32" len=%d\n",
-                pci_dev->name, config_addr, val, len);
- the_end:
+
 #if 0
-    PCI_DPRINTF("pci_data_read: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
-                addr, val, len);
+    PCI_DPRINTF("%s: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                __func__, addr, val, len);
 #endif
     return val;
 }
 
+static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
+{
+    int bus_num = (addr >> 16) & 0xff;
+    unsigned int devfn = (addr >> 8) & 0xff;
+
+    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+static inline uint32_t pci_addr_to_config(uint32_t addr)
+{
+    return addr & 0xff;
+}
+
+void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+#if 0
+    PCI_DPRINTF("pci_data_write: addr=%08"PRIx32" val=%08"PRIx32" len=%d\n",
+                addr, val, len);
+#endif
+
+    pci_data_write_common(pci_addr_to_dev(s, addr), pci_addr_to_config(addr),
+                          val, len);
+}
+
+uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_data_read_common(pci_addr_to_dev(s, addr),
+                                pci_addr_to_config(addr), len);
+}
 /***********************************************************/
 /* generic PCI irq support */
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 15/25] pci_host.h: split non-inline static function in pci_host.h into pci_host.c
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (13 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 14/25] pci: factor out the logic to get pci device from address Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 16/25] pci: pcie host and mmcfg support Isaku Yamahata
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Later a structures declared in pci_host.h, PCIHostState, will be used.
However pci_host.h doesn't allow to include itself easily. This patches
addresses it.

pci_host.h includes non-inline static functions which are instantiated
in .c by including pci_host.h. That prevents from including pci_host.h
to use PCIHostState.
So split pci_host.h non-inline static functions into pci_host.c.
Its purpose to include is to instantiate io function for mmio or ioio.
To avoid including code, we always instantiate both version.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 Makefile.target               |    8 ++--
 hw/apb_pci.c                  |   21 ++-------
 hw/grackle_pci.c              |   24 ++--------
 hw/gt64xxx.c                  |   11 +----
 hw/{pci_host.h => pci_host.c} |   61 +++++++++++++++++++++-----
 hw/pci_host.h                 |   96 ++++++-----------------------------------
 hw/piix_pci.c                 |   16 +++----
 hw/ppc4xx_pci.c               |   18 +-------
 hw/ppce500_pci.c              |   17 +------
 hw/prep_pci.c                 |   14 +++---
 hw/unin_pci.c                 |   47 +++++---------------
 11 files changed, 105 insertions(+), 228 deletions(-)
 copy hw/{pci_host.h => pci_host.c} (69%)

diff --git a/Makefile.target b/Makefile.target
index 1f4518c..2da39b7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -186,11 +186,11 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += ne2000-isa.o
+obj-i386-y += ne2000-isa.o pci_host.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
-obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o
+obj-ppc-y += vga.o vga-pci.o $(sound-obj-y) dma.o openpic.o pci_host.o
 # PREP target
 obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
 obj-ppc-y += prep_pci.o ppc_prep.o ne2000-isa.o
@@ -217,7 +217,7 @@ obj-mips-y += gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
 obj-mips-y += piix4.o parallel.o cirrus_vga.o pcspk.o $(sound-obj-y)
 obj-mips-y += mipsnet.o ne2000-isa.o
 obj-mips-y += pflash_cfi01.o
-obj-mips-y += vmware_vga.o
+obj-mips-y += vmware_vga.o pci_host.o
 
 obj-microblaze-y = petalogix_s3adsp1800_mmu.o
 
@@ -244,7 +244,7 @@ obj-cris-y += etraxfs_ser.o
 obj-cris-y += pflash_cfi02.o
 
 ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o pckbd.o apb_pci.o
+obj-sparc-y = sun4u.o pckbd.o apb_pci.o pci_host.o
 obj-sparc-y += ide/core.o ide/qdev.o ide/pci.o
 obj-sparc-y += vga.o vga-pci.o
 obj-sparc-y += fdc.o mc146818rtc.o serial.o
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 599e354..00165e5 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -28,6 +28,7 @@
 
 #include "sysbus.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -39,9 +40,6 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 #define APB_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct APBState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -136,18 +134,6 @@ static CPUReadMemoryFunc * const apb_config_read[] = {
     &apb_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_apb_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_apb_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
                                   uint32_t val)
 {
@@ -282,8 +268,9 @@ static int pci_pbm_init_device(SysBusDevice *dev)
                                             pci_apb_config_write, s);
     sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
     /* mem_data */
-    pci_mem_data = cpu_register_io_memory(pci_apb_read,
-                                          pci_apb_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
     return 0;
 }
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index d878cf6..d29175b 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -26,6 +26,7 @@
 #include "sysbus.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
@@ -37,9 +38,6 @@
 #define GRACKLE_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct GrackleState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -84,18 +82,6 @@ static CPUReadMemoryFunc * const pci_grackle_config_read[] = {
     &pci_grackle_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_grackle_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_grackle_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
 {
@@ -163,8 +149,8 @@ static int pci_grackle_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
                                             pci_grackle_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
-                                          pci_grackle_write,
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
                                           &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -185,8 +171,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_grackle_config_read,
                                             pci_grackle_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_grackle_read,
-                                          pci_grackle_write,
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
                                           &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8f9ae4a..fb7f5bd 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -25,10 +25,8 @@
 #include "hw.h"
 #include "mips.h"
 #include "pci.h"
-#include "pc.h"
-
-typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"
+#include "pc.h"
 
 //#define DEBUG
 
@@ -1119,13 +1117,6 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
     GT64120State *s;
     PCIDevice *d;
 
-    (void)&pci_host_data_writeb; /* avoid warning */
-    (void)&pci_host_data_writew; /* avoid warning */
-    (void)&pci_host_data_writel; /* avoid warning */
-    (void)&pci_host_data_readb; /* avoid warning */
-    (void)&pci_host_data_readw; /* avoid warning */
-    (void)&pci_host_data_readl; /* avoid warning */
-
     s = qemu_mallocz(sizeof(GT64120State));
     s->pci = qemu_mallocz(sizeof(GT64120PCIState));
 
diff --git a/hw/pci_host.h b/hw/pci_host.c
similarity index 69%
copy from hw/pci_host.h
copy to hw/pci_host.c
index 48862b5..5c06f03 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.c
@@ -25,10 +25,13 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
+#ifndef PCI_HOST_C
+
 /* debug PCI */
 //#define DEBUG_PCI
 
-#include "sysbus.h"
+#include "pci.h"
+#include "pci_host.h"
 
 #ifdef DEBUG_PCI
 #define PCI_DPRINTF(fmt, ...) \
@@ -37,13 +40,40 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
 #define PCI_DPRINTF(fmt, ...)
 #endif
 
-typedef struct {
-    SysBusDevice busdev;
-    uint32_t config_reg;
-    PCIBus *bus;
-} PCIHostState;
+#define PCI_HOST_C
+
+#define PCI_ADDR_T      target_phys_addr_t
+#define PCI_HOST_SUFFIX _mmio
+#define PCI_HOST_STATIC static
+
+#include "pci_host.c"
+
+CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
+    &glue(pci_host_data_writeb, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_writew, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_writel, PCI_HOST_SUFFIX),
+};
+
+CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
+    &glue(pci_host_data_readb, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_readw, PCI_HOST_SUFFIX),
+    &glue(pci_host_data_readl, PCI_HOST_SUFFIX),
+};
+
+#undef PCI_ADDR_T
+#undef PCI_HOST_SUFFIX
+#undef PCI_HOST_STATIC
 
-static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
+#define PCI_ADDR_T      uint32_t
+#define PCI_HOST_SUFFIX _ioport
+#define PCI_HOST_STATIC /* nothing. export this function */
+
+#include "pci_host.c"
+
+#else
+
+PCI_HOST_STATIC void glue(pci_host_data_writeb, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 
@@ -53,7 +83,8 @@ static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
 }
 
-static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
+PCI_HOST_STATIC void glue(pci_host_data_writew, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -65,7 +96,8 @@ static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
 }
 
-static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
+PCI_HOST_STATIC void glue(pci_host_data_writel, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr, uint32_t val)
 {
     PCIHostState *s = opaque;
 #ifdef TARGET_WORDS_BIGENDIAN
@@ -77,7 +109,8 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
         pci_data_write(s->bus, s->config_reg, val, 4);
 }
 
-static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readb, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -90,7 +123,8 @@ static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
     return val;
 }
 
-static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readw, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -105,7 +139,8 @@ static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
     return val;
 }
 
-static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
+PCI_HOST_STATIC uint32_t glue(pci_host_data_readl, PCI_HOST_SUFFIX)(
+    void* opaque, PCI_ADDR_T addr)
 {
     PCIHostState *s = opaque;
     uint32_t val;
@@ -119,3 +154,5 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
 #endif
     return val;
 }
+
+#endif
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 48862b5..ea98ed2 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -25,97 +25,27 @@
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
-/* debug PCI */
-//#define DEBUG_PCI
+#ifndef PCI_HOST_H
+#define PCI_HOST_H
 
 #include "sysbus.h"
 
-#ifdef DEBUG_PCI
-#define PCI_DPRINTF(fmt, ...) \
-do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define PCI_DPRINTF(fmt, ...)
-#endif
-
 typedef struct {
     SysBusDevice busdev;
     uint32_t config_reg;
     PCIBus *bus;
 } PCIHostState;
 
-static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-
-    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
-}
-
-static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
-}
-
-static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
-{
-    PCIHostState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg, val, 4);
-}
-
-static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-
-    if (!(s->config_reg & (1 << 31)))
-        return 0xff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
-    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-    return val;
-}
+/* for mmio */
+extern CPUWriteMemoryFunc * const pci_host_data_write_mmio[];
+extern CPUReadMemoryFunc * const pci_host_data_read_mmio[];
 
-static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
-    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
-    return val;
-}
+/* for ioio */
+void pci_host_data_writeb_ioport(void* opaque, uint32_t addr, uint32_t val);
+void pci_host_data_writew_ioport(void* opaque, uint32_t addr, uint32_t val);
+void pci_host_data_writel_ioport(void* opaque, uint32_t addr, uint32_t val);
+uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
+uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
+uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
 
-static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffffffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
-    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
-                (target_phys_addr_t)addr, val);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    return val;
-}
+#endif /* PCI_HOST_H */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index edd6df0..c8db791 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -25,12 +25,10 @@
 #include "hw.h"
 #include "pc.h"
 #include "pci.h"
+#include "pci_host.h"
 #include "isa.h"
 #include "sysbus.h"
 
-typedef uint32_t pci_addr_t;
-#include "pci_host.h"
-
 typedef PCIHostState I440FXState;
 
 typedef struct PIIX3State {
@@ -201,12 +199,12 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
 
-    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
     return 0;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 655fe86..953e6b6 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -22,8 +22,6 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc4xx.h"
-
-typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
@@ -117,18 +115,6 @@ static CPUWriteMemoryFunc * const pci4xx_cfgaddr_write[] = {
     &pci4xx_cfgaddr_writel,
 };
 
-static CPUReadMemoryFunc * const pci4xx_cfgdata_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
-static CPUWriteMemoryFunc * const pci4xx_cfgdata_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
 static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
                                   uint32_t value)
 {
@@ -392,8 +378,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = cpu_register_io_memory(pci4xx_cfgdata_read,
-                                   pci4xx_cfgdata_write,
+    index = cpu_register_io_memory(pci_host_data_read_mmio,
+                                   pci_host_data_write_mmio,
                                    &controller->pci_state);
     if (index < 0)
         goto free;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 64fccfd..4920837 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -17,7 +17,6 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppce500.h"
-typedef target_phys_addr_t pci_addr_t;
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
@@ -116,18 +115,6 @@ static CPUWriteMemoryFunc * const pcie500_cfgaddr_write[] = {
     &pcie500_cfgaddr_writel,
 };
 
-static CPUReadMemoryFunc * const pcie500_cfgdata_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
-static CPUWriteMemoryFunc * const pcie500_cfgdata_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
 static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
 {
     PPCE500PCIState *pci = opaque;
@@ -344,8 +331,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
     cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = cpu_register_io_memory(pcie500_cfgdata_read,
-                                   pcie500_cfgdata_write,
+    index = cpu_register_io_memory(pci_host_data_read_mmio,
+                                   pci_host_data_write_mmio,
                                    &controller->pci_state);
     if (index < 0)
         goto free;
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 2d8a0fa..943de90 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -24,8 +24,6 @@
 
 #include "hw.h"
 #include "pci.h"
-
-typedef uint32_t pci_addr_t;
 #include "pci_host.h"
 
 typedef PCIHostState PREPPCIState;
@@ -144,12 +142,12 @@ PCIBus *pci_prep_init(qemu_irq *pic)
     register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
 
-    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
-    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
-    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
-    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
-    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
-    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb_ioport, s);
+    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew_ioport, s);
+    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel_ioport, s);
+    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb_ioport, s);
+    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw_ioport, s);
+    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl_ioport, s);
 
     PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
                                            PPC_PCIIO_write, s);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index a202153..1d11816 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -24,6 +24,7 @@
 #include "hw.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "pci_host.h"
 
 /* debug UniNorth */
 //#define DEBUG_UNIN
@@ -35,9 +36,6 @@
 #define UNIN_DPRINTF(fmt, ...)
 #endif
 
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
 typedef struct UNINState {
     SysBusDevice busdev;
     PCIHostState host_state;
@@ -83,18 +81,6 @@ static CPUReadMemoryFunc * const pci_unin_main_config_read[] = {
     &pci_unin_main_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_unin_main_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_main_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
                                     uint32_t val)
 {
@@ -123,18 +109,6 @@ static CPUReadMemoryFunc * const pci_unin_config_read[] = {
     &pci_unin_config_readl,
 };
 
-static CPUWriteMemoryFunc * const pci_unin_write[] = {
-    &pci_host_data_writeb,
-    &pci_host_data_writew,
-    &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc * const pci_unin_read[] = {
-    &pci_host_data_readb,
-    &pci_host_data_readw,
-    &pci_host_data_readl,
-};
-
 /* Don't know if this matches real hardware, but it agrees with OHW.  */
 static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
 {
@@ -180,8 +154,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
                                             pci_unin_main_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
 
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
@@ -203,8 +178,9 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
     // XXX: s = &pci_bridge[2];
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -220,8 +196,9 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
-                                          pci_unin_main_write, &s->host_state);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio,
+                                          &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -237,8 +214,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
 
     pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_unin_read,
-                                          pci_unin_write, s);
+    pci_mem_data = cpu_register_io_memory(pci_host_data_read_mmio,
+                                          pci_host_data_write_mmio, s);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 16/25] pci: pcie host and mmcfg support.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (14 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 15/25] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 17/25] pci: fix pci_default_write_config() Isaku Yamahata
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

This patch adds common routines for pcie host bridge and pcie mmcfg.
This will be used by q35 based chipset emulation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/hw.h       |   12 +++
 hw/pci.c      |  247 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 hw/pci.h      |   36 ++++++++-
 hw/pci_host.h |   22 +++++
 4 files changed, 285 insertions(+), 32 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index cf266b3..478b0b2 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -428,6 +428,18 @@ extern const VMStateDescription vmstate_pci_device;
             + type_check(PCIDevice,typeof_field(_state, _field))     \
 }
 
+extern const VMStateDescription vmstate_pcie_device;
+
+#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .version_id = 2,                                                 \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pcie_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(PCIDevice,typeof_field(_state, _field))     \
+}
+
 /* _f : field name
    _f_n : num of elements field_name
    _n : num of elements
diff --git a/hw/pci.c b/hw/pci.c
index b11f5c3..1afcfb8 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -23,6 +23,7 @@
  */
 #include "hw.h"
 #include "pci.h"
+#include "pci_host.h"
 #include "monitor.h"
 #include "net.h"
 #include "sysemu.h"
@@ -184,9 +185,12 @@ int pci_bus_num(PCIBus *s)
 static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
-    uint8_t config[size];
+    uint8_t *config;
     int i;
 
+    assert(size == pcie_config_size(s));
+    config = qemu_malloc(size * sizeof(config[0]));
+
     qemu_get_buffer(f, config, size);
     for (i = 0; i < size; ++i)
         if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i])
@@ -195,6 +199,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 
     pci_update_mappings(s);
 
+    qemu_free(config);
     return 0;
 }
 
@@ -202,6 +207,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 static void put_pci_config_device(QEMUFile *f, const void *pv, size_t size)
 {
     const uint8_t *v = pv;
+    assert(size == pcie_config_size(container_of(pv, PCIDevice, config)));
     qemu_put_buffer(f, v, size);
 }
 
@@ -211,6 +217,17 @@ static VMStateInfo vmstate_info_pci_config = {
     .put  = put_pci_config_device,
 };
 
+#define VMSTATE_PCI_CONFIG(_field, _state, _version, _info, _type,   \
+                           _size) {                                  \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &(_info),                                          \
+    .flags      = VMS_SINGLE | VMS_POINTER,                          \
+    .offset     = offsetof(_state, _field)                           \
+            + type_check(_type,typeof_field(_state, _field))         \
+}
+
 const VMStateDescription vmstate_pci_device = {
     .name = "PCIDevice",
     .version_id = 2,
@@ -218,21 +235,46 @@ const VMStateDescription vmstate_pci_device = {
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_INT32_LE(version_id, PCIDevice),
-        VMSTATE_SINGLE(config, PCIDevice, 0, vmstate_info_pci_config,
-                       typeof_field(PCIDevice,config)),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCI_CONFIG_SPACE_SIZE),
+        VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_pcie_device = {
+    .name = "PCIDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_PCI_CONFIG(config, PCIDevice, 0, vmstate_info_pci_config,
+                           typeof_field(PCIDevice, config),
+                           PCIE_CONFIG_SPACE_SIZE),
         VMSTATE_INT32_ARRAY_V(irq_state, PCIDevice, PCI_NUM_PINS, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
+static const VMStateDescription *pci_get_vmstate(PCIDevice *s)
+{
+    if (pci_is_pcie(s)) {
+        return &vmstate_pcie_device;
+    }
+
+    return &vmstate_pci_device;
+}
+
 void pci_device_save(PCIDevice *s, QEMUFile *f)
 {
-    vmstate_save_state(f, &vmstate_pci_device, s);
+    vmstate_save_state(f, pci_get_vmstate(s), s);
 }
 
 int pci_device_load(PCIDevice *s, QEMUFile *f)
 {
-    return vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
+    return vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
 }
 
 static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
@@ -341,14 +383,31 @@ static void pci_init_cmask(PCIDevice *dev)
 static void pci_init_wmask(PCIDevice *dev)
 {
     int i;
+    uint32_t config_size = pcie_config_size(dev);
+
     dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
     dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
     dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
                               | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         dev->wmask[i] = 0xff;
 }
 
+static void pci_config_alloc(PCIDevice *pci_dev)
+{
+    int config_size = pcie_config_size(pci_dev);
+#define PCI_CONFIG_ALLOC(d, member, size)                               \
+    do {                                                                \
+        (d)->member =                                                   \
+            (typeof((d)->member))qemu_mallocz(sizeof((d)->member[0]) *  \
+                                              size);                    \
+    } while (0)
+    PCI_CONFIG_ALLOC(pci_dev, config, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, cmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, wmask, config_size);
+    PCI_CONFIG_ALLOC(pci_dev, used, config_size);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
@@ -369,6 +428,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
+    pci_config_alloc(pci_dev);
     pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
     pci_init_wmask(pci_dev);
@@ -566,40 +626,48 @@ static void pci_update_mappings(PCIDevice *d)
     }
 }
 
+static uint8_t pcie_config_get_byte(PCIDevice *d, uint32_t addr)
+{
+    uint8_t *conf = &d->config[addr];
+    if (conf != NULL)
+        return *conf;
+    return 0;
+}
+
+static uint32_t pcie_config_get(PCIDevice *d, uint32_t addr, int len)
+{
+    int i;
+    union {
+        uint8_t val8[4];
+        uint32_t val32;
+    } v = { .val32 = 0 };
+
+    for (i = 0; i < len; i++) {
+        v.val8[i] = pcie_config_get_byte(d, addr + i);
+    }
+
+    return le32_to_cpu(v.val32);
+}
+
 uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
-    uint32_t val;
+    uint32_t config_size = pcie_config_size(d);
 
-    switch(len) {
-    default:
-    case 4:
-	if (address <= 0xfc) {
-            val = pci_get_long(d->config + address);
-	    break;
-	}
-	/* fall through */
-    case 2:
-        if (address <= 0xfe) {
-            val = pci_get_word(d->config + address);
-	    break;
-	}
-	/* fall through */
-    case 1:
-        val = pci_get_byte(d->config + address);
-        break;
-    }
-    return val;
+    assert(len == 1 || len == 2 || len == 4);
+    len = MIN(len, config_size - MIN(config_size, address));
+    return pcie_config_get(d, address, len);
 }
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
     uint8_t orig[PCI_CONFIG_SPACE_SIZE];
     int i;
+    uint32_t config_size = pcie_config_size(d);
 
     /* not efficient, but simple */
     memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
-    for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) {
+    for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
@@ -684,6 +752,128 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     return pci_data_read_common(pci_addr_to_dev(s, addr),
                                 pci_addr_to_config(addr), len);
 }
+
+#define PCIE_MASK(val, hi_bit, low_bit)                 \
+    (((val) & (((1ULL << (hi_bit)) - 1))) >> (low_bit))
+#define PCIE_VAL(VAL, val)                                              \
+    PCIE_MASK((val), PCIE_MMCFG_ ## VAL ## _HI, PCIE_MMCFG_ ## VAL ## _LOW)
+#define PCIE_MMCFG_BUS_HI               28
+#define PCIE_MMCFG_BUS_LOW              20
+#define PCIE_MMCFG_DEV_HI               19
+#define PCIE_MMCFG_DEV_LOW              15
+#define PCIE_MMCFG_FUNC_HI              14
+#define PCIE_MMCFG_FUNC_LOW             12
+#define PCIE_MMCFG_CONFADDR_HI          11
+#define PCIE_MMCFG_CONFADDR_LOW         0
+#define PCIE_MMCFG_BUS(addr)            PCIE_VAL(BUS, (addr))
+#define PCIE_MMCFG_DEV(addr)            PCIE_VAL(DEV, (addr))
+#define PCIE_MMCFG_FUNC(addr)           PCIE_VAL(FUNC, (addr))
+#define PCIE_MMCFG_CONFADDR(addr)       PCIE_VAL(CONFADDR, (addr))
+
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
+{
+    PCIBus *s = opaque;
+    pci_data_write_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
+                                          PCIE_MMCFG_DEV(addr),
+                                          PCIE_MMCFG_FUNC(addr)),
+                          PCIE_MMCFG_CONFADDR(addr),
+                          val, len);
+}
+
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len)
+{
+    PCIBus *s = opaque;
+    return pci_data_read_common(pci_find_device(s, PCIE_MMCFG_BUS(addr),
+                                                PCIE_MMCFG_DEV(addr),
+                                                PCIE_MMCFG_FUNC(addr)),
+                                PCIE_MMCFG_CONFADDR(addr),
+                                len);
+}
+
+#define DEFINE_PCIE_HOST_DATA_READ(len)                         \
+    static uint32_t pcie_host_data_read_ ## len (               \
+        void *opaque, target_phys_addr_t addr)                  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        return pcie_data_read(e->pci.bus,                       \
+                              addr - e->base_addr, (len));      \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_WRITE(len)                        \
+    static void pcie_host_data_write_ ## len (                  \
+        void *opaque, target_phys_addr_t addr, uint32_t value)  \
+    {                                                           \
+        PCIExpressHost *e = (PCIExpressHost *)opaque;           \
+        pcie_data_write(e->pci.bus,                             \
+                        addr - e->base_addr, value, (len));     \
+    }
+
+#define DEFINE_PCIE_HOST_DATA_MMIO(len)      \
+        DEFINE_PCIE_HOST_DATA_READ(len)      \
+        DEFINE_PCIE_HOST_DATA_WRITE(len)
+
+DEFINE_PCIE_HOST_DATA_MMIO(1)
+DEFINE_PCIE_HOST_DATA_MMIO(2)
+DEFINE_PCIE_HOST_DATA_MMIO(4)
+
+#define DEFINE_PCIE_MEMORY_FUNCS(Type, type)                            \
+    static CPU ## Type ## MemoryFunc *pcie_host_data_ ## type [] =      \
+    {                                                                   \
+        &pcie_host_data_ ## type ## _1,                                 \
+        &pcie_host_data_ ## type ## _2,                                 \
+        &pcie_host_data_ ## type ## _4,                                 \
+    };
+
+DEFINE_PCIE_MEMORY_FUNCS(Read, read)
+DEFINE_PCIE_MEMORY_FUNCS(Write, write)
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write)
+{
+    e->base_addr = PCIE_BASE_ADDR_INVALID;
+
+    if (mmcfg_read == NULL)
+        mmcfg_read = pcie_host_data_read;
+    if (mmcfg_write == NULL)
+        mmcfg_write = pcie_host_data_write;
+    e->mmio_index = cpu_register_io_memory(mmcfg_read, mmcfg_write, e);
+    if (e->mmio_index < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e)
+{
+    if (e->base_addr != PCIE_BASE_ADDR_INVALID) {
+        cpu_register_physical_memory(e->base_addr, e->size, IO_MEM_UNASSIGNED);
+    }
+}
+
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size)
+{
+    assert((size & (size - 1)) == 0); /* power of 2 */
+    assert(size >= (1ULL << PCIE_MMCFG_BUS_LOW));
+    assert(size <= (1ULL << PCIE_MMCFG_BUS_HI));
+
+    e->base_addr = addr;
+    e->size = size;
+    cpu_register_physical_memory(e->base_addr, e->size, e->mmio_index);
+}
+
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size)
+{
+    pcie_host_mmcfg_unmap(e);
+    if (enable) {
+        pcie_host_mmcfg_map(e, addr, size);
+    }
+}
+
 /***********************************************************/
 /* generic PCI irq support */
 
@@ -1045,9 +1235,10 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
 
 static int pci_find_space(PCIDevice *pdev, uint8_t size)
 {
+    int config_size = pcie_config_size(pdev);
     int offset = PCI_CONFIG_HEADER_SIZE;
     int i;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
         if (pdev->used[i])
             offset = i + 1;
         else if (i - offset + 1 == size)
diff --git a/hw/pci.h b/hw/pci.h
index 2737440..66d899d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -181,20 +181,26 @@ enum {
     QEMU_PCI_CAP_MSIX = 0x1,
 };
 
+/* Size of the standart PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE  0x1000
+#define PCIE_EXT_CONFIG_SPACE_SIZE                      \
+    (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE)
+
 struct PCIDevice {
     DeviceState qdev;
+
     /* PCI config space */
-    uint8_t config[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *config;
 
     /* Used to enable config checks on load. Note that writeable bits are
      * never checked even if set in cmask. */
-    uint8_t cmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *cmask;
 
     /* Used to implement R/W bytes */
-    uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *wmask;
 
     /* Used to allocate config space for capabilities. */
-    uint8_t used[PCI_CONFIG_SPACE_SIZE];
+    uint8_t *used;
 
     /* the following fields are read only */
     PCIBus *bus;
@@ -276,6 +282,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
                         const char *default_devaddr);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
+void pcie_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
+uint32_t pcie_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
 void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
 PCIBus *pci_find_host_bus(int domain);
@@ -362,6 +370,9 @@ typedef struct {
     pci_qdev_initfn init;
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
+
+    /* pcie stuff */
+    int pcie;
 } PCIDeviceInfo;
 
 void pci_qdev_register(PCIDeviceInfo *info);
@@ -371,6 +382,23 @@ PCIDevice *pci_create(const char *name, const char *devaddr);
 PCIDevice *pci_create_noinit(PCIBus *bus, int devfn, const char *name);
 PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
 
+static inline int pci_is_pcie(PCIDevice *d)
+{
+    /*
+     * At the moment, all the pci devices aren't qdevfied. So
+     * d->qdev.info might be NULL.
+     * Given that pcie device emulator hasn't exist, we conclude that
+     * such a device isn't pcie.
+     */
+    return d->qdev.info != NULL &&
+        container_of(d->qdev.info, PCIDeviceInfo, qdev)->pcie;
+}
+
+static inline uint32_t pcie_config_size(PCIDevice *d)
+{
+    return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index ea98ed2..59147cf 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -48,4 +48,26 @@ uint32_t pci_host_data_readb_ioport(void* opaque, uint32_t addr);
 uint32_t pci_host_data_readw_ioport(void* opaque, uint32_t addr);
 uint32_t pci_host_data_readl_ioport(void* opaque, uint32_t addr);
 
+typedef struct {
+    PCIHostState pci;
+
+    /* express part */
+    target_phys_addr_t  base_addr;
+#define PCIE_BASE_ADDR_INVALID  ((target_phys_addr_t)-1ULL)
+    target_phys_addr_t  size;
+    int bus_num_order;
+    int mmio_index;
+} PCIExpressHost;
+
+int pcie_host_init(PCIExpressHost *e,
+                   CPUReadMemoryFunc **mmcfg_read,
+                   CPUWriteMemoryFunc **mmcfg_write);
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e);
+void pcie_host_mmcfg_map(PCIExpressHost *e,
+                         target_phys_addr_t addr, uint32_t size);
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            target_phys_addr_t addr, uint32_t size);
+
 #endif /* PCI_HOST_H */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 17/25] pci: fix pci_default_write_config()
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (15 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 16/25] pci: pcie host and mmcfg support Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-04  8:36   ` [Qemu-devel] " Michael S. Tsirkin
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 18/25] pci: add helper functions for pci config write function Isaku Yamahata
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata, Michael S. Tsirkin

When updated ROM expantion address of header type 0, it missed
to update mappings.
Add PCI_ROM_ADDRESS check whether to call pci_update_mappings()

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |    3 ++-
 hw/pci.h |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 1afcfb8..c9054c1 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -671,7 +671,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
-    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
+    if ((memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) ||
+         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
         || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
             & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
         pci_update_mappings(d);
diff --git a/hw/pci.h b/hw/pci.h
index 66d899d..3ea5258 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -144,6 +144,7 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
 #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
 
+#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
 #define  PCI_ROM_ADDRESS_ENABLE 0x01
 
 /* Bits in the PCI Status Register (PCI 2.3 spec) */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 18/25] pci: add helper functions for pci config write function.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (16 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 17/25] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 19/25] pci: use helper function in pci_default_write_config() Isaku Yamahata
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper functions for pci config write function to check
if its configuration space is changed..
Those function will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.h |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/pci.h b/hw/pci.h
index 3ea5258..ec989f0 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -400,6 +400,50 @@ static inline uint32_t pcie_config_size(PCIDevice *d)
     return pci_is_pcie(d)? PCIE_CONFIG_SPACE_SIZE: PCI_CONFIG_SPACE_SIZE;
 }
 
+static inline uint8_t *pci_write_config_init(PCIDevice *d,
+                                             uint32_t addr, int len)
+{
+    uint8_t *orig = qemu_malloc(pcie_config_size(d));
+    memcpy(orig + addr, d->config + addr, len);
+    return orig;
+}
+
+static inline void pci_write_config_done(uint8_t *orig)
+{
+    qemu_free(orig);
+}
+
+static inline int pci_config_changed(const uint8_t *orig, const uint8_t *new,
+                                     uint32_t addr, uint32_t len,
+                                     uint32_t base, uint32_t end)
+{
+    uint32_t low = MAX(addr, base);
+    uint32_t high = MIN(addr + len, end);
+
+    /* check if [addr, addr + len) intersects [base, end)
+       the intersection is [log, high) */
+    if (low >= high)
+        return 0;
+
+    return memcmp(orig + low, new + low, high - low);
+}
+
+static inline int pci_config_changed_with_size(const uint8_t *orig,
+                                               const uint8_t *new,
+                                               uint32_t addr, uint32_t len,
+                                               uint32_t base, uint32_t size)
+{
+    uint32_t low = MAX(addr, base);
+    uint32_t high = MIN(addr + len, base + size);
+
+    /* check if [addr, addr + len) intersects [base, base + size)
+       the intersection is [log, high) */
+    if (low >= high)
+        return 0;
+
+    return memcmp(orig + low, new + low, high - low);
+}
+
 /* lsi53c895a.c */
 #define LSI_MAX_DEVS 7
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 19/25] pci: use helper function in pci_default_write_config()
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (17 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 18/25] pci: add helper functions for pci config write function Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 20/25] pci: factor out config update logic Isaku Yamahata
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata, Michael S. Tsirkin

use helper function in pci_default_write_config() to
check whether the configuration space is changed.

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   18 +++++++++++-------
 hw/pci.h |    7 ++++++-
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index c9054c1..880a8ae 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -661,21 +661,25 @@ uint32_t pci_default_read_config(PCIDevice *d,
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
-    uint8_t orig[PCI_CONFIG_SPACE_SIZE];
     int i;
     uint32_t config_size = pcie_config_size(d);
+    uint8_t *orig = pci_write_config_init(d, addr, l);
 
-    /* not efficient, but simple */
-    memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
     for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
-    if ((memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) ||
-         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
-        || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
-            & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
+
+    if (pci_config_changed(orig, d->config, addr, l,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
+        pci_config_changed_with_size(orig, d->config, addr, l,
+                                     PCI_ROM_ADDRESS, 4) ||
+        pci_config_changed_with_size(orig, d->config, addr, l,
+                                     PCI_COMMAND, 1)) {
         pci_update_mappings(d);
+    }
+
+    pci_write_config_done(orig);
 }
 
 static void pci_data_write_common(PCIDevice *pci_dev,
diff --git a/hw/pci.h b/hw/pci.h
index ec989f0..f19b7a8 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -124,7 +124,12 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define  PCI_HEADER_TYPE_BRIDGE		1
 #define  PCI_HEADER_TYPE_CARDBUS	2
 #define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
-#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
 #define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
 #define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
 #define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 20/25] pci: factor out config update logic.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (18 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 19/25] pci: use helper function in pci_default_write_config() Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 21/25] pci: make bar update function aware of pci bridge Isaku Yamahata
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

Updating BAR in pci bar is specific to header type 00.
So split out the logic to common to header type 01 which
will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 880a8ae..7910800 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -659,16 +659,24 @@ uint32_t pci_default_read_config(PCIDevice *d,
     return pcie_config_get(d, address, len);
 }
 
-void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+static void pci_default_write_config_common(PCIDevice *d,
+                                            uint32_t addr, uint32_t val, int l)
 {
     int i;
     uint32_t config_size = pcie_config_size(d);
-    uint8_t *orig = pci_write_config_init(d, addr, l);
 
+    assert(l == 1 || l == 2 || l == 4);
     for(i = 0; i < l && addr < config_size; val >>= 8, ++i, ++addr) {
         uint8_t wmask = d->wmask[addr];
         d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
     }
+}
+
+void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+{
+    uint8_t *orig = pci_write_config_init(d, addr, l);
+
+    pci_default_write_config_common(d, addr, val, l);
 
     if (pci_config_changed(orig, d->config, addr, l,
                            PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_5 + 4) ||
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 21/25] pci: make bar update function aware of pci bridge.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (19 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 20/25] pci: factor out config update logic Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 22/25] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

header type of 01 has differenct BAR to type 00.
It has only BAR0,1 and expantion rom whose offset address
is different from type 00 one.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++----------
 hw/pci.h |    1 +
 2 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 7910800..1d638c4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -498,6 +498,35 @@ int pci_unregister_device(PCIDevice *pci_dev)
     return 0;
 }
 
+#define PCI_BAR_INVALID  UINT32_MAX
+static uint32_t pci_bar_config_offset(PCIDevice *d, int region_num)
+{
+    switch (d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION) {
+    case PCI_HEADER_TYPE_NORMAL:
+        /* BAR 0-5 and Expantion ROM*/
+        if (region_num < PCI_ROM_SLOT) {
+            return PCI_BASE_ADDRESS_0 + region_num * 4;
+        } else if (region_num == PCI_ROM_SLOT) {
+            return PCI_ROM_ADDRESS;
+        }
+        break;
+    case PCI_HEADER_TYPE_BRIDGE:
+        /* BAR 0-1 and Expantion ROM */
+        if (region_num < 2) {
+            return PCI_BASE_ADDRESS_0 + region_num * 4;
+        } else if (region_num == PCI_ROM_SLOT) {
+            return PCI_ROM_ADDRESS1;
+        }
+        break;
+    case PCI_HEADER_TYPE_CARDBUS:
+    default:
+        break;
+    }
+    fprintf(stderr, "ERROR: %s: unknow PCI config header type %d or bar %d\n",
+            __func__, d->config[PCI_HEADER_TYPE], region_num);
+    return PCI_BAR_INVALID;
+}
+
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             pcibus_t size, int type,
                             PCIMapIORegionFunc *map_func)
@@ -521,13 +550,11 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
 
+    addr = pci_bar_config_offset(pci_dev, region_num);
     wmask = ~(size - 1);
     if (region_num == PCI_ROM_SLOT) {
-        addr = 0x30;
         /* ROM enable bit is writeable */
         wmask |= PCI_ROM_ADDRESS_ENABLE;
-    } else {
-        addr = 0x10 + region_num * 4;
     }
     pci_set_long(pci_dev->config + addr, type);
     if (pci_bar_is_64bit(r)) {
@@ -549,11 +576,9 @@ static void pci_update_mappings(PCIDevice *d)
     cmd = pci_get_word(d->config + PCI_COMMAND);
     for(i = 0; i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
-        if (i == PCI_ROM_SLOT) {
-            config_ofs = 0x30;
-        } else {
-            config_ofs = 0x10 + i * 4;
-        }
+
+        config_ofs = pci_bar_config_offset(d, i);
+
         if (r->size != 0) {
             if (r->type & PCI_ADDRESS_SPACE_IO) {
                 if (cmd & PCI_COMMAND_IO) {
@@ -1134,10 +1159,29 @@ static void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
+    PCIBus *bus = s->bus;
+    uint8_t *orig = pci_write_config_init(d, address, len);
+
+    pci_default_write_config_common(d, address, val, len);
 
-    pci_default_write_config(d, address, val, len);
-    s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
-    s->bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
+    if (pci_config_changed(orig, d->config, address, len,
+                           PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_2 + 4) ||
+        pci_config_changed_with_size(orig, d->config, address, len,
+                                     PCI_ROM_ADDRESS1, 4) ||
+        pci_config_changed_with_size(orig, d->config, address, len,
+                                     PCI_COMMAND, 1)) {
+        pci_update_mappings(d);
+    }
+    if (pci_config_changed_with_size(orig, d->config, address, len,
+                                     PCI_SECONDARY_BUS, 1)) {
+        bus->bus_num = d->config[PCI_SECONDARY_BUS];
+    }
+    if (pci_config_changed_with_size(orig, d->config, address, len,
+                                     PCI_SECONDARY_BUS, 1)) {
+        bus->sub_bus = d->config[PCI_SUBORDINATE_BUS];
+    }
+
+    pci_write_config_done(orig);
 }
 
 PCIBus *pci_find_bus(PCIBus *bus, int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index f19b7a8..645dacd 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -174,6 +174,7 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 22/25] pci/brdige: qdevfy and initialize secondary bus and subordinate bus.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (20 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 21/25] pci: make bar update function aware of pci bridge Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 23/25] pci: add helper function to initialize wmask Isaku Yamahata
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

qdevfy pci bridge, and
initialize secondary bus and subordinate bus in configuration space.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/apb_pci.c |    6 ++-
 hw/pci.c     |  110 +++++++++++++++++++++++++++++++++++++++++++---------------
 hw/pci.h     |   12 ++++++
 3 files changed, 98 insertions(+), 30 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 00165e5..5ccb654 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -238,10 +238,12 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                                          0, 32);
     pci_create_simple(d->host_state.bus, 0, "pbm");
     /* APB secondary busses */
-    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
+    *bus2 = pci_bridge_init(d->host_state.bus,
+                            PCI_DEVFN(1, 0), PCI_VENDOR_ID_SUN,
                             PCI_DEVICE_ID_SUN_SIMBA, 1, 1, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 1");
-    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
+    *bus3 = pci_bridge_init(d->host_state.bus,
+                            PCI_DEVFN(1, 1), PCI_VENDOR_ID_SUN,
                             PCI_DEVICE_ID_SUN_SIMBA, 2, 2, pci_apb_map_irq,
                             "Advanced PCI Bus secondary bridge 2");
 
diff --git a/hw/pci.c b/hw/pci.c
index 1d638c4..2b3591b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -133,12 +133,17 @@ PCIBus *pci_find_host_bus(int domain)
     return NULL;
 }
 
+static int pci_bus_get_instance_id(void)
+{
+    static int nbus = 0;
+    return nbus++;
+}
+
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque, int devfn_min, int nirq)
 {
     PCIBus *bus;
-    static int nbus = 0;
 
     bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, parent, name));
     bus->set_irq = set_irq;
@@ -154,7 +159,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
     QLIST_INIT(&bus->child);
     pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
 
-    vmstate_register(nbus++, &vmstate_pcibus, bus);
+    vmstate_register(pci_bus_get_instance_id(), &vmstate_pcibus, bus);
     qemu_register_reset(pci_bus_reset, bus);
     return bus;
 }
@@ -162,7 +167,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 static PCIBus *pci_register_secondary_bus(PCIBus *parent,
                                           PCIDevice *dev,
                                           pci_map_irq_fn map_irq,
-                                          const char *name)
+                                          const char *name, int devfn_min)
 {
     PCIBus *bus;
 
@@ -172,8 +177,10 @@ static PCIBus *pci_register_secondary_bus(PCIBus *parent,
 
     bus->bus_num = dev->config[PCI_SECONDARY_BUS];
     bus->sub_bus = dev->config[PCI_SUBORDINATE_BUS];
+    bus->devfn_min = devfn_min;
     QLIST_INIT(&bus->child);
     QLIST_INSERT_HEAD(&parent->child, bus, sibling);
+    vmstate_register(pci_bus_get_instance_id(), &vmstate_pcibus, bus);
     return bus;
 }
 
@@ -1155,7 +1162,7 @@ typedef struct {
     PCIBus *bus;
 } PCIBridge;
 
-static void pci_bridge_write_config(PCIDevice *d,
+void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
@@ -1213,35 +1220,82 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
-PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
-                        uint8_t sec_bus, uint8_t sub_bus,
-                        pci_map_irq_fn map_irq, const char *name)
+int pci_bridge_initfn(PCIDevice *pci_dev)
 {
-    PCIBridge *s;
-    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
-                                         devfn, NULL, pci_bridge_write_config);
-
-    pci_config_set_vendor_id(s->dev.config, vid);
-    pci_config_set_device_id(s->dev.config, did);
-
-    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
-    s->dev.config[0x05] = 0x00;
-    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    s->dev.config[0x07] = 0x00; // status = fast devsel
-    s->dev.config[0x08] = 0x00; // revision
-    s->dev.config[0x09] = 0x00; // programming i/f
-    pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
-    s->dev.config[0x0D] = 0x10; // latency_timer
-    s->dev.config[PCI_HEADER_TYPE] =
+    uint8_t *pci_conf;
+
+    pci_conf = pci_dev->config;
+    pci_conf[0x04] = 0x06; // command = bus master, pci mem
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_conf[0x07] = 0x00; // status = fast devsel
+    pci_conf[0x08] = 0x00; // revision
+    pci_conf[0x09] = 0x00; // programming i/f
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_PCI);
+    pci_conf[0x0D] = 0x10; // latency_timer
+    pci_conf[PCI_HEADER_TYPE] =
         PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
-    s->dev.config[0x1E] = 0xa0; // secondary status
+    pci_conf[0x18] = pci_dev->bus->bus_num;// primary bus number
+    /* secondary bus and subordinate bus will be set by the caller */
+    pci_conf[0x1E] = 0xa0; // secondary status
+
+    /* vid/did will be set later */
+
+    return 0;
+}
+
+#define PCI_BRIDGE_DEFAULT      "default PCI to PCI bridge"
+static PCIDeviceInfo pci_bridge_info_default = {
+    .qdev.name = PCI_BRIDGE_DEFAULT,
+    .qdev.size = sizeof(PCIBridge),
+    .config_write = pci_bridge_write_config,
+    .init = pci_bridge_initfn,
+    .pcie = 0,
+};
+
+static void pci_bridge_register_device(void)
+{
+    pci_qdev_register(&pci_bridge_info_default);
+}
+device_init(pci_bridge_register_device);
+
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
+                                 uint16_t vid, uint16_t did,
+                                 uint8_t sec_bus, uint8_t sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name)
+{
+    DeviceState *qdev;
+    uint8_t* pci_conf;
+    PCIDevice *d;
+    PCIBridge *br;
+
+    qdev = qdev_create(&bus->qbus, name);
+
+    qdev_prop_set_uint32(qdev, "addr", devfn);
+
+    qdev_init(qdev);
+
+    d = DO_UPCAST(PCIDevice, qdev, qdev);
+    pci_conf = d->config;
+    pci_config_set_vendor_id(pci_conf, vid);
+    pci_config_set_device_id(pci_conf, did);
 
     assert(sec_bus <= sub_bus);
-    s->dev.config[PCI_SECONDARY_BUS] = sec_bus;
-    s->dev.config[PCI_SUBORDINATE_BUS] = sub_bus;
+    pci_set_byte(d->config + PCI_SECONDARY_BUS, sec_bus);
+    pci_set_byte(d->config + PCI_SUBORDINATE_BUS, sub_bus);
 
-    s->bus = pci_register_secondary_bus(bus, &s->dev, map_irq, name);
-    return s->bus;
+    br = DO_UPCAST(PCIBridge, dev, d);
+    br->bus = pci_register_secondary_bus(bus, d, map_irq, name, 0);
+    return br->bus;
+}
+
+PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
+                        uint16_t did, uint8_t sec_bus, uint8_t sub_bus,
+                        pci_map_irq_fn map_irq, const char *name)
+{
+    return pci_bridge_create_simple(bus, devfn, vid, did, sec_bus, sub_bus,
+                                    map_irq, name, PCI_BRIDGE_DEFAULT);
 }
 
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
diff --git a/hw/pci.h b/hw/pci.h
index 645dacd..be241b4 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -175,6 +175,8 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -304,6 +306,16 @@ void pci_info(Monitor *mon);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         uint8_t sec_bus, uint8_t sub_bus,
                         pci_map_irq_fn map_irq, const char *name);
+PCIBus *pci_bridge_create_simple(PCIBus *bus, int devfn,
+                                 uint16_t vid, uint16_t did,
+                                 uint8_t sec_bus, uint8_t sub_bus,
+                                 pci_map_irq_fn map_irq, const char *bus_name,
+                                 const char *name);
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len);
+int pci_bridge_initfn(PCIDevice *pci_dev);
+void pci_bridge_set_map_irq(PCIBus *bus, pci_map_irq_fn map_irq);
+
 
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 23/25] pci: add helper function to initialize wmask.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (21 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 22/25] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 24/25] pci: initialize wmask according to pci header type Isaku Yamahata
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

add helper function to initialize wmask.
This will be used later.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   25 +++++++++++++++++++++++++
 hw/pci.h |    4 ++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 2b3591b..13506d4 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -415,6 +415,31 @@ static void pci_config_alloc(PCIDevice *pci_dev)
     PCI_CONFIG_ALLOC(pci_dev, used, config_size);
 }
 
+static void pci_conf_init(PCIDevice *d, uint32_t addr, uint32_t wmask, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        d->wmask[addr + i] = wmask & 0xff;
+        wmask >>= 8;
+    }
+}
+
+void pci_conf_initb(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 1);
+}
+
+void pci_conf_initw(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 2);
+}
+
+void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask)
+{
+    pci_conf_init(d, addr, wmask, 4);
+}
+
 /* -1 for devfn means auto assign */
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
diff --git a/hw/pci.h b/hw/pci.h
index be241b4..56285e2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -255,6 +255,10 @@ struct PCIDevice {
     target_phys_addr_t msix_page_size;
 };
 
+void pci_conf_initb(PCIDevice *d, uint32_t addr, uint32_t wmask);
+void pci_conf_initw(PCIDevice *d, uint32_t addr, uint32_t wmask);
+void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask);
+
 PCIDevice *pci_register_device(PCIBus *bus, const char *name,
                                int instance_size, int devfn,
                                PCIConfigReadFunc *config_read,
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 24/25] pci: initialize wmask according to pci header type.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (22 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 23/25] pci: add helper function to initialize wmask Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 25/25] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
  2009-10-02 13:21 ` [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Gerd Hoffmann
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

- initialize wmask according to pci header type.
  So far, header of type 01  was not correctly initialized.
- only sets default subsystem id for header type 00.
  header type 01 doesn't have subsystem id, and uses the register
  for other purpose. So setting default subsystem id doesn't make sense.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/cirrus_vga.c |    2 +-
 hw/pci.c        |  105 ++++++++++++++++++++++++++++++++++++++++++++++++------
 hw/pci.h        |   41 +++++++++++++++++++++-
 3 files changed, 134 insertions(+), 14 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 2a6aba8..55ef4c1 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -180,7 +180,7 @@
 #define PCI_COMMAND_PALETTESNOOPING         0x0020
 #define PCI_COMMAND_PARITYDETECTION         0x0040
 #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
-#define PCI_COMMAND_SERR                    0x0100
+// #define PCI_COMMAND_SERR                    0x0100 /* duplicated */
 #define PCI_COMMAND_BACKTOBACKTRANS         0x0200
 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
 #define PCI_CLASS_BASE_DISPLAY        0x03
diff --git a/hw/pci.c b/hw/pci.c
index 13506d4..2be853e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -387,17 +387,33 @@ static void pci_init_cmask(PCIDevice *dev)
     dev->cmask[PCI_CAPABILITY_LIST] = 0xff;
 }
 
-static void pci_init_wmask(PCIDevice *dev)
+static void pci_conf_init_type_00_default(PCIDevice *dev)
 {
     int i;
     uint32_t config_size = pcie_config_size(dev);
 
-    dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
-    dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
-    dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
-                              | PCI_COMMAND_MASTER;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
-        dev->wmask[i] = 0xff;
+    pci_set_default_subsystem_id(dev);
+
+    pci_conf_initw(dev, PCI_COMMAND,
+                   PCI_COMMAND_IO |
+                   PCI_COMMAND_MEMORY |
+                   PCI_COMMAND_MASTER |
+                   PCI_COMMAND_SPECIAL |
+                   PCI_COMMAND_INVALIDATE |
+                   PCI_COMMAND_VGA_PALETTE |
+                   PCI_COMMAND_PARITY |
+                   PCI_COMMAND_WAIT |
+                   PCI_COMMAND_SERR |
+                   PCI_COMMAND_FAST_BACK |
+                   PCI_COMMAND_INTX_DISABLE);
+
+    pci_conf_initb(dev, PCI_CACHE_LINE_SIZE, ~0);
+    pci_conf_initb(dev, PCI_LATENCY_TIMER, ~0);
+    pci_conf_initb(dev, PCI_INTERRUPT_LINE, ~0);
+
+    /* device dependent part */
+    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; i++)
+        pci_conf_initb(dev, i, ~0);
 }
 
 static void pci_config_alloc(PCIDevice *pci_dev)
@@ -441,10 +457,12 @@ void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask)
 }
 
 /* -1 for devfn means auto assign */
+typedef void (*pci_conf_init_t)(PCIDevice *d);
 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                                          const char *name, int devfn,
                                          PCIConfigReadFunc *config_read,
-                                         PCIConfigWriteFunc *config_write)
+                                         PCIConfigWriteFunc *config_write,
+                                         pci_conf_init_t conf_init)
 {
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
@@ -461,9 +479,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
     pci_config_alloc(pci_dev);
-    pci_set_default_subsystem_id(pci_dev);
     pci_init_cmask(pci_dev);
-    pci_init_wmask(pci_dev);
+    conf_init(pci_dev);
 
     if (!config_read)
         config_read = pci_default_read_config;
@@ -486,9 +503,11 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 
     pci_dev = qemu_mallocz(instance_size);
     pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
-                                     config_read, config_write);
+                                     config_read, config_write,
+                                     pci_conf_init_type_00_default);
     return pci_dev;
 }
+
 static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
 {
     return addr + pci_mem_base;
@@ -1245,6 +1264,52 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function)
     return bus->devices[PCI_DEVFN(slot, function)];
 }
 
+static void pci_conf_init_type_01_default(PCIDevice *d)
+{
+    uint32_t addr;
+    uint32_t config_size = pcie_config_size(d);
+
+    pci_conf_initw(d, PCI_COMMAND,
+                   PCI_COMMAND_IO |
+                   PCI_COMMAND_MEMORY |
+                   PCI_COMMAND_MASTER |
+                   PCI_COMMAND_SPECIAL |
+                   PCI_COMMAND_INVALIDATE |
+                   PCI_COMMAND_VGA_PALETTE |
+                   PCI_COMMAND_PARITY |
+                   PCI_COMMAND_WAIT |
+                   PCI_COMMAND_SERR |
+                   PCI_COMMAND_FAST_BACK |
+                   PCI_COMMAND_INTX_DISABLE);
+
+    pci_conf_initb(d, PCI_CACHE_LINE_SIZE, ~0);
+    pci_conf_initb(d, PCI_LATENCY_TIMER, ~0);
+
+    pci_conf_initb(d, PCI_PRIMARY_BUS, ~0);
+    pci_conf_initb(d, PCI_SECONDARY_BUS, ~0);
+    pci_conf_initb(d, PCI_SUBORDINATE_BUS, ~0);
+    pci_conf_initb(d, PCI_SEC_LATENCY_TIMER, ~0);
+    pci_conf_initb(d, PCI_IO_BASE, PCI_IO_RANGE_MASK & 0xff);
+    pci_conf_initb(d, PCI_IO_LIMIT, PCI_IO_RANGE_MASK & 0xff);
+
+    /* sec status isn't emulated (yet) */
+    pci_conf_initw(d, PCI_SEC_STATUS, 0);
+
+    pci_conf_initw(d, PCI_MEMORY_BASE, PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_MEMORY_LIMIT, PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_PREF_MEMORY_BASE, PCI_PREF_RANGE_MASK & 0xffff);
+    pci_conf_initw(d, PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_MASK & 0xffff);
+    pci_conf_initl(d, PCI_PREF_BASE_UPPER32, ~0);
+    pci_conf_initl(d, PCI_PREF_LIMIT_UPPER32, ~0);
+
+    pci_conf_initb(d, PCI_INTERRUPT_LINE, ~0);
+    pci_conf_initw(d, PCI_BRIDGE_CONTROL, ~0);
+
+    /* device dependent part */
+    for (addr = PCI_CONFIG_HEADER_SIZE; addr < config_size; addr++)
+        pci_conf_initb(d, addr, ~0);
+}
+
 int pci_bridge_initfn(PCIDevice *pci_dev)
 {
     uint8_t *pci_conf;
@@ -1323,6 +1388,21 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
                                     map_irq, name, PCI_BRIDGE_DEFAULT);
 }
 
+static pci_conf_init_t pci_get_config_initfn(uint8_t header_type)
+{
+    switch (header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION) {
+    case PCI_HEADER_TYPE_NORMAL:
+        return pci_conf_init_type_00_default;
+    case PCI_HEADER_TYPE_BRIDGE:
+        return pci_conf_init_type_01_default;
+    case PCI_HEADER_TYPE_CARDBUS:
+    default:
+        abort();
+        break;
+    }
+    /* NOTREACHED */
+}
+
 static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     PCIDevice *pci_dev = (PCIDevice *)qdev;
@@ -1333,7 +1413,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
     devfn = pci_dev->devfn;
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
-                                     info->config_read, info->config_write);
+                                     info->config_read, info->config_write,
+                                     pci_get_config_initfn(info->header_type));
     assert(pci_dev);
     return info->init(pci_dev);
 }
diff --git a/hw/pci.h b/hw/pci.h
index 56285e2..085eab3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -113,6 +113,14 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 #define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
 #define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
 #define  PCI_COMMAND_MASTER	0x4	/* Enable bus master */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE 0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
 #define PCI_STATUS              0x06    /* 16 bits */
 #define PCI_REVISION_ID         0x08    /* 8 bits  */
 #define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
@@ -174,9 +182,37 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
 
 /* Header type 1 (PCI-to-PCI bridges) */
 #define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER   0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE             0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT            0x1d
+#define  PCI_IO_RANGE_TYPE_MASK 0x0fUL  /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16   0x00
+#define  PCI_IO_RANGE_TYPE_32   0x01
+#define  PCI_IO_RANGE_MASK      (~0x0fUL)
+#define PCI_MEMORY_BASE         0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT        0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK  (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE    0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT   0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32 0x00
+#define  PCI_PREF_RANGE_TYPE_64 0x01
+#define  PCI_PREF_RANGE_MASK    (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32   0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32  0x2c
+#define PCI_IO_BASE_UPPER16     0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16    0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
 #define PCI_ROM_ADDRESS1        0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
-#define PCI_SUBORDINATE_BUS     0x1a    /* Highest bus number behind the bridge */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL      0x3e
+
+/* Bits in the PCI Command Register (PCI 2.3 spec) */
+#define PCI_COMMAND_RESERVED_BRIDGE     0xf880
 
+#define PCI_COMMAND_RESERVED_MASK_HI_BRIDGE (PCI_COMMAND_RESERVED >> 8)
 
 /* Size of the standard PCI config header */
 #define PCI_CONFIG_HEADER_SIZE 0x40
@@ -394,6 +430,9 @@ typedef struct {
     PCIConfigReadFunc *config_read;
     PCIConfigWriteFunc *config_write;
 
+    /* pci config header type */
+    uint8_t header_type;
+
     /* pcie stuff */
     int pcie;
 } PCIDeviceInfo;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 25/25] pci/monitor: print out bridge's filtering values and so on.
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (23 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 24/25] pci: initialize wmask according to pci header type Isaku Yamahata
@ 2009-10-02 10:31 ` Isaku Yamahata
  2009-10-02 13:21 ` [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Gerd Hoffmann
  25 siblings, 0 replies; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 10:31 UTC (permalink / raw)
  To: qemu-devel, anthony; +Cc: yamahata

make pci_info_device() print out bridge's filtering value like
io base/limit, subbus and subordinate bus.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/pci.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 2be853e..24aaba0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1065,7 +1065,50 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d)
                        d->config[PCI_INTERRUPT_LINE]);
     }
     if (class == 0x0604) {
+        int shift;
+        uint64_t base;
+        uint64_t limit;
         monitor_printf(mon, "      BUS %d.\n", d->config[0x19]);
+        monitor_printf(mon, "      SECONDARY BUS %d.\n",
+                       d->config[PCI_SECONDARY_BUS]);
+        monitor_printf(mon, "      SUBORDINATE BUS %d.\n",
+                       d->config[PCI_SUBORDINATE_BUS]);
+
+        if (d->config[PCI_IO_BASE] & PCI_IO_RANGE_TYPE_32) {
+            shift = 16;
+        } else {
+            shift = 8;
+        }
+        base = ((uint32_t)d->config[PCI_IO_BASE] & ~PCI_IO_RANGE_TYPE_MASK)
+            << shift;
+        base |= pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16;
+        limit = ((uint32_t)d->config[PCI_IO_LIMIT] & ~PCI_IO_RANGE_TYPE_MASK)
+            << shift;
+        limit |= pci_get_word(d->config + PCI_IO_LIMIT_UPPER16) << 16;
+        limit |= 0xfff;
+        monitor_printf(mon, "      IO range [0x%04"PRIx64", 0x%04"PRIx64"]\n",
+                       base, limit);
+
+        shift = 16;
+        base = (pci_get_word(d->config + PCI_MEMORY_BASE) &
+                PCI_MEMORY_RANGE_MASK) << shift;
+        limit = (pci_get_word(d->config + PCI_MEMORY_LIMIT) &
+                 PCI_MEMORY_RANGE_MASK) << shift;
+        limit |= 0xfffff;
+        monitor_printf(mon,
+                       "      MEM range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
+        shift = 16;
+        base = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_BASE) &
+                PCI_PREF_RANGE_MASK) << shift;
+        limit = ((uint64_t)pci_get_word(d->config + PCI_PREF_MEMORY_LIMIT) &
+                 PCI_PREF_RANGE_MASK) << shift;
+        base |= (uint64_t)pci_get_long(d->config + PCI_PREF_BASE_UPPER32) << 32;
+        limit |= (uint64_t)pci_get_long(d->config + PCI_PREF_LIMIT_UPPER32) << 32;
+        limit |= 0xfffff;
+        monitor_printf(mon,
+                       "      pref MEM range [0x%08"PRIx64", 0x%08"PRIx64"]\n",
+                       base, limit);
     }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2
  2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
                   ` (24 preceding siblings ...)
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 25/25] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
@ 2009-10-02 13:21 ` Gerd Hoffmann
  2009-10-02 13:42   ` Gerd Hoffmann
  25 siblings, 1 reply; 31+ messages in thread
From: Gerd Hoffmann @ 2009-10-02 13:21 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On 10/02/09 12:31, Isaku Yamahata wrote:
> This patch set is preliminary for q35 based chipset support.
> This patch sets does various pci related clean ups and
> 64bit bar, pciemmconfig and pci bridge support.

sparc64 segfaults with this series applied (it is the only system 
emulation using pci bridges right now).

(gdb) bt
#0  subpage_register (mmio=0x23ed600, start=<value optimized out>, 
end=<value optimized out>,
     memory=5242880, region_offset=41943040) at 
/home/kraxel/projects/qemu/exec.c:2862
#1  0x00000000004c4c69 in subpage_init (base=41943040, phys=0x1c2f000, 
orig_memory=41943040,
     region_offset=41943040) at /home/kraxel/projects/qemu/exec.c:2893
#2  0x00000000004c4e7b in cpu_register_physical_memory_offset 
(start_addr=<value optimized out>,
     size=256, phys_offset=104, region_offset=0) at 
/home/kraxel/projects/qemu/exec.c:2332
#3  0x0000000000415122 in pci_update_mappings (d=0x1c1f010)
     at /home/kraxel/projects/qemu/hw/pci.c:698
#4  0x00000000004164bd in pci_default_write_config (d=0x1c1f010, 
addr=20, val=41943040,
     l=<value optimized out>) at /home/kraxel/projects/qemu/hw/pci.c:763
#5  0x0000000041e552e3 in ?? ()
#6  0x00007fffa44f63cc in ?? ()
#7  0x0000000001bf3110 in ?? ()
#8  0x0000000000000200 in ?? ()
#9  0x00000000ffd18000 in ?? ()
#10 0x0000000001bf3110 in ?? ()
#11 0x00000000ffd18000 in ?? ()
#12 0x00007f168b678c90 in ?? ()
#13 0x0000000000000200 in ?? ()
#14 0x00000000ffd18000 in ?? ()
#15 0x00000000004c727d in tb_gen_code (env=0x1ff00000014, pc=<value 
optimized out>, cs_base=65280,
     flags=<value optimized out>, cflags=<value optimized out>)
     at /home/kraxel/projects/qemu/exec.c:908
#16 0x00000000004c8d53 in cpu_sparc_exec (env1=<value optimized out>)
     at /home/kraxel/projects/qemu/cpu-exec.c:620
#17 0x000000000040d8da in qemu_cpu_exec (env=<value optimized out>)
     at /home/kraxel/projects/qemu/vl.c:3946
#18 tcg_cpu_exec (env=<value optimized out>) at 
/home/kraxel/projects/qemu/vl.c:3977
#19 main_loop (env=<value optimized out>) at 
/home/kraxel/projects/qemu/vl.c:4092
#20 main (env=<value optimized out>) at /home/kraxel/projects/qemu/vl.c:5949

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2
  2009-10-02 13:21 ` [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Gerd Hoffmann
@ 2009-10-02 13:42   ` Gerd Hoffmann
  2009-10-02 19:30     ` Isaku Yamahata
  0 siblings, 1 reply; 31+ messages in thread
From: Gerd Hoffmann @ 2009-10-02 13:42 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

> sparc64 segfaults with this series applied (it is the only system
> emulation using pci bridges right now).

ppc is broken too.  I get this on the serial line:

 >> Cannot manage 'ethernet controller' PCI device type 'network':
 >>  10ec 8139 (2 0 0)

and the system hangs somewhere in the prom code.

For the record: x86_64 works fine.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2
  2009-10-02 13:42   ` Gerd Hoffmann
@ 2009-10-02 19:30     ` Isaku Yamahata
  2009-10-05 13:21       ` Gerd Hoffmann
  0 siblings, 1 reply; 31+ messages in thread
From: Isaku Yamahata @ 2009-10-02 19:30 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Thank you for testing.
Does the following patch helps?

diff --git a/hw/pci.c b/hw/pci.c
index 24aaba0..d562410 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -812,10 +812,15 @@ static uint32_t pci_data_read_common(PCIDevice *pci_dev,
 
 static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
 {
-    int bus_num = (addr >> 16) & 0xff;
-    unsigned int devfn = (addr >> 8) & 0xff;
+    uint8_t bus_num = (addr >> 16) & 0xff;
+    uint8_t devfn = (addr >> 8) & 0xff;
+    PCIBus *s = pci_find_bus(bus, bus_num);
 
-    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+    if (!s) {
+        return NULL;
+    }
+
+    return pci_find_device(s, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
 }
 
 static inline uint32_t pci_addr_to_config(uint32_t addr)
-- 
1.6.0.2




On Fri, Oct 02, 2009 at 03:42:09PM +0200, Gerd Hoffmann wrote:
> >sparc64 segfaults with this series applied (it is the only system
> >emulation using pci bridges right now).
> 
> ppc is broken too.  I get this on the serial line:
> 
> >> Cannot manage 'ethernet controller' PCI device type 'network':
> >>  10ec 8139 (2 0 0)
> 
> and the system hangs somewhere in the prom code.
> 
> For the record: x86_64 works fine.
> 
> cheers,
>   Gerd
> 
> 

-- 
yamahata

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] Re: [PATCH 17/25] pci: fix pci_default_write_config()
  2009-10-02 10:31 ` [Qemu-devel] [PATCH 17/25] pci: fix pci_default_write_config() Isaku Yamahata
@ 2009-10-04  8:36   ` Michael S. Tsirkin
  0 siblings, 0 replies; 31+ messages in thread
From: Michael S. Tsirkin @ 2009-10-04  8:36 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On Fri, Oct 02, 2009 at 07:31:49PM +0900, Isaku Yamahata wrote:
> When updated ROM expantion address of header type 0, it missed
> to update mappings.
> Add PCI_ROM_ADDRESS check whether to call pci_update_mappings()
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci.c |    3 ++-
>  hw/pci.h |    1 +
>  2 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/pci.c b/hw/pci.c
> index 1afcfb8..c9054c1 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -671,7 +671,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
>          uint8_t wmask = d->wmask[addr];
>          d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
>      }
> -    if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
> +    if ((memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24) ||
> +         memcmp(orig + PCI_ROM_ADDRESS, d->config + PCI_ROM_ADDRESS, 4))
>          || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
>              & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
>          pci_update_mappings(d);
> diff --git a/hw/pci.h b/hw/pci.h
> index 66d899d..3ea5258 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -144,6 +144,7 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r)
>  #define PCI_SUBVENDOR_ID        0x2c    /* obsolete, use PCI_SUBSYSTEM_VENDOR_ID */
>  #define PCI_SUBDEVICE_ID        0x2e    /* obsolete, use PCI_SUBSYSTEM_ID */
>  
> +#define PCI_ROM_ADDRESS         0x30    /* Bits 31..11 are address, 10..1 reserved */
>  #define  PCI_ROM_ADDRESS_ENABLE 0x01
>  
>  /* Bits in the PCI Status Register (PCI 2.3 spec) */
> -- 
> 1.6.0.2

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2
  2009-10-02 19:30     ` Isaku Yamahata
@ 2009-10-05 13:21       ` Gerd Hoffmann
  0 siblings, 0 replies; 31+ messages in thread
From: Gerd Hoffmann @ 2009-10-05 13:21 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: qemu-devel

On 10/02/09 21:30, Isaku Yamahata wrote:
> Thank you for testing.
> Does the following patch helps?

Partly.  ppc works again, sparc64 does still segfault.

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2009-10-05 13:21 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-02 10:31 [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 01/25] pci: fix PCI_DPRINTF() wrt variadic macro Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 02/25] pci: use appropriate PRIs in PCI_DPRINTF() for portability Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 03/25] pci: introduce constant PCI_NUM_PINS for the number of interrupt pins, 4 Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 04/25] pci: use the symbolic constant, PCI_ROM_ADDRESS_ENABLE instead of 1 Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 05/25] pci: use PCI_SLOT() and PCI_FUNC() Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 06/25] pci: define a constant to represent a unmapped bar and use it Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 07/25] pci: helper functions to access PCIDevice::config Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 08/25] pci: use helper functions to access pci config space Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 09/25] pci: introduce pcibus_t to represent pci bus address/size instead of uint32_t Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 10/25] pci: introduce FMT_pcibus for printf format for pcibus_t Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 11/25] pci: typedef pcibus_t as uint64_t instead of uint32_t Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 12/25] pci: 64bit bar support Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 13/25] pci: make pci configuration transaction more accurate Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 14/25] pci: factor out the logic to get pci device from address Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 15/25] pci_host.h: split non-inline static function in pci_host.h into pci_host.c Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 16/25] pci: pcie host and mmcfg support Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 17/25] pci: fix pci_default_write_config() Isaku Yamahata
2009-10-04  8:36   ` [Qemu-devel] " Michael S. Tsirkin
2009-10-02 10:31 ` [Qemu-devel] [PATCH 18/25] pci: add helper functions for pci config write function Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 19/25] pci: use helper function in pci_default_write_config() Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 20/25] pci: factor out config update logic Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 21/25] pci: make bar update function aware of pci bridge Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 22/25] pci/brdige: qdevfy and initialize secondary bus and subordinate bus Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 23/25] pci: add helper function to initialize wmask Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 24/25] pci: initialize wmask according to pci header type Isaku Yamahata
2009-10-02 10:31 ` [Qemu-devel] [PATCH 25/25] pci/monitor: print out bridge's filtering values and so on Isaku Yamahata
2009-10-02 13:21 ` [Qemu-devel] [PATCH 00/25] pci: various pci clean up and pci express support. V2 Gerd Hoffmann
2009-10-02 13:42   ` Gerd Hoffmann
2009-10-02 19:30     ` Isaku Yamahata
2009-10-05 13:21       ` Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).