xref: /original-bsd/sys/vax/vax/ka820.c (revision 4d072710)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  *	@(#)ka820.c	7.2 (Berkeley) 07/09/88
21  */
22 
23 #if VAX8200
24 
25 /*
26  * KA820 specific CPU code.  (Note that the VAX8200 uses a KA820, not
27  * a KA8200.  Sigh.)
28  */
29 
30 #include "param.h"
31 #include "time.h"
32 #include "kernel.h"
33 #include "vmmac.h"
34 
35 #include "cpu.h"
36 #include "clock.h"
37 #include "ka820.h"
38 #include "mem.h"
39 #include "mtpr.h"
40 #include "pte.h"
41 
42 #include "../vaxbi/bireg.h"
43 
44 extern struct pte Clockmap[];
45 extern struct pte RX50map[];
46 extern struct pte Ka820map[];
47 struct ka820clock ka820clock;
48 struct ka820port ka820port;
49 
50 #ifdef notyet
51 extern struct pte BRAMmap[];
52 extern struct pte EEPROMmap[];
53 char bootram[KA820_BRPAGES * NBPG];
54 char eeprom[KA820_EEPAGES * NBPG];
55 #endif
56 
57 ka820_init()
58 {
59 	register int csr;
60 
61 	/* map in the various devices */
62 	*(int *)&Ka820map[0] = PG_V|PG_KW|btop(KA820_PORTADDR);
63 	*(int *)&RX50map[0] = PG_V|PG_KW|btop(KA820_RX50ADDR);
64 	*(int *)&Clockmap[0] = PG_V|PG_KW|btop(KA820_CLOCKADDR);
65 #ifdef notyet
66 	ioaccess(bootram, BRAMmap, KA820_BRPAGES * NBPG);
67 	ioaccess(eeprom, EEPROMmap, KA820_EEPAGES * NBPG);
68 #else
69 	mtpr(TBIA, 0);
70 #endif
71 
72 	/* reset the console and enable the RX50 */
73 	csr = ka820port.csr;
74 	csr &= ~KA820PORT_RSTHALT;	/* ??? */
75 	csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN |
76 		KA820PORT_RXIE;
77 	ka820port.csr = csr;
78 }
79 
80 /* Set system time from clock */
81 /* ARGSUSED */
82 ka820_clkread(base)
83 	time_t base;
84 {
85 	register struct ka820clock *clock = &ka820clock;
86 	struct chiptime c;
87 	int s, rv;
88 
89 	rv = CLKREAD_OK;
90 	/* I wish I knew the differences between these */
91 	if ((clock->csr3 & KA820CLK_3_VALID) == 0) {
92 		printf("WARNING: TOY clock not marked valid\n");
93 		rv = CLKREAD_WARN;
94 	}
95 	if ((clock->csr1 & KA820CLK_1_GO) != KA820CLK_1_GO) {
96 		printf("WARNING: TOY clock stopped\n");
97 		rv = CLKREAD_WARN;
98 	}
99 	/* THIS IS NOT RIGHT (clock may change on us) */
100 	s = splhigh();
101 	while (clock->csr0 & KA820CLK_0_BUSY)
102 		/* void */;
103 	c.sec = clock->sec;
104 	c.min = clock->min;
105 	c.hour = clock->hr;
106 	c.day = clock->day;
107 	c.mon = clock->mon;
108 	c.year = clock->yr;
109 	splx(s);
110 
111 	/* the darn thing needs tweaking! */
112 	c.sec >>= 1;		/* tweak */
113 	c.min >>= 1;		/* tweak */
114 	c.hour >>= 1;		/* tweak */
115 	c.day >>= 1;		/* tweak */
116 	c.mon >>= 1;		/* tweak */
117 	c.year >>= 1;		/* tweak */
118 
119 	time.tv_sec = chiptotime(&c);
120 	return (time.tv_sec ? rv : CLKREAD_BAD);
121 }
122 
123 /* store time into clock */
124 ka820_clkwrite()
125 {
126 	register struct ka820clock *clock = &ka820clock;
127 	struct chiptime c;
128 	int s;
129 
130 	timetochip(&c);
131 
132 	/* play it again, sam (or mike or kirk or ...) */
133 	c.sec <<= 1;		/* tweak */
134 	c.min <<= 1;		/* tweak */
135 	c.hour <<= 1;		/* tweak */
136 	c.day <<= 1;		/* tweak */
137 	c.mon <<= 1;		/* tweak */
138 	c.year <<= 1;		/* tweak */
139 
140 	s = splhigh();
141 	clock->csr1 = KA820CLK_1_SET;
142 	while (clock->csr0 & KA820CLK_0_BUSY)
143 		/* void */;
144 	clock->sec = c.sec;
145 	clock->min = c.min;
146 	clock->hr = c.hour;
147 	clock->day = c.day;
148 	clock->mon = c.mon;
149 	clock->yr = c.year;
150 	/* should we set a `rate'? */
151 	clock->csr1 = KA820CLK_1_GO;
152 	splx(s);
153 }
154 
155 /*
156  * MS820 support.
157  */
158 struct ms820regs {
159 	struct	biiregs biic;		/* BI interface chip */
160 	u_long	ms_gpr[4];		/* the four gprs (unused) */
161 	int	ms_csr1;		/* control/status register 1 */
162 	int	ms_csr2;		/* control/status register 2 */
163 };
164 
165 /*
166  * Bits in CSR1.
167  */
168 #define	MS1_ERRSUM	0x80000000	/* error summary (ro) */
169 #define	MS1_ECCDIAG	0x40000000	/* ecc diagnostic (rw) */
170 #define	MS1_ECCDISABLE	0x20000000	/* ecc disable (rw) */
171 #define	MS1_MSIZEMASK	0x1ffc0000	/* mask for memory size (ro) */
172 #define	MS1_RAMTYMASK	0x00030000	/* mask for ram type (ro) */
173 #define	MS1_RAMTY64K	0x00000000	/* 64K chips */
174 #define	MS1_RAMTY256K	0x00010000	/* 256K chips */
175 					/* types 2 and 3 reserved */
176 #define	MS1_CRDINH	0x00008000	/* inhibit crd interrupts (rw) */
177 #define	MS1_MEMVALID	0x00004000	/* memory has been written (ro) */
178 #define	MS1_INTLK	0x00002000	/* interlock flag (ro) */
179 #define	MS1_BROKE	0x00001000	/* broken (rw) */
180 #define	MS1_MBZ		0x00000880	/* zero */
181 #define	MS1_MWRITEERR	0x00000400	/* rds during masked write (rw) */
182 #define	MS1_CNTLERR	0x00000200	/* internal timing busted (rw) */
183 #define	MS1_INTLV	0x00000100	/* internally interleaved (ro) */
184 #define	MS1_DIAGC	0x0000007f	/* ecc diagnostic bits (rw) */
185 
186 /*
187  * Bits in CSR2.
188  */
189 #define	MS2_RDSERR	0x80000000	/* rds error (rw) */
190 #define	MS2_HIERR	0x40000000	/* high error rate (rw) */
191 #define	MS2_CRDERR	0x20000000	/* crd error (rw) */
192 #define	MS2_ADRSERR	0x10000000	/* rds due to addr par err (rw) */
193 #define	MS2_MBZ		0x0f000080	/* zero */
194 #define	MS2_ADDR	0x00fffe00	/* address in error (relative) (ro) */
195 #define	MS2_INTLVADDR	0x00000100	/* error was in bank 1 (ro) */
196 #define	MS2_SYN		0x0000007f	/* error syndrome (ro, rw diag) */
197 
198 
199 ka820_memenable()
200 {
201 	register struct ms820regs *mcr;
202 	register int m;
203 
204 	for (m = 0; m < nmcr; m++) {
205 		mcr = (struct ms820regs *)mcraddr[m];
206 		/*
207 		 * This will be noisy.  Should we do anything
208 		 * about that?
209 		 */
210 		if ((mcr->biic.bi_csr & BICSR_STS) == 0)
211 			printf("mcr%d: failed self test\n", m);
212 		else {
213 			mcr->ms_csr1 = MS1_MWRITEERR | MS1_CNTLERR;
214 			mcr->ms_csr2 = MS2_RDSERR | MS2_HIERR |
215 				MS2_CRDERR | MS2_ADRSERR;
216 		}
217 	}
218 }
219 
220 ka820_memerr()
221 {
222 	register struct ms820regs *mcr;
223 	register int m, hard;
224 	register char *type;
225 static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\
226 \16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV";
227 static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS";
228 
229 	for (m = 0; m < nmcr; m++) {
230 		mcr = (struct ms820regs *)mcraddr[m];
231 printf("mcr%d: csr1=%b csr2=%b\n", m, mcr->ms_csr1, b1, mcr->ms_csr2, b2);
232 		if ((mcr->ms_csr1 & MS1_ERRSUM) == 0)
233 			continue;
234 		hard = 1;
235 		if (mcr->ms_csr1 & MS1_BROKE)
236 			type = "broke";
237 		else if (mcr->ms_csr1 & MS1_CNTLERR)
238 			type = "cntl err";
239 		else if (mcr->ms_csr2 & MS2_ADRSERR)
240 			type = "address parity err";
241 		else if (mcr->ms_csr2 & MS2_RDSERR)
242 			type = "rds err";
243 		else if (mcr->ms_csr2 & MS2_CRDERR) {
244 			hard = 0;
245 			type = "";
246 		} else
247 			type = "mysterious error";
248 		printf("mcr%d: %s%s%s addr %x bank %x syn %x\n", m,
249 			hard ? "hard error: " : "soft ecc",
250 			type, mcr->ms_csr2 & MS2_HIERR ?
251 			" (+ other rds or crd err)" : "",
252 			((mcr->ms_csr2 & MS2_ADDR) + mcr->biic.bi_sadr) >> 9,
253 			(mcr->ms_csr2 & MS2_INTLVADDR) != 0,
254 			mcr->ms_csr2 & MS2_SYN);
255 		mcr->ms_csr1 = mcr->ms_csr1 | MS1_CRDINH;
256 		mcr->ms_csr2 = mcr->ms_csr2;
257 	}
258 }
259 
260 /* these are bits 0 to 6 in the summary field */
261 char *mc8200[] = {
262 	"cpu bad ipl",		"ucode lost err",
263 	"ucode par err",	"DAL par err",
264 	"BI bus err",		"BTB tag par",
265 	"cache tag par",
266 };
267 #define	MC8200_BADIPL	0x01
268 #define	MC8200_UERR	0x02
269 #define	MC8200_UPAR	0x04
270 #define	MC8200_DPAR	0x08
271 #define	MC8200_BIERR	0x10
272 #define	MC8200_BTAGPAR	0x20
273 #define	MC8200_CTAGPAR	0x40
274 
275 struct mc8200frame {
276 	int	mc82_bcnt;		/* byte count == 0x20 */
277 	int	mc82_summary;		/* summary parameter */
278 	int	mc82_param1;		/* parameter 1 */
279 	int	mc82_va;		/* va register */
280 	int	mc82_vap;		/* va prime register */
281 	int	mc82_ma;		/* memory address */
282 	int	mc82_status;		/* status word */
283 	int	mc82_epc;		/* error pc */
284 	int	mc82_upc;		/* micro pc */
285 	int	mc82_pc;		/* current pc */
286 	int	mc82_psl;		/* current psl */
287 };
288 
289 ka820_mchk(cmcf)
290 	caddr_t cmcf;
291 {
292 	register struct mc8200frame *mcf = (struct mc8200frame *)cmcf;
293 	register int i, type = mcf->mc82_summary;
294 	extern int cold;
295 
296 	/* ignore BI bus errors during configuration */
297 	if (cold && type == MC8200_BIERR) {
298 		mtpr(MCESR, 0xf);
299 		return (MCHK_RECOVERED);
300 	}
301 
302 	/*
303 	 * SOME ERRORS ARE RECOVERABLE
304 	 * do it later
305 	 */
306 	printf("machine check %x: ", type);
307 	for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++)
308 		if (type & (1 << i))
309 			printf(" %s,", mc8200[i]);
310 	printf(" param1 %x\n", mcf->mc82_param1);
311 	printf(
312 "\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n",
313 		mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma,
314 		mcf->mc82_pc, mcf->mc82_psl,
315 		mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc);
316 	return (MCHK_PANIC);
317 }
318 
319 /*
320  * Receive a character from logical console.
321  */
322 rxcdintr()
323 {
324 	register int c = mfpr(RXCD);
325 
326 	/* not sure what (if anything) to do with these */
327 	printf("rxcd node %x c=0x%x\n", (c >> 8) & 0xf, c & 0xff);
328 }
329 #endif
330