Add pci_find_capability to scan capability list. Return 0 on error, capability offset if found.
Signed-off-by: Michael S. Tsirkin mst@redhat.com
---
Not useful by itself, but should be handy if we ever want to look at capabilities such as pci express.
diff --git a/src/pci.c b/src/pci.c index 23a6878..324ac96 100644 --- a/src/pci.c +++ b/src/pci.c @@ -57,6 +57,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on) pci_config_writew(bdf, addr, val); }
+unsigned char pci_find_capability(u16 bdf, unsigned char cap_id) +{ + unsigned char next, prev; + int loop = 0; + + if (!(pci_config_readb(bdf, PCI_STATUS) & PCI_STATUS_CAP_LIST)) + return 0; + + for (prev = PCI_CAPABILITY_LIST; (next = pci_config_readb(bdf, prev)); + prev = next + PCI_CAP_LIST_NEXT) { + if (pci_config_readb(bdf, next + PCI_CAP_LIST_ID) == cap_id) + break; + if (loop++ > 0x100) { + dprintf(1, "ERROR: capability loop detected. " + "PCI device %02x:%02x.%x\n" + , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) + , pci_bdf_to_fn(bdf)); + return 0; + } + } + + return next; +} + // Helper function for foreachbdf() macro - return next device int pci_next(int bdf, int bus) diff --git a/src/pci.h b/src/pci.h index c34e348..160cfc1 100644 --- a/src/pci.h +++ b/src/pci.h @@ -110,6 +110,8 @@ void pci_reboot(void); u32 pci_readl(u32 addr); void pci_writel(u32 addr, u32 val);
+unsigned char pci_find_capability(u16 bdf, unsigned char cap_id); + // pirtable.c void create_pirtable(void);
On Wed, Jul 06, 2011 at 05:03:21PM +0300, Michael S. Tsirkin wrote:
Add pci_find_capability to scan capability list. Return 0 on error, capability offset if found.
Signed-off-by: Michael S. Tsirkin mst@redhat.com
Not useful by itself, but should be handy if we ever want to look at capabilities such as pci express.
Here's an example using slot register and pci express register to figure out how many expansion slots does a bridge have:
diff --git a/src/pci.c b/src/pci.c index 23a6878..5e72347 100644 --- a/src/pci.c +++ b/src/pci.c @@ -57,30 +57,59 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on) pci_config_writew(bdf, addr, val); }
unsigned char pci_find_capability(u16 bdf, unsigned char cap_id) { unsigned char next, prev; int loop = 0;
if (!(pci_config_readb(bdf, PCI_STATUS) & PCI_STATUS_CAP_LIST)) return 0;
for (prev = PCI_CAPABILITY_LIST; (next = pci_config_readb(bdf, prev)); prev = next + PCI_CAP_LIST_NEXT) { if (pci_config_readb(bdf, next + PCI_CAP_LIST_ID) == cap_id) break; if (loop++ > 0x100) { dprintf(1, "ERROR: capability loop detected. " "PCI device %02x:%02x.%x\n" , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) , pci_bdf_to_fn(bdf)); return 0; } }
return next; }
+static int pci_bridge_conventional_slots(u16 bdf) +{ + u8 cap = pci_find_capability(bdf, PCI_CAP_ID_SLOTID); + if (!cap) + return 32; + u8 slots = pci_config_readb(bdf, cap + 2); + return slots; +} + +int pci_bridge_get_slots(u16 bdf) +{ + /* No express cap: assume 32 ports. */ + u8 flags, type; + u8 cap = pci_find_capability(bdf, PCI_CAP_ID_EXP); + if (!cap) + return pci_bridge_conventional_slots(bdf); + flags = pci_config_readb(cap + 2); + type = flags >> 4; + switch (type) { + case PCI_EXP_TYPE_UPSTREAM: + return 0; + case PCI_EXP_TYPE_DOWNSTREAM: + return 1; + default: + return pci_bridge_conventional_slots(bdf); + } + +} + // Helper function for foreachbdf() macro - return next device int pci_next(int bdf, int bus)
On 07/06/11 16:57, Michael S. Tsirkin wrote:
On Wed, Jul 06, 2011 at 05:03:21PM +0300, Michael S. Tsirkin wrote:
Add pci_find_capability to scan capability list. Return 0 on error, capability offset if found.
Signed-off-by: Michael S. Tsirkinmst@redhat.com
Not useful by itself, but should be handy if we ever want to look at capabilities such as pci express.
Here's an example using slot register and pci express register to figure out how many expansion slots does a bridge have:
Thanks, I'll use the bits for finetuning in the next version of the two-pass pci init patches.
cheers, Gerd
On Wed, Jul 06, 2011 at 05:43:34PM +0200, Gerd Hoffmann wrote:
On 07/06/11 16:57, Michael S. Tsirkin wrote:
On Wed, Jul 06, 2011 at 05:03:21PM +0300, Michael S. Tsirkin wrote:
Add pci_find_capability to scan capability list. Return 0 on error, capability offset if found.
Signed-off-by: Michael S. Tsirkinmst@redhat.com
Not useful by itself, but should be handy if we ever want to look at capabilities such as pci express.
Here's an example using slot register and pci express register to figure out how many expansion slots does a bridge have:
Thanks, I'll use the bits for finetuning in the next version of the two-pass pci init patches.
cheers, Gerd
BTw I don't think we need to make it a dependency of that patchset, necessarily. Keeping it simple also has certain appeal, and might make it easier for management to figure out what is and isn't supported.
Hi,
BTw I don't think we need to make it a dependency of that patchset, necessarily. Keeping it simple also has certain appeal, and might make it easier for management to figure out what is and isn't supported.
Just figured while checking the bridge specs that the minimum range you can assign to a bridge is 4k anyway ...
What do you think should we do with bridges which have no devices at all? Assign ressources too? Or just leave it to the OS to handle this in case some device gets hot-plugged there?
cheers, Gerd
On Thu, Jul 07, 2011 at 05:43:58PM +0200, Gerd Hoffmann wrote:
Hi,
BTw I don't think we need to make it a dependency of that patchset, necessarily. Keeping it simple also has certain appeal, and might make it easier for management to figure out what is and isn't supported.
Just figured while checking the bridge specs that the minimum range you can assign to a bridge is 4k anyway ...
What do you think should we do with bridges which have no devices at all? Assign ressources too? Or just leave it to the OS to handle this in case some device gets hot-plugged there?
cheers, Gerd
Not sure, need to see how well do guests handle such hotplug. For now, I would do whatever is easiest to implement.