1 /* $NetBSD: ka860.c,v 1.34 2010/12/14 23:44:49 matt Exp $ */ 2 /* 3 * Copyright (c) 1986, 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * @(#)ka860.c 7.4 (Berkeley) 12/16/90 31 */ 32 33 /* 34 * VAX 8600 specific routines. 35 * Also contains abus spec's and memory init routines. 36 * 37 * Todo: Set up all four console lines in a VAX8600. 38 * This is: local, remote, EMM and logical. 39 * 40 * ABus code added by Johnny Billquist 2010 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: ka860.c,v 1.34 2010/12/14 23:44:49 matt Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/cpu.h> 49 #include <sys/device.h> 50 51 #include <machine/clock.h> 52 #include <machine/nexus.h> 53 #include <machine/ioa.h> 54 #include <machine/sid.h> 55 #include <machine/mainbus.h> 56 57 #include <vax/vax/gencons.h> 58 59 void crlattach(void); 60 61 static void ka86_memerr(void); 62 static int ka86_mchk(void *); 63 static void ka86_reboot(int); 64 static void ka86_clrf(void); 65 static void ka860_conf(void); 66 static void ka86_attach_cpu(device_t); 67 static int abus_mainbus_match(device_t, cfdata_t, void *); 68 static void abus_mainbus_attach(device_t, device_t, void*); 69 static int abus_print(void *, const char *); 70 71 static const char * const ka86_devs[] = { "cpu", "abus", NULL }; 72 73 const struct cpu_dep ka860_calls = { 74 .cpu_mchk = ka86_mchk, 75 .cpu_memerr = ka86_memerr, 76 .cpu_conf = ka860_conf, 77 .cpu_gettime = generic_gettime, 78 .cpu_settime = generic_settime, 79 .cpu_vups = 6, /* ~VUPS */ 80 .cpu_scbsz = 10, /* SCB pages */ 81 .cpu_reboot = ka86_reboot, 82 .cpu_clrf = ka86_clrf, 83 .cpu_devs = ka86_devs, 84 .cpu_attach_cpu = ka86_attach_cpu, 85 }; 86 87 /* 88 * 8600 memory register (MERG) bit definitions 89 */ 90 #define M8600_ICRD 0x400 /* inhibit crd interrupts */ 91 #define M8600_TB_ERR 0xf00 /* translation buffer error mask */ 92 93 /* 94 * MDECC register 95 */ 96 #define M8600_ADDR_PE 0x080000 /* address parity error */ 97 #define M8600_DBL_ERR 0x100000 /* data double bit error */ 98 #define M8600_SNG_ERR 0x200000 /* data single bit error */ 99 #define M8600_BDT_ERR 0x400000 /* bad data error */ 100 101 /* 102 * ESPA register is used to address scratch pad registers in the Ebox. 103 * To access a register in the scratch pad, write the ESPA with the address 104 * and then read the ESPD register. 105 * 106 * NOTE: In assmebly code, the mfpr instruction that reads the ESPD 107 * register must immedately follow the mtpr instruction that setup 108 * the ESPA register -- per the VENUS processor register spec. 109 * 110 * The scratchpad registers that are supplied for a single bit ECC 111 * error are: 112 */ 113 #define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */ 114 #define SPAD_MSTAT2 0x26 /* scratch pad mstat2 register */ 115 #define SPAD_MDECC 0x27 /* scratch pad mdecc register */ 116 #define SPAD_MEAR 0x2a /* scratch pad mear register */ 117 118 #define M8600_MEMERR(mdecc) ((mdecc) & 0x780000) 119 #define M8600_HRDERR(mdecc) ((mdecc) & 0x580000) 120 #define M8600_SYN(mdecc) (((mdecc) >> 9) & 0x3f) 121 #define M8600_ADDR(mear) ((mear) & 0x3ffffffc) 122 #define M8600_ARRAY(mear) (((mear) >> 22) & 0x0f) 123 124 #define M8600_MDECC_BITS \ 125 "\20\27BAD_DT_ERR\26SNG_BIT_ERR\25DBL_BIT_ERR\24ADDR_PE" 126 127 #define M8600_MSTAT1_BITS "\20\30CPR_PE_A\27CPR_PE_B\26ABUS_DT_PE\ 128 \25ABUS_CTL_MSK_PE\24ABUS_ADR_PE\23ABUS_C/A_CYCLE\22ABUS_ADP_1\21ABUS_ADP_0\ 129 \20TB_MISS\17BLK_HIT\16C0_TAG_MISS\15CHE_MISS\14TB_VAL_ERR\13TB_PTE_B_PE\ 130 \12TB_PTE_A_PE\11TB_TAG_PE\10WR_DT_PE_B3\7WR_DT_PE_B2\6WR_DT_PE_B1\ 131 \5WR_DT_PE_B0\4CHE_RD_DT_PE\3CHE_SEL\2ANY_REFL\1CP_BW_CHE_DT_PE" 132 133 #define M8600_MSTAT2_BITS "\20\20CP_BYT_WR\17ABUS_BD_DT_CODE\10MULT_ERR\ 134 \7CHE_TAG_PE\6CHE_TAG_W_PE\5CHE_WRTN_BIT\4NXM\3CP-IO_BUF_ERR\2MBOX_LOCK" 135 136 /* log CRD errors */ 137 void 138 ka86_memerr(void) 139 { 140 int mdecc, mear, mstat1, mstat2, array; 141 142 /* 143 * Scratchpad registers in the Ebox must be read by 144 * storing their ID number in ESPA and then immediately 145 * reading ESPD's contents with no other intervening 146 * machine instructions! 147 * 148 * The asm's below have a number of constants which 149 * are defined correctly above and in mtpr.h. 150 */ 151 __asm("mtpr $0x27,$0x4e; mfpr $0x4f,%0" : "=g" (mdecc)); 152 /* must acknowledge interrupt? */ 153 if (M8600_MEMERR(mdecc)) { 154 __asm("mtpr $0x2a,$0x4e; mfpr $0x4f,%0" : "=g" (mear)); 155 __asm("mtpr $0x25,$0x4e; mfpr $0x4f,%0" : "=g" (mstat1)); 156 __asm("mtpr $0x26,$0x4e; mfpr $0x4f,%0" : "=g" (mstat2)); 157 array = M8600_ARRAY(mear); 158 159 { 160 char sbuf[256], sbuf2[256]; 161 162 printf("mcr0: ecc error, addr %x (array %d) syn %x\n", 163 M8600_ADDR(mear), array, M8600_SYN(mdecc)); 164 165 snprintb(sbuf, sizeof(sbuf), M8600_MSTAT1_BITS, mstat1); 166 snprintb(sbuf2, sizeof(sbuf2), M8600_MSTAT2_BITS, mstat2); 167 printf("\tMSTAT1 = %s\n\tMSTAT2 = %s\n", sbuf, sbuf2); 168 } 169 170 mtpr(0, PR_EHSR); 171 mtpr(mfpr(PR_MERG) | M8600_ICRD, PR_MERG); 172 } 173 } 174 175 #define NMC8600 7 176 const char * const mc8600[] = { 177 "unkn type", "fbox error", "ebox error", "ibox error", 178 "mbox error", "tbuf error", "mbox 1D error" 179 }; 180 /* codes for above */ 181 #define MC_FBOX 1 182 #define MC_EBOX 2 183 #define MC_IBOX 3 184 #define MC_MBOX 4 185 #define MC_TBUF 5 186 #define MC_MBOX1D 6 187 188 /* error bits */ 189 #define MBOX_FE 0x8000 /* Mbox fatal error */ 190 #define FBOX_SERV 0x10000000 /* Fbox service error */ 191 #define IBOX_ERR 0x2000 /* Ibox error */ 192 #define EBOX_ERR 0x1e00 /* Ebox error */ 193 #define MBOX_1D 0x81d0000 /* Mbox 1D error */ 194 #define EDP_PE 0x200 195 196 struct mc8600frame { 197 int mc86_bcnt; /* byte count == 0x58 */ 198 int mc86_ehmsts; 199 int mc86_evmqsav; 200 int mc86_ebcs; 201 int mc86_edpsr; 202 int mc86_cslint; 203 int mc86_ibesr; 204 int mc86_ebxwd1; 205 int mc86_ebxwd2; 206 int mc86_ivasav; 207 int mc86_vibasav; 208 int mc86_esasav; 209 int mc86_isasav; 210 int mc86_cpc; 211 int mc86_mstat1; 212 int mc86_mstat2; 213 int mc86_mdecc; 214 int mc86_merg; 215 int mc86_cshctl; 216 int mc86_mear; 217 int mc86_medr; 218 int mc86_accs; 219 int mc86_cses; 220 int mc86_pc; /* trapped pc */ 221 int mc86_psl; /* trapped psl */ 222 }; 223 224 /* machine check */ 225 int 226 ka86_mchk(void *cmcf) 227 { 228 struct mc8600frame *mcf = (struct mc8600frame *)cmcf; 229 int type; 230 231 if (mcf->mc86_ebcs & MBOX_FE) 232 mcf->mc86_ehmsts |= MC_MBOX; 233 else if (mcf->mc86_ehmsts & FBOX_SERV) 234 mcf->mc86_ehmsts |= MC_FBOX; 235 else if (mcf->mc86_ebcs & EBOX_ERR) { 236 if (mcf->mc86_ebcs & EDP_PE) 237 mcf->mc86_ehmsts |= MC_MBOX; 238 else 239 mcf->mc86_ehmsts |= MC_EBOX; 240 } else if (mcf->mc86_ehmsts & IBOX_ERR) 241 mcf->mc86_ehmsts |= MC_IBOX; 242 else if (mcf->mc86_mstat1 & M8600_TB_ERR) 243 mcf->mc86_ehmsts |= MC_TBUF; 244 else if ((mcf->mc86_cslint & MBOX_1D) == MBOX_1D) 245 mcf->mc86_ehmsts |= MC_MBOX1D; 246 247 type = mcf->mc86_ehmsts & 0x7; 248 printf("machine check %x: %s\n", type, 249 type < NMC8600 ? mc8600[type] : "???"); 250 printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n", 251 mcf->mc86_ehmsts, mcf->mc86_evmqsav, mcf->mc86_ebcs, 252 mcf->mc86_edpsr, mcf->mc86_cslint); 253 printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n", 254 mcf->mc86_ibesr, mcf->mc86_ebxwd1, mcf->mc86_ebxwd2, 255 mcf->mc86_ivasav, mcf->mc86_vibasav); 256 printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n", 257 mcf->mc86_esasav, mcf->mc86_isasav, mcf->mc86_cpc, 258 mcf->mc86_mstat1, mcf->mc86_mstat2, mcf->mc86_mdecc); 259 printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n", 260 mcf->mc86_merg, mcf->mc86_cshctl, mcf->mc86_mear, 261 mcf->mc86_medr, mcf->mc86_accs, mcf->mc86_cses); 262 printf("\tpc %x psl %x\n", mcf->mc86_pc, mcf->mc86_psl); 263 mtpr(0, PR_EHSR); 264 return (MCHK_PANIC); 265 } 266 267 struct ka86 { 268 unsigned snr:12, 269 plant:4, 270 eco:7, 271 v8650:1, 272 type:8; 273 }; 274 275 /* The manufacturing plant information comes from EK-86XV1-MG-003 276 * VAX 86XX System Maintenance Guide 277 * /bqt 278 */ 279 280 static const char * const manuf[] = {"Unknown", 281 "Galway, Ireland", 282 "Franklin, MA", 283 "Burlington, VT", 284 "Marlboro, MA"}; 285 286 const int mindex[] = {0,1,1,1, 0,2,2,2, 0,0,3,3, 3,4,4,4}; 287 288 void 289 ka860_conf(void) 290 { 291 /* Enable cache */ 292 mtpr(3, PR_CSWP); 293 294 /* enable CRD reports */ 295 mtpr(mfpr(PR_MERG) & ~M8600_ICRD, PR_MERG); 296 } 297 298 void 299 ka86_attach_cpu(device_t self) 300 { 301 struct ka86 * const ka86 = (void *)&vax_cpudata; 302 int fpa; 303 304 aprint_naive(": KA86%d, S/N %d, Rev. %c, manufactured in %s.\n", 305 ka86->v8650 ? 5 : 0, ka86->snr, ka86->eco+64, 306 manuf[mindex[ka86->plant]]); 307 aprint_normal(": KA86%d, S/N %d, Rev. %c, manufactured in %s.\n", 308 ka86->v8650 ? 5 : 0, ka86->snr, ka86->eco+64, 309 manuf[mindex[ka86->plant]]); 310 fpa = mfpr(PR_ACCS); 311 if (fpa & 255) { 312 aprint_naive_dev(self, 313 "FPA present: type %d, serial number %d\n", 314 fpa & 255, fpa >> 16); 315 aprint_normal_dev(self, 316 "FPA present: type %d, serial number %d\n", 317 fpa & 255, fpa >> 16); 318 mtpr(0x8000, PR_ACCS); 319 } else { 320 aprint_naive_dev(self, "no FPA\n"); 321 aprint_normal_dev(self, "no FPA\n"); 322 } 323 324 /* 325 * Init CPU. 326 * Attach crl first. 327 */ 328 329 crlattach(); 330 } 331 332 /* 333 * Clear restart flag. 334 */ 335 void 336 ka86_clrf(void) 337 { 338 /* 339 * We block all interrupts here so that there won't be any 340 * interrupts for an ongoing printout. 341 */ 342 int s = splhigh(), old = mfpr(PR_TXCS); 343 344 #define WAIT while ((mfpr(PR_TXCS) & GC_RDY) == 0) ; 345 346 WAIT; 347 348 /* Enable channel to console */ 349 mtpr(GC_LT|GC_WRT, PR_TXCS); 350 WAIT; 351 352 /* clear warm start flag */ 353 mtpr(GC_CWFL, PR_TXDB); 354 WAIT; 355 356 /* clear cold start flag */ 357 mtpr(GC_CCFL, PR_TXDB); 358 WAIT; 359 360 /* restore old state */ 361 mtpr(old|GC_WRT, PR_TXCS); 362 splx(s); 363 } 364 365 void 366 ka86_reboot(int howto) 367 { 368 WAIT; 369 370 /* Enable channel to console */ 371 mtpr(GC_LT|GC_WRT, PR_TXCS); 372 WAIT; 373 374 mtpr(GC_BTFL, PR_TXDB); 375 WAIT; 376 377 __asm("halt"); 378 } 379 380 381 CFATTACH_DECL_NEW(abus_mainbus, 0, 382 abus_mainbus_match, abus_mainbus_attach, NULL, NULL); 383 384 int abus_mainbus_match(device_t parent, cfdata_t self, void *aux) 385 { 386 return (vax_bustype == VAX_ABUS); 387 } 388 389 void abus_mainbus_attach(device_t parent, device_t self, void *aux) 390 { 391 struct mainbus_attach_args * const ma = aux; 392 struct abus_attach_args aa; 393 394 unsigned int tmp; 395 volatile struct sbia_regs *sbiar; 396 397 int type, i; 398 399 aprint_naive("\n"); 400 aprint_normal("\n"); 401 402 for (i = 0; i < NIOA8600; i++) { 403 sbiar = (struct sbia_regs *)vax_map_physmem((paddr_t)IOA8600(i), 404 (IOAMAPSIZ / VAX_NBPG)); 405 if (badaddr(sbiar, 4)) { 406 vax_unmap_physmem((vaddr_t)sbiar, 407 (IOAMAPSIZ / VAX_NBPG)); 408 continue; 409 } 410 411 tmp = sbiar->sbi_cfg; 412 type = tmp & IOA_TYPMSK; 413 414 switch (type) { 415 416 case IOA_SBIA: 417 418 aa.aa_base = (bus_addr_t)(SBIA8600(i)); 419 aa.aa_num = i; 420 aa.aa_name = "sbi"; 421 aa.aa_type = tmp; 422 aa.aa_iot = ma->ma_iot; 423 aa.aa_dmat = ma->ma_dmat; 424 425 sbiar->sbi_errsum = -1; 426 sbiar->sbi_error = 0x1000; 427 sbiar->sbi_fltsts = 0xc0000; 428 429 config_found(self, &aa, abus_print); 430 break; 431 432 default: 433 aprint_naive("IOAdapter %#x unsupported\n", type); 434 aprint_normal("IOAdapter %#x unsupported\n", type); 435 } 436 437 vax_unmap_physmem((vaddr_t)sbiar, (IOAMAPSIZ / VAX_NBPG)); 438 } 439 } 440 441 int abus_print(void *aux, const char *name) 442 { 443 struct abus_attach_args *aa = aux; 444 445 if (name) { 446 aprint_naive("%s%d at %s\n", aa->aa_name, aa->aa_num, name); 447 aprint_normal("%s%d at %s\n", aa->aa_name, aa->aa_num, name); 448 } 449 return UNSUPP; 450 } 451