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