Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/pci/pci_pci.c
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <dev/pci/pci_private.h> | #include <dev/pci/pci_private.h> | ||||
#include <dev/pci/pcib_private.h> | #include <dev/pci/pcib_private.h> | ||||
#include "pcib_if.h" | #include "pcib_if.h" | ||||
static int pcib_probe(device_t dev); | static int pcib_probe(device_t dev); | ||||
static int pcib_suspend(device_t dev); | |||||
static int pcib_resume(device_t dev); | static int pcib_resume(device_t dev); | ||||
static int pcib_power_for_sleep(device_t pcib, device_t dev, | static int pcib_power_for_sleep(device_t pcib, device_t dev, | ||||
int *pstate); | int *pstate); | ||||
static int pcib_ari_get_id(device_t pcib, device_t dev, | static int pcib_ari_get_id(device_t pcib, device_t dev, | ||||
enum pci_id_type type, uintptr_t *id); | enum pci_id_type type, uintptr_t *id); | ||||
static uint32_t pcib_read_config(device_t dev, u_int b, u_int s, | static uint32_t pcib_read_config(device_t dev, u_int b, u_int s, | ||||
u_int f, u_int reg, int width); | u_int f, u_int reg, int width); | ||||
static void pcib_write_config(device_t dev, u_int b, u_int s, | static void pcib_write_config(device_t dev, u_int b, u_int s, | ||||
Show All 14 Lines | |||||
static int pcib_reset_child(device_t dev, device_t child, int flags); | static int pcib_reset_child(device_t dev, device_t child, int flags); | ||||
static device_method_t pcib_methods[] = { | static device_method_t pcib_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, pcib_probe), | DEVMETHOD(device_probe, pcib_probe), | ||||
DEVMETHOD(device_attach, pcib_attach), | DEVMETHOD(device_attach, pcib_attach), | ||||
DEVMETHOD(device_detach, pcib_detach), | DEVMETHOD(device_detach, pcib_detach), | ||||
DEVMETHOD(device_shutdown, bus_generic_shutdown), | DEVMETHOD(device_shutdown, bus_generic_shutdown), | ||||
DEVMETHOD(device_suspend, pcib_suspend), | DEVMETHOD(device_suspend, bus_generic_suspend), | ||||
DEVMETHOD(device_resume, pcib_resume), | DEVMETHOD(device_resume, pcib_resume), | ||||
/* Bus interface */ | /* Bus interface */ | ||||
DEVMETHOD(bus_child_present, pcib_child_present), | DEVMETHOD(bus_child_present, pcib_child_present), | ||||
DEVMETHOD(bus_read_ivar, pcib_read_ivar), | DEVMETHOD(bus_read_ivar, pcib_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, pcib_write_ivar), | DEVMETHOD(bus_write_ivar, pcib_write_ivar), | ||||
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), | DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), | ||||
#ifdef NEW_PCIB | |||||
DEVMETHOD(bus_adjust_resource, pcib_adjust_resource), | DEVMETHOD(bus_adjust_resource, pcib_adjust_resource), | ||||
DEVMETHOD(bus_release_resource, pcib_release_resource), | DEVMETHOD(bus_release_resource, pcib_release_resource), | ||||
#else | |||||
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), | |||||
DEVMETHOD(bus_release_resource, bus_generic_release_resource), | |||||
#endif | |||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), | DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), | ||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), | DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), | ||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), | DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), | ||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), | DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), | ||||
DEVMETHOD(bus_reset_child, pcib_reset_child), | DEVMETHOD(bus_reset_child, pcib_reset_child), | ||||
/* pcib interface */ | /* pcib interface */ | ||||
DEVMETHOD(pcib_maxslots, pcib_ari_maxslots), | DEVMETHOD(pcib_maxslots, pcib_ari_maxslots), | ||||
Show All 17 Lines | |||||
}; | }; | ||||
static devclass_t pcib_devclass; | static devclass_t pcib_devclass; | ||||
DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); | DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); | ||||
EARLY_DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL, | EARLY_DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL, | ||||
BUS_PASS_BUS); | BUS_PASS_BUS); | ||||
#if defined(NEW_PCIB) || defined(PCI_HP) | |||||
SYSCTL_DECL(_hw_pci); | SYSCTL_DECL(_hw_pci); | ||||
rpokala: This drops the `PCI_HP` check in addition to `NEW_PCIB`; is that what you intended? | |||||
jrtc27AuthorUnsubmitted Done Inline ActionsYes, because true || X is always true, it's only where it's an && that the RHS needs to stay jrtc27: Yes, because true || X is always true, it's only where it's an && that the RHS needs to stay | |||||
#endif | |||||
#ifdef NEW_PCIB | |||||
static int pci_clear_pcib; | static int pci_clear_pcib; | ||||
SYSCTL_INT(_hw_pci, OID_AUTO, clear_pcib, CTLFLAG_RDTUN, &pci_clear_pcib, 0, | SYSCTL_INT(_hw_pci, OID_AUTO, clear_pcib, CTLFLAG_RDTUN, &pci_clear_pcib, 0, | ||||
"Clear firmware-assigned resources for PCI-PCI bridge I/O windows."); | "Clear firmware-assigned resources for PCI-PCI bridge I/O windows."); | ||||
/* | /* | ||||
* Get the corresponding window if this resource from a child device was | * Get the corresponding window if this resource from a child device was | ||||
* sub-allocated from one of our window resource managers. | * sub-allocated from one of our window resource managers. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 636 Lines • ▼ Show 20 Lines | pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid, | ||||
} | } | ||||
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 | #endif | ||||
#else | |||||
/* | |||||
* Is the prefetch window open (eg, can we allocate memory in it?) | |||||
*/ | |||||
static int | |||||
pcib_is_prefetch_open(struct pcib_softc *sc) | |||||
{ | |||||
return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit); | |||||
} | |||||
/* | |||||
* Is the nonprefetch window open (eg, can we allocate memory in it?) | |||||
*/ | |||||
static int | |||||
pcib_is_nonprefetch_open(struct pcib_softc *sc) | |||||
{ | |||||
return (sc->membase > 0 && sc->membase < sc->memlimit); | |||||
} | |||||
/* | |||||
* Is the io window open (eg, can we allocate ports in it?) | |||||
*/ | |||||
static int | |||||
pcib_is_io_open(struct pcib_softc *sc) | |||||
{ | |||||
return (sc->iobase > 0 && sc->iobase < sc->iolimit); | |||||
} | |||||
/* | |||||
* Get current I/O decode. | |||||
*/ | |||||
static void | |||||
pcib_get_io_decode(struct pcib_softc *sc) | |||||
{ | |||||
device_t dev; | |||||
uint32_t iolow; | |||||
dev = sc->dev; | |||||
iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); | |||||
if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) | |||||
sc->iobase = PCI_PPBIOBASE( | |||||
pci_read_config(dev, PCIR_IOBASEH_1, 2), iolow); | |||||
else | |||||
sc->iobase = PCI_PPBIOBASE(0, iolow); | |||||
iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); | |||||
if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) | |||||
sc->iolimit = PCI_PPBIOLIMIT( | |||||
pci_read_config(dev, PCIR_IOLIMITH_1, 2), iolow); | |||||
else | |||||
sc->iolimit = PCI_PPBIOLIMIT(0, iolow); | |||||
} | |||||
/* | |||||
* Get current memory decode. | |||||
*/ | |||||
static void | |||||
pcib_get_mem_decode(struct pcib_softc *sc) | |||||
{ | |||||
device_t dev; | |||||
pci_addr_t pmemlow; | |||||
dev = sc->dev; | |||||
sc->membase = PCI_PPBMEMBASE(0, | |||||
pci_read_config(dev, PCIR_MEMBASE_1, 2)); | |||||
sc->memlimit = PCI_PPBMEMLIMIT(0, | |||||
pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); | |||||
pmemlow = pci_read_config(dev, PCIR_PMBASEL_1, 2); | |||||
if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) | |||||
sc->pmembase = PCI_PPBMEMBASE( | |||||
pci_read_config(dev, PCIR_PMBASEH_1, 4), pmemlow); | |||||
else | |||||
sc->pmembase = PCI_PPBMEMBASE(0, pmemlow); | |||||
pmemlow = pci_read_config(dev, PCIR_PMLIMITL_1, 2); | |||||
if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) | |||||
sc->pmemlimit = PCI_PPBMEMLIMIT( | |||||
pci_read_config(dev, PCIR_PMLIMITH_1, 4), pmemlow); | |||||
else | |||||
sc->pmemlimit = PCI_PPBMEMLIMIT(0, pmemlow); | |||||
} | |||||
/* | |||||
* Restore previous I/O decode. | |||||
*/ | |||||
static void | |||||
pcib_set_io_decode(struct pcib_softc *sc) | |||||
{ | |||||
device_t dev; | |||||
uint32_t iohi; | |||||
dev = sc->dev; | |||||
iohi = sc->iobase >> 16; | |||||
if (iohi > 0) | |||||
pci_write_config(dev, PCIR_IOBASEH_1, iohi, 2); | |||||
pci_write_config(dev, PCIR_IOBASEL_1, sc->iobase >> 8, 1); | |||||
iohi = sc->iolimit >> 16; | |||||
if (iohi > 0) | |||||
pci_write_config(dev, PCIR_IOLIMITH_1, iohi, 2); | |||||
pci_write_config(dev, PCIR_IOLIMITL_1, sc->iolimit >> 8, 1); | |||||
} | |||||
/* | |||||
* Restore previous memory decode. | |||||
*/ | |||||
static void | |||||
pcib_set_mem_decode(struct pcib_softc *sc) | |||||
{ | |||||
device_t dev; | |||||
pci_addr_t pmemhi; | |||||
dev = sc->dev; | |||||
pci_write_config(dev, PCIR_MEMBASE_1, sc->membase >> 16, 2); | |||||
pci_write_config(dev, PCIR_MEMLIMIT_1, sc->memlimit >> 16, 2); | |||||
pmemhi = sc->pmembase >> 32; | |||||
if (pmemhi > 0) | |||||
pci_write_config(dev, PCIR_PMBASEH_1, pmemhi, 4); | |||||
pci_write_config(dev, PCIR_PMBASEL_1, sc->pmembase >> 16, 2); | |||||
pmemhi = sc->pmemlimit >> 32; | |||||
if (pmemhi > 0) | |||||
pci_write_config(dev, PCIR_PMLIMITH_1, pmemhi, 4); | |||||
pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmemlimit >> 16, 2); | |||||
} | |||||
#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, | ||||
"Enable support for native PCI-express HotPlug."); | "Enable support for native PCI-express HotPlug."); | ||||
▲ Show 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | pcib_detach_hotplug(struct pcib_softc *sc) | ||||
taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_ab_task); | taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_ab_task); | ||||
taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_cc_task); | taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_cc_task); | ||||
taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_dll_task); | taskqueue_drain_timeout(taskqueue_pci_hp, &sc->pcie_dll_task); | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Get current bridge configuration. | |||||
*/ | |||||
static void | |||||
pcib_cfg_save(struct pcib_softc *sc) | |||||
{ | |||||
#ifndef NEW_PCIB | |||||
device_t dev; | |||||
uint16_t command; | |||||
dev = sc->dev; | |||||
command = pci_read_config(dev, PCIR_COMMAND, 2); | |||||
if (command & PCIM_CMD_PORTEN) | |||||
pcib_get_io_decode(sc); | |||||
if (command & PCIM_CMD_MEMEN) | |||||
pcib_get_mem_decode(sc); | |||||
#endif | |||||
} | |||||
/* | |||||
* Restore previous bridge configuration. | * Restore previous bridge configuration. | ||||
*/ | */ | ||||
static void | static void | ||||
pcib_cfg_restore(struct pcib_softc *sc) | pcib_cfg_restore(struct pcib_softc *sc) | ||||
{ | { | ||||
#ifndef NEW_PCIB | |||||
uint16_t command; | |||||
#endif | |||||
#ifdef NEW_PCIB | |||||
pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM); | pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM); | ||||
#else | |||||
command = pci_read_config(sc->dev, PCIR_COMMAND, 2); | |||||
if (command & PCIM_CMD_PORTEN) | |||||
pcib_set_io_decode(sc); | |||||
if (command & PCIM_CMD_MEMEN) | |||||
pcib_set_mem_decode(sc); | |||||
#endif | |||||
} | } | ||||
/* | /* | ||||
* Generic device interface | * Generic device interface | ||||
*/ | */ | ||||
static int | static int | ||||
pcib_probe(device_t dev) | pcib_probe(device_t dev) | ||||
{ | { | ||||
Show All 15 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(NEW_PCIB) && defined(PCI_RES_BUS)) | #if !defined(PCI_RES_BUS) | ||||
sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); | sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1); | ||||
sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); | sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1); | ||||
#endif | #endif | ||||
sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); | sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); | ||||
pcib_cfg_save(sc); | |||||
/* | /* | ||||
* 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 10 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(NEW_PCIB) && defined(PCI_RES_BUS)) | #if !defined(PCI_RES_BUS) | ||||
case 0x12258086: /* Intel 82454KX/GX (Orion) */ | case 0x12258086: /* Intel 82454KX/GX (Orion) */ | ||||
{ | { | ||||
uint8_t supbus; | uint8_t supbus; | ||||
supbus = pci_read_config(dev, 0x41, 1); | supbus = pci_read_config(dev, 0x41, 1); | ||||
if (supbus != 0xff) { | if (supbus != 0xff) { | ||||
sc->bus.sec = supbus + 1; | sc->bus.sec = supbus + 1; | ||||
sc->bus.sub = supbus + 1; | sc->bus.sub = supbus + 1; | ||||
Show All 10 Lines | #endif | ||||
* 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(NEW_PCIB) && defined(PCI_RES_BUS)) | #if !defined(PCI_RES_BUS) | ||||
/* Compaq R3000 BIOS sets wrong subordinate bus number. */ | /* Compaq R3000 BIOS sets wrong subordinate bus number. */ | ||||
case 0x00dd10de: | case 0x00dd10de: | ||||
{ | { | ||||
char *cp; | char *cp; | ||||
if ((cp = kern_getenv("smbios.planar.maker")) == NULL) | if ((cp = kern_getenv("smbios.planar.maker")) == NULL) | ||||
break; | break; | ||||
if (strncmp(cp, "Compal", 6) != 0) { | if (strncmp(cp, "Compal", 6) != 0) { | ||||
Show All 33 Lines | sc->flags |= PCIB_DISABLE_MSIX; | ||||
*/ | */ | ||||
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 NEW_PCIB | |||||
#ifdef PCI_RES_BUS | #ifdef PCI_RES_BUS | ||||
pcib_setup_secbus(dev, &sc->bus, 1); | pcib_setup_secbus(dev, &sc->bus, 1); | ||||
#endif | #endif | ||||
pcib_probe_windows(sc); | pcib_probe_windows(sc); | ||||
#endif | |||||
#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); | ||||
device_printf(dev, " subordinate bus %d\n", sc->bus.sub); | device_printf(dev, " subordinate bus %d\n", sc->bus.sub); | ||||
#ifdef NEW_PCIB | |||||
if (pcib_is_window_open(&sc->io)) | if (pcib_is_window_open(&sc->io)) | ||||
device_printf(dev, " I/O decode 0x%jx-0x%jx\n", | device_printf(dev, " I/O decode 0x%jx-0x%jx\n", | ||||
(uintmax_t)sc->io.base, (uintmax_t)sc->io.limit); | (uintmax_t)sc->io.base, (uintmax_t)sc->io.limit); | ||||
if (pcib_is_window_open(&sc->mem)) | if (pcib_is_window_open(&sc->mem)) | ||||
device_printf(dev, " memory decode 0x%jx-0x%jx\n", | device_printf(dev, " memory decode 0x%jx-0x%jx\n", | ||||
(uintmax_t)sc->mem.base, (uintmax_t)sc->mem.limit); | (uintmax_t)sc->mem.base, (uintmax_t)sc->mem.limit); | ||||
if (pcib_is_window_open(&sc->pmem)) | if (pcib_is_window_open(&sc->pmem)) | ||||
device_printf(dev, " prefetched decode 0x%jx-0x%jx\n", | device_printf(dev, " prefetched decode 0x%jx-0x%jx\n", | ||||
(uintmax_t)sc->pmem.base, (uintmax_t)sc->pmem.limit); | (uintmax_t)sc->pmem.base, (uintmax_t)sc->pmem.limit); | ||||
#else | |||||
if (pcib_is_io_open(sc)) | |||||
device_printf(dev, " I/O decode 0x%x-0x%x\n", | |||||
sc->iobase, sc->iolimit); | |||||
if (pcib_is_nonprefetch_open(sc)) | |||||
device_printf(dev, " memory decode 0x%jx-0x%jx\n", | |||||
(uintmax_t)sc->membase, (uintmax_t)sc->memlimit); | |||||
if (pcib_is_prefetch_open(sc)) | |||||
device_printf(dev, " prefetched decode 0x%jx-0x%jx\n", | |||||
(uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit); | |||||
#endif | |||||
if (sc->bridgectl & (PCIB_BCR_ISA_ENABLE | PCIB_BCR_VGA_ENABLE) || | if (sc->bridgectl & (PCIB_BCR_ISA_ENABLE | PCIB_BCR_VGA_ENABLE) || | ||||
sc->flags & PCIB_SUBTRACTIVE) { | sc->flags & PCIB_SUBTRACTIVE) { | ||||
device_printf(dev, " special decode "); | device_printf(dev, " special decode "); | ||||
comma = 0; | comma = 0; | ||||
if (sc->bridgectl & PCIB_BCR_ISA_ENABLE) { | if (sc->bridgectl & PCIB_BCR_ISA_ENABLE) { | ||||
printf("ISA"); | printf("ISA"); | ||||
comma = 1; | comma = 1; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | pcib_attach(device_t dev) | ||||
pcib_attach_common(dev); | pcib_attach_common(dev); | ||||
return (pcib_attach_child(dev)); | return (pcib_attach_child(dev)); | ||||
} | } | ||||
int | int | ||||
pcib_detach(device_t dev) | pcib_detach(device_t dev) | ||||
{ | { | ||||
#if defined(PCI_HP) || defined(NEW_PCIB) | |||||
struct pcib_softc *sc; | struct pcib_softc *sc; | ||||
rpokalaUnsubmitted Not Done Inline ActionsThese drop the PCI_HP check as well as the NEW_PCIB check; intentional? rpokala: These drop the `PCI_HP` check as well as the `NEW_PCIB` check; intentional? | |||||
#endif | |||||
int error; | int error; | ||||
#if defined(PCI_HP) || defined(NEW_PCIB) | |||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
#endif | |||||
error = bus_generic_detach(dev); | error = bus_generic_detach(dev); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
#ifdef PCI_HP | #ifdef PCI_HP | ||||
if (sc->flags & PCIB_HOTPLUG) { | if (sc->flags & PCIB_HOTPLUG) { | ||||
error = pcib_detach_hotplug(sc); | error = pcib_detach_hotplug(sc); | ||||
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); | ||||
#ifdef NEW_PCIB | |||||
pcib_free_windows(sc); | pcib_free_windows(sc); | ||||
#ifdef PCI_RES_BUS | #ifdef PCI_RES_BUS | ||||
pcib_free_secbus(dev, &sc->bus); | pcib_free_secbus(dev, &sc->bus); | ||||
#endif | #endif | ||||
#endif | |||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
pcib_suspend(device_t dev) | |||||
{ | |||||
pcib_cfg_save(device_get_softc(dev)); | |||||
return (bus_generic_suspend(dev)); | |||||
} | |||||
emasteUnsubmitted Not Done Inline Actionswhat's the story here? emaste: what's the story here? | |||||
jrtc27AuthorUnsubmitted Done Inline Actionspcib_cfg_save is a no-op without NEW_PCIB so I just replaced the kobj method with bus_generic_suspend jrtc27: pcib_cfg_save is a no-op without NEW_PCIB so I just replaced the kobj method with… | |||||
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)); | ||||
/* | /* | ||||
* Restore the Command register only after restoring the windows. | * Restore the Command register only after restoring the windows. | ||||
* The bridge should not be claiming random windows. | * The bridge should not be claiming random windows. | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) | ||||
case PCIB_IVAR_DOMAIN: | case PCIB_IVAR_DOMAIN: | ||||
return(EINVAL); | return(EINVAL); | ||||
case PCIB_IVAR_BUS: | case PCIB_IVAR_BUS: | ||||
return(EINVAL); | return(EINVAL); | ||||
} | } | ||||
return(ENOENT); | return(ENOENT); | ||||
} | } | ||||
#ifdef NEW_PCIB | |||||
/* | /* | ||||
* Attempt to allocate a resource from the existing resources assigned | * Attempt to allocate a resource from the existing resources assigned | ||||
* to a window. | * to a window. | ||||
*/ | */ | ||||
static struct resource * | static struct resource * | ||||
pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, | ||||
device_t child, int type, int *rid, rman_res_t start, rman_res_t end, | device_t child, int type, int *rid, rman_res_t start, rman_res_t end, | ||||
rman_res_t count, u_int flags) | rman_res_t count, u_int flags) | ||||
▲ Show 20 Lines • Show All 539 Lines • ▼ Show 20 Lines | if (rman_get_flags(r) & RF_ACTIVE) { | ||||
error = bus_deactivate_resource(child, type, rid, r); | error = bus_deactivate_resource(child, type, rid, r); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
return (rman_release_resource(r)); | return (rman_release_resource(r)); | ||||
} | } | ||||
return (bus_generic_release_resource(dev, child, type, rid, r)); | return (bus_generic_release_resource(dev, child, type, rid, r)); | ||||
} | } | ||||
#else | |||||
/* | |||||
* We have to trap resource allocation requests and ensure that the bridge | |||||
* is set up to, or capable of handling them. | |||||
*/ | |||||
struct resource * | |||||
pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, | |||||
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | |||||
{ | |||||
struct pcib_softc *sc = device_get_softc(dev); | |||||
const char *name, *suffix; | |||||
int ok; | |||||
/* | |||||
* Fail the allocation for this range if it's not supported. | |||||
*/ | |||||
name = device_get_nameunit(child); | |||||
if (name == NULL) { | |||||
name = ""; | |||||
suffix = ""; | |||||
} else | |||||
suffix = " "; | |||||
switch (type) { | |||||
case SYS_RES_IOPORT: | |||||
ok = 0; | |||||
if (!pcib_is_io_open(sc)) | |||||
break; | |||||
ok = (start >= sc->iobase && end <= sc->iolimit); | |||||
/* | |||||
* Make sure we allow access to VGA I/O addresses when the | |||||
* bridge has the "VGA Enable" bit set. | |||||
*/ | |||||
if (!ok && pci_is_vga_ioport_range(start, end)) | |||||
ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; | |||||
if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { | |||||
if (!ok) { | |||||
if (start < sc->iobase) | |||||
start = sc->iobase; | |||||
if (end > sc->iolimit) | |||||
end = sc->iolimit; | |||||
if (start < end) | |||||
ok = 1; | |||||
} | |||||
} else { | |||||
ok = 1; | |||||
#if 0 | |||||
/* | |||||
* If we overlap with the subtractive range, then | |||||
* pick the upper range to use. | |||||
*/ | |||||
if (start < sc->iolimit && end > sc->iobase) | |||||
start = sc->iolimit + 1; | |||||
#endif | |||||
} | |||||
if (end < start) { | |||||
device_printf(dev, "ioport: end (%jx) < start (%jx)\n", | |||||
end, start); | |||||
start = 0; | |||||
end = 0; | |||||
ok = 0; | |||||
} | |||||
if (!ok) { | |||||
device_printf(dev, "%s%srequested unsupported I/O " | |||||
"range 0x%jx-0x%jx (decoding 0x%x-0x%x)\n", | |||||
name, suffix, start, end, sc->iobase, sc->iolimit); | |||||
return (NULL); | |||||
} | |||||
if (bootverbose) | |||||
device_printf(dev, | |||||
"%s%srequested I/O range 0x%jx-0x%jx: in range\n", | |||||
name, suffix, start, end); | |||||
break; | |||||
case SYS_RES_MEMORY: | |||||
ok = 0; | |||||
if (pcib_is_nonprefetch_open(sc)) | |||||
ok = ok || (start >= sc->membase && end <= sc->memlimit); | |||||
if (pcib_is_prefetch_open(sc)) | |||||
ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit); | |||||
/* | |||||
* Make sure we allow access to VGA memory addresses when the | |||||
* bridge has the "VGA Enable" bit set. | |||||
*/ | |||||
if (!ok && pci_is_vga_memory_range(start, end)) | |||||
ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; | |||||
if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { | |||||
if (!ok) { | |||||
ok = 1; | |||||
if (flags & RF_PREFETCHABLE) { | |||||
if (pcib_is_prefetch_open(sc)) { | |||||
if (start < sc->pmembase) | |||||
start = sc->pmembase; | |||||
if (end > sc->pmemlimit) | |||||
end = sc->pmemlimit; | |||||
} else { | |||||
ok = 0; | |||||
} | |||||
} else { /* non-prefetchable */ | |||||
if (pcib_is_nonprefetch_open(sc)) { | |||||
if (start < sc->membase) | |||||
start = sc->membase; | |||||
if (end > sc->memlimit) | |||||
end = sc->memlimit; | |||||
} else { | |||||
ok = 0; | |||||
} | |||||
} | |||||
} | |||||
} else if (!ok) { | |||||
ok = 1; /* subtractive bridge: always ok */ | |||||
#if 0 | |||||
if (pcib_is_nonprefetch_open(sc)) { | |||||
if (start < sc->memlimit && end > sc->membase) | |||||
start = sc->memlimit + 1; | |||||
} | |||||
if (pcib_is_prefetch_open(sc)) { | |||||
if (start < sc->pmemlimit && end > sc->pmembase) | |||||
start = sc->pmemlimit + 1; | |||||
} | |||||
#endif | |||||
} | |||||
if (end < start) { | |||||
device_printf(dev, "memory: end (%jx) < start (%jx)\n", | |||||
end, start); | |||||
start = 0; | |||||
end = 0; | |||||
ok = 0; | |||||
} | |||||
if (!ok && bootverbose) | |||||
device_printf(dev, | |||||
"%s%srequested unsupported memory range %#jx-%#jx " | |||||
"(decoding %#jx-%#jx, %#jx-%#jx)\n", | |||||
name, suffix, start, end, | |||||
(uintmax_t)sc->membase, (uintmax_t)sc->memlimit, | |||||
(uintmax_t)sc->pmembase, (uintmax_t)sc->pmemlimit); | |||||
if (!ok) | |||||
return (NULL); | |||||
if (bootverbose) | |||||
device_printf(dev,"%s%srequested memory range " | |||||
"0x%jx-0x%jx: good\n", | |||||
name, suffix, start, end); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
/* | |||||
* Bridge is OK decoding this resource, so pass it up. | |||||
*/ | |||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end, | |||||
count, flags)); | |||||
} | |||||
#endif | |||||
/* | /* | ||||
* If ARI is enabled on this downstream port, translate the function number | * If ARI is enabled on this downstream port, translate the function number | ||||
* to the non-ARI slot/function. The downstream port will convert it back in | * to the non-ARI slot/function. The downstream port will convert it back in | ||||
* hardware. If ARI is not enabled slot and func are not modified. | * hardware. If ARI is not enabled slot and func are not modified. | ||||
*/ | */ | ||||
static __inline void | static __inline void | ||||
pcib_xlate_ari(device_t pcib, int bus, int *slot, int *func) | pcib_xlate_ari(device_t pcib, int bus, int *slot, int *func) | ||||
▲ Show 20 Lines • Show All 424 Lines • Show Last 20 Lines |
This drops the PCI_HP check in addition to NEW_PCIB; is that what you intended?