From owner-p4-projects@FreeBSD.ORG Mon Apr 4 02:30:37 2011 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id BBA381065673; Mon, 4 Apr 2011 02:30:37 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7E4EA106564A for ; Mon, 4 Apr 2011 02:30:37 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 688F28FC1C for ; Mon, 4 Apr 2011 02:30:37 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p342UbOF029286 for ; Mon, 4 Apr 2011 02:30:37 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p342UbFb029283 for perforce@freebsd.org; Mon, 4 Apr 2011 02:30:37 GMT (envelope-from jhb@freebsd.org) Date: Mon, 4 Apr 2011 02:30:37 GMT Message-Id: <201104040230.p342UbFb029283@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 191000 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Apr 2011 02:30:38 -0000 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 */