Annotation of sys/arch/i386/pci/pci_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pci_machdep.c,v 1.39 2007/05/21 22:10:45 kettenis Exp $ */
! 2: /* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1997 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 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 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:
! 90: #include <uvm/uvm_extern.h>
! 91:
! 92: #define _I386_BUS_DMA_PRIVATE
! 93: #include <machine/bus.h>
! 94: #include <machine/pio.h>
! 95: #include <machine/i8259.h>
! 96:
! 97: #include "bios.h"
! 98: #if NBIOS > 0
! 99: #include <machine/biosvar.h>
! 100: extern bios_pciinfo_t *bios_pciinfo;
! 101: #endif
! 102:
! 103: #include <dev/isa/isavar.h>
! 104: #include <dev/pci/pcivar.h>
! 105: #include <dev/pci/pcireg.h>
! 106: #include <dev/pci/pcidevs.h>
! 107: #include <dev/pci/ppbreg.h>
! 108:
! 109: #include "ioapic.h"
! 110:
! 111: #include <machine/i82093var.h>
! 112: #if NIOAPIC > 0
! 113: #include <machine/mpbiosvar.h>
! 114: #endif
! 115:
! 116: #include "pcibios.h"
! 117: #if NPCIBIOS > 0
! 118: #include <i386/pci/pcibiosvar.h>
! 119: #endif
! 120:
! 121: int pci_mode = -1;
! 122:
! 123: #define PCI_MODE1_ENABLE 0x80000000UL
! 124: #define PCI_MODE1_ADDRESS_REG 0x0cf8
! 125: #define PCI_MODE1_DATA_REG 0x0cfc
! 126:
! 127: #define PCI_MODE2_ENABLE_REG 0x0cf8
! 128: #define PCI_MODE2_FORWARD_REG 0x0cfa
! 129:
! 130: #define _m1tag(b, d, f) \
! 131: (PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8))
! 132: #define _qe(bus, dev, fcn, vend, prod) \
! 133: {_m1tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)}
! 134: struct {
! 135: u_int32_t tag;
! 136: pcireg_t id;
! 137: } pcim1_quirk_tbl[] = {
! 138: _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1),
! 139: /* XXX Triflex2 not tested */
! 140: _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2),
! 141: _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4),
! 142: /* Triton needed for Connectix Virtual PC */
! 143: _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX),
! 144: /* Connectix Virtual PC 5 has a 440BX */
! 145: _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP),
! 146: {0, 0xffffffff} /* patchable */
! 147: };
! 148: #undef _m1tag
! 149: #undef _qe
! 150:
! 151: /*
! 152: * PCI doesn't have any special needs; just use the generic versions
! 153: * of these functions.
! 154: */
! 155: struct i386_bus_dma_tag pci_bus_dma_tag = {
! 156: NULL, /* _cookie */
! 157: _bus_dmamap_create,
! 158: _bus_dmamap_destroy,
! 159: _bus_dmamap_load,
! 160: _bus_dmamap_load_mbuf,
! 161: _bus_dmamap_load_uio,
! 162: _bus_dmamap_load_raw,
! 163: _bus_dmamap_unload,
! 164: NULL, /* _dmamap_sync */
! 165: _bus_dmamem_alloc,
! 166: _bus_dmamem_free,
! 167: _bus_dmamem_map,
! 168: _bus_dmamem_unmap,
! 169: _bus_dmamem_mmap,
! 170: };
! 171:
! 172: void
! 173: pci_attach_hook(struct device *parent, struct device *self,
! 174: struct pcibus_attach_args *pba)
! 175: {
! 176:
! 177: #if NBIOS > 0
! 178: if (pba->pba_bus == 0)
! 179: printf(": configuration mode %d (%s)",
! 180: pci_mode, (bios_pciinfo?"bios":"no bios"));
! 181: #else
! 182: if (pba->pba_bus == 0)
! 183: printf(": configuration mode %d", pci_mode);
! 184: #endif
! 185: }
! 186:
! 187: int
! 188: pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
! 189: {
! 190:
! 191: /*
! 192: * Bus number is irrelevant. If Configuration Mechanism 2 is in
! 193: * use, can only have devices 0-15 on any bus. If Configuration
! 194: * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal'
! 195: * range).
! 196: */
! 197: if (pci_mode == 2)
! 198: return (16);
! 199: else
! 200: return (32);
! 201: }
! 202:
! 203: pcitag_t
! 204: pci_make_tag(pci_chipset_tag_t pc, int bus, int device, int function)
! 205: {
! 206: pcitag_t tag;
! 207:
! 208: switch (pci_mode) {
! 209: case 1:
! 210: if (bus >= 256 || device >= 32 || function >= 8)
! 211: panic("pci_make_tag: bad request");
! 212:
! 213: tag.mode1 = PCI_MODE1_ENABLE |
! 214: (bus << 16) | (device << 11) | (function << 8);
! 215: break;
! 216: case 2:
! 217: if (bus >= 256 || device >= 16 || function >= 8)
! 218: panic("pci_make_tag: bad request");
! 219:
! 220: tag.mode2.port = 0xc000 | (device << 8);
! 221: tag.mode2.enable = 0xf0 | (function << 1);
! 222: tag.mode2.forward = bus;
! 223: break;
! 224: default:
! 225: panic("pci_make_tag: mode not configured");
! 226: }
! 227:
! 228: return tag;
! 229: }
! 230:
! 231: void
! 232: pci_decompose_tag(pci_chipset_tag_t pc, pcitag_t tag, int *bp, int *dp, int *fp)
! 233: {
! 234:
! 235: switch (pci_mode) {
! 236: case 1:
! 237: if (bp != NULL)
! 238: *bp = (tag.mode1 >> 16) & 0xff;
! 239: if (dp != NULL)
! 240: *dp = (tag.mode1 >> 11) & 0x1f;
! 241: if (fp != NULL)
! 242: *fp = (tag.mode1 >> 8) & 0x7;
! 243: break;
! 244: case 2:
! 245: if (bp != NULL)
! 246: *bp = tag.mode2.forward & 0xff;
! 247: if (dp != NULL)
! 248: *dp = (tag.mode2.port >> 8) & 0xf;
! 249: if (fp != NULL)
! 250: *fp = (tag.mode2.enable >> 1) & 0x7;
! 251: break;
! 252: default:
! 253: panic("pci_decompose_tag: mode not configured");
! 254: }
! 255: }
! 256:
! 257: pcireg_t
! 258: pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
! 259: {
! 260: pcireg_t data;
! 261:
! 262: switch (pci_mode) {
! 263: case 1:
! 264: outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
! 265: data = inl(PCI_MODE1_DATA_REG);
! 266: outl(PCI_MODE1_ADDRESS_REG, 0);
! 267: break;
! 268: case 2:
! 269: outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
! 270: outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
! 271: data = inl(tag.mode2.port | reg);
! 272: outb(PCI_MODE2_ENABLE_REG, 0);
! 273: break;
! 274: default:
! 275: panic("pci_conf_read: mode not configured");
! 276: }
! 277:
! 278: return data;
! 279: }
! 280:
! 281: void
! 282: pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
! 283: {
! 284:
! 285: switch (pci_mode) {
! 286: case 1:
! 287: outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
! 288: outl(PCI_MODE1_DATA_REG, data);
! 289: outl(PCI_MODE1_ADDRESS_REG, 0);
! 290: break;
! 291: case 2:
! 292: outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
! 293: outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
! 294: outl(tag.mode2.port | reg, data);
! 295: outb(PCI_MODE2_ENABLE_REG, 0);
! 296: break;
! 297: default:
! 298: panic("pci_conf_write: mode not configured");
! 299: }
! 300: }
! 301:
! 302: int
! 303: pci_mode_detect(void)
! 304: {
! 305:
! 306: #ifdef PCI_CONF_MODE
! 307: #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2)
! 308: return (pci_mode = PCI_CONF_MODE);
! 309: #else
! 310: #error Invalid PCI configuration mode.
! 311: #endif
! 312: #else
! 313: u_int32_t sav, val;
! 314: int i;
! 315: pcireg_t idreg;
! 316:
! 317: if (pci_mode != -1)
! 318: return (pci_mode);
! 319:
! 320: #if NBIOS > 0
! 321: /*
! 322: * If we have PCI info passed from the BIOS, use the mode given there
! 323: * for all of this code. If not, pass on through to the previous tests
! 324: * to try and divine the correct mode.
! 325: */
! 326: if (bios_pciinfo != NULL) {
! 327: if (bios_pciinfo->pci_chars & 0x2)
! 328: return (pci_mode = 2);
! 329:
! 330: if (bios_pciinfo->pci_chars & 0x1)
! 331: return (pci_mode = 1);
! 332:
! 333: /* We should never get here, but if we do, fall through... */
! 334: }
! 335: #endif
! 336:
! 337: /*
! 338: * We try to divine which configuration mode the host bridge wants.
! 339: *
! 340: * This should really be done using the PCI BIOS. If we get here, the
! 341: * PCI BIOS does not exist, or the boot blocks did not provide the
! 342: * information.
! 343: */
! 344:
! 345: sav = inl(PCI_MODE1_ADDRESS_REG);
! 346:
! 347: pci_mode = 1; /* assume this for now */
! 348: /*
! 349: * catch some known buggy implementations of mode 1
! 350: */
! 351: for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]);
! 352: i++) {
! 353: pcitag_t t;
! 354:
! 355: if (!pcim1_quirk_tbl[i].tag)
! 356: break;
! 357: t.mode1 = pcim1_quirk_tbl[i].tag;
! 358: idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */
! 359: if (idreg == pcim1_quirk_tbl[i].id) {
! 360: #ifdef DEBUG
! 361: printf("known mode 1 PCI chipset (%08x)\n",
! 362: idreg);
! 363: #endif
! 364: return (pci_mode);
! 365: }
! 366: }
! 367:
! 368: /*
! 369: * Strong check for standard compliant mode 1:
! 370: * 1. bit 31 ("enable") can be set
! 371: * 2. byte/word access does not affect register
! 372: */
! 373: outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
! 374: outb(PCI_MODE1_ADDRESS_REG + 3, 0);
! 375: outw(PCI_MODE1_ADDRESS_REG + 2, 0);
! 376: val = inl(PCI_MODE1_ADDRESS_REG);
! 377: if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) {
! 378: #ifdef DEBUG
! 379: printf("pci_mode_detect: mode 1 enable failed (%x)\n",
! 380: val);
! 381: #endif
! 382: goto not1;
! 383: }
! 384: outl(PCI_MODE1_ADDRESS_REG, 0);
! 385: val = inl(PCI_MODE1_ADDRESS_REG);
! 386: if ((val & 0x80fffffc) != 0)
! 387: goto not1;
! 388: return (pci_mode);
! 389: not1:
! 390: outl(PCI_MODE1_ADDRESS_REG, sav);
! 391:
! 392: /*
! 393: * This mode 2 check is quite weak (and known to give false
! 394: * positives on some Compaq machines).
! 395: * However, this doesn't matter, because this is the
! 396: * last test, and simply no PCI devices will be found if
! 397: * this happens.
! 398: */
! 399: outb(PCI_MODE2_ENABLE_REG, 0);
! 400: outb(PCI_MODE2_FORWARD_REG, 0);
! 401: if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
! 402: inb(PCI_MODE2_FORWARD_REG) != 0)
! 403: goto not2;
! 404: return (pci_mode = 2);
! 405: not2:
! 406: return (pci_mode = 0);
! 407: #endif
! 408: }
! 409:
! 410: int
! 411: pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
! 412: {
! 413: int pin = pa->pa_intrpin;
! 414: int line = pa->pa_intrline;
! 415: #if NIOAPIC > 0
! 416: int rawpin = pa->pa_rawintrpin;
! 417: struct mp_intr_map *mip;
! 418: int bus, dev, func;
! 419: #endif
! 420:
! 421: #if (NPCIBIOS > 0) || (NIOAPIC > 0)
! 422: pci_chipset_tag_t pc = pa->pa_pc;
! 423: pcitag_t intrtag = pa->pa_intrtag;
! 424: #endif
! 425:
! 426: if (pin == 0) {
! 427: /* No IRQ used. */
! 428: goto bad;
! 429: }
! 430:
! 431: if (pin > PCI_INTERRUPT_PIN_MAX) {
! 432: printf("pci_intr_map: bad interrupt pin %d\n", pin);
! 433: goto bad;
! 434: }
! 435:
! 436: ihp->line = line;
! 437: ihp->pin = pin;
! 438:
! 439: #if NIOAPIC > 0
! 440: pci_decompose_tag (pc, intrtag, &bus, &dev, &func);
! 441:
! 442: if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
! 443: /*
! 444: * Assumes 1:1 mapping between PCI bus numbers and
! 445: * the numbers given by the MP bios.
! 446: * XXX Is this a valid assumption?
! 447: */
! 448: int mpspec_pin = (dev<<2)|(pin-1);
! 449:
! 450: for (mip = mp_busses[bus].mb_intrs; mip != NULL; mip=mip->next) {
! 451: if (mip->bus_pin == mpspec_pin) {
! 452: ihp->line = mip->ioapic_ih | line;
! 453: return 0;
! 454: }
! 455: }
! 456:
! 457: if (pa->pa_bridgetag) {
! 458: int pin = PPB_INTERRUPT_SWIZZLE(rawpin, dev);
! 459: if (pa->pa_bridgeih[pin - 1].line != -1) {
! 460: ihp->line = pa->pa_bridgeih[pin - 1].line;
! 461: ihp->line |= line;
! 462: return 0;
! 463: }
! 464: }
! 465: /*
! 466: * No explicit PCI mapping found. This is not fatal,
! 467: * we'll try the ISA (or possibly EISA) mappings next.
! 468: */
! 469: }
! 470: #endif
! 471:
! 472: #if NPCIBIOS > 0
! 473: pci_intr_header_fixup(pc, intrtag, ihp);
! 474: line = ihp->line & APIC_INT_LINE_MASK;
! 475: #endif
! 476:
! 477: /*
! 478: * Section 6.2.4, `Miscellaneous Functions', says that 255 means
! 479: * `unknown' or `no connection' on a PC. We assume that a device with
! 480: * `no connection' either doesn't have an interrupt (in which case the
! 481: * pin number should be 0, and would have been noticed above), or
! 482: * wasn't configured by the BIOS (in which case we punt, since there's
! 483: * no real way we can know how the interrupt lines are mapped in the
! 484: * hardware).
! 485: *
! 486: * XXX
! 487: * Since IRQ 0 is only used by the clock, and we can't actually be sure
! 488: * that the BIOS did its job, we also recognize that as meaning that
! 489: * the BIOS has not configured the device.
! 490: */
! 491: if (line == 0 || line == I386_PCI_INTERRUPT_LINE_NO_CONNECTION)
! 492: goto bad;
! 493:
! 494: if (line >= ICU_LEN) {
! 495: printf("pci_intr_map: bad interrupt line %d\n", line);
! 496: goto bad;
! 497: }
! 498: if (line == 2) {
! 499: printf("pci_intr_map: changed line 2 to line 9\n");
! 500: line = 9;
! 501: }
! 502:
! 503: #if NIOAPIC > 0
! 504: if (!(ihp->line & PCI_INT_VIA_ISA) && mp_busses != NULL) {
! 505: if (mip == NULL && mp_isa_bus) {
! 506: for (mip = mp_isa_bus->mb_intrs; mip != NULL;
! 507: mip = mip->next) {
! 508: if (mip->bus_pin == line) {
! 509: ihp->line = mip->ioapic_ih | line;
! 510: return 0;
! 511: }
! 512: }
! 513: }
! 514: if (mip == NULL && mp_eisa_bus) {
! 515: for (mip = mp_eisa_bus->mb_intrs; mip != NULL;
! 516: mip = mip->next) {
! 517: if (mip->bus_pin == line) {
! 518: ihp->line = mip->ioapic_ih | line;
! 519: return 0;
! 520: }
! 521: }
! 522: }
! 523: if (mip == NULL) {
! 524: printf("pci_intr_map: "
! 525: "bus %d dev %d func %d pin %d; line %d\n",
! 526: bus, dev, func, pin, line);
! 527: printf("pci_intr_map: no MP mapping found\n");
! 528: }
! 529: }
! 530: #endif
! 531:
! 532: return 0;
! 533:
! 534: bad:
! 535: ihp->line = -1;
! 536: return 1;
! 537: }
! 538:
! 539: const char *
! 540: pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih)
! 541: {
! 542: static char irqstr[64];
! 543: int line = ih.line & APIC_INT_LINE_MASK;
! 544:
! 545: #if NIOAPIC > 0
! 546: if (ih.line & APIC_INT_VIA_APIC) {
! 547: snprintf(irqstr, sizeof irqstr, "apic %d int %d (irq %d)",
! 548: APIC_IRQ_APIC(ih.line), APIC_IRQ_PIN(ih.line), line);
! 549: return (irqstr);
! 550: }
! 551: #endif
! 552:
! 553: if (line == 0 || line >= ICU_LEN || line == 2)
! 554: panic("pci_intr_string: bogus handle 0x%x", line);
! 555:
! 556: snprintf(irqstr, sizeof irqstr, "irq %d", line);
! 557: return (irqstr);
! 558: }
! 559:
! 560: void *
! 561: pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
! 562: int (*func)(void *), void *arg, char *what)
! 563: {
! 564: void *ret;
! 565: int l = ih.line & APIC_INT_LINE_MASK;
! 566:
! 567: #if NIOAPIC > 0
! 568: if (l != -1 && ih.line & APIC_INT_VIA_APIC)
! 569: return (apic_intr_establish(ih.line, IST_LEVEL, level, func,
! 570: arg, what));
! 571: #endif
! 572: if (l == 0 || l >= ICU_LEN || l == 2)
! 573: panic("pci_intr_establish: bogus handle 0x%x", l);
! 574:
! 575: ret = isa_intr_establish(NULL, l, IST_LEVEL, level, func, arg, what);
! 576: #if NPCIBIOS > 0
! 577: if (ret)
! 578: pci_intr_route_link(pc, &ih);
! 579: #endif
! 580: return (ret);
! 581: }
! 582:
! 583: void
! 584: pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
! 585: {
! 586: /* XXX oh, unroute the pci int link? */
! 587: isa_intr_disestablish(NULL, cookie);
! 588: }
CVSweb