diff options
author | grehan <grehan@FreeBSD.org> | 2002-09-19 04:57:10 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2002-09-19 04:57:10 +0000 |
commit | 22d2979d2dd5d80d32a308dc412a86747ca1ecee (patch) | |
tree | d8d9590f9f64d7806c566b3381c82a1bf3b3ba02 /sys/powerpc/psim | |
parent | b9926b1f0b93d56ded1b08d95336ddc0886e1403 (diff) | |
download | FreeBSD-src-22d2979d2dd5d80d32a308dc412a86747ca1ecee.zip FreeBSD-src-22d2979d2dd5d80d32a308dc412a86747ca1ecee.tar.gz |
Support files and a h/w tree description for the PSIM ppc simulator
Approved by: benno
Diffstat (limited to 'sys/powerpc/psim')
-rw-r--r-- | sys/powerpc/psim/ata_iobus.c | 244 | ||||
-rw-r--r-- | sys/powerpc/psim/iobus.c | 409 | ||||
-rw-r--r-- | sys/powerpc/psim/iobusvar.h | 73 | ||||
-rw-r--r-- | sys/powerpc/psim/psim-tree | 74 | ||||
-rw-r--r-- | sys/powerpc/psim/sio_iobus.c | 109 | ||||
-rw-r--r-- | sys/powerpc/psim/uart_iobus.c | 109 |
6 files changed, 1018 insertions, 0 deletions
diff --git a/sys/powerpc/psim/ata_iobus.c b/sys/powerpc/psim/ata_iobus.c new file mode 100644 index 0000000..692f618 --- /dev/null +++ b/sys/powerpc/psim/ata_iobus.c @@ -0,0 +1,244 @@ +/* + * Copyright 2002 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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$ + */ + +/* + * PSIM local bus ATA controller + */ +#include "opt_ata.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/disk.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/bio.h> +#include <sys/malloc.h> +#include <sys/devicestat.h> +#include <sys/sysctl.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <dev/ata/ata-all.h> + +#include <dev/ofw/openfirm.h> +#include <powerpc/psim/iobusvar.h> + +/* + * Define the iobus ata bus attachment. This creates a pseudo-bus that + * the ATA device can be attached to + */ +static int ata_iobus_attach(device_t dev); +static int ata_iobus_probe(device_t dev); +static int ata_iobus_print_child(device_t dev, device_t child); +struct resource *ata_iobus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int ata_iobus_release_resource(device_t, device_t, int, int, + struct resource *); + +static device_method_t ata_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_iobus_probe), + DEVMETHOD(device_attach, ata_iobus_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus methods */ + DEVMETHOD(bus_print_child, ata_iobus_print_child), + DEVMETHOD(bus_alloc_resource, ata_iobus_alloc_resource), + DEVMETHOD(bus_release_resource, ata_iobus_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t ata_iobus_driver = { + "ataiobus", + ata_iobus_methods, + 0, +}; + +static devclass_t ata_iobus_devclass; + +DRIVER_MODULE(ataiobus, iobus, ata_iobus_driver, ata_iobus_devclass, 0, 0); + + +static int +ata_iobus_probe(device_t dev) +{ + char *type = iobus_get_name(dev); + + if (strncmp(type, "ata", 3) != 0) + return (ENXIO); + + device_set_desc(dev, "PSIM ATA Controller"); + return (0); +} + + +static int +ata_iobus_attach(device_t dev) +{ + /* + * Add a single child per controller. Should be able + * to add two + */ + device_add_child(dev, "ata", + devclass_find_free_unit(ata_devclass, 0)); + + return (bus_generic_attach(dev)); +} + + +static int +ata_iobus_print_child(device_t dev, device_t child) +{ + struct ata_channel *ch = device_get_softc(child); + int retval = 0; + + retval += bus_print_child_header(dev, child); + retval += printf(": at 0x%lx", rman_get_start(ch->r_io)); + /* irq ? */ + retval += bus_print_child_footer(dev, child); + + return (retval); +} + + +struct resource * +ata_iobus_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *res = NULL; + int myrid; + u_int *ofw_regs; + + ofw_regs = iobus_get_regs(dev); + + /* + * The reg array for the PSIM ata device has 6 start/size entries: + * 0 - unused + * 1/2/3 - unused + * 4/5/6 - primary command + * 7/8/9 - secondary command + * 10/11/12 - primary control + * 13/14/15 - secondary control + * 16/17/18 - primary/secondary dma registers, unimplemented + * + * The resource values are calculated from these registers + */ + if (type == SYS_RES_IOPORT) { + switch (*rid) { + case ATA_IOADDR_RID: + myrid = 0; + start = ofw_regs[4]; + end = start + ATA_IOSIZE - 1; + count = ATA_IOSIZE; + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_MEMORY, &myrid, + start, end, count, flags); + break; + + case ATA_ALTADDR_RID: + myrid = 0; + start = ofw_regs[10]; + end = start + ATA_ALTIOSIZE - 1; + count = ATA_ALTIOSIZE; + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_MEMORY, &myrid, + start, end, count, flags); + break; + + case ATA_BMADDR_RID: + /* DMA not properly supported by psim */ + break; + } + return (res); + + } else if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { + /* + * Pass this on to the parent + */ + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IRQ, rid, 0, ~0, 1, flags)); + + } else { + return (NULL); + } +} + + +static int +ata_iobus_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + /* no hotplug... */ + return (0); +} + + +/* + * Define the actual ATA device. This is a sub-bus to the ata-iobus layer + * to allow the higher layer bus to massage the resource allocation. + */ + +static int ata_iobus_sub_probe(device_t dev); + +static device_method_t ata_iobus_sub_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_iobus_sub_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_resume, ata_resume), + + { 0, 0 } +}; + +static driver_t ata_iobus_sub_driver = { + "ata", + ata_iobus_sub_methods, + sizeof(struct ata_channel), +}; + +DRIVER_MODULE(ata, ataiobus, ata_iobus_sub_driver, ata_devclass, 0, 0); + +static int +ata_iobus_sub_probe(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + /* Only a single unit per controller thus far */ + ch->unit = 0; + + return ata_probe(dev); +} diff --git a/sys/powerpc/psim/iobus.c b/sys/powerpc/psim/iobus.c new file mode 100644 index 0000000..3428125 --- /dev/null +++ b/sys/powerpc/psim/iobus.c @@ -0,0 +1,409 @@ +/* + * Copyright 2002 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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$ + */ + +/* + * PSIM 'iobus' local bus. Should be set up in the device tree like: + * + * /iobus@0x80000000/name psim-iobus + * + * Code borrowed from various nexus.c and uninorth.c :-) + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/resource.h> +#include <machine/nexusvar.h> + +#include <powerpc/psim/iobusvar.h> + +static MALLOC_DEFINE(M_IOBUS, "iobus", "iobus device information"); + +static int iobus_probe(device_t); +static int iobus_attach(device_t); +static int iobus_print_child(device_t dev, device_t child); +static void iobus_probe_nomatch(device_t, device_t); +static int iobus_read_ivar(device_t, device_t, int, uintptr_t *); +static int iobus_write_ivar(device_t, device_t, int, uintptr_t); +static struct resource *iobus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int iobus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int iobus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int iobus_release_resource(device_t, device_t, int, int, + struct resource *); + +/* + * Bus interface definition + */ +static device_method_t iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, iobus_probe), + DEVMETHOD(device_attach, iobus_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, iobus_print_child), + DEVMETHOD(bus_probe_nomatch, iobus_probe_nomatch), + DEVMETHOD(bus_read_ivar, iobus_read_ivar), + DEVMETHOD(bus_write_ivar, iobus_write_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + DEVMETHOD(bus_alloc_resource, iobus_alloc_resource), + DEVMETHOD(bus_release_resource, iobus_release_resource), + DEVMETHOD(bus_activate_resource, iobus_activate_resource), + DEVMETHOD(bus_deactivate_resource, iobus_deactivate_resource), + + { 0, 0 } +}; + +static driver_t iobus_driver = { + "iobus", + iobus_methods, + sizeof(struct iobus_softc) +}; + +devclass_t iobus_devclass; + +DRIVER_MODULE(iobus, nexus, iobus_driver, iobus_devclass, 0, 0); + +static int +iobus_probe(device_t dev) +{ + char *type = nexus_get_name(dev); + + if (strcmp(type, "psim-iobus") != 0) + return (ENXIO); + + device_set_desc(dev, "PSIM local bus"); + return (0); +} + +/* + * Add interrupt/addr range to the dev's resource list if present + */ +static void +iobus_add_intr(phandle_t devnode, struct iobus_devinfo *dinfo) +{ + u_int intr = -1; + + if (OF_getprop(devnode, "interrupt", &intr, sizeof(intr)) != -1) { + resource_list_add(&dinfo->id_resources, + SYS_RES_IRQ, 0, intr, intr, 1); + } + dinfo->id_interrupt = intr; +} + + +static void +iobus_add_reg(phandle_t devnode, struct iobus_devinfo *dinfo, + vm_offset_t iobus_off) +{ + u_int size; + int i; + + size = OF_getprop(devnode, "reg", dinfo->id_reg,sizeof(dinfo->id_reg)); + + if (size != -1) { + dinfo->id_nregs = size / (sizeof(dinfo->id_reg[0])); + + for (i = 0; i < dinfo->id_nregs; i+= 3) { + /* + * Scale the absolute addresses back to iobus + * relative offsets. This is to better simulate + * macio + */ + dinfo->id_reg[i+1] -= iobus_off; + + resource_list_add(&dinfo->id_resources, + SYS_RES_MEMORY, 0, + dinfo->id_reg[i+1], + dinfo->id_reg[i+1] + + dinfo->id_reg[i+2], + dinfo->id_reg[i+2]); + } + } +} + + +static int +iobus_attach(device_t dev) +{ + struct iobus_softc *sc; + struct iobus_devinfo *dinfo; + phandle_t root; + phandle_t child; + device_t cdev; + char *name; + u_int reg[2]; + int size; + + sc = device_get_softc(dev); + sc->sc_node = nexus_get_node(dev); + + /* + * Find the base addr/size of the iobus, and initialize the + * resource manager + */ + size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg)); + if (size == sizeof(reg)) { + sc->sc_addr = reg[0]; + sc->sc_size = reg[1]; + } else { + return (ENXIO); + } + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "IOBus Device Memory"; + if (rman_init(&sc->sc_mem_rman) != 0) { + device_printf(dev, + "failed to init mem range resources\n"); + return (ENXIO); + } + rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); + + /* + * Iterate through the sub-devices + */ + root = sc->sc_node; + + for (child = OF_child(root); child != 0; child = OF_peer(child)) { + OF_getprop_alloc(child, "name", 1, (void **)&name); + + cdev = device_add_child(dev, NULL, -1); + if (cdev != NULL) { + dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK); + memset(dinfo, 0, sizeof(*dinfo)); + resource_list_init(&dinfo->id_resources); + dinfo->id_node = child; + dinfo->id_name = name; + iobus_add_intr(child, dinfo); + iobus_add_reg(child, dinfo, sc->sc_addr); + device_set_ivars(cdev, dinfo); + } else { + free(name, M_OFWPROP); + } + } + + return (bus_generic_attach(dev)); +} + + +static int +iobus_print_child(device_t dev, device_t child) +{ + struct iobus_devinfo *dinfo; + struct resource_list *rl; + int retval = 0; + + dinfo = device_get_ivars(child); + rl = &dinfo->id_resources; + + retval += bus_print_child_header(dev, child); + + retval += printf(" offset 0x%x", dinfo->id_reg[1]); + retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + + retval += bus_print_child_footer(dev, child); + + return (retval); +} + + +static void +iobus_probe_nomatch(device_t dev, device_t child) +{ +} + + +static int +iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct iobus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(child)) == 0) + return (ENOENT); + + switch (which) { + case IOBUS_IVAR_NODE: + *result = dinfo->id_node; + break; + case IOBUS_IVAR_NAME: + *result = (uintptr_t)dinfo->id_name; + break; + case IOBUS_IVAR_NREGS: + *result = dinfo->id_nregs; + break; + case IOBUS_IVAR_REGS: + *result = (uintptr_t)dinfo->id_reg; + break; + default: + return (ENOENT); + } + + return (0); +} + + +static int +iobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + return (EINVAL); +} + + +static struct resource * +iobus_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 iobus_softc *sc; + int needactivate; + struct resource *rv; + struct rman *rm; + bus_space_tag_t tagval; + + sc = device_get_softc(bus); + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + switch (type) { + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + rm = &sc->sc_mem_rman; + tagval = PPC_BUS_SPACE_MEM; + if (flags & PPC_BUS_SPARSE4) + tagval |= 4; + break; + case SYS_RES_IRQ: + return (bus_alloc_resource(bus, type, rid, start, end, count, + flags)); + break; + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "failed to reserve resource for %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rman_set_bustag(rv, tagval); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + + +static int +iobus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + if (rman_get_flags(res) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, res); + if (error) + return error; + } + + return (rman_release_resource(res)); +} + + +static int +iobus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct iobus_softc *sc; + void *p; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) + return (bus_activate_resource(bus, type, rid, res)); + + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr, + (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + + +static int +iobus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + /* + * If this is a memory resource, unmap it. + */ + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + u_int32_t psize; + + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + } + + return (rman_deactivate_resource(res)); +} diff --git a/sys/powerpc/psim/iobusvar.h b/sys/powerpc/psim/iobusvar.h new file mode 100644 index 0000000..3862c64 --- /dev/null +++ b/sys/powerpc/psim/iobusvar.h @@ -0,0 +1,73 @@ +/* + * Copyright 2002 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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 _PSIM_IOBUSVAR_H_ +#define _PSIM_IOBUSVAR_H_ + +/* + * Accessors for iobus devices + */ + +enum iobus_ivars { + IOBUS_IVAR_NODE, + IOBUS_IVAR_NAME, + IOBUS_IVAR_NREGS, + IOBUS_IVAR_REGS, +}; + +#define IOBUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(iobus, var, IOBUS, ivar, type) + +IOBUS_ACCESSOR(node, NODE, phandle_t) +IOBUS_ACCESSOR(name, NAME, char *) +IOBUS_ACCESSOR(nregs, NREGS, u_int) +IOBUS_ACCESSOR(regs, REGS, u_int *) + +#undef IOBUS_ACCESSOR + +/* + * Per-device structure. + */ +struct iobus_devinfo { + phandle_t id_node; + char *id_name; + int id_interrupt; + u_int id_nregs; + u_int id_reg[24]; + struct resource_list id_resources; +}; + +struct iobus_softc { + phandle_t sc_node; + vm_offset_t sc_addr; + vm_offset_t sc_size; + struct rman sc_mem_rman; +}; + +#endif /* _PSIM_IOBUSVAR_H_ */ diff --git a/sys/powerpc/psim/psim-tree b/sys/powerpc/psim/psim-tree new file mode 100644 index 0000000..6e038d4 --- /dev/null +++ b/sys/powerpc/psim/psim-tree @@ -0,0 +1,74 @@ +# $FreeBSD$ +# +# Simple psim h/w description +# + +/#address-cells 1 +/openprom/options/use-stdio? false +#/openprom/options/strict-alignment? true + +# +# CPU definition. The phandle property is to help nexus.c locate the +# interrupt controller. +# +/cpus/cpu@0 + +# +# disk file, done via phb crap. maybe there's a better way. +# +/phb@0x70000000 + ./device_type "pci + ./name "pci + ./#address-cells 3 + ./#size-cells 2 + ./ranges ni0,0,0,0 0xc0000000 0x10000 + +/phb@0x70000000/ide@1 + ./device_type "ide + ./name "ide + ./assigned-addresses \ + ni0,0,10,1f0 8 \ + ni0,0,14,3f8 8 \ + ni0,0,18,170 8 \ + ni0,0,1c,378 8 \ + ni0,0,20,200 8 + ./reg \ + 1 0 \ + i0,0,10,0 8 \ + i0,0,18,0 8 \ + i0,0,14,6 1 \ + i0,0,1c,6 1 \ + i0,0,20,0 8 + ./ready-delay 1000 + +/phb@0x70000000/ide@1/disk@0/file "PPC.IMG + +# +# I/O Bus +# +/iobus@0x80000000 + ./name psim-iobus + ./reg 0x80000000 0x20000000 + +# +# OpenPIC +# +/iobus@0x80000000/opic@0x80000000 + ./name interrupt-controller + ./device_type open-pic + ./compatible psim,open-pic + ./reg 0x80000000 0x40000 + ./interrupt-ranges 0 256 + +/iobus/opic > intr0 int /cpus/cpu@0x0 + +# +# IDE1 +# +#/iobus@0x80000000/ide@0x80052000 +# ./name ata-4 +# ./ioport 1 +# ./device_type ata +# ./interrupt 12 +# ./reg 0x80052000 8 0x80052010 8 0x80052020 8 0x80052030 1 0x80052040 1 0x80052050 8 +#/iobus@0x80000000/ide@0x80052000 > a irq12 /iobus/opic diff --git a/sys/powerpc/psim/sio_iobus.c b/sys/powerpc/psim/sio_iobus.c new file mode 100644 index 0000000..f2174ae --- /dev/null +++ b/sys/powerpc/psim/sio_iobus.c @@ -0,0 +1,109 @@ +/* + * Copyright 2002 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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$ + */ + +/* + * PSIM local bus 16550 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/module.h> +#include <sys/tty.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <sys/timepps.h> + +#include <dev/ofw/openfirm.h> +#include <powerpc/psim/iobusvar.h> + +#include <dev/sio/sioreg.h> +#include <dev/sio/siovar.h> + +#include <isa/isavar.h> /* for isa_irq_pending() prototype */ + +static int sio_iobus_attach(device_t dev); +static int sio_iobus_probe(device_t dev); + +static device_method_t sio_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, sio_iobus_probe), + DEVMETHOD(device_attach, sio_iobus_attach), + + { 0, 0 } +}; + +static driver_t sio_iobus_driver = { + sio_driver_name, + sio_iobus_methods, + 0, +}; + +static int +sio_iobus_attach(device_t dev) +{ + return (sioattach(dev, 0, DEFAULT_RCLK)); +} + +static int +sio_iobus_probe(device_t dev) +{ + char *type = iobus_get_name(dev); + + if (strncmp(type, "com", 3) != 0) + return (ENXIO); + + + device_set_desc(dev, "PSIM serial port"); + + /* + * Call sioprobe with noprobe=1, to avoid hitting a psim bug + */ + return (sioprobe(dev, 0, 0, 1)); +} + +DRIVER_MODULE(sio, iobus, sio_iobus_driver, sio_devclass, 0, 0); + +/* + * Stub function. Perhaps a way to get this to work correctly would + * be for child devices to set a field in the dev structure to + * inform the parent that they are isa devices, and then use a + * intr_pending() call which would propagate up to nexus to see + * if the interrupt controller had any intrs in the isa group set + */ +intrmask_t +isa_irq_pending(void) +{ + return (0); +} diff --git a/sys/powerpc/psim/uart_iobus.c b/sys/powerpc/psim/uart_iobus.c new file mode 100644 index 0000000..f2174ae --- /dev/null +++ b/sys/powerpc/psim/uart_iobus.c @@ -0,0 +1,109 @@ +/* + * Copyright 2002 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 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$ + */ + +/* + * PSIM local bus 16550 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/module.h> +#include <sys/tty.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <sys/timepps.h> + +#include <dev/ofw/openfirm.h> +#include <powerpc/psim/iobusvar.h> + +#include <dev/sio/sioreg.h> +#include <dev/sio/siovar.h> + +#include <isa/isavar.h> /* for isa_irq_pending() prototype */ + +static int sio_iobus_attach(device_t dev); +static int sio_iobus_probe(device_t dev); + +static device_method_t sio_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, sio_iobus_probe), + DEVMETHOD(device_attach, sio_iobus_attach), + + { 0, 0 } +}; + +static driver_t sio_iobus_driver = { + sio_driver_name, + sio_iobus_methods, + 0, +}; + +static int +sio_iobus_attach(device_t dev) +{ + return (sioattach(dev, 0, DEFAULT_RCLK)); +} + +static int +sio_iobus_probe(device_t dev) +{ + char *type = iobus_get_name(dev); + + if (strncmp(type, "com", 3) != 0) + return (ENXIO); + + + device_set_desc(dev, "PSIM serial port"); + + /* + * Call sioprobe with noprobe=1, to avoid hitting a psim bug + */ + return (sioprobe(dev, 0, 0, 1)); +} + +DRIVER_MODULE(sio, iobus, sio_iobus_driver, sio_devclass, 0, 0); + +/* + * Stub function. Perhaps a way to get this to work correctly would + * be for child devices to set a field in the dev structure to + * inform the parent that they are isa devices, and then use a + * intr_pending() call which would propagate up to nexus to see + * if the interrupt controller had any intrs in the isa group set + */ +intrmask_t +isa_irq_pending(void) +{ + return (0); +} |