[BACK]Return to mpbios_intr_fixup.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

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