Annotation of sys/arch/i386/i386/mpbios_intr_fixup.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mpbios_intr_fixup.c,v 1.3 2006/07/17 21:56:39 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Mark Kettenis
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/param.h>
! 20: #include <sys/systm.h>
! 21:
! 22: #include <dev/pci/pcireg.h>
! 23: #include <dev/pci/pcivar.h>
! 24: #include <dev/pci/pcidevs.h>
! 25:
! 26: #include <machine/i82093var.h>
! 27: #include <machine/mpbiosvar.h>
! 28:
! 29: void mpbios_pin_fixup(int, int, int, int);
! 30: const struct mpbios_icu_table *mpbios_icu_lookup(pcireg_t);
! 31:
! 32: void via8237_mpbios_fixup(pci_chipset_tag_t, pcitag_t);
! 33: void nforce4_mpbios_fixup(pci_chipset_tag_t, pcitag_t);
! 34: void mcp04_mpbios_fixup(pci_chipset_tag_t, pcitag_t);
! 35:
! 36: const struct mpbios_icu_table {
! 37: pci_vendor_id_t mpit_vendor;
! 38: pci_product_id_t mpit_product;
! 39: void (*mpit_mpbios_fixup)(pci_chipset_tag_t, pcitag_t);
! 40: } mpbios_icu_table[] = {
! 41: { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8237_ISA,
! 42: via8237_mpbios_fixup },
! 43: { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_ISA,
! 44: nforce4_mpbios_fixup },
! 45: { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_ISA2,
! 46: nforce4_mpbios_fixup },
! 47: { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_ISA,
! 48: mcp04_mpbios_fixup }
! 49: };
! 50:
! 51: const struct mpbios_icu_table *
! 52: mpbios_icu_lookup(pcireg_t id)
! 53: {
! 54: const struct mpbios_icu_table *mpit;
! 55:
! 56: for (mpit = mpbios_icu_table; mpit->mpit_mpbios_fixup != NULL; mpit++)
! 57: if (PCI_VENDOR(id) == mpit->mpit_vendor &&
! 58: PCI_PRODUCT(id) == mpit->mpit_product)
! 59: return (mpit);
! 60:
! 61: return (NULL);
! 62: }
! 63:
! 64: /*
! 65: * NVIDIA nForce4 PCI-ISA bridge.
! 66: */
! 67:
! 68: #define NFORCE4_PNPIRQ1 0x7c
! 69: #define NFORCE4_PNPIRQ2 0x80
! 70: #define NFORCE4_USB2_SHIFT 12
! 71: #define NFORCE4_USB2_MASK (0xf << NFORCE4_USB2_SHIFT)
! 72: #define NFORCE4_SATA1_SHIFT 28
! 73: #define NFORCE4_SATA1_MASK (0xf << NFORCE4_SATA1_SHIFT)
! 74: #define NFORCE4_SATA2_SHIFT 24
! 75: #define NFORCE4_SATA2_MASK (0xf << NFORCE4_SATA2_SHIFT)
! 76: #define NFORCE4_PNPIRQ3 0x84
! 77: #define NFORCE4_USB1_SHIFT 0
! 78: #define NFORCE4_USB1_MASK (0xf << NFORCE4_USB1_SHIFT)
! 79: #define NFORCE4_LAN_SHIFT 8
! 80: #define NFORCE4_LAN_MASK (0xf << NFORCE4_LAN_SHIFT)
! 81:
! 82: void
! 83: nforce4_mpbios_fixup(pci_chipset_tag_t pc, pcitag_t tag)
! 84: {
! 85: pcireg_t reg;
! 86: int bus, pin;
! 87:
! 88: pci_decompose_tag (pc, tag, &bus, NULL, NULL);
! 89:
! 90: reg = pci_conf_read(pc, tag, NFORCE4_PNPIRQ2);
! 91: pin = (reg & NFORCE4_USB2_MASK) >> NFORCE4_USB2_SHIFT;
! 92: if (pin != 0)
! 93: mpbios_pin_fixup(bus, 2, PCI_INTERRUPT_PIN_B, pin);
! 94: pin = (reg & NFORCE4_SATA1_MASK) >> NFORCE4_SATA1_SHIFT;
! 95: if (pin != 0)
! 96: mpbios_pin_fixup(bus, 7, PCI_INTERRUPT_PIN_A, pin);
! 97: pin = (reg & NFORCE4_SATA2_MASK) >> NFORCE4_SATA2_SHIFT;
! 98: if (pin != 0)
! 99: mpbios_pin_fixup(bus, 8, PCI_INTERRUPT_PIN_A, pin);
! 100:
! 101: reg = pci_conf_read(pc, tag, NFORCE4_PNPIRQ3);
! 102: pin = (reg & NFORCE4_USB1_MASK) >> NFORCE4_USB1_SHIFT;
! 103: if (pin != 0)
! 104: mpbios_pin_fixup(bus, 2, PCI_INTERRUPT_PIN_A, pin);
! 105: pin = (reg & NFORCE4_LAN_MASK) >> NFORCE4_LAN_SHIFT;
! 106: if (pin != 0)
! 107: mpbios_pin_fixup(bus, 10, PCI_INTERRUPT_PIN_A, pin);
! 108: }
! 109:
! 110: /*
! 111: * NVIDIA MCP04 PCI-ISA bridge.
! 112: */
! 113:
! 114: void
! 115: mcp04_mpbios_fixup(pci_chipset_tag_t pc, pcitag_t tag)
! 116: {
! 117: pcireg_t reg;
! 118: int bus, pin;
! 119:
! 120: pci_decompose_tag (pc, tag, &bus, NULL, NULL);
! 121:
! 122: reg = pci_conf_read(pc, tag, NFORCE4_PNPIRQ2);
! 123: pin = (reg & NFORCE4_SATA1_MASK) >> NFORCE4_SATA1_SHIFT;
! 124: if (pin != 0)
! 125: mpbios_pin_fixup(bus, 16, PCI_INTERRUPT_PIN_A, pin);
! 126: pin = (reg & NFORCE4_SATA2_MASK) >> NFORCE4_SATA2_SHIFT;
! 127: if (pin != 0)
! 128: mpbios_pin_fixup(bus, 17, PCI_INTERRUPT_PIN_A, pin);
! 129: }
! 130:
! 131: /*
! 132: * VIA VT8237 PCI-ISA bridge.
! 133: */
! 134:
! 135: void
! 136: via8237_mpbios_fixup(pci_chipset_tag_t pc, pcitag_t tag)
! 137: {
! 138: int bus;
! 139:
! 140: pci_decompose_tag (pc, tag, &bus, NULL, NULL);
! 141:
! 142: /* SATA is hardwired to APIC pin 20. */
! 143: mpbios_pin_fixup(bus, 15, 2, 20);
! 144: }
! 145:
! 146: void
! 147: mpbios_pin_fixup(int bus, int dev, int rawpin, int pin)
! 148: {
! 149: struct mp_bus *mpb = &mp_busses[bus];
! 150: struct mp_intr_map *mip;
! 151:
! 152: for (mip = mpb->mb_intrs; mip != NULL; mip = mip->next) {
! 153: if (mip->bus_pin == ((dev << 2) | (rawpin - 1)) &&
! 154: mip->ioapic_pin != pin) {
! 155:
! 156: if (mp_verbose) {
! 157:
! 158: printf("%s: int%d attached to %s",
! 159: mip->ioapic->sc_dev.dv_xname,
! 160: pin, mpb->mb_name);
! 161:
! 162: if (mpb->mb_idx != -1)
! 163: printf("%d", mpb->mb_idx);
! 164:
! 165: (*(mpb->mb_intr_print))(mip->bus_pin);
! 166:
! 167: printf(" (fixup)\n");
! 168: }
! 169:
! 170: mip->ioapic_pin = pin;
! 171: mip->ioapic_ih &= ~APIC_INT_PIN_MASK;
! 172: mip->ioapic_ih |= (pin << APIC_INT_PIN_SHIFT);
! 173: if (mip->ioapic->sc_pins[pin].ip_map == NULL)
! 174: mip->ioapic->sc_pins[pin].ip_map = mip;
! 175: }
! 176: }
! 177: }
! 178:
! 179: void
! 180: mpbios_intr_fixup(void)
! 181: {
! 182: const struct mpbios_icu_table *mpit = NULL;
! 183: pci_chipset_tag_t pc = NULL;
! 184: pcitag_t icutag;
! 185: int device, maxdevs = pci_bus_maxdevs(pc, 0);
! 186:
! 187: /* Search configuration space for a known interrupt router. */
! 188: for (device = 0; device < maxdevs; device++) {
! 189: const struct pci_quirkdata *qd;
! 190: int function, nfuncs;
! 191: pcireg_t icuid;
! 192: pcireg_t bhlcr;
! 193:
! 194: icutag = pci_make_tag(pc, 0, device, 0);
! 195: icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
! 196:
! 197: /* Invalid vendor ID value? */
! 198: if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
! 199: continue;
! 200:
! 201: qd = pci_lookup_quirkdata(PCI_VENDOR(icuid),
! 202: PCI_PRODUCT(icuid));
! 203:
! 204: bhlcr = pci_conf_read(pc, icutag, PCI_BHLC_REG);
! 205: if (PCI_HDRTYPE_MULTIFN(bhlcr) || (qd != NULL &&
! 206: (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
! 207: nfuncs = 8;
! 208: else
! 209: nfuncs = 1;
! 210:
! 211: for (function = 0; function < nfuncs; function++) {
! 212: icutag = pci_make_tag(pc, 0, device, function);
! 213: icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
! 214:
! 215: /* Invalid vendor ID value? */
! 216: if (PCI_VENDOR(icuid) == PCI_VENDOR_INVALID)
! 217: continue;
! 218:
! 219: if ((mpit = mpbios_icu_lookup(icuid)))
! 220: break;
! 221: }
! 222:
! 223: if (mpit != NULL)
! 224: break;
! 225: }
! 226:
! 227: if (mpit)
! 228: mpit->mpit_mpbios_fixup(pc, icutag);
! 229: }
CVSweb