1/* $NetBSD: ka650.c,v 1.39 2024/02/21 23:23:06 andvar Exp $ */ 2/* 3 * Copyright (c) 1988 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Mt. Xinu. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ka650.c 7.7 (Berkeley) 12/16/90 34 */ 35 36/* 37 * vax650-specific code. 38 */ 39 40#include <sys/cdefs.h> 41__KERNEL_RCSID(0, "$NetBSD: ka650.c,v 1.39 2024/02/21 23:23:06 andvar Exp $"); 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/cpu.h> 46#include <sys/device.h> 47#include <sys/kernel.h> 48#include <sys/time.h> 49 50#include <machine/ka650.h> 51#include <machine/clock.h> 52#include <machine/sid.h> 53 54struct ka650_merr *ka650merr_ptr; 55struct ka650_cbd *ka650cbd_ptr; 56struct ka650_ssc *ka650ssc_ptr; 57struct ka650_ipcr *ka650ipcr_ptr; 58int *KA650_CACHE_ptr; 59 60#define CACHEOFF 0 61#define CACHEON 1 62 63static void ka650setcache(int); 64static void ka650_halt(void); 65static void ka650_reboot(int); 66static void ka650_conf(void); 67static void ka650_memerr(void); 68static int ka650_mchk(void *); 69static void ka650_attach_cpu(device_t); 70 71static const char * const ka650_devs[] = { "cpu", "lance", "uba", NULL }; 72 73const struct cpu_dep ka650_calls = { 74 .cpu_mchk = ka650_mchk, 75 .cpu_memerr = ka650_memerr, 76 .cpu_conf = ka650_conf, 77 .cpu_gettime = generic_gettime, 78 .cpu_settime = generic_settime, 79 .cpu_vups = 4, /* ~VUPS */ 80 .cpu_scbsz = 2, /* SCB pages */ 81 .cpu_halt = ka650_halt, 82 .cpu_reboot = ka650_reboot, 83 .cpu_devs = ka650_devs, 84 .cpu_attach_cpu = ka650_attach_cpu, 85 .cpu_flags = CPU_RAISEIPL, /* Needed for the LANCE chip */ 86}; 87 88/* 89 * ka650_conf() is called by cpu_attach to do the cpu_specific setup. 90 */ 91void 92ka650_conf(void) 93{ 94 95 /* 96 * MicroVAX III: We map in memory error registers, 97 * cache control registers, SSC registers, 98 * interprocessor registers and cache diag space. 99 */ 100 ka650merr_ptr = (void *)vax_map_physmem(KA650_MERR, 1); 101 ka650cbd_ptr = (void *)vax_map_physmem(KA650_CBD, 1); 102 ka650ssc_ptr = (void *)vax_map_physmem(KA650_SSC, 3); 103 ka650ipcr_ptr = (void *)vax_map_physmem(KA650_IPCR, 1); 104 KA650_CACHE_ptr = (void *)vax_map_physmem(KA650_CACHE, 105 (KA650_CACHESIZE/VAX_NBPG)); 106 107 ka650setcache(CACHEON); 108 if (ctob(physmem) > ka650merr_ptr->merr_qbmbr) { 109 printf("physmem(0x%"PRIxPSIZE") > qbmbr(0x%x)\n", 110 ctob(physmem), (int)ka650merr_ptr->merr_qbmbr); 111 panic("qbus map unprotected"); 112 } 113 if (mfpr(PR_TODR) == 0) 114 mtpr(1, PR_TODR); 115} 116 117void 118ka650_attach_cpu(device_t self) 119{ 120 int syssub = GETSYSSUBT(vax_siedata); 121 122 aprint_normal(": KA6%d%d, CVAX microcode rev %d Firmware rev %d\n", 123 syssub == VAX_SIE_KA640 ? 4 : 5, 124 syssub == VAX_SIE_KA655 ? 5 : 0, 125 (vax_cpudata & 0xff), GETFRMREV(vax_siedata)); 126} 127 128void 129ka650_memerr(void) 130{ 131 printf("memory err!\n"); 132#if 0 /* XXX Fix this */ 133 char *cp = NULL; 134 int m; 135 extern u_int cache2tag; 136 137 if (ka650cbd.cbd_cacr & CACR_CPE) { 138 printf("cache 2 tag parity error: "); 139 if (time.tv_sec - cache2tag < 7) { 140 ka650setcache(CACHEOFF); 141 printf("cacheing disabled\n"); 142 } else { 143 cache2tag = time.tv_sec; 144 printf("flushing cache\n"); 145 ka650setcache(CACHEON); 146 } 147 } 148 m = ka650merr.merr_errstat; 149 ka650merr.merr_errstat = MEM_EMASK; 150 if (m & MEM_CDAL) { 151 cp = "Bus Parity"; 152 } else if (m & MEM_RDS) { 153 cp = "Hard ECC"; 154 } else if (m & MEM_CRD) { 155 cp = "Soft ECC"; 156 } 157 if (cp) { 158 printf("%sMemory %s Error: page 0x%x\n", 159 (m & MEM_DMA) ? "DMA " : "", cp, 160 (m & MEM_PAGE) >> MEM_PAGESHFT); 161 } 162#endif 163} 164 165#define NMC650 15 166const char * const mc650[] = { 167 0, "FPA proto err", "FPA resv inst", 168 "FPA Ill Stat 2", "FPA Ill Stat 1", "PTE in P0, TB miss", 169 "PTE in P1, TB miss", "PTE in P0, Mod", "PTE in P1, Mod", 170 "Illegal intr IPL", "MOVC state error", "bus read error", 171 "SCB read error", "bus write error", "PCB write error" 172}; 173u_int cache1tag; 174u_int cache1data; 175u_int cdalerr; 176u_int cache2tag; 177 178struct mc650frame { 179 int mc65_bcnt; /* byte count == 0xc */ 180 int mc65_summary; /* summary parameter */ 181 int mc65_mrvaddr; /* most recent vad */ 182 int mc65_istate1; /* internal state */ 183 int mc65_istate2; /* internal state */ 184 int mc65_pc; /* trapped pc */ 185 int mc65_psl; /* trapped psl */ 186}; 187 188int 189ka650_mchk(void *cmcf) 190{ 191 struct mc650frame *mcf = (struct mc650frame *)cmcf; 192 u_int type = mcf->mc65_summary; 193 u_int i; 194 char sbuf[256]; 195 196 printf("machine check %x", type); 197 if (type >= 0x80 && type <= 0x83) 198 type -= (0x80 + 11); 199 if (type < NMC650 && mc650[type]) 200 printf(": %s", mc650[type]); 201 printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n", 202 mcf->mc65_mrvaddr, mcf->mc65_istate1, mcf->mc65_istate2, 203 mcf->mc65_pc, mcf->mc65_psl); 204 snprintb(sbuf, sizeof(sbuf), DMASER_BITS, ka650merr_ptr->merr_dser); 205 printf("dmaser=%s qbear=0x%x dmaear=0x%x\n", sbuf, 206 (int)ka650merr_ptr->merr_qbear, 207 (int)ka650merr_ptr->merr_dear); 208 ka650merr_ptr->merr_dser = DSER_CLEAR; 209 210 i = mfpr(PR_CAER); 211 mtpr(CAER_MCC | CAER_DAT | CAER_TAG, PR_CAER); 212 if (i & CAER_MCC) { 213 printf("cache 1 "); 214 if (i & CAER_DAT) { 215 printf("data"); 216 i = cache1data; 217 cache1data = time_second; 218 } 219 if (i & CAER_TAG) { 220 printf("tag"); 221 i = cache1tag; 222 cache1tag = time_second; 223 } 224 } else if ((i & CAER_MCD) || (ka650merr_ptr->merr_errstat & MEM_CDAL)) { 225 printf("CDAL"); 226 i = cdalerr; 227 cdalerr = time_second; 228 } 229 if (time_second - i < 7) { 230 ka650setcache(CACHEOFF); 231 printf(" parity error: cacheing disabled\n"); 232 } else { 233 printf(" parity error: flushing cache\n"); 234 ka650setcache(CACHEON); 235 } 236 /* 237 * May be able to recover if type is 1-4, 0x80 or 0x81, but 238 * only if FPD is set in the saved PSL, or bit VCR in Istate2 239 * is clear. 240 */ 241 if ((type > 0 && type < 5) || type == 11 || type == 12) { 242 if ((mcf->mc65_psl & PSL_FPD) 243 || !(mcf->mc65_istate2 & IS2_VCR)) { 244 ka650_memerr(); 245 return 0; 246 } 247 } 248 return -1; 249} 250 251/* 252 * Make sure both caches are off and not in diagnostic mode. Clear the 253 * 2nd level cache (by writing to each quadword entry), then enable it. 254 * Enable 1st level cache too. 255 */ 256void 257ka650setcache(int state) 258{ 259 int syssub = GETSYSSUBT(vax_siedata); 260 int i; 261 262 /* 263 * Before doing anything, disable the cache. 264 */ 265 mtpr(0, PR_CADR); 266 if (syssub != VAX_SIE_KA640) 267 ka650cbd_ptr->cbd_cacr = CACR_CPE; 268 269 /* 270 * Check what we want to do, enable or disable. 271 */ 272 if (state == CACHEON) { 273 mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR); 274 if (syssub != VAX_SIE_KA640) { 275 for (i = 0; 276 i < (KA650_CACHESIZE / sizeof(KA650_CACHE_ptr[0])); 277 i += 2) 278 KA650_CACHE_ptr[i] = 0; 279 ka650cbd_ptr->cbd_cacr = CACR_CEN; 280 } 281 } 282} 283 284void 285ka650_halt(void) 286{ 287 ka650ssc_ptr->ssc_cpmbx = CPMB650_DOTHIS | CPMB650_HALT; 288 __asm("halt"); 289} 290 291void 292ka650_reboot(int arg) 293{ 294 ka650ssc_ptr->ssc_cpmbx = CPMB650_DOTHIS | CPMB650_REBOOT; 295} 296