Index: head/sys/conf/files.powerpc =================================================================== --- head/sys/conf/files.powerpc (revision 280771) +++ head/sys/conf/files.powerpc (revision 280772) @@ -1,244 +1,246 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # # font.h optional sc \ compile-with "uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h" \ no-obj no-implicit-rule before-depend \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" # # There is only an asm version on ppc64. cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs powerpc compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/atomic/powerpc64/opensolaris_atomic.S optional zfs powerpc64 compile-with "${ZFS_S}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/bm/if_bm.c optional bm powermac dev/adb/adb_bus.c optional adb dev/adb/adb_kbd.c optional adb dev/adb/adb_mouse.c optional adb dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb dev/adb/adb_buttons.c optional adb dev/agp/agp_apple.c optional agp powermac dev/fb/fb.c optional sc dev/fdt/fdt_powerpc.c optional fdt +# ofwbus depends on simplebus. +dev/fdt/simplebus.c optional aim | fdt dev/hwpmc/hwpmc_powerpc.c optional hwpmc dev/hwpmc/hwpmc_mpc7xxx.c optional hwpmc dev/hwpmc/hwpmc_ppc970.c optional hwpmc dev/iicbus/ad7417.c optional ad7417 powermac dev/iicbus/adm1030.c optional powermac windtunnel | adm1030 powermac dev/iicbus/adt746x.c optional adt746x powermac dev/iicbus/ds1631.c optional ds1631 powermac dev/iicbus/ds1775.c optional ds1775 powermac dev/iicbus/max6690.c optional max6690 powermac dev/kbd/kbd.c optional sc | vt dev/nand/nfc_fsl.c optional nand mpc85xx # ofw can be either aim or fdt: fdt case handled in files. aim only powerpc specific. dev/ofw/openfirm.c optional aim dev/ofw/openfirmio.c optional aim dev/ofw/ofw_bus_if.m optional aim dev/ofw/ofw_cpu.c optional aim dev/ofw/ofw_if.m optional aim 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_iicbus.c optional iicbus aim dev/ofw/ofwbus.c optional aim | fdt dev/ofw/ofw_standard.c optional aim powerpc dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac dev/sec/sec.c optional sec mpc85xx dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac dev/sound/macio/davbus.c optional snd_davbus powermac dev/sound/macio/i2s.c optional snd_ai2s powermac dev/sound/macio/onyx.c optional snd_ai2s iicbus powermac dev/sound/macio/snapper.c optional snd_ai2s iicbus powermac dev/sound/macio/tumbler.c optional snd_ai2s iicbus powermac dev/syscons/scgfbrndr.c optional sc dev/syscons/scterm-teken.c optional sc dev/syscons/scvtb.c optional sc dev/tsec/if_tsec.c optional tsec dev/tsec/if_tsec_fdt.c optional tsec fdt dev/uart/uart_cpu_powerpc.c optional uart dev/usb/controller/ehci_fsl.c optional ehci mpc85xx dev/vt/hw/ofwfb/ofwfb.c optional vt aim kern/kern_clocksource.c standard kern/subr_dummy_vdso_tc.c standard kern/syscalls.c optional ktr kern/subr_sfbuf.c standard libkern/ashldi3.c optional powerpc libkern/ashrdi3.c optional powerpc libkern/bcmp.c standard libkern/cmpdi2.c optional powerpc libkern/divdi3.c optional powerpc libkern/ffs.c standard libkern/ffsl.c standard libkern/fls.c standard libkern/flsl.c standard libkern/flsll.c standard libkern/lshrdi3.c optional powerpc libkern/memmove.c standard libkern/memset.c standard libkern/moddi3.c optional powerpc libkern/qdivrem.c optional powerpc libkern/ucmpdi2.c optional powerpc libkern/udivdi3.c optional powerpc libkern/umoddi3.c optional powerpc powerpc/aim/interrupt.c optional aim powerpc/aim/locore.S optional aim no-obj powerpc/aim/machdep.c optional aim powerpc/aim/mmu_oea.c optional aim powerpc powerpc/aim/mmu_oea64.c optional aim powerpc/aim/moea64_if.m optional aim powerpc/aim/moea64_native.c optional aim powerpc/aim/mp_cpudep.c optional aim powerpc/aim/slb.c optional aim powerpc64 powerpc/aim/trap.c optional aim powerpc/aim/uma_machdep.c optional aim powerpc/booke/interrupt.c optional booke powerpc/booke/locore.S optional booke no-obj powerpc/booke/machdep.c optional booke powerpc/booke/machdep_e500.c optional booke_e500 powerpc/booke/mp_cpudep.c optional booke smp powerpc/booke/platform_bare.c optional booke powerpc/booke/pmap.c optional booke powerpc/booke/trap.c optional booke powerpc/cpufreq/dfs.c optional cpufreq powerpc/cpufreq/pcr.c optional cpufreq aim powerpc/cpufreq/pmufreq.c optional cpufreq aim pmu powerpc/fpu/fpu_add.c optional fpu_emu powerpc/fpu/fpu_compare.c optional fpu_emu powerpc/fpu/fpu_div.c optional fpu_emu powerpc/fpu/fpu_emu.c optional fpu_emu powerpc/fpu/fpu_explode.c optional fpu_emu powerpc/fpu/fpu_implode.c optional fpu_emu powerpc/fpu/fpu_mul.c optional fpu_emu powerpc/fpu/fpu_sqrt.c optional fpu_emu powerpc/fpu/fpu_subr.c optional fpu_emu powerpc/mambo/mambocall.S optional mambo powerpc/mambo/mambo.c optional mambo powerpc/mambo/mambo_console.c optional mambo powerpc/mambo/mambo_disk.c optional mambo powerpc/mpc85xx/atpic.c optional mpc85xx isa powerpc/mpc85xx/ds1553_bus_fdt.c optional ds1553 fdt powerpc/mpc85xx/ds1553_core.c optional ds1553 powerpc/mpc85xx/i2c.c optional iicbus fdt powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/mpc85xx.c optional mpc85xx powerpc/mpc85xx/platform_mpc85xx.c optional mpc85xx powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx powerpc/ofw/ofw_machdep.c standard powerpc/ofw/ofw_pci.c optional pci powerpc/ofw/ofw_pcibus.c optional pci powerpc/ofw/ofw_pcib_pci.c optional pci powerpc/ofw/ofw_real.c optional aim powerpc/ofw/ofw_syscons.c optional sc aim powerpc/ofw/ofwcall32.S optional aim powerpc powerpc/ofw/ofwcall64.S optional aim powerpc64 powerpc/ofw/ofwmagic.S optional aim powerpc/ofw/openpic_ofw.c optional aim | fdt powerpc/ofw/rtas.c optional aim powerpc/powermac/ata_kauai.c optional powermac ata | powermac atamacio powerpc/powermac/ata_macio.c optional powermac ata | powermac atamacio powerpc/powermac/ata_dbdma.c optional powermac ata | powermac atamacio powerpc/powermac/atibl.c optional powermac atibl powerpc/powermac/cuda.c optional powermac cuda powerpc/powermac/cpcht.c optional powermac pci powerpc/powermac/dbdma.c optional powermac pci powerpc/powermac/fcu.c optional powermac fcu powerpc/powermac/grackle.c optional powermac pci powerpc/powermac/hrowpic.c optional powermac pci powerpc/powermac/kiic.c optional powermac kiic powerpc/powermac/macgpio.c optional powermac pci powerpc/powermac/macio.c optional powermac pci powerpc/powermac/nvbl.c optional powermac nvbl powerpc/powermac/platform_powermac.c optional powermac powerpc/powermac/powermac_thermal.c optional powermac powerpc/powermac/pswitch.c optional powermac pswitch powerpc/powermac/pmu.c optional powermac pmu powerpc/powermac/smu.c optional powermac smu powerpc/powermac/smusat.c optional powermac smu powerpc/powermac/uninorth.c optional powermac powerpc/powermac/uninorthpci.c optional powermac pci powerpc/powermac/vcoregpio.c optional powermac powerpc/powerpc/altivec.c standard powerpc/powerpc/autoconf.c standard powerpc/powerpc/bcopy.c standard powerpc/powerpc/bus_machdep.c standard powerpc/powerpc/busdma_machdep.c standard powerpc/powerpc/clock.c standard powerpc/powerpc/copyinout.c standard powerpc/powerpc/copystr.c standard powerpc/powerpc/cpu.c standard powerpc/powerpc/db_disasm.c optional ddb powerpc/powerpc/db_hwwatch.c optional ddb powerpc/powerpc/db_interface.c optional ddb powerpc/powerpc/db_trace.c optional ddb powerpc/powerpc/dump_machdep.c standard powerpc/powerpc/elf32_machdep.c optional powerpc | compat_freebsd32 powerpc/powerpc/elf64_machdep.c optional powerpc64 powerpc/powerpc/exec_machdep.c standard powerpc/powerpc/fpu.c standard powerpc/powerpc/fuswintr.c standard powerpc/powerpc/gdb_machdep.c optional gdb powerpc/powerpc/in_cksum.c optional inet | inet6 powerpc/powerpc/intr_machdep.c standard powerpc/powerpc/iommu_if.m standard powerpc/powerpc/mem.c optional mem powerpc/powerpc/mmu_if.m standard powerpc/powerpc/mp_machdep.c optional smp powerpc/powerpc/nexus.c standard powerpc/powerpc/openpic.c standard powerpc/powerpc/pic_if.m standard powerpc/powerpc/pmap_dispatch.c standard powerpc/powerpc/platform.c standard powerpc/powerpc/platform_if.m standard powerpc/powerpc/ptrace_machdep.c standard powerpc/powerpc/sc_machdep.c optional sc powerpc/powerpc/setjmp.S standard powerpc/powerpc/sigcode32.S optional powerpc | compat_freebsd32 powerpc/powerpc/sigcode64.S optional powerpc64 powerpc/powerpc/swtch32.S optional powerpc powerpc/powerpc/swtch64.S optional powerpc64 powerpc/powerpc/stack_machdep.c optional ddb | stack powerpc/powerpc/suswintr.c standard powerpc/powerpc/syncicache.c standard powerpc/powerpc/sys_machdep.c standard powerpc/powerpc/uio_machdep.c standard powerpc/powerpc/vm_machdep.c standard powerpc/ps3/ehci_ps3.c optional ps3 ehci powerpc/ps3/ohci_ps3.c optional ps3 ohci powerpc/ps3/if_glc.c optional ps3 glc powerpc/ps3/mmu_ps3.c optional ps3 powerpc/ps3/platform_ps3.c optional ps3 powerpc/ps3/ps3bus.c optional ps3 powerpc/ps3/ps3cdrom.c optional ps3 scbus powerpc/ps3/ps3disk.c optional ps3 powerpc/ps3/ps3pic.c optional ps3 powerpc/ps3/ps3_syscons.c optional ps3 vt powerpc/ps3/ps3-hvcall.S optional ps3 powerpc/pseries/phyp-hvcall.S optional pseries powerpc64 powerpc/pseries/mmu_phyp.c optional pseries powerpc64 powerpc/pseries/phyp_console.c optional pseries powerpc64 uart powerpc/pseries/phyp_llan.c optional llan powerpc/pseries/phyp_vscsi.c optional pseries powerpc64 scbus powerpc/pseries/platform_chrp.c optional pseries powerpc/pseries/plpar_iommu.c optional pseries powerpc64 powerpc/pseries/plpar_pcibus.c optional pseries powerpc64 pci powerpc/pseries/rtas_dev.c optional pseries powerpc/pseries/rtas_pci.c optional pseries pci powerpc/pseries/vdevice.c optional pseries powerpc64 powerpc/pseries/xics.c optional pseries powerpc64 powerpc/psim/iobus.c optional psim powerpc/psim/ata_iobus.c optional ata psim powerpc/psim/openpic_iobus.c optional psim powerpc/psim/uart_iobus.c optional uart psim Index: head/sys/dev/fdt/simplebus.c =================================================================== --- head/sys/dev/fdt/simplebus.c (revision 280771) +++ head/sys/dev/fdt/simplebus.c (revision 280772) @@ -1,364 +1,423 @@ /*- * Copyright (c) 2013 Nathan Whitehorn * 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 AND CONTRIBUTORS ``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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include /* * Bus interface. */ static int simplebus_probe(device_t dev); static int simplebus_attach(device_t dev); static struct resource *simplebus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static void simplebus_probe_nomatch(device_t bus, device_t child); static int simplebus_print_child(device_t bus, device_t child); - +static device_t simplebus_add_child(device_t dev, u_int order, + const char *name, int unit); +static struct resource_list *simplebus_get_resource_list(device_t bus, + device_t child); /* * ofw_bus interface */ static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus, device_t child); /* * local methods */ static int simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc); -static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev, - phandle_t node); /* * Driver methods. */ static device_method_t simplebus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, simplebus_probe), DEVMETHOD(device_attach, simplebus_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ + DEVMETHOD(bus_add_child, simplebus_add_child), DEVMETHOD(bus_print_child, simplebus_print_child), DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), + DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo), DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; DEFINE_CLASS_0(simplebus, simplebus_driver, simplebus_methods, sizeof(struct simplebus_softc)); static devclass_t simplebus_devclass; EARLY_DRIVER_MODULE(simplebus, ofwbus, simplebus_driver, simplebus_devclass, 0, 0, BUS_PASS_BUS); EARLY_DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); static int simplebus_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); /* * FDT data puts a "simple-bus" compatible string on many things that * have children but aren't really busses in our world. Without a * ranges property we will fail to attach, so just fail to probe too. */ if (!(ofw_bus_is_compatible(dev, "simple-bus") && ofw_bus_has_prop(dev, "ranges")) && (ofw_bus_get_type(dev) == NULL || strcmp(ofw_bus_get_type(dev), "soc") != 0)) return (ENXIO); device_set_desc(dev, "Flattened device tree simple bus"); return (BUS_PROBE_GENERIC); } static int simplebus_attach(device_t dev) { struct simplebus_softc *sc; - struct simplebus_devinfo *di; phandle_t node; - device_t cdev; - node = ofw_bus_get_node(dev); sc = device_get_softc(dev); + simplebus_init(dev, 0); + if (simplebus_fill_ranges(sc->node, sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + /* + * In principle, simplebus could have an interrupt map, but ignore that + * for now + */ + + for (node = OF_child(sc->node); node > 0; node = OF_peer(node)) + simplebus_add_device(dev, node, 0, NULL, -1, NULL); + return (bus_generic_attach(dev)); +} + +void +simplebus_init(device_t dev, phandle_t node) +{ + struct simplebus_softc *sc; + + sc = device_get_softc(dev); + if (node == 0) + node = ofw_bus_get_node(dev); sc->dev = dev; sc->node = node; /* * Some important numbers */ sc->acells = 2; OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells)); sc->scells = 1; OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells)); - - if (simplebus_fill_ranges(node, sc) < 0) { - device_printf(dev, "could not get ranges\n"); - return (ENXIO); - } - - /* - * In principle, simplebus could have an interrupt map, but ignore that - * for now - */ - - for (node = OF_child(node); node > 0; node = OF_peer(node)) { - if ((di = simplebus_setup_dinfo(dev, node)) == NULL) - continue; - cdev = device_add_child(dev, NULL, -1); - if (cdev == NULL) { - device_printf(dev, "<%s>: device_add_child failed\n", - di->obdinfo.obd_name); - resource_list_free(&di->rl); - ofw_bus_gen_destroy_devinfo(&di->obdinfo); - free(di, M_DEVBUF); - continue; - } - device_set_ivars(cdev, di); - } - - return (bus_generic_attach(dev)); } static int simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc) { int host_address_cells; cell_t *base_ranges; ssize_t nbase_ranges; int err; int i, j, k; err = OF_searchencprop(OF_parent(node), "#address-cells", &host_address_cells, sizeof(host_address_cells)); if (err <= 0) return (-1); nbase_ranges = OF_getproplen(node, "ranges"); if (nbase_ranges < 0) return (-1); sc->nranges = nbase_ranges / sizeof(cell_t) / (sc->acells + host_address_cells + sc->scells); if (sc->nranges == 0) return (0); sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), M_DEVBUF, M_WAITOK); base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); OF_getencprop(node, "ranges", base_ranges, nbase_ranges); for (i = 0, j = 0; i < sc->nranges; i++) { sc->ranges[i].bus = 0; for (k = 0; k < sc->acells; k++) { sc->ranges[i].bus <<= 32; sc->ranges[i].bus |= base_ranges[j++]; } sc->ranges[i].host = 0; for (k = 0; k < host_address_cells; k++) { sc->ranges[i].host <<= 32; sc->ranges[i].host |= base_ranges[j++]; } sc->ranges[i].size = 0; for (k = 0; k < sc->scells; k++) { sc->ranges[i].size <<= 32; sc->ranges[i].size |= base_ranges[j++]; } } free(base_ranges, M_DEVBUF); return (sc->nranges); } -static struct simplebus_devinfo * -simplebus_setup_dinfo(device_t dev, phandle_t node) +struct simplebus_devinfo * +simplebus_setup_dinfo(device_t dev, phandle_t node, + struct simplebus_devinfo *di) { struct simplebus_softc *sc; struct simplebus_devinfo *ndi; sc = device_get_softc(dev); - - ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + if (di == NULL) + ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + else + ndi = di; if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) { - free(ndi, M_DEVBUF); + if (di == NULL) + free(ndi, M_DEVBUF); return (NULL); } resource_list_init(&ndi->rl); ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->rl); ofw_bus_intr_to_rl(dev, node, &ndi->rl); return (ndi); } +device_t +simplebus_add_device(device_t dev, phandle_t node, u_int order, + const char *name, int unit, struct simplebus_devinfo *di) +{ + struct simplebus_devinfo *ndi; + device_t cdev; + + if ((ndi = simplebus_setup_dinfo(dev, node, di)) == NULL) + return (NULL); + cdev = device_add_child_ordered(dev, order, name, unit); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + ndi->obdinfo.obd_name); + resource_list_free(&ndi->rl); + ofw_bus_gen_destroy_devinfo(&ndi->obdinfo); + if (di == NULL) + free(ndi, M_DEVBUF); + return (NULL); + } + device_set_ivars(cdev, ndi); + + return(cdev); +} + +static device_t +simplebus_add_child(device_t dev, u_int order, const char *name, int unit) +{ + device_t cdev; + struct simplebus_devinfo *ndi; + + cdev = device_add_child_ordered(dev, order, name, unit); + if (cdev == NULL) + return (NULL); + + ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); + ndi->obdinfo.obd_node = -1; + resource_list_init(&ndi->rl); + device_set_ivars(cdev, ndi); + + return (cdev); +} + static const struct ofw_bus_devinfo * simplebus_get_devinfo(device_t bus __unused, device_t child) { struct simplebus_devinfo *ndi; ndi = device_get_ivars(child); return (&ndi->obdinfo); } +static struct resource_list * +simplebus_get_resource_list(device_t bus __unused, device_t child) +{ + struct simplebus_devinfo *ndi; + + ndi = device_get_ivars(child); + return (&ndi->rl); +} + static struct resource * simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct simplebus_softc *sc; struct simplebus_devinfo *di; struct resource_list_entry *rle; int j; sc = device_get_softc(bus); /* * Request for the default allocation with a given rid: use resource * list stored in the local device info. */ if ((start == 0UL) && (end == ~0UL)) { if ((di = device_get_ivars(child)) == NULL) return (NULL); if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; rle = resource_list_find(&di->rl, type, *rid); if (rle == NULL) { if (bootverbose) device_printf(bus, "no default resources for " "rid = %d, type = %d\n", *rid, type); return (NULL); } start = rle->start; end = rle->end; count = rle->count; } if (type == SYS_RES_MEMORY) { /* Remap through ranges property */ for (j = 0; j < sc->nranges; j++) { if (start >= sc->ranges[j].bus && end < sc->ranges[j].bus + sc->ranges[j].size) { start -= sc->ranges[j].bus; start += sc->ranges[j].host; end -= sc->ranges[j].bus; end += sc->ranges[j].host; break; } } if (j == sc->nranges && sc->nranges != 0) { if (bootverbose) device_printf(bus, "Could not map resource " "%#lx-%#lx\n", start, end); return (NULL); } } return (bus_generic_alloc_resource(bus, child, type, rid, start, end, count, flags)); } static int simplebus_print_res(struct simplebus_devinfo *di) { int rv; rv = 0; rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx"); rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld"); return (rv); } static void simplebus_probe_nomatch(device_t bus, device_t child) { const char *name, *type, *compat; if (!bootverbose) return; + compat = ofw_bus_get_compat(child); + if (compat == NULL) + return; name = ofw_bus_get_name(child); type = ofw_bus_get_type(child); - compat = ofw_bus_get_compat(child); device_printf(bus, "<%s>", name != NULL ? name : "unknown"); simplebus_print_res(device_get_ivars(child)); if (!ofw_bus_status_okay(child)) printf(" disabled"); if (type) printf(" type %s", type); - if (compat) - printf(" compat %s", compat); - printf(" (no driver attached)\n"); + printf(" compat %s (no driver attached)\n", compat); } static int simplebus_print_child(device_t bus, device_t child) { int rv; rv = bus_print_child_header(bus, child); rv += simplebus_print_res(device_get_ivars(child)); if (!ofw_bus_status_okay(child)) rv += printf(" disabled"); rv += bus_print_child_footer(bus, child); return (rv); } Index: head/sys/dev/fdt/simplebus.h =================================================================== --- head/sys/dev/fdt/simplebus.h (revision 280771) +++ head/sys/dev/fdt/simplebus.h (revision 280772) @@ -1,56 +1,64 @@ /*- * Copyright (c) 2013 Nathan Whitehorn * 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 AND CONTRIBUTORS ``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 _FDT_SIMPLEBUS_PRIVATE_H -#define _FDT_SIMPLEBUS_PRIVATE_H +#ifndef _FDT_SIMPLEBUS_H +#define _FDT_SIMPLEBUS_H +#include + /* FDT simplebus */ DECLARE_CLASS(simplebus_driver); struct simplebus_range { uint64_t bus; uint64_t host; uint64_t size; }; /* devinfo and softc */ struct simplebus_softc { device_t dev; phandle_t node; struct simplebus_range *ranges; int nranges; pcell_t acells, scells; }; struct simplebus_devinfo { struct ofw_bus_devinfo obdinfo; struct resource_list rl; }; -#endif /* _FDT_SIMPLEBUS_PRIVATE_H */ + +void simplebus_init(device_t dev, phandle_t node); +device_t simplebus_add_device(device_t dev, phandle_t node, u_int order, + const char *name, int unit, struct simplebus_devinfo *di); +struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev, phandle_t node, + struct simplebus_devinfo *di); +#endif /* _FDT_SIMPLEBUS_H */ Index: head/sys/dev/ofw/ofwbus.c =================================================================== --- head/sys/dev/ofw/ofwbus.c (revision 280771) +++ head/sys/dev/ofw/ofwbus.c (revision 280772) @@ -1,488 +1,276 @@ /*- * Copyright 1998 Massachusetts Institute of Technology * Copyright 2001 by Thomas Moestl . * Copyright 2006 by Marius Strobl . * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. 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: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include /* * The ofwbus (which is a pseudo-bus actually) iterates over the nodes that * hang from the Open Firmware root node and adds them as devices to this bus * (except some special nodes which are excluded) so that drivers can be * attached to them. * */ -struct ofwbus_devinfo { - struct ofw_bus_devinfo ndi_obdinfo; - struct resource_list ndi_rl; -}; - struct ofwbus_softc { - uint32_t acells, scells; + struct simplebus_softc simplebus_sc; struct rman sc_intr_rman; struct rman sc_mem_rman; }; static device_identify_t ofwbus_identify; static device_probe_t ofwbus_probe; static device_attach_t ofwbus_attach; -static bus_print_child_t ofwbus_print_child; -static bus_add_child_t ofwbus_add_child; -static bus_probe_nomatch_t ofwbus_probe_nomatch; static bus_alloc_resource_t ofwbus_alloc_resource; static bus_adjust_resource_t ofwbus_adjust_resource; static bus_release_resource_t ofwbus_release_resource; -static bus_get_resource_list_t ofwbus_get_resource_list; -static ofw_bus_get_devinfo_t ofwbus_get_devinfo; -static int ofwbus_inlist(const char *, const char *const *); -static struct ofwbus_devinfo * ofwbus_setup_dinfo(device_t, phandle_t); -static void ofwbus_destroy_dinfo(struct ofwbus_devinfo *); -static int ofwbus_print_res(struct ofwbus_devinfo *); - static device_method_t ofwbus_methods[] = { /* Device interface */ DEVMETHOD(device_identify, ofwbus_identify), DEVMETHOD(device_probe, ofwbus_probe), DEVMETHOD(device_attach, ofwbus_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ - DEVMETHOD(bus_print_child, ofwbus_print_child), - DEVMETHOD(bus_probe_nomatch, ofwbus_probe_nomatch), - DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), - DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), - DEVMETHOD(bus_add_child, ofwbus_add_child), - DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), DEVMETHOD(bus_alloc_resource, ofwbus_alloc_resource), DEVMETHOD(bus_adjust_resource, ofwbus_adjust_resource), DEVMETHOD(bus_release_resource, ofwbus_release_resource), - DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), - DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), - DEVMETHOD(bus_get_resource_list, ofwbus_get_resource_list), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_config_intr, bus_generic_config_intr), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_devinfo, ofwbus_get_devinfo), - DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), - DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), - DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), - DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), - DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), - DEVMETHOD_END }; -static driver_t ofwbus_driver = { - "ofwbus", - ofwbus_methods, - sizeof(struct ofwbus_softc) -}; +DEFINE_CLASS_1(ofwbus, ofwbus_driver, ofwbus_methods, + sizeof(struct ofwbus_softc), simplebus_driver); static devclass_t ofwbus_devclass; EARLY_DRIVER_MODULE(ofwbus, nexus, ofwbus_driver, ofwbus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(ofwbus, 1); -static const char *const ofwbus_excl_name[] = { - "FJSV,system", - "aliases", - "associations", - "chosen", - "cmp", - "counter-timer", /* No separate device; handled by psycho/sbus */ - "failsafe", - "memory", - "openprom", - "options", - "packages", - "physical-memory", - "rsc", - "sgcn", - "todsg", - "virtual-memory", - NULL -}; - -static const char *const ofwbus_excl_type[] = { - "core", - "cpu", - NULL -}; - -static int -ofwbus_inlist(const char *name, const char *const *list) -{ - int i; - - if (name == NULL) - return (0); - for (i = 0; list[i] != NULL; i++) - if (strcmp(name, list[i]) == 0) - return (1); - return (0); -} - -#define OFWBUS_EXCLUDED(name, type) \ - (ofwbus_inlist((name), ofwbus_excl_name) || \ - ((type) != NULL && ofwbus_inlist((type), ofwbus_excl_type))) - static void ofwbus_identify(driver_t *driver, device_t parent) { /* Check if Open Firmware has been instantiated */ if (OF_peer(0) == 0) return; - + if (device_find_child(parent, "ofwbus", -1) == NULL) BUS_ADD_CHILD(parent, 0, "ofwbus", -1); } static int ofwbus_probe(device_t dev) { device_set_desc(dev, "Open Firmware Device Tree"); return (BUS_PROBE_NOWILDCARD); } static int ofwbus_attach(device_t dev) { - struct ofwbus_devinfo *ndi; struct ofwbus_softc *sc; - device_t cdev; phandle_t node; + struct ofw_bus_devinfo obd; sc = device_get_softc(dev); node = OF_peer(0); /* * If no Open Firmware, bail early */ if (node == -1) return (ENXIO); + /* + * ofwbus bus starts on unamed node in FDT, so we cannot make + * ofw_bus_devinfo from it. Pass node to simplebus_init directly. + */ + simplebus_init(dev, node); sc->sc_intr_rman.rm_type = RMAN_ARRAY; sc->sc_intr_rman.rm_descr = "Interrupts"; sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "Device Memory"; if (rman_init(&sc->sc_intr_rman) != 0 || rman_init(&sc->sc_mem_rman) != 0 || rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 || rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR) != 0) panic("%s: failed to set up rmans.", __func__); /* * Allow devices to identify. */ bus_generic_probe(dev); /* - * Some important numbers - */ - sc->acells = 2; - OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells)); - sc->scells = 1; - OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells)); - - /* * Now walk the OFW tree and attach top-level devices. */ for (node = OF_child(node); node > 0; node = OF_peer(node)) { - if ((ndi = ofwbus_setup_dinfo(dev, node)) == NULL) + if (ofw_bus_gen_setup_devinfo(&obd, node) != 0) continue; - cdev = device_add_child(dev, NULL, -1); - if (cdev == NULL) { - device_printf(dev, "<%s>: device_add_child failed\n", - ndi->ndi_obdinfo.obd_name); - ofwbus_destroy_dinfo(ndi); - continue; - } - device_set_ivars(cdev, ndi); + simplebus_add_device(dev, node, 0, NULL, -1, NULL); } return (bus_generic_attach(dev)); } -static device_t -ofwbus_add_child(device_t dev, u_int order, const char *name, int unit) -{ - device_t cdev; - struct ofwbus_devinfo *ndi; - - cdev = device_add_child_ordered(dev, order, name, unit); - if (cdev == NULL) - return (NULL); - - ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); - ndi->ndi_obdinfo.obd_node = -1; - resource_list_init(&ndi->ndi_rl); - device_set_ivars(cdev, ndi); - - return (cdev); -} - -static int -ofwbus_print_child(device_t bus, device_t child) -{ - int rv; - - rv = bus_print_child_header(bus, child); - rv += ofwbus_print_res(device_get_ivars(child)); - rv += bus_print_child_footer(bus, child); - return (rv); -} - -static void -ofwbus_probe_nomatch(device_t bus, device_t child) -{ - const char *name, *type; - - if (!bootverbose) - return; - - name = ofw_bus_get_name(child); - type = ofw_bus_get_type(child); - - device_printf(bus, "<%s>", - name != NULL ? name : "unknown"); - ofwbus_print_res(device_get_ivars(child)); - printf(" type %s (no driver attached)\n", - type != NULL ? type : "unknown"); -} - static struct resource * ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ofwbus_softc *sc; struct rman *rm; struct resource *rv; struct resource_list_entry *rle; int isdefault, passthrough; isdefault = (start == 0UL && end == ~0UL); passthrough = (device_get_parent(child) != bus); sc = device_get_softc(bus); rle = NULL; - if (!passthrough && isdefault) { rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, *rid); - if (rle == NULL) + if (rle == NULL) { + if (bootverbose) + device_printf(bus, "no default resources for " + "rid = %d, type = %d\n", *rid, type); return (NULL); - if (rle->res != NULL) - panic("%s: resource entry is busy", __func__); + } start = rle->start; count = ulmax(count, rle->count); end = ulmax(rle->end, start + count - 1); } switch (type) { case SYS_RES_IRQ: rm = &sc->sc_intr_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, child); if (rv == NULL) return (NULL); rman_set_rid(rv, *rid); if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, *rid, rv) != 0) { rman_release_resource(rv); return (NULL); } if (!passthrough && rle != NULL) { rle->res = rv; rle->start = rman_get_start(rv); rle->end = rman_get_end(rv); rle->count = rle->end - rle->start + 1; } return (rv); } static int ofwbus_adjust_resource(device_t bus, device_t child __unused, int type, struct resource *r, u_long start, u_long end) { struct ofwbus_softc *sc; struct rman *rm; device_t ofwbus; ofwbus = bus; while (strcmp(device_get_name(device_get_parent(ofwbus)), "root") != 0) ofwbus = device_get_parent(ofwbus); sc = device_get_softc(ofwbus); switch (type) { case SYS_RES_IRQ: rm = &sc->sc_intr_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; default: return (EINVAL); } if (rm == NULL) return (ENXIO); if (rman_is_region_manager(r, rm) == 0) return (EINVAL); return (rman_adjust_resource(r, start, end)); } static int ofwbus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct resource_list_entry *rle; int error; /* Clean resource list entry */ rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), type, rid); if (rle != NULL) rle->res = NULL; if ((rman_get_flags(r) & RF_ACTIVE) != 0) { error = bus_deactivate_resource(child, type, rid, r); if (error) return (error); } return (rman_release_resource(r)); } - -static struct resource_list * -ofwbus_get_resource_list(device_t bus __unused, device_t child) -{ - struct ofwbus_devinfo *ndi; - - ndi = device_get_ivars(child); - return (&ndi->ndi_rl); -} - -static const struct ofw_bus_devinfo * -ofwbus_get_devinfo(device_t bus __unused, device_t child) -{ - struct ofwbus_devinfo *ndi; - - ndi = device_get_ivars(child); - return (&ndi->ndi_obdinfo); -} - -static struct ofwbus_devinfo * -ofwbus_setup_dinfo(device_t dev, phandle_t node) -{ - struct ofwbus_softc *sc; - struct ofwbus_devinfo *ndi; - const char *nodename; - - sc = device_get_softc(dev); - - ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); - if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) { - free(ndi, M_DEVBUF); - return (NULL); - } - nodename = ndi->ndi_obdinfo.obd_name; - if (OFWBUS_EXCLUDED(nodename, ndi->ndi_obdinfo.obd_type)) { - ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo); - free(ndi, M_DEVBUF); - return (NULL); - } - - resource_list_init(&ndi->ndi_rl); - ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->ndi_rl); - ofw_bus_intr_to_rl(dev, node, &ndi->ndi_rl); - - return (ndi); -} - -static void -ofwbus_destroy_dinfo(struct ofwbus_devinfo *ndi) -{ - - resource_list_free(&ndi->ndi_rl); - ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo); - free(ndi, M_DEVBUF); -} - -static int -ofwbus_print_res(struct ofwbus_devinfo *ndi) -{ - int rv; - - rv = 0; - rv += resource_list_print_type(&ndi->ndi_rl, "mem", SYS_RES_MEMORY, - "%#lx"); - rv += resource_list_print_type(&ndi->ndi_rl, "irq", SYS_RES_IRQ, - "%ld"); - return (rv); -} -