Add support for managing PCI bus numbers. As with BARs and PCI-PCI bridge

I/O windows, the default is to preserve the firmware-assigned resources.
PCI bus numbers are only managed if NEW_PCIB is enabled and the architecture
defines a PCI_RES_BUS resource type.
- Add a helper API to create top-level PCI bus resource managers for each
  PCI domain/segment.  Host-PCI bridge drivers use this API to allocate
  bus numbers from their associated domain.
- Change the PCI bus and CardBus drivers to allocate a bus resource for
  their bus number from the parent PCI bridge device.
- Change the PCI-PCI and PCI-CardBus bridge drivers to allocate the
  full range of bus numbers from secbus to subbus from their parent bridge.
  The drivers also always program their primary bus register.  The bridge
  drivers also support growing their bus range by extending the bus resource
  and updating subbus to match the larger range.
- Add support for managing PCI bus resources to the Host-PCI bridge drivers
  used for amd64 and i386 (acpi_pcib, mptable_pcib, legacy_pcib, and qpi_pcib).
- Define a PCI_RES_BUS resource type for amd64 and i386.

Reviewed by:	imp
MFC after:	1 month
This commit is contained in:
John Baldwin 2014-02-12 04:30:37 +00:00
parent ff9a07fa97
commit 4edef187b8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=261790
20 changed files with 836 additions and 68 deletions

View File

@ -40,5 +40,8 @@
#define SYS_RES_DRQ 2 /* isa dma lines */
#define SYS_RES_MEMORY 3 /* i/o memory */
#define SYS_RES_IOPORT 4 /* i/o ports */
#ifdef NEW_PCIB
#define PCI_RES_BUS 5 /* PCI bus numbers */
#endif
#endif /* !_MACHINE_RESOURCE_H_ */

View File

@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
#include <machine/pci_cfgreg.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
@ -96,6 +97,11 @@ static struct resource *acpi_pcib_acpi_alloc_resource(device_t dev,
static int acpi_pcib_acpi_adjust_resource(device_t dev,
device_t child, int type, struct resource *r,
u_long start, u_long end);
#ifdef PCI_RES_BUS
static int acpi_pcib_acpi_release_resource(device_t dev,
device_t child, int type, int rid,
struct resource *r);
#endif
#endif
static device_method_t acpi_pcib_acpi_methods[] = {
@ -115,7 +121,11 @@ static device_method_t acpi_pcib_acpi_methods[] = {
#else
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
#endif
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
DEVMETHOD(bus_release_resource, acpi_pcib_acpi_release_resource),
#else
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
#endif
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
@ -271,6 +281,20 @@ acpi_pcib_producer_handler(ACPI_RESOURCE *res, void *context)
}
#endif
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
static int
first_decoded_bus(struct acpi_hpcib_softc *sc, u_long *startp)
{
struct resource_list_entry *rle;
rle = resource_list_find(&sc->ap_host_res.hr_rl, PCI_RES_BUS, 0);
if (rle == NULL)
return (ENXIO);
*startp = rle->start;
return (0);
}
#endif
static int
acpi_pcib_acpi_attach(device_t dev)
{
@ -278,6 +302,11 @@ acpi_pcib_acpi_attach(device_t dev)
ACPI_STATUS status;
static int bus0_seen = 0;
u_int slot, func, busok;
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
struct resource *bus_res;
u_long start;
int rid;
#endif
uint8_t busno;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@ -389,6 +418,39 @@ acpi_pcib_acpi_attach(device_t dev)
}
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
/*
* If nothing else worked, hope that ACPI at least lays out the
* Host-PCI bridges in order and that as a result the next free
* bus number is our bus number.
*/
if (busok == 0) {
/*
* If we have a region of bus numbers, use the first
* number for our bus.
*/
if (first_decoded_bus(sc, &start) == 0)
sc->ap_bus = start;
else {
rid = 0;
bus_res = pci_domain_alloc_bus(sc->ap_segment, dev, &rid, 0,
PCI_BUSMAX, 1, 0);
if (bus_res == NULL) {
device_printf(dev,
"could not allocate bus number\n");
pcib_host_res_free(dev, &sc->ap_host_res);
return (ENXIO);
}
sc->ap_bus = rman_get_start(bus_res);
pci_domain_release_bus(sc->ap_segment, dev, rid, bus_res);
}
} else {
#ifdef INVARIANTS
if (first_decoded_bus(sc, &start) == 0)
KASSERT(start == sc->ap_bus, ("bus number mismatch"));
#endif
}
#else
/*
* If nothing else worked, hope that ACPI at least lays out the
* host-PCI bridges in order and that as a result our unit number
@ -399,6 +461,7 @@ acpi_pcib_acpi_attach(device_t dev)
sc->ap_bus = device_get_unit(dev);
device_printf(dev, "trying bus number %d\n", sc->ap_bus);
}
#endif
/* If this is bus 0 on segment 0, note that it has been seen already. */
if (sc->ap_segment == 0 && sc->ap_bus == 0)
@ -534,6 +597,11 @@ acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid,
#ifdef NEW_PCIB
sc = device_get_softc(dev);
#ifdef PCI_RES_BUS
if (type == PCI_RES_BUS)
return (pci_domain_alloc_bus(sc->ap_segment, child, rid, start, end,
count, flags));
#endif
res = pcib_host_res_alloc(&sc->ap_host_res, child, type, rid, start, end,
count, flags);
@ -562,7 +630,26 @@ acpi_pcib_acpi_adjust_resource(device_t dev, device_t child, int type,
struct acpi_hpcib_softc *sc;
sc = device_get_softc(dev);
#ifdef PCI_RES_BUS
if (type == PCI_RES_BUS)
return (pci_domain_adjust_bus(sc->ap_segment, child, r, start,
end));
#endif
return (pcib_host_res_adjust(&sc->ap_host_res, child, type, r, start,
end));
}
#ifdef PCI_RES_BUS
int
acpi_pcib_acpi_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct acpi_hpcib_softc *sc;
sc = device_get_softc(dev);
if (type == PCI_RES_BUS)
return (pci_domain_release_bus(sc->ap_segment, child, rid, r));
return (bus_generic_release_resource(dev, child, type, rid, r));
}
#endif
#endif

View File

@ -120,7 +120,7 @@ acpi_pcib_pci_attach(device_t dev)
pcib_attach_common(dev);
sc = device_get_softc(dev);
sc->ap_handle = acpi_get_handle(dev);
return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.secbus));
return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_pcibsc.bus.sec));
}
static int

View File

@ -96,17 +96,36 @@ static int
cardbus_attach(device_t cbdev)
{
struct cardbus_softc *sc;
#ifdef PCI_RES_BUS
int rid;
#endif
sc = device_get_softc(cbdev);
sc->sc_dev = cbdev;
#ifdef PCI_RES_BUS
rid = 0;
sc->sc_bus = bus_alloc_resource(cbdev, PCI_RES_BUS, &rid,
pcib_get_bus(cbdev), pcib_get_bus(cbdev), 1, 0);
if (sc->sc_bus == NULL) {
device_printf(cbdev, "failed to allocate bus number\n");
return (ENXIO);
}
#endif
return (0);
}
static int
cardbus_detach(device_t cbdev)
{
#ifdef PCI_RES_BUS
struct cardbus_softc *sc;
#endif
cardbus_detach_card(cbdev);
#ifdef PCI_RES_BUS
sc = device_get_softc(cbdev);
(void)bus_release_resource(cbdev, PCI_RES_BUS, 0, sc->sc_bus);
#endif
return (0);
}

View File

@ -69,6 +69,9 @@ struct cardbus_devinfo
struct cardbus_softc
{
device_t sc_dev;
#ifdef PCI_RES_BUS
struct resource *sc_bus;
#endif
};
/*

View File

@ -97,6 +97,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include <dev/pccard/pccardreg.h>
#include <dev/pccard/pccardvar.h>
@ -1548,7 +1549,7 @@ cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
*result = sc->domain;
return (0);
case PCIB_IVAR_BUS:
*result = sc->secbus;
*result = sc->bus.sec;
return (0);
}
return (ENOENT);
@ -1557,14 +1558,12 @@ cbb_read_ivar(device_t brdev, device_t child, int which, uintptr_t *result)
int
cbb_write_ivar(device_t brdev, device_t child, int which, uintptr_t value)
{
struct cbb_softc *sc = device_get_softc(brdev);
switch (which) {
case PCIB_IVAR_DOMAIN:
return (EINVAL);
case PCIB_IVAR_BUS:
sc->secbus = value;
return (0);
return (EINVAL);
}
return (ENOENT);
}

View File

@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$");
#include <isa/isavar.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include <dev/pccard/pccardreg.h>
#include <dev/pccard/pccardvar.h>

View File

@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include <dev/pccard/pccardreg.h>
#include <dev/pccard/pccardvar.h>
@ -303,13 +304,15 @@ cbb_print_config(device_t dev)
static int
cbb_pci_attach(device_t brdev)
{
#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
uint32_t pribus;
#endif
struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev);
struct sysctl_ctx_list *sctx;
struct sysctl_oid *soid;
int rid;
device_t parent;
uint32_t pribus;
parent = device_get_parent(brdev);
mtx_init(&sc->mtx, device_get_nameunit(brdev), "cbb", MTX_DEF);
@ -318,9 +321,13 @@ cbb_pci_attach(device_t brdev)
sc->cbdev = NULL;
sc->exca[0].pccarddev = NULL;
sc->domain = pci_get_domain(brdev);
sc->secbus = pci_read_config(brdev, PCIR_SECBUS_2, 1);
sc->subbus = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
sc->bus.sec = pci_read_config(brdev, PCIR_SECBUS_2, 1);
sc->bus.sub = pci_read_config(brdev, PCIR_SUBBUS_2, 1);
sc->pribus = pcib_get_bus(parent);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
pcib_setup_secbus(brdev, &sc->bus, 1);
#endif
SLIST_INIT(&sc->rl);
cbb_powerstate_d0(brdev);
@ -352,9 +359,9 @@ cbb_pci_attach(device_t brdev)
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus",
CTLFLAG_RD, &sc->pribus, 0, "Primary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus",
CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number");
CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number");
CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number");
#if 0
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "memory",
CTLFLAG_RD, &sc->subbus, 0, "Memory window open");
@ -366,15 +373,16 @@ cbb_pci_attach(device_t brdev)
CTLFLAG_RD, &sc->subbus, 0, "io range 2 open");
#endif
#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
/*
* This is a gross hack. We should be scanning the entire pci
* tree, assigning bus numbers in a way such that we (1) can
* reserve 1 extra bus just in case and (2) all sub busses
* are in an appropriate range.
*/
DEVPRINTF((brdev, "Secondary bus is %d\n", sc->secbus));
DEVPRINTF((brdev, "Secondary bus is %d\n", sc->bus.sec));
pribus = pci_read_config(brdev, PCIR_PRIBUS_2, 1);
if (sc->secbus == 0 || sc->pribus != pribus) {
if (sc->bus.sec == 0 || sc->pribus != pribus) {
if (curr_bus_number <= sc->pribus)
curr_bus_number = sc->pribus + 1;
if (pribus != sc->pribus) {
@ -382,13 +390,14 @@ cbb_pci_attach(device_t brdev)
sc->pribus));
pci_write_config(brdev, PCIR_PRIBUS_2, sc->pribus, 1);
}
sc->secbus = curr_bus_number++;
sc->subbus = curr_bus_number++;
sc->bus.sec = curr_bus_number++;
sc->bus.sub = curr_bus_number++;
DEVPRINTF((brdev, "Secondary bus set to %d subbus %d\n",
sc->secbus, sc->subbus));
pci_write_config(brdev, PCIR_SECBUS_2, sc->secbus, 1);
pci_write_config(brdev, PCIR_SUBBUS_2, sc->subbus, 1);
sc->bus.sec, sc->bus.sub));
pci_write_config(brdev, PCIR_SECBUS_2, sc->bus.sec, 1);
pci_write_config(brdev, PCIR_SUBBUS_2, sc->bus.sub, 1);
}
#endif
/* attach children */
sc->cbdev = device_add_child(brdev, "cardbus", -1);
@ -467,8 +476,8 @@ cbb_chipinit(struct cbb_softc *sc)
/* Restore bus configuration */
pci_write_config(sc->dev, PCIR_PRIBUS_2, sc->pribus, 1);
pci_write_config(sc->dev, PCIR_SECBUS_2, sc->secbus, 1);
pci_write_config(sc->dev, PCIR_SUBBUS_2, sc->subbus, 1);
pci_write_config(sc->dev, PCIR_SECBUS_2, sc->bus.sec, 1);
pci_write_config(sc->dev, PCIR_SUBBUS_2, sc->bus.sub, 1);
/* Enable memory access */
pci_enable_busmaster(sc->dev);
@ -783,6 +792,58 @@ cbb_pci_filt(void *arg)
return retval;
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
static struct resource *
cbb_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct cbb_softc *sc;
sc = device_get_softc(bus);
if (type == PCI_RES_BUS)
return (pcib_alloc_subbus(&sc->bus, child, rid, start, end,
count, flags));
return (cbb_alloc_resource(bus, child, type, rid, start, end, count,
flags));
}
static int
cbb_pci_adjust_resource(device_t bus, device_t child, int type,
struct resource *r, u_long start, u_long end)
{
struct cbb_softc *sc;
sc = device_get_softc(bus);
if (type == PCI_RES_BUS) {
if (!rman_is_region_manager(r, &sc->bus.rman))
return (EINVAL);
return (rman_adjust_resource(r, start, end));
}
return (bus_generic_adjust_resource(bus, child, type, r, start, end));
}
static int
cbb_pci_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
struct cbb_softc *sc;
int error;
sc = device_get_softc(bus);
if (type == PCI_RES_BUS) {
if (!rman_is_region_manager(r, &sc->bus.rman))
return (EINVAL);
if (rman_get_flags(r) & RF_ACTIVE) {
error = bus_deactivate_resource(child, type, rid, r);
if (error)
return (error);
}
return (rman_release_resource(r));
}
return (cbb_release_resource(bus, child, type, rid, r));
}
#endif
/************************************************************************/
/* PCI compat methods */
/************************************************************************/
@ -826,8 +887,14 @@ static device_method_t cbb_methods[] = {
/* bus methods */
DEVMETHOD(bus_read_ivar, cbb_read_ivar),
DEVMETHOD(bus_write_ivar, cbb_write_ivar),
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
DEVMETHOD(bus_alloc_resource, cbb_pci_alloc_resource),
DEVMETHOD(bus_adjust_resource, cbb_pci_adjust_resource),
DEVMETHOD(bus_release_resource, cbb_pci_release_resource),
#else
DEVMETHOD(bus_alloc_resource, cbb_alloc_resource),
DEVMETHOD(bus_release_resource, cbb_release_resource),
#endif
DEVMETHOD(bus_activate_resource, cbb_activate_resource),
DEVMETHOD(bus_deactivate_resource, cbb_deactivate_resource),
DEVMETHOD(bus_driver_added, cbb_driver_added),

View File

@ -64,8 +64,7 @@ struct cbb_softc {
bus_space_handle_t bsh;
uint32_t domain;
unsigned int pribus;
unsigned int secbus;
unsigned int subbus;
struct pcib_secbus bus;
struct mtx mtx;
int cardok;
u_int32_t flags;

View File

@ -92,6 +92,9 @@ static int pci_add_map(device_t bus, device_t dev, int reg,
struct resource_list *rl, int force, int prefetch);
static int pci_probe(device_t dev);
static int pci_attach(device_t dev);
#ifdef PCI_RES_BUS
static int pci_detach(device_t dev);
#endif
static void pci_load_vendor_data(void);
static int pci_describe_parse_line(char **ptr, int *vendor,
int *device, char **desc);
@ -125,7 +128,11 @@ static device_method_t pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pci_probe),
DEVMETHOD(device_attach, pci_attach),
#ifdef PCI_RES_BUS
DEVMETHOD(device_detach, pci_detach),
#else
DEVMETHOD(device_detach, bus_generic_detach),
#endif
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, pci_suspend),
DEVMETHOD(device_resume, pci_resume),
@ -337,6 +344,13 @@ TUNABLE_INT("hw.pci.clear_bars", &pci_clear_bars);
SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0,
"Ignore firmware-assigned resources for BARs.");
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
static int pci_clear_buses;
TUNABLE_INT("hw.pci.clear_buses", &pci_clear_buses);
SYSCTL_INT(_hw_pci, OID_AUTO, clear_buses, CTLFLAG_RDTUN, &pci_clear_buses, 0,
"Ignore firmware-assigned bus numbers.");
#endif
static int
pci_has_quirk(uint32_t devid, int quirk)
{
@ -3197,6 +3211,164 @@ xhci_early_takeover(device_t self)
bus_release_resource(self, SYS_RES_MEMORY, rid, res);
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
static void
pci_reserve_secbus(device_t bus, device_t dev, pcicfgregs *cfg,
struct resource_list *rl)
{
struct resource *res;
char *cp;
u_long start, end, count;
int rid, sec_bus, sec_reg, sub_bus, sub_reg, sup_bus;
switch (cfg->hdrtype & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_BRIDGE:
sec_reg = PCIR_SECBUS_1;
sub_reg = PCIR_SUBBUS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
sec_reg = PCIR_SECBUS_2;
sub_reg = PCIR_SUBBUS_2;
break;
default:
return;
}
/*
* If the existing bus range is valid, attempt to reserve it
* from our parent. If this fails for any reason, clear the
* secbus and subbus registers.
*
* XXX: Should we reset sub_bus to sec_bus if it is < sec_bus?
* This would at least preserve the existing sec_bus if it is
* valid.
*/
sec_bus = PCI_READ_CONFIG(bus, dev, sec_reg, 1);
sub_bus = PCI_READ_CONFIG(bus, dev, sub_reg, 1);
/* Quirk handling. */
switch (pci_get_devid(dev)) {
case 0x12258086: /* Intel 82454KX/GX (Orion) */
sup_bus = pci_read_config(dev, 0x41, 1);
if (sup_bus != 0xff) {
sec_bus = sup_bus + 1;
sub_bus = sup_bus + 1;
PCI_WRITE_CONFIG(bus, dev, sec_reg, sec_bus, 1);
PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1);
}
break;
case 0x00dd10de:
/* Compaq R3000 BIOS sets wrong subordinate bus number. */
if ((cp = getenv("smbios.planar.maker")) == NULL)
break;
if (strncmp(cp, "Compal", 6) != 0) {
freeenv(cp);
break;
}
freeenv(cp);
if ((cp = getenv("smbios.planar.product")) == NULL)
break;
if (strncmp(cp, "08A0", 4) != 0) {
freeenv(cp);
break;
}
freeenv(cp);
if (sub_bus < 0xa) {
sub_bus = 0xa;
PCI_WRITE_CONFIG(bus, dev, sub_reg, sub_bus, 1);
}
break;
}
if (bootverbose)
printf("\tsecbus=%d, subbus=%d\n", sec_bus, sub_bus);
if (sec_bus > 0 && sub_bus >= sec_bus) {
start = sec_bus;
end = sub_bus;
count = end - start + 1;
resource_list_add(rl, PCI_RES_BUS, 0, 0ul, ~0ul, count);
/*
* If requested, clear secondary bus registers in
* bridge devices to force a complete renumbering
* rather than reserving the existing range. However,
* preserve the existing size.
*/
if (pci_clear_buses)
goto clear;
rid = 0;
res = resource_list_reserve(rl, bus, dev, PCI_RES_BUS, &rid,
start, end, count, 0);
if (res != NULL)
return;
if (bootverbose)
device_printf(bus,
"pci%d:%d:%d:%d secbus failed to allocate\n",
pci_get_domain(dev), pci_get_bus(dev),
pci_get_slot(dev), pci_get_function(dev));
}
clear:
PCI_WRITE_CONFIG(bus, dev, sec_reg, 0, 1);
PCI_WRITE_CONFIG(bus, dev, sub_reg, 0, 1);
}
static struct resource *
pci_alloc_secbus(device_t dev, device_t child, int *rid, u_long start,
u_long end, u_long count, u_int flags)
{
struct pci_devinfo *dinfo;
pcicfgregs *cfg;
struct resource_list *rl;
struct resource *res;
int sec_reg, sub_reg;
dinfo = device_get_ivars(child);
cfg = &dinfo->cfg;
rl = &dinfo->resources;
switch (cfg->hdrtype & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_BRIDGE:
sec_reg = PCIR_SECBUS_1;
sub_reg = PCIR_SUBBUS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
sec_reg = PCIR_SECBUS_2;
sub_reg = PCIR_SUBBUS_2;
break;
default:
return (NULL);
}
if (*rid != 0)
return (NULL);
if (resource_list_find(rl, PCI_RES_BUS, *rid) == NULL)
resource_list_add(rl, PCI_RES_BUS, *rid, start, end, count);
if (!resource_list_reserved(rl, PCI_RES_BUS, *rid)) {
res = resource_list_reserve(rl, dev, child, PCI_RES_BUS, rid,
start, end, count, flags & ~RF_ACTIVE);
if (res == NULL) {
resource_list_delete(rl, PCI_RES_BUS, *rid);
device_printf(child, "allocating %lu bus%s failed\n",
count, count == 1 ? "" : "es");
return (NULL);
}
if (bootverbose)
device_printf(child,
"Lazy allocation of %lu bus%s at %lu\n", count,
count == 1 ? "" : "es", rman_get_start(res));
PCI_WRITE_CONFIG(dev, child, sec_reg, rman_get_start(res), 1);
PCI_WRITE_CONFIG(dev, child, sub_reg, rman_get_end(res), 1);
}
return (resource_list_alloc(rl, dev, child, PCI_RES_BUS, rid, start,
end, count, flags));
}
#endif
void
pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
{
@ -3269,6 +3441,14 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI)
uhci_early_takeover(dev);
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
/*
* Reserve resources for secondary bus ranges behind bridge
* devices.
*/
pci_reserve_secbus(bus, dev, cfg, rl);
#endif
}
void
@ -3334,10 +3514,22 @@ pci_attach_common(device_t dev)
#ifdef PCI_DMA_BOUNDARY
int error, tag_valid;
#endif
#ifdef PCI_RES_BUS
int rid;
#endif
sc = device_get_softc(dev);
domain = pcib_get_domain(dev);
busno = pcib_get_bus(dev);
#ifdef PCI_RES_BUS
rid = 0;
sc->sc_bus = bus_alloc_resource(dev, PCI_RES_BUS, &rid, busno, busno,
1, 0);
if (sc->sc_bus == NULL) {
device_printf(dev, "failed to allocate bus number\n");
return (ENXIO);
}
#endif
if (bootverbose)
device_printf(dev, "domain=%d, physical bus=%d\n",
domain, busno);
@ -3382,6 +3574,21 @@ pci_attach(device_t dev)
return (bus_generic_attach(dev));
}
#ifdef PCI_RES_BUS
static int
pci_detach(device_t dev)
{
struct pci_softc *sc;
int error;
error = bus_generic_detach(dev);
if (error)
return (error);
sc = device_get_softc(dev);
return (bus_release_resource(dev, PCI_RES_BUS, 0, sc->sc_bus));
}
#endif
static void
pci_set_power_children(device_t dev, device_t *devlist, int numdevs,
int state)
@ -3879,6 +4086,10 @@ pci_child_detached(device_t dev, device_t child)
pci_printf(&dinfo->cfg, "Device leaked memory resources\n");
if (resource_list_release_active(rl, dev, child, SYS_RES_IOPORT) != 0)
pci_printf(&dinfo->cfg, "Device leaked I/O resources\n");
#ifdef PCI_RES_BUS
if (resource_list_release_active(rl, dev, child, PCI_RES_BUS) != 0)
pci_printf(&dinfo->cfg, "Device leaked PCI bus numbers\n");
#endif
pci_cfg_save(child, dinfo, 1);
}
@ -4295,6 +4506,11 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
rl = &dinfo->resources;
cfg = &dinfo->cfg;
switch (type) {
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
case PCI_RES_BUS:
return (pci_alloc_secbus(dev, child, rid, start, end, count,
flags));
#endif
case SYS_RES_IRQ:
/*
* Can't alloc legacy interrupt once MSI messages have

View File

@ -119,6 +119,10 @@ pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r)
{
switch (type) {
#ifdef PCI_RES_BUS
case PCI_RES_BUS:
return (rman_is_region_manager(r, &sc->bus.rman));
#endif
case SYS_RES_IOPORT:
return (rman_is_region_manager(r, &sc->io.rman));
case SYS_RES_MEMORY:
@ -523,6 +527,173 @@ pcib_probe_windows(struct pcib_softc *sc)
}
}
#ifdef PCI_RES_BUS
/*
* Allocate a suitable secondary bus for this bridge if needed and
* initialize the resource manager for the secondary bus range. Note
* that the minimum count is a desired value and this may allocate a
* smaller range.
*/
void
pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count)
{
char buf[64];
int error, rid;
switch (pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_BRIDGE:
bus->sub_reg = PCIR_SUBBUS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
bus->sub_reg = PCIR_SUBBUS_2;
break;
default:
panic("not a PCI bridge");
}
bus->dev = dev;
bus->rman.rm_start = 0;
bus->rman.rm_end = PCI_BUSMAX;
bus->rman.rm_type = RMAN_ARRAY;
snprintf(buf, sizeof(buf), "%s bus numbers", device_get_nameunit(dev));
bus->rman.rm_descr = strdup(buf, M_DEVBUF);
error = rman_init(&bus->rman);
if (error)
panic("Failed to initialize %s bus number rman",
device_get_nameunit(dev));
/*
* Allocate a bus range. This will return an existing bus range
* if one exists, or a new bus range if one does not.
*/
rid = 0;
bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, 0ul, ~0ul,
min_count, 0);
if (bus->res == NULL) {
/*
* Fall back to just allocating a range of a single bus
* number.
*/
bus->res = bus_alloc_resource(dev, PCI_RES_BUS, &rid, 0ul, ~0ul,
1, 0);
} else if (rman_get_size(bus->res) < min_count)
/*
* Attempt to grow the existing range to satisfy the
* minimum desired count.
*/
(void)bus_adjust_resource(dev, PCI_RES_BUS, bus->res,
rman_get_start(bus->res), rman_get_start(bus->res) +
min_count - 1);
/*
* Add the initial resource to the rman.
*/
if (bus->res != NULL) {
error = rman_manage_region(&bus->rman, rman_get_start(bus->res),
rman_get_end(bus->res));
if (error)
panic("Failed to add resource to rman");
bus->sec = rman_get_start(bus->res);
bus->sub = rman_get_end(bus->res);
}
}
static struct resource *
pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct resource *res;
res = rman_reserve_resource(&bus->rman, start, end, count, flags,
child);
if (res == NULL)
return (NULL);
if (bootverbose)
device_printf(bus->dev,
"allocated bus range (%lu-%lu) for rid %d of %s\n",
rman_get_start(res), rman_get_end(res), *rid,
pcib_child_name(child));
rman_set_rid(res, *rid);
return (res);
}
/*
* Attempt to grow the secondary bus range. This is much simpler than
* for I/O windows as the range can only be grown by increasing
* subbus.
*/
static int
pcib_grow_subbus(struct pcib_secbus *bus, u_long new_end)
{
u_long old_end;
int error;
old_end = rman_get_end(bus->res);
KASSERT(new_end > old_end, ("attempt to shrink subbus"));
error = bus_adjust_resource(bus->dev, PCI_RES_BUS, bus->res,
rman_get_start(bus->res), new_end);
if (error)
return (error);
if (bootverbose)
device_printf(bus->dev, "grew bus range to %lu-%lu\n",
rman_get_start(bus->res), rman_get_end(bus->res));
error = rman_manage_region(&bus->rman, old_end + 1,
rman_get_end(bus->res));
if (error)
panic("Failed to add resource to rman");
bus->sub = rman_get_end(bus->res);
pci_write_config(bus->dev, bus->sub_reg, bus->sub, 1);
return (0);
}
struct resource *
pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct resource *res;
u_long start_free, end_free, new_end;
/*
* First, see if the request can be satisified by the existing
* bus range.
*/
res = pcib_suballoc_bus(bus, child, rid, start, end, count, flags);
if (res != NULL)
return (res);
/*
* Figure out a range to grow the bus range. First, find the
* first bus number after the last allocated bus in the rman and
* enforce that as a minimum starting point for the range.
*/
if (rman_last_free_region(&bus->rman, &start_free, &end_free) != 0 ||
end_free != bus->sub)
start_free = bus->sub + 1;
if (start_free < start)
start_free = start;
new_end = start_free + count - 1;
/*
* See if this new range would satisfy the request if it
* succeeds.
*/
if (new_end > end)
return (NULL);
/* Finally, attempt to grow the existing resource. */
if (bootverbose) {
device_printf(bus->dev,
"attempting to grow bus range for %lu buses\n", count);
printf("\tback candidate range: %lu-%lu\n", start_free,
new_end);
}
if (pcib_grow_subbus(bus, new_end) == 0)
return (pcib_suballoc_bus(bus, child, rid, start, end, count,
flags));
return (NULL);
}
#endif
#else
/*
@ -669,8 +840,8 @@ pcib_cfg_save(struct pcib_softc *sc)
sc->command = pci_read_config(dev, PCIR_COMMAND, 2);
sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1);
sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1);
sc->subbus = pci_read_config(dev, PCIR_SUBBUS_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->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1);
#ifndef NEW_PCIB
@ -693,8 +864,8 @@ pcib_cfg_restore(struct pcib_softc *sc)
pci_write_config(dev, PCIR_COMMAND, sc->command, 2);
pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1);
pci_write_config(dev, PCIR_SECBUS_1, sc->secbus, 1);
pci_write_config(dev, PCIR_SUBBUS_1, sc->subbus, 1);
pci_write_config(dev, PCIR_SECBUS_1, sc->bus.sec, 1);
pci_write_config(dev, PCIR_SUBBUS_1, sc->bus.sub, 1);
pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2);
pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1);
#ifdef NEW_PCIB
@ -739,6 +910,13 @@ pcib_attach_common(device_t dev)
sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2);
pcib_cfg_save(sc);
/*
* The primary bus register should always be the bus of the
* parent.
*/
sc->pribus = pci_get_bus(dev);
pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1);
/*
* Setup sysctl reporting nodes
*/
@ -749,25 +927,27 @@ pcib_attach_common(device_t dev)
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus",
CTLFLAG_RD, &sc->pribus, 0, "Primary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus",
CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number");
CTLFLAG_RD, &sc->bus.sec, 0, "Secondary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number");
CTLFLAG_RD, &sc->bus.sub, 0, "Subordinate bus number");
/*
* Quirk handling.
*/
switch (pci_get_devid(dev)) {
#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS)
case 0x12258086: /* Intel 82454KX/GX (Orion) */
{
uint8_t supbus;
supbus = pci_read_config(dev, 0x41, 1);
if (supbus != 0xff) {
sc->secbus = supbus + 1;
sc->subbus = supbus + 1;
sc->bus.sec = supbus + 1;
sc->bus.sub = supbus + 1;
}
break;
}
#endif
/*
* The i82380FB mobile docking controller is a PCI-PCI bridge,
@ -781,6 +961,7 @@ pcib_attach_common(device_t dev)
sc->flags |= PCIB_SUBTRACTIVE;
break;
#if !defined(NEW_PCIB) && !defined(PCI_RES_BUS)
/* Compaq R3000 BIOS sets wrong subordinate bus number. */
case 0x00dd10de:
{
@ -800,12 +981,13 @@ pcib_attach_common(device_t dev)
break;
}
freeenv(cp);
if (sc->subbus < 0xa) {
if (sc->bus.sub < 0xa) {
pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1);
sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1);
sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1);
}
break;
}
#endif
}
if (pci_msi_device_blacklisted(dev))
@ -827,12 +1009,15 @@ pcib_attach_common(device_t dev)
sc->flags |= PCIB_SUBTRACTIVE;
#ifdef NEW_PCIB
#ifdef PCI_RES_BUS
pcib_setup_secbus(dev, &sc->bus, 1);
#endif
pcib_probe_windows(sc);
#endif
if (bootverbose) {
device_printf(dev, " domain %d\n", sc->domain);
device_printf(dev, " secondary bus %d\n", sc->secbus);
device_printf(dev, " subordinate bus %d\n", sc->subbus);
device_printf(dev, " secondary bus %d\n", sc->bus.sec);
device_printf(dev, " subordinate bus %d\n", sc->bus.sub);
#ifdef NEW_PCIB
if (pcib_is_window_open(&sc->io))
device_printf(dev, " I/O decode 0x%jx-0x%jx\n",
@ -872,20 +1057,6 @@ pcib_attach_common(device_t dev)
}
}
/*
* XXX If the secondary bus number is zero, we should assign a bus number
* since the BIOS hasn't, then initialise the bridge. A simple
* bus_alloc_resource with the a couple of busses seems like the right
* approach, but we don't know what busses the BIOS might have already
* assigned to other bridges on this bus that probe later than we do.
*
* If the subordinate bus number is less than the secondary bus number,
* we should pick a better value. One sensible alternative would be to
* pick 255; the only tradeoff here is that configuration transactions
* would be more widely routed than absolutely necessary. We could
* then do a walk of the tree later and fix it.
*/
/*
* Always enable busmastering on bridges so that transactions
* initiated on the secondary bus are passed through to the
@ -902,8 +1073,8 @@ pcib_attach(device_t dev)
pcib_attach_common(dev);
sc = device_get_softc(dev);
if (sc->secbus != 0) {
child = device_add_child(dev, "pci", sc->secbus);
if (sc->bus.sec != 0) {
child = device_add_child(dev, "pci", sc->bus.sec);
if (child != NULL)
return(bus_generic_attach(dev));
}
@ -953,7 +1124,7 @@ pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
*result = sc->domain;
return(0);
case PCIB_IVAR_BUS:
*result = sc->secbus;
*result = sc->bus.sec;
return(0);
}
return(ENOENT);
@ -962,14 +1133,12 @@ pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
int
pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
{
struct pcib_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_DOMAIN:
return(EINVAL);
case PCIB_IVAR_BUS:
sc->secbus = value;
return(0);
return(EINVAL);
}
return(ENOENT);
}
@ -1379,6 +1548,11 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
switch (type) {
#ifdef PCI_RES_BUS
case PCI_RES_BUS:
return (pcib_alloc_subbus(&sc->bus, child, rid, start, end,
count, flags));
#endif
case SYS_RES_IOPORT:
if (pcib_is_isa_range(sc, start, end, count))
return (NULL);

View File

@ -40,6 +40,9 @@ DECLARE_CLASS(pci_driver);
struct pci_softc {
bus_dma_tag_t sc_dma_tag;
#ifdef PCI_RES_BUS
struct resource *sc_bus;
#endif
};
extern int pci_do_power_resume;

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/systm.h>
@ -282,4 +283,102 @@ pcib_host_res_adjust(struct pcib_host_resources *hr, device_t dev, int type,
}
return (ERANGE);
}
#ifdef PCI_RES_BUS
struct pci_domain {
int pd_domain;
struct rman pd_bus_rman;
TAILQ_ENTRY(pci_domain) pd_link;
};
static TAILQ_HEAD(, pci_domain) domains = TAILQ_HEAD_INITIALIZER(domains);
/*
* Each PCI domain maintains its own resource manager for PCI bus
* numbers in that domain. Domain objects are created on first use.
* Host to PCI bridge drivers and PCI-PCI bridge drivers should
* allocate their bus ranges from their domain.
*/
static struct pci_domain *
pci_find_domain(int domain)
{
struct pci_domain *d;
char buf[64];
int error;
TAILQ_FOREACH(d, &domains, pd_link) {
if (d->pd_domain == domain)
return (d);
}
snprintf(buf, sizeof(buf), "PCI domain %d bus numbers", domain);
d = malloc(sizeof(*d) + strlen(buf) + 1, M_DEVBUF, M_WAITOK | M_ZERO);
d->pd_domain = domain;
d->pd_bus_rman.rm_start = 0;
d->pd_bus_rman.rm_end = PCI_BUSMAX;
d->pd_bus_rman.rm_type = RMAN_ARRAY;
strcpy((char *)(d + 1), buf);
d->pd_bus_rman.rm_descr = (char *)(d + 1);
error = rman_init(&d->pd_bus_rman);
if (error == 0)
error = rman_manage_region(&d->pd_bus_rman, 0, PCI_BUSMAX);
if (error)
panic("Failed to initialize PCI domain %d rman", domain);
TAILQ_INSERT_TAIL(&domains, d, pd_link);
return (d);
}
struct resource *
pci_domain_alloc_bus(int domain, device_t dev, int *rid, u_long start,
u_long end, u_long count, u_int flags)
{
struct pci_domain *d;
struct resource *res;
if (domain < 0 || domain > PCI_DOMAINMAX)
return (NULL);
d = pci_find_domain(domain);
res = rman_reserve_resource(&d->pd_bus_rman, start, end, count, flags,
dev);
if (res == NULL)
return (NULL);
rman_set_rid(res, *rid);
return (res);
}
int
pci_domain_adjust_bus(int domain, device_t dev, struct resource *r,
u_long start, u_long end)
{
#ifdef INVARIANTS
struct pci_domain *d;
#endif
if (domain < 0 || domain > PCI_DOMAINMAX)
return (EINVAL);
#ifdef INVARIANTS
d = pci_find_domain(domain);
KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
#endif
return (rman_adjust_resource(r, start, end));
}
int
pci_domain_release_bus(int domain, device_t dev, int rid, struct resource *r)
{
#ifdef INVARIANTS
struct pci_domain *d;
#endif
if (domain < 0 || domain > PCI_DOMAINMAX)
return (EINVAL);
#ifdef INVARIANTS
d = pci_find_domain(domain);
KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
#endif
return (rman_release_resource(r));
}
#endif /* PCI_RES_BUS */
#endif /* NEW_PCIB */

View File

@ -83,6 +83,18 @@ struct pcib_window {
};
#endif
struct pcib_secbus {
u_int sec;
u_int sub;
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
device_t dev;
struct rman rman;
struct resource *res;
const char *name;
int sub_reg;
#endif
};
/*
* Bridge-specific data.
*/
@ -96,8 +108,7 @@ struct pcib_softc
uint16_t command; /* command register */
u_int domain; /* domain number */
u_int pribus; /* primary bus number */
u_int secbus; /* secondary bus number */
u_int subbus; /* subordinate bus number */
struct pcib_secbus bus; /* secondary bus numbers */
#ifdef NEW_PCIB
struct pcib_window io; /* I/O port window */
struct pcib_window mem; /* memory window */
@ -117,13 +128,26 @@ struct pcib_softc
typedef uint32_t pci_read_config_fn(int b, int s, int f, int reg, int width);
int host_pcib_get_busno(pci_read_config_fn read_config, int bus,
int slot, int func, uint8_t *busnum);
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
struct resource *pci_domain_alloc_bus(int domain, device_t dev, int *rid,
u_long start, u_long end, u_long count, u_int flags);
int pci_domain_adjust_bus(int domain, device_t dev,
struct resource *r, u_long start, u_long end);
int pci_domain_release_bus(int domain, device_t dev, int rid,
struct resource *r);
struct resource *pcib_alloc_subbus(struct pcib_secbus *bus, device_t child,
int *rid, u_long start, u_long end, u_long count,
u_int flags);
void pcib_setup_secbus(device_t dev, struct pcib_secbus *bus,
int min_count);
#endif
int pcib_attach(device_t dev);
void pcib_attach_common(device_t dev);
#ifdef NEW_PCIB
const char *pcib_child_name(device_t child);
#endif
int host_pcib_get_busno(pci_read_config_fn read_config, int bus,
int slot, int func, uint8_t *busnum);
int pcib_attach(device_t dev);
void pcib_attach_common(device_t dev);
int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,

View File

@ -40,5 +40,8 @@
#define SYS_RES_DRQ 2 /* isa dma lines */
#define SYS_RES_MEMORY 3 /* i/o memory */
#define SYS_RES_IOPORT 4 /* i/o ports */
#ifdef NEW_PCIB
#define PCI_RES_BUS 5 /* PCI bus numbers */
#endif
#endif /* !_MACHINE_RESOURCE_H_ */

View File

@ -177,9 +177,9 @@ apb_attach(device_t dev)
pci_read_config(dev, PCIR_COMMAND, 2);
sc->sc_bsc.ops_pcib_sc.pribus =
pci_read_config(dev, PCIR_PRIBUS_1, 1);
sc->sc_bsc.ops_pcib_sc.secbus =
sc->sc_bsc.ops_pcib_sc.bus.sec =
pci_read_config(dev, PCIR_SECBUS_1, 1);
sc->sc_bsc.ops_pcib_sc.subbus =
sc->sc_bsc.ops_pcib_sc.bus.sub =
pci_read_config(dev, PCIR_SUBBUS_1, 1);
sc->sc_bsc.ops_pcib_sc.bridgectl =
pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
@ -200,10 +200,10 @@ apb_attach(device_t dev)
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.pribus, 0,
"Primary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus",
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.secbus, 0,
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sec, 0,
"Secondary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.subbus, 0,
CTLFLAG_RD, &sc->sc_bsc.ops_pcib_sc.bus.sub, 0,
"Subordinate bus number");
ofw_pcib_gen_setup(dev);
@ -212,9 +212,9 @@ apb_attach(device_t dev)
device_printf(dev, " domain %d\n",
sc->sc_bsc.ops_pcib_sc.domain);
device_printf(dev, " secondary bus %d\n",
sc->sc_bsc.ops_pcib_sc.secbus);
sc->sc_bsc.ops_pcib_sc.bus.sec);
device_printf(dev, " subordinate bus %d\n",
sc->sc_bsc.ops_pcib_sc.subbus);
sc->sc_bsc.ops_pcib_sc.bus.sub);
device_printf(dev, " I/O decode ");
apb_map_print(sc->sc_iomap, APB_IO_SCALE);
printf("\n");

View File

@ -57,6 +57,10 @@ int legacy_pcib_write_ivar(device_t dev, device_t child, int which,
uintptr_t value);
struct resource *legacy_pcib_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
int legacy_pcib_adjust_resource(device_t dev, device_t child, int type,
struct resource *r, u_long start, u_long end);
int legacy_pcib_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r);
int legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count,
int maxcount, int *irqs);
int legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq);

View File

@ -597,11 +597,38 @@ legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
start = hostb_alloc_start(type, start, end, count);
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
count, flags));
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
if (type == PCI_RES_BUS)
return (pci_domain_alloc_bus(0, child, rid, start, end, count,
flags));
#endif
start = hostb_alloc_start(type, start, end, count);
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
count, flags));
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
int
legacy_pcib_adjust_resource(device_t dev, device_t child, int type,
struct resource *r, u_long start, u_long end)
{
if (type == PCI_RES_BUS)
return (pci_domain_adjust_bus(0, child, r, start, end));
return (bus_generic_adjust_resource(dev, child, type, r, start, end));
}
int
legacy_pcib_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
if (type == PCI_RES_BUS)
return (pci_domain_release_bus(0, child, rid, r));
return (bus_generic_release_resource(dev, child, type, rid, r));
}
#endif
static device_method_t legacy_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, legacy_pcib_identify),
@ -615,8 +642,13 @@ static device_method_t legacy_pcib_methods[] = {
DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
DEVMETHOD(bus_adjust_resource, legacy_pcib_adjust_resource),
DEVMETHOD(bus_release_resource, legacy_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_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),

View File

@ -238,6 +238,20 @@ qpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
}
}
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
static struct resource *
qpi_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
if (type == PCI_RES_BUS)
return (pci_domain_alloc_bus(0, child, rid, start, end, count,
flags));
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
count, flags));
}
#endif
static int
qpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
@ -258,8 +272,14 @@ static device_method_t qpi_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_read_ivar, qpi_pcib_read_ivar),
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
DEVMETHOD(bus_alloc_resource, qpi_pcib_alloc_resource),
DEVMETHOD(bus_adjust_resource, legacy_pcib_adjust_resource),
DEVMETHOD(bus_release_resource, legacy_pcib_release_resource),
#else
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
#endif
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),

View File

@ -105,6 +105,11 @@ mptable_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid,
{
struct mptable_hostb_softc *sc;
#ifdef PCI_RES_BUS
if (type == PCI_RES_BUS)
return (pci_domain_alloc_bus(0, child, rid, start, end, count,
flags));
#endif
sc = device_get_softc(dev);
if (type == SYS_RES_IOPORT && start + count - 1 == end) {
if (mptable_is_isa_range(start, end)) {
@ -141,6 +146,10 @@ mptable_hostb_adjust_resource(device_t dev, device_t child, int type,
{
struct mptable_hostb_softc *sc;
#ifdef PCI_RES_BUS
if (type == PCI_RES_BUS)
return (pci_domain_adjust_bus(0, child, r, start, end));
#endif
sc = device_get_softc(dev);
return (pcib_host_res_adjust(&sc->sc_host_res, child, type, r, start,
end));
@ -165,7 +174,11 @@ static device_method_t mptable_hostb_methods[] = {
DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource),
DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
#endif
#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
DEVMETHOD(bus_release_resource, legacy_pcib_release_resource),
#else
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
#endif
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),