aboutsummaryrefslogtreecommitdiffstats
path: root/xen/drivers/pci
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2011-11-22 17:22:31 +0100
committerJan Beulich <jbeulich@suse.com>2011-11-22 17:22:31 +0100
commitd2e02c9b9cb44d7300f0757b48114210483aad29 (patch)
treeae99c66c5fd103e0a81d0126832abbf28b121dbe /xen/drivers/pci
parentebbd2561b4cefb299f0f68a88b2788504223de18 (diff)
downloadxen-d2e02c9b9cb44d7300f0757b48114210483aad29.tar.gz
xen-d2e02c9b9cb44d7300f0757b48114210483aad29.tar.bz2
xen-d2e02c9b9cb44d7300f0757b48114210483aad29.zip
move pci_find_ext_capability() into common PCI code
There's nothing architecture specific about it. It requires, however, that x86-32's pci_conf_read32() tolerates register accesses above 255 (for consistency the adjustment is done to all pci_conf_readNN() functions). Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/drivers/pci')
-rw-r--r--xen/drivers/pci/pci.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/xen/drivers/pci/pci.c b/xen/drivers/pci/pci.c
index 9a15e8fd28..b6e388a4f1 100644
--- a/xen/drivers/pci/pci.c
+++ b/xen/drivers/pci/pci.c
@@ -62,3 +62,43 @@ int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, u8 pos, int cap)
}
return 0;
}
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it. Possible values for @cap:
+ *
+ * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
+ * %PCI_EXT_CAP_ID_VC Virtual Channel
+ * %PCI_EXT_CAP_ID_DSN Device Serial Number
+ * %PCI_EXT_CAP_ID_PWR Power Budgeting
+ */
+int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
+{
+ u32 header;
+ int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
+ int pos = 0x100;
+
+ header = pci_conf_read32(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
+
+ /*
+ * If we have no capabilities, this is indicated by cap ID,
+ * cap version and next pointer all being 0.
+ */
+ if ( (header == 0) || (header == -1) )
+ return 0;
+
+ while ( ttl-- > 0 ) {
+ if ( PCI_EXT_CAP_ID(header) == cap )
+ return pos;
+ pos = PCI_EXT_CAP_NEXT(header);
+ if ( pos < 0x100 )
+ break;
+ header = pci_conf_read32(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
+ }
+ return 0;
+}