pci_subr.c revision 102977
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 102977 2002-09-05 17:08:35Z jhb $ 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> 46102441Sjhb#include <pci/pcib_private.h> 4769783Smsmith 4869783Smsmith#include "pcib_if.h" 4989383Simp#include "opt_pci.h" 5069783Smsmith 5169783Smsmithstatic int pcib_probe(device_t dev); 5269783Smsmithstatic int pcib_attach(device_t dev); 5369783Smsmithstatic int pcib_route_interrupt(device_t pcib, device_t dev, int pin); 5469783Smsmith 5569783Smsmithstatic device_method_t pcib_methods[] = { 5669783Smsmith /* Device interface */ 5769783Smsmith DEVMETHOD(device_probe, pcib_probe), 5869783Smsmith DEVMETHOD(device_attach, pcib_attach), 5969783Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 6069783Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), 6169783Smsmith DEVMETHOD(device_resume, bus_generic_resume), 6269783Smsmith 6369783Smsmith /* Bus interface */ 6469783Smsmith DEVMETHOD(bus_print_child, bus_generic_print_child), 6569783Smsmith DEVMETHOD(bus_read_ivar, pcib_read_ivar), 6669783Smsmith DEVMETHOD(bus_write_ivar, pcib_write_ivar), 6769783Smsmith DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), 6869783Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 6969783Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 7069783Smsmith DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 7169783Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 7269783Smsmith DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 7369783Smsmith 7469783Smsmith /* pcib interface */ 7569783Smsmith DEVMETHOD(pcib_maxslots, pcib_maxslots), 7669783Smsmith DEVMETHOD(pcib_read_config, pcib_read_config), 7769783Smsmith DEVMETHOD(pcib_write_config, pcib_write_config), 7869783Smsmith DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), 7969783Smsmith 8069783Smsmith { 0, 0 } 8169783Smsmith}; 8269783Smsmith 8369783Smsmithstatic driver_t pcib_driver = { 8469783Smsmith "pcib", 8569783Smsmith pcib_methods, 8669783Smsmith sizeof(struct pcib_softc), 8769783Smsmith}; 8869783Smsmith 89102441Sjhbdevclass_t pcib_devclass; 9069783Smsmith 9169783SmsmithDRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); 9269783Smsmith 9369783Smsmith/* 9469783Smsmith * Generic device interface 9569783Smsmith */ 9669783Smsmithstatic int 9769783Smsmithpcib_probe(device_t dev) 9869783Smsmith{ 9969783Smsmith if ((pci_get_class(dev) == PCIC_BRIDGE) && 10069783Smsmith (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { 10169783Smsmith device_set_desc(dev, "PCI-PCI bridge"); 10269783Smsmith return(-10000); 10369783Smsmith } 10469783Smsmith return(ENXIO); 10569783Smsmith} 10669783Smsmith 107102441Sjhbvoid 108102441Sjhbpcib_attach_common(device_t dev) 10969783Smsmith{ 11069783Smsmith struct pcib_softc *sc; 11169908Smsmith u_int8_t iolow; 11269783Smsmith 11369783Smsmith sc = device_get_softc(dev); 11469783Smsmith sc->dev = dev; 11569783Smsmith 11669908Smsmith /* 11769908Smsmith * Get current bridge configuration. 11869908Smsmith */ 11969953Smsmith sc->command = pci_read_config(dev, PCIR_COMMAND, 1); 12069908Smsmith sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); 12169908Smsmith sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); 12269908Smsmith sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); 12369908Smsmith sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); 12469908Smsmith sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); 12569783Smsmith 12669908Smsmith /* 12769908Smsmith * Determine current I/O decode. 12869908Smsmith */ 12969953Smsmith if (sc->command & PCIM_CMD_PORTEN) { 13069953Smsmith iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); 13169953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 13269953Smsmith sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2), 13369953Smsmith pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13469953Smsmith } else { 13569953Smsmith sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13669953Smsmith } 13769908Smsmith 13869953Smsmith iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); 13969953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 14069953Smsmith sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2), 14169953Smsmith pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14269953Smsmith } else { 14369953Smsmith sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14469953Smsmith } 14569908Smsmith } 14669908Smsmith 14769908Smsmith /* 14869908Smsmith * Determine current memory decode. 14969908Smsmith */ 15069953Smsmith if (sc->command & PCIM_CMD_MEMEN) { 15169953Smsmith sc->membase = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2)); 15269953Smsmith sc->memlimit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); 15369953Smsmith sc->pmembase = PCI_PPBMEMBASE((pci_addr_t)pci_read_config(dev, PCIR_PMBASEH_1, 4), 15469953Smsmith pci_read_config(dev, PCIR_PMBASEL_1, 2)); 15569953Smsmith sc->pmemlimit = PCI_PPBMEMLIMIT((pci_addr_t)pci_read_config(dev, PCIR_PMLIMITH_1, 4), 15669953Smsmith pci_read_config(dev, PCIR_PMLIMITL_1, 2)); 15769953Smsmith } 15869908Smsmith 15969908Smsmith /* 16069908Smsmith * Quirk handling. 16169908Smsmith */ 16269908Smsmith switch (pci_get_devid(dev)) { 16369908Smsmith case 0x12258086: /* Intel 82454KX/GX (Orion) */ 16469908Smsmith { 16569908Smsmith u_int8_t supbus; 16669908Smsmith 16769908Smsmith supbus = pci_read_config(dev, 0x41, 1); 16869908Smsmith if (supbus != 0xff) { 16969908Smsmith sc->secbus = supbus + 1; 17069908Smsmith sc->subbus = supbus + 1; 17169908Smsmith } 17269908Smsmith } 17369908Smsmith break; 17469908Smsmith } 17569908Smsmith 17669783Smsmith if (bootverbose) { 17769783Smsmith device_printf(dev, " secondary bus %d\n", sc->secbus); 17869783Smsmith device_printf(dev, " subordinate bus %d\n", sc->subbus); 17969783Smsmith device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit); 18069783Smsmith device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit); 18169783Smsmith device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit); 18269783Smsmith } 18369783Smsmith 18469783Smsmith /* 18569783Smsmith * XXX If the secondary bus number is zero, we should assign a bus number 18669783Smsmith * since the BIOS hasn't, then initialise the bridge. 18769783Smsmith */ 18869783Smsmith 18969783Smsmith /* 19069783Smsmith * XXX If the subordinate bus number is less than the secondary bus number, 19169783Smsmith * we should pick a better value. One sensible alternative would be to 19269783Smsmith * pick 255; the only tradeoff here is that configuration transactions 19369783Smsmith * would be more widely routed than absolutely necessary. 19469783Smsmith */ 195102441Sjhb} 19669783Smsmith 197102441Sjhbstatic int 198102441Sjhbpcib_attach(device_t dev) 199102441Sjhb{ 200102441Sjhb struct pcib_softc *sc; 201102441Sjhb device_t child; 202102441Sjhb 203102441Sjhb pcib_attach_common(dev); 204102441Sjhb sc = device_get_softc(dev); 20569783Smsmith if (sc->secbus != 0) { 20669783Smsmith child = device_add_child(dev, "pci", -1); 20769783Smsmith if (child != NULL) 20869783Smsmith return(bus_generic_attach(dev)); 20969783Smsmith } 21069783Smsmith 21169783Smsmith /* no secondary bus; we should have fixed this */ 21269783Smsmith return(0); 21369783Smsmith} 21469783Smsmith 215102441Sjhbint 21669783Smsmithpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 21769783Smsmith{ 21869783Smsmith struct pcib_softc *sc = device_get_softc(dev); 21969783Smsmith 22069783Smsmith switch (which) { 22169783Smsmith case PCIB_IVAR_BUS: 22269783Smsmith *result = sc->secbus; 22369783Smsmith return(0); 22469783Smsmith } 22569783Smsmith return(ENOENT); 22669783Smsmith} 22769783Smsmith 228102441Sjhbint 22969783Smsmithpcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 23069783Smsmith{ 23169783Smsmith struct pcib_softc *sc = device_get_softc(dev); 23269783Smsmith 23369783Smsmith switch (which) { 23469783Smsmith case PCIB_IVAR_BUS: 23569783Smsmith sc->secbus = value; 23669783Smsmith break; 23769783Smsmith } 23869783Smsmith return(ENOENT); 23969783Smsmith} 24069783Smsmith 24169783Smsmith/* 24290388Simp * Is this a decoded ISA I/O port address? Note, we need to do the mask that 24390388Simp * we do below because of the ISA alias addresses. I'm not 100% sure that 24490388Simp * this is correct. 24590388Simp */ 24690388Simpstatic int 24790388Simppcib_is_isa_io(u_long start) 24890388Simp{ 24990898Simp if ((start & 0xfffUL) > 0x3ffUL || start == 0) 25090388Simp return (0); 25190388Simp return (1); 25290388Simp} 25390388Simp 25490388Simp/* 25590388Simp * Is this a decoded ISA memory address? 25690388Simp */ 25790388Simpstatic int 25890388Simppcib_is_isa_mem(u_long start) 25990388Simp{ 26090898Simp if (start > 0xfffffUL || start == 0) 26190388Simp return (0); 26290388Simp return (1); 26390388Simp} 26490388Simp 26590388Simp/* 26669783Smsmith * We have to trap resource allocation requests and ensure that the bridge 26769783Smsmith * is set up to, or capable of handling them. 26869783Smsmith */ 269102441Sjhbstruct resource * 27069783Smsmithpcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 27169783Smsmith u_long start, u_long end, u_long count, u_int flags) 27269783Smsmith{ 27369783Smsmith struct pcib_softc *sc = device_get_softc(dev); 27469783Smsmith 27569783Smsmith /* 27669783Smsmith * If this is a "default" allocation against this rid, we can't work 27769783Smsmith * out where it's coming from (we should actually never see these) so we 27869783Smsmith * just have to punt. 27969783Smsmith */ 28069783Smsmith if ((start == 0) && (end == ~0)) { 28169783Smsmith device_printf(dev, "can't decode default resource id %d for %s%d, bypassing\n", 28269783Smsmith *rid, device_get_name(child), device_get_unit(child)); 28369783Smsmith } else { 28469783Smsmith /* 28569783Smsmith * Fail the allocation for this range if it's not supported. 28669783Smsmith * 28769783Smsmith * XXX we should probably just fix up the bridge decode and soldier on. 28869783Smsmith */ 28969783Smsmith switch (type) { 29069783Smsmith case SYS_RES_IOPORT: 29190898Simp if (!pcib_is_isa_io(start)) { 29291064Sphk#ifndef PCI_ALLOW_UNSUPPORTED_IO_RANGE 29390898Simp if (start < sc->iobase) 29490898Simp start = sc->iobase; 29590898Simp if (end > sc->iolimit) 29690898Simp end = sc->iolimit; 29790898Simp if (end < start) 29890898Simp start = 0; 29991064Sphk#else 30091064Sphk if (start < sc->iobase) 30191278Simp printf("start (%lx) < sc->iobase (%x)\n", start, sc->iobase); 30291064Sphk if (end > sc->iolimit) 30391278Simp printf("end (%lx) > sc->iolimit (%x)\n", end, sc->iolimit); 30491064Sphk if (end < start) 30591278Simp printf("end (%lx) < start (%lx)\n", end, start); 30691064Sphk#endif 30790898Simp } 30890388Simp if (!pcib_is_isa_io(start) && 30990388Simp ((start < sc->iobase) || (end > sc->iolimit))) { 31069783Smsmith device_printf(dev, "device %s%d requested unsupported I/O range 0x%lx-0x%lx" 31169783Smsmith " (decoding 0x%x-0x%x)\n", 31269783Smsmith device_get_name(child), device_get_unit(child), start, end, 31369783Smsmith sc->iobase, sc->iolimit); 31490388Simp return (NULL); 31569783Smsmith } 31669908Smsmith if (bootverbose) 31769908Smsmith device_printf(sc->dev, "device %s%d requested decoded I/O range 0x%lx-0x%lx\n", 31869908Smsmith device_get_name(child), device_get_unit(child), start, end); 31969783Smsmith break; 32069783Smsmith 32169783Smsmith /* 32269783Smsmith * XXX will have to decide whether the device making the request is asking 32369783Smsmith * for prefetchable memory or not. If it's coming from another bridge 32469783Smsmith * down the line, do we assume not, or ask the bridge to pass in another 32569783Smsmith * flag as the request bubbles up? 32669783Smsmith */ 32769783Smsmith case SYS_RES_MEMORY: 32890898Simp if (!pcib_is_isa_mem(start)) { 32991064Sphk#ifndef PCI_ALLOW_UNSUPPORTED_IO_RANGE 33094573Simp if (start < sc->membase && end >= sc->membase) 33190898Simp start = sc->membase; 33290898Simp if (end > sc->memlimit) 33390898Simp end = sc->memlimit; 33490898Simp if (end < start) 33590898Simp start = 0; 33691064Sphk#else 33791064Sphk if (start < sc->membase && end > sc->membase) 33891278Simp printf("start (%lx) < sc->membase (%x)\n", start, sc->membase); 33991064Sphk if (end > sc->memlimit) 34091278Simp printf("end (%lx) > sc->memlimit (%x)\n", end, sc->memlimit); 34191064Sphk if (end < start) 34291278Simp printf("end (%lx) < start (%lx)\n", end, start); 34391064Sphk#endif 34490898Simp } 34590388Simp if (!pcib_is_isa_mem(start) && 34690388Simp (((start < sc->membase) || (end > sc->memlimit)) && 34790388Simp ((start < sc->pmembase) || (end > sc->pmemlimit)))) { 34890435Simp if (bootverbose) 34990435Simp device_printf(dev, 35090435Simp "device %s%d requested unsupported memory range " 35190435Simp "0x%lx-0x%lx (decoding 0x%x-0x%x, 0x%x-0x%x)\n", 35290435Simp device_get_name(child), device_get_unit(child), start, 35390435Simp end, sc->membase, sc->memlimit, sc->pmembase, 35490435Simp sc->pmemlimit); 35583951Sbrooks#ifndef PCI_ALLOW_UNSUPPORTED_IO_RANGE 35669783Smsmith return(NULL); 35783951Sbrooks#endif 35869783Smsmith } 35969908Smsmith if (bootverbose) 36069908Smsmith device_printf(sc->dev, "device %s%d requested decoded memory range 0x%lx-0x%lx\n", 36169908Smsmith device_get_name(child), device_get_unit(child), start, end); 36269908Smsmith break; 36369908Smsmith 36469783Smsmith default: 36569908Smsmith break; 36669783Smsmith } 36769783Smsmith } 36869908Smsmith 36969783Smsmith /* 37069783Smsmith * Bridge is OK decoding this resource, so pass it up. 37169783Smsmith */ 37269783Smsmith return(bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); 37369783Smsmith} 37469783Smsmith 37569783Smsmith/* 37669783Smsmith * PCIB interface. 37769783Smsmith */ 378102441Sjhbint 37969783Smsmithpcib_maxslots(device_t dev) 38069783Smsmith{ 38169908Smsmith return(PCI_SLOTMAX); 38269783Smsmith} 38369783Smsmith 38469783Smsmith/* 38569783Smsmith * Since we are a child of a PCI bus, its parent must support the pcib interface. 38669783Smsmith */ 387102441Sjhbu_int32_t 38869783Smsmithpcib_read_config(device_t dev, int b, int s, int f, int reg, int width) 38969783Smsmith{ 39069783Smsmith return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); 39169783Smsmith} 39269783Smsmith 393102441Sjhbvoid 39469783Smsmithpcib_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, int width) 39569783Smsmith{ 39669783Smsmith PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); 39769783Smsmith} 39869783Smsmith 39969783Smsmith/* 40069783Smsmith * Route an interrupt across a PCI bridge. 40169783Smsmith */ 40269783Smsmithstatic int 40369783Smsmithpcib_route_interrupt(device_t pcib, device_t dev, int pin) 40469783Smsmith{ 40569783Smsmith device_t bus; 40669783Smsmith int parent_intpin; 40769783Smsmith int intnum; 40869783Smsmith 40969783Smsmith /* 41069783Smsmith * 41169783Smsmith * The PCI standard defines a swizzle of the child-side device/intpin to 41269783Smsmith * the parent-side intpin as follows. 41369783Smsmith * 41469783Smsmith * device = device on child bus 41569783Smsmith * child_intpin = intpin on child bus slot (0-3) 41669783Smsmith * parent_intpin = intpin on parent bus slot (0-3) 41769783Smsmith * 41869783Smsmith * parent_intpin = (device + child_intpin) % 4 41969783Smsmith */ 42069783Smsmith parent_intpin = (pci_get_slot(pcib) + (pin - 1)) % 4; 42169783Smsmith 42269783Smsmith /* 42369783Smsmith * Our parent is a PCI bus. Its parent must export the pcib interface 42469783Smsmith * which includes the ability to route interrupts. 42569783Smsmith */ 42669783Smsmith bus = device_get_parent(pcib); 42769783Smsmith intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1); 42890554Smsmith if (PCI_INTERRUPT_VALID(intnum)) { 429102977Sjhb device_printf(pcib, "slot %d INT%c is routed to irq %d\n", 430102977Sjhb pci_get_slot(dev), 'A' + pin - 1, intnum); 43190554Smsmith } 43269783Smsmith return(intnum); 43369783Smsmith} 434