qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support
@ 2010-06-17 11:03 Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro Isaku Yamahata
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

This patch set allows seabios to initialize multi pci bus and 64bit BAR.

Currently seabios is able to initialize only pci root bus.
However multi pci bus support is wanted because
  - more pci bus is wanted in qemu for many slots
  - pci express support is commin in qemu which requires multi pci bus.
those patches on Qemu part are under way, though.

Isaku Yamahata (8):
  seabios: pci: introduce foreachpci_in_bus() helper macro.
  seabios: pciinit: factor out pci bar region allocation logic.
  seabios: pciinit: make pci memory space assignment 64bit aware.
  seabios: pciinit: make pci bar assigner preferchable memory aware.
  seabios: pciinit: factor out bar offset calculation.
  seabios: pciinit: make bar offset calculation pci bridge aware.
  seabios: pciinit: pci bridge bus initialization.
  seabios: pciinit: initialize pci bridge filtering registers.

 src/pci.c     |   30 ++++++
 src/pci.h     |   11 ++
 src/pciinit.c |  310 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 306 insertions(+), 45 deletions(-)

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

* [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 2/8] seabios: pciinit: factor out pci bar region allocation logic Isaku Yamahata
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

This patch introduces foreachpci_in_bus() helper macro for
depth first recursion. foreachpci() is for width first recursion.
The macro will be used later to initialize pci bridge
that requires depth first recursion.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 src/pci.c |   30 ++++++++++++++++++++++++++++++
 src/pci.h |   11 +++++++++++
 2 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/src/pci.c b/src/pci.c
index 1ab3c2c..d418b4b 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -157,6 +157,36 @@ pci_find_vga(void)
     }
 }
 
+// Helper function for foreachpci_in_bus() macro - return next devfn
+int
+pci_next_in_bus(int bus, int devfn)
+{
+    int bdf = pci_bus_devfn_to_bdf(bus, devfn);
+    if (pci_bdf_to_fn(bdf) == 1
+        && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
+        // Last found device wasn't a multi-function device - skip to
+        // the next device.
+        devfn += 7;
+
+    for (;;) {
+        if (devfn >= 0x100)
+            return -1;
+
+        bdf = pci_bus_devfn_to_bdf(bus, devfn);
+        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
+        if (v != 0x0000 && v != 0xffff)
+            // Device is present.
+            break;
+
+        if (pci_bdf_to_fn(bdf) == 0)
+            devfn += 8;
+        else
+            devfn += 1;
+    }
+
+    return devfn;
+}
+
 // Search for a device with the specified vendor and device ids.
 int
 pci_find_device(u16 vendid, u16 devid)
diff --git a/src/pci.h b/src/pci.h
index 8a21c06..26bfd40 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -21,6 +21,9 @@ static inline u8 pci_bdf_to_fn(u16 bdf) {
 static inline u16 pci_to_bdf(int bus, int dev, int fn) {
     return (bus<<8) | (dev<<3) | fn;
 }
+static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
+    return (bus << 8) | devfn;
+}
 
 static inline u32 pci_vd(u16 vendor, u16 device) {
     return (device << 16) | vendor;
@@ -50,6 +53,14 @@ int pci_next(int bdf, int *pmax);
          ; BDF >= 0                             \
          ; BDF=pci_next(BDF+1, &MAX))
 
+int pci_next_in_bus(int bus, int devfn);
+#define foreachpci_in_bus(BUS, DEVFN, BDF)              \
+    for (DEVFN = pci_next_in_bus(BUS, 0),               \
+         BDF = pci_bus_devfn_to_bdf(BUS, DEVFN)         \
+         ; DEVFN >= 0                                   \
+         ; DEVFN = pci_next_in_bus(BUS, DEVFN + 1),     \
+           BDF = pci_bus_devfn_to_bdf(BUS, DEVFN))
+
 // pirtable.c
 void create_pirtable(void);
 
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 2/8] seabios: pciinit: factor out pci bar region allocation logic.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 3/8] seabios: pciinit: make pci memory space assignment 64bit aware Isaku Yamahata
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

factor out pci bar region allocation logic.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index 0556ee2..488c77b 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -37,6 +37,50 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
     dprintf(1, "region %d: 0x%08x\n", region_num, addr);
 }
 
+static void pci_bios_allocate_region(u16 bdf, int region_num)
+{
+    u32 *paddr;
+    int ofs;
+    if (region_num == PCI_ROM_SLOT)
+        ofs = PCI_ROM_ADDRESS;
+    else
+        ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
+
+    u32 old = pci_config_readl(bdf, ofs);
+    u32 mask;
+    if (region_num == PCI_ROM_SLOT) {
+        mask = PCI_ROM_ADDRESS_MASK;
+        pci_config_writel(bdf, ofs, mask);
+    } else {
+        if (old & PCI_BASE_ADDRESS_SPACE_IO)
+            mask = PCI_BASE_ADDRESS_IO_MASK;
+        else
+            mask = PCI_BASE_ADDRESS_MEM_MASK;
+        pci_config_writel(bdf, ofs, ~0);
+    }
+    u32 val = pci_config_readl(bdf, ofs);
+    pci_config_writel(bdf, ofs, old);
+
+    if (val != 0) {
+        u32 size = (~(val & mask)) + 1;
+        if (val & PCI_BASE_ADDRESS_SPACE_IO)
+            paddr = &pci_bios_io_addr;
+        else
+            paddr = &pci_bios_mem_addr;
+        *paddr = ALIGN(*paddr, size);
+        pci_set_io_region_addr(bdf, region_num, *paddr);
+        *paddr += size;
+    }
+}
+
+static void pci_bios_allocate_regions(u16 bdf)
+{
+    int i;
+    for (i = 0; i < PCI_NUM_REGIONS; i++) {
+        pci_bios_allocate_region(bdf, i);
+    }
+}
+
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
    mapping. */
@@ -78,8 +122,7 @@ static void pci_bios_init_bridges(u16 bdf)
 static void pci_bios_init_device(u16 bdf)
 {
     int class;
-    u32 *paddr;
-    int i, pin, pic_irq, vendor_id, device_id;
+    int pin, pic_irq, vendor_id, device_id;
 
     class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
     vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
@@ -94,7 +137,7 @@ static void pci_bios_init_device(u16 bdf)
             /* PIIX3/PIIX4 IDE */
             pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
             pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
-            goto default_map;
+            pci_bios_allocate_regions(bdf);
         } else {
             /* IDE: we map it as in ISA mode */
             pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
@@ -121,41 +164,8 @@ static void pci_bios_init_device(u16 bdf)
         }
         break;
     default:
-    default_map:
         /* default memory mappings */
-        for (i = 0; i < PCI_NUM_REGIONS; i++) {
-            int ofs;
-            if (i == PCI_ROM_SLOT)
-                ofs = PCI_ROM_ADDRESS;
-            else
-                ofs = PCI_BASE_ADDRESS_0 + i * 4;
-
-            u32 old = pci_config_readl(bdf, ofs);
-            u32 mask;
-            if (i == PCI_ROM_SLOT) {
-                mask = PCI_ROM_ADDRESS_MASK;
-                pci_config_writel(bdf, ofs, mask);
-            } else {
-                if (old & PCI_BASE_ADDRESS_SPACE_IO)
-                    mask = PCI_BASE_ADDRESS_IO_MASK;
-                else
-                    mask = PCI_BASE_ADDRESS_MEM_MASK;
-                pci_config_writel(bdf, ofs, ~0);
-            }
-            u32 val = pci_config_readl(bdf, ofs);
-            pci_config_writel(bdf, ofs, old);
-
-            if (val != 0) {
-                u32 size = (~(val & mask)) + 1;
-                if (val & PCI_BASE_ADDRESS_SPACE_IO)
-                    paddr = &pci_bios_io_addr;
-                else
-                    paddr = &pci_bios_mem_addr;
-                *paddr = ALIGN(*paddr, size);
-                pci_set_io_region_addr(bdf, i, *paddr);
-                *paddr += size;
-            }
-        }
+        pci_bios_allocate_regions(bdf);
         break;
     }
 
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 3/8] seabios: pciinit: make pci memory space assignment 64bit aware.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 2/8] seabios: pciinit: factor out pci bar region allocation logic Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 4/8] seabios: pciinit: make pci bar assigner preferchable memory aware Isaku Yamahata
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

make pci memory space assignment 64bit aware.
If 64bit memory space is found while assigning pci memory space,
clear higher bit and skip to next bar.

This patch is preparation for q35 chipset initialization which
has 64bit bar.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index 488c77b..b635e44 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -37,7 +37,12 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
     dprintf(1, "region %d: 0x%08x\n", region_num, addr);
 }
 
-static void pci_bios_allocate_region(u16 bdf, int region_num)
+/*
+ * return value
+ *      0:     32bit BAR
+ *      non 0: 64bit BAR
+ */
+static int pci_bios_allocate_region(u16 bdf, int region_num)
 {
     u32 *paddr;
     int ofs;
@@ -71,13 +76,23 @@ static void pci_bios_allocate_region(u16 bdf, int region_num)
         pci_set_io_region_addr(bdf, region_num, *paddr);
         *paddr += size;
     }
+
+    int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
+        (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
+    if (is_64bit) {
+        pci_config_writel(bdf, ofs + 4, 0);
+    }
+    return is_64bit;
 }
 
 static void pci_bios_allocate_regions(u16 bdf)
 {
     int i;
     for (i = 0; i < PCI_NUM_REGIONS; i++) {
-        pci_bios_allocate_region(bdf, i);
+        int is_64bit = pci_bios_allocate_region(bdf, i);
+        if (is_64bit){
+            i++;
+        }
     }
 }
 
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 4/8] seabios: pciinit: make pci bar assigner preferchable memory aware.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (2 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 3/8] seabios: pciinit: make pci memory space assignment 64bit aware Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 5/8] seabios: pciinit: factor out bar offset calculation Isaku Yamahata
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

Make pci bar assigner preferchable memory aware.
This is needed for PCI bridge support because memory space and
prefetchable memory space is filtered independently based on
memory base/limit and prefetchable memory base/limit of pci bridge.
On bus 0, such a distinction isn't necessary so keep existing behavior
by checking bus=0.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index b635e44..b6ab157 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -16,6 +16,7 @@
 
 static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
+static u32 pci_bios_prefmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
 static u8 pci_irqs[4] = {
     10, 10, 11, 11
@@ -70,6 +71,12 @@ static int pci_bios_allocate_region(u16 bdf, int region_num)
         u32 size = (~(val & mask)) + 1;
         if (val & PCI_BASE_ADDRESS_SPACE_IO)
             paddr = &pci_bios_io_addr;
+        else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
+                 /* keep behaviour on bus = 0 */
+                 pci_bdf_to_bus(bdf) != 0 &&
+                 /* If pci_bios_prefmem_addr == 0, keep old behaviour */
+                 pci_bios_prefmem_addr != 0)
+            paddr = &pci_bios_prefmem_addr;
         else
             paddr = &pci_bios_mem_addr;
         *paddr = ALIGN(*paddr, size);
@@ -221,6 +228,9 @@ pci_setup(void)
     pci_bios_io_addr = 0xc000;
     pci_bios_mem_addr = BUILD_PCIMEM_START;
 
+    /* pci_bios_mem_addr + <some value> */
+    pci_bios_prefmem_addr = pci_bios_mem_addr + 0x08000000;
+
     int bdf, max;
     foreachpci(bdf, max) {
         pci_bios_init_bridges(bdf);
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 5/8] seabios: pciinit: factor out bar offset calculation.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (3 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 4/8] seabios: pciinit: make pci bar assigner preferchable memory aware Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 6/8] seabios: pciinit: make bar offset calculation pci bridge aware Isaku Yamahata
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

This patch factors out bar offset calculation.
Later the calculation logic will be enhanced.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index b6ab157..6ba51f2 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -22,15 +22,19 @@ static u8 pci_irqs[4] = {
     10, 10, 11, 11
 };
 
+static u32 pci_bar(u16 bdf, int region_num)
+{
+    if (region_num != PCI_ROM_SLOT) {
+        return PCI_BASE_ADDRESS_0 + region_num * 4;
+    }
+    return PCI_ROM_ADDRESS;
+}
+
 static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 {
     u32 ofs, old_addr;
 
-    if (region_num == PCI_ROM_SLOT) {
-        ofs = PCI_ROM_ADDRESS;
-    } else {
-        ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
-    }
+    ofs = pci_bar(bdf, region_num);
 
     old_addr = pci_config_readl(bdf, ofs);
 
@@ -46,11 +50,7 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 static int pci_bios_allocate_region(u16 bdf, int region_num)
 {
     u32 *paddr;
-    int ofs;
-    if (region_num == PCI_ROM_SLOT)
-        ofs = PCI_ROM_ADDRESS;
-    else
-        ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
+    u32 ofs = pci_bar(bdf, region_num);
 
     u32 old = pci_config_readl(bdf, ofs);
     u32 mask;
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 6/8] seabios: pciinit: make bar offset calculation pci bridge aware.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (4 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 5/8] seabios: pciinit: factor out bar offset calculation Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 7/8] seabios: pciinit: pci bridge bus initialization Isaku Yamahata
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

This patch makes pci bar offset calculation pci bridge aware.
The offset of pci bridge rom is different from normal device.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index 6ba51f2..1c2c8c6 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -27,7 +27,11 @@ static u32 pci_bar(u16 bdf, int region_num)
     if (region_num != PCI_ROM_SLOT) {
         return PCI_BASE_ADDRESS_0 + region_num * 4;
     }
-    return PCI_ROM_ADDRESS;
+
+#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+    u8 type = pci_config_readb(bdf, PCI_HEADER_TYPE);
+    type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
 }
 
 static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 7/8] seabios: pciinit: pci bridge bus initialization.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (5 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 6/8] seabios: pciinit: make bar offset calculation pci bridge aware Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers Isaku Yamahata
  2010-06-17 11:17 ` [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support Michael S. Tsirkin
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

pci bridge bus initialization.

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

diff --git a/src/pciinit.c b/src/pciinit.c
index 1c2c8c6..fe6848a 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -220,6 +220,74 @@ static void pci_bios_init_device(u16 bdf)
     }
 }
 
+static void
+pci_bios_init_bus_rec(int bus, u8 *pci_bus)
+{
+    int devfn, bdf;
+    u16 class;
+
+    dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
+
+    /* prevent accidental access to unintended devices */
+    foreachpci_in_bus(bus, devfn, bdf) {
+        class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+        if (class == PCI_CLASS_BRIDGE_PCI) {
+            pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
+            pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
+        }
+    }
+
+    foreachpci_in_bus(bus, devfn, bdf) {
+        class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+        if (class != PCI_CLASS_BRIDGE_PCI) {
+            continue;
+        }
+        dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
+
+        u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
+        if (pribus != bus) {
+            dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
+            pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
+        } else {
+            dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
+        }
+
+        u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+        (*pci_bus)++;
+        if (*pci_bus != secbus) {
+            dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
+                    secbus, *pci_bus);
+            secbus = *pci_bus;
+            pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
+        } else {
+            dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
+        }
+
+        /* set to max for access to all subordinate buses.
+           later set it to accurate value */
+        u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
+        pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
+
+        pci_bios_init_bus_rec(secbus, pci_bus);
+
+        if (subbus != *pci_bus) {
+            dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
+                    subbus, *pci_bus);
+            subbus = *pci_bus;
+        } else {
+            dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
+        }
+        pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
+    }
+}
+
+static void
+pci_bios_init_bus(void)
+{
+    u8 pci_bus = 0;
+    pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
+}
+
 void
 pci_setup(void)
 {
@@ -235,6 +303,8 @@ pci_setup(void)
     /* pci_bios_mem_addr + <some value> */
     pci_bios_prefmem_addr = pci_bios_mem_addr + 0x08000000;
 
+    pci_bios_init_bus();
+
     int bdf, max;
     foreachpci(bdf, max) {
         pci_bios_init_bridges(bdf);
-- 
1.6.6.1

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

* [Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers.
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (6 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 7/8] seabios: pciinit: pci bridge bus initialization Isaku Yamahata
@ 2010-06-17 11:03 ` Isaku Yamahata
  2010-06-17 11:17 ` [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support Michael S. Tsirkin
  8 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-17 11:03 UTC (permalink / raw)
  To: seabios
  Cc: stefano.stabellini, jan.kiszka, mst, allen.m.kay, qemu-devel,
	yamahata, jean.guyader

initialize pci bridge filtering registers.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 src/pciinit.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/src/pciinit.c b/src/pciinit.c
index fe6848a..f68a690 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -14,6 +14,8 @@
 #define PCI_ROM_SLOT 6
 #define PCI_NUM_REGIONS 7
 
+static void pci_bios_init_device_in_bus(int bus);
+
 static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
 static u32 pci_bios_prefmem_addr;
@@ -145,6 +147,106 @@ static void pci_bios_init_bridges(u16 bdf)
     }
 }
 
+#define PCI_IO_ALIGN            4096
+#define PCI_IO_SHIFT            8
+#define PCI_MEMORY_ALIGN        (1UL << 20)
+#define PCI_MEMORY_SHIFT        16
+#define PCI_PREF_MEMORY_ALIGN   (1UL << 20)
+#define PCI_PREF_MEMORY_SHIFT   16
+
+static void pci_bios_init_device_bridge(u16 bdf)
+{
+    u32 io_old;
+    u32 mem_old;
+    u32 prefmem_old;
+
+    u32 io_base;
+    u32 io_end;
+    u32 mem_base;
+    u32 mem_end;
+    u32 prefmem_base;
+    u32 prefmem_end;
+
+    pci_bios_allocate_region(bdf, 0);
+    pci_bios_allocate_region(bdf, 1);
+    pci_bios_allocate_region(bdf, PCI_ROM_SLOT);
+
+    io_old = pci_bios_io_addr;
+    mem_old = pci_bios_mem_addr;
+    prefmem_old = pci_bios_prefmem_addr;
+
+    /* IO BASE is assumed to be 16 bit */
+    pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN);
+    pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN);
+    pci_bios_prefmem_addr =
+        ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN);
+
+    io_base = pci_bios_io_addr;
+    mem_base = pci_bios_mem_addr;
+    prefmem_base = pci_bios_prefmem_addr;
+
+    u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+    if (secbus > 0) {
+        pci_bios_init_device_in_bus(secbus);
+    }
+
+    pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN);
+    pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN);
+    pci_bios_prefmem_addr =
+        ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN);
+
+    io_end = pci_bios_io_addr;
+    if (io_end == io_base) {
+        pci_bios_io_addr = io_old;
+        io_base = 0xffff;
+        io_end = 1;
+    }
+    pci_config_writeb(bdf, PCI_IO_BASE, io_base >> PCI_IO_SHIFT);
+    pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
+    pci_config_writeb(bdf, PCI_IO_LIMIT, (io_end - 1) >> PCI_IO_SHIFT);
+    pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
+
+    mem_end = pci_bios_mem_addr;
+    if (mem_end == mem_base) {
+        pci_bios_mem_addr = mem_old;
+        mem_base = 0xffffffff;
+        mem_end = 1;
+    }
+    pci_config_writew(bdf, PCI_MEMORY_BASE, mem_base >> PCI_MEMORY_SHIFT);
+    pci_config_writew(bdf, PCI_MEMORY_LIMIT, (mem_end -1) >> PCI_MEMORY_SHIFT);
+
+    prefmem_end = pci_bios_prefmem_addr;
+    if (prefmem_end == prefmem_base) {
+        pci_bios_prefmem_addr = prefmem_old;
+        prefmem_base = 0xffffffff;
+        prefmem_end = 1;
+    }
+    pci_config_writew(bdf, PCI_PREF_MEMORY_BASE,
+                      prefmem_base >> PCI_PREF_MEMORY_SHIFT);
+    pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT,
+                      (prefmem_end - 1) >> PCI_PREF_MEMORY_SHIFT);
+    pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
+    pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
+
+    dprintf(1, "PCI: br io   = [0x%x, 0x%x)\n", io_base, io_end);
+    dprintf(1, "PCI: br mem  = [0x%x, 0x%x)\n", mem_base, mem_end);
+    dprintf(1, "PCI: br pref = [0x%x, 0x%x)\n", prefmem_base, prefmem_end);
+
+    u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
+    cmd &= ~PCI_COMMAND_IO;
+    if (io_end > io_base) {
+        cmd |= PCI_COMMAND_IO;
+    }
+    cmd &= ~PCI_COMMAND_MEMORY;
+    if (mem_end > mem_base || prefmem_end > prefmem_base) {
+        cmd |= PCI_COMMAND_MEMORY;
+    }
+    cmd |= PCI_COMMAND_MASTER;
+    pci_config_writew(bdf, PCI_COMMAND, cmd);
+
+    pci_config_maskw(bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_SERR);
+}
+
 static void pci_bios_init_device(u16 bdf)
 {
     int class;
@@ -189,6 +291,9 @@ static void pci_bios_init_device(u16 bdf)
             pci_set_io_region_addr(bdf, 0, 0x80800000);
         }
         break;
+    case PCI_CLASS_BRIDGE_PCI:
+        pci_bios_init_device_bridge(bdf);
+        break;
     default:
         /* default memory mappings */
         pci_bios_allocate_regions(bdf);
@@ -220,6 +325,14 @@ static void pci_bios_init_device(u16 bdf)
     }
 }
 
+static void pci_bios_init_device_in_bus(int bus)
+{
+    int devfn, bdf;
+    foreachpci_in_bus(bus, devfn, bdf) {
+        pci_bios_init_device(bdf);
+    }
+}
+
 static void
 pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 {
@@ -309,7 +422,5 @@ pci_setup(void)
     foreachpci(bdf, max) {
         pci_bios_init_bridges(bdf);
     }
-    foreachpci(bdf, max) {
-        pci_bios_init_device(bdf);
-    }
+    pci_bios_init_device_in_bus(0 /* host bus */);
 }
-- 
1.6.6.1

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

* [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support
  2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
                   ` (7 preceding siblings ...)
  2010-06-17 11:03 ` [Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers Isaku Yamahata
@ 2010-06-17 11:17 ` Michael S. Tsirkin
  2010-06-18  2:02   ` Isaku Yamahata
  8 siblings, 1 reply; 11+ messages in thread
From: Michael S. Tsirkin @ 2010-06-17 11:17 UTC (permalink / raw)
  To: Isaku Yamahata
  Cc: stefano.stabellini, jan.kiszka, seabios, allen.m.kay, qemu-devel,
	jean.guyader

On Thu, Jun 17, 2010 at 08:03:08PM +0900, Isaku Yamahata wrote:
> This patch set allows seabios to initialize multi pci bus and 64bit BAR.
> 
> Currently seabios is able to initialize only pci root bus.
> However multi pci bus support is wanted because
>   - more pci bus is wanted in qemu for many slots
>   - pci express support is commin in qemu which requires multi pci bus.
> those patches on Qemu part are under way, though.

Not that I object, but - does it really require multi bus? Why?

> Isaku Yamahata (8):
>   seabios: pci: introduce foreachpci_in_bus() helper macro.
>   seabios: pciinit: factor out pci bar region allocation logic.
>   seabios: pciinit: make pci memory space assignment 64bit aware.
>   seabios: pciinit: make pci bar assigner preferchable memory aware.
>   seabios: pciinit: factor out bar offset calculation.
>   seabios: pciinit: make bar offset calculation pci bridge aware.
>   seabios: pciinit: pci bridge bus initialization.
>   seabios: pciinit: initialize pci bridge filtering registers.
> 
>  src/pci.c     |   30 ++++++
>  src/pci.h     |   11 ++
>  src/pciinit.c |  310 ++++++++++++++++++++++++++++++++++++++++++++++++--------
>  3 files changed, 306 insertions(+), 45 deletions(-)

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

* [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support
  2010-06-17 11:17 ` [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support Michael S. Tsirkin
@ 2010-06-18  2:02   ` Isaku Yamahata
  0 siblings, 0 replies; 11+ messages in thread
From: Isaku Yamahata @ 2010-06-18  2:02 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: stefano.stabellini, jan.kiszka, seabios, allen.m.kay, qemu-devel,
	jean.guyader

On Thu, Jun 17, 2010 at 02:17:20PM +0300, Michael S. Tsirkin wrote:
> On Thu, Jun 17, 2010 at 08:03:08PM +0900, Isaku Yamahata wrote:
> > This patch set allows seabios to initialize multi pci bus and 64bit BAR.
> > 
> > Currently seabios is able to initialize only pci root bus.
> > However multi pci bus support is wanted because
> >   - more pci bus is wanted in qemu for many slots
> >   - pci express support is commin in qemu which requires multi pci bus.
> > those patches on Qemu part are under way, though.
> 
> Not that I object, but - does it really require multi bus? Why?

I should have explained about pci express a bit more.
Express defines root/upstream/upstream port. They are shown
to software as pci-to-pci bride.
Express slot to which express device is inserted is
under a root or downstream port. That means multi bus.
Native hot plug is implemented in root or downstream port.
Again that means multi bus.

I heard that some windows device driver checks pci-to-pci
bridge existence. Perhaps others may know this better.
-- 
yamahata

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

end of thread, other threads:[~2010-06-18  2:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-17 11:03 [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 2/8] seabios: pciinit: factor out pci bar region allocation logic Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 3/8] seabios: pciinit: make pci memory space assignment 64bit aware Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 4/8] seabios: pciinit: make pci bar assigner preferchable memory aware Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 5/8] seabios: pciinit: factor out bar offset calculation Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 6/8] seabios: pciinit: make bar offset calculation pci bridge aware Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 7/8] seabios: pciinit: pci bridge bus initialization Isaku Yamahata
2010-06-17 11:03 ` [Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers Isaku Yamahata
2010-06-17 11:17 ` [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support Michael S. Tsirkin
2010-06-18  2:02   ` Isaku Yamahata

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).