pci_subr.c revision 157949
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 157949 2006-04-21 19:35:03Z jkim $"); 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), 61145661Simp DEVMETHOD(device_detach, bus_generic_detach), 6269783Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 6369783Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), 6469783Smsmith DEVMETHOD(device_resume, bus_generic_resume), 6569783Smsmith 6669783Smsmith /* Bus interface */ 6769783Smsmith DEVMETHOD(bus_print_child, bus_generic_print_child), 6869783Smsmith DEVMETHOD(bus_read_ivar, pcib_read_ivar), 6969783Smsmith DEVMETHOD(bus_write_ivar, pcib_write_ivar), 7069783Smsmith DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), 7169783Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 7269783Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 7369783Smsmith DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 7469783Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 7569783Smsmith DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 7669783Smsmith 7769783Smsmith /* pcib interface */ 7869783Smsmith DEVMETHOD(pcib_maxslots, pcib_maxslots), 7969783Smsmith DEVMETHOD(pcib_read_config, pcib_read_config), 8069783Smsmith DEVMETHOD(pcib_write_config, pcib_write_config), 8169783Smsmith DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), 8269783Smsmith 8369783Smsmith { 0, 0 } 8469783Smsmith}; 8569783Smsmith 86154079Sjhbstatic devclass_t pcib_devclass; 8769783Smsmith 88154079SjhbDEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); 8969783SmsmithDRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); 9069783Smsmith 9169783Smsmith/* 9269783Smsmith * Generic device interface 9369783Smsmith */ 9469783Smsmithstatic int 9569783Smsmithpcib_probe(device_t dev) 9669783Smsmith{ 9769783Smsmith if ((pci_get_class(dev) == PCIC_BRIDGE) && 9869783Smsmith (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { 9969783Smsmith device_set_desc(dev, "PCI-PCI bridge"); 10069783Smsmith return(-10000); 10169783Smsmith } 10269783Smsmith return(ENXIO); 10369783Smsmith} 10469783Smsmith 105102441Sjhbvoid 106102441Sjhbpcib_attach_common(device_t dev) 10769783Smsmith{ 10869783Smsmith struct pcib_softc *sc; 109119266Simp uint8_t iolow; 11069783Smsmith 11169783Smsmith sc = device_get_softc(dev); 11269783Smsmith sc->dev = dev; 11369783Smsmith 11469908Smsmith /* 11569908Smsmith * Get current bridge configuration. 11669908Smsmith */ 11769953Smsmith sc->command = pci_read_config(dev, PCIR_COMMAND, 1); 11869908Smsmith sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); 11969908Smsmith sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); 12069908Smsmith sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); 12169908Smsmith sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); 12269908Smsmith sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); 12369783Smsmith 12469908Smsmith /* 12569908Smsmith * Determine current I/O decode. 12669908Smsmith */ 12769953Smsmith if (sc->command & PCIM_CMD_PORTEN) { 12869953Smsmith iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); 12969953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 13069953Smsmith sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2), 13169953Smsmith pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13269953Smsmith } else { 13369953Smsmith sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1)); 13469953Smsmith } 13569908Smsmith 13669953Smsmith iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); 13769953Smsmith if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { 13869953Smsmith sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2), 13969953Smsmith pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14069953Smsmith } else { 14169953Smsmith sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1)); 14269953Smsmith } 14369908Smsmith } 14469908Smsmith 14569908Smsmith /* 14669908Smsmith * Determine current memory decode. 14769908Smsmith */ 14869953Smsmith if (sc->command & PCIM_CMD_MEMEN) { 14969953Smsmith sc->membase = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2)); 15069953Smsmith sc->memlimit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); 15169953Smsmith sc->pmembase = PCI_PPBMEMBASE((pci_addr_t)pci_read_config(dev, PCIR_PMBASEH_1, 4), 15269953Smsmith pci_read_config(dev, PCIR_PMBASEL_1, 2)); 15369953Smsmith sc->pmemlimit = PCI_PPBMEMLIMIT((pci_addr_t)pci_read_config(dev, PCIR_PMLIMITH_1, 4), 15469953Smsmith pci_read_config(dev, PCIR_PMLIMITL_1, 2)); 15569953Smsmith } 15669908Smsmith 15769908Smsmith /* 15869908Smsmith * Quirk handling. 15969908Smsmith */ 16069908Smsmith switch (pci_get_devid(dev)) { 161124365Simp case 0x12258086: /* Intel 82454KX/GX (Orion) */ 16269908Smsmith { 163119266Simp uint8_t supbus; 16469908Smsmith 16569908Smsmith supbus = pci_read_config(dev, 0x41, 1); 16669908Smsmith if (supbus != 0xff) { 16769908Smsmith sc->secbus = supbus + 1; 16869908Smsmith sc->subbus = supbus + 1; 16969908Smsmith } 170124365Simp break; 17169908Smsmith } 172124365Simp 173124365Simp /* 174124365Simp * The i82380FB mobile docking controller is a PCI-PCI bridge, 175124365Simp * and it is a subtractive bridge. However, the ProgIf is wrong 176124365Simp * so the normal setting of PCIB_SUBTRACTIVE bit doesn't 177124365Simp * happen. There's also a Toshiba bridge that behaves this 178124365Simp * way. 179124365Simp */ 180124365Simp case 0x124b8086: /* Intel 82380FB Mobile */ 181124365Simp case 0x060513d7: /* Toshiba ???? */ 182124365Simp sc->flags |= PCIB_SUBTRACTIVE; 18369908Smsmith break; 184149521Sjkim 185149521Sjkim /* Compaq R3000 BIOS sets wrong subordinate bus number. */ 186149521Sjkim case 0x00dd10de: 187149521Sjkim { 188149521Sjkim char *cp; 189149521Sjkim 190157949Sjkim if ((cp = getenv("smbios.planar.maker")) == NULL) 191149521Sjkim break; 192157949Sjkim if (strncmp(cp, "Compal", 6) != 0) { 193157949Sjkim freeenv(cp); 194149521Sjkim break; 195157949Sjkim } 196157949Sjkim freeenv(cp); 197157949Sjkim if ((cp = getenv("smbios.planar.product")) == NULL) 198157949Sjkim break; 199157949Sjkim if (strncmp(cp, "08A0", 4) != 0) { 200157949Sjkim freeenv(cp); 201157949Sjkim break; 202157949Sjkim } 203157949Sjkim freeenv(cp); 204149521Sjkim if (sc->subbus < 0xa) { 205149521Sjkim pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1); 206149521Sjkim sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); 207149521Sjkim } 208149521Sjkim break; 209149521Sjkim } 21069908Smsmith } 21169908Smsmith 212124365Simp /* 213124365Simp * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, 214124365Simp * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, 215124365Simp * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. 216124365Simp * This means they act as if they were subtractively decoding 217124365Simp * bridges and pass all transactions. Mark them and real ProgIf 1 218124365Simp * parts as subtractive. 219124365Simp */ 220124365Simp if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 || 221124365Simp pci_read_config(dev, PCIR_PROGIF, 1) == 1) 222124365Simp sc->flags |= PCIB_SUBTRACTIVE; 223124365Simp 22469783Smsmith if (bootverbose) { 22569783Smsmith device_printf(dev, " secondary bus %d\n", sc->secbus); 22669783Smsmith device_printf(dev, " subordinate bus %d\n", sc->subbus); 22769783Smsmith device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit); 22869783Smsmith device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit); 22969783Smsmith device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit); 230124365Simp if (sc->flags & PCIB_SUBTRACTIVE) 231124365Simp device_printf(dev, " Subtractively decoded bridge.\n"); 23269783Smsmith } 23369783Smsmith 23469783Smsmith /* 23569783Smsmith * XXX If the secondary bus number is zero, we should assign a bus number 23669783Smsmith * since the BIOS hasn't, then initialise the bridge. 23769783Smsmith */ 23869783Smsmith 23969783Smsmith /* 24069783Smsmith * XXX If the subordinate bus number is less than the secondary bus number, 24169783Smsmith * we should pick a better value. One sensible alternative would be to 24269783Smsmith * pick 255; the only tradeoff here is that configuration transactions 24369783Smsmith * would be more widely routed than absolutely necessary. 24469783Smsmith */ 245102441Sjhb} 24669783Smsmith 247103042Sjhbint 248102441Sjhbpcib_attach(device_t dev) 249102441Sjhb{ 250102441Sjhb struct pcib_softc *sc; 251102441Sjhb device_t child; 252102441Sjhb 253102441Sjhb pcib_attach_common(dev); 254102441Sjhb sc = device_get_softc(dev); 25569783Smsmith if (sc->secbus != 0) { 256103016Sjhb child = device_add_child(dev, "pci", sc->secbus); 25769783Smsmith if (child != NULL) 25869783Smsmith return(bus_generic_attach(dev)); 25969783Smsmith } 26069783Smsmith 26169783Smsmith /* no secondary bus; we should have fixed this */ 26269783Smsmith return(0); 26369783Smsmith} 26469783Smsmith 265102441Sjhbint 26669783Smsmithpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 26769783Smsmith{ 26869783Smsmith struct pcib_softc *sc = device_get_softc(dev); 26969783Smsmith 27069783Smsmith switch (which) { 27169783Smsmith case PCIB_IVAR_BUS: 27269783Smsmith *result = sc->secbus; 27369783Smsmith return(0); 27469783Smsmith } 27569783Smsmith return(ENOENT); 27669783Smsmith} 27769783Smsmith 278102441Sjhbint 27969783Smsmithpcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 28069783Smsmith{ 28169783Smsmith struct pcib_softc *sc = device_get_softc(dev); 28269783Smsmith 28369783Smsmith switch (which) { 28469783Smsmith case PCIB_IVAR_BUS: 28569783Smsmith sc->secbus = value; 28669783Smsmith break; 28769783Smsmith } 28869783Smsmith return(ENOENT); 28969783Smsmith} 29069783Smsmith 29169783Smsmith/* 292107546Simp * Is the prefetch window open (eg, can we allocate memory in it?) 293107546Simp */ 294107546Simpstatic int 295107546Simppcib_is_prefetch_open(struct pcib_softc *sc) 296107546Simp{ 297124365Simp return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit); 298107546Simp} 299107546Simp 300107546Simp/* 301107546Simp * Is the nonprefetch window open (eg, can we allocate memory in it?) 302107546Simp */ 303107546Simpstatic int 304107546Simppcib_is_nonprefetch_open(struct pcib_softc *sc) 305107546Simp{ 306124365Simp return (sc->membase > 0 && sc->membase < sc->memlimit); 307107546Simp} 308107546Simp 309107546Simp/* 310107546Simp * Is the io window open (eg, can we allocate ports in it?) 311107546Simp */ 312107546Simpstatic int 313107546Simppcib_is_io_open(struct pcib_softc *sc) 314107546Simp{ 315124365Simp return (sc->iobase > 0 && sc->iobase < sc->iolimit); 316107546Simp} 317107546Simp 318107546Simp/* 31969783Smsmith * We have to trap resource allocation requests and ensure that the bridge 32069783Smsmith * is set up to, or capable of handling them. 32169783Smsmith */ 322102441Sjhbstruct resource * 32369783Smsmithpcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 324142051Simp u_long start, u_long end, u_long count, u_int flags) 32569783Smsmith{ 326124365Simp struct pcib_softc *sc = device_get_softc(dev); 327124365Simp int ok; 32869783Smsmith 32969783Smsmith /* 33069783Smsmith * Fail the allocation for this range if it's not supported. 33169783Smsmith */ 33269783Smsmith switch (type) { 33369783Smsmith case SYS_RES_IOPORT: 334107546Simp ok = 0; 335124365Simp if (!pcib_is_io_open(sc)) 336124365Simp break; 337124365Simp ok = (start >= sc->iobase && end <= sc->iolimit); 338145652Smarcel 339145652Smarcel /* 340145652Smarcel * Make sure we allow access to VGA I/O addresses when the 341145652Smarcel * bridge has the "VGA Enable" bit set. 342145652Smarcel */ 343145652Smarcel if (!ok && pci_is_vga_ioport_range(start, end)) 344145652Smarcel ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; 345145652Smarcel 346124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 347124365Simp if (!ok) { 348124365Simp if (start < sc->iobase) 349124365Simp start = sc->iobase; 350124365Simp if (end > sc->iolimit) 351124365Simp end = sc->iolimit; 352142051Simp if (start < end) 353142051Simp ok = 1; 354124365Simp } 355106844Smdodd } else { 356124365Simp ok = 1; 357128058Simp#if 1 358124365Simp if (start < sc->iobase && end > sc->iolimit) { 359124365Simp start = sc->iobase; 360124365Simp end = sc->iolimit; 361124365Simp } 362124641Simp#endif 363106844Smdodd } 364124365Simp if (end < start) { 365142051Simp device_printf(dev, "ioport: end (%lx) < start (%lx)\n", 366142051Simp end, start); 367124365Simp start = 0; 368124365Simp end = 0; 369124365Simp ok = 0; 370124365Simp } 371124365Simp if (!ok) { 372142051Simp device_printf(dev, "%s requested unsupported I/O " 373124365Simp "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n", 374124365Simp device_get_nameunit(child), start, end, 375124365Simp sc->iobase, sc->iolimit); 376124365Simp return (NULL); 377124365Simp } 378124365Simp if (bootverbose) 379142051Simp device_printf(dev, 380142051Simp "%s requested I/O range 0x%lx-0x%lx: in range\n", 381124365Simp device_get_nameunit(child), start, end); 382124365Simp break; 38369783Smsmith 38469783Smsmith case SYS_RES_MEMORY: 385107546Simp ok = 0; 386107546Simp if (pcib_is_nonprefetch_open(sc)) 387124365Simp ok = ok || (start >= sc->membase && end <= sc->memlimit); 388107546Simp if (pcib_is_prefetch_open(sc)) 389124365Simp ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit); 390145652Smarcel 391145652Smarcel /* 392145652Smarcel * Make sure we allow access to VGA memory addresses when the 393145652Smarcel * bridge has the "VGA Enable" bit set. 394145652Smarcel */ 395145652Smarcel if (!ok && pci_is_vga_memory_range(start, end)) 396145652Smarcel ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; 397145652Smarcel 398124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 399124365Simp if (!ok) { 400124365Simp ok = 1; 401124365Simp if (flags & RF_PREFETCHABLE) { 402124365Simp if (pcib_is_prefetch_open(sc)) { 403124365Simp if (start < sc->pmembase) 404124365Simp start = sc->pmembase; 405124365Simp if (end > sc->pmemlimit) 406124365Simp end = sc->pmemlimit; 407124365Simp } else { 408124365Simp ok = 0; 409124365Simp } 410124365Simp } else { /* non-prefetchable */ 411124365Simp if (pcib_is_nonprefetch_open(sc)) { 412124365Simp if (start < sc->membase) 413124365Simp start = sc->membase; 414124365Simp if (end > sc->memlimit) 415124365Simp end = sc->memlimit; 416124365Simp } else { 417124365Simp ok = 0; 418124365Simp } 419124365Simp } 420107546Simp } 421107546Simp } else if (!ok) { 422124365Simp ok = 1; /* subtractive bridge: always ok */ 423128058Simp#if 1 424124365Simp if (pcib_is_nonprefetch_open(sc)) { 425124365Simp if (start < sc->membase && end > sc->memlimit) { 426124365Simp start = sc->membase; 427124365Simp end = sc->memlimit; 428124365Simp } 429124365Simp } 430124365Simp if (pcib_is_prefetch_open(sc)) { 431124365Simp if (start < sc->pmembase && end > sc->pmemlimit) { 432124365Simp start = sc->pmembase; 433124365Simp end = sc->pmemlimit; 434124365Simp } 435124365Simp } 436124641Simp#endif 437106844Smdodd } 438124365Simp if (end < start) { 439142051Simp device_printf(dev, "memory: end (%lx) < start (%lx)\n", 440142051Simp end, start); 441124365Simp start = 0; 442124365Simp end = 0; 443124365Simp ok = 0; 444124365Simp } 445124365Simp if (!ok && bootverbose) 446124365Simp device_printf(dev, 447142051Simp "%s requested unsupported memory range " 448124365Simp "0x%lx-0x%lx (decoding 0x%x-0x%x, 0x%x-0x%x)\n", 449124365Simp device_get_nameunit(child), start, end, 450124365Simp sc->membase, sc->memlimit, sc->pmembase, 451124365Simp sc->pmemlimit); 452124365Simp if (!ok) 453124365Simp return (NULL); 454124365Simp if (bootverbose) 455142051Simp device_printf(dev,"%s requested memory range " 456142051Simp "0x%lx-0x%lx: good\n", 457124365Simp device_get_nameunit(child), start, end); 458124365Simp break; 45969908Smsmith 46069783Smsmith default: 461124365Simp break; 46269783Smsmith } 463124365Simp /* 464124365Simp * Bridge is OK decoding this resource, so pass it up. 465124365Simp */ 466142051Simp return (bus_generic_alloc_resource(dev, child, type, rid, start, end, 467142051Simp count, flags)); 46869783Smsmith} 46969783Smsmith 47069783Smsmith/* 47169783Smsmith * PCIB interface. 47269783Smsmith */ 473102441Sjhbint 47469783Smsmithpcib_maxslots(device_t dev) 47569783Smsmith{ 47669908Smsmith return(PCI_SLOTMAX); 47769783Smsmith} 47869783Smsmith 47969783Smsmith/* 48069783Smsmith * Since we are a child of a PCI bus, its parent must support the pcib interface. 48169783Smsmith */ 482119266Simpuint32_t 48369783Smsmithpcib_read_config(device_t dev, int b, int s, int f, int reg, int width) 48469783Smsmith{ 48569783Smsmith return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); 48669783Smsmith} 48769783Smsmith 488102441Sjhbvoid 489119266Simppcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width) 49069783Smsmith{ 49169783Smsmith PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); 49269783Smsmith} 49369783Smsmith 49469783Smsmith/* 49569783Smsmith * Route an interrupt across a PCI bridge. 49669783Smsmith */ 497109229Sbennoint 49869783Smsmithpcib_route_interrupt(device_t pcib, device_t dev, int pin) 49969783Smsmith{ 50069783Smsmith device_t bus; 50169783Smsmith int parent_intpin; 50269783Smsmith int intnum; 50369783Smsmith 50469783Smsmith /* 50569783Smsmith * 50669783Smsmith * The PCI standard defines a swizzle of the child-side device/intpin to 50769783Smsmith * the parent-side intpin as follows. 50869783Smsmith * 50969783Smsmith * device = device on child bus 51069783Smsmith * child_intpin = intpin on child bus slot (0-3) 51169783Smsmith * parent_intpin = intpin on parent bus slot (0-3) 51269783Smsmith * 51369783Smsmith * parent_intpin = (device + child_intpin) % 4 51469783Smsmith */ 515115234Sticso parent_intpin = (pci_get_slot(dev) + (pin - 1)) % 4; 51669783Smsmith 51769783Smsmith /* 51869783Smsmith * Our parent is a PCI bus. Its parent must export the pcib interface 51969783Smsmith * which includes the ability to route interrupts. 52069783Smsmith */ 52169783Smsmith bus = device_get_parent(pcib); 52269783Smsmith intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1); 523131398Sjhb if (PCI_INTERRUPT_VALID(intnum) && bootverbose) { 524102977Sjhb device_printf(pcib, "slot %d INT%c is routed to irq %d\n", 525102977Sjhb pci_get_slot(dev), 'A' + pin - 1, intnum); 52690554Smsmith } 52769783Smsmith return(intnum); 52869783Smsmith} 529107172Sjhb 530107172Sjhb/* 531107172Sjhb * Try to read the bus number of a host-PCI bridge using appropriate config 532107172Sjhb * registers. 533107172Sjhb */ 534107172Sjhbint 535107172Sjhbhost_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, 536119266Simp uint8_t *busnum) 537107172Sjhb{ 538119266Simp uint32_t id; 539107172Sjhb 540107172Sjhb id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); 541107248Sjhb if (id == 0xffffffff) 542107172Sjhb return (0); 543107172Sjhb 544107172Sjhb switch (id) { 545107172Sjhb case 0x12258086: 546107172Sjhb /* Intel 824?? */ 547107172Sjhb /* XXX This is a guess */ 548107172Sjhb /* *busnum = read_config(bus, slot, func, 0x41, 1); */ 549107172Sjhb *busnum = bus; 550107172Sjhb break; 551107172Sjhb case 0x84c48086: 552107172Sjhb /* Intel 82454KX/GX (Orion) */ 553107172Sjhb *busnum = read_config(bus, slot, func, 0x4a, 1); 554107172Sjhb break; 555107172Sjhb case 0x84ca8086: 556107172Sjhb /* 557107172Sjhb * For the 450nx chipset, there is a whole bundle of 558107172Sjhb * things pretending to be host bridges. The MIOC will 559107172Sjhb * be seen first and isn't really a pci bridge (the 560107172Sjhb * actual busses are attached to the PXB's). We need to 561107172Sjhb * read the registers of the MIOC to figure out the 562107172Sjhb * bus numbers for the PXB channels. 563107172Sjhb * 564107172Sjhb * Since the MIOC doesn't have a pci bus attached, we 565107172Sjhb * pretend it wasn't there. 566107172Sjhb */ 567107172Sjhb return (0); 568107172Sjhb case 0x84cb8086: 569107172Sjhb switch (slot) { 570107172Sjhb case 0x12: 571107172Sjhb /* Intel 82454NX PXB#0, Bus#A */ 572107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd0, 1); 573107172Sjhb break; 574107172Sjhb case 0x13: 575107172Sjhb /* Intel 82454NX PXB#0, Bus#B */ 576107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; 577107172Sjhb break; 578107172Sjhb case 0x14: 579107172Sjhb /* Intel 82454NX PXB#1, Bus#A */ 580107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd3, 1); 581107172Sjhb break; 582107172Sjhb case 0x15: 583107172Sjhb /* Intel 82454NX PXB#1, Bus#B */ 584107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; 585107172Sjhb break; 586107172Sjhb } 587107172Sjhb break; 588107172Sjhb 589107172Sjhb /* ServerWorks -- vendor 0x1166 */ 590107172Sjhb case 0x00051166: 591107172Sjhb case 0x00061166: 592107172Sjhb case 0x00081166: 593107172Sjhb case 0x00091166: 594107172Sjhb case 0x00101166: 595107172Sjhb case 0x00111166: 596107172Sjhb case 0x00171166: 597107172Sjhb case 0x01011166: 598107172Sjhb case 0x010f1014: 599107172Sjhb case 0x02011166: 600107172Sjhb case 0x03021014: 601107172Sjhb *busnum = read_config(bus, slot, func, 0x44, 1); 602107172Sjhb break; 603144110Sjhb 604144110Sjhb /* Compaq/HP -- vendor 0x0e11 */ 605144110Sjhb case 0x60100e11: 606144110Sjhb *busnum = read_config(bus, slot, func, 0xc8, 1); 607144110Sjhb break; 608107172Sjhb default: 609107172Sjhb /* Don't know how to read bus number. */ 610107172Sjhb return 0; 611107172Sjhb } 612107172Sjhb 613107172Sjhb return 1; 614107172Sjhb} 615