diff options
author | Steve Murphree <smurph@cvs.openbsd.org> | 2001-12-13 08:59:39 +0000 |
---|---|---|
committer | Steve Murphree <smurph@cvs.openbsd.org> | 2001-12-13 08:59:39 +0000 |
commit | 435d459b77c471f2bcfe110600897fadc120da92 (patch) | |
tree | 390ee38c1d909cc6b795fa041c70d763684b32a5 /sys/arch/mvme88k/dev/bussw.c | |
parent | 473b535f76f86533ee5e407fe116de57f486b4ab (diff) |
Support for MVME917 complete.
Diffstat (limited to 'sys/arch/mvme88k/dev/bussw.c')
-rw-r--r-- | sys/arch/mvme88k/dev/bussw.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/sys/arch/mvme88k/dev/bussw.c b/sys/arch/mvme88k/dev/bussw.c new file mode 100644 index 00000000000..369382d811f --- /dev/null +++ b/sys/arch/mvme88k/dev/bussw.c @@ -0,0 +1,196 @@ +/* $OpenBSD: bussw.c,v 1.1 2001/12/13 08:59:38 smurph Exp $ */ + +/* + * Copyright (c) 1999 Steve Murphree, Jr. + * + * 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 under OpenBSD by + * Theo de Raadt for Willowglen Singapore. + * 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 <sys/param.h> +#include <sys/kernel.h> +#include <sys/ioctl.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <machine/psl.h> +#include <machine/autoconf.h> +#include <machine/bugio.h> +#include <machine/cpu.h> +#include <machine/mioctl.h> +#include <machine/vmparam.h> + +#include <mvme88k/dev/busswreg.h> +#include <mvme88k/dev/busswfunc.h> + +struct bussw_softc { + struct device sc_dev; + void *sc_paddr; + void *sc_vaddr; + int sc_len; + struct intrhand sc_abih; /* `abort' switch */ + struct bussw_reg *sc_bussw; +}; + +void bussw_attach __P((struct device *, struct device *, void *)); +int bussw_match __P((struct device *, void *, void *)); + +struct cfattach bussw_ca = { + sizeof(struct bussw_softc), bussw_match, bussw_attach +}; + +struct cfdriver bussw_cd = { + NULL, "bussw", DV_DULL, 0 +}; + +int bussw_print __P((void *args, const char *bus)); +int bussw_scan __P((struct device *parent, void *child, void *args)); +int busswabort __P((void *)); + +int +bussw_match(parent, vcf, args) +struct device *parent; +void *vcf, *args; +{ + struct confargs *ca = args; + struct bussw_reg *bussw; + /* Don't match if wrong cpu */ + if (brdtyp != BRD_197) + return (0); /* The only one... */ + + bussw = (struct bussw_reg *)(IIOV(ca->ca_paddr)); + if (badvaddr((vm_offset_t)bussw, 4)) { + printf("==> busswitch: failed address check.\n"); + return (0); + } + return (1); +} + +void +bussw_attach(parent, self, args) +struct device *parent, *self; +void *args; +{ + struct confargs *ca = args; + struct bussw_softc *sc = (struct bussw_softc *)self; + struct bussw_reg *bs; + + sc->sc_vaddr = sc->sc_paddr = ca->ca_paddr; + bs = sc->sc_bussw = (struct bussw_reg *)sc->sc_vaddr; + bs->bs_intr2 |= BS_VECBASE; + bs->bs_gcsr |= BS_GCSR_XIPL; + /* + * pseudo driver, abort interrupt handler + */ + sc->sc_abih.ih_fn = busswabort; + sc->sc_abih.ih_arg = 0; + sc->sc_abih.ih_wantframe = 1; + sc->sc_abih.ih_ipl = IPL_NMI; /* level 8!! */ + busswintr_establish(BS_ABORTIRQ, &sc->sc_abih); + bs->bs_intr1 |= BS_INTR1_ABORT_IEN; + + printf(": rev %d\n", BS_CHIPREV(bs)); + config_search(bussw_scan, self, args); +} + +int +bussw_print(args, bus) +void *args; +const char *bus; +{ + struct confargs *ca = args; + + if (ca->ca_offset != -1) + printf(" offset 0x%x", ca->ca_offset); + if (ca->ca_ipl > 0) + printf(" ipl %d", ca->ca_ipl); + return (UNCONF); +} + +int +bussw_scan(parent, child, args) +struct device *parent; +void *child, *args; +{ + struct cfdata *cf = child; + struct bussw_softc *sc = (struct bussw_softc *)parent; + struct confargs oca; + + if (parent->dv_cfdata->cf_driver->cd_indirect) { + printf(" indirect devices not supported\n"); + return 0; + } + + bzero(&oca, sizeof oca); + oca.ca_offset = cf->cf_loc[0]; + oca.ca_ipl = cf->cf_loc[1]; + if (((int)oca.ca_offset != -1) && ISIIOVA(sc->sc_vaddr + oca.ca_offset)) { + oca.ca_vaddr = sc->sc_vaddr + oca.ca_offset; + oca.ca_paddr = sc->sc_paddr + oca.ca_offset; + } else { + oca.ca_vaddr = (void *)-1; + oca.ca_paddr = (void *)-1; + } + oca.ca_bustype = BUS_BUSSWITCH; + oca.ca_master = (void *)sc->sc_bussw; + oca.ca_name = cf->cf_driver->cd_name; + if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0) + return (0); + config_attach(parent, cf, &oca, bussw_print); + return (1); +} + +int +busswintr_establish(vec, ih) + int vec; + struct intrhand *ih; +{ + if (vec >= BS_NVEC) { + printf("bussw: illegal vector: 0x%x\n", vec); + panic("busswintr_establish"); + } + return (intr_establish(BS_VECBASE+vec, ih)); +} + +int +busswabort(eframe) + void *eframe; +{ + struct frame *frame = eframe; + + struct bussw_softc *sc = (struct bussw_softc *)bussw_cd.cd_devs[0]; + struct bussw_reg *bs = sc->sc_bussw; + + if (bs->bs_intr1 & BS_INTR1_ABORT_INT) { + bs->bs_intr1 |= BS_INTR1_ABORT_ICLR; + nmihand(frame); + return 1; + } + return 0; +} + |