1 /* $NetBSD: ka43.c,v 1.25 2002/09/27 15:36:59 provos Exp $ */ 2 /* 3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Ludd by Bertram Barth. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed at Ludd, University of 19 * Lule}, Sweden and its contributors. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/types.h> 37 #include <sys/device.h> 38 #include <sys/kernel.h> 39 #include <sys/systm.h> 40 41 #include <uvm/uvm_extern.h> 42 43 #include <machine/pte.h> 44 #include <machine/cpu.h> 45 #include <machine/mtpr.h> 46 #include <machine/sid.h> 47 #include <machine/pmap.h> 48 #include <machine/nexus.h> 49 #include <machine/uvax.h> 50 #include <machine/vsbus.h> 51 #include <machine/ka43.h> 52 #include <machine/clock.h> 53 54 static void ka43_conf __P((void)); 55 static void ka43_steal_pages __P((void)); 56 57 static int ka43_mchk __P((caddr_t)); 58 static void ka43_memerr __P((void)); 59 #if 0 60 static void ka43_clear_errors __P((void)); 61 #endif 62 static int ka43_cache_init __P((void)); /* "int mapen" as argument? */ 63 static int ka43_cache_reset __P((void)); 64 static int ka43_cache_enable __P((void)); 65 static int ka43_cache_disable __P((void)); 66 static int ka43_cache_invalidate __P((void)); 67 static void ka43_halt __P((void)); 68 static void ka43_reboot __P((int)); 69 static void ka43_clrf __P((void)); 70 71 72 struct cpu_dep ka43_calls = { 73 ka43_steal_pages, 74 ka43_mchk, 75 ka43_memerr, 76 ka43_conf, 77 chip_clkread, 78 chip_clkwrite, 79 7, /* 7.6 VUP */ 80 2, /* SCB pages */ 81 ka43_halt, 82 ka43_reboot, 83 ka43_clrf, 84 NULL, 85 CPU_RAISEIPL, 86 }; 87 88 /* 89 * ka43_steal_pages() is called with MMU disabled, after that call MMU gets 90 * enabled. Thus we initialize these four pointers with physical addresses, 91 * but before leving ka43_steal_pages() we reset them to virtual addresses. 92 */ 93 static volatile struct ka43_cpu *ka43_cpu = (void*)KA43_CPU_BASE; 94 static volatile u_int *ka43_creg = (void*)KA43_CH2_CREG; 95 static volatile u_int *ka43_ctag = (void*)KA43_CT2_BASE; 96 97 #define KA43_MC_RESTART 0x00008000 /* Restart possible*/ 98 #define KA43_PSL_FPDONE 0x00010000 /* First Part Done */ 99 100 struct ka43_mcframe { /* Format of RigelMAX machine check frame: */ 101 int mc43_bcnt; /* byte count, always 24 (0x18) */ 102 int mc43_code; /* machine check type code and restart bit */ 103 int mc43_addr; /* most recent (faulting?) virtual address */ 104 int mc43_viba; /* contents of VIBA register */ 105 int mc43_sisr; /* ICCS bit 6 and SISR bits 15:0 */ 106 int mc43_istate; /* internal state */ 107 int mc43_sc; /* shift count register */ 108 int mc43_pc; /* trapped PC */ 109 int mc43_psl; /* trapped PSL */ 110 }; 111 112 static char *ka43_mctype[] = { 113 "no error (0)", /* Code 0: No error */ 114 "FPA: protocol error", /* Code 1-5: FPA errors */ 115 "FPA: illegal opcode", 116 "FPA: operand parity error", 117 "FPA: unknown status", 118 "FPA: result parity error", 119 "unused (6)", /* Code 6-7: Unused */ 120 "unused (7)", 121 "MMU error (TLB miss)", /* Code 8-9: MMU errors */ 122 "MMU error (TLB hit)", 123 "HW interrupt at unused IPL", /* Code 10: Interrupt error */ 124 "MOVCx impossible state", /* Code 11-13: Microcode errors */ 125 "undefined trap code (i-box)", 126 "undefined control store address", 127 "unused (14)", /* Code 14-15: Unused */ 128 "unused (15)", 129 "PC tag or data parity error", /* Code 16: Cache error */ 130 "data bus parity error", /* Code 17: Read error */ 131 "data bus error (NXM)", /* Code 18: Write error */ 132 "undefined data bus state", /* Code 19: Bus error */ 133 }; 134 #define MC43_MAX 19 135 136 static int ka43_error_count = 0; 137 138 int 139 ka43_mchk(addr) 140 caddr_t addr; 141 { 142 register struct ka43_mcframe *mcf = (void*)addr; 143 144 mtpr(0x00, PR_MCESR); /* Acknowledge the machine check */ 145 printf("machine check %d (0x%x)\n", mcf->mc43_code, mcf->mc43_code); 146 printf("reason: %s\n", ka43_mctype[mcf->mc43_code & 0xff]); 147 if (++ka43_error_count > 10) { 148 printf("error_count exceeded: %d\n", ka43_error_count); 149 return (-1); 150 } 151 152 /* 153 * If either the Restart flag is set or the First-Part-Done flag 154 * is set, and the TRAP2 (double error) bit is not set, then the 155 * error is recoverable. 156 */ 157 if (mfpr(PR_PCSTS) & KA43_PCS_TRAP2) { 158 printf("TRAP2 (double error) in ka43_mchk.\n"); 159 panic("unrecoverable state in ka43_mchk."); 160 return (-1); 161 } 162 if ((mcf->mc43_code & KA43_MC_RESTART) || 163 (mcf->mc43_psl & KA43_PSL_FPDONE)) { 164 printf("ka43_mchk: recovering from machine-check.\n"); 165 ka43_cache_reset(); /* reset caches */ 166 return (0); /* go on; */ 167 } 168 169 /* 170 * Unknown error state, panic/halt the machine! 171 */ 172 printf("ka43_mchk: unknown error state!\n"); 173 return (-1); 174 } 175 176 void 177 ka43_memerr() 178 { 179 char sbuf[256]; 180 181 /* 182 * Don\'t know what to do here. So just print some messages 183 * and try to go on... 184 */ 185 186 printf("memory error!\n"); 187 188 bitmask_snprintf(mfpr(PR_PCSTS), KA43_PCSTS_BITS, sbuf, sizeof(sbuf)); 189 printf("primary cache status: %s\n", sbuf); 190 191 bitmask_snprintf(*ka43_creg, KA43_SESR_BITS, sbuf, sizeof(sbuf)); 192 printf("secondary cache status: %s\n", sbuf); 193 } 194 195 int 196 ka43_cache_init() 197 { 198 return (ka43_cache_reset()); 199 } 200 201 #if 0 202 void 203 ka43_clear_errors() 204 { 205 int val = *ka43_creg; 206 val |= KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR; 207 *ka43_creg = val; 208 } 209 #endif 210 211 int 212 ka43_cache_reset() 213 { 214 char sbuf[256]; 215 216 /* 217 * resetting primary and secondary caches is done in three steps: 218 * 1. disable both caches 219 * 2. manually clear secondary cache 220 * 3. enable both caches 221 */ 222 ka43_cache_disable(); 223 ka43_cache_invalidate(); 224 ka43_cache_enable(); 225 226 bitmask_snprintf(mfpr(PR_PCSTS), KA43_PCSTS_BITS, sbuf, sizeof(sbuf)); 227 printf("primary cache status: %s\n", sbuf); 228 229 bitmask_snprintf(*ka43_creg, KA43_SESR_BITS, sbuf, sizeof(sbuf)); 230 printf("secondary cache status: %s\n", sbuf); 231 232 return (0); 233 } 234 235 int 236 ka43_cache_disable() 237 { 238 int val; 239 240 /* 241 * first disable primary cache and clear error flags 242 */ 243 mtpr(KA43_PCS_REFRESH, PR_PCSTS); /* disable primary cache */ 244 val = mfpr(PR_PCSTS); 245 mtpr(val, PR_PCSTS); /* clear error flags */ 246 247 /* 248 * now disable secondary cache and clear error flags 249 */ 250 val = *ka43_creg & ~KA43_SESR_CENB; /* BICL !!! */ 251 *ka43_creg = val; /* disable secondary cache */ 252 val = KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR; 253 *ka43_creg = val; /* clear error flags */ 254 255 return (0); 256 } 257 258 int 259 ka43_cache_invalidate() 260 { 261 int i, val; 262 263 val = KA43_PCTAG_PARITY; /* clear valid flag, set parity bit */ 264 for (i = 0; i < 256; i++) { /* 256 Quadword entries */ 265 mtpr(i*8, PR_PCIDX); /* write index of tag */ 266 mtpr(val, PR_PCTAG); /* write value into tag */ 267 } 268 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH; 269 mtpr(val, PR_PCSTS); /* flush primary cache */ 270 271 /* 272 * Rigel\'s secondary cache doesn\'t implement a valid-flag. 273 * Thus we initialize all entries with out-of-range/dummy 274 * addresses which will never be referenced (ie. never hit). 275 * After enabling cache we also access 128K of memory starting 276 * at 0x00 so that secondary cache will be filled with these 277 * valid addresses... 278 */ 279 val = 0xff; 280 /* if (memory > 28 MB) val = 0x55; */ 281 for (i = 0; i < KA43_CT2_SIZE; i+= 4) { /* Quadword entries ?? */ 282 ka43_ctag[i/4] = val; /* reset upper and lower */ 283 } 284 285 return (0); 286 } 287 288 289 int 290 ka43_cache_enable() 291 { 292 volatile char *membase = (void*)0x80000000; /* physical 0x00 */ 293 int i, val; 294 295 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH; 296 mtpr(val, PR_PCSTS); /* flush primary cache */ 297 298 /* 299 * now we enable secondary cache and access first 128K of memory 300 * so that secondary cache gets really initialized and holds 301 * valid addresses/data... 302 */ 303 *ka43_creg = KA43_SESR_CENB; /* enable secondary cache */ 304 for (i=0; i<128*1024; i++) { 305 val += membase[i]; /* some dummy operation... */ 306 } 307 308 val = KA43_PCS_ENABLE | KA43_PCS_REFRESH; 309 mtpr(val, PR_PCSTS); /* enable primary cache */ 310 311 return (0); 312 } 313 314 void 315 ka43_conf() 316 { 317 printf("cpu: KA43\n"); 318 ka43_cpu = (void *)vax_map_physmem(VS_REGS, 1); 319 320 ka43_creg = (void *)vax_map_physmem(KA43_CH2_CREG, 1); 321 ka43_ctag = (void *)vax_map_physmem(KA43_CT2_BASE, 322 (KA43_CT2_SIZE/VAX_NBPG)); 323 324 /* 325 * ka43_conf() gets called with MMU enabled, now it's save to 326 * init/reset the caches. 327 */ 328 ka43_cache_init(); 329 330 clk_adrshift = 1; /* Addressed at long's... */ 331 clk_tweak = 2; /* ...and shift two */ 332 clk_page = (short *)vax_map_physmem(VS_CLOCK, 1); 333 } 334 335 336 /* 337 * The interface for communication with the LANCE ethernet controller 338 * is setup in the xxx_steal_pages() routine. We decrease highest 339 * available address by 64K and use this area as communication buffer. 340 */ 341 342 void 343 ka43_steal_pages() 344 { 345 int val; 346 347 348 /* 349 * if LANCE\'s io-buffer is above 16 MB, then the appropriate flag 350 * in the parity control register has to be set (it works as an 351 * additional address bit). In any case, don\'t enable CPEN and 352 * DPEN in the PARCTL register, somewhow they are internally managed 353 * by the RIGEL chip itself!?! 354 */ 355 val = ka43_cpu->parctl & 0x03; /* read the old value */ 356 ka43_cpu->parctl = val; /* and write new value */ 357 } 358 359 static void 360 ka43_clrf() 361 { 362 struct ka43_clock *clk = (void *)clk_page; 363 364 /* 365 * Clear restart and boot in progress flags in the CPMBX. 366 */ 367 clk->cpmbx = (clk->cpmbx & ~0xf0); 368 } 369 370 static void 371 ka43_halt() 372 { 373 asm("movl $0xc, (%0)"::"r"((int)clk_page + 0x38)); /* Don't ask */ 374 asm("halt"); 375 } 376 377 static void 378 ka43_reboot(arg) 379 int arg; 380 { 381 asm("movl $0xc, (%0)"::"r"((int)clk_page + 0x38)); /* Don't ask */ 382 asm("halt"); 383 } 384 385