--- //depot/vendor/freebsd/src/sys/conf/files.sparc64 2008/09/28 00:10:14 +++ //depot/projects/ppc-g5/sys/conf/files.sparc64 2008/11/17 02:23:57 @@ -121,7 +123,6 @@ sparc64/sparc64/mp_locore.S optional smp sparc64/sparc64/mp_machdep.c optional smp sparc64/sparc64/nexus.c standard -sparc64/sparc64/ofw_bus.c standard sparc64/sparc64/ofw_machdep.c standard sparc64/sparc64/pmap.c standard sparc64/sparc64/prof_machdep.c optional profiling-routine --- //depot/vendor/freebsd/src/sys/conf/files.sun4v 2008/09/03 17:35:14 +++ //depot/projects/ppc-g5/sys/conf/files.sun4v 2008/11/18 13:52:59 @@ -65,7 +67,6 @@ sun4v/sun4v/mp_machdep.c optional smp sun4v/sun4v/nexus.c standard sun4v/cddl/t1_copy.S standard -sparc64/sparc64/ofw_bus.c standard sparc64/sparc64/ofw_machdep.c standard sun4v/sun4v/pmap.c standard sparc64/sparc64/prof_machdep.c optional profiling-routine --- //depot/vendor/freebsd/src/sys/dev/ofw/ofw_bus_subr.c 2005/11/22 16:40:37 +++ //depot/projects/ppc-g5/sys/dev/ofw/ofw_bus_subr.c 2008/11/18 13:41:50 @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2001 - 2003 by Thomas Moestl . * Copyright (c) 2005 Marius Strobl * All rights reserved. * @@ -126,3 +127,135 @@ return (NULL); return (obd->obd_type); } + +static int +ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen) +{ + int rv; + + for (; node != 0; node = OF_parent(node)) { + if ((rv = OF_getprop(node, propname, buf, buflen)) != -1) + return (rv); + } + return (-1); +} + +void +ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz) +{ + pcell_t addrc; + int msksz; + + if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1) + addrc = 2; + ii->opi_addrc = addrc * sizeof(pcell_t); + + ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1, + (void **)&ii->opi_imap); + if (ii->opi_imapsz > 0) { + msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1, + (void **)&ii->opi_imapmsk); + /* + * Failure to get the mask is ignored; a full mask is used then. + * Barf on bad mask sizes, however. + */ + if (msksz != -1 && msksz != ii->opi_addrc + intrsz) { + panic("ofw_bus_setup_iinfo: bad interrupt-map-mask " + "property!"); + } + } + +} + +int +ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, + int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz, + void *maskbuf) +{ + int rv; + + if (ii->opi_imapsz <= 0) + return (0); + KASSERT(regsz >= ii->opi_addrc, + ("ofw_bus_lookup_imap: register size too small: %d < %d", + regsz, ii->opi_addrc)); + rv = OF_getprop(node, "reg", reg, regsz); + if (rv < regsz) + panic("ofw_bus_lookup_imap: could not get reg property"); + return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc, + ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr, + mintrsz)); +} + +/* + * Map an interrupt using the firmware reg, interrupt-map and + * interrupt-map-mask properties. + * The interrupt property to be mapped must be of size intrsz, and pointed to + * by intr. The regs property of the node for which the mapping is done must + * be passed as regs. This property is an array of register specifications; + * the size of the address part of such a specification must be passed as + * physsz. Only the first element of the property is used. + * imap and imapsz hold the interrupt mask and it's size. + * imapmsk is a pointer to the interrupt-map-mask property, which must have + * a size of physsz + intrsz; it may be NULL, in which case a full mask is + * assumed. + * maskbuf must point to a buffer of length physsz + intrsz. + * The interrupt is returned in result, which must point to a buffer of length + * rintrsz (which gives the expected size of the mapped interrupt). + * Returns 1 if a mapping was found, 0 otherwise. + */ +int +ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, + void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result, + int rintrsz) +{ + phandle_t parent; + u_int8_t *ref = maskbuf; + u_int8_t *uiintr = intr; + u_int8_t *uiregs = regs; + u_int8_t *uiimapmsk = imapmsk; + u_int8_t *mptr; + pcell_t pintrsz; + int i, rsz, tsz; + + rsz = -1; + if (imapmsk != NULL) { + for (i = 0; i < physsz; i++) + ref[i] = uiregs[i] & uiimapmsk[i]; + for (i = 0; i < intrsz; i++) + ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i]; + } else { + bcopy(regs, ref, physsz); + bcopy(intr, ref + physsz, intrsz); + } + + mptr = imap; + i = imapsz; + tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz; + while (i > 0) { + KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map")); + bcopy(mptr + physsz + intrsz, &parent, sizeof(parent)); + if (ofw_bus_searchprop(parent, "#interrupt-cells", + &pintrsz, sizeof(pintrsz)) == -1) + pintrsz = 1; /* default */ + pintrsz *= sizeof(pcell_t); + if (pintrsz != rintrsz) + panic("ofw_bus_search_intrmap: expected interrupt cell " + "size incorrect: %d > %d", rintrsz, pintrsz); + + /* + * XXX: Apple hardware used a second cell to set information + * on the interrupt trigger type. This information should + * be used. + */ + + if (bcmp(ref, mptr, physsz + intrsz) == 0) { + bcopy(mptr + physsz + intrsz + sizeof(parent), + result, rintrsz); + return (1); + } + mptr += tsz; + i -= tsz; + } + return (0); +} --- //depot/vendor/freebsd/src/sys/dev/ofw/ofw_bus_subr.h 2005/11/22 16:40:37 +++ //depot/projects/ppc-g5/sys/dev/ofw/ofw_bus_subr.h 2008/11/17 02:23:57 @@ -37,9 +37,27 @@ #include "ofw_bus_if.h" +#define ORIP_NOINT -1 +#define ORIR_NOTFOUND 0xffffffff + +struct ofw_bus_iinfo { + u_int8_t *opi_imap; + u_int8_t *opi_imapmsk; + int opi_imapsz; + pcell_t opi_addrc; +}; + int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t); void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *); +/* Routines for processing firmware interrupt maps */ + +void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int); +int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, + void *, int, void *, int, void *); +int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, + void *, void *, int); + ofw_bus_get_compat_t ofw_bus_gen_get_compat; ofw_bus_get_model_t ofw_bus_gen_get_model; ofw_bus_get_name_t ofw_bus_gen_get_name; --- //depot/vendor/freebsd/src/sys/powerpc/include/param.h 2008/03/27 05:05:14 +++ //depot/projects/ppc-g5/sys/powerpc/include/param.h 2008/10/21 02:31:49 @@ -56,6 +56,9 @@ #ifndef _NO_NAMESPACE_POLLUTION +/* Needed to display interrupts on OFW PCI */ +#define __PCI_REROUTE_INTERRUPT + #ifndef _MACHINE_PARAM_H_ #define _MACHINE_PARAM_H_ --- //depot/vendor/freebsd/src/sys/powerpc/ofw/ofw_pcib_pci.c 2008/10/14 14:55:20 +++ //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcib_pci.c 2008/11/17 02:23:57 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,8 @@ static int ofw_pcib_pci_probe(device_t bus); static int ofw_pcib_pci_attach(device_t bus); static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev); +static int ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, + int intpin); static device_method_t ofw_pcib_pci_methods[] = { /* Device interface */ @@ -70,7 +73,7 @@ DEVMETHOD(pcib_maxslots, pcib_maxslots), DEVMETHOD(pcib_read_config, pcib_read_config), DEVMETHOD(pcib_write_config, pcib_write_config), - DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), + DEVMETHOD(pcib_route_interrupt, ofw_pcib_pci_route_interrupt), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pcib_pci_get_node), @@ -80,8 +83,20 @@ static devclass_t pcib_devclass; +struct ofw_pcib_softc { + /* + * This is here so that we can use pci bridge methods, too - the + * generic routines only need the dev, secbus and subbus members + * filled. + */ + struct pcib_softc ops_pcib_sc; + phandle_t ops_node; + struct ofw_bus_iinfo ops_iinfo; +}; + + DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods, - sizeof(struct pcib_softc)); + sizeof(struct ofw_pcib_softc)); DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0); static int @@ -103,6 +118,15 @@ static int ofw_pcib_pci_attach(device_t dev) { + struct ofw_pcib_softc *sc; + + sc = device_get_softc(dev); + sc->ops_pcib_sc.dev = dev; + sc->ops_node = ofw_bus_get_node(dev); + + ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo, + sizeof(cell_t)); + pcib_attach_common(dev); device_add_child(dev, "pci", -1); @@ -110,7 +134,7 @@ return (bus_generic_attach(dev)); } -phandle_t +static phandle_t ofw_pcib_pci_get_node(device_t bridge, device_t dev) { /* We have only one child, the PCI bus, so pass it our node */ @@ -118,3 +142,37 @@ return (ofw_bus_get_node(bridge)); } +static int +ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin) +{ + struct ofw_pcib_softc *sc; + struct ofw_bus_iinfo *ii; + struct ofw_pci_register reg; + cell_t pintr, mintr; + uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; + + sc = device_get_softc(bridge); + ii = &sc->ops_iinfo; + if (ii->opi_imapsz > 0) { + pintr = intpin; + if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, ®, + sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), + maskbuf)) { + /* + * If we've found a mapping, return it and don't map + * it again on higher levels - that causes problems + * in some cases, and never seems to be required. + */ + return (mintr); + } + } else if (intpin >= 1 && intpin <= 4) { + /* + * When an interrupt map is missing, we need to do the + * standard PCI swizzle and continue mapping at the parent. + */ + return (pcib_route_interrupt(bridge, dev, intpin)); + } + return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent( + bridge)), bridge, intpin)); +} + --- //depot/vendor/freebsd/src/sys/powerpc/ofw/ofw_pcibus.c 2008/10/14 14:55:20 +++ //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcibus.c 2008/11/17 02:23:57 @@ -1,6 +1,4 @@ /*- - * Copyright (c) 1994 Charles M. Hannum. All rights reserved. - * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * Copyright (c) 1997, Stefan Esser * Copyright (c) 2000, Michael Smith * Copyright (c) 2000, BSDi @@ -30,7 +28,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/powerpc/ofw/ofw_pcibus.c,v 1.1 2008/10/14 14:54:14 nwhitehorn Exp $"); +__FBSDID("$FreeBSD: src/sys/sparc64/pci/ofw_pcibus.c,v 1.21 2008/08/24 15:05:46 marius Exp $"); #include #include @@ -54,10 +52,11 @@ #include "pcib_if.h" #include "pci_if.h" +typedef uint32_t ofw_pci_intr_t; + /* Helper functions */ -static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *); -static int ofw_pci_find_intline(phandle_t node, uint32_t *irqs); -static void ofw_pci_fixup_node(device_t dev, phandle_t node); +static void ofw_pcibus_setup_device(device_t bridge, phandle_t dev, + uint32_t clock, u_int busno, u_int slot, u_int func); /* Methods */ static device_probe_t ofw_pcibus_probe; @@ -70,6 +69,8 @@ DEVMETHOD(device_probe, ofw_pcibus_probe), DEVMETHOD(device_attach, ofw_pcibus_attach), + /* Bus interface */ + /* PCI interface */ DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), @@ -100,6 +101,7 @@ static int ofw_pcibus_probe(device_t dev) { + if (ofw_bus_get_node(dev) == 0) return (ENXIO); device_set_desc(dev, "OFW PCI bus"); @@ -107,6 +109,26 @@ return (0); } +/* + * Perform miscellaneous setups the firmware usually does not do for us. + */ +static void +ofw_pcibus_setup_device(device_t bridge, phandle_t dev, uint32_t clock, + u_int busno, u_int slot, u_int func) +{ + int intline = PCI_INVALID_IRQ; + + /* + * The preset in the intline register is usually wrong. Reset + * it to 255, so that the PCI code will reroute the interrupt if + * needed. + */ + if (OF_getproplen(dev, "interrupts") > 0) + intline = 0; + PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_INTLINE, + intline, 1); +} + static int ofw_pcibus_attach(device_t dev) { @@ -114,6 +136,7 @@ struct ofw_pci_register pcir; struct ofw_pcibus_devinfo *dinfo; phandle_t node, child; + uint32_t clock; u_int busno, domain, func, slot; pcib = device_get_parent(dev); @@ -124,44 +147,44 @@ domain, busno); node = ofw_bus_get_node(dev); + if (OF_getprop(ofw_bus_get_node(pcib), "clock-frequency", &clock, + sizeof(clock)) == -1) + clock = 33000000; for (child = OF_child(node); child != 0; child = OF_peer(child)) { if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) continue; slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); - /* Some OFW device trees contain dupes. */ if (pci_find_dbsf(domain, busno, slot, func) != NULL) continue; - - ofw_pci_fixup_node(pcib, child); - + ofw_pcibus_setup_device(pcib, child, clock, busno, slot, func); dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, domain, busno, slot, func, sizeof(*dinfo)); - if (dinfo == NULL) continue; - - /* Set up OFW devinfo */ if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 0) { pci_freecfg((struct pci_devinfo *)dinfo); continue; } - pci_add_child(dev, (struct pci_devinfo *)dinfo); /* - * Some devices don't have an intpin set, but do have - * interrupts. Add them to the appropriate resource list. - */ - if (dinfo->opd_dinfo.cfg.intpin == 0) { - uint32_t irqs[4]; + * Some devices don't have an intpin set, but do have + * interrupts. These are fully specified, and set in the + * interrupts property, so add that value to the device's + * resource list. + */ + if (dinfo->opd_dinfo.cfg.intpin == 0) { + ofw_pci_intr_t intr; - if (ofw_pci_find_intline(child, irqs) > 0) - resource_list_add(&dinfo->opd_dinfo.resources, - SYS_RES_IRQ, 0, irqs[0], irqs[0], 1); - } + if (OF_getprop(child, "interrupts", &intr, + sizeof(intr)) > 0) { + resource_list_add(&dinfo->opd_dinfo.resources, + SYS_RES_IRQ, 0, intr, intr, 1); + } + } } return (bus_generic_attach(dev)); @@ -170,18 +193,34 @@ static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { - uint32_t irqs[4]; + ofw_pci_intr_t intr; + int isz; - device_printf(child,"Assigning interrupt\n"); + /* Any AAPL,interrupts property gets priority and is fully spec'ed */ - if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0) - return PCI_INVALID_IRQ; + isz = OF_getprop(ofw_bus_get_node(child), "AAPL,interrupts", &intr, + sizeof(intr)); + if (isz == sizeof(intr)) { + return (intr); + } - device_printf(child,"IRQ %d\n",irqs[0]); - - return irqs[0]; - -// return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); + isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, + sizeof(intr)); + if (isz != sizeof(intr)) { + /* No property; our best guess is the intpin. */ + intr = pci_get_intpin(child); + } + /* + * If we got intr from a property, it may or may not be an intpin. + * For on-board devices, it frequently is not, and is completely out + * of the valid intpin range. For PCI slots, it hopefully is, + * otherwise we will have trouble interfacing with non-OFW buses + * such as cardbus. + * Since we cannot tell which it is without violating layering, we + * will always use the route_interrupt method, and treat exceptions + * on the level they become apparent. + */ + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); } static const struct ofw_bus_devinfo * @@ -193,167 +232,3 @@ return (&dinfo->opd_obdinfo); } -static void -ofw_pci_fixup_node(device_t dev, phandle_t node) -{ - uint32_t csr, intr, irqs[4]; - struct ofw_pci_register addr[8]; - int len, i; - - len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); - if (len < (int)sizeof(struct ofw_pci_register)) { - return; - } - - csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), - OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), - OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4); - csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); - - for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) { - switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) { - case OFW_PCI_PHYS_HI_SPACE_IO: - csr |= PCIM_CMD_PORTEN; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM32: - csr |= PCIM_CMD_MEMEN; - break; - } - } - - PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), - OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), - OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4); - - if (ofw_pci_find_intline(node, irqs) != -1) { - intr = PCIB_READ_CONFIG(dev, - OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), - OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), - OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2); - intr &= ~(0xff); - intr |= irqs[0] & 0xff; - PCIB_WRITE_CONFIG(dev, - OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), - OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), - OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, - intr, 2); - } -} - -static int -ofw_pci_find_intline(phandle_t node, uint32_t *irqs) -{ - uint32_t npintr, paddr[4]; - struct ofw_pci_register addr[8]; - int len; - - len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); - if (len < (int)sizeof(struct ofw_pci_register)) - return -1; - /* - * Create PCI interrupt-map array element. pci-mid/pci-lo - * aren't required, but the 'interrupts' property needs - * to be appended - */ - npintr = 0; - OF_getprop(node, "interrupts", &npintr, 4); - paddr[0] = addr[0].phys_hi; - paddr[1] = 0; - paddr[2] = 0; - paddr[3] = npintr; - - return find_node_intr(node, paddr, irqs); -} - -static int -find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr) -{ - phandle_t parent, iparent; - int len, mlen, match, i; - u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells; - char name[32]; - - len = OF_getprop(node, "AAPL,interrupts", intr, 4); - if (len == 4) { - return (len); - } - - parent = OF_parent(node); - len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); - mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask)); - - if (len == -1 || mlen == -1) - goto nomap; - - memcpy(maskedaddr, addr, mlen); - for (i = 0; i < mlen/4; i++) - maskedaddr[i] &= imask[i]; - - mp = map; - while (len > mlen) { - match = bcmp(maskedaddr, mp, mlen); - mp += mlen / 4; - len -= mlen; - - /* - * We must read "#interrupt-cells" for each time because - * interrupt-parent may be different. - */ - iparent = *mp++; - len -= 4; - if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4) - goto nomap; - - /* Found. */ - if (match == 0) { - bcopy(mp, intr, icells * 4); - return (icells * 4); - } - - mp += icells; - len -= icells * 4; - } - -nomap: - /* - * Check for local properties indicating interrupts - */ - - len = OF_getprop(node, "interrupts", intr, 16); - if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) == - sizeof(iparent)) { - OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells)); - for (i = 0; i < len/icells/4; i++) - intr[i] = intr[i*icells]; - - return (len); - } - - - /* - * If the node has no interrupt property and the parent is a PCI - * bridge, use the parent's interrupt. This occurs on a PCI slot. - */ - bzero(name, sizeof(name)); - OF_getprop(parent, "name", name, sizeof(name)); - if (strcmp(name, "pci-bridge") == 0) { - len = OF_getprop(parent, "AAPL,interrupts", intr, 4); - if (len == 4) { - return (len); - } - - /* - * XXX I don't know what is the correct local address. - * XXX Use the first entry for now. - */ - len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); - if (len >= 36) { - addr = &map[5]; - /* XXX Use 0 for 'interrupts' for compat */ - return (find_node_intr(parent, addr, intr)); - } - } - - return (-1); -} - --- //depot/vendor/freebsd/src/sys/powerpc/powermac/grackle.c 2008/10/14 14:55:20 +++ //depot/projects/ppc-g5/sys/powerpc/powermac/grackle.c 2008/11/17 02:29:09 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -164,7 +165,7 @@ grackle_attach(device_t dev) { struct grackle_softc *sc; - phandle_t node; + phandle_t node, iparent; u_int32_t busrange[2]; struct grackle_range *rp, *io, *mem[2]; int nmem, i, error; @@ -251,6 +252,16 @@ } } + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + + /* We need the number of interrupt cells to read the imap */ + if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) <= 0) + iparent = node; + + if (OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells, + sizeof(sc->sc_icells)) <= 0) + sc->sc_icells = 1; + device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); } @@ -335,8 +346,25 @@ static int grackle_route_interrupt(device_t bus, device_t dev, int pin) { + struct grackle_softc *sc; + struct ofw_pci_register reg; + uint32_t pintr, mintr[2]; + uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; + + sc = device_get_softc(bus); + pintr = pin; + if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, + sizeof(reg), &pintr, sizeof(pintr), &mintr, + sizeof(mintr[0])*sc->sc_icells, maskbuf)) + return (mintr[0]); - return (0); + /* Maybe it's a real interrupt, not an intpin */ + if (pin > 4) + return (pin); + + device_printf(bus, "could not route pin %d for device %d.%d\n", + pin, pci_get_slot(dev), pci_get_function(dev)); + return (PCI_INVALID_IRQ); } static int --- //depot/vendor/freebsd/src/sys/powerpc/powermac/gracklevar.h 2005/01/07 02:32:16 +++ //depot/projects/ppc-g5/sys/powerpc/powermac/gracklevar.h 2008/11/14 04:47:43 @@ -52,6 +52,9 @@ struct rman sc_mem_rman; bus_space_tag_t sc_memt; bus_dma_tag_t sc_dmat; + int sc_icells; + + struct ofw_bus_iinfo sc_pci_iinfo; }; /* --- //depot/vendor/freebsd/src/sys/powerpc/powermac/uninorth.c 2008/10/14 14:55:20 +++ //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c 2008/11/17 02:23:57 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -163,8 +164,7 @@ { struct uninorth_softc *sc; const char *compatible; - phandle_t node; - phandle_t child; + phandle_t node, child, iparent; u_int32_t reg[2], busrange[2]; struct uninorth_range *rp, *io, *mem[2]; int nmem, i, error; @@ -294,6 +294,14 @@ } } + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + + /* We need the number of interrupt cells to read the imap */ + sc->sc_icells = 2; + if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) > 0) + OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells, + sizeof(sc->sc_icells)); + device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); } @@ -360,8 +368,25 @@ static int uninorth_route_interrupt(device_t bus, device_t dev, int pin) { + struct uninorth_softc *sc; + struct ofw_pci_register reg; + uint32_t pintr, mintr[2]; + uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; - return (0); + sc = device_get_softc(bus); + pintr = pin; + if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, + sizeof(reg), &pintr, sizeof(pintr), mintr, + sizeof(mintr[0])*sc->sc_icells, maskbuf)) + return (mintr[0]); + + /* Maybe it's a real interrupt, not an intpin */ + if (pin > 4) + return (pin); + + device_printf(bus, "could not route pin %d for device %d.%d\n", + pin, pci_get_slot(dev), pci_get_function(dev)); + return (PCI_INVALID_IRQ); } static int --- //depot/vendor/freebsd/src/sys/powerpc/powermac/uninorthvar.h 2008/10/14 14:55:20 +++ //depot/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h 2008/11/14 04:47:43 @@ -61,8 +61,10 @@ bus_space_tag_t sc_iot; bus_space_tag_t sc_memt; bus_dma_tag_t sc_dmat; + struct ofw_bus_iinfo sc_pci_iinfo; int sc_u3; + int sc_icells; }; struct unin_chip_softc { --- //depot/vendor/freebsd/src/sys/sparc64/ebus/ebus.c 2008/08/23 15:45:13 +++ //depot/projects/ppc-g5/sys/sparc64/ebus/ebus.c 2008/11/17 02:23:57 @@ -51,7 +51,6 @@ #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/include/ofw_machdep.h 2005/02/12 19:15:37 +++ //depot/projects/ppc-g5/sys/sparc64/include/ofw_machdep.h 2008/11/17 01:51:19 @@ -29,10 +29,15 @@ #define _MACHINE_OFW_MACHDEP_H_ #include +#include +#include + +typedef uint64_t cell_t; int OF_decode_addr(phandle_t, int, int *, bus_addr_t *); void OF_getetheraddr(device_t, u_char *); void cpu_shutdown(void *); -void openfirmware_exit(void *); +int ofw_entry(void *); +void ofw_exit(void *); #endif /* _MACHINE_OFW_MACHDEP_H_ */ --- //depot/vendor/freebsd/src/sys/sparc64/isa/ofw_isa.c 2005/12/05 18:57:50 +++ //depot/projects/ppc-g5/sys/sparc64/isa/ofw_isa.c 2008/11/17 02:23:57 @@ -41,10 +41,10 @@ #include #include +#include #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/apb.c 2008/04/17 12:44:19 +++ //depot/projects/ppc-g5/sys/sparc64/pci/apb.c 2008/11/17 02:23:57 @@ -53,7 +53,6 @@ #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/ofw_pci.h 2008/08/22 20:30:15 +++ //depot/projects/ppc-g5/sys/sparc64/pci/ofw_pci.h 2008/11/17 02:23:57 @@ -34,7 +34,7 @@ #ifndef _SPARC64_PCI_OFW_PCI_H_ #define _SPARC64_PCI_OFW_PCI_H_ -#include +#include typedef uint32_t ofw_pci_intr_t; --- //depot/vendor/freebsd/src/sys/sparc64/pci/ofw_pcib.c 2008/04/17 12:44:19 +++ //depot/projects/ppc-g5/sys/sparc64/pci/ofw_pcib.c 2008/11/17 02:23:57 @@ -45,7 +45,6 @@ #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/ofw_pcib_subr.c 2008/04/17 12:44:19 +++ //depot/projects/ppc-g5/sys/sparc64/pci/ofw_pcib_subr.c 2008/11/17 02:23:57 @@ -37,7 +37,6 @@ #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/ofw_pcibus.c 2008/08/24 15:10:15 +++ //depot/projects/ppc-g5/sys/sparc64/pci/ofw_pcibus.c 2008/11/17 02:23:57 @@ -40,7 +40,6 @@ #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/psycho.c 2008/09/18 19:50:14 +++ //depot/projects/ppc-g5/sys/sparc64/pci/psycho.c 2008/11/17 02:23:57 @@ -64,7 +64,6 @@ #include #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/pci/schizo.c 2008/10/28 22:05:45 +++ //depot/projects/ppc-g5/sys/sparc64/pci/schizo.c 2008/11/17 02:23:57 @@ -64,7 +64,6 @@ #include #include #include -#include #include #include --- //depot/vendor/freebsd/src/sys/sparc64/sparc64/ofw_machdep.c 2007/01/18 18:37:02 +++ //depot/projects/ppc-g5/sys/sparc64/sparc64/ofw_machdep.c 2008/11/17 02:23:57 @@ -43,7 +43,6 @@ #include #include -#include #include void