PERFORCE change 191000 for review
John Baldwin
jhb at FreeBSD.org
Mon Apr 4 02:30:38 UTC 2011
http://p4web.freebsd.org/@@191000?ac=10
Change 191000 by jhb at jhb_fiver on 2011/04/04 02:30:31
Checkpoint more PCI-PCI bridge resource stuff.
Affected files ...
.. //depot/projects/pci/sys/dev/pci/pci.c#11 edit
.. //depot/projects/pci/sys/dev/pci/pci_pci.c#4 edit
.. //depot/projects/pci/sys/dev/pci/pcib_private.h#4 edit
Differences ...
==== //depot/projects/pci/sys/dev/pci/pci.c#11 (text+ko) ====
@@ -3945,6 +3945,25 @@
break;
case SYS_RES_IOPORT:
case SYS_RES_MEMORY:
+#ifdef NEW_PCIB
+ /*
+ * PCI-PCI bridge I/O window resources are not BARs.
+ * For those allocations just pass the request up the
+ * tree.
+ */
+ if (cfg->hdrtype == PCIM_HDRTYPE_BRIDGE) {
+ switch (*rid) {
+ case PCIR_IOBASEL_1:
+ case PCIR_MEMBASE_1:
+ case PCIR_PMBASEL_1:
+ break;
+ default:
+ goto bar;
+ }
+ break;
+ }
+ bar:
+#endif
/* Reserve resources for this BAR if needed. */
rle = resource_list_find(rl, type, *rid);
if (rle == NULL) {
==== //depot/projects/pci/sys/dev/pci/pci_pci.c#4 (text+ko) ====
@@ -53,6 +53,12 @@
#include "pcib_if.h"
+#ifdef NEW_PCIB
+#define WIN_IO 0x1
+#define WIN_MEM 0x2
+#define WIN_PMEM 0x4
+#endif
+
static int pcib_probe(device_t dev);
static int pcib_suspend(device_t dev);
static int pcib_resume(device_t dev);
@@ -109,9 +115,12 @@
pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r)
{
- /* Subtractive bridges do manage resources. */
+ /* XXX: Can subtractive bridges still use windows? */
+#if 0
+ /* Subtractive bridges don't manage resources. */
if (sc->flags & PCIB_SUBTRACTIVE)
return (0);
+#endif
switch (type) {
case SYS_RES_IOPORT:
@@ -125,7 +134,173 @@
}
return (0);
}
-#endif
+
+static int
+pcib_is_window_open(struct pcib_window *pw)
+{
+
+ return (pw->base > 0 && pw->base < pw->limit);
+}
+
+static void
+pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type, int reg,
+ int flags, const char *name, pci_addr_t max_address)
+{
+ int error, rid;
+
+ if (max_address != (u_long)max_address)
+ max_address = ~0ul;
+ w->rman.rm_start = 0;
+ w->rman.rm_end = max_address;
+ w->rman.rm_type = RMAN_ARRAY;
+ w->rman.rm_descr = malloc(64, M_DEVBUF, M_WAITOK);
+ snprintf(w->rman.rm_descr, 64, "%s %s window", device_get_nameunit(sc->dev), name);
+ error = rman_init(&w->rman);
+ if (error)
+ panic("Failed to initialize %s %s rman", device_get_nameunit(sc->dev),
+ name);
+
+ if (!pcib_is_window_open(w))
+ return;
+
+ if (w->base > max_address || w->limit > max_address) {
+ device_printf(sc->dev, "initial %s window has too many bits, ignoring\n",
+ name);
+ w->base = 0;
+ return;
+ }
+ rid = reg;
+ w->res = bus_alloc_resource(sc->dev, type, &rid, w->base, w->limit, w->limit -
+ w->base + 1, flags);
+ if (w->res == NULL) {
+ device_printf(sc->dev, "failed to allocate initial %s window: %jx - %jx\n",
+ name, (uintmax_t)w->base, (uintmax_t)w->limit);
+ w->base = 0;
+ return;
+ }
+
+ error = rman_manage_region(&w->rman, rman_get_start(w->res), rman_get_end(w->res));
+ if (error)
+ panic("Failed to initialize rman with resource");
+}
+
+/*
+ * Initialize I/O windows.
+ */
+static void
+pcib_probe_windows(struct pcib_softc *sc)
+{
+ pci_addr_t max;
+ device_t dev;
+ uint32_t val;
+ int rid;
+
+ dev = sc->dev;
+
+ /* Determine if the I/O port window is implemented. */
+ val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
+ if (val == 0) {
+ /* If 'val' is zero, then only 16-bits of I/O space are supported. */
+ pci_write_config(dev, PCIR_IOBASEL_1, 0xff, 1);
+ if (pci_read_config(dev, PCIR_IOBASEL_1, 1) != 0) {
+ sc->io.valid = 1;
+ pci_write_config(dev, PCIR_IOBASEL_1, 0, 1);
+ }
+ } else
+ sc->io.valid = 1;
+
+ /* Read the existing I/O port window. */
+ if (sc->io.valid) {
+ if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
+ sc->io.base = PCI_PPBIOBASE(
+ pci_read_config(dev, PCIR_IOBASEH_1, 2), val);
+ sc->io.limit = PCI_PPBIOLIMIT(
+ pci_read_config(dev, PCIR_IOLIMITH_1, 2),
+ pci_read_config(dev, PCIR_IOLIMITL_1, 1));
+ max = 0xffffffff;
+ } else {
+ sc->io.base = PCI_PPBIOBASE(0, val);
+ sc->io.limit = PCI_PPBIOLIMIT(0,
+ pci_read_config(dev, PCIR_IOLIMITL_1, 1));
+ max = 0xffff;
+ }
+ pcib_alloc_window(sc, &sc->io, SYS_RES_IOPORT, PCIR_IOBASEL_1, 0,
+ "I/O port", max);
+ }
+
+ /* Read the existing memory window. */
+ sc->mem.valid = 1;
+ sc->mem.base = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2));
+ sc->mem.limit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2));
+ pcib_alloc_window(sc, &sc->mem, SYS_RES_MEMORY, PCIR_MEMBASE_1, 0, "memory",
+ 0xffffffff);
+
+ /* Determine if the prefetchable memory window is implemented. */
+ val = pci_read_config(dev, PCIR_PMBASEL_1, 2);
+ if (val == 0) {
+ /* If 'val' is zero, then only 32-bits of memory space are supported. */
+ pci_write_config(dev, PCIR_PMBASEL_1, 0xffff, 2);
+ if (pci_read_config(dev, PCIR_PMBASEL_1, 2) != 0) {
+ sc->pmem.valid = 1;
+ pci_write_config(dev, PCIR_PMBASEL_1, 0, 2);
+ }
+ } else
+ sc->pmem.valid = 1;
+
+ /* Read the existing prefetchable memory window. */
+ if (sc->pmem.valid) {
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ sc->pmem.base = PCI_PPBMEMBASE(
+ pci_read_config(dev, PCIR_PMBASEH_1, 4), pmemlow);
+ sc->pmem.limit = PCI_PPBMEMLIMIT(
+ pci_read_config(dev, PCIR_PMLIMITH_1, 4),
+ pci_read_config(dev, PCIR_PMLIMITL_1, 2));
+ max = 0xffffffffffffffff;
+ } else {
+ sc->pmem.base = PCI_PPBMEMBASE(0, pmemlow);
+ sc->pmem.limit = PCI_PPBMEMLIMIT(0,
+ pci_read_config(dev, PCIR_PMLIMITL_1, 2));
+ max = 0xffffffff;
+ }
+ pcib_alloc_window(sc, &sc->pmem, SYS_RES_MEMORY, PCIR_PMBASEL_1,
+ RF_PREFETCHABLE, "prefetchable memory", max);
+ }
+}
+
+static void
+pcib_write_windows(struct pcib_softc *sc, int mask)
+{
+ device_t dev;
+ uint32_t val;
+
+ dev = sc->dev;
+ if (mask & WIN_IO) {
+ val = pci_read_config(dev, PCIR_IOBASEL_1, 1);
+ if ((val & PCIM_BRIO_MASK) == PCIM_BRIO_32) {
+ pci_write_config(dev, PCIR_IOBASEH_1, sc->io.base >> 16, 2);
+ pci_write_config(dev, PCIR_IOLIMITH_1, sc->io.limit >> 16, 2);
+ }
+ pci_write_config(dev, PCIR_IOBASEL_1, sc->io.base >> 8, 1);
+ pci_write_config(dev, PCIR_IOLIMITL_1, sc->io.limit >> 8, 1);
+ }
+
+ if (mask & WIN_MEM) {
+ pci_write_config(dev, PCIR_MEMBASE_1, sc->mem.base >> 16, 2);
+ pci_write_config(dev, PCIR_MEMLIMIT_1, sc->mem.limit >> 16, 2);
+ }
+
+ if (mask & WIN_PMEM) {
+ val = pci_read_config(dev, PCIR_PMBASEL_1, 2);
+ if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) {
+ pci_write_config(dev, PCIR_PMBASEH_1, sc->pmem.base >> 32, 4);
+ pci_write_config(dev, PCIR_PMLIMITH_1, sc->pmem.limit >> 32, 4);
+ }
+ pci_write_config(dev, PCIR_PMBASEL_1, sc->pmem.base >> 16, 2);
+ pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmem.limit >> 16, 2);
+ }
+}
+
+#else
/*
* Is the prefetch window open (eg, can we allocate memory in it?)
@@ -257,6 +432,7 @@
pci_write_config(dev, PCIR_PMLIMITH_1, pmemhi, 4);
pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmemlimit >> 16, 2);
}
+#endif
/*
* Get current bridge configuration.
@@ -274,10 +450,12 @@
sc->subbus = 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
if (sc->command & PCIM_CMD_PORTEN)
pcib_get_io_decode(sc);
if (sc->command & PCIM_CMD_MEMEN)
pcib_get_mem_decode(sc);
+#endif
}
/*
@@ -296,10 +474,14 @@
pci_write_config(dev, PCIR_SUBBUS_1, sc->subbus, 1);
pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2);
pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1);
+#ifdef NEW_PCIB
+ pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM);
+#else
if (sc->command & PCIM_CMD_PORTEN)
pcib_set_io_decode(sc);
if (sc->command & PCIM_CMD_MEMEN)
pcib_set_mem_decode(sc);
+#endif
}
/*
@@ -416,18 +598,34 @@
if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 ||
pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE)
sc->flags |= PCIB_SUBTRACTIVE;
-
+
+#ifdef NEW_PCIB
+ pcib_probe_windows();
+#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, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit);
+#ifdef NEW_PCIB
+ if (pcib_is_window_open(&sc->io)
+ device_printf(dev, " I/O decode 0x%jx-0x%jx\n",
+ (uintmax_t)sc->io.base, (uintmax_t)sc->io.limit);
+ if (pcib_is_window_open(&sc->mem))
+ device_printf(dev, " memory decode 0x%jx-0x%jx\n",
+ (uintmax_t)sc->mem.base, (uintmax_t)sc->mem.limit);
+ if (pcib_is_window_open(&sc->pmem))
+ device_printf(dev, " prefetched decode 0x%jx-0x%jx\n",
+ (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
else
device_printf(dev, " no prefetched decode\n");
if (sc->flags & PCIB_SUBTRACTIVE)
@@ -529,7 +727,48 @@
return(ENOENT);
}
+#ifdef NEW_PCIB
/*
+ * Attempt to allocate a resource from the existing resources assigned to a window.
+ */
+static struct resource *
+pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w, device_t child,
+ int type, int *rid, u_long start, u_long end, u_long count, u_int flags)
+{
+ struct resource *res;
+
+ if (!pcib_is_window_open(w))
+ return (NULL);
+
+ res = rman_reserve_resource(&w->rm, start, end, count, flags & ~RF_ACTIVE,
+ child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_rid(res, *rid);
+
+ /*
+ * If the resource should be active, pass that request up the
+ * tree. This assumes the parent drivers can handle
+ * activating sub-allocated resources.
+ */
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, res) != 0) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ }
+
+ return (res);
+}
+
+/*
+ * Attempt to grow a window to make room for a given resource request.
+ */
+static int
+pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w
+
+/*
* We have to trap resource allocation requests and ensure that the bridge
* is set up to, or capable of handling them.
*/
@@ -537,6 +776,21 @@
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)
{
+ struct pcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ switch (type) {
+
+
+#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,
+ u_long start, u_long end, u_long count, u_int flags)
+{
struct pcib_softc *sc = device_get_softc(dev);
const char *name, *suffix;
int ok;
@@ -684,6 +938,7 @@
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
count, flags));
}
+#endif
int
pcib_adjust_resource(device_t bus, device_t child, int type, struct resource *r,
==== //depot/projects/pci/sys/dev/pci/pcib_private.h#4 (text+ko) ====
@@ -39,6 +39,16 @@
*/
DECLARE_CLASS(pcib_driver);
+#ifdef NEW_PCIB
+struct pcib_window {
+ pci_addr_t base;
+ pci_addr_t limit;
+ struct rman rman;
+ struct resource *res;
+ int valid;
+};
+#endif
+
/*
* Bridge-specific data.
*/
@@ -54,16 +64,18 @@
u_int secbus; /* secondary bus number */
u_int subbus; /* subordinate bus number */
#ifdef NEW_PCIB
- struct rman pmem_rman; /* prefetchable memory window */
- struct rman mem_rman; /* memory window */
- struct rman io_rman; /* I/O port window */
-#endif
+ u_int valid_windows;
+ struct pcib_window pmem; /* prefetchable memory window */
+ struct pcib_window mem; /* memory window */
+ struct pcib_window io; /* I/O port window */
+#else
pci_addr_t pmembase; /* base address of prefetchable memory */
pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
pci_addr_t membase; /* base address of memory window */
pci_addr_t memlimit; /* topmost address of memory window */
uint32_t iobase; /* base address of port window */
uint32_t iolimit; /* topmost address of port window */
+#endif
uint16_t secstat; /* secondary bus status register */
uint16_t bridgectl; /* bridge control register */
uint8_t seclat; /* secondary bus latency timer */
More information about the p4-projects
mailing list