pci_subr.c revision 69783
169783Smsmith/*- 269783Smsmith * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier 369783Smsmith * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 469783Smsmith * Copyright (c) 2000 BSDi 569783Smsmith * All rights reserved. 669783Smsmith * 769783Smsmith * Redistribution and use in source and binary forms, with or without 869783Smsmith * modification, are permitted provided that the following conditions 969783Smsmith * are met: 1069783Smsmith * 1. Redistributions of source code must retain the above copyright 1169783Smsmith * notice, this list of conditions and the following disclaimer. 1269783Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1369783Smsmith * notice, this list of conditions and the following disclaimer in the 1469783Smsmith * documentation and/or other materials provided with the distribution. 1569783Smsmith * 3. The name of the author may not be used to endorse or promote products 1669783Smsmith * derived from this software without specific prior written permission. 1769783Smsmith * 1869783Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1969783Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2069783Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2169783Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2269783Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2369783Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2469783Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2569783Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2669783Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2769783Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2869783Smsmith * SUCH DAMAGE. 2969783Smsmith * 3069783Smsmith * $FreeBSD: head/sys/dev/pci/pci_pci.c 69783 2000-12-08 22:11:23Z msmith $ 3169783Smsmith */ 3269783Smsmith 3369783Smsmith/* 3469783Smsmith * PCI:PCI bridge support. 3569783Smsmith */ 3669783Smsmith 3769783Smsmith#include <sys/param.h> 3869783Smsmith#include <sys/systm.h> 3969783Smsmith#include <sys/kernel.h> 4069783Smsmith#include <sys/bus.h> 4169783Smsmith 4269783Smsmith#include <machine/resource.h> 4369783Smsmith 4469783Smsmith#include <pci/pcivar.h> 4569783Smsmith#include <pci/pcireg.h> 4669783Smsmith 4769783Smsmith#include "pcib_if.h" 4869783Smsmith 4969783Smsmith/* 5069783Smsmith * Bridge-specific data. 5169783Smsmith */ 5269783Smsmithstruct pcib_softc 5369783Smsmith{ 5469783Smsmith device_t dev; 5569783Smsmith u_int8_t secbus; /* secondary bus number */ 5669783Smsmith u_int8_t subbus; /* subordinate bus number */ 5769783Smsmith pci_addr_t pmembase; /* base address of prefetchable memory */ 5869783Smsmith pci_addr_t pmemlimit; /* topmost address of prefetchable memory */ 5969783Smsmith u_int32_t membase; /* base address of memory window */ 6069783Smsmith u_int32_t memlimit; /* topmost address of memory window */ 6169783Smsmith u_int32_t iobase; /* base address of port window */ 6269783Smsmith u_int32_t iolimit; /* topmost address of port window */ 6369783Smsmith u_int16_t secstat; /* secondary bus status register */ 6469783Smsmith u_int16_t bridgectl; /* bridge control register */ 6569783Smsmith u_int8_t seclat; /* secondary bus latency timer */ 6669783Smsmith}; 6769783Smsmith 6869783Smsmithstatic int pcib_probe(device_t dev); 6969783Smsmithstatic int pcib_attach(device_t dev); 7069783Smsmithstatic int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); 7169783Smsmithstatic int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value); 7269783Smsmithstatic struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 7369783Smsmith u_long start, u_long end, u_long count, u_int flags); 7469783Smsmithstatic int pcib_maxslots(device_t dev); 7569783Smsmithstatic u_int32_t pcib_read_config(device_t dev, int b, int s, int f, int reg, int width); 7669783Smsmithstatic void pcib_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, int width); 7769783Smsmithstatic int pcib_route_interrupt(device_t pcib, device_t dev, int pin); 7869783Smsmith 7969783Smsmithstatic device_method_t pcib_methods[] = { 8069783Smsmith /* Device interface */ 8169783Smsmith DEVMETHOD(device_probe, pcib_probe), 8269783Smsmith DEVMETHOD(device_attach, pcib_attach), 8369783Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 8469783Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), 8569783Smsmith DEVMETHOD(device_resume, bus_generic_resume), 8669783Smsmith 8769783Smsmith /* Bus interface */ 8869783Smsmith DEVMETHOD(bus_print_child, bus_generic_print_child), 8969783Smsmith DEVMETHOD(bus_read_ivar, pcib_read_ivar), 9069783Smsmith DEVMETHOD(bus_write_ivar, pcib_write_ivar), 9169783Smsmith DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), 9269783Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 9369783Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 9469783Smsmith DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 9569783Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 9669783Smsmith DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 9769783Smsmith 9869783Smsmith /* pcib interface */ 9969783Smsmith DEVMETHOD(pcib_maxslots, pcib_maxslots), 10069783Smsmith DEVMETHOD(pcib_read_config, pcib_read_config), 10169783Smsmith DEVMETHOD(pcib_write_config, pcib_write_config), 10269783Smsmith DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), 10369783Smsmith 10469783Smsmith { 0, 0 } 10569783Smsmith}; 10669783Smsmith 10769783Smsmithstatic driver_t pcib_driver = { 10869783Smsmith "pcib", 10969783Smsmith pcib_methods, 11069783Smsmith sizeof(struct pcib_softc), 11169783Smsmith}; 11269783Smsmith 11369783Smsmithstatic devclass_t pcib_devclass; 11469783Smsmith 11569783SmsmithDRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); 11669783Smsmith 11769783Smsmith/* 11869783Smsmith * Generic device interface 11969783Smsmith */ 12069783Smsmithstatic int 12169783Smsmithpcib_probe(device_t dev) 12269783Smsmith{ 12369783Smsmith if ((pci_get_class(dev) == PCIC_BRIDGE) && 12469783Smsmith (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { 12569783Smsmith device_set_desc(dev, "PCI-PCI bridge"); 12669783Smsmith return(-10000); 12769783Smsmith } 12869783Smsmith return(ENXIO); 12969783Smsmith} 13069783Smsmith 13169783Smsmithstatic int 13269783Smsmithpcib_attach(device_t dev) 13369783Smsmith{ 13469783Smsmith struct pcib_softc *sc; 13569783Smsmith device_t pcib, child; 13669783Smsmith int b, s, f; 13769783Smsmith 13869783Smsmith sc = device_get_softc(dev); 13969783Smsmith sc->dev = dev; 14069783Smsmith pcib = device_get_parent(dev); 14169783Smsmith b = pci_get_bus(dev); 14269783Smsmith s = pci_get_slot(dev); 14369783Smsmith f = pci_get_function(dev); 14469783Smsmith 14569783Smsmith sc->secbus = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECBUS_1, 1); 14669783Smsmith sc->subbus = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SUBBUS_1, 1); 14769783Smsmith sc->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2); 14869783Smsmith sc->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2); 14969783Smsmith sc->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1); 15069783Smsmith sc->iobase = PCI_PPBIOBASE(PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASEH_1, 2), 15169783Smsmith PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASEL_1, 1)); 15269783Smsmith sc->iolimit = PCI_PPBIOLIMIT(PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMITH_1, 2), 15369783Smsmith PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMITL_1, 1)); 15469783Smsmith sc->membase = PCI_PPBMEMBASE(0, PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE_1, 2)); 15569783Smsmith sc->memlimit = PCI_PPBMEMLIMIT(0, PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT_1, 2)); 15669783Smsmith sc->pmembase = PCI_PPBMEMBASE((pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4), 15769783Smsmith PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2)); 15869783Smsmith sc->pmemlimit = PCI_PPBMEMLIMIT((pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,PCIR_PMLIMITH_1, 4), 15969783Smsmith PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2)); 16069783Smsmith 16169783Smsmith if (bootverbose) { 16269783Smsmith device_printf(dev, " secondary bus %d\n", sc->secbus); 16369783Smsmith device_printf(dev, " subordinate bus %d\n", sc->subbus); 16469783Smsmith device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit); 16569783Smsmith device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit); 16669783Smsmith device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit); 16769783Smsmith } 16869783Smsmith 16969783Smsmith /* 17069783Smsmith * XXX If the secondary bus number is zero, we should assign a bus number 17169783Smsmith * since the BIOS hasn't, then initialise the bridge. 17269783Smsmith */ 17369783Smsmith 17469783Smsmith /* 17569783Smsmith * XXX If the subordinate bus number is less than the secondary bus number, 17669783Smsmith * we should pick a better value. One sensible alternative would be to 17769783Smsmith * pick 255; the only tradeoff here is that configuration transactions 17869783Smsmith * would be more widely routed than absolutely necessary. 17969783Smsmith */ 18069783Smsmith 18169783Smsmith if (sc->secbus != 0) { 18269783Smsmith child = device_add_child(dev, "pci", -1); 18369783Smsmith if (child != NULL) 18469783Smsmith return(bus_generic_attach(dev)); 18569783Smsmith } 18669783Smsmith 18769783Smsmith /* no secondary bus; we should have fixed this */ 18869783Smsmith return(0); 18969783Smsmith} 19069783Smsmith 19169783Smsmithstatic int 19269783Smsmithpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 19369783Smsmith{ 19469783Smsmith struct pcib_softc *sc = device_get_softc(dev); 19569783Smsmith 19669783Smsmith switch (which) { 19769783Smsmith case PCIB_IVAR_BUS: 19869783Smsmith *result = sc->secbus; 19969783Smsmith return(0); 20069783Smsmith } 20169783Smsmith return(ENOENT); 20269783Smsmith} 20369783Smsmith 20469783Smsmithstatic int 20569783Smsmithpcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 20669783Smsmith{ 20769783Smsmith struct pcib_softc *sc = device_get_softc(dev); 20869783Smsmith 20969783Smsmith switch (which) { 21069783Smsmith case PCIB_IVAR_BUS: 21169783Smsmith sc->secbus = value; 21269783Smsmith break; 21369783Smsmith } 21469783Smsmith return(ENOENT); 21569783Smsmith} 21669783Smsmith 21769783Smsmith/* 21869783Smsmith * We have to trap resource allocation requests and ensure that the bridge 21969783Smsmith * is set up to, or capable of handling them. 22069783Smsmith */ 22169783Smsmithstatic struct resource * 22269783Smsmithpcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 22369783Smsmith u_long start, u_long end, u_long count, u_int flags) 22469783Smsmith{ 22569783Smsmith struct pcib_softc *sc = device_get_softc(dev); 22669783Smsmith 22769783Smsmith /* 22869783Smsmith * If this is a "default" allocation against this rid, we can't work 22969783Smsmith * out where it's coming from (we should actually never see these) so we 23069783Smsmith * just have to punt. 23169783Smsmith */ 23269783Smsmith if ((start == 0) && (end == ~0)) { 23369783Smsmith device_printf(dev, "can't decode default resource id %d for %s%d, bypassing\n", 23469783Smsmith *rid, device_get_name(child), device_get_unit(child)); 23569783Smsmith } else { 23669783Smsmith /* 23769783Smsmith * Fail the allocation for this range if it's not supported. 23869783Smsmith * 23969783Smsmith * XXX we should probably just fix up the bridge decode and soldier on. 24069783Smsmith */ 24169783Smsmith switch (type) { 24269783Smsmith case SYS_RES_IOPORT: 24369783Smsmith if ((start < sc->iobase) || (end > sc->iolimit)) { 24469783Smsmith device_printf(dev, "device %s%d requested unsupported I/O range 0x%lx-0x%lx" 24569783Smsmith " (decoding 0x%x-0x%x)\n", 24669783Smsmith device_get_name(child), device_get_unit(child), start, end, 24769783Smsmith sc->iobase, sc->iolimit); 24869783Smsmith return(NULL); 24969783Smsmith } 25069783Smsmith break; 25169783Smsmith 25269783Smsmith /* 25369783Smsmith * XXX will have to decide whether the device making the request is asking 25469783Smsmith * for prefetchable memory or not. If it's coming from another bridge 25569783Smsmith * down the line, do we assume not, or ask the bridge to pass in another 25669783Smsmith * flag as the request bubbles up? 25769783Smsmith */ 25869783Smsmith case SYS_RES_MEMORY: 25969783Smsmith if (((start < sc->membase) || (end > sc->memlimit)) && 26069783Smsmith ((start < sc->pmembase) || (end > sc->pmemlimit))) { 26169783Smsmith device_printf(dev, "device %s%d requested unsupported memory range 0x%lx-0x%lx" 26269783Smsmith " (decoding 0x%x-0x%x, 0x%x-0x%x)\n", 26369783Smsmith device_get_name(child), device_get_unit(child), start, end, 26469783Smsmith sc->membase, sc->memlimit, sc->pmembase, sc->pmemlimit); 26569783Smsmith return(NULL); 26669783Smsmith } 26769783Smsmith default: 26869783Smsmith } 26969783Smsmith } 27069783Smsmith device_printf(sc->dev, "resource request type %d 0x%lx-0x%lx decodes OK\n", 27169783Smsmith type, start, end); 27269783Smsmith /* 27369783Smsmith * Bridge is OK decoding this resource, so pass it up. 27469783Smsmith */ 27569783Smsmith return(bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); 27669783Smsmith} 27769783Smsmith 27869783Smsmith/* 27969783Smsmith * PCIB interface. 28069783Smsmith */ 28169783Smsmithstatic int 28269783Smsmithpcib_maxslots(device_t dev) 28369783Smsmith{ 28469783Smsmith return(31); 28569783Smsmith} 28669783Smsmith 28769783Smsmith/* 28869783Smsmith * Since we are a child of a PCI bus, its parent must support the pcib interface. 28969783Smsmith */ 29069783Smsmithstatic u_int32_t 29169783Smsmithpcib_read_config(device_t dev, int b, int s, int f, int reg, int width) 29269783Smsmith{ 29369783Smsmith return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); 29469783Smsmith} 29569783Smsmith 29669783Smsmithstatic void 29769783Smsmithpcib_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, int width) 29869783Smsmith{ 29969783Smsmith PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); 30069783Smsmith} 30169783Smsmith 30269783Smsmith/* 30369783Smsmith * Route an interrupt across a PCI bridge. 30469783Smsmith */ 30569783Smsmithstatic int 30669783Smsmithpcib_route_interrupt(device_t pcib, device_t dev, int pin) 30769783Smsmith{ 30869783Smsmith device_t bus; 30969783Smsmith int parent_intpin; 31069783Smsmith int intnum; 31169783Smsmith 31269783Smsmith /* 31369783Smsmith * 31469783Smsmith * The PCI standard defines a swizzle of the child-side device/intpin to 31569783Smsmith * the parent-side intpin as follows. 31669783Smsmith * 31769783Smsmith * device = device on child bus 31869783Smsmith * child_intpin = intpin on child bus slot (0-3) 31969783Smsmith * parent_intpin = intpin on parent bus slot (0-3) 32069783Smsmith * 32169783Smsmith * parent_intpin = (device + child_intpin) % 4 32269783Smsmith */ 32369783Smsmith parent_intpin = (pci_get_slot(pcib) + (pin - 1)) % 4; 32469783Smsmith 32569783Smsmith /* 32669783Smsmith * Our parent is a PCI bus. Its parent must export the pcib interface 32769783Smsmith * which includes the ability to route interrupts. 32869783Smsmith */ 32969783Smsmith bus = device_get_parent(pcib); 33069783Smsmith intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1); 33169783Smsmith device_printf(pcib, "routed slot %d INT%c to irq %d\n", pci_get_slot(dev), 33269783Smsmith 'A' + pin - 1, intnum); 33369783Smsmith return(intnum); 33469783Smsmith} 335