Expand the set of APIs available for locating PCI capabilities:
- pci_find_extcap() is repurposed to be used for fetching PCI-express extended capabilities (PCIZ_* constants in <dev/pci/pcireg.h>). - pci_find_htcap() can be used to locate a specific HyperTransport capability (PCIM_HTCAP_* constants in <dev/pci/pcireg.h>). - Cache the starting location of the PCI-express capability for PCI-express devices in PCI device ivars.
This commit is contained in:
parent
5794e3ef03
commit
db63f69541
@ -196,6 +196,14 @@ pci_hostb_assign_interrupt(device_t dev, device_t child)
|
||||
return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_cap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_cap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_extcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
@ -204,6 +212,14 @@ pci_hostb_find_extcap(device_t dev, device_t child, int capability,
|
||||
return (pci_find_extcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_htcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_htcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static device_method_t pci_hostb_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pci_hostb_probe),
|
||||
@ -233,7 +249,9 @@ static device_method_t pci_hostb_methods[] = {
|
||||
DEVMETHOD(pci_get_powerstate, pci_hostb_get_powerstate),
|
||||
DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate),
|
||||
DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt),
|
||||
DEVMETHOD(pci_find_cap, pci_hostb_find_cap),
|
||||
DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap),
|
||||
DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -177,7 +177,9 @@ static device_method_t pci_methods[] = {
|
||||
DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
|
||||
DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
|
||||
DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
|
||||
DEVMETHOD(pci_find_cap, pci_find_cap_method),
|
||||
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
|
||||
DEVMETHOD(pci_find_htcap, pci_find_htcap_method),
|
||||
DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method),
|
||||
DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method),
|
||||
DEVMETHOD(pci_remap_msix, pci_remap_msix_method),
|
||||
@ -737,6 +739,9 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg)
|
||||
* at least one PCI-express device.
|
||||
*/
|
||||
pcie_chipset = 1;
|
||||
cfg->pcie.pcie_location = ptr;
|
||||
val = REG(ptr + PCIR_EXPRESS_FLAGS, 2);
|
||||
cfg->pcie.pcie_type = val & PCIM_EXP_FLAGS_TYPE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1154,12 +1159,55 @@ pci_get_vpd_readonly_method(device_t dev, device_t child, const char *kw,
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the requested extended capability and return the offset in
|
||||
* configuration space via the pointer provided. The function returns
|
||||
* 0 on success and error code otherwise.
|
||||
* Find the requested HyperTransport capability and return the offset
|
||||
* in configuration space via the pointer provided. The function
|
||||
* returns 0 on success and an error code otherwise.
|
||||
*/
|
||||
int
|
||||
pci_find_extcap_method(device_t dev, device_t child, int capability,
|
||||
pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
|
||||
{
|
||||
int ptr, error;
|
||||
uint16_t val;
|
||||
|
||||
error = pci_find_cap(child, PCIY_HT, &ptr);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Traverse the capabilities list checking each HT capability
|
||||
* to see if it matches the requested HT capability.
|
||||
*/
|
||||
while (ptr != 0) {
|
||||
val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2);
|
||||
if (capability == PCIM_HTCAP_SLAVE ||
|
||||
capability == PCIM_HTCAP_HOST)
|
||||
val &= 0xe000;
|
||||
else
|
||||
val &= PCIM_HTCMD_CAP_MASK;
|
||||
if (val == capability) {
|
||||
if (capreg != NULL)
|
||||
*capreg = ptr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Skip to the next HT capability. */
|
||||
while (ptr != 0) {
|
||||
ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1);
|
||||
if (pci_read_config(child, ptr + PCICAP_ID, 1) ==
|
||||
PCIY_HT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the requested capability and return the offset in
|
||||
* configuration space via the pointer provided. The function returns
|
||||
* 0 on success and an error code otherwise.
|
||||
*/
|
||||
int
|
||||
pci_find_cap_method(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
@ -1206,6 +1254,43 @@ pci_find_extcap_method(device_t dev, device_t child, int capability,
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the requested extended capability and return the offset in
|
||||
* configuration space via the pointer provided. The function returns
|
||||
* 0 on success and an error code otherwise.
|
||||
*/
|
||||
int
|
||||
pci_find_extcap_method(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
pcicfgregs *cfg = &dinfo->cfg;
|
||||
uint32_t ecap;
|
||||
uint16_t ptr;
|
||||
|
||||
/* Only supported for PCI-express devices. */
|
||||
if (cfg->pcie.pcie_location == 0)
|
||||
return (ENXIO);
|
||||
|
||||
ptr = PCIR_EXTCAP;
|
||||
ecap = pci_read_config(child, ptr, 4);
|
||||
if (ecap == 0xffffffff || ecap == 0)
|
||||
return (ENOENT);
|
||||
for (;;) {
|
||||
if (PCI_EXTCAP_ID(ecap) == capability) {
|
||||
if (capreg != NULL)
|
||||
*capreg = ptr;
|
||||
return (0);
|
||||
}
|
||||
ptr = PCI_EXTCAP_NEXTPTR(ecap);
|
||||
if (ptr == 0)
|
||||
break;
|
||||
ecap = pci_read_config(child, ptr, 4);
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for MSI-X message interrupts.
|
||||
*/
|
||||
@ -1696,10 +1781,12 @@ pci_ht_map_msi(device_t dev, uint64_t addr)
|
||||
int
|
||||
pci_get_max_read_req(device_t dev)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(dev);
|
||||
int cap;
|
||||
uint16_t val;
|
||||
|
||||
if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
|
||||
cap = dinfo->cfg.pcie.pcie_location;
|
||||
if (cap == 0)
|
||||
return (0);
|
||||
val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
|
||||
val &= PCIM_EXP_CTL_MAX_READ_REQUEST;
|
||||
@ -1710,10 +1797,12 @@ pci_get_max_read_req(device_t dev)
|
||||
int
|
||||
pci_set_max_read_req(device_t dev, int size)
|
||||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(dev);
|
||||
int cap;
|
||||
uint16_t val;
|
||||
|
||||
if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
|
||||
cap = dinfo->cfg.pcie.pcie_location;
|
||||
if (cap == 0)
|
||||
return (0);
|
||||
if (size < 128)
|
||||
size = 128;
|
||||
|
@ -105,6 +105,13 @@ METHOD int assign_interrupt {
|
||||
device_t child;
|
||||
};
|
||||
|
||||
METHOD int find_cap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_extcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
@ -112,6 +119,13 @@ METHOD int find_extcap {
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_htcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int alloc_msi {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
|
@ -80,8 +80,12 @@ int pci_enable_busmaster_method(device_t dev, device_t child);
|
||||
int pci_disable_busmaster_method(device_t dev, device_t child);
|
||||
int pci_enable_io_method(device_t dev, device_t child, int space);
|
||||
int pci_disable_io_method(device_t dev, device_t child, int space);
|
||||
int pci_find_cap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
int pci_find_extcap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
int pci_find_htcap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
int pci_alloc_msi_method(device_t dev, device_t child, int *count);
|
||||
int pci_alloc_msix_method(device_t dev, device_t child, int *count);
|
||||
int pci_remap_msix_method(device_t dev, device_t child,
|
||||
|
@ -123,6 +123,12 @@ struct pcicfg_ht {
|
||||
uint64_t ht_msiaddr; /* MSI mapping base address */
|
||||
};
|
||||
|
||||
/* Interesting values for PCI-express */
|
||||
struct pcicfg_pcie {
|
||||
uint8_t pcie_location; /* Offset of PCI-e capability registers. */
|
||||
uint8_t pcie_type; /* Device type. */
|
||||
};
|
||||
|
||||
/* config header information common to all header types */
|
||||
typedef struct pcicfg {
|
||||
struct device *dev; /* device which owns this */
|
||||
@ -164,6 +170,7 @@ typedef struct pcicfg {
|
||||
struct pcicfg_msi msi; /* PCI MSI */
|
||||
struct pcicfg_msix msix; /* PCI MSI-X */
|
||||
struct pcicfg_ht ht; /* HyperTransport */
|
||||
struct pcicfg_pcie pcie; /* PCI Express */
|
||||
} pcicfgregs;
|
||||
|
||||
/* additional type 1 device config header information (PCI to PCI bridge) */
|
||||
@ -409,7 +416,7 @@ pci_get_powerstate(device_t dev)
|
||||
static __inline int
|
||||
pci_find_cap(device_t dev, int capability, int *capreg)
|
||||
{
|
||||
return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
|
||||
return (PCI_FIND_CAP(device_get_parent(dev), dev, capability, capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
@ -418,6 +425,12 @@ pci_find_extcap(device_t dev, int capability, int *capreg)
|
||||
return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
pci_find_htcap(device_t dev, int capability, int *capreg)
|
||||
{
|
||||
return (PCI_FIND_HTCAP(device_get_parent(dev), dev, capability, capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
pci_alloc_msi(device_t dev, int *count)
|
||||
{
|
||||
|
@ -313,6 +313,14 @@ vga_pci_assign_interrupt(device_t dev, device_t child)
|
||||
return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_cap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_cap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_extcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
@ -321,6 +329,14 @@ vga_pci_find_extcap(device_t dev, device_t child, int capability,
|
||||
return (pci_find_extcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_htcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_htcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_alloc_msi(device_t dev, device_t child, int *count)
|
||||
{
|
||||
@ -422,7 +438,9 @@ static device_method_t vga_pci_methods[] = {
|
||||
DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate),
|
||||
DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate),
|
||||
DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt),
|
||||
DEVMETHOD(pci_find_cap, vga_pci_find_cap),
|
||||
DEVMETHOD(pci_find_extcap, vga_pci_find_extcap),
|
||||
DEVMETHOD(pci_find_htcap, vga_pci_find_htcap),
|
||||
DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi),
|
||||
DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix),
|
||||
DEVMETHOD(pci_remap_msix, vga_pci_remap_msix),
|
||||
|
@ -278,6 +278,14 @@ siba_bwn_teardown_intr(device_t dev, device_t child, struct resource *irq,
|
||||
return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
|
||||
}
|
||||
|
||||
static int
|
||||
siba_bwn_find_cap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_cap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
siba_bwn_find_extcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
@ -286,6 +294,14 @@ siba_bwn_find_extcap(device_t dev, device_t child, int capability,
|
||||
return (pci_find_extcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
siba_bwn_find_htcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_htcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
siba_bwn_alloc_msi(device_t dev, device_t child, int *count)
|
||||
{
|
||||
@ -405,7 +421,9 @@ static device_method_t siba_bwn_methods[] = {
|
||||
DEVMETHOD(bus_teardown_intr, siba_bwn_teardown_intr),
|
||||
|
||||
/* PCI interface */
|
||||
DEVMETHOD(pci_find_cap, siba_bwn_find_cap),
|
||||
DEVMETHOD(pci_find_extcap, siba_bwn_find_extcap),
|
||||
DEVMETHOD(pci_find_htcap, siba_bwn_find_htcap),
|
||||
DEVMETHOD(pci_alloc_msi, siba_bwn_alloc_msi),
|
||||
DEVMETHOD(pci_release_msi, siba_bwn_release_msi),
|
||||
DEVMETHOD(pci_msi_count, siba_bwn_msi_count),
|
||||
|
Loading…
Reference in New Issue
Block a user