/* $NetBSD: gvpio.c,v 1.11 2002/09/27 20:30:04 thorpej Exp $ */ /* * Copyright (c) 1997 Ignatios Souvatzis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Ignatios Souvatzis * for the NetBSD Project. * 4. 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. */ #include __KERNEL_RCSID(0, "$NetBSD: gvpio.c,v 1.11 2002/09/27 20:30:04 thorpej Exp $"); /* * GVP I/O Extender */ #include #include #include #include #include #include #include #include #include #include #include #include #include struct gvpio_softc { struct device sc_dev; struct bus_space_tag sc_bst; caddr_t sc_cntr; LIST_HEAD(, gvpcom_int_hdl) sc_comhdls; struct isr sc_comisr; }; int gvpiomatch(struct device *, struct cfdata *, void *); void gvpioattach(struct device *, struct device *, void *); int gvpioprint(void *auxp, const char *); int gvp_com_intr(void *); void gvp_com_intr_establish(struct device *, struct gvpcom_int_hdl *); const struct cfattach gvpio_ca = { sizeof(struct gvpio_softc), gvpiomatch, gvpioattach }; int gvpiomatch(struct device *parent, struct cfdata *cfp, void *auxp) { struct gvpbus_args *gap; gap = auxp; if (gap->flags & GVP_IO) return (1); return (0); } struct gvpio_devs { char *name; int off; int arg; int ipl; } gvpiodevs[] = { { "com", 0x0b0, 115200 * 16 * 4, 6 }, { "com", 0x130, 115200 * 16 * 4, 6 }, { "lpt", 0x1b0, 0, 2 }, { 0 } }; void gvpioattach(struct device *parent, struct device *self, void *auxp) { struct gvpio_softc *giosc; struct gvpio_devs *giosd; struct gvpbus_args *gap; struct supio_attach_args supa; volatile caddr_t gbase; u_int16_t needpsl; giosc = (struct gvpio_softc *)self; gap = auxp; if (parent) printf("\n"); gbase = gap->zargs.va; giosc->sc_cntr = &gbase[0x41]; giosc->sc_bst.base = (u_long)gbase + 1; giosc->sc_bst.absm = &amiga_bus_stride_2; LIST_INIT(&giosc->sc_comhdls); giosd = gvpiodevs; supa.supio_iot = &giosc->sc_bst; gbase[0x041] = 0; gbase[0x161 + 1*2] = 0; gbase[0x261 + 1*2] = 0; gbase[0x361 + 2*2] = 0; gbase[0x461] = 0xd0; while (giosd->name) { supa.supio_name = giosd->name; supa.supio_iobase = giosd->off; supa.supio_arg = giosd->arg; supa.supio_ipl = giosd->ipl; config_found(self, &supa, gvpioprint); /* XXX */ ++giosd; } if (giosc->sc_comhdls.lh_first) { /* XXX this should be really in the interupt stuff */ needpsl = PSL_S|PSL_IPL6; if (amiga_serialspl < needpsl) { printf("%s: raising amiga_serialspl from 0x%x to 0x%x\n", giosc->sc_dev.dv_xname, amiga_serialspl, needpsl); amiga_serialspl = needpsl; } giosc->sc_comisr.isr_intr = gvp_com_intr; giosc->sc_comisr.isr_arg = giosc; giosc->sc_comisr.isr_ipl = 6; add_isr(&giosc->sc_comisr); } gbase[0x041] = 0x08; } int gvpioprint(void *auxp, const char *pnp) { struct supio_attach_args *supa; supa = auxp; if (pnp == NULL) return(QUIET); printf("%s at %s port 0x%02x ipl %d", supa->supio_name, pnp, supa->supio_iobase, supa->supio_ipl); return(UNCONF); } void gvp_com_intr_establish(struct device *self, struct gvpcom_int_hdl *p) { struct gvpio_softc *sc; sc = (struct gvpio_softc *)self; LIST_INSERT_HEAD(&sc->sc_comhdls, p, next); } int gvp_com_intr(void *p) { struct gvpio_softc *sc; struct gvpcom_int_hdl *np; volatile caddr_t cntr; sc = (struct gvpio_softc *)p; cntr = sc->sc_cntr; if (!(*cntr & 0x2)) return (0); *cntr &= ~0xa; for (np = sc->sc_comhdls.lh_first; np != NULL; np = np->next.le_next) { (*np->f)(np->p); } *cntr |= 0x8; return (1); }