/* $Id: pcc.c,v 1.2 1996/03/17 01:35:03 thorpej Exp $ */ /* * * Copyright (c) 1995 Charles D. Cranor * 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 Charles D. Cranor. * 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. */ /* * peripheral channel controller */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Autoconfiguration stuff. */ struct pccsoftc { struct device sc_dev; struct pcc *sc_pcc; }; void pccattach __P((struct device *, struct device *, void *)); int pccmatch __P((struct device *, void *, void *)); struct cfattach pcc_ca = { sizeof(struct pccsoftc), pccmatch, pccattach }; struct cfdriver pcc_cd = { NULL, "pcc", DV_DULL, 0 }; /* * globals */ struct pcc *sys_pcc = NULL; struct { int (*pcc_fn)(); void *arg; int lvl; } pcc_vecs[PCC_NVEC]; int pccmatch(parent, vcf, args) struct device *parent; void *vcf, *args; { struct cfdata *cf = vcf; return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf)); } void pccattach(parent, self, args) struct device *parent, *self; void *args; { struct pccsoftc *pccsc; if (sys_pcc) panic("pcc already attached!"); iio_print(self->dv_cfdata); /* * link into softc and set up interrupt vector base */ pccsc = (struct pccsoftc *) self; sys_pcc = pccsc->sc_pcc = (struct pcc *)IIO_CFLOC_ADDR(self->dv_cfdata); pccsc->sc_pcc->int_vectr = PCC_VECBASE; bzero(pcc_vecs, sizeof(pcc_vecs)); printf(" rev %d intbvr 0x%x\n", pccsc->sc_pcc->pcc_rev, pccsc->sc_pcc->int_vectr); } /* * pccintr: called from locore with the PC and evec from the trap frame. */ int pccintr(pc, evec, frame) int pc; int evec; void *frame; { int vec = (evec & 0xfff) >> 2; /* XXX should be m68k macro? */ extern u_long intrcnt[]; /* XXX from locore */ vec = vec & 0xf; /* XXX mask out */ if (vec >= PCC_NVEC || pcc_vecs[vec].pcc_fn == NULL) return(straytrap(pc, evec)); cnt.v_intr++; intrcnt[pcc_vecs[vec].lvl]++; /* arg override? only timer1 gets access to frame */ if (vec != PCCV_TIMER1) frame = pcc_vecs[vec].arg; return((*pcc_vecs[vec].pcc_fn)(frame)); } /* * pccintr_establish: establish pcc interrupt */ int pccintr_establish(vec, hand, lvl, arg) u_long vec; int (*hand)(), lvl; void *arg; { if (vec >= PCC_NVEC) { printf("pcc: illegal vector: 0x%x\n", vec); panic("pccintr_establish"); } if (pcc_vecs[vec].pcc_fn) { printf("pcc: vector 0x%x in use: (0x%x,0x%x) (0x%x,0x%x)\n", hand, arg, pcc_vecs[vec].pcc_fn, pcc_vecs[vec].arg); panic("pccintr_establish"); } pcc_vecs[vec].pcc_fn = hand; pcc_vecs[vec].lvl = lvl; pcc_vecs[vec].arg = arg; }