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
ka820_init()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 */
ka820_clkread(base)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 */
ka820_clkwrite()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
ka820_memenable()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
ka820_memerr()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
ka820_mchk(cmcf)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 */
rxcdintr()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