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