Date: Mon, 20 Oct 2008 13:45:35 GMT From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 151604 for review Message-ID: <200810201345.m9KDjZxl097940@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=151604 Change 151604 by nwhitehorn@nwhitehorn_trantor on 2008/10/20 13:44:36 Mega-commit for beginnings of real Mambo support. This includes the following: 1. Finish transformation of PPC PCI code to use sparc64's OFW PCI stuff. 2. Merge some of sparc64's OFW code to sys/dev/ofw. The sparc64 side of this still needs cleaning. 3. Add ISA support on PowerPC. 4. Add support for real device drivers hanging off nexus by implementing bus_alloc_resource() to do something intelligent. This is necessary for ISA and OpenPIC support on Mambo, and for SMU support and u3 PIC support on real hardware. 4. Add a driver for Mambo's OpenPIC. This apparently tries to access registers it shouldn't, causing Mambo to die with FATAL ERROR: accessing area for non existent proc after probing the PIC. Affected files ... .. //depot/projects/ppc-g5/sys/conf/files.powerpc#6 edit .. //depot/projects/ppc-g5/sys/dev/ofw/ofw_imap.c#1 add .. //depot/projects/ppc-g5/sys/dev/ofw/ofw_imap.h#1 add .. //depot/projects/ppc-g5/sys/powerpc/aim/nexus.c#3 edit .. //depot/projects/ppc-g5/sys/powerpc/mambo/openpic_mambo.c#1 add .. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_isa.c#1 add .. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_isa.h#1 add .. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcib_pci.c#4 edit .. //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcibus.c#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/cpcht.c#5 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/cpchtvar.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/grackle.c#4 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/gracklevar.h#2 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c#5 edit .. //depot/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h#5 edit .. //depot/projects/ppc-g5/sys/powerpc/powerpc/autoconf.c#3 edit Differences ... ==== //depot/projects/ppc-g5/sys/conf/files.powerpc#6 (text+ko) ==== @@ -37,6 +37,7 @@ dev/ofw/ofw_bus_subr.c optional aim dev/ofw/ofw_console.c optional aim dev/ofw/ofw_disk.c optional ofwd aim +dev/ofw/ofw_imap.c optional aim dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac @@ -105,6 +106,7 @@ powerpc/mpc85xx/ocpbus.c optional mpc85xx powerpc/mpc85xx/opic.c optional mpc85xx powerpc/mpc85xx/pci_ocp.c optional pci mpc85xx +powerpc/ofw/ofw_isa.c optional isa aim powerpc/ofw/ofw_pcibus.c optional pci aim powerpc/ofw/ofw_pcib_pci.c optional pci aim powerpc/ofw/ofw_syscons.c optional sc aim @@ -149,6 +151,7 @@ powerpc/powerpc/suswintr.c standard powerpc/powerpc/syncicache.c standard powerpc/powerpc/sys_machdep.c standard +powerpc/mambo/openpic_mambo.c optional mambo powerpc/psim/iobus.c optional psim powerpc/psim/ata_iobus.c optional ata psim powerpc/psim/openpic_iobus.c optional psim ==== //depot/projects/ppc-g5/sys/powerpc/aim/nexus.c#3 (text+ko) ==== @@ -64,6 +64,8 @@ #include <sys/cons.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <vm/vm.h> +#include <vm/pmap.h> #include <dev/ofw/openfirm.h> @@ -105,7 +107,8 @@ }; struct nexus_softc { - struct rman sc_rman; + struct rman sc_intr_rman; + struct rman sc_mem_rman; }; /* @@ -212,23 +215,24 @@ phandle_t root; phandle_t child; struct nexus_softc *sc; - u_long start, end; if ((root = OF_peer(0)) == -1) panic("nexus_probe: OF_peer failed."); sc = device_get_softc(dev); - start = 0; - end = INTR_VECTORS - 1; + sc->sc_intr_rman.rm_type = RMAN_ARRAY; + sc->sc_intr_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&sc->sc_intr_rman) || + rman_manage_region(&sc->sc_intr_rman, 0, INTR_VECTORS - 1)) + panic("nexus_probe IRQ rman"); + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "Device Memory"; + if (rman_init(&sc->sc_mem_rman) || + rman_manage_region(&sc->sc_mem_rman, 0, ~0UL)) + panic("nexus_probe mem rman"); - sc->sc_rman.rm_start = start; - sc->sc_rman.rm_end = end; - sc->sc_rman.rm_type = RMAN_ARRAY; - sc->sc_rman.rm_descr = "Interrupt request lines"; - if (rman_init(&sc->sc_rman) || - rman_manage_region(&sc->sc_rman, start, end)) - panic("nexus_probe IRQ rman"); /* * Now walk the OFW tree to locate top-level devices @@ -386,84 +390,116 @@ { struct nexus_softc *sc; struct resource *rv; + struct rman *rman; + int needactivate; + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) { + rman = &sc->sc_intr_rman; - if (type != SYS_RES_IRQ) { + if (count == 0 || start + count - 1 != end) { + device_printf(bus, "invalid IRQ allocation from %s\n", + device_get_nameunit(child)); + return (NULL); + } + } else if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { + rman = &sc->sc_mem_rman; + } else { device_printf(bus, "unknown resource request from %s\n", device_get_nameunit(child)); return (NULL); } - if (count == 0 || start + count - 1 != end) { - device_printf(bus, "invalid IRQ allocation from %s\n", + rv = rman_reserve_resource(rman, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "Resource allocation failed for %s\n", device_get_nameunit(child)); return (NULL); } - sc = device_get_softc(bus); + rman_set_rid(rv, *rid); - rv = rman_reserve_resource(&sc->sc_rman, start, end, count, - flags, child); - if (rv == NULL) { - device_printf(bus, "IRQ allocation failed for %s\n", - device_get_nameunit(child)); - } else - rman_set_rid(rv, *rid); + if (needactivate) { + if (nexus_activate_resource(bus, child, type, *rid, rv) != 0) { + device_printf(bus, + "Resource activation failed for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } return (rv); } static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) +struct resource *res) { + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + vm_offset_t start; + void *p; + + start = (vm_offset_t)rman_get_start(res); - /* Not much to be done yet... */ + p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bustag(res, &bs_be_tag); + rman_set_bushandle(res, (u_long)p); + } + return (rman_activate_resource(res)); } static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) +struct resource *res) { - /* Not much to be done yet... */ - return (rman_deactivate_resource(res)); +/* Not much to be done yet... */ +return (rman_deactivate_resource(res)); } static int nexus_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) +struct resource *res) { - if (type != SYS_RES_IRQ) { - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (EINVAL); - } +if (type != SYS_RES_IRQ) { + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (EINVAL); +} - return (rman_release_resource(res)); +return (rman_release_resource(res)); } static device_t nexus_device_from_node(device_t parent, phandle_t node) { - device_t cdev; - struct nexus_devinfo *dinfo; - char *name, *type, *compatible; +device_t cdev; +struct nexus_devinfo *dinfo; +char *name, *type, *compatible; - OF_getprop_alloc(node, "name", 1, (void **)&name); - OF_getprop_alloc(node, "device_type", 1, (void **)&type); - OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); - cdev = device_add_child(parent, NULL, -1); - if (cdev != NULL) { - dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); - dinfo->ndi_node = node; - dinfo->ndi_name = name; - dinfo->ndi_device_type = type; - dinfo->ndi_compatible = compatible; - device_set_ivars(cdev, dinfo); - } else - free(name, M_OFWPROP); +OF_getprop_alloc(node, "name", 1, (void **)&name); +OF_getprop_alloc(node, "device_type", 1, (void **)&type); +OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); +cdev = device_add_child(parent, NULL, -1); +if (cdev != NULL) { + dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); + dinfo->ndi_node = node; + dinfo->ndi_name = name; + dinfo->ndi_device_type = type; + dinfo->ndi_compatible = compatible; + device_set_ivars(cdev, dinfo); +} else + free(name, M_OFWPROP); return (cdev); } ==== //depot/projects/ppc-g5/sys/powerpc/ofw/ofw_pcib_pci.c#4 (text+ko) ==== @@ -35,6 +35,7 @@ #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_pci.h> +#include <dev/ofw/ofw_imap.h> #include <dev/ofw/ofw_bus.h> #include <dev/pci/pcivar.h> @@ -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/projects/ppc-g5/sys/powerpc/ofw/ofw_pcibus.c#2 (text+ko) ==== @@ -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 <se@freebsd.org> * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> * Copyright (c) 2000, BSDi @@ -30,7 +28,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/powerpc/pci/ofw_pcibus.c 182108 2008-08-24 15:05:46Z marius $"); +__FBSDID("$FreeBSD: src/sys/sparc64/pci/ofw_pcibus.c,v 1.21 2008/08/24 15:05:46 marius Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -42,6 +40,7 @@ #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/ofw_pci.h> +#include <dev/ofw/ofw_imap.h> #include <dev/ofw/openfirm.h> #include <machine/bus.h> @@ -54,10 +53,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, uint32_t clock, + u_int busno, u_int slot, u_int func); /* Methods */ static device_probe_t ofw_pcibus_probe; @@ -70,6 +70,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 +102,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 +110,22 @@ return (0); } +/* + * Perform miscellaneous setups the firmware usually does not do for us. + */ +static void +ofw_pcibus_setup_device(device_t bridge, uint32_t clock, u_int busno, + u_int slot, u_int func) +{ + /* + * The preset in the intline register is usually wrong. Reset + * it to 255, so that the PCI code will reroute the interrupt if + * needed. + */ + PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_INTLINE, + PCI_INVALID_IRQ, 1); +} + static int ofw_pcibus_attach(device_t dev) { @@ -114,6 +133,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 +144,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, 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 +190,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 +229,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/projects/ppc-g5/sys/powerpc/powermac/cpcht.c#5 (text+ko) ==== @@ -37,6 +37,7 @@ #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> +#include <isa/isavar.h> #include <machine/bus.h> #include <machine/md_var.h> @@ -46,6 +47,7 @@ #include <sys/rman.h> #include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_imap.h> #include <dev/ofw/ofw_bus_subr.h> #include <powerpc/powermac/cpchtvar.h> @@ -133,14 +135,13 @@ root = ofw_bus_get_node(dev); - if (OF_getprop(root, "reg", reg, sizeof(reg)) < 24) + if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8) return (ENXIO); for (child = OF_child(root); child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_CPCHT, M_WAITOK | M_ZERO); - if (ofw_bus_gen_setup_devinfo(dinfo, child) - != 0) { + if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { free(dinfo, M_CPCHT); continue; } @@ -165,6 +166,56 @@ } /* + * CPC ISA Device interface. + */ +static int cpcisa_probe(device_t); + +/* + * Driver methods. + */ +static device_method_t cpcisa_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, cpcisa_probe), + DEVMETHOD(device_attach, isab_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_activate_resource,bus_generic_activate_resource), + + {0,0} +}; + +static driver_t cpcisa_driver = { + "isab", + cpcisa_methods, + 0 +}; + +DRIVER_MODULE(cpcisa, cpcht, cpcisa_driver, isab_devclass, 0, 0); + +static int +cpcisa_probe(device_t dev) +{ + const char *type; + + type = ofw_bus_get_type(dev); + + if (type == NULL) + return (ENXIO); + + if (strcmp(type, "isa") != 0) + return (ENXIO); + + device_set_desc(dev, "HyperTransport-ISA bridge"); + + return (0); +} + +/* * CPC PCI Device interface. */ static int cpcpci_probe(device_t); @@ -351,6 +402,8 @@ } } + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); @@ -540,6 +593,19 @@ static int cpcpci_route_interrupt(device_t bus, device_t dev, int pin) { - return (0); + struct cpcpci_softc *sc; + struct ofw_pci_register reg; + uint32_t pintr, mintr; + 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), maskbuf)) + return (mintr); + + 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); } ==== //depot/projects/ppc-g5/sys/powerpc/powermac/cpchtvar.h#2 (text+ko) ==== @@ -52,6 +52,7 @@ 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; }; #endif /* _POWERPC_POWERMAC_CPCHTVAR_H_ */ ==== //depot/projects/ppc-g5/sys/powerpc/powermac/grackle.c#4 (text+ko) ==== @@ -37,6 +37,7 @@ #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_pci.h> #include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_imap.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> @@ -251,6 +252,8 @@ } } + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); } @@ -335,8 +338,20 @@ 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; + 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), maskbuf)) + return (mintr); + + 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/projects/ppc-g5/sys/powerpc/powermac/gracklevar.h#2 (text+ko) ==== @@ -52,6 +52,8 @@ struct rman sc_mem_rman; bus_space_tag_t sc_memt; bus_dma_tag_t sc_dmat; + + struct ofw_bus_iinfo sc_pci_iinfo; }; /* ==== //depot/projects/ppc-g5/sys/powerpc/powermac/uninorth.c#5 (text+ko) ==== @@ -35,6 +35,7 @@ #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_pci.h> #include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_imap.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> @@ -294,6 +295,8 @@ } } + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); } @@ -360,8 +363,20 @@ 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; + 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), maskbuf)) + return (mintr); + + 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/projects/ppc-g5/sys/powerpc/powermac/uninorthvar.h#5 (text+ko) ==== @@ -61,6 +61,7 @@ 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; }; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810201345.m9KDjZxl097940>