xref: /netbsd/sys/arch/mac68k/mac68k/psc.c (revision bf9ec67e)
1 /*	$NetBSD: psc.c,v 1.6 1999/06/28 01:41:13 briggs Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 David Huang <khym@bga.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 /*
29  * This handles registration/unregistration of PSC (Peripheral
30  * Subsystem Controller) interrupts. The PSC is used only on the
31  * Centris/Quadra 660av and the Quadra 840av.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 
37 #include <machine/bus.h>
38 #include <machine/cpu.h>
39 #include <machine/psc.h>
40 
41 static void	psc_kill_dma __P((void));
42 int		psc_lev3_intr __P((void *));
43 static void	psc_lev3_noint __P((void *));
44 int		psc_lev4_intr __P((void *));
45 static int	psc_lev4_noint __P((void *));
46 int		psc_lev5_intr __P((void *));
47 static void	psc_lev5_noint __P((void *));
48 int		psc_lev6_intr __P((void *));
49 static void	psc_lev6_noint __P((void *));
50 
51 void	(*psc3_ihandler) __P((void *)) = psc_lev3_noint;
52 void	*psc3_iarg;
53 
54 int (*psc4_itab[4]) __P((void *)) = {
55 	psc_lev4_noint, /* 0 */
56 	psc_lev4_noint, /* 1 */
57 	psc_lev4_noint, /* 2 */
58 	psc_lev4_noint  /* 3 */
59 };
60 
61 void *psc4_iarg[4] = {
62 	(void *)0, (void *)1, (void *)2, (void *)3
63 };
64 
65 void (*psc5_itab[2]) __P((void *)) = {
66 	psc_lev5_noint, /* 0 */
67 	psc_lev5_noint  /* 1 */
68 };
69 
70 void *psc5_iarg[2] = {
71 	(void *)0, (void *)1
72 };
73 
74 void (*psc6_itab[3]) __P((void *)) = {
75 	psc_lev6_noint, /* 0 */
76 	psc_lev6_noint, /* 1 */
77 	psc_lev6_noint  /* 2 */
78 };
79 
80 void *psc6_iarg[3] = {
81 	(void *)0, (void *)1, (void *)2
82 };
83 
84 /*
85  * Make excessively sure that all PSC DMA is shut down.
86  */
87 void
88 psc_kill_dma()
89 {
90 	int	i;
91 
92 	for (i = 0; i < 9; i++) {
93 		psc_reg2(PSC_CTLBASE + (i << 4)) = 0x8800;
94 		psc_reg2(PSC_CTLBASE + (i << 4)) = 0x1000;
95 		psc_reg2(PSC_CMDBASE + (i << 5)) = 0x1100;
96 		psc_reg2(PSC_CMDBASE + (i << 5) + PSC_SET1) = 0x1100;
97 	}
98 }
99 
100 /*
101  * Setup the interrupt vectors and disable most of the PSC interrupts
102  */
103 void
104 psc_init()
105 {
106 	int	s, i;
107 
108 	/*
109 	 * Only Quadra AVs have a PSC.
110 	 */
111 	if (current_mac_model->class == MACH_CLASSAV) {
112 		s = splhigh();
113 		psc_kill_dma();
114 		intr_establish(psc_lev3_intr, NULL, 3);
115 		intr_establish(psc_lev4_intr, NULL, 4);
116 		intr_establish(psc_lev5_intr, NULL, 5);
117 		intr_establish(psc_lev6_intr, NULL, 6);
118 		for (i = 3; i < 7; i++) {
119 			/* Clear any flags */
120 			psc_reg1(PSC_ISR_BASE + 0x10 * i) = 0x0F;
121 			/* Clear any interrupt enable */
122 			psc_reg1(PSC_IER_BASE + 0x10 * i) = 0x0F;
123 		}
124 		psc_reg1(PSC_LEV4_IER) = 0x86; /* enable SCC */
125 		splx(s);
126 	}
127 }
128 
129 int
130 add_psc_lev3_intr(handler, arg)
131 	void (*handler)(void *);
132 	void *arg;
133 {
134 	int s;
135 
136 	s = splhigh();
137 
138 	psc3_ihandler = handler;
139 	psc3_iarg = arg;
140 
141 	splx(s);
142 
143 	return 1;
144 }
145 
146 int
147 remove_psc_lev3_intr()
148 {
149 	return add_psc_lev3_intr(psc_lev3_noint, (void *)0);
150 }
151 
152 int
153 psc_lev3_intr(arg)
154 	void *arg;
155 {
156 	u_int8_t intbits;
157 
158 	while ((intbits = psc_reg1(PSC_LEV3_ISR)) != psc_reg1(PSC_LEV3_ISR))
159 		;
160 	intbits &= 0x1 & psc_reg1(PSC_LEV3_IER);
161 
162 	if (intbits)
163 		psc3_ihandler(psc3_iarg);
164 
165 	return 0;
166 }
167 
168 static void
169 psc_lev3_noint(arg)
170 	void *arg;
171 {
172 	printf("psc_lev3_noint\n");
173 }
174 
175 int
176 psc_lev4_intr(arg)
177 	void *arg;
178 {
179 	u_int8_t intbits, bitnum;
180 	u_int mask;
181 
182 	while ((intbits = psc_reg1(PSC_LEV4_ISR)) != psc_reg1(PSC_LEV4_ISR))
183 		;
184 	intbits &= 0xf & psc_reg1(PSC_LEV4_IER);
185 
186 	mask = 1;
187 	bitnum = 0;
188 	do {
189 		if (intbits & mask)
190 			psc4_itab[bitnum](psc4_iarg[bitnum]);
191 		mask <<= 1;
192 	} while (intbits >= mask && ++bitnum);
193 
194 	return 0;
195 }
196 
197 int
198 add_psc_lev4_intr(dev, handler, arg)
199 	int dev;
200 	int (*handler)(void *);
201 	void *arg;
202 {
203 	int s;
204 
205 	if ((dev < 0) || (dev > 3))
206 		return 0;
207 
208 	s = splhigh();
209 
210 	psc4_itab[dev] = handler;
211 	psc4_iarg[dev] = arg;
212 
213 	splx(s);
214 
215 	return 1;
216 }
217 
218 int
219 remove_psc_lev4_intr(dev)
220 	int dev;
221 {
222 	return add_psc_lev4_intr(dev, psc_lev4_noint, (void *)dev);
223 }
224 
225 int
226 psc_lev4_noint(arg)
227 	void *arg;
228 {
229 	printf("psc_lev4_noint: device %d\n", (int)arg);
230 	return 0;
231 }
232 
233 int
234 psc_lev5_intr(arg)
235 	void *arg;
236 {
237 	u_int8_t intbits, bitnum;
238 	u_int mask;
239 
240 	while ((intbits = psc_reg1(PSC_LEV5_ISR)) != psc_reg1(PSC_LEV5_ISR))
241 		;
242 	intbits &= 0x3 & psc_reg1(PSC_LEV5_IER);
243 
244 	mask = 1;
245 	bitnum = 0;
246 	do {
247 		if (intbits & mask)
248 			psc5_itab[bitnum](psc5_iarg[bitnum]);
249 		mask <<= 1;
250 	} while (intbits >= mask && ++bitnum);
251 
252 	return 0;
253 }
254 
255 int
256 add_psc_lev5_intr(dev, handler, arg)
257 	int dev;
258 	void (*handler)(void *);
259 	void *arg;
260 {
261 	int s;
262 
263 	if ((dev < 0) || (dev > 1))
264 		return 0;
265 
266 	s = splhigh();
267 
268 	psc5_itab[dev] = handler;
269 	psc5_iarg[dev] = arg;
270 
271 	splx(s);
272 
273 	return 1;
274 }
275 
276 int
277 remove_psc_lev5_intr(dev)
278 	int dev;
279 {
280 	return add_psc_lev5_intr(dev, psc_lev5_noint, (void *)dev);
281 }
282 
283 void
284 psc_lev5_noint(arg)
285 	void *arg;
286 {
287 	printf("psc_lev5_noint: device %d\n", (int)arg);
288 }
289 
290 int
291 psc_lev6_intr(arg)
292 	void *arg;
293 {
294 	u_int8_t intbits, bitnum;
295 	u_int mask;
296 
297 	while ((intbits = psc_reg1(PSC_LEV6_ISR)) != psc_reg1(PSC_LEV6_ISR))
298 		;
299 	intbits &= 0x7 & psc_reg1(PSC_LEV6_IER);
300 
301 	mask = 1;
302 	bitnum = 0;
303 	do {
304 		if (intbits & mask)
305 			psc6_itab[bitnum](psc6_iarg[bitnum]);
306 		mask <<= 1;
307 	} while (intbits >= mask && ++bitnum);
308 
309 	return 0;
310 }
311 
312 int
313 add_psc_lev6_intr(dev, handler, arg)
314 	int dev;
315 	void (*handler)(void *);
316 	void *arg;
317 {
318 	int s;
319 
320 	if ((dev < 0) || (dev > 2))
321 		return 0;
322 
323 	s = splhigh();
324 
325 	psc6_itab[dev] = handler;
326 	psc6_iarg[dev] = arg;
327 
328 	splx(s);
329 
330 	return 1;
331 }
332 
333 int
334 remove_psc_lev6_intr(dev)
335 	int dev;
336 {
337 	return add_psc_lev6_intr(dev, psc_lev6_noint, (void *)dev);
338 }
339 
340 void
341 psc_lev6_noint(arg)
342 	void *arg;
343 {
344 	printf("psc_lev6_noint: device %d\n", (int)arg);
345 }
346