diff options
author | jhb <jhb@FreeBSD.org> | 2015-11-05 21:26:06 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2015-11-05 21:26:06 +0000 |
commit | 0c12e4753ba6951c7105eee5418f69cfda826f9c (patch) | |
tree | 8c409df6aaf8e0cc9b8b82131928b46509d8b572 /sys/dev/pci/pci.c | |
parent | 42d9b66898a9a9cbc2e8113e8c44b5acebc7109b (diff) | |
download | FreeBSD-src-0c12e4753ba6951c7105eee5418f69cfda826f9c.zip FreeBSD-src-0c12e4753ba6951c7105eee5418f69cfda826f9c.tar.gz |
Add helper routines for PCI device drivers to read, write, and modify
PCI-Express capability registers (that is, PCI config registers in the
standard PCI config space belonging to the PCI-Express capability
register set).
Note that all of the current PCI-e registers are either 16 or 32-bits,
so only widths of 2 or 4 bytes are supported.
Reviewed by: imp
MFC after: 1 week
Sponsored by: Chelsio
Differential Revision: https://reviews.freebsd.org/D4088
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r-- | sys/dev/pci/pci.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 39d311f..5116a4f 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1917,6 +1917,63 @@ pci_set_max_read_req(device_t dev, int size) return (size); } +uint32_t +pcie_read_config(device_t dev, int reg, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) { + if (width == 2) + return (0xffff); + return (0xffffffff); + } + + return (pci_read_config(dev, cap + reg, width)); +} + +void +pcie_write_config(device_t dev, int reg, uint32_t value, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return; + pci_write_config(dev, cap + reg, value, width); +} + +/* + * Adjusts a PCI-e capability register by clearing the bits in mask + * and setting the bits in (value & mask). Bits not set in mask are + * not adjusted. + * + * Returns the old value on success or all ones on failure. + */ +uint32_t +pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, + int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + uint32_t old, new; + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) { + if (width == 2) + return (0xffff); + return (0xffffffff); + } + + old = pci_read_config(dev, cap + reg, width); + new = old & ~mask; + new |= (value & mask); + pci_write_config(dev, cap + reg, new, width); + return (old); +} + /* * Support for MSI message signalled interrupts. */ |