diff options
author | Jan Beulich <jbeulich@suse.com> | 2011-11-22 17:22:31 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2011-11-22 17:22:31 +0100 |
commit | d2e02c9b9cb44d7300f0757b48114210483aad29 (patch) | |
tree | ae99c66c5fd103e0a81d0126832abbf28b121dbe /xen/drivers/pci | |
parent | ebbd2561b4cefb299f0f68a88b2788504223de18 (diff) | |
download | xen-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.c | 40 |
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; +} |