From owner-svn-src-all@FreeBSD.ORG Fri Jun 24 21:39:39 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (unknown [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 15CFA106566B; Fri, 24 Jun 2011 21:39:39 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [69.147.83.44]) by mx1.freebsd.org (Postfix) with ESMTP id 050DC8FC17; Fri, 24 Jun 2011 21:39:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p5OLdd6l071307; Fri, 24 Jun 2011 21:39:39 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p5OLdctw071303; Fri, 24 Jun 2011 21:39:38 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201106242139.p5OLdctw071303@svn.freebsd.org> From: John Baldwin Date: Fri, 24 Jun 2011 21:39:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r223520 - in head/sys: conf dev/pci X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jun 2011 21:39:39 -0000 Author: jhb Date: Fri Jun 24 21:39:38 2011 New Revision: 223520 URL: http://svn.freebsd.org/changeset/base/223520 Log: Split out host_pcib_get_busno() from the generic PCI-PCI bridge driver to start a new file that will hold utility APIs used by various Host-PCI bridge drivers and drivers that provide PCI domains. Added: head/sys/dev/pci/pci_subr.c - copied, changed from r223482, head/sys/dev/pci/pci_pci.c Modified: head/sys/conf/files head/sys/dev/pci/pci_pci.c Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Fri Jun 24 21:32:03 2011 (r223519) +++ head/sys/conf/files Fri Jun 24 21:39:38 2011 (r223520) @@ -1552,6 +1552,7 @@ dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci +dev/pci/pci_subr.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pci/vga_pci.c optional pci Modified: head/sys/dev/pci/pci_pci.c ============================================================================== --- head/sys/dev/pci/pci_pci.c Fri Jun 24 21:32:03 2011 (r223519) +++ head/sys/dev/pci/pci_pci.c Fri Jun 24 21:39:38 2011 (r223520) @@ -38,16 +38,12 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include -#include -#include - #include #include #include @@ -1432,91 +1428,3 @@ pcib_power_for_sleep(device_t pcib, devi bus = device_get_parent(pcib); return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate)); } - -/* - * Try to read the bus number of a host-PCI bridge using appropriate config - * registers. - */ -int -host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, - uint8_t *busnum) -{ - uint32_t id; - - id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); - if (id == 0xffffffff) - return (0); - - switch (id) { - case 0x12258086: - /* Intel 824?? */ - /* XXX This is a guess */ - /* *busnum = read_config(bus, slot, func, 0x41, 1); */ - *busnum = bus; - break; - case 0x84c48086: - /* Intel 82454KX/GX (Orion) */ - *busnum = read_config(bus, slot, func, 0x4a, 1); - break; - case 0x84ca8086: - /* - * For the 450nx chipset, there is a whole bundle of - * things pretending to be host bridges. The MIOC will - * be seen first and isn't really a pci bridge (the - * actual busses are attached to the PXB's). We need to - * read the registers of the MIOC to figure out the - * bus numbers for the PXB channels. - * - * Since the MIOC doesn't have a pci bus attached, we - * pretend it wasn't there. - */ - return (0); - case 0x84cb8086: - switch (slot) { - case 0x12: - /* Intel 82454NX PXB#0, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd0, 1); - break; - case 0x13: - /* Intel 82454NX PXB#0, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; - break; - case 0x14: - /* Intel 82454NX PXB#1, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd3, 1); - break; - case 0x15: - /* Intel 82454NX PXB#1, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; - break; - } - break; - - /* ServerWorks -- vendor 0x1166 */ - case 0x00051166: - case 0x00061166: - case 0x00081166: - case 0x00091166: - case 0x00101166: - case 0x00111166: - case 0x00171166: - case 0x01011166: - case 0x010f1014: - case 0x01101166: - case 0x02011166: - case 0x02251166: - case 0x03021014: - *busnum = read_config(bus, slot, func, 0x44, 1); - break; - - /* Compaq/HP -- vendor 0x0e11 */ - case 0x60100e11: - *busnum = read_config(bus, slot, func, 0xc8, 1); - break; - default: - /* Don't know how to read bus number. */ - return 0; - } - - return 1; -} Copied and modified: head/sys/dev/pci/pci_subr.c (from r223482, head/sys/dev/pci/pci_pci.c) ============================================================================== --- head/sys/dev/pci/pci_pci.c Thu Jun 23 17:42:27 2011 (r223482, copy source) +++ head/sys/dev/pci/pci_subr.c Fri Jun 24 21:39:38 2011 (r223520) @@ -1,7 +1,6 @@ /*- - * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier - * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000 BSDi + * Copyright (c) 2011 Advanced Computing Technologies LLC + * Written by: John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,8 +11,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -32,1407 +29,18 @@ __FBSDID("$FreeBSD$"); /* - * PCI:PCI bridge support. + * Support APIs for Host to PCI bridge drivers and drivers that + * provide PCI domains. */ -#include +#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include - -#include #include -#include +#include #include -#include "pcib_if.h" - -static int pcib_probe(device_t dev); -static int pcib_suspend(device_t dev); -static int pcib_resume(device_t dev); -static int pcib_power_for_sleep(device_t pcib, device_t dev, - int *pstate); - -static device_method_t pcib_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcib_probe), - DEVMETHOD(device_attach, pcib_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, pcib_suspend), - DEVMETHOD(device_resume, pcib_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, pcib_read_ivar), - DEVMETHOD(bus_write_ivar, pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), -#ifdef NEW_PCIB - DEVMETHOD(bus_adjust_resource, pcib_adjust_resource), - DEVMETHOD(bus_release_resource, pcib_release_resource), -#else - DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), -#endif - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, pcib_maxslots), - DEVMETHOD(pcib_read_config, pcib_read_config), - DEVMETHOD(pcib_write_config, pcib_write_config), - DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), - DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi), - DEVMETHOD(pcib_release_msi, pcib_release_msi), - DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix), - DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, pcib_map_msi), - DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep), - - { 0, 0 } -}; - -static devclass_t pcib_devclass; - -DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); -DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); - -#ifdef NEW_PCIB -/* - * XXX Todo: - * - properly handle the ISA enable bit. If it is set, we should change - * the behavior of the I/O window resource and rman to not allocate the - * blocked ranges (upper 768 bytes of each 1K in the first 64k of the - * I/O port address space). - */ - -/* - * Is a resource from a child device sub-allocated from one of our - * resource managers? - */ -static int -pcib_is_resource_managed(struct pcib_softc *sc, int type, struct resource *r) -{ - - switch (type) { - case SYS_RES_IOPORT: - return (rman_is_region_manager(r, &sc->io.rman)); - case SYS_RES_MEMORY: - /* Prefetchable resources may live in either memory rman. */ - if (rman_get_flags(r) & RF_PREFETCHABLE && - rman_is_region_manager(r, &sc->pmem.rman)) - return (1); - return (rman_is_region_manager(r, &sc->mem.rman)); - } - return (0); -} - -static int -pcib_is_window_open(struct pcib_window *pw) -{ - - return (pw->valid && pw->base < pw->limit); -} - -/* - * XXX: If RF_ACTIVE did not also imply allocating a bus space tag and - * handle for the resource, we could pass RF_ACTIVE up to the PCI bus - * when allocating the resource windows and rely on the PCI bus driver - * to do this for us. - */ -static void -pcib_activate_window(struct pcib_softc *sc, int type) -{ - - PCI_ENABLE_IO(device_get_parent(sc->dev), sc->dev, type); -} - -static void -pcib_write_windows(struct pcib_softc *sc, int mask) -{ - device_t dev; - uint32_t val; - - dev = sc->dev; - if (sc->io.valid && 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 (sc->pmem.valid && 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); - } -} - -static void -pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type, - int flags, pci_addr_t max_address) -{ - char buf[64]; - 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; - snprintf(buf, sizeof(buf), "%s %s window", - device_get_nameunit(sc->dev), w->name); - w->rman.rm_descr = strdup(buf, M_DEVBUF); - error = rman_init(&w->rman); - if (error) - panic("Failed to initialize %s %s rman", - device_get_nameunit(sc->dev), w->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", w->name); - return; - } - rid = w->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", - w->name, (uintmax_t)w->base, (uintmax_t)w->limit); - w->base = max_address; - w->limit = 0; - pcib_write_windows(sc, w->mask); - return; - } - pcib_activate_window(sc, type); - - 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; - - 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) { - sc->io.reg = PCIR_IOBASEL_1; - sc->io.step = 12; - sc->io.mask = WIN_IO; - sc->io.name = "I/O port"; - 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, 0, max); - } - - /* Read the existing memory window. */ - sc->mem.valid = 1; - sc->mem.reg = PCIR_MEMBASE_1; - sc->mem.step = 20; - sc->mem.mask = WIN_MEM; - sc->mem.name = "memory"; - 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, 0, 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) { - sc->pmem.reg = PCIR_PMBASEL_1; - sc->pmem.step = 20; - sc->pmem.mask = WIN_PMEM; - sc->pmem.name = "prefetch"; - if ((val & PCIM_BRPM_MASK) == PCIM_BRPM_64) { - sc->pmem.base = PCI_PPBMEMBASE( - pci_read_config(dev, PCIR_PMBASEH_1, 4), val); - 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, val); - 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, - RF_PREFETCHABLE, max); - } -} - -#else - -/* - * Is the prefetch window open (eg, can we allocate memory in it?) - */ -static int -pcib_is_prefetch_open(struct pcib_softc *sc) -{ - return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit); -} - -/* - * Is the nonprefetch window open (eg, can we allocate memory in it?) - */ -static int -pcib_is_nonprefetch_open(struct pcib_softc *sc) -{ - return (sc->membase > 0 && sc->membase < sc->memlimit); -} - -/* - * Is the io window open (eg, can we allocate ports in it?) - */ -static int -pcib_is_io_open(struct pcib_softc *sc) -{ - return (sc->iobase > 0 && sc->iobase < sc->iolimit); -} - -/* - * Get current I/O decode. - */ -static void -pcib_get_io_decode(struct pcib_softc *sc) -{ - device_t dev; - uint32_t iolow; - - dev = sc->dev; - - iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) - sc->iobase = PCI_PPBIOBASE( - pci_read_config(dev, PCIR_IOBASEH_1, 2), iolow); - else - sc->iobase = PCI_PPBIOBASE(0, iolow); - - iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) - sc->iolimit = PCI_PPBIOLIMIT( - pci_read_config(dev, PCIR_IOLIMITH_1, 2), iolow); - else - sc->iolimit = PCI_PPBIOLIMIT(0, iolow); -} - -/* - * Get current memory decode. - */ -static void -pcib_get_mem_decode(struct pcib_softc *sc) -{ - device_t dev; - pci_addr_t pmemlow; - - dev = sc->dev; - - sc->membase = PCI_PPBMEMBASE(0, - pci_read_config(dev, PCIR_MEMBASE_1, 2)); - sc->memlimit = PCI_PPBMEMLIMIT(0, - pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); - - pmemlow = pci_read_config(dev, PCIR_PMBASEL_1, 2); - if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmembase = PCI_PPBMEMBASE( - pci_read_config(dev, PCIR_PMBASEH_1, 4), pmemlow); - else - sc->pmembase = PCI_PPBMEMBASE(0, pmemlow); - - pmemlow = pci_read_config(dev, PCIR_PMLIMITL_1, 2); - if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmemlimit = PCI_PPBMEMLIMIT( - pci_read_config(dev, PCIR_PMLIMITH_1, 4), pmemlow); - else - sc->pmemlimit = PCI_PPBMEMLIMIT(0, pmemlow); -} - -/* - * Restore previous I/O decode. - */ -static void -pcib_set_io_decode(struct pcib_softc *sc) -{ - device_t dev; - uint32_t iohi; - - dev = sc->dev; - - iohi = sc->iobase >> 16; - if (iohi > 0) - pci_write_config(dev, PCIR_IOBASEH_1, iohi, 2); - pci_write_config(dev, PCIR_IOBASEL_1, sc->iobase >> 8, 1); - - iohi = sc->iolimit >> 16; - if (iohi > 0) - pci_write_config(dev, PCIR_IOLIMITH_1, iohi, 2); - pci_write_config(dev, PCIR_IOLIMITL_1, sc->iolimit >> 8, 1); -} - -/* - * Restore previous memory decode. - */ -static void -pcib_set_mem_decode(struct pcib_softc *sc) -{ - device_t dev; - pci_addr_t pmemhi; - - dev = sc->dev; - - pci_write_config(dev, PCIR_MEMBASE_1, sc->membase >> 16, 2); - pci_write_config(dev, PCIR_MEMLIMIT_1, sc->memlimit >> 16, 2); - - pmemhi = sc->pmembase >> 32; - if (pmemhi > 0) - pci_write_config(dev, PCIR_PMBASEH_1, pmemhi, 4); - pci_write_config(dev, PCIR_PMBASEL_1, sc->pmembase >> 16, 2); - - pmemhi = sc->pmemlimit >> 32; - if (pmemhi > 0) - 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. - */ -static void -pcib_cfg_save(struct pcib_softc *sc) -{ - device_t dev; - - dev = sc->dev; - - sc->command = pci_read_config(dev, PCIR_COMMAND, 2); - sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); - sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); - 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 -} - -/* - * Restore previous bridge configuration. - */ -static void -pcib_cfg_restore(struct pcib_softc *sc) -{ - device_t dev; - - dev = sc->dev; - - pci_write_config(dev, PCIR_COMMAND, sc->command, 2); - pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); - pci_write_config(dev, PCIR_SECBUS_1, sc->secbus, 1); - 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 -} - -/* - * Generic device interface - */ -static int -pcib_probe(device_t dev) -{ - if ((pci_get_class(dev) == PCIC_BRIDGE) && - (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { - device_set_desc(dev, "PCI-PCI bridge"); - return(-10000); - } - return(ENXIO); -} - -void -pcib_attach_common(device_t dev) -{ - struct pcib_softc *sc; - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - - sc = device_get_softc(dev); - sc->dev = dev; - - /* - * Get current bridge configuration. - */ - sc->domain = pci_get_domain(dev); - sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); - pcib_cfg_save(sc); - - /* - * Setup sysctl reporting nodes - */ - sctx = device_get_sysctl_ctx(dev); - soid = device_get_sysctl_tree(dev); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "domain", - CTLFLAG_RD, &sc->domain, 0, "Domain number"); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "pribus", - CTLFLAG_RD, &sc->pribus, 0, "Primary bus number"); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "secbus", - CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number"); - SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", - CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number"); - - /* - * Quirk handling. - */ - switch (pci_get_devid(dev)) { - case 0x12258086: /* Intel 82454KX/GX (Orion) */ - { - uint8_t supbus; - - supbus = pci_read_config(dev, 0x41, 1); - if (supbus != 0xff) { - sc->secbus = supbus + 1; - sc->subbus = supbus + 1; - } - break; - } - - /* - * The i82380FB mobile docking controller is a PCI-PCI bridge, - * and it is a subtractive bridge. However, the ProgIf is wrong - * so the normal setting of PCIB_SUBTRACTIVE bit doesn't - * happen. There's also a Toshiba bridge that behaves this - * way. - */ - case 0x124b8086: /* Intel 82380FB Mobile */ - case 0x060513d7: /* Toshiba ???? */ - sc->flags |= PCIB_SUBTRACTIVE; - break; - - /* Compaq R3000 BIOS sets wrong subordinate bus number. */ - case 0x00dd10de: - { - char *cp; - - if ((cp = getenv("smbios.planar.maker")) == NULL) - break; - if (strncmp(cp, "Compal", 6) != 0) { - freeenv(cp); - break; - } - freeenv(cp); - if ((cp = getenv("smbios.planar.product")) == NULL) - break; - if (strncmp(cp, "08A0", 4) != 0) { - freeenv(cp); - break; - } - freeenv(cp); - if (sc->subbus < 0xa) { - pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1); - sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); - } - break; - } - } - - if (pci_msi_device_blacklisted(dev)) - sc->flags |= PCIB_DISABLE_MSI; - - /* - * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, - * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, - * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. - * This means they act as if they were subtractively decoding - * bridges and pass all transactions. Mark them and real ProgIf 1 - * parts as subtractive. - */ - 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(sc); -#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); -#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) - device_printf(dev, " Subtractively decoded bridge.\n"); - } - - /* - * XXX If the secondary bus number is zero, we should assign a bus number - * since the BIOS hasn't, then initialise the bridge. A simple - * bus_alloc_resource with the a couple of busses seems like the right - * approach, but we don't know what busses the BIOS might have already - * assigned to other bridges on this bus that probe later than we do. - * - * If the subordinate bus number is less than the secondary bus number, - * we should pick a better value. One sensible alternative would be to - * pick 255; the only tradeoff here is that configuration transactions - * would be more widely routed than absolutely necessary. We could - * then do a walk of the tree later and fix it. - */ -} - -int -pcib_attach(device_t dev) -{ - struct pcib_softc *sc; - device_t child; - - pcib_attach_common(dev); - sc = device_get_softc(dev); - if (sc->secbus != 0) { - child = device_add_child(dev, "pci", sc->secbus); - if (child != NULL) - return(bus_generic_attach(dev)); - } - - /* no secondary bus; we should have fixed this */ - return(0); -} - -int -pcib_suspend(device_t dev) -{ - device_t pcib; - int dstate, error; - - pcib_cfg_save(device_get_softc(dev)); - error = bus_generic_suspend(dev); - if (error == 0 && pci_do_power_suspend) { - dstate = PCI_POWERSTATE_D3; - pcib = device_get_parent(device_get_parent(dev)); - if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) - pci_set_powerstate(dev, dstate); - } - return (error); -} - -int -pcib_resume(device_t dev) -{ - device_t pcib; - - if (pci_do_power_resume) { - pcib = device_get_parent(device_get_parent(dev)); - if (PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0) - pci_set_powerstate(dev, PCI_POWERSTATE_D0); - } - pcib_cfg_restore(device_get_softc(dev)); - return (bus_generic_resume(dev)); -} - -int -pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct pcib_softc *sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = sc->domain; - return(0); - case PCIB_IVAR_BUS: - *result = sc->secbus; - return(0); - } - return(ENOENT); -} - -int -pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct pcib_softc *sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - return(EINVAL); - case PCIB_IVAR_BUS: - sc->secbus = value; - return(0); - } - return(ENOENT); -} - -#ifdef NEW_PCIB -static const char * -pcib_child_name(device_t child) -{ - static char buf[64]; - - if (device_get_nameunit(child) != NULL) - return (device_get_nameunit(child)); - snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child), - pci_get_bus(child), pci_get_slot(child), pci_get_function(child)); - return (buf); -} - -/* - * 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->rman, start, end, count, - flags & ~RF_ACTIVE, child); - if (res == NULL) - return (NULL); - - if (bootverbose) - device_printf(sc->dev, - "allocated %s range (%#lx-%#lx) for rid %x of %s\n", - w->name, rman_get_start(res), rman_get_end(res), *rid, - pcib_child_name(child)); - 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. - * The 'step' parameter is log_2 of the desired I/O window's alignment. - */ -static int -pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type, - u_long start, u_long end, u_long count, u_int flags) -{ - u_long align, start_free, end_free, front, back; - int error, rid; - - /* - * Clamp the desired resource range to the maximum address - * this window supports. Reject impossible requests. - */ - if (!w->valid) - return (EINVAL); - if (end > w->rman.rm_end) - end = w->rman.rm_end; - if (start + count - 1 > end || start + count < start) - return (EINVAL); - - /* - * If there is no resource at all, just try to allocate enough - * aligned space for this resource. - */ - if (w->res == NULL) { - if (RF_ALIGNMENT(flags) < w->step) { - flags &= ~RF_ALIGNMENT_MASK; - flags |= RF_ALIGNMENT_LOG2(w->step); - } - start &= ~((1ul << w->step) - 1); - end |= ((1ul << w->step) - 1); - count = roundup2(count, 1ul << w->step); - rid = w->reg; - w->res = bus_alloc_resource(sc->dev, type, &rid, start, end, - count, flags & ~RF_ACTIVE); - if (w->res == NULL) { - if (bootverbose) - device_printf(sc->dev, - "failed to allocate initial %s window (%#lx-%#lx,%#lx)\n", - w->name, start, end, count); - return (ENXIO); - } - if (bootverbose) - device_printf(sc->dev, - "allocated initial %s window of %#lx-%#lx\n", - w->name, rman_get_start(w->res), - rman_get_end(w->res)); - error = rman_manage_region(&w->rman, rman_get_start(w->res), - rman_get_end(w->res)); - if (error) { - if (bootverbose) - device_printf(sc->dev, - "failed to add initial %s window to rman\n", - w->name); - bus_release_resource(sc->dev, type, w->reg, w->res); - w->res = NULL; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***