root/arch/i386/i386/mpbios_intr_fixup.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mpbios_icu_lookup
  2. nforce4_mpbios_fixup
  3. mcp04_mpbios_fixup
  4. via8237_mpbios_fixup
  5. mpbios_pin_fixup
  6. mpbios_intr_fixup

    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 }

/* [<][>][^][v][top][bottom][index][help] */