Add a new method PCI_FIND_EXTCAP() to the pci bus interface that is used
to search for a specific extended capability. If the specified capability is found for the given device, then the function returns success and optionally returns the offset of that capability. If the capability is not found, the function returns an error.
This commit is contained in:
parent
52146665a5
commit
4f9795b9fe
@ -117,6 +117,7 @@ static device_method_t acpi_pci_methods[] = {
|
||||
DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
|
||||
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
|
||||
DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
|
||||
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -133,6 +133,7 @@ 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_extcap, pci_find_extcap_method),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
@ -449,10 +450,10 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
|
||||
}
|
||||
/* Find the next entry */
|
||||
ptr = nextptr;
|
||||
nextptr = REG(ptr + 1, 1);
|
||||
nextptr = REG(ptr + PCICAP_NEXTPTR, 1);
|
||||
|
||||
/* Process this entry */
|
||||
switch (REG(ptr, 1)) {
|
||||
switch (REG(ptr + PCICAP_ID, 1)) {
|
||||
case PCIY_PMG: /* PCI power management */
|
||||
if (cfg->pp.pp_cap == 0) {
|
||||
cfg->pp.pp_cap = REG(ptr + PCIR_POWER_CAP, 2);
|
||||
@ -477,6 +478,57 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
|
||||
#undef REG
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset in configuration space of the requested extended
|
||||
* capability entry or 0 if the specified capability was not found.
|
||||
*/
|
||||
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;
|
||||
u_int32_t status;
|
||||
u_int8_t ptr;
|
||||
|
||||
/*
|
||||
* Check the CAP_LIST bit of the PCI status register first.
|
||||
*/
|
||||
status = pci_read_config(child, PCIR_STATUS, 2);
|
||||
if (!(status & PCIM_STATUS_CAPPRESENT))
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* Determine the start pointer of the capabilities list.
|
||||
*/
|
||||
switch (cfg->hdrtype & PCIM_HDRTYPE) {
|
||||
case 0:
|
||||
ptr = PCIR_CAP_PTR;
|
||||
break;
|
||||
case 2:
|
||||
ptr = PCIR_CAP_PTR_2;
|
||||
break;
|
||||
default:
|
||||
/* XXX: panic? */
|
||||
return (ENXIO); /* no extended capabilities support */
|
||||
}
|
||||
ptr = pci_read_config(child, ptr, 1);
|
||||
|
||||
/*
|
||||
* Traverse the capabilities list.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/* free pcicfgregs structure and all depending data structures */
|
||||
|
||||
int
|
||||
|
@ -82,3 +82,10 @@ METHOD int assign_interrupt {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
};
|
||||
|
||||
METHOD int find_extcap {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
int capability;
|
||||
int *capreg;
|
||||
};
|
||||
|
@ -59,6 +59,8 @@ 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_extcap_method(device_t dev, device_t child,
|
||||
int capability, int *capreg);
|
||||
struct resource *pci_alloc_resource(device_t dev, device_t child,
|
||||
int type, int *rid, u_long start, u_long end, u_long count,
|
||||
u_int flags);
|
||||
|
@ -88,6 +88,11 @@
|
||||
#define PCIM_MFDEV 0x80
|
||||
#define PCIR_BIST 0x0f
|
||||
|
||||
/* Capability Register Offsets */
|
||||
|
||||
#define PCICAP_ID 0x0
|
||||
#define PCICAP_NEXTPTR 0x1
|
||||
|
||||
/* Capability Identification Numbers */
|
||||
|
||||
#define PCIY_PMG 0x01 /* PCI Power Management */
|
||||
|
@ -348,6 +348,12 @@ pci_get_powerstate(device_t dev)
|
||||
return PCI_GET_POWERSTATE(device_get_parent(dev), dev);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
pci_find_extcap(device_t dev, int capability, int *capreg)
|
||||
{
|
||||
return PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg);
|
||||
}
|
||||
|
||||
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
|
||||
device_t pci_find_device(uint16_t, uint16_t);
|
||||
#endif /* _SYS_BUS_H_ */
|
||||
|
@ -106,6 +106,7 @@ static device_method_t ofw_pcibus_methods[] = {
|
||||
DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
|
||||
DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
|
||||
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
|
||||
DEVMETHOD(pci_find_extcap, pci_find_extcap_method),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo),
|
||||
|
Loading…
Reference in New Issue
Block a user