mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
Add PCI methods to iterate over the PCI capabilities
VirtIO V1 provides configuration in multiple VENDOR capabilities so this allows all of the configuration to be discovered. Reviewed by: jhb MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D14325
This commit is contained in:
parent
21d5bcbe67
commit
7a16dacdfa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329598
|
@ -42,6 +42,9 @@
|
|||
.Nm pci_find_device ,
|
||||
.Nm pci_find_extcap ,
|
||||
.Nm pci_find_htcap ,
|
||||
.Nm pci_find_next_cap ,
|
||||
.Nm pci_find_next_extcap ,
|
||||
.Nm pci_find_next_htcap ,
|
||||
.Nm pci_find_pcie_root_port ,
|
||||
.Nm pci_get_id ,
|
||||
.Nm pci_get_max_payload ,
|
||||
|
@ -100,6 +103,12 @@
|
|||
.Fn pci_find_extcap "device_t dev" "int capability" "int *capreg"
|
||||
.Ft int
|
||||
.Fn pci_find_htcap "device_t dev" "int capability" "int *capreg"
|
||||
.Ft int
|
||||
.Fn pci_find_next_cap "device_t dev" "int capability" "int start" "int *capreg"
|
||||
.Ft int
|
||||
.Fn pci_find_next_extcap "device_t dev" "int capability" "int start" "int *capreg"
|
||||
.Ft int
|
||||
.Fn pci_find_next_htcap "device_t dev" "int capability" "int start" "int *capreg"
|
||||
.Ft device_t
|
||||
.Fn pci_find_pcie_root_port "device_t dev"
|
||||
.Ft int
|
||||
|
@ -330,6 +339,22 @@ returns zero.
|
|||
If the capability is not found or the device does not support capabilities,
|
||||
.Fn pci_find_cap
|
||||
returns an error.
|
||||
The
|
||||
.Fn pci_find_next_cap
|
||||
function is used to locate the next instance of a PCI capability
|
||||
register set for the device
|
||||
.Fa dev .
|
||||
The
|
||||
.Fa start
|
||||
should be the
|
||||
.Fa *capreg
|
||||
returned by a prior
|
||||
.Fn pci_find_cap
|
||||
or
|
||||
.Fn pci_find_next_cap .
|
||||
When no more instances are located
|
||||
.Fn pci_find_next_cap
|
||||
returns an error.
|
||||
.Pp
|
||||
The
|
||||
.Fn pci_find_extcap
|
||||
|
@ -352,6 +377,22 @@ If the extended capability is not found or the device is not a
|
|||
PCI-express device,
|
||||
.Fn pci_find_extcap
|
||||
returns an error.
|
||||
The
|
||||
.Fn pci_find_next_extcap
|
||||
function is used to locate the next instance of a PCI-express
|
||||
extended capability register set for the device
|
||||
.Fa dev .
|
||||
The
|
||||
.Fa start
|
||||
should be the
|
||||
.Fa *capreg
|
||||
returned by a prior
|
||||
.Fn pci_find_extcap
|
||||
or
|
||||
.Fn pci_find_next_extcap .
|
||||
When no more instances are located
|
||||
.Fn pci_find_next_extcap
|
||||
returns an error.
|
||||
.Pp
|
||||
The
|
||||
.Fn pci_find_htcap
|
||||
|
@ -373,6 +414,22 @@ returns zero.
|
|||
If the capability is not found or the device is not a HyperTransport device,
|
||||
.Fn pci_find_htcap
|
||||
returns an error.
|
||||
The
|
||||
.Fn pci_find_next_htcap
|
||||
function is used to locate the next instance of a HyperTransport capability
|
||||
register set for the device
|
||||
.Fa dev .
|
||||
The
|
||||
.Fa start
|
||||
should be the
|
||||
.Fa *capreg
|
||||
returned by a prior
|
||||
.Fn pci_find_htcap
|
||||
or
|
||||
.Fn pci_find_next_htcap .
|
||||
When no more instances are located
|
||||
.Fn pci_find_next_htcap
|
||||
returns an error.
|
||||
.Pp
|
||||
The
|
||||
.Fn pci_find_pcie_root_port
|
||||
|
|
|
@ -206,6 +206,14 @@ pci_hostb_find_cap(device_t dev, device_t child, int capability,
|
|||
return (pci_find_cap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_next_cap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_cap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_extcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
|
@ -214,6 +222,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_next_extcap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_extcap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_htcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
|
@ -222,6 +238,14 @@ pci_hostb_find_htcap(device_t dev, device_t child, int capability,
|
|||
return (pci_find_htcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
pci_hostb_find_next_htcap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_htcap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static device_method_t pci_hostb_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pci_hostb_probe),
|
||||
|
@ -252,8 +276,11 @@ static device_method_t pci_hostb_methods[] = {
|
|||
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_next_cap, pci_hostb_find_next_cap),
|
||||
DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap),
|
||||
DEVMETHOD(pci_find_next_extcap, pci_hostb_find_next_extcap),
|
||||
DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap),
|
||||
DEVMETHOD(pci_find_next_htcap, pci_hostb_find_next_htcap),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
|
@ -183,8 +183,11 @@ static device_method_t pci_methods[] = {
|
|||
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_next_cap, pci_find_next_cap_method),
|
||||
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
|
||||
DEVMETHOD(pci_find_next_extcap, pci_find_next_extcap_method),
|
||||
DEVMETHOD(pci_find_htcap, pci_find_htcap_method),
|
||||
DEVMETHOD(pci_find_next_htcap, pci_find_next_htcap_method),
|
||||
DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method),
|
||||
DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method),
|
||||
DEVMETHOD(pci_enable_msi, pci_enable_msi_method),
|
||||
|
@ -1377,7 +1380,7 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
|
|||
* Traverse the capabilities list checking each HT capability
|
||||
* to see if it matches the requested HT capability.
|
||||
*/
|
||||
while (ptr != 0) {
|
||||
for (;;) {
|
||||
val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2);
|
||||
if (capability == PCIM_HTCAP_SLAVE ||
|
||||
capability == PCIM_HTCAP_HOST)
|
||||
|
@ -1391,13 +1394,51 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next requested HyperTransport capability after start 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_next_htcap_method(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
int ptr;
|
||||
uint16_t val;
|
||||
|
||||
KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == PCIY_HT,
|
||||
("start capability is not HyperTransport capability"));
|
||||
ptr = start;
|
||||
|
||||
/*
|
||||
* Traverse the capabilities list checking each HT capability
|
||||
* to see if it matches the requested HT capability.
|
||||
*/
|
||||
for (;;) {
|
||||
/* Skip to the next HT capability. */
|
||||
if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0)
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
|
@ -1412,8 +1453,8 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
|
|||
{
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
pcicfgregs *cfg = &dinfo->cfg;
|
||||
u_int32_t status;
|
||||
u_int8_t ptr;
|
||||
uint32_t status;
|
||||
uint8_t ptr;
|
||||
|
||||
/*
|
||||
* Check the CAP_LIST bit of the PCI status register first.
|
||||
|
@ -1454,6 +1495,33 @@ pci_find_cap_method(device_t dev, device_t child, int capability,
|
|||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next requested capability after start 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_next_cap_method(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
uint8_t ptr;
|
||||
|
||||
KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == capability,
|
||||
("start capability is not expected capability"));
|
||||
|
||||
ptr = pci_read_config(child, start + PCICAP_NEXTPTR, 1);
|
||||
while (ptr != 0) {
|
||||
if (pci_read_config(child, ptr + PCICAP_ID, 1) == capability) {
|
||||
if (capreg != NULL)
|
||||
*capreg = ptr;
|
||||
return (0);
|
||||
}
|
||||
ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1);
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the requested extended capability and return the offset in
|
||||
* configuration space via the pointer provided. The function returns
|
||||
|
@ -1491,6 +1559,41 @@ pci_find_extcap_method(device_t dev, device_t child, int capability,
|
|||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next requested extended capability after start 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_next_extcap_method(device_t dev, device_t child, int capability,
|
||||
int start, 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);
|
||||
|
||||
ecap = pci_read_config(child, start, 4);
|
||||
KASSERT(PCI_EXTCAP_ID(ecap) == capability,
|
||||
("start extended capability is not expected capability"));
|
||||
ptr = PCI_EXTCAP_NEXTPTR(ecap);
|
||||
while (ptr != 0) {
|
||||
ecap = pci_read_config(child, ptr, 4);
|
||||
if (PCI_EXTCAP_ID(ecap) == capability) {
|
||||
if (capreg != NULL)
|
||||
*capreg = ptr;
|
||||
return (0);
|
||||
}
|
||||
ptr = PCI_EXTCAP_NEXTPTR(ecap);
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for MSI-X message interrupts.
|
||||
*/
|
||||
|
|
|
@ -141,6 +141,14 @@ METHOD int find_cap {
|
|||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_next_cap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int start;
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_extcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
|
@ -148,6 +156,14 @@ METHOD int find_extcap {
|
|||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_next_extcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int start;
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_htcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
|
@ -155,6 +171,14 @@ METHOD int find_htcap {
|
|||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int find_next_htcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int start;
|
||||
int *capreg;
|
||||
};
|
||||
|
||||
METHOD int alloc_msi {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
|
|
|
@ -90,10 +90,16 @@ 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_next_cap_method(device_t dev, device_t child,
|
||||
int capability, int start, int *capreg);
|
||||
int pci_find_extcap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
int pci_find_next_extcap_method(device_t dev, device_t child,
|
||||
int capability, int start, int *capreg);
|
||||
int pci_find_htcap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
int pci_find_next_htcap_method(device_t dev, device_t child,
|
||||
int capability, int start, 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);
|
||||
void pci_enable_msi_method(device_t dev, device_t child,
|
||||
|
|
|
@ -467,18 +467,39 @@ pci_find_cap(device_t dev, int capability, int *capreg)
|
|||
return (PCI_FIND_CAP(device_get_parent(dev), dev, capability, capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
pci_find_next_cap(device_t dev, int capability, int start, int *capreg)
|
||||
{
|
||||
return (PCI_FIND_NEXT_CAP(device_get_parent(dev), dev, capability, start,
|
||||
capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
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_next_extcap(device_t dev, int capability, int start, int *capreg)
|
||||
{
|
||||
return (PCI_FIND_NEXT_EXTCAP(device_get_parent(dev), dev, capability,
|
||||
start, 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_find_next_htcap(device_t dev, int capability, int start, int *capreg)
|
||||
{
|
||||
return (PCI_FIND_NEXT_HTCAP(device_get_parent(dev), dev, capability,
|
||||
start, capreg));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
pci_alloc_msi(device_t dev, int *count)
|
||||
{
|
||||
|
|
|
@ -496,6 +496,14 @@ vga_pci_find_cap(device_t dev, device_t child, int capability,
|
|||
return (pci_find_cap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_next_cap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_cap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_extcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
|
@ -504,6 +512,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_next_extcap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_extcap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_htcap(device_t dev, device_t child, int capability,
|
||||
int *capreg)
|
||||
|
@ -512,6 +528,14 @@ vga_pci_find_htcap(device_t dev, device_t child, int capability,
|
|||
return (pci_find_htcap(dev, capability, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_find_next_htcap(device_t dev, device_t child, int capability,
|
||||
int start, int *capreg)
|
||||
{
|
||||
|
||||
return (pci_find_next_htcap(dev, capability, start, capreg));
|
||||
}
|
||||
|
||||
static int
|
||||
vga_pci_alloc_msi(device_t dev, device_t child, int *count)
|
||||
{
|
||||
|
@ -622,8 +646,11 @@ static device_method_t vga_pci_methods[] = {
|
|||
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_next_cap, vga_pci_find_next_cap),
|
||||
DEVMETHOD(pci_find_extcap, vga_pci_find_extcap),
|
||||
DEVMETHOD(pci_find_next_extcap, vga_pci_find_next_extcap),
|
||||
DEVMETHOD(pci_find_htcap, vga_pci_find_htcap),
|
||||
DEVMETHOD(pci_find_next_htcap, vga_pci_find_next_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),
|
||||
|
|
Loading…
Reference in a new issue