Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 May 2011 00:44:49 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 192802 for review
Message-ID:  <201105080044.p480in0b036274@skunkworks.freebsd.org>

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

Change 192802 by jhb@jhb_fiver on 2011/05/08 00:44:27

	Finish first cut at using MPTable info to determine which address ranges
	Host-PCI bridges decode.

Affected files ...

.. //depot/projects/pci/sys/x86/include/mptable.h#4 edit
.. //depot/projects/pci/sys/x86/x86/mptable.c#4 edit
.. //depot/projects/pci/sys/x86/x86/mptable_pci.c#7 edit

Differences ...

==== //depot/projects/pci/sys/x86/include/mptable.h#4 (text+ko) ====

@@ -72,14 +72,14 @@
 	u_char  reserved;
 }      *mpcth_t;
 
+/* Base table entries */
+
 #define	MPCT_ENTRY_PROCESSOR	0
 #define	MPCT_ENTRY_BUS		1
 #define	MPCT_ENTRY_IOAPIC	2
 #define	MPCT_ENTRY_INT		3
 #define	MPCT_ENTRY_LOCAL_INT	4
 
-/* Base table entries */
-
 typedef struct PROCENTRY {
 	u_char  type;
 	u_char  apic_id;
@@ -141,6 +141,10 @@
 	u_char	length;
 }      *ext_entry_ptr;
 
+#define	MPCT_EXTENTRY_SAS	0x80
+#define	MPCT_EXTENTRY_BHD	0x81
+#define	MPCT_EXTENTRY_CBASM	0x82
+
 typedef struct SASENTRY {
 	u_char	type;
 	u_char	length;

==== //depot/projects/pci/sys/x86/x86/mptable.c#4 (text+ko) ====

@@ -1083,16 +1083,123 @@
 }
 
 #ifdef NEW_PCIB
+struct host_res_args {
+	struct mptable_hostb_softc *sc;
+	device_t dev;
+	u_char	bus;
+};
+
 /*
  * Initialize a Host-PCI bridge so it can restrict resource allocation
  * requests to the resources it actually decodes according to MP
  * config table extended entries.
  */
+static void
+mptable_host_res_handler(ext_entry_ptr *entry, void *arg)
+{
+	struct host_res_args *args;
+	cbasm_entry_ptr *cbasm;
+	sas_entry_ptr *sas;
+	const char *name;
+	uint64_t start, end;
+	int error, *flagp, flags, type;
+
+	args = arg;
+	switch (entry->type) {
+	case MPCT_EXTENTRY_SAS:
+		sas = (sas_entry_ptr *)entry;
+		if (sas->bus_id != args->bus)
+			break;
+		switch (sas->address_type) {
+		case SASENTRY_TYPE_IO:
+			type = SYS_RES_IOPORT;
+			flags = 0;
+			break;
+		case SASENTRY_TYPE_MEMORY:
+			type = SYS_RES_MEMORY;
+			flags = 0;
+			break;
+		case SASENTRY_TYPE_PREFETCH:
+			type = SYS_RES_MEMORY;
+			flags = RF_PREFETCHABLE;
+			break;
+		}
+		start = sas->address_base;
+		end = sas->address_base + sas->address_length - 1;
+#ifdef __i386__
+		if (start > ULONG_MAX) {
+			device_printf(args->dev,
+			    "Ignoring %d range above 4GB (%#jx-%#jx)\n",
+			    type, (uintmax_t)start, (uintmax_t)end);
+			break;
+		}
+		if (end > ULONG_MAX) {
+			device_printf(args->dev,
+			    "Truncating end of range above 4GB (%#jx-%#jx)\n",
+			    type, (uintmax_t)start, (uintmax_t)end);
+			end = ULONG_MAX;
+		}
+#endif
+		error = pcib_host_res_decodes(&args->sc->sc_host_res, type, start, end,
+		    flags);
+		if (error)
+			panic("Failed to manage %d range (%#jx-%#jx): %d", type,
+			    (uintmax_t)start, (uintmax_t)end, error);
+		break;
+	case MPCT_EXTENTRY_CBASM:
+		cbasm = (cbasm_entry_ptr *)entry;
+		if (cbasm->bus_id != args->bus)
+			break;
+		switch (cbasm->predefined_range) {
+		case CBASMENTRY_RANGE_ISA_IO:
+			flagp = &args->sc->sc_decodes_isa_io;
+			name = "ISA I/O";
+			break;
+		case CBASMENTRY_RANGE_VGA_IO:
+			flagp = &args->sc->sc_decodes_vga_io;
+			name = "VGA I/O";
+			break;
+		default:
+			printf(
+		    "MPTable: Unknown compatiblity address space range for bus %u: %d\n",
+			    cbasm->bus_id, cbasm->predefined_range);
+			return;
+		}
+		if (*flagp != 0)
+			printf("MPTable: Duplicate compatibility %s range for bus %u\n",
+			    name, cbasm->bus_id);
+		switch (cbasm->address_mod) {
+		case CBASMENTRY_ADDRESS_MOD_ADD:
+			*flagp = 1;
+			if (bootverbose)
+				device_printf(args->dev, "decoding %s ports\n", name);
+			break;
+		case CBASMENTRY_ADDRESS_MOD_SUBTRACT:
+			*flagp = -1;
+			if (bootverbose)
+				device_printf(args->dev, "not decoding %s ports\n", name);
+			break;
+		default:
+			printf(
+			    "MPTable: Unknown compatibility address space modifier: %u\n",
+			    cbasm->address_mod);
+			break;
+		}
+		break;
+	}
+}
+
 void
 mptable_pci_host_res_init(device_t pcib)
 {
-	struct mptable_hostb_softc *sc;
+	struct host_res_args args;
 
-	sc = device_get_softc(dev);
+	KASSERT(pci0 != -1, ("do not know how to map PCI bus IDs"));
+	args.bus = pci_get_bus(dev) + pci0;
+	args.dev = dev;
+	args.sc = device_get_softc(dev);
+	if (pcib_host_res_init(dev, &sc->sc_host_res) != 0)
+		panic("failed to init hostb resources");
+	mptable_walk_extended_table(mptable_host_res_handler, &args);
 }
 #endif

==== //depot/projects/pci/sys/x86/x86/mptable_pci.c#7 (text+ko) ====

@@ -109,6 +109,31 @@
 }
 
 #ifdef NEW_PCIB
+static int
+mptable_is_isa_range(u_long start, u_long end)
+{
+
+	if (end >= 0x10000)
+		return (0);
+	if (start & 0xfc00 != end & 0xfc00)
+		return (0);
+	start &= ~0xfc00;
+	end &- ~0xfc00;
+	return (start >= 0x100 && end <= 0x3ff);
+}
+
+static int
+mptable_is_vga_range(u_long start, u_long end)
+{
+	if (end >= 0x10000)
+		return (0);
+	if (start & 0xfc00 != end & 0xfc00)
+		return (0);
+	start &= ~0xfc00;
+	end &- ~0xfc00;
+	return (pci_is_vga_ioport_range(start, end));
+}
+
 static struct resource *
 mptable_hostb_alloc_resource(device_t dev, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
@@ -116,7 +141,30 @@
 	struct mptable_hostb_softc *sc;
 
 	sc = device_get_softc(dev);
-	/* XXX: Special handling for VGA and ISA I/O ranges. */
+	if (type == SYS_RES_IOPORT && start + count - 1 == end) {
+		if (mptable_is_isa_range(start, end)) {
+			switch (sc->sc_decodes_isa_io) {
+			case -1:
+				return (NULL);
+			case 1:
+				return (bus_generic_alloc_resource(dev, child, type, rid,
+				    start, end, count, flags));
+			default:
+				break;
+			}
+		}
+		if (mptable_is_vga_range(start, end)) {
+			switch (sc->sc_decodes_vga_io) {
+			case -1:
+				return (NULL);
+			case 1:
+				return (bus_generic_alloc_resource(dev, child, type, rid,
+				    start, end, count, flags));
+			default:
+				break;
+			}
+		}
+	}
 	return (pcib_host_res_alloc(&sc->sc_host_res, child, type, rid, start,
 	    end, count, flags));
 }



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