pcc.c revision 1.3 1 1.3 chuck /* $Id: pcc.c,v 1.3 1996/04/26 19:00:06 chuck 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.3 chuck int pccmatch __P((struct device *, void *, void *));
70 1.3 chuck int pccprint __P((void *, 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.1 chuck pccmatch(parent, vcf, args)
104 1.1 chuck struct device *parent;
105 1.1 chuck void *vcf, *args;
106 1.1 chuck {
107 1.3 chuck char *ma_name = args;
108 1.3 chuck
109 1.3 chuck /* Only attach one PCC. */
110 1.3 chuck if (sys_pcc)
111 1.3 chuck return (0);
112 1.1 chuck
113 1.3 chuck return (strcmp(ma_name, pcc_cd.cd_name) == 0);
114 1.1 chuck }
115 1.1 chuck
116 1.1 chuck void
117 1.1 chuck pccattach(parent, self, args)
118 1.1 chuck struct device *parent, *self;
119 1.1 chuck void *args;
120 1.1 chuck {
121 1.1 chuck struct pccsoftc *pccsc;
122 1.3 chuck struct pcc_attach_args npa;
123 1.3 chuck caddr_t kva;
124 1.3 chuck int i, error;
125 1.1 chuck
126 1.1 chuck if (sys_pcc)
127 1.3 chuck panic("pccattach: pcc already attached!");
128 1.1 chuck
129 1.3 chuck sys_pcc = (struct pcc *)PCC_VADDR(PCC_REG_OFF);
130 1.1 chuck
131 1.1 chuck /*
132 1.3 chuck * link into softc and set up interrupt vector base,
133 1.3 chuck * and initialize the chip.
134 1.1 chuck */
135 1.1 chuck pccsc = (struct pccsoftc *) self;
136 1.3 chuck pccsc->sc_pcc = sys_pcc;
137 1.1 chuck pccsc->sc_pcc->int_vectr = PCC_VECBASE;
138 1.1 chuck
139 1.3 chuck printf(": Peripheral Channel Controller, "
140 1.3 chuck "rev %d, vecbase 0x%x\n", pccsc->sc_pcc->pcc_rev,
141 1.1 chuck pccsc->sc_pcc->int_vectr);
142 1.3 chuck
143 1.3 chuck /* Hook up interrupt handler for abort button. */
144 1.3 chuck pccintr_establish(PCCV_ABORT, pccintr, 7, NULL);
145 1.3 chuck
146 1.3 chuck /*
147 1.3 chuck * Now that the interrupt handler has been established,
148 1.3 chuck * enable the ABORT switch interrupt.
149 1.3 chuck */
150 1.3 chuck pccsc->sc_pcc->abrt_int = PCC_ABORT_IEN | PCC_ABORT_ACK;
151 1.3 chuck
152 1.3 chuck /* Make sure the global interrupt line is hot. */
153 1.3 chuck pccsc->sc_pcc->gen_cr |= PCC_GENCR_IEN;
154 1.3 chuck
155 1.3 chuck /*
156 1.3 chuck * Attach configured children.
157 1.3 chuck */
158 1.3 chuck for (i = 0; pcc_devices[i].pcc_name != NULL; ++i) {
159 1.3 chuck /*
160 1.3 chuck * Note that IPL is filled in by match function.
161 1.3 chuck */
162 1.3 chuck npa.pa_name = pcc_devices[i].pcc_name;
163 1.3 chuck npa.pa_offset = pcc_devices[i].pcc_offset;
164 1.3 chuck npa.pa_ipl = -1;
165 1.3 chuck
166 1.3 chuck /* Check for hardware. (XXX is this really necessary?) */
167 1.3 chuck kva = PCC_VADDR(npa.pa_offset);
168 1.3 chuck /* XXX should change interface to badaddr() */
169 1.3 chuck switch (pcc_devices[i].pcc_bytes) {
170 1.3 chuck case 1:
171 1.3 chuck error = badbaddr(kva);
172 1.3 chuck break;
173 1.3 chuck
174 1.3 chuck case 2:
175 1.3 chuck error = badaddr(kva);
176 1.3 chuck break;
177 1.3 chuck
178 1.3 chuck default:
179 1.3 chuck panic("pccattach: bad probe size");
180 1.3 chuck }
181 1.3 chuck if (error) {
182 1.3 chuck /*
183 1.3 chuck * Hardware not present.
184 1.3 chuck */
185 1.3 chuck continue;
186 1.3 chuck }
187 1.3 chuck
188 1.3 chuck /* Attach the device if configured. */
189 1.3 chuck (void)config_found(self, &npa, pccprint);
190 1.3 chuck }
191 1.1 chuck }
192 1.1 chuck
193 1.1 chuck int
194 1.3 chuck pccprint(aux, cp)
195 1.3 chuck void *aux;
196 1.3 chuck char *cp;
197 1.1 chuck {
198 1.3 chuck struct pcc_attach_args *pa = aux;
199 1.3 chuck
200 1.3 chuck if (cp)
201 1.3 chuck printf("%s at %s", pa->pa_name, cp);
202 1.3 chuck
203 1.3 chuck printf(" offset 0x%lx", pa->pa_offset);
204 1.3 chuck if (pa->pa_ipl != -1)
205 1.3 chuck printf(" ipl %d", pa->pa_ipl);
206 1.1 chuck
207 1.3 chuck return (UNCONF);
208 1.1 chuck }
209 1.1 chuck
210 1.1 chuck /*
211 1.1 chuck * pccintr_establish: establish pcc interrupt
212 1.1 chuck */
213 1.3 chuck void
214 1.3 chuck pccintr_establish(pccvec, hand, lvl, arg)
215 1.3 chuck int pccvec;
216 1.3 chuck int (*hand) __P((void *)), lvl;
217 1.1 chuck void *arg;
218 1.1 chuck {
219 1.3 chuck
220 1.3 chuck if ((pccvec < 0) || (pccvec >= PCC_NVEC)) {
221 1.3 chuck printf("pcc: illegal vector offset: 0x%x\n", pccvec);
222 1.1 chuck panic("pccintr_establish");
223 1.1 chuck }
224 1.1 chuck
225 1.3 chuck if ((lvl < 1) || (lvl > 7)) {
226 1.3 chuck printf("pcc: illegal interrupt level: %d\n", lvl);
227 1.1 chuck panic("pccintr_establish");
228 1.1 chuck }
229 1.1 chuck
230 1.3 chuck isrlink_vectored(hand, arg, lvl, pccvec + PCC_VECBASE);
231 1.3 chuck }
232 1.3 chuck
233 1.3 chuck void
234 1.3 chuck pccintr_disestablish(pccvec)
235 1.3 chuck int pccvec;
236 1.3 chuck {
237 1.3 chuck
238 1.3 chuck if ((pccvec < 0) || (pccvec >= PCC_NVEC)) {
239 1.3 chuck printf("pcc: illegal vector offset: 0x%x\n", pccvec);
240 1.3 chuck panic("pccintr_establish");
241 1.3 chuck }
242 1.3 chuck
243 1.3 chuck isrunlink_vectored(pccvec + PCC_VECBASE);
244 1.3 chuck }
245 1.3 chuck
246 1.3 chuck /*
247 1.3 chuck * Handle NMI from abort switch.
248 1.3 chuck */
249 1.3 chuck int
250 1.3 chuck pccintr(frame)
251 1.3 chuck void *frame;
252 1.3 chuck {
253 1.3 chuck
254 1.3 chuck /* XXX wait until button pops out */
255 1.3 chuck sys_pcc->abrt_int = PCC_ABORT_IEN | PCC_ABORT_ACK;
256 1.3 chuck nmihand((struct frame *)frame);
257 1.3 chuck return (1);
258 1.1 chuck }
259