Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/pci_pci.c
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Is a resource from a child device sub-allocated from one of our | * Is a resource from a child device sub-allocated from one of our | ||||
* resource managers? | * resource managers? | ||||
*/ | */ | ||||
static int | static int | ||||
pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r) | pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r) | ||||
{ | { | ||||
#ifdef PCI_RES_BUS | |||||
if (type == PCI_RES_BUS) | if (type == PCI_RES_BUS) | ||||
return (rman_is_region_manager(r, &sc->bus.rman)); | return (rman_is_region_manager(r, &sc->bus.rman)); | ||||
#endif | |||||
return (pcib_get_resource_window(sc, type, r) != NULL); | return (pcib_get_resource_window(sc, type, r) != NULL); | ||||
} | } | ||||
static int | static int | ||||
pcib_is_window_open(struct pcib_window *pw) | pcib_is_window_open(struct pcib_window *pw) | ||||
{ | { | ||||
return (pw->valid && pw->base < pw->limit); | return (pw->valid && pw->base < pw->limit); | ||||
▲ Show 20 Lines • Show All 407 Lines • ▼ Show 20 Lines | |||||
pcib_free_windows(struct pcib_softc *sc) | pcib_free_windows(struct pcib_softc *sc) | ||||
{ | { | ||||
pcib_release_window(sc, &sc->pmem, SYS_RES_MEMORY); | pcib_release_window(sc, &sc->pmem, SYS_RES_MEMORY); | ||||
pcib_release_window(sc, &sc->mem, SYS_RES_MEMORY); | pcib_release_window(sc, &sc->mem, SYS_RES_MEMORY); | ||||
pcib_release_window(sc, &sc->io, SYS_RES_IOPORT); | pcib_release_window(sc, &sc->io, SYS_RES_IOPORT); | ||||
} | } | ||||
#ifdef PCI_RES_BUS | |||||
/* | /* | ||||
* Allocate a suitable secondary bus for this bridge if needed and | * Allocate a suitable secondary bus for this bridge if needed and | ||||
* initialize the resource manager for the secondary bus range. Note | * initialize the resource manager for the secondary bus range. Note | ||||
* that the minimum count is a desired value and this may allocate a | * that the minimum count is a desired value and this may allocate a | ||||
* smaller range. | * smaller range. | ||||
*/ | */ | ||||
void | void | ||||
pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count) | pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count) | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | if (bootverbose) { | ||||
printf("\tback candidate range: %ju-%ju\n", start_free, | printf("\tback candidate range: %ju-%ju\n", start_free, | ||||
new_end); | new_end); | ||||
} | } | ||||
if (pcib_grow_subbus(bus, new_end) == 0) | if (pcib_grow_subbus(bus, new_end) == 0) | ||||
return (pcib_suballoc_bus(bus, child, rid, start, end, count, | return (pcib_suballoc_bus(bus, child, rid, start, end, count, | ||||
flags)); | flags)); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#endif | |||||
#ifdef PCI_HP | #ifdef PCI_HP | ||||
/* | /* | ||||
* PCI-express HotPlug support. | * PCI-express HotPlug support. | ||||
*/ | */ | ||||
static int pci_enable_pcie_hp = 1; | static int pci_enable_pcie_hp = 1; | ||||
SYSCTL_INT(_hw_pci, OID_AUTO, enable_pcie_hp, CTLFLAG_RDTUN, | SYSCTL_INT(_hw_pci, OID_AUTO, enable_pcie_hp, CTLFLAG_RDTUN, | ||||
&pci_enable_pcie_hp, 0, | &pci_enable_pcie_hp, 0, | ||||
▲ Show 20 Lines • Show All 590 Lines • ▼ Show 20 Lines | pcib_attach_common(device_t dev) | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
/* | /* | ||||
* Get current bridge configuration. | * Get current bridge configuration. | ||||
*/ | */ | ||||
sc->domain = pci_get_domain(dev); | sc->domain = pci_get_domain(dev); | ||||
#if !defined(PCI_RES_BUS) | |||||
sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); | |||||
sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); | |||||
#endif | |||||
sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); | sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); | ||||
/* | /* | ||||
* The primary bus register should always be the bus of the | * The primary bus register should always be the bus of the | ||||
* parent. | * parent. | ||||
*/ | */ | ||||
sc->pribus = pci_get_bus(dev); | sc->pribus = pci_get_bus(dev); | ||||
pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); | pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); | ||||
Show All 11 Lines | SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", | ||||
CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number"); | CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number"); | ||||
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", | SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", | ||||
CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number"); | CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number"); | ||||
/* | /* | ||||
* Quirk handling. | * Quirk handling. | ||||
*/ | */ | ||||
switch (pci_get_devid(dev)) { | switch (pci_get_devid(dev)) { | ||||
#if !defined(PCI_RES_BUS) | |||||
case 0x12258086: /* Intel 82454KX/GX (Orion) */ | |||||
{ | |||||
uint8_t supbus; | |||||
supbus = pci_read_config(dev, 0x41, 1); | |||||
if (supbus != 0xff) { | |||||
sc->bus.sec = supbus + 1; | |||||
sc->bus.sub = supbus + 1; | |||||
} | |||||
break; | |||||
} | |||||
#endif | |||||
imp: Maybe this is a separate commit? IT's super-duper old hw that I doubt freebsd could still boot… | |||||
Not Done Inline ActionsI think in the PCI_RES_BUS case I had previously replicated this logic up in the pci(4) bus driver since it now tracks bus numbers in ivars. In particular, check pci_reserve_secbus in sys/dev/pci/pci.c. jhb: I think in the PCI_RES_BUS case I had previously replicated this logic up in the pci(4) bus… | |||||
Done Inline ActionsAlso I'm not removing functionality, I'm removing code that's always compiled out jrtc27: Also I'm not removing functionality, I'm removing code that's always compiled out | |||||
/* | /* | ||||
* The i82380FB mobile docking controller is a PCI-PCI bridge, | * The i82380FB mobile docking controller is a PCI-PCI bridge, | ||||
* and it is a subtractive bridge. However, the ProgIf is wrong | * and it is a subtractive bridge. However, the ProgIf is wrong | ||||
* so the normal setting of PCIB_SUBTRACTIVE bit doesn't | * so the normal setting of PCIB_SUBTRACTIVE bit doesn't | ||||
* happen. There are also Toshiba and Cavium ThunderX bridges | * happen. There are also Toshiba and Cavium ThunderX bridges | ||||
* that behave this way. | * that behave this way. | ||||
*/ | */ | ||||
case 0xa002177d: /* Cavium ThunderX */ | case 0xa002177d: /* Cavium ThunderX */ | ||||
case 0x124b8086: /* Intel 82380FB Mobile */ | case 0x124b8086: /* Intel 82380FB Mobile */ | ||||
case 0x060513d7: /* Toshiba ???? */ | case 0x060513d7: /* Toshiba ???? */ | ||||
sc->flags |= PCIB_SUBTRACTIVE; | sc->flags |= PCIB_SUBTRACTIVE; | ||||
break; | break; | ||||
#if !defined(PCI_RES_BUS) | |||||
/* Compaq R3000 BIOS sets wrong subordinate bus number. */ | |||||
Not Done Inline Actions2003/2004 era laptop... likely related to the hacks I had in cbb imp: 2003/2004 era laptop... likely related to the hacks I had in cbb | |||||
case 0x00dd10de: | |||||
{ | |||||
char *cp; | |||||
if ((cp = kern_getenv("smbios.planar.maker")) == NULL) | |||||
break; | |||||
if (strncmp(cp, "Compal", 6) != 0) { | |||||
freeenv(cp); | |||||
break; | |||||
} | } | ||||
freeenv(cp); | |||||
if ((cp = kern_getenv("smbios.planar.product")) == NULL) | |||||
break; | |||||
if (strncmp(cp, "08A0", 4) != 0) { | |||||
freeenv(cp); | |||||
break; | |||||
} | |||||
freeenv(cp); | |||||
if (sc->bus.sub < 0xa) { | |||||
pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1); | |||||
sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); | |||||
} | |||||
break; | |||||
} | |||||
#endif | |||||
} | |||||
if (pci_msi_device_blacklisted(dev)) | if (pci_msi_device_blacklisted(dev)) | ||||
sc->flags |= PCIB_DISABLE_MSI; | sc->flags |= PCIB_DISABLE_MSI; | ||||
if (pci_msix_device_blacklisted(dev)) | if (pci_msix_device_blacklisted(dev)) | ||||
sc->flags |= PCIB_DISABLE_MSIX; | sc->flags |= PCIB_DISABLE_MSIX; | ||||
/* | /* | ||||
* Intel 815, 845 and other chipsets say they are PCI-PCI bridges, | * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, | ||||
* but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, | * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, | ||||
* BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. | * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. | ||||
* This means they act as if they were subtractively decoding | * This means they act as if they were subtractively decoding | ||||
* bridges and pass all transactions. Mark them and real ProgIf 1 | * bridges and pass all transactions. Mark them and real ProgIf 1 | ||||
* parts as subtractive. | * parts as subtractive. | ||||
*/ | */ | ||||
if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 || | if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 || | ||||
pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE) | pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE) | ||||
sc->flags |= PCIB_SUBTRACTIVE; | sc->flags |= PCIB_SUBTRACTIVE; | ||||
#ifdef PCI_HP | #ifdef PCI_HP | ||||
pcib_probe_hotplug(sc); | pcib_probe_hotplug(sc); | ||||
#endif | #endif | ||||
#ifdef PCI_RES_BUS | |||||
pcib_setup_secbus(dev, &sc->bus, 1); | pcib_setup_secbus(dev, &sc->bus, 1); | ||||
#endif | |||||
pcib_probe_windows(sc); | pcib_probe_windows(sc); | ||||
#ifdef PCI_HP | #ifdef PCI_HP | ||||
if (sc->flags & PCIB_HOTPLUG) | if (sc->flags & PCIB_HOTPLUG) | ||||
pcib_setup_hotplug(sc); | pcib_setup_hotplug(sc); | ||||
#endif | #endif | ||||
if (bootverbose) { | if (bootverbose) { | ||||
device_printf(dev, " domain %d\n", sc->domain); | device_printf(dev, " domain %d\n", sc->domain); | ||||
device_printf(dev, " secondary bus %d\n", sc->bus.sec); | device_printf(dev, " secondary bus %d\n", sc->bus.sec); | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | if (sc->flags & PCIB_HOTPLUG) { | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif | #endif | ||||
error = device_delete_children(dev); | error = device_delete_children(dev); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
pcib_free_windows(sc); | pcib_free_windows(sc); | ||||
#ifdef PCI_RES_BUS | |||||
pcib_free_secbus(dev, &sc->bus); | pcib_free_secbus(dev, &sc->bus); | ||||
#endif | |||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pcib_resume(device_t dev) | pcib_resume(device_t dev) | ||||
{ | { | ||||
pcib_cfg_restore(device_get_softc(dev)); | pcib_cfg_restore(device_get_softc(dev)); | ||||
▲ Show 20 Lines • Show All 465 Lines • ▼ Show 20 Lines | if ((type == SYS_RES_IOPORT && pci_is_vga_ioport_range(start, end)) || | ||||
if (sc->bridgectl & PCIB_BCR_VGA_ENABLE) | if (sc->bridgectl & PCIB_BCR_VGA_ENABLE) | ||||
return (bus_generic_alloc_resource(dev, child, type, | return (bus_generic_alloc_resource(dev, child, type, | ||||
rid, start, end, count, flags)); | rid, start, end, count, flags)); | ||||
else | else | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
switch (type) { | switch (type) { | ||||
#ifdef PCI_RES_BUS | |||||
case PCI_RES_BUS: | case PCI_RES_BUS: | ||||
return (pcib_alloc_subbus(&sc->bus, child, rid, start, end, | return (pcib_alloc_subbus(&sc->bus, child, rid, start, end, | ||||
count, flags)); | count, flags)); | ||||
#endif | |||||
case SYS_RES_IOPORT: | case SYS_RES_IOPORT: | ||||
if (pcib_is_isa_range(sc, start, end, count)) | if (pcib_is_isa_range(sc, start, end, count)) | ||||
return (NULL); | return (NULL); | ||||
r = pcib_suballoc_resource(sc, &sc->io, child, type, rid, start, | r = pcib_suballoc_resource(sc, &sc->io, child, type, rid, start, | ||||
end, count, flags); | end, count, flags); | ||||
if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0) | if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0) | ||||
break; | break; | ||||
if (pcib_grow_window(sc, &sc->io, type, start, end, count, | if (pcib_grow_window(sc, &sc->io, type, start, end, count, | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r, | ||||
/* | /* | ||||
* If the resource wasn't sub-allocated from one of our region | * If the resource wasn't sub-allocated from one of our region | ||||
* managers then just pass the request up. | * managers then just pass the request up. | ||||
*/ | */ | ||||
if (!pcib_is_resource_managed(sc, type, r)) | if (!pcib_is_resource_managed(sc, type, r)) | ||||
return (bus_generic_adjust_resource(bus, child, type, r, | return (bus_generic_adjust_resource(bus, child, type, r, | ||||
start, end)); | start, end)); | ||||
#ifdef PCI_RES_BUS | |||||
if (type == PCI_RES_BUS) { | if (type == PCI_RES_BUS) { | ||||
/* | /* | ||||
* If our bus range isn't big enough to grow the sub-allocation | * If our bus range isn't big enough to grow the sub-allocation | ||||
* then we need to grow our bus range. Any request that would | * then we need to grow our bus range. Any request that would | ||||
* require us to decrease the start of our own bus range is | * require us to decrease the start of our own bus range is | ||||
* invalid, we can only extend the end; ignore such requests | * invalid, we can only extend the end; ignore such requests | ||||
* and let rman_adjust_resource fail below. | * and let rman_adjust_resource fail below. | ||||
*/ | */ | ||||
if (start >= sc->bus.sec && end > sc->bus.sub) { | if (start >= sc->bus.sec && end > sc->bus.sub) { | ||||
error = pcib_grow_subbus(&sc->bus, end); | error = pcib_grow_subbus(&sc->bus, end); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
} else | } else { | ||||
#endif | |||||
{ | |||||
/* | /* | ||||
* Resource is managed and not a secondary bus number, must | * Resource is managed and not a secondary bus number, must | ||||
* be from one of our windows. | * be from one of our windows. | ||||
*/ | */ | ||||
w = pcib_get_resource_window(sc, type, r); | w = pcib_get_resource_window(sc, type, r); | ||||
KASSERT(w != NULL, | KASSERT(w != NULL, | ||||
("%s: no window for resource (%#jx-%#jx) type %d", | ("%s: no window for resource (%#jx-%#jx) type %d", | ||||
__func__, rman_get_start(r), rman_get_end(r), type)); | __func__, rman_get_start(r), rman_get_end(r), type)); | ||||
▲ Show 20 Lines • Show All 474 Lines • Show Last 20 Lines |
Maybe this is a separate commit? IT's super-duper old hw that I doubt freebsd could still boot on...
But maybe it's ok to include in this omnibus cleanup.