xref: /netbsd-src/sys/arch/pmax/pmax/dec_3max.c (revision e691d98f971f4464abb0774514c0188372cde33f)
1 /* $NetBSD: dec_3max.c,v 1.56 2014/03/24 19:31:39 christos Exp $ */
2 
3 /*
4  * Copyright (c) 1998 Jonathan Stone.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Jonathan Stone for
17  *      the NetBSD Project.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1988 University of Utah.
35  * Copyright (c) 1992, 1993
36  *	The Regents of the University of California.  All rights reserved.
37  *
38  * This code is derived from software contributed to Berkeley by
39  * the Systems Programming Group of the University of Utah Computer
40  * Science Department, The Mach Operating System project at
41  * Carnegie-Mellon University and Ralph Campbell.
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. Neither the name of the University nor the names of its contributors
52  *    may be used to endorse or promote products derived from this software
53  *    without specific prior written permission.
54  *
55  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65  * SUCH DAMAGE.
66  *
67  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
68  */
69 
70 #define	__INTR_PRIVATE
71 
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: dec_3max.c,v 1.56 2014/03/24 19:31:39 christos Exp $");
74 
75 #include "dzkbd.h"
76 
77 #include <sys/param.h>
78 #include <sys/bus.h>
79 #include <sys/cpu.h>
80 #include <sys/device.h>
81 #include <sys/intr.h>
82 #include <sys/lwp.h>
83 #include <sys/systm.h>
84 
85 #include <mips/locore.h>
86 
87 #include <mips/mips/mips_mcclock.h>	/* mcclock CPUspeed estimation */
88 
89 #include <dev/tc/tcvar.h>		/* tc_addr_t */
90 
91 #include <pmax/sysconf.h>
92 
93 #include <pmax/pmax/machdep.h>
94 #include <pmax/pmax/kn02.h>
95 #include <pmax/pmax/memc.h>
96 
97 #include <dev/dec/dzreg.h>
98 #include <dev/dec/dzvar.h>
99 #include <dev/dec/dzkbdvar.h>
100 #include <pmax/pmax/cons.h>
101 #include "wsdisplay.h"
102 
103 void		dec_3max_init(void);		/* XXX */
104 static void	dec_3max_bus_reset(void);
105 
106 static void	dec_3max_cons_init(void);
107 static void	dec_3max_errintr(void);
108 static void	dec_3max_intr(uint32_t, vaddr_t, uint32_t);
109 static void	dec_3max_intr_establish(device_t, void *,
110 		    int, int (*)(void *), void *);
111 
112 
113 #define	kn02_wbflush()	wbflush()	/* XXX to be corrected XXX */
114 
115 static const struct ipl_sr_map dec_3max_ipl_sr_map = {
116     .sr_bits = {
117 	[IPL_NONE] = 0,
118 	[IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
119 	[IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
120 	[IPL_VM] = MIPS_SPL0,
121 	[IPL_SCHED] = MIPS_SPLHIGH,
122 	[IPL_DDB] = MIPS_SPLHIGH,
123 	[IPL_HIGH] = MIPS_SPLHIGH,
124     },
125 };
126 
127 void
dec_3max_init(void)128 dec_3max_init(void)
129 {
130 	uint32_t csr;
131 
132 	platform.iobus = "tcbus";
133 	platform.bus_reset = dec_3max_bus_reset;
134 	platform.cons_init = dec_3max_cons_init;
135 	platform.iointr = dec_3max_intr;
136 	platform.intr_establish = dec_3max_intr_establish;
137 	platform.memsize = memsize_bitmap;
138 	/* no high resolution timer available */
139 
140 	/* clear any memory errors */
141 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_ERRADR) = 0;
142 	kn02_wbflush();
143 
144 	ipl_sr_map = dec_3max_ipl_sr_map;
145 
146 	/* calibrate cpu_mhz value */
147 	mc_cpuspeed(MIPS_PHYS_TO_KSEG1(KN02_SYS_CLOCK), MIPS_INT_MASK_1);
148 
149 	/*
150 	 * Enable ECC memory correction, turn off LEDs, and
151 	 * disable all TURBOchannel interrupts.
152 	 */
153 	csr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR);
154 	csr &= ~(KN02_CSR_WRESERVED|KN02_CSR_IOINTEN|KN02_CSR_CORRECT|0xff);
155 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR) = csr;
156 	kn02_wbflush();
157 
158 	cpu_setmodel("DECstation 5000/200 (3MAX)");
159 }
160 
161 /*
162  * Initialize the memory system and I/O buses.
163  */
164 static void
dec_3max_bus_reset(void)165 dec_3max_bus_reset(void)
166 {
167 
168 	/*
169 	 * Reset interrupts, clear any errors from newconf probes
170 	 */
171 
172 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_ERRADR) = 0;
173 	kn02_wbflush();
174 
175 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CHKSYN) = 0;
176 	kn02_wbflush();
177 }
178 
179 static void
dec_3max_cons_init(void)180 dec_3max_cons_init(void)
181 {
182 	int kbd, crt, screen;
183 	extern int tcfb_cnattach(int);		/* XXX */
184 
185 	kbd = crt = screen = 0;
186 	prom_findcons(&kbd, &crt, &screen);
187 
188 	if (screen > 0) {
189 #if NWSDISPLAY > 0
190  		if (kbd == 7 && tcfb_cnattach(crt) > 0) {
191 			dz_ibus_cnsetup(KN02_SYS_DZ);
192 			dzkbd_cnattach(NULL);
193  			return;
194  		}
195 #endif
196 		printf("No framebuffer device configured for slot %d: ", crt);
197 		printf("using serial console\n");
198 	}
199 	/*
200 	 * Delay to allow PROM putchars to complete.
201 	 * FIFO depth * character time,
202 	 * character time = (1000000 / (defaultrate / 10))
203 	 */
204 	DELAY(160000000 / 9600);	/* XXX */
205 
206 	dz_ibus_cnsetup(KN02_SYS_DZ);
207 	dz_ibus_cnattach(kbd);
208 }
209 
210 static const struct {
211 	int cookie;
212 	int intrbit;
213 } kn02intrs[] = {
214 	{ SYS_DEV_OPT0,	 KN02_IP_SLOT0 },
215 	{ SYS_DEV_OPT1,	 KN02_IP_SLOT1 },
216 	{ SYS_DEV_OPT2,	 KN02_IP_SLOT2 },
217 	{ SYS_DEV_SCSI,	 KN02_IP_SCSI },
218 	{ SYS_DEV_LANCE, KN02_IP_LANCE },
219 	{ SYS_DEV_SCC0,	 KN02_IP_DZ },
220 };
221 
222 static void
dec_3max_intr_establish(device_t dev,void * cookie,int level,int (* handler)(void *),void * arg)223 dec_3max_intr_establish(device_t dev, void *cookie, int level,
224     int (*handler)(void *), void *arg)
225 {
226 	int i;
227 	uint32_t csr;
228 
229 	for (i = 0; i < __arraycount(kn02intrs); i++) {
230 		if (kn02intrs[i].cookie == (intptr_t)cookie)
231 			goto found;
232 	}
233 	panic("intr_establish: invalid cookie %p", cookie);
234 
235 found:
236 	intrtab[(intptr_t)cookie].ih_func = handler;
237 	intrtab[(intptr_t)cookie].ih_arg = arg;
238 
239 	csr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR) &
240 	    0x00ffff00;
241 	csr |= (kn02intrs[i].intrbit << 16);
242 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR) = csr;
243 }
244 
245 
246 #define CALLINTR(vvv)						\
247 	do {							\
248 		intrtab[vvv].ih_count.ev_count++;		\
249 		(*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg);	\
250 	} while (/*CONSTCOND*/0)
251 
252 static void
dec_3max_intr(uint32_t status,vaddr_t pc,uint32_t ipending)253 dec_3max_intr(uint32_t status, vaddr_t pc, uint32_t ipending)
254 {
255 	static bool warned = false;
256 	uint32_t csr;
257 
258 	/* handle clock interrupts ASAP */
259 	if (ipending & MIPS_INT_MASK_1) {
260 		struct clockframe cf;
261 
262 		csr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR);
263 		if ((csr & KN02_CSR_PSWARN) && !warned) {
264 			warned = true;
265 			printf("WARNING: power supply is overheating!\n");
266 		} else if (warned && !(csr & KN02_CSR_PSWARN)) {
267 			warned = false;
268 			printf("WARNING: power supply is OK again\n");
269 		}
270 
271 		__asm volatile("lbu $0,48(%0)" ::
272 			"r"(MIPS_PHYS_TO_KSEG1(KN02_SYS_CLOCK)));
273 		cf.pc = pc;
274 		cf.sr = status;
275 		cf.intr = (curcpu()->ci_idepth > 1);
276 		hardclock(&cf);
277 		pmax_clock_evcnt.ev_count++;
278 
279 		/* keep clock interrupts enabled when we return */
280 	}
281 
282 	if (ipending & MIPS_INT_MASK_0) {
283 		csr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR);
284 		csr &= (csr >> KN02_CSR_IOINTEN_SHIFT);
285 		if (csr & (KN02_IP_DZ | KN02_IP_LANCE | KN02_IP_SCSI)) {
286 			if (csr & KN02_IP_DZ)
287 				CALLINTR(SYS_DEV_SCC0);
288 			if (csr & KN02_IP_LANCE)
289 				CALLINTR(SYS_DEV_LANCE);
290 			if (csr & KN02_IP_SCSI)
291 				CALLINTR(SYS_DEV_SCSI);
292 		}
293 		if (csr & (KN02_IP_SLOT2 | KN02_IP_SLOT1 | KN02_IP_SLOT0)) {
294 			if (csr & KN02_IP_SLOT2)
295 				CALLINTR(SYS_DEV_OPT2);
296 			if (csr & KN02_IP_SLOT1)
297 				CALLINTR(SYS_DEV_OPT1);
298 			if (csr & KN02_IP_SLOT0)
299 				CALLINTR(SYS_DEV_OPT0);
300 		}
301 	}
302 	if (ipending & MIPS_INT_MASK_3) {
303 		dec_3max_errintr();
304 		pmax_memerr_evcnt.ev_count++;
305 	}
306 }
307 
308 
309 /*
310  * Handle Memory error.   3max, 3maxplus has ECC.
311  * Correct single-bit error, panic on double-bit error.
312  * XXX on double-error on clean user page, mark bad and reload frame?
313  */
314 static void
dec_3max_errintr(void)315 dec_3max_errintr(void)
316 {
317 	uint32_t erradr, csr;
318 	vaddr_t errsyn;
319 
320 	/* Fetch error address, ECC chk/syn bits, clear interrupt */
321 	erradr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_ERRADR);
322 	errsyn = MIPS_PHYS_TO_KSEG1(KN02_SYS_CHKSYN);
323 	*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_ERRADR) = 0;
324 	kn02_wbflush();
325 	csr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN02_SYS_CSR);
326 
327 	/* Send to kn02/kn03 memory subsystem handler */
328 	dec_mtasic_err(erradr, errsyn, csr & KN02_CSR_BNK32M);
329 }
330