Commit | Line | Data |
---|---|---|
025fd248 | 1 | /* |
35962040 KB |
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) %G% | |
025fd248 MK |
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 |