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