diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64 index 93f07edb8793..25ef599b3f65 100644 --- a/sys/conf/files.sparc64 +++ b/sys/conf/files.sparc64 @@ -111,7 +111,6 @@ sparc64/sparc64/mp_exception.S optional smp \ 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 diff --git a/sys/conf/files.sun4v b/sys/conf/files.sun4v index 03fca3543a30..150e9317a0ae 100644 --- a/sys/conf/files.sun4v +++ b/sys/conf/files.sun4v @@ -65,7 +65,6 @@ sun4v/sun4v/mp_locore.S optional smp 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 diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 7a394c1e7f51..19de2b979e4c 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2001 - 2003 by Thomas Moestl . * Copyright (c) 2005 Marius Strobl * All rights reserved. * @@ -33,7 +34,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -71,6 +74,22 @@ ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd) free(obd->obd_type, M_OFWPROP); } +int +ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, + size_t buflen) +{ + if (ofw_bus_get_name(child) != NULL) { + strlcat(buf, "name=", buflen); + strlcat(buf, ofw_bus_get_name(child), buflen); + } + + if (ofw_bus_get_compat(child) != NULL) { + strlcat(buf, " compat=", buflen); + strlcat(buf, ofw_bus_get_compat(child), buflen); + } + + return (0); +}; const char * ofw_bus_gen_get_compat(device_t bus, device_t dev) @@ -126,3 +145,135 @@ ofw_bus_gen_get_type(device_t bus, device_t dev) 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 uses a second cell to set information + * on the interrupt trigger type. This information should + * be used somewhere to program the PIC. + */ + + if (bcmp(ref, mptr, physsz + intrsz) == 0) { + bcopy(mptr + physsz + intrsz + sizeof(parent), + result, rintrsz); + return (1); + } + mptr += tsz; + i -= tsz; + } + return (0); +} diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index 6096b3e36d76..58dd5873ca09 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -37,9 +37,30 @@ #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 *); +/* Helper method to report interesting OF properties in pnpinfo */ +int ofw_bus_gen_child_pnpinfo_str(device_t, device_t, char *, size_t); + +/* 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; diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h index a8c06331f3f8..414e8482a32a 100644 --- a/sys/dev/ofw/openfirm.h +++ b/sys/dev/ofw/openfirm.h @@ -69,6 +69,12 @@ typedef unsigned long cell_t; typedef unsigned int ihandle_t; typedef unsigned int phandle_t; +/* + * Other than in Open Firmware calls, the size of a bus cell seems to be + * always the same. + */ +typedef u_int32_t pcell_t; + #ifdef _KERNEL #include #include diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h index 1b58db92805a..1a910baa8e00 100644 --- a/sys/powerpc/include/param.h +++ b/sys/powerpc/include/param.h @@ -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_ diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c index 5d6fba6b5bd7..0b6e0cac5b30 100644 --- a/sys/powerpc/ofw/ofw_pcib_pci.c +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -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 @@ static device_method_t ofw_pcib_pci_methods[] = { 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 device_method_t ofw_pcib_pci_methods[] = { 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 @@ ofw_pcib_pci_probe(device_t dev) 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 @@ ofw_pcib_pci_attach(device_t dev) 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 @@ ofw_pcib_pci_get_node(device_t bridge, device_t dev) 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)); +} + diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index 916d98bc57b7..6ec2da60ea3d 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -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 @@ -54,22 +52,27 @@ __FBSDID("$FreeBSD$"); #include "pcib_if.h" #include "pci_if.h" -/* 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); +typedef uint32_t ofw_pci_intr_t; /* Methods */ static device_probe_t ofw_pcibus_probe; static device_attach_t ofw_pcibus_attach; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; +static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, + char *buf, size_t buflen); + +static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno); +static void ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno); static device_method_t ofw_pcibus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ofw_pcibus_probe), DEVMETHOD(device_attach, ofw_pcibus_attach), + /* Bus interface */ + DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method), + /* PCI interface */ DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), @@ -100,6 +103,7 @@ MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1); static int ofw_pcibus_probe(device_t dev) { + if (ofw_bus_get_node(dev) == 0) return (ENXIO); device_set_desc(dev, "OFW PCI bus"); @@ -110,18 +114,43 @@ ofw_pcibus_probe(device_t dev) static int ofw_pcibus_attach(device_t dev) { - device_t pcib; - struct ofw_pci_register pcir; - struct ofw_pcibus_devinfo *dinfo; - phandle_t node, child; - u_int busno, domain, func, slot; + u_int busno, domain; - pcib = device_get_parent(dev); domain = pcib_get_domain(dev); busno = pcib_get_bus(dev); if (bootverbose) device_printf(dev, "domain=%d, physical bus=%d\n", domain, busno); + + /* + * Attach those children represented in the device tree. + */ + + ofw_pcibus_enum_devtree(dev, domain, busno); + + /* + * We now attach any laggard devices. FDT, for instance, allows + * the device tree to enumerate only some PCI devices. Apple's + * OF device tree on some Grackle-based hardware can also miss + * functions on multi-function cards. + */ + + ofw_pcibus_enum_bus(dev, domain, busno); + + return (bus_generic_attach(dev)); +} + +static void +ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) +{ + device_t pcib; + struct ofw_pci_register pcir; + struct ofw_pcibus_devinfo *dinfo; + phandle_t node, child; + u_int func, slot; + int intline; + + pcib = device_get_parent(dev); node = ofw_bus_get_node(dev); for (child = OF_child(node); child != 0; child = OF_peer(child)) { @@ -134,54 +163,170 @@ ofw_pcibus_attach(device_t dev) if (pci_find_dbsf(domain, busno, slot, func) != NULL) continue; - ofw_pci_fixup_node(pcib, child); + /* + * The preset in the intline register is usually bogus. Reset + * it such that the PCI code will reroute the interrupt if + * needed. + */ + + intline = PCI_INVALID_IRQ; + if (OF_getproplen(child, "interrupts") > 0) + intline = 0; + PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE, + intline, 1); + + /* + * Now set up the PCI and OFW bus layer devinfo and add it + * to the PCI bus. + */ 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); + } + } + } +} + +/* + * The following is an almost exact clone of pci_add_children(), with the + * addition that it (a) will not add children that have already been added, + * and (b) will set up the OFW devinfo to point to invalid values. This is + * to handle non-enumerated PCI children as exist in FDT and on the second + * function of the Rage 128 in my Blue & White G3. + */ + +static void +ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno) +{ + device_t pcib; + struct ofw_pcibus_devinfo *dinfo; + int maxslots; + int s, f, pcifunchigh; + uint8_t hdrtype; + + pcib = device_get_parent(dev); + + maxslots = PCIB_MAXSLOTS(pcib); + for (s = 0; s <= maxslots; s++) { + pcifunchigh = 0; + f = 0; + DELAY(1); + hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + if (hdrtype & PCIM_MFDEV) + pcifunchigh = PCI_FUNCMAX; + for (f = 0; f <= pcifunchigh; f++) { + /* Filter devices we have already added */ + if (pci_find_dbsf(domain, busno, s, f) != NULL) + continue; + + dinfo = (struct ofw_pcibus_devinfo *)pci_read_device( + pcib, domain, busno, s, f, sizeof(*dinfo)); + if (dinfo != NULL) { + dinfo->opd_obdinfo.obd_node = -1; + + dinfo->opd_obdinfo.obd_name = NULL; + dinfo->opd_obdinfo.obd_compat = NULL; + dinfo->opd_obdinfo.obd_type = NULL; + dinfo->opd_obdinfo.obd_model = NULL; + pci_add_child(dev, (struct pci_devinfo *)dinfo); + } } } - - return (bus_generic_attach(dev)); } +static int +ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, + size_t buflen) +{ + pci_child_pnpinfo_str_method(cbdev, child, buf, buflen); + + if (ofw_bus_get_node(child) != -1) { + strlcat(buf, " ", buflen); /* Separate info */ + ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen); + } + + return (0); +} + static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { - uint32_t irqs[4]; + ofw_pci_intr_t intr; + phandle_t node; + int isz; - device_printf(child,"Assigning interrupt\n"); + node = ofw_bus_get_node(child); - if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0) - return PCI_INVALID_IRQ; + if (node == -1) { + /* Non-firmware enumerated child, use standard routing */ + + /* + * XXX: Right now we don't have anything sensible to do here, + * since the ofw_imap stuff relies on nodes have a reg + * property. There exists ways around this, so the ePAPR + * spec will need to be studied. + */ - device_printf(child,"IRQ %d\n",irqs[0]); + return (0); - return irqs[0]; +#ifdef NOTYET + intr = pci_get_intpin(child); + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, + intr)); +#endif + } + + /* + * Any AAPL,interrupts property gets priority and is + * fully specified (i.e. does not need routing) + */ -// return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); + isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr)); + if (isz == sizeof(intr)) { + return (intr); + } + + isz = OF_getprop(node, "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 +338,3 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev) 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); -} - diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c index 08e14acd7f14..9dd796d33a4e 100644 --- a/sys/powerpc/powermac/grackle.c +++ b/sys/powerpc/powermac/grackle.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -164,7 +165,7 @@ static int 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 @@ grackle_attach(device_t dev) } } + 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 @@ grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func, 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)]; - 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 diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h index bb5b150e074a..78461d88ae7f 100644 --- a/sys/powerpc/powermac/gracklevar.h +++ b/sys/powerpc/powermac/gracklevar.h @@ -52,6 +52,9 @@ struct grackle_softc { 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; }; /* diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c index 9a4b3ac0d8f2..71be1136ccc7 100644 --- a/sys/powerpc/powermac/macio.c +++ b/sys/powerpc/powermac/macio.c @@ -107,6 +107,8 @@ static device_method_t macio_methods[] = { DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource), DEVMETHOD(bus_get_resource_list, macio_get_resource_list), + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), + /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, macio_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c index 097532cba635..b0b55a4d161d 100644 --- a/sys/powerpc/powermac/uninorth.c +++ b/sys/powerpc/powermac/uninorth.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -163,8 +164,7 @@ uninorth_attach(device_t dev) { 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 @@ uninorth_attach(device_t dev) } } + 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 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func, 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 diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h index ff789acc9b42..6bb4024fbb6b 100644 --- a/sys/powerpc/powermac/uninorthvar.h +++ b/sys/powerpc/powermac/uninorthvar.h @@ -61,8 +61,10 @@ struct uninorth_softc { 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 { diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c index bcc92a2c7d1a..9baa7a8fe48c 100644 --- a/sys/sparc64/ebus/ebus.c +++ b/sys/sparc64/ebus/ebus.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -118,6 +117,7 @@ static device_method_t ebus_methods[] = { DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_release_resource, ebus_release_resource), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo), diff --git a/sys/sparc64/include/ofw_bus.h b/sys/sparc64/include/ofw_bus.h deleted file mode 100644 index 1e9004e15d77..000000000000 --- a/sys/sparc64/include/ofw_bus.h +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * Copyright (c) 2001 - 2003 by Thomas Moestl . - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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$ - */ - -#ifndef _MACHINE_OFW_BUS_H_ -#define _MACHINE_OFW_BUS_H_ - -#define ORIP_NOINT -1 -#define ORIR_NOTFOUND 0xffffffff - -/* - * Other than in Open Firmware calls, the size of a bus cell seems to be - * always the same. - */ -typedef u_int32_t pcell_t; - -struct ofw_bus_iinfo { - u_int8_t *opi_imap; - u_int8_t *opi_imapmsk; - int opi_imapsz; - pcell_t opi_addrc; -}; - -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); - -#endif /* !_MACHINE_OFW_BUS_H_ */ diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c index e1d75374aec1..de9086958db0 100644 --- a/sys/sparc64/isa/ofw_isa.c +++ b/sys/sparc64/isa/ofw_isa.c @@ -41,10 +41,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include -#include #include #include diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c index d908c178df56..ba0698cc74f1 100644 --- a/sys/sparc64/pci/apb.c +++ b/sys/sparc64/pci/apb.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h index 252f474a90f8..19c2fbed5dbe 100644 --- a/sys/sparc64/pci/ofw_pci.h +++ b/sys/sparc64/pci/ofw_pci.h @@ -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; diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c index 966d77f6d2c7..8a5b9915cbc7 100644 --- a/sys/sparc64/pci/ofw_pcib.c +++ b/sys/sparc64/pci/ofw_pcib.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c index 9996b7e63665..6dd0990b5bc9 100644 --- a/sys/sparc64/pci/ofw_pcib_subr.c +++ b/sys/sparc64/pci/ofw_pcib_subr.c @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c index 7918370c8b06..65a498aa002e 100644 --- a/sys/sparc64/pci/ofw_pcibus.c +++ b/sys/sparc64/pci/ofw_pcibus.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -69,6 +68,8 @@ static device_probe_t ofw_pcibus_probe; static device_attach_t ofw_pcibus_attach; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; +static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, + char *buf, size_t buflen); static device_method_t ofw_pcibus_methods[] = { /* Device interface */ @@ -76,6 +77,7 @@ static device_method_t ofw_pcibus_methods[] = { DEVMETHOD(device_attach, ofw_pcibus_attach), /* Bus interface */ + DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method), /* PCI interface */ DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), @@ -302,3 +304,18 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev) dinfo = device_get_ivars(dev); return (&dinfo->opd_obdinfo); } + +static int +ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, + size_t buflen) +{ + pci_child_pnpinfo_str_method(cbdev, child, buf, buflen); + + if (ofw_bus_get_node(child) != -1) { + strlcat(buf, " ", buflen); /* Separate info */ + ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen); + } + + return (0); +} + diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index d9611918645d..505eec4aafac 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c index 8f01f9c58433..45bee8d0fa75 100644 --- a/sys/sparc64/pci/schizo.c +++ b/sys/sparc64/pci/schizo.c @@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index a97fd10f1a48..d6b8393c868a 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -226,6 +226,7 @@ static device_method_t sbus_methods[] = { DEVMETHOD(bus_get_resource_list, sbus_get_resource_list), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag), + DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo), diff --git a/sys/sparc64/sparc64/ofw_bus.c b/sys/sparc64/sparc64/ofw_bus.c deleted file mode 100644 index f7458dcc62fd..000000000000 --- a/sys/sparc64/sparc64/ofw_bus.c +++ /dev/null @@ -1,198 +0,0 @@ -/*- - * Copyright (C) 1996 Wolfgang Solfrank. - * Copyright (C) 1996 TooLs GmbH. - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by TooLs GmbH. - * 4. The name of TooLs GmbH may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. - */ -/*- - * Copyright (c) 2001 - 2003 by Thomas Moestl . - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. - * - * from: $NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $ - * - * $FreeBSD$ - */ - -/* - * Open Firmware bus support code that is (hopefully) independent from the - * used hardware. - * Maybe this should go into dev/ofw/; there may however be sparc specific - * bits left. - */ - -#include -#include -#include - -#include - -#include - -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); - if (bcmp(ref, mptr, physsz + intrsz) == 0) { - bcopy(mptr + physsz + intrsz + sizeof(parent), - result, rintrsz); - return (1); - } - mptr += tsz; - i -= tsz; - } - return (0); -} diff --git a/sys/sparc64/sparc64/ofw_machdep.c b/sys/sparc64/sparc64/ofw_machdep.c index 7efc807e28b7..bcacea77b41b 100644 --- a/sys/sparc64/sparc64/ofw_machdep.c +++ b/sys/sparc64/sparc64/ofw_machdep.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include void diff --git a/sys/sun4v/include/ofw_bus.h b/sys/sun4v/include/ofw_bus.h deleted file mode 100644 index 1e9004e15d77..000000000000 --- a/sys/sun4v/include/ofw_bus.h +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * Copyright (c) 2001 - 2003 by Thomas Moestl . - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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$ - */ - -#ifndef _MACHINE_OFW_BUS_H_ -#define _MACHINE_OFW_BUS_H_ - -#define ORIP_NOINT -1 -#define ORIR_NOTFOUND 0xffffffff - -/* - * Other than in Open Firmware calls, the size of a bus cell seems to be - * always the same. - */ -typedef u_int32_t pcell_t; - -struct ofw_bus_iinfo { - u_int8_t *opi_imap; - u_int8_t *opi_imapmsk; - int opi_imapsz; - pcell_t opi_addrc; -}; - -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); - -#endif /* !_MACHINE_OFW_BUS_H_ */