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