151d163d3SNathan Whitehorn /*- 251d163d3SNathan Whitehorn * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 351d163d3SNathan Whitehorn * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 451d163d3SNathan Whitehorn * Copyright (c) 2000, BSDi 551d163d3SNathan Whitehorn * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org> 651d163d3SNathan Whitehorn * All rights reserved. 751d163d3SNathan Whitehorn * 851d163d3SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 951d163d3SNathan Whitehorn * modification, are permitted provided that the following conditions 1051d163d3SNathan Whitehorn * are met: 1151d163d3SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 1251d163d3SNathan Whitehorn * notice unmodified, this list of conditions, and the following 1351d163d3SNathan Whitehorn * disclaimer. 1451d163d3SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 1551d163d3SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 1651d163d3SNathan Whitehorn * documentation and/or other materials provided with the distribution. 1751d163d3SNathan Whitehorn * 1851d163d3SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1951d163d3SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2051d163d3SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2151d163d3SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2251d163d3SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2351d163d3SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2451d163d3SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2551d163d3SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2651d163d3SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2751d163d3SNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2851d163d3SNathan Whitehorn */ 2951d163d3SNathan Whitehorn 3051d163d3SNathan Whitehorn #include <sys/cdefs.h> 3151d163d3SNathan Whitehorn __FBSDID("$FreeBSD$"); 3251d163d3SNathan Whitehorn 3351d163d3SNathan Whitehorn #include <sys/param.h> 3451d163d3SNathan Whitehorn #include <sys/bus.h> 3551d163d3SNathan Whitehorn #include <sys/kernel.h> 3651d163d3SNathan Whitehorn #include <sys/libkern.h> 3751d163d3SNathan Whitehorn #include <sys/module.h> 3851d163d3SNathan Whitehorn #include <sys/pciio.h> 3951d163d3SNathan Whitehorn 4051d163d3SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 4151d163d3SNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 4251d163d3SNathan Whitehorn #include <dev/ofw/ofw_pci.h> 4351d163d3SNathan Whitehorn #include <dev/ofw/openfirm.h> 4451d163d3SNathan Whitehorn 4551d163d3SNathan Whitehorn #include <machine/bus.h> 464dea0435SNathan Whitehorn #include <machine/intr_machdep.h> 4751d163d3SNathan Whitehorn #include <machine/resource.h> 4851d163d3SNathan Whitehorn 4951d163d3SNathan Whitehorn #include <dev/pci/pcireg.h> 5051d163d3SNathan Whitehorn #include <dev/pci/pcivar.h> 5151d163d3SNathan Whitehorn #include <dev/pci/pci_private.h> 5251d163d3SNathan Whitehorn 53817ba5c0SNathan Whitehorn #include "ofw_pcibus.h" 5451d163d3SNathan Whitehorn #include "pcib_if.h" 5551d163d3SNathan Whitehorn #include "pci_if.h" 5651d163d3SNathan Whitehorn 5794b4a038SNathan Whitehorn typedef uint32_t ofw_pci_intr_t; 5851d163d3SNathan Whitehorn 5951d163d3SNathan Whitehorn /* Methods */ 6051d163d3SNathan Whitehorn static device_probe_t ofw_pcibus_probe; 6151d163d3SNathan Whitehorn static device_attach_t ofw_pcibus_attach; 62*6cd99ae8SJohn Baldwin static pci_alloc_devinfo_t ofw_pcibus_alloc_devinfo; 6351d163d3SNathan Whitehorn static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; 6451d163d3SNathan Whitehorn static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; 65496dfa89SJohn Baldwin static bus_child_deleted_t ofw_pcibus_child_deleted; 6694b4a038SNathan Whitehorn static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, 6794b4a038SNathan Whitehorn char *buf, size_t buflen); 6894b4a038SNathan Whitehorn 6994b4a038SNathan Whitehorn static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno); 7094b4a038SNathan Whitehorn static void ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno); 7151d163d3SNathan Whitehorn 7251d163d3SNathan Whitehorn static device_method_t ofw_pcibus_methods[] = { 7351d163d3SNathan Whitehorn /* Device interface */ 7451d163d3SNathan Whitehorn DEVMETHOD(device_probe, ofw_pcibus_probe), 7551d163d3SNathan Whitehorn DEVMETHOD(device_attach, ofw_pcibus_attach), 7651d163d3SNathan Whitehorn 7794b4a038SNathan Whitehorn /* Bus interface */ 78496dfa89SJohn Baldwin DEVMETHOD(bus_child_deleted, ofw_pcibus_child_deleted), 7994b4a038SNathan Whitehorn DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method), 8094b4a038SNathan Whitehorn 8151d163d3SNathan Whitehorn /* PCI interface */ 82*6cd99ae8SJohn Baldwin DEVMETHOD(pci_alloc_devinfo, ofw_pcibus_alloc_devinfo), 8351d163d3SNathan Whitehorn DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), 8451d163d3SNathan Whitehorn 8551d163d3SNathan Whitehorn /* ofw_bus interface */ 8651d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo), 8751d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 8851d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 8951d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 9051d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 9151d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 9251d163d3SNathan Whitehorn 93817ba5c0SNathan Whitehorn DEVMETHOD_END 9451d163d3SNathan Whitehorn }; 9551d163d3SNathan Whitehorn 9651d163d3SNathan Whitehorn static devclass_t pci_devclass; 9751d163d3SNathan Whitehorn 981b1596a3SJohn Baldwin DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 991b1596a3SJohn Baldwin sizeof(struct pci_softc), pci_driver); 10051d163d3SNathan Whitehorn DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0); 10151d163d3SNathan Whitehorn MODULE_VERSION(ofw_pcibus, 1); 10251d163d3SNathan Whitehorn MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); 10351d163d3SNathan Whitehorn 1041c5fc51cSNathan Whitehorn static int ofw_devices_only = 0; 1051c5fc51cSNathan Whitehorn TUNABLE_INT("hw.pci.ofw_devices_only", &ofw_devices_only); 1061c5fc51cSNathan Whitehorn 10751d163d3SNathan Whitehorn static int 10851d163d3SNathan Whitehorn ofw_pcibus_probe(device_t dev) 10951d163d3SNathan Whitehorn { 11094b4a038SNathan Whitehorn 1110d8d9edaSNathan Whitehorn if (ofw_bus_get_node(dev) == -1) 11251d163d3SNathan Whitehorn return (ENXIO); 11351d163d3SNathan Whitehorn device_set_desc(dev, "OFW PCI bus"); 11451d163d3SNathan Whitehorn 1151c5fc51cSNathan Whitehorn return (BUS_PROBE_DEFAULT); 11651d163d3SNathan Whitehorn } 11751d163d3SNathan Whitehorn 11851d163d3SNathan Whitehorn static int 11951d163d3SNathan Whitehorn ofw_pcibus_attach(device_t dev) 12051d163d3SNathan Whitehorn { 12194b4a038SNathan Whitehorn u_int busno, domain; 1221b1596a3SJohn Baldwin int error; 12351d163d3SNathan Whitehorn 1241b1596a3SJohn Baldwin error = pci_attach_common(dev); 1251b1596a3SJohn Baldwin if (error) 1261b1596a3SJohn Baldwin return (error); 12751d163d3SNathan Whitehorn domain = pcib_get_domain(dev); 12851d163d3SNathan Whitehorn busno = pcib_get_bus(dev); 12994b4a038SNathan Whitehorn 13094b4a038SNathan Whitehorn /* 13194b4a038SNathan Whitehorn * Attach those children represented in the device tree. 13294b4a038SNathan Whitehorn */ 13394b4a038SNathan Whitehorn 13494b4a038SNathan Whitehorn ofw_pcibus_enum_devtree(dev, domain, busno); 13594b4a038SNathan Whitehorn 13694b4a038SNathan Whitehorn /* 13794b4a038SNathan Whitehorn * We now attach any laggard devices. FDT, for instance, allows 13894b4a038SNathan Whitehorn * the device tree to enumerate only some PCI devices. Apple's 13994b4a038SNathan Whitehorn * OF device tree on some Grackle-based hardware can also miss 14094b4a038SNathan Whitehorn * functions on multi-function cards. 14194b4a038SNathan Whitehorn */ 14294b4a038SNathan Whitehorn 1431c5fc51cSNathan Whitehorn if (!ofw_devices_only) 14494b4a038SNathan Whitehorn ofw_pcibus_enum_bus(dev, domain, busno); 14594b4a038SNathan Whitehorn 14694b4a038SNathan Whitehorn return (bus_generic_attach(dev)); 14794b4a038SNathan Whitehorn } 14894b4a038SNathan Whitehorn 149*6cd99ae8SJohn Baldwin struct pci_devinfo * 150*6cd99ae8SJohn Baldwin ofw_pcibus_alloc_devinfo(device_t dev) 151*6cd99ae8SJohn Baldwin { 152*6cd99ae8SJohn Baldwin struct ofw_pcibus_devinfo *dinfo; 153*6cd99ae8SJohn Baldwin 154*6cd99ae8SJohn Baldwin dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO); 155*6cd99ae8SJohn Baldwin return (&dinfo->opd_dinfo); 156*6cd99ae8SJohn Baldwin } 157*6cd99ae8SJohn Baldwin 15894b4a038SNathan Whitehorn static void 15994b4a038SNathan Whitehorn ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) 16094b4a038SNathan Whitehorn { 16194b4a038SNathan Whitehorn device_t pcib; 16294b4a038SNathan Whitehorn struct ofw_pci_register pcir; 16394b4a038SNathan Whitehorn struct ofw_pcibus_devinfo *dinfo; 16494b4a038SNathan Whitehorn phandle_t node, child; 16594b4a038SNathan Whitehorn u_int func, slot; 16694b4a038SNathan Whitehorn int intline; 16794b4a038SNathan Whitehorn 16894b4a038SNathan Whitehorn pcib = device_get_parent(dev); 16951d163d3SNathan Whitehorn node = ofw_bus_get_node(dev); 17051d163d3SNathan Whitehorn 17151d163d3SNathan Whitehorn for (child = OF_child(node); child != 0; child = OF_peer(child)) { 172509142e1SNathan Whitehorn if (OF_getencprop(child, "reg", (pcell_t *)&pcir, 173509142e1SNathan Whitehorn sizeof(pcir)) == -1) 17451d163d3SNathan Whitehorn continue; 17551d163d3SNathan Whitehorn slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 17651d163d3SNathan Whitehorn func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 17751d163d3SNathan Whitehorn 17851d163d3SNathan Whitehorn /* Some OFW device trees contain dupes. */ 17951d163d3SNathan Whitehorn if (pci_find_dbsf(domain, busno, slot, func) != NULL) 18051d163d3SNathan Whitehorn continue; 18151d163d3SNathan Whitehorn 18294b4a038SNathan Whitehorn /* 18394b4a038SNathan Whitehorn * The preset in the intline register is usually bogus. Reset 18494b4a038SNathan Whitehorn * it such that the PCI code will reroute the interrupt if 18594b4a038SNathan Whitehorn * needed. 18694b4a038SNathan Whitehorn */ 18794b4a038SNathan Whitehorn 18894b4a038SNathan Whitehorn intline = PCI_INVALID_IRQ; 18994b4a038SNathan Whitehorn if (OF_getproplen(child, "interrupts") > 0) 19094b4a038SNathan Whitehorn intline = 0; 19194b4a038SNathan Whitehorn PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE, 19294b4a038SNathan Whitehorn intline, 1); 19394b4a038SNathan Whitehorn 19494b4a038SNathan Whitehorn /* 19594b4a038SNathan Whitehorn * Now set up the PCI and OFW bus layer devinfo and add it 19694b4a038SNathan Whitehorn * to the PCI bus. 19794b4a038SNathan Whitehorn */ 19851d163d3SNathan Whitehorn 199*6cd99ae8SJohn Baldwin dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, dev, 200*6cd99ae8SJohn Baldwin domain, busno, slot, func); 20151d163d3SNathan Whitehorn if (dinfo == NULL) 20251d163d3SNathan Whitehorn continue; 20351d163d3SNathan Whitehorn if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 20451d163d3SNathan Whitehorn 0) { 20551d163d3SNathan Whitehorn pci_freecfg((struct pci_devinfo *)dinfo); 20651d163d3SNathan Whitehorn continue; 20751d163d3SNathan Whitehorn } 208817ba5c0SNathan Whitehorn dinfo->opd_dma_tag = NULL; 20951d163d3SNathan Whitehorn pci_add_child(dev, (struct pci_devinfo *)dinfo); 21051d163d3SNathan Whitehorn 21151d163d3SNathan Whitehorn /* 21251d163d3SNathan Whitehorn * Some devices don't have an intpin set, but do have 21394b4a038SNathan Whitehorn * interrupts. These are fully specified, and set in the 21494b4a038SNathan Whitehorn * interrupts property, so add that value to the device's 21594b4a038SNathan Whitehorn * resource list. 21651d163d3SNathan Whitehorn */ 217c47d4cdeSIan Lepore if (dinfo->opd_dinfo.cfg.intpin == 0) 218a8c5ea04SRuslan Bukin ofw_bus_intr_to_rl(dev, child, 219a8c5ea04SRuslan Bukin &dinfo->opd_dinfo.resources, NULL); 22051d163d3SNathan Whitehorn } 22151d163d3SNathan Whitehorn } 22251d163d3SNathan Whitehorn 22394b4a038SNathan Whitehorn /* 22494b4a038SNathan Whitehorn * The following is an almost exact clone of pci_add_children(), with the 22594b4a038SNathan Whitehorn * addition that it (a) will not add children that have already been added, 22694b4a038SNathan Whitehorn * and (b) will set up the OFW devinfo to point to invalid values. This is 22794b4a038SNathan Whitehorn * to handle non-enumerated PCI children as exist in FDT and on the second 22894b4a038SNathan Whitehorn * function of the Rage 128 in my Blue & White G3. 22994b4a038SNathan Whitehorn */ 23094b4a038SNathan Whitehorn 23194b4a038SNathan Whitehorn static void 23294b4a038SNathan Whitehorn ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno) 23394b4a038SNathan Whitehorn { 23494b4a038SNathan Whitehorn device_t pcib; 23594b4a038SNathan Whitehorn struct ofw_pcibus_devinfo *dinfo; 23694b4a038SNathan Whitehorn int maxslots; 23794b4a038SNathan Whitehorn int s, f, pcifunchigh; 23894b4a038SNathan Whitehorn uint8_t hdrtype; 23994b4a038SNathan Whitehorn 24094b4a038SNathan Whitehorn pcib = device_get_parent(dev); 24194b4a038SNathan Whitehorn 24294b4a038SNathan Whitehorn maxslots = PCIB_MAXSLOTS(pcib); 24394b4a038SNathan Whitehorn for (s = 0; s <= maxslots; s++) { 24494b4a038SNathan Whitehorn pcifunchigh = 0; 24594b4a038SNathan Whitehorn f = 0; 24694b4a038SNathan Whitehorn DELAY(1); 24794b4a038SNathan Whitehorn hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); 24894b4a038SNathan Whitehorn if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 24994b4a038SNathan Whitehorn continue; 25094b4a038SNathan Whitehorn if (hdrtype & PCIM_MFDEV) 25194b4a038SNathan Whitehorn pcifunchigh = PCI_FUNCMAX; 25294b4a038SNathan Whitehorn for (f = 0; f <= pcifunchigh; f++) { 25394b4a038SNathan Whitehorn /* Filter devices we have already added */ 25494b4a038SNathan Whitehorn if (pci_find_dbsf(domain, busno, s, f) != NULL) 25594b4a038SNathan Whitehorn continue; 25694b4a038SNathan Whitehorn 25794b4a038SNathan Whitehorn dinfo = (struct ofw_pcibus_devinfo *)pci_read_device( 258*6cd99ae8SJohn Baldwin pcib, dev, domain, busno, s, f); 259a7a32004SNathan Whitehorn if (dinfo == NULL) 260a7a32004SNathan Whitehorn continue; 261a7a32004SNathan Whitehorn 262817ba5c0SNathan Whitehorn dinfo->opd_dma_tag = NULL; 26394b4a038SNathan Whitehorn dinfo->opd_obdinfo.obd_node = -1; 26494b4a038SNathan Whitehorn 26594b4a038SNathan Whitehorn dinfo->opd_obdinfo.obd_name = NULL; 26694b4a038SNathan Whitehorn dinfo->opd_obdinfo.obd_compat = NULL; 26794b4a038SNathan Whitehorn dinfo->opd_obdinfo.obd_type = NULL; 26894b4a038SNathan Whitehorn dinfo->opd_obdinfo.obd_model = NULL; 269a7a32004SNathan Whitehorn 270a7a32004SNathan Whitehorn /* 271a7a32004SNathan Whitehorn * For non OFW-devices, don't believe 0 272a7a32004SNathan Whitehorn * for an interrupt. 273a7a32004SNathan Whitehorn */ 274a7a32004SNathan Whitehorn if (dinfo->opd_dinfo.cfg.intline == 0) { 275a7a32004SNathan Whitehorn dinfo->opd_dinfo.cfg.intline = PCI_INVALID_IRQ; 276a7a32004SNathan Whitehorn PCIB_WRITE_CONFIG(pcib, busno, s, f, 277a7a32004SNathan Whitehorn PCIR_INTLINE, PCI_INVALID_IRQ, 1); 27894b4a038SNathan Whitehorn } 279a7a32004SNathan Whitehorn 280a7a32004SNathan Whitehorn pci_add_child(dev, (struct pci_devinfo *)dinfo); 28194b4a038SNathan Whitehorn } 28294b4a038SNathan Whitehorn } 28394b4a038SNathan Whitehorn } 28494b4a038SNathan Whitehorn 285496dfa89SJohn Baldwin static void 286496dfa89SJohn Baldwin ofw_pcibus_child_deleted(device_t dev, device_t child) 287496dfa89SJohn Baldwin { 288496dfa89SJohn Baldwin struct ofw_pcibus_devinfo *dinfo; 289496dfa89SJohn Baldwin 290496dfa89SJohn Baldwin dinfo = device_get_ivars(dev); 291496dfa89SJohn Baldwin ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); 292496dfa89SJohn Baldwin pci_child_deleted(dev, child); 293496dfa89SJohn Baldwin } 294496dfa89SJohn Baldwin 29594b4a038SNathan Whitehorn static int 29694b4a038SNathan Whitehorn ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, 29794b4a038SNathan Whitehorn size_t buflen) 29894b4a038SNathan Whitehorn { 29994b4a038SNathan Whitehorn pci_child_pnpinfo_str_method(cbdev, child, buf, buflen); 30094b4a038SNathan Whitehorn 30194b4a038SNathan Whitehorn if (ofw_bus_get_node(child) != -1) { 30294b4a038SNathan Whitehorn strlcat(buf, " ", buflen); /* Separate info */ 30394b4a038SNathan Whitehorn ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen); 30494b4a038SNathan Whitehorn } 30594b4a038SNathan Whitehorn 30694b4a038SNathan Whitehorn return (0); 30751d163d3SNathan Whitehorn } 30851d163d3SNathan Whitehorn 30951d163d3SNathan Whitehorn static int 31051d163d3SNathan Whitehorn ofw_pcibus_assign_interrupt(device_t dev, device_t child) 31151d163d3SNathan Whitehorn { 312bbc6da03SNathan Whitehorn ofw_pci_intr_t intr[2]; 313eaef5f0aSNathan Whitehorn phandle_t node, iparent; 314bbc6da03SNathan Whitehorn int isz, icells; 31551d163d3SNathan Whitehorn 31694b4a038SNathan Whitehorn node = ofw_bus_get_node(child); 31751d163d3SNathan Whitehorn 31894b4a038SNathan Whitehorn if (node == -1) { 31994b4a038SNathan Whitehorn /* Non-firmware enumerated child, use standard routing */ 32051d163d3SNathan Whitehorn 321bbc6da03SNathan Whitehorn intr[0] = pci_get_intpin(child); 32294b4a038SNathan Whitehorn return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, 323bbc6da03SNathan Whitehorn intr[0])); 32494b4a038SNathan Whitehorn } 32594b4a038SNathan Whitehorn 32694b4a038SNathan Whitehorn /* 327eaef5f0aSNathan Whitehorn * Try to determine the node's interrupt parent so we know which 328eaef5f0aSNathan Whitehorn * PIC to use. 329eaef5f0aSNathan Whitehorn */ 330eaef5f0aSNathan Whitehorn 331eaef5f0aSNathan Whitehorn iparent = -1; 332509142e1SNathan Whitehorn if (OF_getencprop(node, "interrupt-parent", &iparent, 333509142e1SNathan Whitehorn sizeof(iparent)) < 0) 334eaef5f0aSNathan Whitehorn iparent = -1; 335bbc6da03SNathan Whitehorn icells = 1; 336bbc6da03SNathan Whitehorn if (iparent != -1) 337509142e1SNathan Whitehorn OF_getencprop(OF_node_from_xref(iparent), "#interrupt-cells", 338bbc6da03SNathan Whitehorn &icells, sizeof(icells)); 339eaef5f0aSNathan Whitehorn 340eaef5f0aSNathan Whitehorn /* 34194b4a038SNathan Whitehorn * Any AAPL,interrupts property gets priority and is 34294b4a038SNathan Whitehorn * fully specified (i.e. does not need routing) 34394b4a038SNathan Whitehorn */ 34494b4a038SNathan Whitehorn 345509142e1SNathan Whitehorn isz = OF_getencprop(node, "AAPL,interrupts", intr, sizeof(intr)); 346bbc6da03SNathan Whitehorn if (isz == sizeof(intr[0])*icells) 347bbc6da03SNathan Whitehorn return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev, 348bbc6da03SNathan Whitehorn iparent, icells, intr)); 34994b4a038SNathan Whitehorn 350509142e1SNathan Whitehorn isz = OF_getencprop(node, "interrupts", intr, sizeof(intr)); 351bbc6da03SNathan Whitehorn if (isz == sizeof(intr[0])*icells) { 352eaef5f0aSNathan Whitehorn if (iparent != -1) 353bbc6da03SNathan Whitehorn intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr); 354eaef5f0aSNathan Whitehorn } else { 355eaef5f0aSNathan Whitehorn /* No property: our best guess is the intpin. */ 356bbc6da03SNathan Whitehorn intr[0] = pci_get_intpin(child); 35794b4a038SNathan Whitehorn } 35894b4a038SNathan Whitehorn 35994b4a038SNathan Whitehorn /* 36094b4a038SNathan Whitehorn * If we got intr from a property, it may or may not be an intpin. 36194b4a038SNathan Whitehorn * For on-board devices, it frequently is not, and is completely out 36294b4a038SNathan Whitehorn * of the valid intpin range. For PCI slots, it hopefully is, 36394b4a038SNathan Whitehorn * otherwise we will have trouble interfacing with non-OFW buses 36494b4a038SNathan Whitehorn * such as cardbus. 36594b4a038SNathan Whitehorn * Since we cannot tell which it is without violating layering, we 36694b4a038SNathan Whitehorn * will always use the route_interrupt method, and treat exceptions 36794b4a038SNathan Whitehorn * on the level they become apparent. 36894b4a038SNathan Whitehorn */ 369bbc6da03SNathan Whitehorn return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0])); 37051d163d3SNathan Whitehorn } 37151d163d3SNathan Whitehorn 37251d163d3SNathan Whitehorn static const struct ofw_bus_devinfo * 37351d163d3SNathan Whitehorn ofw_pcibus_get_devinfo(device_t bus, device_t dev) 37451d163d3SNathan Whitehorn { 37551d163d3SNathan Whitehorn struct ofw_pcibus_devinfo *dinfo; 37651d163d3SNathan Whitehorn 37751d163d3SNathan Whitehorn dinfo = device_get_ivars(dev); 37851d163d3SNathan Whitehorn return (&dinfo->opd_obdinfo); 37951d163d3SNathan Whitehorn } 38051d163d3SNathan Whitehorn 381