📄 kn02ba.c
字号:
*/kn02ba_print_consinfo(p)struct kn02ba_consinfo_t *p;{ int simm, byte; u_int memreg; /* * If console is a graphics device, * force printf messages directly to screen. */ printstate |= PANICPRINT; switch (p->pkt_type) { case KN02BA_ESRPKT: cprintf("\nException condition\n"); cprintf("\tCause reg\t= 0x%x\n", p->pkt.esrp.cause); cprintf("\tException PC\t= 0x%x\n", p->pkt.esrp.epc); cprintf("\tStatus reg\t= 0x%x\n", p->pkt.esrp.status); cprintf("\tBad virt addr\t= 0x%x\n", p->pkt.esrp.badva); cprintf("\tStack ptr\t= 0x%x\n", p->pkt.esrp.sp); cprintf("\tSystem Support reg = 0x%x\n", p->pkt.esrp.ssr); cprintf("\tSystem Interrupt reg = 0x%x\n", p->pkt.esrp.sir); cprintf("\tSystem Interrupt Mask reg = 0x%x\n", p->pkt.esrp.sirm); break; case KN02BA_MEMPKT: memreg = p->pkt.memp.memreg; cprintf("\nMemory Parity Error\n"); simm = (memreg >> SIMMOFF) & 0xf; cprintf("\tSIMM (module number)\t= BANK %d, %s\n", simm/2, ((simm & 0x1) ? "D16-31" : "D0-15")); if (((memreg >> TYPEOFF) & HARDPAR) == HARDPAR) cprintf("\tHard error\t\n"); else if (((memreg >> TYPEOFF) & SOFTPAR) == SOFTPAR) cprintf("\tSoft error\t\n"); else cprintf("\tTransient error\t\n"); if (simm & 0x1) { /* D16-31(high) simm: high half word */ if ((memreg >> BYTEOFF) & 0x1) byte = 3; else byte = 2; } else { /* D0-15(low) simm: low half word */ if ((memreg >> BYTEOFF) & 0x1) byte = 1; else byte = 0; } cprintf("\tByte in error (0-3)\t= %d\n", byte); cprintf("\t%s bit error\n", ((memreg >> DPOFF) & 0x1) ? "Parity" : "Data"); cprintf("\tTransient errors for this SIMM\t= %d\n", kn02ba_tcount[simm]); cprintf("\tSoft errors for this SIMM\t= %d\n", kn02ba_scount[simm]); cprintf("\tHard errors for this SIMM\t= %d\n", kn02ba_hcount[simm]); cprintf("\tPhysical address of error\t= 0x%x\n", p->pkt.memp.pa); cprintf("\tException PC\t\t\t= 0x%x\n", p->pkt.memp.epc); cprintf("\tVirtual address of error\t= 0x%x\n", p->pkt.memp.badva); break; default: cprintf("bad print_consinfo \n"); break; }}kn02ba_isolate_memerr(memerr_status) struct tc_memerr_status *memerr_status;{ unsigned memreg; int ep[EF_SIZE/4]; if (btop((int)memerr_status->pa) >= physmem) return (-1); /* zero out these since they are not pertinent */ /* for this type of error */ ep[EF_EPC] = 0; ep[EF_BADVADDR] = 0; memreg = kn02ba_isolatepar(memerr_status->pa, memerr_status->va, memerr_status->blocksize); memerr_status->errtype = TC_MEMERR_NOERROR; if (((memreg >> TYPEOFF) & HARDPAR) == HARDPAR) memerr_status->errtype = TC_MEMERR_HARD; else if (((memreg >> TYPEOFF) & SOFTPAR) == SOFTPAR) memerr_status->errtype = TC_MEMERR_SOFT; else if (((memreg >> TYPEOFF) & TRANSPAR) == TRANSPAR) memerr_status->errtype = TC_MEMERR_TRANS; if (memerr_status->log == TC_LOG_MEMERR) { kn02ba_logmempkt(EL_PRISEVERE, ep, memreg, memerr_status->pa); kn02ba_consprint(KN02BA_MEMPKT, ep, memreg, memerr_status->pa, 0, 0, 0); }}/* * Isolate a memory parity error to which SIMM is in error. * This routine is machine specific, in that it "knows" how the memory * is laid out, i.e. how to convert a physical address to a module number. * * Block faults from occuring while we isolate the parity error by using * "nofault" facility thru the bbadaddr routine. */unsignedkn02ba_isolatepar(pa, va, blocksize) register caddr_t pa; /* the phys addr to convert to a SIMM */ caddr_t va; /* the virtual addr of the error */ int blocksize; /* the size of the block error occured in */{ register int i; /* loop index */ register int *blockaddr;/* address of the beginning of block in error */ register int *addr; /* increment thru the block w/ parity error */ register char *baddr; /* increment thru the word w/ parity error */ unsigned memreg; /* collection of memory error info */ int low; /* true if its the D0-15(low) SIMM */ int simm; /* which simm had the error */ register int allzeros; /* true if parity err occurs on all 0's write */ register int allones; /* true if parity err occurs on all 1's write */ register int oneone; /* true if parity err occurs on 1 1 write */ int dp; /* 0 for data bit, 1 for parity bit */ int type; /* error type: transient, soft, hard */ int byte; /* 0 for low byte; 1 for high byte in word */ int bank; int banksize; int parityerr; int blockcnt; /* * Round physical address to beginning of block */ blockaddr = (int *)(PHYS_TO_K1((int)pa & ~((blocksize << 2) - 1))); addr = blockaddr; for (blockcnt = 0; blockcnt < blocksize; blockcnt++, addr++) { type = 0; dp = 0; /* * Do badaddr probe on addr (a few times), * to see if it was only a transient. */ parityerr = 0; for (i = 0; i < 4; i++) { if (bbadaddr(addr, 4)) { parityerr = 1; break; } } if (!parityerr) { /* if no error, try the next word */ continue; } /* * Isolate the parity error to which SIMM is in error (which byte in * the word) and isolate the type of error: soft or hard, data bit * or parity bit. * * This is done by writing (& reading) each byte in the word first * with all 0's then with all 1's (0xff) then with one 1 (0x1). * * Use k1 address in order not to get TLBMOD exception when writing * shared memory space. */ for (i = 0, baddr = (char *)addr; i < 4; i++, baddr += 1) { allzeros = 0; *baddr = 0x00; if (bbadaddr(baddr, 1)) allzeros = 1; allones = 0; *baddr = 0xff; if (bbadaddr(baddr, 1)) allones = 1; oneone = 0; *baddr = 0x1; if (bbadaddr(baddr, 1)) oneone = 1; /* * If all 3 reads caused the error then this is the wrong * byte, go on to the next byte */ if (allzeros && allones && oneone) continue; /* * If only one of the allones/allzeros patterns caused a * parity error, then we have a hard data bit stuck to * zero or one. */ if ((allzeros && !allones && !oneone) || (allones && !allzeros && !oneone)) { type = HARDPAR; break; } /* * If only the "oneone" (0x1) pattern caused a parity error, * then we have a parity bit stuck to zero. * If only the "oneone" (0x1) pattern did NOT cause a parity * error then we have a parity bit stuck to one. */ if ((oneone && !allzeros && !allones) || (allzeros && allones && !oneone)) { type = HARDPAR; dp = 1; break; } /* * If no parity error on all 3 patterns then we had a soft * parity error in one of the data bits or in the parity bit * of this byte. */ if (!allzeros && !allones && !oneone) { type = SOFTPAR; break; } } /* * If i is 0 or 1, parity error is on the D0-15(low) SIMM. * If i is 2 or 3, parity error is on the D16-31(high) SIMM. * Also record high or low byte position in half-word. */ switch (i) { case 0: byte = 0; low = 1; break; case 1: byte = 1; low = 1; break; case 2: byte = 0; low = 0; break; case 3: default: byte = 1; low = 0; break; } /* we found the bad word, now determine which simm */ break; } /* if none of the words checked found an error, the error must */ /* have been a transient parity error. */ if (!parityerr) { unsigned int mer; type = TRANSPAR; mer = *(u_int *)(PHYS_TO_K1(KN02BA_MEM_ERR)); mer &= LAST_BYTE_ERR_MASK; if (mer & 0x800) { byte = 1; low = 0; } else if (mer & 0x400) { byte = 0; low = 0; } else if (mer & 0x200) { byte = 1; low = 1; } else { byte = 0; low = 1; } /* clear error bits */ *(u_int *)(PHYS_TO_K1(KN02BA_MEM_ERR)) = 0; baddr = (char *)blockaddr; } if (*((u_int *)PHYS_TO_K1(KN02BA_MEM_SIZE)) & KN02BA_16MB_MEM) banksize = 16 * 1024 * 1024; else banksize = 4 * 1024 * 1024; /* There are 8 banks, numbered 0 - 7 */ bank = (int)svtophy(baddr) / banksize; /* There are 16 simms, numbered 0 - 15 */ if (low) simm = (bank * 2); else simm = (bank * 2) + 1; /* * Increment error counts */ switch (type) { case TRANSPAR: default: kn02ba_tcount[simm]++; if (kn02ba_tcount[simm] > 255) { mprintf("Transient parity error count on simm in BANK # %d, %s reached 255, reset to zero.\n", bank, (low ? "D0-15" : "D16-31")); kn02ba_tcount[simm] = 0; } break; case SOFTPAR: kn02ba_scount[simm]++; break; case HARDPAR: kn02ba_hcount[simm]++; break; } memreg = MEMREGFMT(simm, type, byte, dp, kn02ba_tcount[simm], kn02ba_scount[simm], kn02ba_hcount[simm]); return(memreg);}#ifdef ERRLOG_DEBUG#define NO_TEST 0#define HARD_PAR_TEST 1#define SOFT_PAR_TEST 2#define TRANS_PAR_TEST 3#define WTO_TEST 4#define TRAP_TEST 5#define UNALIGNED_TEST 6#define RTMO_TEST 7int kn02ba_errlog; u_int dummy;kn02ba_errlog_testing(){ u_char *addr; int i, cnt; switch (kn02ba_errlog) { case NO_TEST: break; case HARD_PAR_TEST: cprintf("value of MER = 0x%x\n", *(u_int *)(PHYS_TO_K1(KN02BA_MEM_ERR))); cprintf("executing HARD_PAR_TEST (cached)\n"); /* read all of the last 4 meg trying to find */ /* bad memory */ addr = (u_char *)(0x81c00000); for (i = 0; i < 0x400000; i++, addr++) { *addr = 0x0; dummy = *addr; if (dummy != 0x0) cprintf("dummy (%d) != 0x0, addr = 0x%x\n", dummy, addr); *addr = 0xff; dummy = *addr; if (dummy != 0xff) cprintf("dummy (%d) != 0xff, addr = 0x%x\n", dummy, addr); *addr = 0x1; dummy = *addr; if (dummy != 0x1) cprintf("dummy (%d) != 0x1, addr = 0x%x\n", dummy, addr); *addr = 0xaa; dummy = *addr; if (dummy != 0xaa) cprintf("dummy (%d) != 0xaa, addr = 0x%x\n", dummy, addr); *addr = 0x55; dummy = *addr; if (dummy != 0x55) cprintf("dummy (%d) != 0x55, addr = 0x%x\n", dummy, addr); } cprintf("executing HARD_PAR_TEST (uncached)\n"); addr = (u_char *)(0xa1c00000); for (i = 0; i < 0x400000; i++, addr++) { *addr = 0x0; dummy = *addr; if (dummy != 0x0) cprintf("dummy (%d) != 0x0, addr = 0x%x\n", dummy, addr); *addr = 0xff; dummy = *addr; if (dummy != 0xff) cprintf("dummy (%d) != 0xff, addr = 0x%x\n", dummy, addr); *addr = 0x1; dummy = *addr; if (dummy != 0x1) cprintf("dummy (%d) != 0x1, addr = 0x%x\n", dummy, addr); *addr = 0xaa; dummy = *addr; if (dummy != 0xaa) cprintf("dummy (%d) != 0xaa, addr = 0x%x\n", dummy, addr); *addr = 0x55; dummy = *addr; if (dummy != 0x55) cprintf("dummy (%d) != 0x55, addr = 0x%x\n", dummy, addr); } cprintf("executing HARD_PAR_TEST (addr bit)\n"); addr = (u_char *)(0xa1c00000); cnt = 0; while (cnt < 0x400000) { for (i = 0; ((i < 254) && (cnt < 0x400000)); i++, cnt++) *addr++ = i; } addr = (u_char *)(0xa1c00000); cnt = 0; while (cnt < 0x400000) { for (i = 0; ((i < 254) && (cnt < 0x400000)); i++, cnt++) { dummy = *addr++; if (dummy != i) { cprintf("dummy (%x) != i (%x), addr = %x\n", dummy, i, addr); } } } cprintf("done\n"); break; case SOFT_PAR_TEST: break; case TRANS_PAR_TEST: printf("isolatepar returns %x\n", kn02ba_isolatepar(0x010205f8, 0, 4)); break; case WTO_TEST: cprintf("executing WTO_TEST\n"); /* write to turbo slot 0 */ *(u_int *)(0xb0000000) = 0; break; case TRAP_TEST: cprintf("executing TRAP_TEST\n"); dummy = *(u_int *) 0; break; case UNALIGNED_TEST: cprintf("executing UNALIGNED_TEST\n"); dummy = *(u_int *)(0x80000002); break; case RTMO_TEST: cprintf("executing RTMO_TEST\n"); dummy = *(u_int *)(0xb0000000); break; default: break; } kn02ba_errlog = 0; timeout(kn02ba_errlog_testing, (caddr_t) 0, 5 * hz);}#endif /* ERRLOG_DEBUG */kn02ba_conf_clk_speed(){ register volatile struct rt_clock *rt =(struct rt_clock *)rt_clock_addr; register volatile int dummy; register int s, counter = 0; int save_rega, save_regb; s = splextreme(); /* allow TOY interrupt to get to the CPU */ *(u_int *)(PHYS_TO_K1(KN02BA_SIRM_ADDR)) = TOY_INTR; /* enable periodic interrupt */ save_rega = rt->rt_rega; save_regb = rt->rt_regb; rt->rt_rega = RTA_DV32K|RTA_4ms; rt->rt_regb = RTB_DMBINARY|RTB_24HR|RTB_PIE; /* clear any old interrupts */ dummy = rt->rt_regc; /* wait for start */ while ((get_cause() & SR_IBIT6) == 0); dummy = rt->rt_regc; /* wait for finish and count */ while ((get_cause() & SR_IBIT6) == 0) counter++; dummy = rt->rt_regc; rt->rt_rega = save_rega; rt->rt_regb = save_regb; splx(s); return (counter);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -