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>