pcc.c revision 1.10 1 /* $NetBSD: pcc.c,v 1.10 1997/10/05 18:17:36 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1995 Charles D. Cranor
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by Charles D. Cranor.
54 * 4. The name of the author may not be used to endorse or promote products
55 * derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69 /*
70 * peripheral channel controller
71 */
72
73 #include <sys/param.h>
74 #include <sys/conf.h>
75 #include <sys/ioctl.h>
76 #include <sys/proc.h>
77 #include <sys/user.h>
78 #include <sys/tty.h>
79 #include <sys/uio.h>
80 #include <sys/callout.h>
81 #include <sys/systm.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84 #include <sys/fcntl.h>
85 #include <sys/device.h>
86 #include <machine/cpu.h>
87 #include <dev/cons.h>
88
89 #include <mvme68k/mvme68k/isr.h>
90
91 #include <mvme68k/dev/pccreg.h>
92 #include <mvme68k/dev/pccvar.h>
93
94 /*
95 * Autoconfiguration stuff.
96 */
97
98 struct pccsoftc {
99 struct device sc_dev;
100 struct pcc *sc_pcc;
101 };
102
103 void pccattach __P((struct device *, struct device *, void *));
104 int pccmatch __P((struct device *, struct cfdata *, void *));
105 int pccprint __P((void *, const char *));
106
107 struct cfattach pcc_ca = {
108 sizeof(struct pccsoftc), pccmatch, pccattach
109 };
110
111 struct cfdriver pcc_cd = {
112 NULL, "pcc", DV_DULL, 0
113 };
114
115 int pccintr __P((void *));
116
117 /*
118 * globals
119 */
120
121 struct pcc *sys_pcc = NULL;
122
123 /*
124 * Devices that live on the PCC, attached in this order.
125 */
126 struct pcc_device pcc_devices[] = {
127 { "clock", PCC_CLOCK_OFF, 1 },
128 { "zsc", PCC_ZS0_OFF, 1 },
129 { "zsc", PCC_ZS1_OFF, 1 },
130 { "le", PCC_LE_OFF, 2 },
131 { "wdsc", PCC_WDSC_OFF, 1 },
132 { "lpt", PCC_LPT_OFF, 1 },
133 { "vmechip", PCC_VME_OFF, 2 },
134 { NULL, 0, 0 },
135 };
136
137 int
138 pccmatch(parent, cf, args)
139 struct device *parent;
140 struct cfdata *cf;
141 void *args;
142 {
143 char *ma_name = args;
144
145 /* Only attach one PCC. */
146 if (sys_pcc)
147 return (0);
148
149 return (strcmp(ma_name, pcc_cd.cd_name) == 0);
150 }
151
152 void
153 pccattach(parent, self, args)
154 struct device *parent, *self;
155 void *args;
156 {
157 struct pccsoftc *pccsc;
158 struct pcc_attach_args npa;
159 caddr_t kva;
160 int i;
161
162 if (sys_pcc)
163 panic("pccattach: pcc already attached!");
164
165 sys_pcc = (struct pcc *)PCC_VADDR(PCC_REG_OFF);
166
167 /*
168 * link into softc and set up interrupt vector base,
169 * and initialize the chip.
170 */
171 pccsc = (struct pccsoftc *) self;
172 pccsc->sc_pcc = sys_pcc;
173 pccsc->sc_pcc->int_vectr = PCC_VECBASE;
174
175 printf(": Peripheral Channel Controller, "
176 "rev %d, vecbase 0x%x\n", pccsc->sc_pcc->pcc_rev,
177 pccsc->sc_pcc->int_vectr);
178
179 /* Hook up interrupt handler for abort button. */
180 pccintr_establish(PCCV_ABORT, pccintr, 7, NULL);
181
182 /*
183 * Now that the interrupt handler has been established,
184 * enable the ABORT switch interrupt.
185 */
186 pccsc->sc_pcc->abrt_int = PCC_ABORT_IEN | PCC_ABORT_ACK;
187
188 /* Make sure the global interrupt line is hot. */
189 pccsc->sc_pcc->gen_cr |= PCC_GENCR_IEN;
190
191 /*
192 * Attach configured children.
193 */
194 for (i = 0; pcc_devices[i].pcc_name != NULL; ++i) {
195 /*
196 * Note that IPL is filled in by match function.
197 */
198 npa.pa_name = pcc_devices[i].pcc_name;
199 npa.pa_offset = pcc_devices[i].pcc_offset;
200 npa.pa_ipl = -1;
201
202 /* Check for hardware. (XXX is this really necessary?) */
203 kva = PCC_VADDR(npa.pa_offset);
204 if (badaddr(kva, pcc_devices[i].pcc_bytes)) {
205 /*
206 * Hardware not present.
207 */
208 continue;
209 }
210
211 /* Attach the device if configured. */
212 (void)config_found(self, &npa, pccprint);
213 }
214 }
215
216 int
217 pccprint(aux, cp)
218 void *aux;
219 const char *cp;
220 {
221 struct pcc_attach_args *pa = aux;
222
223 if (cp)
224 printf("%s at %s", pa->pa_name, cp);
225
226 printf(" offset 0x%lx", pa->pa_offset);
227 if (pa->pa_ipl != -1)
228 printf(" ipl %d", pa->pa_ipl);
229
230 return (UNCONF);
231 }
232
233 /*
234 * pccintr_establish: establish pcc interrupt
235 */
236 void
237 pccintr_establish(pccvec, hand, lvl, arg)
238 int pccvec;
239 int (*hand) __P((void *)), lvl;
240 void *arg;
241 {
242
243 if ((pccvec < 0) || (pccvec >= PCC_NVEC)) {
244 printf("pcc: illegal vector offset: 0x%x\n", pccvec);
245 panic("pccintr_establish");
246 }
247
248 if ((lvl < 1) || (lvl > 7)) {
249 printf("pcc: illegal interrupt level: %d\n", lvl);
250 panic("pccintr_establish");
251 }
252
253 isrlink_vectored(hand, arg, lvl, pccvec + PCC_VECBASE);
254 }
255
256 void
257 pccintr_disestablish(pccvec)
258 int pccvec;
259 {
260
261 if ((pccvec < 0) || (pccvec >= PCC_NVEC)) {
262 printf("pcc: illegal vector offset: 0x%x\n", pccvec);
263 panic("pccintr_establish");
264 }
265
266 isrunlink_vectored(pccvec + PCC_VECBASE);
267 }
268
269 /*
270 * Handle NMI from abort switch.
271 */
272 int
273 pccintr(frame)
274 void *frame;
275 {
276
277 /* XXX wait until button pops out */
278 sys_pcc->abrt_int = PCC_ABORT_IEN | PCC_ABORT_ACK;
279 nmihand((struct frame *)frame);
280 return (1);
281 }
282