pcc.c revision 1.2 1 /* $Id: pcc.c,v 1.2 1996/03/17 01:35:03 thorpej Exp $ */
2
3 /*
4 *
5 * Copyright (c) 1995 Charles D. Cranor
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * peripheral channel controller
36 */
37
38 #include <sys/param.h>
39 #include <sys/conf.h>
40 #include <sys/ioctl.h>
41 #include <sys/proc.h>
42 #include <sys/user.h>
43 #include <sys/tty.h>
44 #include <sys/uio.h>
45 #include <sys/callout.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/syslog.h>
49 #include <sys/fcntl.h>
50 #include <sys/device.h>
51 #include <machine/cpu.h>
52 #include <dev/cons.h>
53 #include <mvme68k/mvme68k/isr.h>
54 #include <mvme68k/dev/iio.h>
55 #include <mvme68k/dev/pccreg.h>
56
57 /*
58 * Autoconfiguration stuff.
59 */
60
61 struct pccsoftc {
62 struct device sc_dev;
63 struct pcc *sc_pcc;
64 };
65
66
67 void pccattach __P((struct device *, struct device *, void *));
68 int pccmatch __P((struct device *, void *, void *));
69
70 struct cfattach pcc_ca = {
71 sizeof(struct pccsoftc), pccmatch, pccattach
72 };
73
74 struct cfdriver pcc_cd = {
75 NULL, "pcc", DV_DULL, 0
76 };
77
78 /*
79 * globals
80 */
81
82 struct pcc *sys_pcc = NULL;
83
84 struct {
85 int (*pcc_fn)();
86 void *arg;
87 int lvl;
88 } pcc_vecs[PCC_NVEC];
89
90 int
91 pccmatch(parent, vcf, args)
92 struct device *parent;
93 void *vcf, *args;
94 {
95 struct cfdata *cf = vcf;
96
97 return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
98 }
99
100 void
101 pccattach(parent, self, args)
102 struct device *parent, *self;
103 void *args;
104 {
105 struct pccsoftc *pccsc;
106
107 if (sys_pcc)
108 panic("pcc already attached!");
109
110 iio_print(self->dv_cfdata);
111
112 /*
113 * link into softc and set up interrupt vector base
114 */
115 pccsc = (struct pccsoftc *) self;
116 sys_pcc = pccsc->sc_pcc = (struct pcc *)IIO_CFLOC_ADDR(self->dv_cfdata);
117 pccsc->sc_pcc->int_vectr = PCC_VECBASE;
118 bzero(pcc_vecs, sizeof(pcc_vecs));
119
120 printf(" rev %d intbvr 0x%x\n", pccsc->sc_pcc->pcc_rev,
121 pccsc->sc_pcc->int_vectr);
122 }
123
124
125 /*
126 * pccintr: called from locore with the PC and evec from the trap frame.
127 */
128 int
129 pccintr(pc, evec, frame)
130 int pc;
131 int evec;
132 void *frame;
133 {
134 int vec = (evec & 0xfff) >> 2; /* XXX should be m68k macro? */
135 extern u_long intrcnt[]; /* XXX from locore */
136
137 vec = vec & 0xf; /* XXX mask out */
138 if (vec >= PCC_NVEC || pcc_vecs[vec].pcc_fn == NULL)
139 return(straytrap(pc, evec));
140
141 cnt.v_intr++;
142 intrcnt[pcc_vecs[vec].lvl]++;
143
144 /* arg override? only timer1 gets access to frame */
145 if (vec != PCCV_TIMER1)
146 frame = pcc_vecs[vec].arg;
147 return((*pcc_vecs[vec].pcc_fn)(frame));
148 }
149
150
151 /*
152 * pccintr_establish: establish pcc interrupt
153 */
154 int
155 pccintr_establish(vec, hand, lvl, arg)
156 u_long vec;
157 int (*hand)(), lvl;
158 void *arg;
159 {
160 if (vec >= PCC_NVEC) {
161 printf("pcc: illegal vector: 0x%x\n", vec);
162 panic("pccintr_establish");
163 }
164
165 if (pcc_vecs[vec].pcc_fn) {
166 printf("pcc: vector 0x%x in use: (0x%x,0x%x) (0x%x,0x%x)\n",
167 hand, arg, pcc_vecs[vec].pcc_fn, pcc_vecs[vec].arg);
168 panic("pccintr_establish");
169 }
170
171 pcc_vecs[vec].pcc_fn = hand;
172 pcc_vecs[vec].lvl = lvl;
173 pcc_vecs[vec].arg = arg;
174 }
175