summaryrefslogtreecommitdiffstats
path: root/sys/amd64/pci/pci_bus.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2002-09-06 22:19:39 +0000
committerjhb <jhb@FreeBSD.org>2002-09-06 22:19:39 +0000
commit68e5e76cede25e8d91ce33a551c67480ace95ca0 (patch)
tree920f72d0ca4237b9d0412288685397aa6cff5211 /sys/amd64/pci/pci_bus.c
parent891a98175a25e80a82abab8a370a4d36e99baa73 (diff)
downloadFreeBSD-src-68e5e76cede25e8d91ce33a551c67480ace95ca0.zip
FreeBSD-src-68e5e76cede25e8d91ce33a551c67480ace95ca0.tar.gz
Add a subclass of the PCI-PCI bridge driver that uses the PCIBIOS to
route interrupts if the child bus is described in the PCIBIOS interrupt routing table. For child busses that are in the routing table, they do not necessarily use a 'swizzle' on their pins on the parent bus to route interrupts for child devices. If the child bus is an embedded device then the pins on the child devices can be (and usually are) directly connected either to a PIC or to a Interrupt Router. This fixes PCIBIOS interrupt routing across PCI-PCI bridges for embedded devices.
Diffstat (limited to 'sys/amd64/pci/pci_bus.c')
-rw-r--r--sys/amd64/pci/pci_bus.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c
index 1315d55..64b98e6 100644
--- a/sys/amd64/pci/pci_bus.c
+++ b/sys/amd64/pci/pci_bus.c
@@ -36,6 +36,7 @@
#include <pci/pcivar.h>
#include <pci/pcireg.h>
+#include <pci/pcib_private.h>
#include <isa/isavar.h>
#include <machine/nexusvar.h>
#include <machine/pci_cfgreg.h>
@@ -48,6 +49,9 @@
#include "pcib_if.h"
+static int pcibios_pcib_route_interrupt(device_t pcib, device_t dev,
+ int pin);
+
static int
nexus_pcib_maxslots(device_t dev)
{
@@ -77,8 +81,7 @@ nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
static int
nexus_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
{
- return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
- pci_get_irq(dev)));
+ return (pcibios_pcib_route_interrupt(pcib, dev, pin));
}
static devclass_t pcib_devclass;
@@ -619,3 +622,67 @@ static driver_t pcibus_pnp_driver = {
static devclass_t pcibus_pnp_devclass;
DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0);
+
+
+/*
+ * Provide a PCI-PCI bridge driver for PCI busses behind PCI-PCI bridges
+ * that appear in the PCIBIOS Interrupt Routing Table to use the routing
+ * table for interrupt routing when possible.
+ */
+static int pcibios_pcib_probe(device_t bus);
+
+static device_method_t pcibios_pcib_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pcibios_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, pcibios_pcib_route_interrupt),
+
+ {0, 0}
+};
+
+static driver_t pcibios_pcib_driver = {
+ "pcib",
+ pcibios_pcib_pci_methods,
+ sizeof(struct pcib_softc),
+};
+
+DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, pcib_devclass, 0, 0);
+
+static int
+pcibios_pcib_probe(device_t dev)
+{
+
+ if ((pci_get_class(dev) != PCIC_BRIDGE) ||
+ (pci_get_subclass(dev) != PCIS_BRIDGE_PCI))
+ return (ENXIO);
+ if (pci_probe_route_table(pcib_get_bus(dev)) == 0)
+ return (ENXIO);
+ device_set_desc(dev, "PCIBIOS PCI-PCI bridge");
+ return (-2000);
+}
+
+static int
+pcibios_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin,
+ pci_get_irq(dev)));
+}
OpenPOWER on IntegriCloud