pci_subr.c revision 154079
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 154079 2006-01-06 19:22:19Z 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), 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 190149521Sjkim cp = getenv("smbios.planar.maker"); 191149521Sjkim if (cp == NULL || strncmp(cp, "Compal", 6) != 0) 192149521Sjkim break; 193149521Sjkim cp = getenv("smbios.planar.product"); 194149521Sjkim if (cp == NULL || strncmp(cp, "08A0", 4) != 0) 195149521Sjkim break; 196149521Sjkim if (sc->subbus < 0xa) { 197149521Sjkim pci_write_config(dev, PCIR_SUBBUS_1, 0xa, 1); 198149521Sjkim sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); 199149521Sjkim } 200149521Sjkim break; 201149521Sjkim } 20269908Smsmith } 20369908Smsmith 204124365Simp /* 205124365Simp * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, 206124365Simp * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, 207124365Simp * BA/CA/DB and E) PCI bridges are HUB-PCI bridges, in Intelese. 208124365Simp * This means they act as if they were subtractively decoding 209124365Simp * bridges and pass all transactions. Mark them and real ProgIf 1 210124365Simp * parts as subtractive. 211124365Simp */ 212124365Simp if ((pci_get_devid(dev) & 0xff00ffff) == 0x24008086 || 213124365Simp pci_read_config(dev, PCIR_PROGIF, 1) == 1) 214124365Simp sc->flags |= PCIB_SUBTRACTIVE; 215124365Simp 21669783Smsmith if (bootverbose) { 21769783Smsmith device_printf(dev, " secondary bus %d\n", sc->secbus); 21869783Smsmith device_printf(dev, " subordinate bus %d\n", sc->subbus); 21969783Smsmith device_printf(dev, " I/O decode 0x%x-0x%x\n", sc->iobase, sc->iolimit); 22069783Smsmith device_printf(dev, " memory decode 0x%x-0x%x\n", sc->membase, sc->memlimit); 22169783Smsmith device_printf(dev, " prefetched decode 0x%x-0x%x\n", sc->pmembase, sc->pmemlimit); 222124365Simp if (sc->flags & PCIB_SUBTRACTIVE) 223124365Simp device_printf(dev, " Subtractively decoded bridge.\n"); 22469783Smsmith } 22569783Smsmith 22669783Smsmith /* 22769783Smsmith * XXX If the secondary bus number is zero, we should assign a bus number 22869783Smsmith * since the BIOS hasn't, then initialise the bridge. 22969783Smsmith */ 23069783Smsmith 23169783Smsmith /* 23269783Smsmith * XXX If the subordinate bus number is less than the secondary bus number, 23369783Smsmith * we should pick a better value. One sensible alternative would be to 23469783Smsmith * pick 255; the only tradeoff here is that configuration transactions 23569783Smsmith * would be more widely routed than absolutely necessary. 23669783Smsmith */ 237102441Sjhb} 23869783Smsmith 239103042Sjhbint 240102441Sjhbpcib_attach(device_t dev) 241102441Sjhb{ 242102441Sjhb struct pcib_softc *sc; 243102441Sjhb device_t child; 244102441Sjhb 245102441Sjhb pcib_attach_common(dev); 246102441Sjhb sc = device_get_softc(dev); 24769783Smsmith if (sc->secbus != 0) { 248103016Sjhb child = device_add_child(dev, "pci", sc->secbus); 24969783Smsmith if (child != NULL) 25069783Smsmith return(bus_generic_attach(dev)); 25169783Smsmith } 25269783Smsmith 25369783Smsmith /* no secondary bus; we should have fixed this */ 25469783Smsmith return(0); 25569783Smsmith} 25669783Smsmith 257102441Sjhbint 25869783Smsmithpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 25969783Smsmith{ 26069783Smsmith struct pcib_softc *sc = device_get_softc(dev); 26169783Smsmith 26269783Smsmith switch (which) { 26369783Smsmith case PCIB_IVAR_BUS: 26469783Smsmith *result = sc->secbus; 26569783Smsmith return(0); 26669783Smsmith } 26769783Smsmith return(ENOENT); 26869783Smsmith} 26969783Smsmith 270102441Sjhbint 27169783Smsmithpcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 27269783Smsmith{ 27369783Smsmith struct pcib_softc *sc = device_get_softc(dev); 27469783Smsmith 27569783Smsmith switch (which) { 27669783Smsmith case PCIB_IVAR_BUS: 27769783Smsmith sc->secbus = value; 27869783Smsmith break; 27969783Smsmith } 28069783Smsmith return(ENOENT); 28169783Smsmith} 28269783Smsmith 28369783Smsmith/* 284107546Simp * Is the prefetch window open (eg, can we allocate memory in it?) 285107546Simp */ 286107546Simpstatic int 287107546Simppcib_is_prefetch_open(struct pcib_softc *sc) 288107546Simp{ 289124365Simp return (sc->pmembase > 0 && sc->pmembase < sc->pmemlimit); 290107546Simp} 291107546Simp 292107546Simp/* 293107546Simp * Is the nonprefetch window open (eg, can we allocate memory in it?) 294107546Simp */ 295107546Simpstatic int 296107546Simppcib_is_nonprefetch_open(struct pcib_softc *sc) 297107546Simp{ 298124365Simp return (sc->membase > 0 && sc->membase < sc->memlimit); 299107546Simp} 300107546Simp 301107546Simp/* 302107546Simp * Is the io window open (eg, can we allocate ports in it?) 303107546Simp */ 304107546Simpstatic int 305107546Simppcib_is_io_open(struct pcib_softc *sc) 306107546Simp{ 307124365Simp return (sc->iobase > 0 && sc->iobase < sc->iolimit); 308107546Simp} 309107546Simp 310107546Simp/* 31169783Smsmith * We have to trap resource allocation requests and ensure that the bridge 31269783Smsmith * is set up to, or capable of handling them. 31369783Smsmith */ 314102441Sjhbstruct resource * 31569783Smsmithpcib_alloc_resource(device_t dev, device_t child, int type, int *rid, 316142051Simp u_long start, u_long end, u_long count, u_int flags) 31769783Smsmith{ 318124365Simp struct pcib_softc *sc = device_get_softc(dev); 319124365Simp int ok; 32069783Smsmith 32169783Smsmith /* 32269783Smsmith * Fail the allocation for this range if it's not supported. 32369783Smsmith */ 32469783Smsmith switch (type) { 32569783Smsmith case SYS_RES_IOPORT: 326107546Simp ok = 0; 327124365Simp if (!pcib_is_io_open(sc)) 328124365Simp break; 329124365Simp ok = (start >= sc->iobase && end <= sc->iolimit); 330145652Smarcel 331145652Smarcel /* 332145652Smarcel * Make sure we allow access to VGA I/O addresses when the 333145652Smarcel * bridge has the "VGA Enable" bit set. 334145652Smarcel */ 335145652Smarcel if (!ok && pci_is_vga_ioport_range(start, end)) 336145652Smarcel ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; 337145652Smarcel 338124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 339124365Simp if (!ok) { 340124365Simp if (start < sc->iobase) 341124365Simp start = sc->iobase; 342124365Simp if (end > sc->iolimit) 343124365Simp end = sc->iolimit; 344142051Simp if (start < end) 345142051Simp ok = 1; 346124365Simp } 347106844Smdodd } else { 348124365Simp ok = 1; 349128058Simp#if 1 350124365Simp if (start < sc->iobase && end > sc->iolimit) { 351124365Simp start = sc->iobase; 352124365Simp end = sc->iolimit; 353124365Simp } 354124641Simp#endif 355106844Smdodd } 356124365Simp if (end < start) { 357142051Simp device_printf(dev, "ioport: end (%lx) < start (%lx)\n", 358142051Simp end, start); 359124365Simp start = 0; 360124365Simp end = 0; 361124365Simp ok = 0; 362124365Simp } 363124365Simp if (!ok) { 364142051Simp device_printf(dev, "%s requested unsupported I/O " 365124365Simp "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n", 366124365Simp device_get_nameunit(child), start, end, 367124365Simp sc->iobase, sc->iolimit); 368124365Simp return (NULL); 369124365Simp } 370124365Simp if (bootverbose) 371142051Simp device_printf(dev, 372142051Simp "%s requested I/O range 0x%lx-0x%lx: in range\n", 373124365Simp device_get_nameunit(child), start, end); 374124365Simp break; 37569783Smsmith 37669783Smsmith case SYS_RES_MEMORY: 377107546Simp ok = 0; 378107546Simp if (pcib_is_nonprefetch_open(sc)) 379124365Simp ok = ok || (start >= sc->membase && end <= sc->memlimit); 380107546Simp if (pcib_is_prefetch_open(sc)) 381124365Simp ok = ok || (start >= sc->pmembase && end <= sc->pmemlimit); 382145652Smarcel 383145652Smarcel /* 384145652Smarcel * Make sure we allow access to VGA memory addresses when the 385145652Smarcel * bridge has the "VGA Enable" bit set. 386145652Smarcel */ 387145652Smarcel if (!ok && pci_is_vga_memory_range(start, end)) 388145652Smarcel ok = (sc->bridgectl & PCIB_BCR_VGA_ENABLE) ? 1 : 0; 389145652Smarcel 390124365Simp if ((sc->flags & PCIB_SUBTRACTIVE) == 0) { 391124365Simp if (!ok) { 392124365Simp ok = 1; 393124365Simp if (flags & RF_PREFETCHABLE) { 394124365Simp if (pcib_is_prefetch_open(sc)) { 395124365Simp if (start < sc->pmembase) 396124365Simp start = sc->pmembase; 397124365Simp if (end > sc->pmemlimit) 398124365Simp end = sc->pmemlimit; 399124365Simp } else { 400124365Simp ok = 0; 401124365Simp } 402124365Simp } else { /* non-prefetchable */ 403124365Simp if (pcib_is_nonprefetch_open(sc)) { 404124365Simp if (start < sc->membase) 405124365Simp start = sc->membase; 406124365Simp if (end > sc->memlimit) 407124365Simp end = sc->memlimit; 408124365Simp } else { 409124365Simp ok = 0; 410124365Simp } 411124365Simp } 412107546Simp } 413107546Simp } else if (!ok) { 414124365Simp ok = 1; /* subtractive bridge: always ok */ 415128058Simp#if 1 416124365Simp if (pcib_is_nonprefetch_open(sc)) { 417124365Simp if (start < sc->membase && end > sc->memlimit) { 418124365Simp start = sc->membase; 419124365Simp end = sc->memlimit; 420124365Simp } 421124365Simp } 422124365Simp if (pcib_is_prefetch_open(sc)) { 423124365Simp if (start < sc->pmembase && end > sc->pmemlimit) { 424124365Simp start = sc->pmembase; 425124365Simp end = sc->pmemlimit; 426124365Simp } 427124365Simp } 428124641Simp#endif 429106844Smdodd } 430124365Simp if (end < start) { 431142051Simp device_printf(dev, "memory: end (%lx) < start (%lx)\n", 432142051Simp end, start); 433124365Simp start = 0; 434124365Simp end = 0; 435124365Simp ok = 0; 436124365Simp } 437124365Simp if (!ok && bootverbose) 438124365Simp device_printf(dev, 439142051Simp "%s requested unsupported memory range " 440124365Simp "0x%lx-0x%lx (decoding 0x%x-0x%x, 0x%x-0x%x)\n", 441124365Simp device_get_nameunit(child), start, end, 442124365Simp sc->membase, sc->memlimit, sc->pmembase, 443124365Simp sc->pmemlimit); 444124365Simp if (!ok) 445124365Simp return (NULL); 446124365Simp if (bootverbose) 447142051Simp device_printf(dev,"%s requested memory range " 448142051Simp "0x%lx-0x%lx: good\n", 449124365Simp device_get_nameunit(child), start, end); 450124365Simp break; 45169908Smsmith 45269783Smsmith default: 453124365Simp break; 45469783Smsmith } 455124365Simp /* 456124365Simp * Bridge is OK decoding this resource, so pass it up. 457124365Simp */ 458142051Simp return (bus_generic_alloc_resource(dev, child, type, rid, start, end, 459142051Simp count, flags)); 46069783Smsmith} 46169783Smsmith 46269783Smsmith/* 46369783Smsmith * PCIB interface. 46469783Smsmith */ 465102441Sjhbint 46669783Smsmithpcib_maxslots(device_t dev) 46769783Smsmith{ 46869908Smsmith return(PCI_SLOTMAX); 46969783Smsmith} 47069783Smsmith 47169783Smsmith/* 47269783Smsmith * Since we are a child of a PCI bus, its parent must support the pcib interface. 47369783Smsmith */ 474119266Simpuint32_t 47569783Smsmithpcib_read_config(device_t dev, int b, int s, int f, int reg, int width) 47669783Smsmith{ 47769783Smsmith return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); 47869783Smsmith} 47969783Smsmith 480102441Sjhbvoid 481119266Simppcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width) 48269783Smsmith{ 48369783Smsmith PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); 48469783Smsmith} 48569783Smsmith 48669783Smsmith/* 48769783Smsmith * Route an interrupt across a PCI bridge. 48869783Smsmith */ 489109229Sbennoint 49069783Smsmithpcib_route_interrupt(device_t pcib, device_t dev, int pin) 49169783Smsmith{ 49269783Smsmith device_t bus; 49369783Smsmith int parent_intpin; 49469783Smsmith int intnum; 49569783Smsmith 49669783Smsmith /* 49769783Smsmith * 49869783Smsmith * The PCI standard defines a swizzle of the child-side device/intpin to 49969783Smsmith * the parent-side intpin as follows. 50069783Smsmith * 50169783Smsmith * device = device on child bus 50269783Smsmith * child_intpin = intpin on child bus slot (0-3) 50369783Smsmith * parent_intpin = intpin on parent bus slot (0-3) 50469783Smsmith * 50569783Smsmith * parent_intpin = (device + child_intpin) % 4 50669783Smsmith */ 507115234Sticso parent_intpin = (pci_get_slot(dev) + (pin - 1)) % 4; 50869783Smsmith 50969783Smsmith /* 51069783Smsmith * Our parent is a PCI bus. Its parent must export the pcib interface 51169783Smsmith * which includes the ability to route interrupts. 51269783Smsmith */ 51369783Smsmith bus = device_get_parent(pcib); 51469783Smsmith intnum = PCIB_ROUTE_INTERRUPT(device_get_parent(bus), pcib, parent_intpin + 1); 515131398Sjhb if (PCI_INTERRUPT_VALID(intnum) && bootverbose) { 516102977Sjhb device_printf(pcib, "slot %d INT%c is routed to irq %d\n", 517102977Sjhb pci_get_slot(dev), 'A' + pin - 1, intnum); 51890554Smsmith } 51969783Smsmith return(intnum); 52069783Smsmith} 521107172Sjhb 522107172Sjhb/* 523107172Sjhb * Try to read the bus number of a host-PCI bridge using appropriate config 524107172Sjhb * registers. 525107172Sjhb */ 526107172Sjhbint 527107172Sjhbhost_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, 528119266Simp uint8_t *busnum) 529107172Sjhb{ 530119266Simp uint32_t id; 531107172Sjhb 532107172Sjhb id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); 533107248Sjhb if (id == 0xffffffff) 534107172Sjhb return (0); 535107172Sjhb 536107172Sjhb switch (id) { 537107172Sjhb case 0x12258086: 538107172Sjhb /* Intel 824?? */ 539107172Sjhb /* XXX This is a guess */ 540107172Sjhb /* *busnum = read_config(bus, slot, func, 0x41, 1); */ 541107172Sjhb *busnum = bus; 542107172Sjhb break; 543107172Sjhb case 0x84c48086: 544107172Sjhb /* Intel 82454KX/GX (Orion) */ 545107172Sjhb *busnum = read_config(bus, slot, func, 0x4a, 1); 546107172Sjhb break; 547107172Sjhb case 0x84ca8086: 548107172Sjhb /* 549107172Sjhb * For the 450nx chipset, there is a whole bundle of 550107172Sjhb * things pretending to be host bridges. The MIOC will 551107172Sjhb * be seen first and isn't really a pci bridge (the 552107172Sjhb * actual busses are attached to the PXB's). We need to 553107172Sjhb * read the registers of the MIOC to figure out the 554107172Sjhb * bus numbers for the PXB channels. 555107172Sjhb * 556107172Sjhb * Since the MIOC doesn't have a pci bus attached, we 557107172Sjhb * pretend it wasn't there. 558107172Sjhb */ 559107172Sjhb return (0); 560107172Sjhb case 0x84cb8086: 561107172Sjhb switch (slot) { 562107172Sjhb case 0x12: 563107172Sjhb /* Intel 82454NX PXB#0, Bus#A */ 564107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd0, 1); 565107172Sjhb break; 566107172Sjhb case 0x13: 567107172Sjhb /* Intel 82454NX PXB#0, Bus#B */ 568107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; 569107172Sjhb break; 570107172Sjhb case 0x14: 571107172Sjhb /* Intel 82454NX PXB#1, Bus#A */ 572107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd3, 1); 573107172Sjhb break; 574107172Sjhb case 0x15: 575107172Sjhb /* Intel 82454NX PXB#1, Bus#B */ 576107248Sjhb *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; 577107172Sjhb break; 578107172Sjhb } 579107172Sjhb break; 580107172Sjhb 581107172Sjhb /* ServerWorks -- vendor 0x1166 */ 582107172Sjhb case 0x00051166: 583107172Sjhb case 0x00061166: 584107172Sjhb case 0x00081166: 585107172Sjhb case 0x00091166: 586107172Sjhb case 0x00101166: 587107172Sjhb case 0x00111166: 588107172Sjhb case 0x00171166: 589107172Sjhb case 0x01011166: 590107172Sjhb case 0x010f1014: 591107172Sjhb case 0x02011166: 592107172Sjhb case 0x03021014: 593107172Sjhb *busnum = read_config(bus, slot, func, 0x44, 1); 594107172Sjhb break; 595144110Sjhb 596144110Sjhb /* Compaq/HP -- vendor 0x0e11 */ 597144110Sjhb case 0x60100e11: 598144110Sjhb *busnum = read_config(bus, slot, func, 0xc8, 1); 599144110Sjhb break; 600107172Sjhb default: 601107172Sjhb /* Don't know how to read bus number. */ 602107172Sjhb return 0; 603107172Sjhb } 604107172Sjhb 605107172Sjhb return 1; 606107172Sjhb} 607