Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Jun 2013 12:15:37 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 229658 for review
Message-ID:  <201306131215.r5DCFbj2011350@skunkworks.freebsd.org>

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

Change 229658 by jhb@jhb_jhbbsd on 2013/06/13 12:15:31

	First cut at ISA enable support.  However, this doesn't properly
	handle nested bridges.  I need to go the whole hog and slice up
	the allocations from the parent to make that work properly.

Affected files ...

.. //depot/projects/pci/sys/dev/pci/pci_pci.c#29 edit

Differences ...

==== //depot/projects/pci/sys/dev/pci/pci_pci.c#29 (text+ko) ====

@@ -196,7 +196,94 @@
 	}
 }
 
+/*
+ * This is used to reject allocations that conflict with an ISA alias
+ * before trying to grow the window.  Note that this check overrides
+ * subtractive decode.
+ */
+static int
+pcib_is_isa_range(struct pcib_softc *sc, u_long start, u_long end, u_long count)
+{
+	u_long next_alias;
+
+	if (!(sc->bridgectl & PCIB_BCR_ISA_ENABLE))
+		return (0);
+
+	/* Only check fixed ranges for overlap. */
+	if (start + count - 1 != end)
+		return (0);
+
+	/* ISA aliases are only in the lower 64KB of I/O space. */
+	if (start >= 65536)
+		return (0);
+
+	/* Check for overlap with 0x000 - 0x0ff as a special case. */
+	if (start < 0x100)
+		goto alias;
+
+	/*
+	 * If the start address is an alias, the range is an alias.
+	 * Otherwise, compute the start of the next alias range and
+	 * check if it is beyond the end of the candidate range.
+	 */
+	if ((start & 0x300) != 0)
+		goto alias;
+	next_start = (start & ~0xfful) | 0x100;
+	if (next_start <= end)
+		goto alias;
+	return (0);
+
+alias:
+	device_printf(sc->dev,
+	    "I/O range %#lx-%#lx overlaps with an ISA alias\n", start,
+	    end);
+	return (1);
+}
+
 static void
+pcib_alloc_isa_ranges(struct pcib_softc *sc, u_long start, u_long end)
+{
+	struct resource *res;
+	u_long next_end;
+
+	if (!(sc->bridgectl & PCIB_BCR_ISA_ENABLE))
+		return (0);
+
+	/* ISA aliases are only in the lower 64KB of I/O space. */
+	if (end > 65535)
+		end = 65535;
+
+	/* XXX */
+	device_printf(sc->dev, "Reserving ISA aliases for %#lx-%#lx\n", start,
+	    end);
+	while (start <= end) {
+		/*
+		 * Find the first address that aliases to 0x0100 and
+		 * reserve the space from that up to the alias with
+		 * 0x03ff.  As a special case, addresses in the range
+		 * 0x000 - 0x0ff should also be reserved since those
+		 * are used for various system I/O devices in ISA
+		 * systems.
+		 */
+		if (start >= 0x100 && (start & 0x300) == 0) {
+			start &= ~0xfful;
+			start |= 0x100;
+		}
+		next_end = MIN(start | 0x3ff, end);
+		//if (bootverbose)
+			device_printf(sc->dev,
+			    "Reserving ISA alias %#lx-%#lx\n", start, next_end);
+		res = rman_reserve_resource(&sc->io.rman, start, next_end,
+		    next_end - start + 1, 0, sc->dev);
+		if (res == NULL)
+			device_printf(sc->dev,
+			    "Failed to reserve ISA alias %#lx-%#lx\n", start,
+			    next_end);
+		start = next_end + 1;
+	}
+}
+
+static void
 pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type,
     int flags, pci_addr_t max_address)
 {
@@ -305,6 +392,8 @@
 			max = 0xffff;
 		}
 		pcib_alloc_window(sc, &sc->io, SYS_RES_IOPORT, 0, max);
+		pcib_alloc_isa_ranges(sc, sc->io.base, sc->io.base +
+		    sc->io.limit - 1);
 	}
 
 	/* Read the existing memory window. */
@@ -562,6 +651,7 @@
     struct pcib_softc	*sc;
     struct sysctl_ctx_list *sctx;
     struct sysctl_oid	*soid;
+    int comma;
 
     sc = device_get_softc(dev);
     sc->dev = dev;
@@ -685,10 +775,22 @@
 	    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)
-	    device_printf(dev, "  Subtractively decoded bridge.\n");
+	if (sc->bridgectl & (PCIB_BCR_ISA_ENABLE | PCIB_BCR_VGA_ENABLE) ||
+	    sc->flags & PCIB_SUBTRACTIVE) {
+		device_printf(dev, "  special decode    ");
+		comma = 0;
+		if (sc->bridgectl & PCIB_BCR_ISA_ENABLE) {
+			printf("ISA");
+			comma = 1;
+		}
+		if (sc->bridgectl & PCIB_BCR_VGA_ENABLE) {
+			printf("%sVGA", comma ? ", " : "");
+			comma = 1;
+		}
+		if (sc->flags & PCIB_SUBTRACTIVE)
+			printf("%ssubtractive", comma ? ", " : "");
+		device_printf("\n");
+	}
     }
 
     /*
@@ -849,9 +951,15 @@
 	/*
 	 * Clamp the desired resource range to the maximum address
 	 * this window supports.  Reject impossible requests.
+	 *
+	 * For I/O port requests behind a bridge with the ISA enable
+	 * bit set, force large allocations to start above 64k.
 	 */
 	if (!w->valid)
 		return (EINVAL);
+	if (sc->bridgectl & PCIB_BCR_ISA_ENABLE && count > 0x100 &&
+	    start < 65536)
+		start = 65536;
 	if (end > w->rman.rm_end)
 		end = w->rman.rm_end;
 	if (start + count - 1 > end || start + count < start)
@@ -1011,11 +1119,17 @@
 		KASSERT(w->limit == rman_get_end(w->res), ("both ends moved"));
 		error = rman_manage_region(&w->rman, rman_get_start(w->res),
 		    w->base - 1);
+		if (type == SYS_RES_IOPORT)
+			pcib_alloc_isa_ranges(sc, rman_get_start(w->res),
+			    w->base - 1);
 	} else {
 		KASSERT(w->limit != rman_get_end(w->res),
 		    ("neither end moved"));
 		error = rman_manage_region(&w->rman, w->limit + 1,
 		    rman_get_end(w->res));
+		if (type == SYS_RES_IOPORT)
+			pcib_alloc_isa_ranges(sc, w->limit + 1,
+			    rman_get_end(w->res));
 	}
 	if (error) {
 		if (bootverbose)
@@ -1066,7 +1180,8 @@
 	case SYS_RES_IOPORT:
 		r = pcib_suballoc_resource(sc, &sc->io, child, type, rid, start,
 		    end, count, flags);
-		if (r != NULL || (sc->flags & PCIB_SUBTRACTIVE) != 0)
+		if (r != NULL || ((sc->flags & PCIB_SUBTRACTIVE) != 0 &&
+		    !pcib_is_isa_range(sc, start, end, count)))
 			break;
 		if (pcib_grow_window(sc, &sc->io, type, start, end, count,
 		    flags) == 0)



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