Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Apr 2011 02:30:37 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 191000 for review
Message-ID:  <201104040230.p342UbFb029283@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@191000?ac=10

Change 191000 by jhb@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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104040230.p342UbFb029283>