diff options
author | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2019-01-23 16:46:35 +0200 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2019-07-04 09:36:19 +0000 |
commit | 9c0e14e7c43e85e99c0bbfdff72019d908de1711 (patch) | |
tree | ef1a0ffee2d7a542a2c8ccb8d2f8cba74114628b /src/device/pci_ops.c | |
parent | dace2498ecfadf645599aaa3ba8fef8cbb111c2d (diff) |
device/pci_ops: Define pci_find_capability() just once
Wrap the simple romstage implementation to be called
from ramstage.
Change-Id: Iadadf3d550416850d6c37233bd4eda025f4d3960
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/31755
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Martin Roth <martinroth@google.com>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/device/pci_ops.c')
-rw-r--r-- | src/device/pci_ops.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/device/pci_ops.c b/src/device/pci_ops.c index 34f9d1e5b5..96133155be 100644 --- a/src/device/pci_ops.c +++ b/src/device/pci_ops.c @@ -11,6 +11,77 @@ * GNU General Public License for more details. */ +#define __SIMPLE_DEVICE__ + #include <stdint.h> +#include <device/pci.h> +#include <device/pci_def.h> +#include <device/pci_ops.h> +#include <device/pci_type.h> u8 *const pci_mmconf = (void *)(uintptr_t)CONFIG_MMCONF_BASE_ADDRESS; + +/** + * Given a device, a capability type, and a last position, return the next + * matching capability. Always start at the head of the list. + * + * @param dev Pointer to the device structure. + * @param cap PCI_CAP_LIST_ID of the PCI capability we're looking for. + * @param last Location of the PCI capability register to start from. + * @return The next matching capability. + */ +u16 pci_s_find_next_capability(pci_devfn_t dev, u16 cap, u16 last) +{ + u16 pos = 0; + u16 status; + int reps = 48; + + status = pci_s_read_config16(dev, PCI_STATUS); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + + u8 hdr_type = pci_s_read_config8(dev, PCI_HEADER_TYPE); + switch (hdr_type & 0x7f) { + case PCI_HEADER_TYPE_NORMAL: + case PCI_HEADER_TYPE_BRIDGE: + pos = PCI_CAPABILITY_LIST; + break; + case PCI_HEADER_TYPE_CARDBUS: + pos = PCI_CB_CAPABILITY_LIST; + break; + default: + return 0; + } + + pos = pci_s_read_config8(dev, pos); + while (reps-- && (pos >= 0x40)) { /* Loop through the linked list. */ + int this_cap; + + pos &= ~3; + this_cap = pci_s_read_config8(dev, pos + PCI_CAP_LIST_ID); + if (this_cap == 0xff) + break; + + if (!last && (this_cap == cap)) + return pos; + + if (last == pos) + last = 0; + + pos = pci_s_read_config8(dev, pos + PCI_CAP_LIST_NEXT); + } + return 0; +} + +/** + * Given a device, and a capability type, return the next matching + * capability. Always start at the head of the list. + * + * @param dev Pointer to the device structure. + * @param cap PCI_CAP_LIST_ID of the PCI capability we're looking for. + * @return The next matching capability. + */ +u16 pci_s_find_capability(pci_devfn_t dev, u16 cap) +{ + return pci_s_find_next_capability(dev, cap, 0); +} |