151d163d3SNathan Whitehorn /*- 251d163d3SNathan Whitehorn * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 351d163d3SNathan Whitehorn * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 451d163d3SNathan Whitehorn * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 551d163d3SNathan Whitehorn * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 651d163d3SNathan Whitehorn * Copyright (c) 2000, BSDi 751d163d3SNathan Whitehorn * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org> 851d163d3SNathan Whitehorn * All rights reserved. 951d163d3SNathan Whitehorn * 1051d163d3SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 1151d163d3SNathan Whitehorn * modification, are permitted provided that the following conditions 1251d163d3SNathan Whitehorn * are met: 1351d163d3SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 1451d163d3SNathan Whitehorn * notice unmodified, this list of conditions, and the following 1551d163d3SNathan Whitehorn * disclaimer. 1651d163d3SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 1751d163d3SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 1851d163d3SNathan Whitehorn * documentation and/or other materials provided with the distribution. 1951d163d3SNathan Whitehorn * 2051d163d3SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2151d163d3SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2251d163d3SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2351d163d3SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2451d163d3SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2551d163d3SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2651d163d3SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2751d163d3SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2851d163d3SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2951d163d3SNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3051d163d3SNathan Whitehorn */ 3151d163d3SNathan Whitehorn 3251d163d3SNathan Whitehorn #include <sys/cdefs.h> 3351d163d3SNathan Whitehorn __FBSDID("$FreeBSD$"); 3451d163d3SNathan Whitehorn 3551d163d3SNathan Whitehorn #include <sys/param.h> 3651d163d3SNathan Whitehorn #include <sys/bus.h> 3751d163d3SNathan Whitehorn #include <sys/kernel.h> 3851d163d3SNathan Whitehorn #include <sys/libkern.h> 3951d163d3SNathan Whitehorn #include <sys/module.h> 4051d163d3SNathan Whitehorn #include <sys/pciio.h> 4151d163d3SNathan Whitehorn 4251d163d3SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 4351d163d3SNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 4451d163d3SNathan Whitehorn #include <dev/ofw/ofw_pci.h> 4551d163d3SNathan Whitehorn #include <dev/ofw/openfirm.h> 4651d163d3SNathan Whitehorn 4751d163d3SNathan Whitehorn #include <machine/bus.h> 4851d163d3SNathan Whitehorn #include <machine/resource.h> 4951d163d3SNathan Whitehorn 5051d163d3SNathan Whitehorn #include <dev/pci/pcireg.h> 5151d163d3SNathan Whitehorn #include <dev/pci/pcivar.h> 5251d163d3SNathan Whitehorn #include <dev/pci/pci_private.h> 5351d163d3SNathan Whitehorn 5451d163d3SNathan Whitehorn #include "pcib_if.h" 5551d163d3SNathan Whitehorn #include "pci_if.h" 5651d163d3SNathan Whitehorn 5751d163d3SNathan Whitehorn /* Helper functions */ 5851d163d3SNathan Whitehorn static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *); 5951d163d3SNathan Whitehorn static int ofw_pci_find_intline(phandle_t node, uint32_t *irqs); 6051d163d3SNathan Whitehorn static void ofw_pci_fixup_node(device_t dev, phandle_t node); 6151d163d3SNathan Whitehorn 6251d163d3SNathan Whitehorn /* Methods */ 6351d163d3SNathan Whitehorn static device_probe_t ofw_pcibus_probe; 6451d163d3SNathan Whitehorn static device_attach_t ofw_pcibus_attach; 6551d163d3SNathan Whitehorn static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; 6651d163d3SNathan Whitehorn static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; 6751d163d3SNathan Whitehorn 6851d163d3SNathan Whitehorn static device_method_t ofw_pcibus_methods[] = { 6951d163d3SNathan Whitehorn /* Device interface */ 7051d163d3SNathan Whitehorn DEVMETHOD(device_probe, ofw_pcibus_probe), 7151d163d3SNathan Whitehorn DEVMETHOD(device_attach, ofw_pcibus_attach), 7251d163d3SNathan Whitehorn 7351d163d3SNathan Whitehorn /* PCI interface */ 7451d163d3SNathan Whitehorn DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), 7551d163d3SNathan Whitehorn 7651d163d3SNathan Whitehorn /* ofw_bus interface */ 7751d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo), 7851d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 7951d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 8051d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 8151d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 8251d163d3SNathan Whitehorn DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 8351d163d3SNathan Whitehorn 8451d163d3SNathan Whitehorn { 0, 0 } 8551d163d3SNathan Whitehorn }; 8651d163d3SNathan Whitehorn 8751d163d3SNathan Whitehorn struct ofw_pcibus_devinfo { 8851d163d3SNathan Whitehorn struct pci_devinfo opd_dinfo; 8951d163d3SNathan Whitehorn struct ofw_bus_devinfo opd_obdinfo; 9051d163d3SNathan Whitehorn }; 9151d163d3SNathan Whitehorn 9251d163d3SNathan Whitehorn static devclass_t pci_devclass; 9351d163d3SNathan Whitehorn 9451d163d3SNathan Whitehorn DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods, 1 /* no softc */, 9551d163d3SNathan Whitehorn pci_driver); 9651d163d3SNathan Whitehorn DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0); 9751d163d3SNathan Whitehorn MODULE_VERSION(ofw_pcibus, 1); 9851d163d3SNathan Whitehorn MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); 9951d163d3SNathan Whitehorn 10051d163d3SNathan Whitehorn static int 10151d163d3SNathan Whitehorn ofw_pcibus_probe(device_t dev) 10251d163d3SNathan Whitehorn { 10351d163d3SNathan Whitehorn if (ofw_bus_get_node(dev) == 0) 10451d163d3SNathan Whitehorn return (ENXIO); 10551d163d3SNathan Whitehorn device_set_desc(dev, "OFW PCI bus"); 10651d163d3SNathan Whitehorn 10751d163d3SNathan Whitehorn return (0); 10851d163d3SNathan Whitehorn } 10951d163d3SNathan Whitehorn 11051d163d3SNathan Whitehorn static int 11151d163d3SNathan Whitehorn ofw_pcibus_attach(device_t dev) 11251d163d3SNathan Whitehorn { 11351d163d3SNathan Whitehorn device_t pcib; 11451d163d3SNathan Whitehorn struct ofw_pci_register pcir; 11551d163d3SNathan Whitehorn struct ofw_pcibus_devinfo *dinfo; 11651d163d3SNathan Whitehorn phandle_t node, child; 11751d163d3SNathan Whitehorn u_int busno, domain, func, slot; 11851d163d3SNathan Whitehorn 11951d163d3SNathan Whitehorn pcib = device_get_parent(dev); 12051d163d3SNathan Whitehorn domain = pcib_get_domain(dev); 12151d163d3SNathan Whitehorn busno = pcib_get_bus(dev); 12251d163d3SNathan Whitehorn if (bootverbose) 12351d163d3SNathan Whitehorn device_printf(dev, "domain=%d, physical bus=%d\n", 12451d163d3SNathan Whitehorn domain, busno); 12551d163d3SNathan Whitehorn node = ofw_bus_get_node(dev); 12651d163d3SNathan Whitehorn 12751d163d3SNathan Whitehorn for (child = OF_child(node); child != 0; child = OF_peer(child)) { 12851d163d3SNathan Whitehorn if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) 12951d163d3SNathan Whitehorn continue; 13051d163d3SNathan Whitehorn slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 13151d163d3SNathan Whitehorn func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 13251d163d3SNathan Whitehorn 13351d163d3SNathan Whitehorn /* Some OFW device trees contain dupes. */ 13451d163d3SNathan Whitehorn if (pci_find_dbsf(domain, busno, slot, func) != NULL) 13551d163d3SNathan Whitehorn continue; 13651d163d3SNathan Whitehorn 13751d163d3SNathan Whitehorn ofw_pci_fixup_node(pcib, child); 13851d163d3SNathan Whitehorn 13951d163d3SNathan Whitehorn dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, 14051d163d3SNathan Whitehorn domain, busno, slot, func, sizeof(*dinfo)); 14151d163d3SNathan Whitehorn 14251d163d3SNathan Whitehorn if (dinfo == NULL) 14351d163d3SNathan Whitehorn continue; 14451d163d3SNathan Whitehorn 14551d163d3SNathan Whitehorn /* Set up OFW devinfo */ 14651d163d3SNathan Whitehorn if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 14751d163d3SNathan Whitehorn 0) { 14851d163d3SNathan Whitehorn pci_freecfg((struct pci_devinfo *)dinfo); 14951d163d3SNathan Whitehorn continue; 15051d163d3SNathan Whitehorn } 15151d163d3SNathan Whitehorn 15251d163d3SNathan Whitehorn pci_add_child(dev, (struct pci_devinfo *)dinfo); 15351d163d3SNathan Whitehorn 15451d163d3SNathan Whitehorn /* 15551d163d3SNathan Whitehorn * Some devices don't have an intpin set, but do have 15651d163d3SNathan Whitehorn * interrupts. Add them to the appropriate resource list. 15751d163d3SNathan Whitehorn */ 15851d163d3SNathan Whitehorn if (dinfo->opd_dinfo.cfg.intpin == 0) { 15951d163d3SNathan Whitehorn uint32_t irqs[4]; 16051d163d3SNathan Whitehorn 16151d163d3SNathan Whitehorn if (ofw_pci_find_intline(child, irqs) > 0) 16251d163d3SNathan Whitehorn resource_list_add(&dinfo->opd_dinfo.resources, 16351d163d3SNathan Whitehorn SYS_RES_IRQ, 0, irqs[0], irqs[0], 1); 16451d163d3SNathan Whitehorn } 16551d163d3SNathan Whitehorn } 16651d163d3SNathan Whitehorn 16751d163d3SNathan Whitehorn return (bus_generic_attach(dev)); 16851d163d3SNathan Whitehorn } 16951d163d3SNathan Whitehorn 17051d163d3SNathan Whitehorn static int 17151d163d3SNathan Whitehorn ofw_pcibus_assign_interrupt(device_t dev, device_t child) 17251d163d3SNathan Whitehorn { 17351d163d3SNathan Whitehorn uint32_t irqs[4]; 17451d163d3SNathan Whitehorn 17551d163d3SNathan Whitehorn device_printf(child,"Assigning interrupt\n"); 17651d163d3SNathan Whitehorn 17751d163d3SNathan Whitehorn if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0) 17851d163d3SNathan Whitehorn return PCI_INVALID_IRQ; 17951d163d3SNathan Whitehorn 18051d163d3SNathan Whitehorn device_printf(child,"IRQ %d\n",irqs[0]); 18151d163d3SNathan Whitehorn 18251d163d3SNathan Whitehorn return irqs[0]; 18351d163d3SNathan Whitehorn 18451d163d3SNathan Whitehorn // return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); 18551d163d3SNathan Whitehorn } 18651d163d3SNathan Whitehorn 18751d163d3SNathan Whitehorn static const struct ofw_bus_devinfo * 18851d163d3SNathan Whitehorn ofw_pcibus_get_devinfo(device_t bus, device_t dev) 18951d163d3SNathan Whitehorn { 19051d163d3SNathan Whitehorn struct ofw_pcibus_devinfo *dinfo; 19151d163d3SNathan Whitehorn 19251d163d3SNathan Whitehorn dinfo = device_get_ivars(dev); 19351d163d3SNathan Whitehorn return (&dinfo->opd_obdinfo); 19451d163d3SNathan Whitehorn } 19551d163d3SNathan Whitehorn 19651d163d3SNathan Whitehorn static void 19751d163d3SNathan Whitehorn ofw_pci_fixup_node(device_t dev, phandle_t node) 19851d163d3SNathan Whitehorn { 19951d163d3SNathan Whitehorn uint32_t csr, intr, irqs[4]; 20051d163d3SNathan Whitehorn struct ofw_pci_register addr[8]; 20151d163d3SNathan Whitehorn int len, i; 20251d163d3SNathan Whitehorn 20351d163d3SNathan Whitehorn len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); 20451d163d3SNathan Whitehorn if (len < (int)sizeof(struct ofw_pci_register)) { 20551d163d3SNathan Whitehorn return; 20651d163d3SNathan Whitehorn } 20751d163d3SNathan Whitehorn 20851d163d3SNathan Whitehorn csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), 20951d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), 21051d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4); 21151d163d3SNathan Whitehorn csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); 21251d163d3SNathan Whitehorn 21351d163d3SNathan Whitehorn for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) { 21451d163d3SNathan Whitehorn switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 21551d163d3SNathan Whitehorn case OFW_PCI_PHYS_HI_SPACE_IO: 21651d163d3SNathan Whitehorn csr |= PCIM_CMD_PORTEN; 21751d163d3SNathan Whitehorn break; 21851d163d3SNathan Whitehorn case OFW_PCI_PHYS_HI_SPACE_MEM32: 21951d163d3SNathan Whitehorn csr |= PCIM_CMD_MEMEN; 22051d163d3SNathan Whitehorn break; 22151d163d3SNathan Whitehorn } 22251d163d3SNathan Whitehorn } 22351d163d3SNathan Whitehorn 22451d163d3SNathan Whitehorn PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), 22551d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), 22651d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4); 22751d163d3SNathan Whitehorn 22851d163d3SNathan Whitehorn if (ofw_pci_find_intline(node, irqs) != -1) { 22951d163d3SNathan Whitehorn intr = PCIB_READ_CONFIG(dev, 23051d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), 23151d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), 23251d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2); 23351d163d3SNathan Whitehorn intr &= ~(0xff); 23451d163d3SNathan Whitehorn intr |= irqs[0] & 0xff; 23551d163d3SNathan Whitehorn PCIB_WRITE_CONFIG(dev, 23651d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), 23751d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), 23851d163d3SNathan Whitehorn OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 23951d163d3SNathan Whitehorn intr, 2); 24051d163d3SNathan Whitehorn } 24151d163d3SNathan Whitehorn } 24251d163d3SNathan Whitehorn 24351d163d3SNathan Whitehorn static int 24451d163d3SNathan Whitehorn ofw_pci_find_intline(phandle_t node, uint32_t *irqs) 24551d163d3SNathan Whitehorn { 24651d163d3SNathan Whitehorn uint32_t npintr, paddr[4]; 24751d163d3SNathan Whitehorn struct ofw_pci_register addr[8]; 24851d163d3SNathan Whitehorn int len; 24951d163d3SNathan Whitehorn 25051d163d3SNathan Whitehorn len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); 25151d163d3SNathan Whitehorn if (len < (int)sizeof(struct ofw_pci_register)) 25251d163d3SNathan Whitehorn return -1; 25351d163d3SNathan Whitehorn /* 25451d163d3SNathan Whitehorn * Create PCI interrupt-map array element. pci-mid/pci-lo 25551d163d3SNathan Whitehorn * aren't required, but the 'interrupts' property needs 25651d163d3SNathan Whitehorn * to be appended 25751d163d3SNathan Whitehorn */ 25851d163d3SNathan Whitehorn npintr = 0; 25951d163d3SNathan Whitehorn OF_getprop(node, "interrupts", &npintr, 4); 26051d163d3SNathan Whitehorn paddr[0] = addr[0].phys_hi; 26151d163d3SNathan Whitehorn paddr[1] = 0; 26251d163d3SNathan Whitehorn paddr[2] = 0; 26351d163d3SNathan Whitehorn paddr[3] = npintr; 26451d163d3SNathan Whitehorn 26551d163d3SNathan Whitehorn return find_node_intr(node, paddr, irqs); 26651d163d3SNathan Whitehorn } 26751d163d3SNathan Whitehorn 26851d163d3SNathan Whitehorn static int 26951d163d3SNathan Whitehorn find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr) 27051d163d3SNathan Whitehorn { 27151d163d3SNathan Whitehorn phandle_t parent, iparent; 27251d163d3SNathan Whitehorn int len, mlen, match, i; 27351d163d3SNathan Whitehorn u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells; 27451d163d3SNathan Whitehorn char name[32]; 27551d163d3SNathan Whitehorn 27651d163d3SNathan Whitehorn len = OF_getprop(node, "AAPL,interrupts", intr, 4); 27751d163d3SNathan Whitehorn if (len == 4) { 27851d163d3SNathan Whitehorn return (len); 27951d163d3SNathan Whitehorn } 28051d163d3SNathan Whitehorn 28151d163d3SNathan Whitehorn parent = OF_parent(node); 28251d163d3SNathan Whitehorn len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); 28351d163d3SNathan Whitehorn mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask)); 28451d163d3SNathan Whitehorn 28551d163d3SNathan Whitehorn if (len == -1 || mlen == -1) 28651d163d3SNathan Whitehorn goto nomap; 28751d163d3SNathan Whitehorn 28851d163d3SNathan Whitehorn memcpy(maskedaddr, addr, mlen); 28951d163d3SNathan Whitehorn for (i = 0; i < mlen/4; i++) 29051d163d3SNathan Whitehorn maskedaddr[i] &= imask[i]; 29151d163d3SNathan Whitehorn 29251d163d3SNathan Whitehorn mp = map; 29351d163d3SNathan Whitehorn while (len > mlen) { 29451d163d3SNathan Whitehorn match = bcmp(maskedaddr, mp, mlen); 29551d163d3SNathan Whitehorn mp += mlen / 4; 29651d163d3SNathan Whitehorn len -= mlen; 29751d163d3SNathan Whitehorn 29851d163d3SNathan Whitehorn /* 29951d163d3SNathan Whitehorn * We must read "#interrupt-cells" for each time because 30051d163d3SNathan Whitehorn * interrupt-parent may be different. 30151d163d3SNathan Whitehorn */ 30251d163d3SNathan Whitehorn iparent = *mp++; 30351d163d3SNathan Whitehorn len -= 4; 30451d163d3SNathan Whitehorn if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4) 30551d163d3SNathan Whitehorn goto nomap; 30651d163d3SNathan Whitehorn 30751d163d3SNathan Whitehorn /* Found. */ 30851d163d3SNathan Whitehorn if (match == 0) { 30951d163d3SNathan Whitehorn bcopy(mp, intr, icells * 4); 31051d163d3SNathan Whitehorn return (icells * 4); 31151d163d3SNathan Whitehorn } 31251d163d3SNathan Whitehorn 31351d163d3SNathan Whitehorn mp += icells; 31451d163d3SNathan Whitehorn len -= icells * 4; 31551d163d3SNathan Whitehorn } 31651d163d3SNathan Whitehorn 31751d163d3SNathan Whitehorn nomap: 31851d163d3SNathan Whitehorn /* 31951d163d3SNathan Whitehorn * Check for local properties indicating interrupts 32051d163d3SNathan Whitehorn */ 32151d163d3SNathan Whitehorn 32251d163d3SNathan Whitehorn len = OF_getprop(node, "interrupts", intr, 16); 32351d163d3SNathan Whitehorn if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) == 32451d163d3SNathan Whitehorn sizeof(iparent)) { 32551d163d3SNathan Whitehorn OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells)); 32651d163d3SNathan Whitehorn for (i = 0; i < len/icells/4; i++) 32751d163d3SNathan Whitehorn intr[i] = intr[i*icells]; 32851d163d3SNathan Whitehorn 32951d163d3SNathan Whitehorn return (len); 33051d163d3SNathan Whitehorn } 33151d163d3SNathan Whitehorn 33251d163d3SNathan Whitehorn 33351d163d3SNathan Whitehorn /* 33451d163d3SNathan Whitehorn * If the node has no interrupt property and the parent is a PCI 33551d163d3SNathan Whitehorn * bridge, use the parent's interrupt. This occurs on a PCI slot. 33651d163d3SNathan Whitehorn */ 33751d163d3SNathan Whitehorn bzero(name, sizeof(name)); 33851d163d3SNathan Whitehorn OF_getprop(parent, "name", name, sizeof(name)); 33951d163d3SNathan Whitehorn if (strcmp(name, "pci-bridge") == 0) { 34051d163d3SNathan Whitehorn len = OF_getprop(parent, "AAPL,interrupts", intr, 4); 34151d163d3SNathan Whitehorn if (len == 4) { 34251d163d3SNathan Whitehorn return (len); 34351d163d3SNathan Whitehorn } 34451d163d3SNathan Whitehorn 34551d163d3SNathan Whitehorn /* 34651d163d3SNathan Whitehorn * XXX I don't know what is the correct local address. 34751d163d3SNathan Whitehorn * XXX Use the first entry for now. 34851d163d3SNathan Whitehorn */ 34951d163d3SNathan Whitehorn len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); 35051d163d3SNathan Whitehorn if (len >= 36) { 35151d163d3SNathan Whitehorn addr = &map[5]; 35251d163d3SNathan Whitehorn /* XXX Use 0 for 'interrupts' for compat */ 35351d163d3SNathan Whitehorn return (find_node_intr(parent, addr, intr)); 35451d163d3SNathan Whitehorn } 35551d163d3SNathan Whitehorn } 35651d163d3SNathan Whitehorn 35751d163d3SNathan Whitehorn return (-1); 35851d163d3SNathan Whitehorn } 35951d163d3SNathan Whitehorn 360