[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/6] New service functions and ported old functions
From: |
Alexey Korolev |
Subject: |
[Qemu-devel] [PATCH 2/6] New service functions and ported old functions to 64bit |
Date: |
Thu, 1 Mar 2012 19:15:40 +1300 |
This patch is all about service functions
It includes:
- basic operations with lists
- 64bit modification of Pci_size_roundup()
- modification of pci_bios_get_bar to support HUGE bars (size over 4GB)
- 2 service function to get pci_region statistics
- dump entry - for debug output
Signed-off-by: Alexey Korolev <address@hidden>
---
src/pciinit.c | 132 +++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 91 insertions(+), 41 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c
index 2e5416c..dbfa4f2 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -51,33 +51,30 @@ struct pci_region {
u64 base;
};
-static int pci_size_to_index(u32 size, enum pci_region_type type)
-{
- int index = __fls(size);
- int shift = (type == PCI_REGION_TYPE_IO) ?
- PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
-
- if (index < shift)
- index = shift;
- index -= shift;
- return index;
-}
+#define foreach_region_entry(R, ENTRY) \
+ for (ENTRY = (R)->list; ENTRY; ENTRY = ENTRY->next)
-static u32 pci_index_to_size(int index, enum pci_region_type type)
-{
- int shift = (type == PCI_REGION_TYPE_IO) ?
- PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
+#define foreach_region_entry_safe(R, N, ENTRY) \
+ for (ENTRY = (R)->list; ENTRY && ({N=ENTRY->next; 1;}); \
+ ENTRY = N)
- return 0x1 << (index + shift);
+static inline void region_entry_del(struct pci_region_entry *entry)
+{
+ struct pci_region_entry *next = entry->next;
+ *entry->pprev = next;
+ if (next)
+ next->pprev = entry->pprev;
}
-static enum pci_region_type pci_addr_to_type(u32 addr)
+static inline void
+region_entry_add(struct pci_region *r, struct pci_region_entry *entry)
{
- if (addr & PCI_BASE_ADDRESS_SPACE_IO)
- return PCI_REGION_TYPE_IO;
- if (addr & PCI_BASE_ADDRESS_MEM_PREFETCH)
- return PCI_REGION_TYPE_PREFMEM;
- return PCI_REGION_TYPE_MEM;
+ struct pci_region_entry *first = r->list;
+ entry->next = first;
+ if (first)
+ first->pprev = &entry->next;
+ r->list = entry;
+ entry->pprev = &r->list;
}
static u32 pci_bar(struct pci_device *pci, int region_num)
@@ -324,38 +321,91 @@ pci_bios_init_bus(void)
pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
}
-
/****************************************************************
* Bus sizing
****************************************************************/
-static u32 pci_size_roundup(u32 size)
+static u64 pci_size_roundup(u64 size)
{
- int index = __fls(size-1)+1;
- return 0x1 << index;
+ int index = __fls((u32)((size - 1) >> 32));
+ if (!index)
+ index = __fls((u32)(size - 1));
+ return 0x1 << (index + 1);
}
-static void
-pci_bios_get_bar(struct pci_device *pci, int bar, u32 *val, u32 *size)
+static u64
+pci_get_bar_size(struct pci_device *pci, int bar,
+ enum pci_region_type *type, int *is64bit)
{
u32 ofs = pci_bar(pci, bar);
u16 bdf = pci->bdf;
- u32 old = pci_config_readl(bdf, ofs);
- u32 mask;
-
- if (bar == PCI_ROM_SLOT) {
- mask = PCI_ROM_ADDRESS_MASK;
- pci_config_writel(bdf, ofs, mask);
+ u32 l, sz, mask;
+
+ mask = (bar == PCI_ROM_SLOT) ? PCI_ROM_ADDRESS_MASK : ~0;
+ l = pci_config_readl(bdf, ofs);
+ pci_config_writel(bdf, ofs, mask);
+ sz = pci_config_readl(bdf, ofs);
+ pci_config_writel(bdf, ofs, l);
+
+ *is64bit = 0;
+ if (l & PCI_BASE_ADDRESS_SPACE_IO) {
+ mask = PCI_BASE_ADDRESS_IO_MASK;
+ *type = PCI_REGION_TYPE_IO;
} else {
- if (old & PCI_BASE_ADDRESS_SPACE_IO)
- mask = PCI_BASE_ADDRESS_IO_MASK;
+ mask = PCI_BASE_ADDRESS_MEM_MASK;
+ if (l & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ *is64bit = 1;
+ if (l & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ *type = PCI_REGION_TYPE_PREFMEM;
else
- mask = PCI_BASE_ADDRESS_MEM_MASK;
- pci_config_writel(bdf, ofs, ~0);
+ *type = PCI_REGION_TYPE_MEM;
+ }
+ if (*is64bit) {
+ u64 mask64, sz64 = sz;
+ l = pci_config_readl(bdf, ofs + 4);
+ pci_config_writel(bdf, ofs + 4, ~0);
+ sz = pci_config_readl(bdf, ofs + 4);
+ pci_config_writel(bdf, ofs + 4, l);
+ mask64 = mask | ((u64)0xffffffff << 32);
+ sz64 |= ((u64)sz << 32);
+ return (~(sz64 & mask64)) + 1;
+ }
+ return (u32)((~(sz & mask)) + 1);
+}
+
+static u64 pci_region_max_size(struct pci_region *r)
+{
+ u64 max = 0;
+ struct pci_region_entry *entry;
+ foreach_region_entry(r, entry) {
+ max = (max > entry->size) ? max : entry->size;
+ }
+ return max;
+}
+
+static u64 pci_region_sum(struct pci_region *r)
+{
+ u64 sum = 0;
+ struct pci_region_entry *entry;
+ foreach_region_entry(r, entry) {
+ sum += entry->size;
}
- *val = pci_config_readl(bdf, ofs);
- pci_config_writel(bdf, ofs, old);
- *size = (~(*val & mask)) + 1;
+ return sum;
+}
+
+static void
+dump_entry(struct pci_region_entry *entry)
+{
+ if (entry->this_region )
+ dprintf(1, "PCI bus %d (secondary)", entry->dev->secondary_bus);
+ else
+ dprintf(1, "PCI region entry: bdf=%02x:%02x.%x BAR %d",
+ pci_bdf_to_bus(entry->dev->bdf), pci_bdf_to_dev(entry->dev->bdf),
+ pci_bdf_to_fn(entry->dev->bdf), entry->bar);
+ dprintf(1, " base=0x%08x%08x size=0x%08x%08x [%s, %s]\n",
+ (u32)(entry->base>>32), (u32)entry->base,
+ (u32)(entry->size>>32), (u32)entry->size,
+ region_type_name[entry->type],entry->is64bit ? "64bits" : "32bits");
}
static void pci_bios_bus_reserve(struct pci_bus *bus, int type, u32 size)
--
1.7.5.4
[Qemu-devel] [PATCH 5/6] Delete old code, Alexey Korolev, 2012/03/01
[Qemu-devel] [PATCH 6/6] 64bit PCI range in _CRS table, Alexey Korolev, 2012/03/01
Re: [Qemu-devel] [SeaBIOS] [Seabios] [PATCH 0/6] 64bit PCI BARs allocations (take 2), Gerd Hoffmann, 2012/03/01