pci_subr.c revision 144110
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 31119418Sobrien#include <sys/cdefs.h> 32119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/pci/pci_pci.c 144110 2005-03-25 14:18:50Z jhb $"); 33119418Sobrien 3469783Smsmith/* 3569783Smsmith * PCI:PCI bridge support. 3669783Smsmith */ 3769783Smsmith 3869783Smsmith#include <sys/param.h> 3969783Smsmith#include <sys/systm.h> 4069783Smsmith#include <sys/kernel.h> 41129876Sphk#include <sys/module.h> 4269783Smsmith#include <sys/bus.h> 43107546Simp#include <machine/bus.h> 44107546Simp#include <sys/rman.h> 45106844Smdodd#include <sys/sysctl.h> 4669783Smsmith 4769783Smsmith#include <machine/resource.h> 4869783Smsmith 49119285Simp#include <dev/pci/pcivar.h> 50119285Simp#include <dev/pci/pcireg.h> 51119285Simp#include <dev/pci/pcib_private.h> 5269783Smsmith 5369783Smsmith#include "pcib_if.h" 5469783Smsmith 5569783Smsmithstatic int pcib_probe(device_t dev); 5669783Smsmith 5769783Smsmithstatic device_method_t pcib_methods[] = { 5869783Smsmith /* Device interface */ 5969783Smsmith DEVMETHOD(device_probe, pcib_probe), 6069783Smsmith DEVMETHOD(device_attach, pcib_attach), 6169783Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 6269783Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), 6369783Smsmith DEVMETHOD(device_resume, bus_generic_resume), 6469783Smsmith 6569783Smsmith /* Bus interface */ 6669783Smsmith DEVMETHOD(bus_print_child, bus_generic_print_child), 6769783Smsmith DEVMETHOD(bus_read_ivar, pcib_read_ivar), 6869783Smsmith DEVMETHOD(bus_write_ivar, pcib_write_ivar), 6969783Smsmith DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), 7069783Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 7169783Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 7269783Smsmith DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 7369783Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 7469783Smsmith DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 7569783Smsmith 7669783Smsmith /* pcib interface */ 7769783Smsmith DEVMETHOD(pcib_maxslots, pcib_maxslots), 7869783Smsmith DEVMETHOD(pcib_read_config, pcib_read_config), 7969783Smsmith DEVMETHOD(pcib_write_config, pcib_write_config), 8069783Smsmith DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), 8169783Smsmith 8269783Smsmith { 0, 0 } 8369783Smsmith}; 8469783Smsmith 8569783Smsmithstatic driver_t pcib_driver = { 8669783Smsmith "pcib", 8769783Smsmith pcib_methods, 8869783Smsmith sizeof(struct pcib_softc), 8969783Smsmith}; 9069783Smsmith 91102441Sjhbdevclass_t pcib_devclass; 9269783Smsmith 9369783SmsmithDRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); 9469783Smsmith 9569783Smsmith/* 9669783Smsmith * Generic device interface 9769783Smsmith */ 9869783Smsmithstatic int 9969783Smsmithpcib_probe(device_t dev) 10069783Smsmith{ 10169783Smsmith if ((pci_get_class(dev) == PCIC_BRIDGE) && 10269783Smsmith (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { 10369783Smsmith device_set_desc(dev, "PCI-PCI bridge"); 10469783Smsmith return(-10000); 10569783Smsmith } 10669783Smsmith return(ENXIO); 10769783Smsmith} 10869783Smsmith 109102441Sjhbvoid 110102441Sjhbpcib_attach_common(device_t dev) 11169783Smsmith{ 11269783Smsmith struct pcib_softc *sc; 113119266Simp uint8_t iolow; 11469783Smsmith 11569783Smsmith sc = device_get_softc(dev); 11669783Smsmith sc->dev = dev; 11769783Smsmith 11869908Smsmith /* 11969908Smsmith * Get current bridge configuration. 12069908Smsmith */ 12169953Smsmith sc->command = pci_read_config(dev, PCIR_COMMAND, 1); 12269908Smsmith sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); 12369908Smsmith sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); 12469908Smsmith sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); 12569908Smsmith sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); 12669908Smsmith sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); 12769783Smsmith 12869908Smsmith /* 12969908Smsmith * Determine current I/O decode. 13069908Smsmith */ 13169953Smsmith if (sc->command & PCIM_CMD_PORTEN) { 13269953Smsmith iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); 13369953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 13469953Smsmith sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2), 13569953Smsmith pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13669953Smsmith } else { 13769953Smsmith sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13869953Smsmith } 13969908Smsmith 14069953Smsmith iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); 14169953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 14269953Smsmith sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2), 14369953Smsmith pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14469953Smsmith } else { 14569953Smsmith sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14669953Smsmith } 14769908Smsmith } 14869908Smsmith 14969908Smsmith /* 15069908Smsmith * Determine current memory decode. 15169908Smsmith */ 15269953Smsmith if (sc->command & PCIM_CMD_MEMEN) { 15369953Smsmith sc->membase = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2)); 15469953Smsmith sc->memlimit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); 15569953Smsmith sc->pmembase = PCI_PPBMEMBASE((pci_addr_t)pci_read_config(dev, PCIR_PMBASEH_1, 4), 15669953Smsmith pci_read_config(dev, PCIR_PMBASEL_1, 2)); 15769953Smsmith sc->pmemlimit = PCI_PPBMEMLIMIT((pci_addr_t)pci_read_config(dev, PCIR_PMLIMITH_1, 4), 15869953Smsmith pci_read_config(dev, PCIR_PMLIMITL_1, 2)); 15969953Smsmith } 16069908Smsmith 16169908Smsmith /* 16269908Smsmith * Quirk handling. 16369908Smsmith */ 16469908Smsmith switch (pci_get_devid(dev)) { 165124365Simp case 0x12258086: /* Intel 82454KX/GX (Orion) */ 16669908Smsmith { 167119266Simp uint8_t supbus; 16869908Smsmith 16969908Smsmith supbus = pci_read_config(dev, 0x41, 1); 17069908Smsmith if (supbus != 0xff) { 17169908Smsmith sc->secbus = supbus + 1; 17269908Smsmith sc->subbus = supbus + 1; 17369908Smsmith } 174124365Simp break; 17569908Smsmith } 176124365Simp 177124365Simp /* 178124365Simp * The i82380FB mobile docking controller is a PCI-PCI bridge, 179124365Simp * and it is a subtractive bridge. However, the ProgIf is wrong 180124365Simp * so the normal setting of PCIB_SUBTRACTIVE bit doesn't 181124365Simp * happen. There's also a Toshiba bridge that behaves this 182124365Simp * way. 183124365Simp */ 184124365Simp case 0x124b8086: /* Intel 82380FB Mobile */ 185124365Simp case 0x060513d7: /* Toshiba ???? */ 186124365Simp sc->flags |= PCIB_SUBTRACTIVE; 18769908Smsmith break; 18869908Smsmith } 18969908Smsmith 190124365Simp /* 191124365Simp * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, 192124365Simp * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, 193124365Simp * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. 194124365Simp * This means they act as if they were subtractively decoding 195124365Simp * bridges and pass all transactions. Mark them and real ProgIf 1 196124365Simp * parts as subtractive. 197124365Simp */ 198124365Simp if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 || 199124365Simp pci_read_config(dev, PCIR_PROGIF, 1) == 1) 200124365Simp sc->flags |= PCIB_SUBTRACTIVE; 201124365Simp 20269783Smsmith if (bootverbose) { 20369783Smsmith device_printf(dev, " secondary bus %d\n", sc->secbus); 20469783Smsmith device_printf(dev, " subordinate bus %d\n", sc->subbus); 20569783Smsmith device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit); 20669783Smsmith device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit); 20769783Smsmith device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit); 208124365Simp if (sc->flags & PCIB_SUBTRACTIVE) 209124365Simp device_printf(dev, " Subtractively decoded bridge.\n"); 21069783Smsmith } 21169783Smsmith 21269783Smsmith /* 21369783Smsmith * XXX If the secondary bus number is zero, we should assign a bus number 21469783Smsmith * since the BIOS hasn't, then initialise the bridge. 21569783Smsmith */ 21669783Smsmith 21769783Smsmith /* 21869783Smsmith * XXX If the subordinate bus number is less than the secondary bus number, 21969783Smsmith * we should pick a better value. One sensible alternative would be to 22069783Smsmith * pick 255; the only tradeoff here is that configuration transactions 22169783Smsmith * would be more widely routed than absolutely necessary. 22269783Smsmith */ 223102441Sjhb} 22469783Smsmith 225103042Sjhbint 226102441Sjhbpcib_attach(device_t dev) 227102441Sjhb{ 228102441Sjhb struct pcib_softc *sc; 229102441Sjhb device_t child; 230102441Sjhb 231102441Sjhb pcib_attach_common(dev); 232102441Sjhb sc = device_get_softc(dev); 23369783Smsmith if (sc->secbus != 0) { 234103016Sjhb child = device_add_child(dev, "pci", sc->secbus); 23569783Smsmith if (child != NULL) 23669783Smsmith return(bus_generic_attach(dev)); 23769783Smsmith } 23869783Smsmith 23969783Smsmith /* no secondary bus; we should have fixed this */ 24069783Smsmith return(0); 24169783Smsmith} 24269783Smsmith 243102441Sjhbint 24469783Smsmithpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 24569783Smsmith{ 24669783Smsmith struct pcib_softc *sc = device_get_softc(dev); 24769783Smsmith 24869783Smsmith switch (which) { 24969783Smsmith case PCIB_IVAR_BUS: 25069783Smsmith *result = sc->secbus; 25169783Smsmith return(0); 25269783Smsmith } 25369783Smsmith return(ENOENT); 25469783Smsmith} 25569783Smsmith 256102441Sjhbint 25769783Smsmithpcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 25869783Smsmith{ 25969783Smsmith struct pcib_softc *sc = device_get_softc(dev); 26069783Smsmith 26169783Smsmith switch (which) { 26269783Smsmith case PCIB_IVAR_BUS: 26369783Smsmith sc->secbus = value; 26469783Smsmith break; 26569783Smsmith } 26669783Smsmith return(ENOENT); 26769783Smsmith} 26869783Smsmith 26969783Smsmith/* 270107546Simp * Is the prefetch window open (eg, can we allocate memory in it?) 271107546Simp */ 272107546Simpstatic int 273107546Simppcib_is_prefetch_open(struct pcib_softc *sc) 274107546Simp{ 275124365Simp return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit); 276107546Simp} 277107546Simp 278107546Simp/* 279107546Simp * Is the nonprefetch window open (eg, can we allocate memory in it?) 280107546Simp */ 281107546Simpstatic int 282107546Simppcib_is_nonprefetch_open(struct pcib_softc *sc) 283107546Simp{ 284124365Simp return (sc->membase > 0 && sc->membase < sc->memlimit); 285107546Simp} 286107546Simp 287107546Simp/* 288107546Simp * Is the io window open (eg, can we allocate ports in it?) 289107546Simp */ 290107546Simpstatic int 291107546Simppcib_is_io_open(struct pcib_softc *sc) 292107546Simp{ 293124365Simp return (sc->iobase > 0 && sc->iobase < sc->iolimit); 294107546Simp} 295107546Simp 296107546Simp/* 29769783Smsmith * We have to trap resource allocation requests and ensure that the bridge 29869783Smsmith * is set up to, or capable of handling them. 29969783Smsmith */ 300102441Sjhbstruct resource * 30169783Smsmithpcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 302142051Simp u_long start, u_long end, u_long count, u_int flags) 30369783Smsmith{ 304124365Simp struct pcib_softc *sc = device_get_softc(dev); 305124365Simp int ok; 30669783Smsmith 30769783Smsmith /* 30869783Smsmith * Fail the allocation for this range if it's not supported. 30969783Smsmith */ 31069783Smsmith switch (type) { 31169783Smsmith case SYS_RES_IOPORT: 312107546Simp ok = 0; 313124365Simp if (!pcib_is_io_open(sc)) 314124365Simp break; 315124365Simp ok = (start >= sc->iobase && end <= sc->iolimit); 316124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 317124365Simp if (!ok) { 318124365Simp if (start < sc->iobase) 319124365Simp start = sc->iobase; 320124365Simp if (end > sc->iolimit) 321124365Simp end = sc->iolimit; 322142051Simp if (start < end) 323142051Simp ok = 1; 324124365Simp } 325106844Smdodd } else { 326124365Simp ok = 1; 327128058Simp#if 1 328124365Simp if (start < sc->iobase && end > sc->iolimit) { 329124365Simp start = sc->iobase; 330124365Simp end = sc->iolimit; 331124365Simp } 332124641Simp#endif 333106844Smdodd } 334124365Simp if (end < start) { 335142051Simp device_printf(dev, "ioport: end (%lx) < start (%lx)\n", 336142051Simp end, start); 337124365Simp start = 0; 338124365Simp end = 0; 339124365Simp ok = 0; 340124365Simp } 341124365Simp if (!ok) { 342142051Simp device_printf(dev, "%s requested unsupported I/O " 343124365Simp "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n", 344124365Simp device_get_nameunit(child), start, end, 345124365Simp sc->iobase, sc->iolimit); 346124365Simp return (NULL); 347124365Simp } 348124365Simp if (bootverbose) 349142051Simp device_printf(dev, 350142051Simp "%s requested I/O range 0x%lx-0x%lx: in range\n", 351124365Simp device_get_nameunit(child), start, end); 352124365Simp break; 35369783Smsmith 35469783Smsmith case SYS_RES_MEMORY: 355107546Simp ok = 0; 356107546Simp if (pcib_is_nonprefetch_open(sc)) 357124365Simp ok = ok || (start >= sc->membase && end <= sc->memlimit); 358107546Simp if (pcib_is_prefetch_open(sc)) 359124365Simp ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit); 360124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 361124365Simp if (!ok) { 362124365Simp ok = 1; 363124365Simp if (flags & RF_PREFETCHABLE) { 364124365Simp if (pcib_is_prefetch_open(sc)) { 365124365Simp if (start < sc->pmembase) 366124365Simp start = sc->pmembase; 367124365Simp if (end > sc->pmemlimit) 368124365Simp end = sc->pmemlimit; 369124365Simp } else { 370124365Simp ok = 0; 371124365Simp } 372124365Simp } else { /* non-prefetchable */ 373124365Simp if (pcib_is_nonprefetch_open(sc)) { 374124365Simp if (start < sc->membase) 375124365Simp start = sc->membase; 376124365Simp if (end > sc->memlimit) 377124365Simp end = sc->memlimit; 378124365Simp } else { 379124365Simp ok = 0; 380124365Simp } 381124365Simp } 382107546Simp } 383107546Simp } else if (!ok) { 384124365Simp ok = 1; /* subtractive bridge: always ok */ 385128058Simp#if 1 386124365Simp if (pcib_is_nonprefetch_open(sc)) { 387124365Simp if (start < sc->membase && end > sc->memlimit) { 388124365Simp start = sc->membase; 389124365Simp end = sc->memlimit; 390124365Simp } 391124365Simp } 392124365Simp if (pcib_is_prefetch_open(sc)) { 393124365Simp if (start < sc->pmembase && end > sc->pmemlimit) { 394124365Simp start = sc->pmembase; 395124365Simp end = sc->pmemlimit; 396124365Simp } 397124365Simp } 398124641Simp#endif 399106844Smdodd } 400124365Simp if (end < start) { 401142051Simp device_printf(dev, "memory: end (%lx) < start (%lx)\n", 402142051Simp end, start); 403124365Simp start = 0; 404124365Simp end = 0; 405124365Simp ok = 0; 406124365Simp } 407124365Simp if (!ok && bootverbose) 408124365Simp device_printf(dev, 409142051Simp "%s requested unsupported memory range " 410124365Simp "0x%lx-0x%lx (decoding 0x%x-0x%x, 0x%x-0x%x)\n", 411124365Simp device_get_nameunit(child), start, end, 412124365Simp sc->membase, sc->memlimit, sc->pmembase, 413124365Simp sc->pmemlimit); 414124365Simp if (!ok) 415124365Simp return (NULL); 416124365Simp if (bootverbose) 417142051Simp device_printf(dev,"%s requested memory range " 418142051Simp "0x%lx-0x%lx: good\n", 419124365Simp device_get_nameunit(child), start, end); 420124365Simp break; 42169908Smsmith 42269783Smsmith default: 423124365Simp break; 42469783Smsmith } 425124365Simp /* 426124365Simp * Bridge is OK decoding this resource, so pass it up. 427124365Simp */ 428142051Simp return (bus_generic_alloc_resource(dev, child, type, rid, start, end, 429142051Simp count, flags)); 43069783Smsmith} 43169783Smsmith 43269783Smsmith/* 43369783Smsmith * PCIB interface. 43469783Smsmith */ 435102441Sjhbint 43669783Smsmithpcib_maxslots(device_t dev) 43769783Smsmith{ 43869908Smsmith return(PCI_SLOTMAX); 43969783Smsmith} 44069783Smsmith 44169783Smsmith/* 44269783Smsmith * Since we are a child of a PCI bus, its parent must support the pcib interface. 44369783Smsmith */ 444119266Simpuint32_t 44569783Smsmithpcib_read_config(device_t dev, int b, int s, int f, int reg, int width) 44669783Smsmith{ 44769783Smsmith return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); 44869783Smsmith} 44969783Smsmith 450102441Sjhbvoid 451119266Simppcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width) 45269783Smsmith{ 45369783Smsmith PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); 45469783Smsmith} 45569783Smsmith 45669783Smsmith/* 45769783Smsmith * Route an interrupt across a PCI bridge. 45869783Smsmith */ 459109229Sbennoint 46069783Smsmithpcib_route_interrupt(device_t pcib, device_t dev, int pin) 46169783Smsmith{ 46269783Smsmith device_t bus; 46369783Smsmith int parent_intpin; 46469783Smsmith int intnum; 46569783Smsmith 46669783Smsmith /* 46769783Smsmith * 46869783Smsmith * The PCI standard defines a swizzle of the child-side device/intpin to 46969783Smsmith * the parent-side intpin as follows. 47069783Smsmith * 47169783Smsmith * device = device on child bus 47269783Smsmith * child_intpin = intpin on child bus slot (0-3) 47369783Smsmith * parent_intpin = intpin on parent bus slot (0-3) 47469783Smsmith * 47569783Smsmith * parent_intpin = (device + child_intpin) % 4 47669783Smsmith */ 477115234Sticso parent_intpin = (pci_get_slot(dev) + (pin - 1)) % 4; 47869783Smsmith 47969783Smsmith /* 48069783Smsmith * Our parent is a PCI bus. Its parent must export the pcib interface 48169783Smsmith * which includes the ability to route interrupts. 48269783Smsmith */ 48369783Smsmith bus = device_get_parent(pcib); 48469783Smsmith intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1); 485131398Sjhb if (PCI_INTERRUPT_VALID(intnum) && bootverbose) { 486102977Sjhb device_printf(pcib, "slot %d INT%c is routed to irq %d\n", 487102977Sjhb pci_get_slot(dev), 'A' + pin - 1, intnum); 48890554Smsmith } 48969783Smsmith return(intnum); 49069783Smsmith} 491107172Sjhb 492107172Sjhb/* 493107172Sjhb * Try to read the bus number of a host-PCI bridge using appropriate config 494107172Sjhb * registers. 495107172Sjhb */ 496107172Sjhbint 497107172Sjhbhost_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, 498119266Simp uint8_t *busnum) 499107172Sjhb{ 500119266Simp uint32_t id; 501107172Sjhb 502107172Sjhb id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); 503107248Sjhb if (id == 0xffffffff) 504107172Sjhb return (0); 505107172Sjhb 506107172Sjhb switch (id) { 507107172Sjhb case 0x12258086: 508107172Sjhb /* Intel 824?? */ 509107172Sjhb /* XXX This is a guess */ 510107172Sjhb /* *busnum = read_config(bus, slot, func, 0x41, 1); */ 511107172Sjhb *busnum = bus; 512107172Sjhb break; 513107172Sjhb case 0x84c48086: 514107172Sjhb /* Intel 82454KX/GX (Orion) */ 515107172Sjhb *busnum = read_config(bus, slot, func, 0x4a, 1); 516107172Sjhb break; 517107172Sjhb case 0x84ca8086: 518107172Sjhb /* 519107172Sjhb * For the 450nx chipset, there is a whole bundle of 520107172Sjhb * things pretending to be host bridges. The MIOC will 521107172Sjhb * be seen first and isn't really a pci bridge (the 522107172Sjhb * actual busses are attached to the PXB's). We need to 523107172Sjhb * read the registers of the MIOC to figure out the 524107172Sjhb * bus numbers for the PXB channels. 525107172Sjhb * 526107172Sjhb * Since the MIOC doesn't have a pci bus attached, we 527107172Sjhb * pretend it wasn't there. 528107172Sjhb */ 529107172Sjhb return (0); 530107172Sjhb case 0x84cb8086: 531107172Sjhb switch (slot) { 532107172Sjhb case 0x12: 533107172Sjhb /* Intel 82454NX PXB#0, Bus#A */ 534107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd0, 1); 535107172Sjhb break; 536107172Sjhb case 0x13: 537107172Sjhb /* Intel 82454NX PXB#0, Bus#B */ 538107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; 539107172Sjhb break; 540107172Sjhb case 0x14: 541107172Sjhb /* Intel 82454NX PXB#1, Bus#A */ 542107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd3, 1); 543107172Sjhb break; 544107172Sjhb case 0x15: 545107172Sjhb /* Intel 82454NX PXB#1, Bus#B */ 546107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; 547107172Sjhb break; 548107172Sjhb } 549107172Sjhb break; 550107172Sjhb 551107172Sjhb /* ServerWorks -- vendor 0x1166 */ 552107172Sjhb case 0x00051166: 553107172Sjhb case 0x00061166: 554107172Sjhb case 0x00081166: 555107172Sjhb case 0x00091166: 556107172Sjhb case 0x00101166: 557107172Sjhb case 0x00111166: 558107172Sjhb case 0x00171166: 559107172Sjhb case 0x01011166: 560107172Sjhb case 0x010f1014: 561107172Sjhb case 0x02011166: 562107172Sjhb case 0x03021014: 563107172Sjhb *busnum = read_config(bus, slot, func, 0x44, 1); 564107172Sjhb break; 565144110Sjhb 566144110Sjhb /* Compaq/HP -- vendor 0x0e11 */ 567144110Sjhb case 0x60100e11: 568144110Sjhb *busnum = read_config(bus, slot, func, 0xc8, 1); 569144110Sjhb break; 570107172Sjhb default: 571107172Sjhb /* Don't know how to read bus number. */ 572107172Sjhb return 0; 573107172Sjhb } 574107172Sjhb 575107172Sjhb return 1; 576107172Sjhb} 577