xref: /netbsd-src/sys/arch/vax/vax/ka650.c (revision 181973476ea9763c3e5953949268c5ac968b3356)
1 /*	$NetBSD: ka650.c,v 1.39 2024/02/21 23:23:06 andvar Exp $	*/
2 /*
3  * Copyright (c) 1988 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Mt. Xinu.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)ka650.c	7.7 (Berkeley) 12/16/90
34  */
35 
36 /*
37  * vax650-specific code.
38  */
39 
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: ka650.c,v 1.39 2024/02/21 23:23:06 andvar Exp $");
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/cpu.h>
46 #include <sys/device.h>
47 #include <sys/kernel.h>
48 #include <sys/time.h>
49 
50 #include <machine/ka650.h>
51 #include <machine/clock.h>
52 #include <machine/sid.h>
53 
54 struct	ka650_merr *ka650merr_ptr;
55 struct	ka650_cbd *ka650cbd_ptr;
56 struct	ka650_ssc *ka650ssc_ptr;
57 struct	ka650_ipcr *ka650ipcr_ptr;
58 int	*KA650_CACHE_ptr;
59 
60 #define	CACHEOFF	0
61 #define	CACHEON		1
62 
63 static	void	ka650setcache(int);
64 static	void	ka650_halt(void);
65 static	void	ka650_reboot(int);
66 static	void    ka650_conf(void);
67 static	void    ka650_memerr(void);
68 static	int     ka650_mchk(void *);
69 static	void	ka650_attach_cpu(device_t);
70 
71 static const char * const ka650_devs[] = { "cpu", "lance", "uba", NULL };
72 
73 const struct cpu_dep ka650_calls = {
74 	.cpu_mchk	= ka650_mchk,
75 	.cpu_memerr	= ka650_memerr,
76 	.cpu_conf	= ka650_conf,
77 	.cpu_gettime	= generic_gettime,
78 	.cpu_settime	= generic_settime,
79 	.cpu_vups	= 4,      /* ~VUPS */
80 	.cpu_scbsz	= 2,	/* SCB pages */
81 	.cpu_halt	= ka650_halt,
82 	.cpu_reboot	= ka650_reboot,
83 	.cpu_devs	= ka650_devs,
84 	.cpu_attach_cpu	= ka650_attach_cpu,
85 	.cpu_flags	= CPU_RAISEIPL,	/* Needed for the LANCE chip */
86 };
87 
88 /*
89  * ka650_conf() is called by cpu_attach to do the cpu_specific setup.
90  */
91 void
ka650_conf(void)92 ka650_conf(void)
93 {
94 
95 	/*
96 	 * MicroVAX III: We map in memory error registers,
97 	 * cache control registers, SSC registers,
98 	 * interprocessor registers and cache diag space.
99 	 */
100 	ka650merr_ptr = (void *)vax_map_physmem(KA650_MERR, 1);
101 	ka650cbd_ptr = (void *)vax_map_physmem(KA650_CBD, 1);
102 	ka650ssc_ptr = (void *)vax_map_physmem(KA650_SSC, 3);
103 	ka650ipcr_ptr = (void *)vax_map_physmem(KA650_IPCR, 1);
104 	KA650_CACHE_ptr = (void *)vax_map_physmem(KA650_CACHE,
105 	    (KA650_CACHESIZE/VAX_NBPG));
106 
107 	ka650setcache(CACHEON);
108 	if (ctob(physmem) > ka650merr_ptr->merr_qbmbr) {
109 		printf("physmem(0x%"PRIxPSIZE") > qbmbr(0x%x)\n",
110 		    ctob(physmem), (int)ka650merr_ptr->merr_qbmbr);
111 		panic("qbus map unprotected");
112 	}
113 	if (mfpr(PR_TODR) == 0)
114 		mtpr(1, PR_TODR);
115 }
116 
117 void
ka650_attach_cpu(device_t self)118 ka650_attach_cpu(device_t self)
119 {
120 	int syssub = GETSYSSUBT(vax_siedata);
121 
122 	aprint_normal(": KA6%d%d, CVAX microcode rev %d Firmware rev %d\n",
123 	    syssub == VAX_SIE_KA640 ? 4 : 5,
124 	    syssub == VAX_SIE_KA655 ? 5 : 0,
125 	    (vax_cpudata & 0xff), GETFRMREV(vax_siedata));
126 }
127 
128 void
ka650_memerr(void)129 ka650_memerr(void)
130 {
131 	printf("memory err!\n");
132 #if 0 /* XXX Fix this */
133 	char *cp = NULL;
134 	int m;
135 	extern u_int cache2tag;
136 
137 	if (ka650cbd.cbd_cacr & CACR_CPE) {
138 		printf("cache 2 tag parity error: ");
139 		if (time.tv_sec - cache2tag < 7) {
140 			ka650setcache(CACHEOFF);
141 			printf("cacheing disabled\n");
142 		} else {
143 			cache2tag = time.tv_sec;
144 			printf("flushing cache\n");
145 			ka650setcache(CACHEON);
146 		}
147 	}
148 	m = ka650merr.merr_errstat;
149 	ka650merr.merr_errstat = MEM_EMASK;
150 	if (m & MEM_CDAL) {
151 		cp = "Bus Parity";
152 	} else if (m & MEM_RDS) {
153 		cp = "Hard ECC";
154 	} else if (m & MEM_CRD) {
155 		cp = "Soft ECC";
156 	}
157 	if (cp) {
158 		printf("%sMemory %s Error: page 0x%x\n",
159 			(m & MEM_DMA) ? "DMA " : "", cp,
160 			(m & MEM_PAGE) >> MEM_PAGESHFT);
161 	}
162 #endif
163 }
164 
165 #define NMC650	15
166 const char * const mc650[] = {
167 	0,			"FPA proto err",	"FPA resv inst",
168 	"FPA Ill Stat 2",	"FPA Ill Stat 1",	"PTE in P0, TB miss",
169 	"PTE in P1, TB miss",	"PTE in P0, Mod",	"PTE in P1, Mod",
170 	"Illegal intr IPL",	"MOVC state error",	"bus read error",
171 	"SCB read error",	"bus write error",	"PCB write error"
172 };
173 u_int	cache1tag;
174 u_int	cache1data;
175 u_int	cdalerr;
176 u_int	cache2tag;
177 
178 struct mc650frame {
179 	int	mc65_bcnt;		/* byte count == 0xc */
180 	int	mc65_summary;		/* summary parameter */
181 	int	mc65_mrvaddr;		/* most recent vad */
182 	int	mc65_istate1;		/* internal state */
183 	int	mc65_istate2;		/* internal state */
184 	int	mc65_pc;		/* trapped pc */
185 	int	mc65_psl;		/* trapped psl */
186 };
187 
188 int
ka650_mchk(void * cmcf)189 ka650_mchk(void *cmcf)
190 {
191 	struct mc650frame *mcf = (struct mc650frame *)cmcf;
192 	u_int type = mcf->mc65_summary;
193 	u_int i;
194 	char sbuf[256];
195 
196 	printf("machine check %x", type);
197 	if (type >= 0x80 && type <= 0x83)
198 		type -= (0x80 + 11);
199 	if (type < NMC650 && mc650[type])
200 		printf(": %s", mc650[type]);
201 	printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n",
202 	    mcf->mc65_mrvaddr, mcf->mc65_istate1, mcf->mc65_istate2,
203 	    mcf->mc65_pc, mcf->mc65_psl);
204 	snprintb(sbuf, sizeof(sbuf), DMASER_BITS, ka650merr_ptr->merr_dser);
205 	printf("dmaser=%s qbear=0x%x dmaear=0x%x\n", sbuf,
206 	    (int)ka650merr_ptr->merr_qbear,
207 	    (int)ka650merr_ptr->merr_dear);
208 	ka650merr_ptr->merr_dser = DSER_CLEAR;
209 
210 	i = mfpr(PR_CAER);
211 	mtpr(CAER_MCC | CAER_DAT | CAER_TAG, PR_CAER);
212 	if (i & CAER_MCC) {
213 		printf("cache 1 ");
214 		if (i & CAER_DAT) {
215 			printf("data");
216 			i = cache1data;
217 			cache1data = time_second;
218 		}
219 		if (i & CAER_TAG) {
220 			printf("tag");
221 			i = cache1tag;
222 			cache1tag = time_second;
223 		}
224 	} else if ((i & CAER_MCD) || (ka650merr_ptr->merr_errstat & MEM_CDAL)) {
225 		printf("CDAL");
226 		i = cdalerr;
227 		cdalerr = time_second;
228 	}
229 	if (time_second - i < 7) {
230 		ka650setcache(CACHEOFF);
231 		printf(" parity error:	cacheing disabled\n");
232 	} else {
233 		printf(" parity error:	flushing cache\n");
234 		ka650setcache(CACHEON);
235 	}
236 	/*
237 	 * May be able to recover if type is 1-4, 0x80 or 0x81, but
238 	 * only if FPD is set in the saved PSL, or bit VCR in Istate2
239 	 * is clear.
240 	 */
241 	if ((type > 0 && type < 5) || type == 11 || type == 12) {
242 		if ((mcf->mc65_psl & PSL_FPD)
243 		    || !(mcf->mc65_istate2 & IS2_VCR)) {
244 			ka650_memerr();
245 			return 0;
246 		}
247 	}
248 	return -1;
249 }
250 
251 /*
252  * Make sure both caches are off and not in diagnostic mode.  Clear the
253  * 2nd level cache (by writing to each quadword entry), then enable it.
254  * Enable 1st level cache too.
255  */
256 void
ka650setcache(int state)257 ka650setcache(int state)
258 {
259 	int syssub = GETSYSSUBT(vax_siedata);
260 	int i;
261 
262 	/*
263 	 * Before doing anything, disable the cache.
264 	 */
265 	mtpr(0, PR_CADR);
266 	if (syssub != VAX_SIE_KA640)
267 		ka650cbd_ptr->cbd_cacr = CACR_CPE;
268 
269 	/*
270 	 * Check what we want to do, enable or disable.
271 	 */
272 	if (state == CACHEON) {
273 		mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR);
274 		if (syssub != VAX_SIE_KA640) {
275 			for (i = 0;
276 			    i < (KA650_CACHESIZE / sizeof(KA650_CACHE_ptr[0]));
277 			    i += 2)
278 				KA650_CACHE_ptr[i] = 0;
279 			ka650cbd_ptr->cbd_cacr = CACR_CEN;
280 		}
281 	}
282 }
283 
284 void
ka650_halt(void)285 ka650_halt(void)
286 {
287 	ka650ssc_ptr->ssc_cpmbx = CPMB650_DOTHIS | CPMB650_HALT;
288 	__asm("halt");
289 }
290 
291 void
ka650_reboot(int arg)292 ka650_reboot(int arg)
293 {
294 	ka650ssc_ptr->ssc_cpmbx = CPMB650_DOTHIS | CPMB650_REBOOT;
295 }
296