1 /* $NetBSD: pci_machdep.c,v 1.15 2006/06/25 03:46:56 soren Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 42 * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by Charles M. Hannum. 55 * 4. The name of the author may not be used to endorse or promote products 56 * derived from this software without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 */ 69 70 /* 71 * Machine-specific functions for PCI autoconfiguration. 72 * 73 * On PCs, there are two methods of generating PCI configuration cycles. 74 * We try to detect the appropriate mechanism for this machine and set 75 * up a few function pointers to access the correct method directly. 76 * 77 * The configuration method can be hard-coded in the config file by 78 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode 79 * as defined section 3.6.4.1, `Generating Configuration Cycles'. 80 */ 81 82 #include <sys/cdefs.h> 83 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.15 2006/06/25 03:46:56 soren Exp $"); 84 85 #include <sys/types.h> 86 #include <sys/param.h> 87 #include <sys/time.h> 88 #include <sys/systm.h> 89 #include <sys/errno.h> 90 #include <sys/device.h> 91 #include <sys/lock.h> 92 93 #include <uvm/uvm_extern.h> 94 95 #include <machine/bus.h> 96 #include <machine/bus_private.h> 97 98 #include <machine/pio.h> 99 100 #include <dev/isa/isareg.h> 101 #include <dev/isa/isavar.h> 102 #include <dev/pci/pcivar.h> 103 #include <dev/pci/pcireg.h> 104 #include <dev/pci/pcidevs.h> 105 106 #include "opt_mpbios.h" 107 #include "opt_mpacpi.h" 108 109 #ifdef MPBIOS 110 #include <machine/mpbiosvar.h> 111 #endif 112 113 #ifdef MPACPI 114 #include <machine/mpacpi.h> 115 #endif 116 117 #include "opt_pci_conf_mode.h" 118 119 int pci_mode = -1; 120 121 static void pci_bridge_hook(pci_chipset_tag_t, pcitag_t, void *); 122 struct pci_bridge_hook_arg { 123 void (*func)(pci_chipset_tag_t, pcitag_t, void *); 124 void *arg; 125 }; 126 127 128 struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER; 129 130 #define PCI_CONF_LOCK(s) \ 131 do { \ 132 (s) = splhigh(); \ 133 simple_lock(&pci_conf_slock); \ 134 } while (0) 135 136 #define PCI_CONF_UNLOCK(s) \ 137 do { \ 138 simple_unlock(&pci_conf_slock); \ 139 splx((s)); \ 140 } while (0) 141 142 #define PCI_MODE1_ENABLE 0x80000000UL 143 #define PCI_MODE1_ADDRESS_REG 0x0cf8 144 #define PCI_MODE1_DATA_REG 0x0cfc 145 146 #define PCI_MODE2_ENABLE_REG 0x0cf8 147 #define PCI_MODE2_FORWARD_REG 0x0cfa 148 149 #define _m1tag(b, d, f) \ 150 (PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8)) 151 #define _qe(bus, dev, fcn, vend, prod) \ 152 {_m1tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)} 153 struct { 154 u_int32_t tag; 155 pcireg_t id; 156 } pcim1_quirk_tbl[] = { 157 _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1), 158 /* XXX Triflex2 not tested */ 159 _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2), 160 _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4), 161 /* Triton needed for Connectix Virtual PC */ 162 _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX), 163 /* Connectix Virtual PC 5 has a 440BX */ 164 _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP), 165 /* Parallels Desktop for Mac */ 166 _qe(0, 2, 0, PCI_VENDOR_PARALLELS, PCI_PRODUCT_PARALLELS_VIDEO), 167 _qe(0, 3, 0, PCI_VENDOR_PARALLELS, PCI_PRODUCT_PARALLELS_TOOLS), 168 /* SIS 741 */ 169 _qe(0, 0, 0, PCI_VENDOR_SIS, PCI_PRODUCT_SIS_741), 170 {0, 0xffffffff} /* patchable */ 171 }; 172 #undef _m1tag 173 #undef _id 174 #undef _qe 175 176 /* 177 * PCI doesn't have any special needs; just use the generic versions 178 * of these functions. 179 */ 180 struct x86_bus_dma_tag pci_bus_dma_tag = { 181 #if defined(_LP64) || defined(PAE) 182 PCI32_DMA_BOUNCE_THRESHOLD, /* bounce_thresh */ 183 ISA_DMA_BOUNCE_THRESHOLD, /* bounce_alloclo */ 184 PCI32_DMA_BOUNCE_THRESHOLD, /* bounce_allochi */ 185 #else 186 0, 187 0, 188 0, 189 #endif 190 NULL, /* _may_bounce */ 191 _bus_dmamap_create, 192 _bus_dmamap_destroy, 193 _bus_dmamap_load, 194 _bus_dmamap_load_mbuf, 195 _bus_dmamap_load_uio, 196 _bus_dmamap_load_raw, 197 _bus_dmamap_unload, 198 #if defined(_LP64) || defined(PAE) 199 _bus_dmamap_sync, 200 #else 201 NULL, 202 #endif 203 _bus_dmamem_alloc, 204 _bus_dmamem_free, 205 _bus_dmamem_map, 206 _bus_dmamem_unmap, 207 _bus_dmamem_mmap, 208 }; 209 210 #ifdef _LP64 211 struct x86_bus_dma_tag pci_bus_dma64_tag = { 212 0, 213 0, 214 0, 215 NULL, /* _may_bounce */ 216 _bus_dmamap_create, 217 _bus_dmamap_destroy, 218 _bus_dmamap_load, 219 _bus_dmamap_load_mbuf, 220 _bus_dmamap_load_uio, 221 _bus_dmamap_load_raw, 222 _bus_dmamap_unload, 223 NULL, 224 _bus_dmamem_alloc, 225 _bus_dmamem_free, 226 _bus_dmamem_map, 227 _bus_dmamem_unmap, 228 _bus_dmamem_mmap, 229 }; 230 #endif 231 232 void 233 pci_attach_hook(parent, self, pba) 234 struct device *parent, *self; 235 struct pcibus_attach_args *pba; 236 { 237 238 if (pba->pba_bus == 0) 239 printf(": configuration mode %d", pci_mode); 240 #ifdef MPBIOS 241 mpbios_pci_attach_hook(parent, self, pba); 242 #endif 243 #ifdef MPACPI 244 mpacpi_pci_attach_hook(parent, self, pba); 245 #endif 246 } 247 248 int 249 pci_bus_maxdevs(pc, busno) 250 pci_chipset_tag_t pc; 251 int busno; 252 { 253 254 /* 255 * Bus number is irrelevant. If Configuration Mechanism 2 is in 256 * use, can only have devices 0-15 on any bus. If Configuration 257 * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal' 258 * range). 259 */ 260 if (pci_mode == 2) 261 return (16); 262 else 263 return (32); 264 } 265 266 pcitag_t 267 pci_make_tag(pc, bus, device, function) 268 pci_chipset_tag_t pc; 269 int bus, device, function; 270 { 271 pcitag_t tag; 272 273 #ifndef PCI_CONF_MODE 274 switch (pci_mode) { 275 case 1: 276 goto mode1; 277 case 2: 278 goto mode2; 279 default: 280 panic("pci_make_tag: mode not configured"); 281 } 282 #endif 283 284 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 285 #ifndef PCI_CONF_MODE 286 mode1: 287 #endif 288 if (bus >= 256 || device >= 32 || function >= 8) 289 panic("pci_make_tag: bad request"); 290 291 tag.mode1 = PCI_MODE1_ENABLE | 292 (bus << 16) | (device << 11) | (function << 8); 293 return tag; 294 #endif 295 296 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 297 #ifndef PCI_CONF_MODE 298 mode2: 299 #endif 300 if (bus >= 256 || device >= 16 || function >= 8) 301 panic("pci_make_tag: bad request"); 302 303 tag.mode2.port = 0xc000 | (device << 8); 304 tag.mode2.enable = 0xf0 | (function << 1); 305 tag.mode2.forward = bus; 306 return tag; 307 #endif 308 } 309 310 void 311 pci_decompose_tag(pc, tag, bp, dp, fp) 312 pci_chipset_tag_t pc; 313 pcitag_t tag; 314 int *bp, *dp, *fp; 315 { 316 317 #ifndef PCI_CONF_MODE 318 switch (pci_mode) { 319 case 1: 320 goto mode1; 321 case 2: 322 goto mode2; 323 default: 324 panic("pci_decompose_tag: mode not configured"); 325 } 326 #endif 327 328 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 329 #ifndef PCI_CONF_MODE 330 mode1: 331 #endif 332 if (bp != NULL) 333 *bp = (tag.mode1 >> 16) & 0xff; 334 if (dp != NULL) 335 *dp = (tag.mode1 >> 11) & 0x1f; 336 if (fp != NULL) 337 *fp = (tag.mode1 >> 8) & 0x7; 338 return; 339 #endif 340 341 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 342 #ifndef PCI_CONF_MODE 343 mode2: 344 #endif 345 if (bp != NULL) 346 *bp = tag.mode2.forward & 0xff; 347 if (dp != NULL) 348 *dp = (tag.mode2.port >> 8) & 0xf; 349 if (fp != NULL) 350 *fp = (tag.mode2.enable >> 1) & 0x7; 351 #endif 352 } 353 354 pcireg_t 355 pci_conf_read(pc, tag, reg) 356 pci_chipset_tag_t pc; 357 pcitag_t tag; 358 int reg; 359 { 360 pcireg_t data; 361 int s; 362 363 #ifndef PCI_CONF_MODE 364 switch (pci_mode) { 365 case 1: 366 goto mode1; 367 case 2: 368 goto mode2; 369 default: 370 panic("pci_conf_read: mode not configured"); 371 } 372 #endif 373 374 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 375 #ifndef PCI_CONF_MODE 376 mode1: 377 #endif 378 PCI_CONF_LOCK(s); 379 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); 380 data = inl(PCI_MODE1_DATA_REG); 381 outl(PCI_MODE1_ADDRESS_REG, 0); 382 PCI_CONF_UNLOCK(s); 383 return data; 384 #endif 385 386 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 387 #ifndef PCI_CONF_MODE 388 mode2: 389 #endif 390 PCI_CONF_LOCK(s); 391 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable); 392 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward); 393 data = inl(tag.mode2.port | reg); 394 outb(PCI_MODE2_ENABLE_REG, 0); 395 PCI_CONF_UNLOCK(s); 396 return data; 397 #endif 398 } 399 400 void 401 pci_conf_write(pc, tag, reg, data) 402 pci_chipset_tag_t pc; 403 pcitag_t tag; 404 int reg; 405 pcireg_t data; 406 { 407 int s; 408 409 #ifndef PCI_CONF_MODE 410 switch (pci_mode) { 411 case 1: 412 goto mode1; 413 case 2: 414 goto mode2; 415 default: 416 panic("pci_conf_write: mode not configured"); 417 } 418 #endif 419 420 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 421 #ifndef PCI_CONF_MODE 422 mode1: 423 #endif 424 PCI_CONF_LOCK(s); 425 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); 426 outl(PCI_MODE1_DATA_REG, data); 427 outl(PCI_MODE1_ADDRESS_REG, 0); 428 PCI_CONF_UNLOCK(s); 429 return; 430 #endif 431 432 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 433 #ifndef PCI_CONF_MODE 434 mode2: 435 #endif 436 PCI_CONF_LOCK(s); 437 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable); 438 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward); 439 outl(tag.mode2.port | reg, data); 440 outb(PCI_MODE2_ENABLE_REG, 0); 441 PCI_CONF_UNLOCK(s); 442 #endif 443 } 444 445 int 446 pci_mode_detect() 447 { 448 449 #ifdef PCI_CONF_MODE 450 #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2) 451 return (pci_mode = PCI_CONF_MODE); 452 #else 453 #error Invalid PCI configuration mode. 454 #endif 455 #else 456 u_int32_t sav, val; 457 int i; 458 pcireg_t idreg; 459 460 if (pci_mode != -1) 461 return pci_mode; 462 463 /* 464 * We try to divine which configuration mode the host bridge wants. 465 */ 466 467 sav = inl(PCI_MODE1_ADDRESS_REG); 468 469 pci_mode = 1; /* assume this for now */ 470 /* 471 * catch some known buggy implementations of mode 1 472 */ 473 for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]); 474 i++) { 475 pcitag_t t; 476 477 if (!pcim1_quirk_tbl[i].tag) 478 break; 479 t.mode1 = pcim1_quirk_tbl[i].tag; 480 idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */ 481 if (idreg == pcim1_quirk_tbl[i].id) { 482 #ifdef DEBUG 483 printf("known mode 1 PCI chipset (%08x)\n", 484 idreg); 485 #endif 486 return (pci_mode); 487 } 488 } 489 490 /* 491 * Strong check for standard compliant mode 1: 492 * 1. bit 31 ("enable") can be set 493 * 2. byte/word access does not affect register 494 */ 495 outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE); 496 outb(PCI_MODE1_ADDRESS_REG + 3, 0); 497 outw(PCI_MODE1_ADDRESS_REG + 2, 0); 498 val = inl(PCI_MODE1_ADDRESS_REG); 499 if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) { 500 #ifdef DEBUG 501 printf("pci_mode_detect: mode 1 enable failed (%x)\n", 502 val); 503 #endif 504 goto not1; 505 } 506 outl(PCI_MODE1_ADDRESS_REG, 0); 507 val = inl(PCI_MODE1_ADDRESS_REG); 508 if ((val & 0x80fffffc) != 0) 509 goto not1; 510 return (pci_mode); 511 not1: 512 outl(PCI_MODE1_ADDRESS_REG, sav); 513 514 /* 515 * This mode 2 check is quite weak (and known to give false 516 * positives on some Compaq machines). 517 * However, this doesn't matter, because this is the 518 * last test, and simply no PCI devices will be found if 519 * this happens. 520 */ 521 outb(PCI_MODE2_ENABLE_REG, 0); 522 outb(PCI_MODE2_FORWARD_REG, 0); 523 if (inb(PCI_MODE2_ENABLE_REG) != 0 || 524 inb(PCI_MODE2_FORWARD_REG) != 0) 525 goto not2; 526 return (pci_mode = 2); 527 not2: 528 529 return (pci_mode = 0); 530 #endif 531 } 532 533 /* 534 * Determine which flags should be passed to the primary PCI bus's 535 * autoconfiguration node. We use this to detect broken chipsets 536 * which cannot safely use memory-mapped device access. 537 */ 538 int 539 pci_bus_flags() 540 { 541 int rval = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | 542 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 543 int device, maxndevs; 544 pcitag_t tag; 545 pcireg_t id; 546 547 maxndevs = pci_bus_maxdevs(NULL, 0); 548 549 for (device = 0; device < maxndevs; device++) { 550 tag = pci_make_tag(NULL, 0, device, 0); 551 id = pci_conf_read(NULL, tag, PCI_ID_REG); 552 553 /* Invalid vendor ID value? */ 554 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 555 continue; 556 /* XXX Not invalid, but we've done this ~forever. */ 557 if (PCI_VENDOR(id) == 0) 558 continue; 559 560 switch (PCI_VENDOR(id)) { 561 case PCI_VENDOR_SIS: 562 switch (PCI_PRODUCT(id)) { 563 case PCI_PRODUCT_SIS_85C496: 564 goto disable_mem; 565 } 566 break; 567 } 568 } 569 570 return (rval); 571 572 disable_mem: 573 printf("Warning: broken PCI-Host bridge detected; " 574 "disabling memory-mapped access\n"); 575 rval &= ~(PCI_FLAGS_MEM_ENABLED|PCI_FLAGS_MRL_OKAY|PCI_FLAGS_MRM_OKAY| 576 PCI_FLAGS_MWI_OKAY); 577 return (rval); 578 } 579 580 void 581 pci_device_foreach(pci_chipset_tag_t pc, int maxbus, 582 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context) 583 { 584 pci_device_foreach_min(pc, 0, maxbus, func, context); 585 } 586 587 void 588 pci_device_foreach_min(pci_chipset_tag_t pc, int minbus, int maxbus, 589 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *context) 590 { 591 const struct pci_quirkdata *qd; 592 int bus, device, function, maxdevs, nfuncs; 593 pcireg_t id, bhlcr; 594 pcitag_t tag; 595 596 for (bus = minbus; bus <= maxbus; bus++) { 597 maxdevs = pci_bus_maxdevs(pc, bus); 598 for (device = 0; device < maxdevs; device++) { 599 tag = pci_make_tag(pc, bus, device, 0); 600 id = pci_conf_read(pc, tag, PCI_ID_REG); 601 602 /* Invalid vendor ID value? */ 603 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 604 continue; 605 /* XXX Not invalid, but we've done this ~forever. */ 606 if (PCI_VENDOR(id) == 0) 607 continue; 608 609 qd = pci_lookup_quirkdata(PCI_VENDOR(id), 610 PCI_PRODUCT(id)); 611 612 bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 613 if (PCI_HDRTYPE_MULTIFN(bhlcr) || 614 (qd != NULL && 615 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 616 nfuncs = 8; 617 else 618 nfuncs = 1; 619 620 for (function = 0; function < nfuncs; function++) { 621 tag = pci_make_tag(pc, bus, device, function); 622 id = pci_conf_read(pc, tag, PCI_ID_REG); 623 624 /* Invalid vendor ID value? */ 625 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 626 continue; 627 /* 628 * XXX Not invalid, but we've done this 629 * ~forever. 630 */ 631 if (PCI_VENDOR(id) == 0) 632 continue; 633 (*func)(pc, tag, context); 634 } 635 } 636 } 637 } 638 639 void 640 pci_bridge_foreach(pci_chipset_tag_t pc, int minbus, int maxbus, 641 void (*func)(pci_chipset_tag_t, pcitag_t, void *), void *ctx) 642 { 643 struct pci_bridge_hook_arg bridge_hook; 644 645 bridge_hook.func = func; 646 bridge_hook.arg = ctx; 647 648 pci_device_foreach_min(pc, minbus, maxbus, pci_bridge_hook, 649 &bridge_hook); 650 } 651 652 static void 653 pci_bridge_hook(pci_chipset_tag_t pc, pcitag_t tag, void *ctx) 654 { 655 struct pci_bridge_hook_arg *bridge_hook = (void *)ctx; 656 pcireg_t reg; 657 658 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 659 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 660 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI || 661 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) { 662 (*bridge_hook->func)(pc, tag, bridge_hook->arg); 663 } 664 } 665