amd64: Copy MPTable PCI interrput routing code from i386
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 10 Jul 2009 11:12:51 +0000 (19:12 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 11 Jul 2009 02:27:18 +0000 (10:27 +0800)
Following three commits on i386 are merged:
eaec4152c00f8d7503f218f2a246802044d2600e
566f2cdcd40f5829aedb2c0b2a8339e189c7570d
6fd2232c44c5937a832a5b929989de0b1ddfc9de

sys/bus/pci/amd64/mptable_pci.c [new file with mode: 0644]
sys/bus/pci/amd64/pci_cfgreg.c
sys/platform/pc64/amd64/mp_machdep.c
sys/platform/pc64/conf/files

diff --git a/sys/bus/pci/amd64/mptable_pci.c b/sys/bus/pci/amd64/mptable_pci.c
new file mode 100644 (file)
index 0000000..bf6d915
--- /dev/null
@@ -0,0 +1,238 @@
+/*-
+ * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD @169221
+ */
+
+/*
+ * Host to PCI and PCI to PCI bridge drivers that use the MP Table to route
+ * interrupts from PCI devices to I/O APICs.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcib_private.h>
+
+#include <machine/smp.h>
+
+#include "legacyvar.h"
+#include "pci_cfgreg.h"
+
+#include "pcib_if.h"
+
+static int
+mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+       int line, bus, slot;
+
+       bus = pci_get_bus(dev);
+       slot = pci_get_slot(dev);
+
+       line = pci_apic_irq(bus, slot, pin);
+       if (line >= 0) {
+               return line;
+       } else {
+               int irq = pci_get_irq(dev);
+
+               /* 
+                * PCI interrupts might be redirected to the
+                * ISA bus according to some MP tables.  Use the
+                * same methods as used by the ISA devices
+                * devices to find the proper IOAPIC int pin.
+                */
+               kprintf("MPTable: Try routing through ISA bus for "
+                       "bus %d slot %d INT%c irq %d\n",
+                       bus, slot, 'A' + pin - 1, irq);
+               line = isa_apic_irq(irq);
+               if (line >= 0)
+                       return line;
+       }
+
+       kprintf("MPTable: Unable to route for bus %d slot %d INT%c\n",
+               bus, slot, 'A' + pin - 1);
+       return PCI_INVALID_IRQ;
+}
+
+/* Host to PCI bridge driver. */
+
+static int
+mptable_hostb_probe(device_t dev)
+{
+
+       if (pci_cfgregopen() == 0)
+               return (ENXIO);
+#ifdef notyet
+       if (mptable_pci_probe_table(pcib_get_bus(dev)) != 0)
+               return (ENXIO);
+#endif
+       device_set_desc(dev, "MPTable Host-PCI bridge");
+       return (0);
+}
+
+static int
+mptable_hostb_attach(device_t dev)
+{
+
+       device_add_child(dev, "pci", pcib_get_bus(dev));
+       return (bus_generic_attach(dev));
+}
+
+/* Pass MSI requests up to the nexus. */
+static int
+mptable_hostb_alloc_msi(device_t pcib, device_t dev, int count, int maxcount,
+    int *irqs)
+{
+       device_t bus;
+
+       bus = device_get_parent(pcib);
+       return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount,
+           irqs));
+}
+
+static int
+mptable_hostb_alloc_msix(device_t pcib, device_t dev, int *irq)
+{
+       device_t bus;
+
+       bus = device_get_parent(pcib);
+       return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq));
+}
+
+static int
+mptable_hostb_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
+    uint32_t *data)
+{
+       device_t bus;
+
+       bus = device_get_parent(pcib);
+       return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+}
+
+static device_method_t mptable_hostb_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         mptable_hostb_probe),
+       DEVMETHOD(device_attach,        mptable_hostb_attach),
+       DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+       DEVMETHOD(device_suspend,       bus_generic_suspend),
+       DEVMETHOD(device_resume,        bus_generic_resume),
+
+       /* Bus interface */
+       DEVMETHOD(bus_print_child,      bus_generic_print_child),
+       DEVMETHOD(bus_read_ivar,        legacy_pcib_read_ivar),
+       DEVMETHOD(bus_write_ivar,       legacy_pcib_write_ivar),
+       DEVMETHOD(bus_alloc_resource,   legacy_pcib_alloc_resource),
+       DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+       DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+       DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+       DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+       DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
+
+       /* pcib interface */
+       DEVMETHOD(pcib_maxslots,        legacy_pcib_maxslots),
+       DEVMETHOD(pcib_read_config,     legacy_pcib_read_config),
+       DEVMETHOD(pcib_write_config,    legacy_pcib_write_config),
+       DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt),
+       DEVMETHOD(pcib_alloc_msi,       mptable_hostb_alloc_msi),
+       DEVMETHOD(pcib_release_msi,     pcib_release_msi),
+       DEVMETHOD(pcib_alloc_msix,      mptable_hostb_alloc_msix),
+       DEVMETHOD(pcib_release_msix,    pcib_release_msix),
+       DEVMETHOD(pcib_map_msi,         mptable_hostb_map_msi),
+
+       { 0, 0 }
+};
+
+static devclass_t hostb_devclass;
+
+DEFINE_CLASS_0(pcib, mptable_hostb_driver, mptable_hostb_methods, 1);
+DRIVER_MODULE(mptable_pcib, legacy, mptable_hostb_driver, hostb_devclass, 0, 0);
+
+/* PCI to PCI bridge driver. */
+
+static int
+mptable_pcib_probe(device_t dev)
+{
+       int bus;
+
+       if ((pci_get_class(dev) != PCIC_BRIDGE) ||
+           (pci_get_subclass(dev) != PCIS_BRIDGE_PCI))
+               return (ENXIO);
+       bus = pci_read_config(dev, PCIR_SECBUS_1, 1);
+       if (bus == 0)
+               return (ENXIO);
+#ifdef notyet
+       if (mptable_pci_probe_table(bus) != 0)
+               return (ENXIO);
+#endif
+       device_set_desc(dev, "MPTable PCI-PCI bridge");
+       return (-500);
+}
+
+static device_method_t mptable_pcib_pci_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         mptable_pcib_probe),
+       DEVMETHOD(device_attach,        pcib_attach),
+       DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+       DEVMETHOD(device_suspend,       bus_generic_suspend),
+       DEVMETHOD(device_resume,        bus_generic_resume),
+
+       /* Bus interface */
+       DEVMETHOD(bus_print_child,      bus_generic_print_child),
+       DEVMETHOD(bus_read_ivar,        pcib_read_ivar),
+       DEVMETHOD(bus_write_ivar,       pcib_write_ivar),
+       DEVMETHOD(bus_alloc_resource,   pcib_alloc_resource),
+       DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+       DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+       DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+       DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+       DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
+
+       /* pcib interface */
+       DEVMETHOD(pcib_maxslots,        pcib_maxslots),
+       DEVMETHOD(pcib_read_config,     pcib_read_config),
+       DEVMETHOD(pcib_write_config,    pcib_write_config),
+       DEVMETHOD(pcib_route_interrupt, mptable_pci_route_interrupt),
+       DEVMETHOD(pcib_alloc_msi,       pcib_alloc_msi),
+       DEVMETHOD(pcib_release_msi,     pcib_release_msi),
+       DEVMETHOD(pcib_alloc_msix,      pcib_alloc_msix),
+       DEVMETHOD(pcib_release_msix,    pcib_release_msix),
+       DEVMETHOD(pcib_map_msi,         pcib_map_msi),
+
+       {0, 0}
+};
+
+static devclass_t pcib_devclass;
+
+DEFINE_CLASS_0(pcib, mptable_pcib_driver, mptable_pcib_pci_methods,
+    sizeof(struct pcib_softc));
+DRIVER_MODULE(mptable_pcib, pci, mptable_pcib_driver, pcib_devclass, 0, 0);
index 165b8e0..21f0b51 100644 (file)
@@ -42,9 +42,6 @@
 #include <bus/pci/pcireg.h>
 #include "pci_cfgreg.h"
 #include <machine/pc/bios.h>
-#ifdef APIC_IO
-#include <machine/smp.h>
-#endif
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -201,48 +198,7 @@ u_int32_t
 pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
 {
        uint32_t line;
-#ifdef APIC_IO
-       uint32_t pin;
-
-       /*
-        * If we are using the APIC, the contents of the intline
-        * register will probably be wrong (since they are set up for
-        * use with the PIC.  Rather than rewrite these registers
-        * (maybe that would be smarter) we trap attempts to read them
-        * and translate to our private vector numbers.
-        */
-       if ((reg == PCIR_INTLINE) && (bytes == 1)) {
 
-               pin = pcireg_cfgread(bus, slot, func, PCIR_INTPIN, 1);
-               line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
-
-               if (pin != 0) {
-                       int airq;
-
-                       airq = pci_apic_irq(bus, slot, pin);
-                       if (airq >= 0) {
-                               /* PCI specific entry found in MP table */
-                               if (airq != line)
-                                       undirect_pci_irq(line);
-                               return (airq);
-                       } else {
-                               /* 
-                                * PCI interrupts might be redirected to the
-                                * ISA bus according to some MP tables. Use the
-                                * same methods as used by the ISA devices
-                                * devices to find the proper IOAPIC int pin.
-                                */
-                               airq = isa_apic_irq(line);
-                               if ((airq >= 0) && (airq != line)) {
-                                       /* XXX: undirect_pci_irq() ? */
-                                       undirect_isa_irq(line);
-                                       return (airq);
-                               }
-                       }
-               }
-               return (line);
-       }
-#else
        /*
         * Some BIOS writers seem to want to ignore the spec and put
         * 0 in the intline rather than 255 to indicate none.  The rest of
@@ -252,7 +208,6 @@ pci_cfgregread(int bus, int slot, int func, int reg, int bytes)
                line = pcireg_cfgread(bus, slot, func, PCIR_INTLINE, 1);
                return (pci_i386_map_intline(line));
        }
-#endif /* APIC_IO */
        return (pcireg_cfgread(bus, slot, func, reg, bytes));
 }
 
index dab1fc5..c532aa8 100644 (file)
@@ -1135,7 +1135,6 @@ allocate_apic_irq(int intr)
        intpin = io_apic_ints[intr].dst_apic_int;
        
        assign_apic_irq(apic, intpin, irq);
-       io_apic_setup_intpin(apic, intpin);
 }
 
 
@@ -1444,7 +1443,14 @@ setup_apic_irq_mapping(void)
                        break;
                }
        }
-       /* PCI interrupt assignment is deferred */
+
+       /* Assign PCI interrupts */
+       for (x = 0; x < nintrs; ++x) {
+               if (io_apic_ints[x].int_type == 0 &&
+                   io_apic_ints[x].int_vector == 0xff && 
+                   apic_int_is_bus_type(x, PCI))
+                       allocate_apic_irq(x);
+       }
 }
 
 #endif
@@ -1649,10 +1655,11 @@ pci_apic_irq(int pciBus, int pciDevice, int pciInt)
                    && (SRCBUSDEVICE(intr) == pciDevice)
                    && (SRCBUSLINE(intr) == pciInt)) {  /* a candidate IRQ */
                        if (apic_int_is_bus_type(intr, PCI)) {
-                               if (INTIRQ(intr) == 0xff)
-                                       allocate_apic_irq(intr);
-                               if (INTIRQ(intr) == 0xff)
+                               if (INTIRQ(intr) == 0xff) {
+                                       kprintf("IOAPIC: pci_apic_irq() "
+                                               "failed\n");
                                        return -1;      /* unassigned */
+                               }
                                return INTIRQ(intr);    /* exact match */
                        }
                }
index 088c105..2b6a29d 100644 (file)
@@ -137,6 +137,7 @@ platform/pc64/icu/icu_vector.s          standard
 bus/pci/amd64/legacy.c                 optional        pci
 bus/pci/amd64/pci_bus.c                        optional        pci
 bus/pci/amd64/pci_cfgreg.c             optional        pci
+bus/pci/amd64/mptable_pci.c            optional        pci smp apic_io
 # notyet (BIOS struct and functions)
 #bus/pci/amd64/pci_pir.c                       optional        pci