📄 kn220.c
字号:
{ esr[0].esr_mesr = 0xffffffff; } } else { /* R3000 Cycle */ pa = esr[0].esr_mear; if((((esr[0].esr_mear & BIT29) == 1)&&((esr[0].esr_mear & BIT28) == 0)) || (((esr[0].esr_mear & BIT29) == 0)&&((esr[0].esr_mear & BIT28) == 1))) { /* I/O Cycle */ esr[0].esr_mesr = 0xffffffff; /* Zap mesr to make ECC Ok*/ } else { /* Memory Cycle */ if((esr[0].esr_mear & KN220_NXM) == 1) esr[0].esr_mesr = 0xffffffff; } } /* Its a Kernel space error * * Look in the Memory Error Syndrome Register and if the error * is a single bit error (LER or HER bit set to zero) then * we will not panic. */ if( (( esr[0].esr_mesr & KN220_LER ) == 0) || (( esr[0].esr_mesr & KN220_HER) == 0)) { /* Single bit error case- * Look in the Sbit_error array to see if the * error has hapened in the last 15 min. If it * has the address will be in here and we * will not log the error. */ for (i=0;i < SBIT_SIZE;i++) { /* Return here because it was only a single bit * memory error and we don't want to panic the system. * But first check for multri bit first just * in case both single and multi were * set (no a valid case but who knows) */ if(Sbit_error[i] == esr[0].esr_mear) if( (( esr[0].esr_mesr & KN220_LME ) == 1) && (( esr[0].esr_mesr & KN220_HME) == 1)) return; } /* The address is not there so load it and go on * to log the error. */ for (i=0;i < SBIT_SIZE;i++) { if ((Sbit_error[i] != 0) && (i != SBIT_SIZE)) continue; if(i == (SBIT_SIZE - 1)) break; Sbit_error[i] = esr[0].esr_mear; kn220logmempkt(EL_PRISEVERE, ep, pa); } /* Return here because it was only a single bit * memory error and we don't want to panic the system. * But first check for multri bit first just * in case both single and multi were * set (no a valid case but who knows) */ if( (( esr[0].esr_mesr & KN220_LME ) == 1) && (( esr[0].esr_mesr & KN220_HME) == 1)) return; } /* Look for Multi bit ECC errors. If it is a * multi bit error bits (HME or LME) will be * zero in the memory error syndrome reister. */ if( (( esr[0].esr_mesr & KN220_LME ) == 0) || (( esr[0].esr_mesr & KN220_HME) == 0)) { /* MULTI BIT error */ kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(ESRPKT, ep, pa, 0); panic("Memory multi bit parity error"); } /* * if the low bit in the address is high its a NXM */ if( (esr[0].esr_mear & KN220_NXM) == 1 ){ /* * if we are still processing a previous interrupt * then simply crash. we don't queue these interrupts. */ if (CURRENT_CPUDATA->cpu_wto_event) { kn220logesrpkt(ep, esr, EL_PRISEVERE); kn220consprint(MEMPKT, ep, pa, 0); panic("nonexistant memory access"); } else { /* * capture error information in kn220consinfo. * softnet() interrupt will print this info * if panicing on the console. */ pcons = &kn220consinfo; pcons->pkt_type = ESRPKT; pcons->qbus = 0; pcons->pkt.cause = ep[EF_CAUSE]; pcons->pkt.epc = ep[EF_EPC]; pcons->pkt.sr = ep[EF_SR]; pcons->pkt.badvaddr = ep[EF_BADVADDR]; pcons->pkt.pa = pa; /* * capture log information in kn220log_errinfo. * softnet() interrupt will log this info * if panicing in the error log buffer. */ plog = &kn220log_errinfo; plog->pkt_type = ESRPKT; plog->cause = ep[EF_CAUSE]; plog->epc = ep[EF_EPC]; plog->sr = ep[EF_SR]; plog->badvaddr = ep[EF_BADVADDR]; plog->sp = ep[EF_SP]; plog->logesr.esr_dser = esr[0].esr_dser; plog->logesr.esr_qbear = esr[0].esr_qbear; plog->logesr.esr_dear = esr[0].esr_dear; plog->logesr.esr_cbtcr = esr[0].esr_cbtcr; plog->logesr.esr_isr = esr[0].esr_isr; plog->logesr.esr_ipcr = esr[0].esr_ipcr; plog->logesr.esr_mesr = esr[0].esr_mesr; plog->logesr.esr_mear = esr[0].esr_mear; CURRENT_CPUDATA->cpu_consinfo = (char *) &kn220consinfo; CURRENT_CPUDATA->cpu_log_errinfo = (char *) &kn220log_errinfo; CURRENT_CPUDATA->cpu_wto_pfn = btop(pa); CURRENT_CPUDATA->cpu_wto_event = 1; setsoftnet(); } }}/* Every 15 min. we want to "zap" the array that keeps track * of single bit ECC memory errors. We do this so that a location * which generates a single bit error does not flood the error log * if it stays in memory and get hit many, many times. This array * tries to limit the amount entries. After this array is zeroed * any new single bit errors will get logged. */kn220_ZSbit(){ int i; extern timeout(); extern int hz; for (i=0;i < SBIT_SIZE;i++) { Sbit_error[i] = 0; } /* Reschedule this routine to run in 15 min. */ timeout(kn220_ZSbit,0,15*60*hz);}/* In the DS_5500 we need to write to a memory location * to clear memory interrupts. This routine seems the best * way to do this? */int kn220badaddr(addr,len)caddr_t addr;int len;{ register int foo,s; #ifdef lint len=len;#endif lint s = splextreme(); *(int *)ISR = 0; foo = bbadaddr(addr,len); *(int *)PHYS_TO_K1(CLEAR_MEM_INTR) = 0; wbflush(); splx(s); return(foo);}/* The CQBIC can generate a memory type error interrupts. This routine checks * for the error and will crash the system. This routine is called from interrupt * if and only if the ISR bit 1 is set. Bit 1 of the ISR indicates a Qbus * posted memory error. The nofault code must clear this bit. */kn220_qbus_memerr(ep)register u_int *ep;{ u_long pa; int isr; /* Content of ISR */ int dser; /* Read content of Interrupt Status Register */ isr = *(int *)ISR; *(int *)ISR = 0; /* Acknowledge all error */ wbflush(); /* * Log DMA system error register, error address register, ..etc. */ esr[0].esr_dser = * (u_long *)KN220DSER; /* DMA Sys error register*/ esr[0].esr_qbear = * (u_long *)KN220QBEAR; /* Qbus error addr reg. */ esr[0].esr_dear = * (u_long *)KN220DEAR; /* DMA error addr reg. */ esr[0].esr_cbtcr = * (u_long *)KN220CBTCR; /* CDAL Bus Timeout */ esr[0].esr_mesr = * (u_long *)KN220MESR; /* Memory Error Syndrom Reg.*/ esr[0].esr_mear = * (u_long *)KN220MEAR; /* Memory Error Address Reg.*/ esr[0].esr_isr = isr; /* Interupt Status Reg. */ /* Clear the error bits */ *(u_long *)KN220DSER = 0xc0bd; *(u_long *)KN220CBTCR = 0xc0000000 | esr[0].esr_cbtcr; /* If the CQBIC reports nogrant or nxm then the address in * the dear is valid */ if (isr & ISR_CERR) { /* if the CQBIC reports a Q22 bus parity error OR bus time out the * Q22 bus the address is in the QBEAR (but left shift it 9). */ if( (esr[0].esr_dser & DSER_PARITY ) || ( esr[0].esr_dser & DSER_MEMTO )) pa = esr[0].esr_qbear << 9; if( (esr[0].esr_dser & DSER_NOGRNT ) || ( esr[0].esr_dser & DSER_NXM )) pa = esr[0].esr_dear << 9; /* Log a error log packet */ kn220logmempkt(EL_PRISEVERE, ep, pa); kn220consprint(MEMPKT, ep, pa, ITS_A_QBUS); /* * Q22 bus write cycle timeout after 10uS, * or Q22 bus parity error. * QBEAR contains Qbus physical address. */ dser = esr[0].esr_dser; if ( dser & DSER_PARITY ) panic("Q22 bus memory parity error"); if ( dser & DSER_MEMTO ) panic("Read bus timeout"); if ((dser & DSER_NXM)||(dser & DSER_MME)) { /* * DMA transfer to non-existent main * memory location. */ panic("DMA memory error"); } if (dser & DSER_NOGRNT) { /* * Q22 Bus does not return a bus grant * within the 10ms of the Bus request for a CPU * read or write cycle. */ panic("Q22 Bus Grant Timeout"); } /* Default case */ panic("Qbus Memory error"); /* END of CQBIC error code */ }}kn220_battery_status(){ register int i, *memid; int B1, B2; int iopres; /* * This routine is called by presto software * periodically. * * See h/presto.h for comments on the data structures involved. * * For DS5500 the NVRAM battery is the primary * and the H3602 battery is the secondary. * Both batteries must be operational for normal Prestoserve * operation. * * Get the battery status for the primary on the fly, the console * gives me the secondary status as it was at boot time. */ memid =(int *) KN220MIDR; nvram_batteries0.nv_nbatteries = 2; /* two batteries */ nvram_batteries0.nv_minimum_ok = 2; /* both must be good */ nvram_batteries0.nv_primary_mandatory = 1; /* primary must be good */ nvram_batteries0.nv_test_retries = 3; /* call this routine 3 times * for each "test" */ ssc_ptr = (struct ssc_regs *)PHYS_TO_K1(DEFAULT_SSC_PHYS); *memid = KN220BLOAD; /* Get old state */ wbflush(); DELAY(kn220_battdelay); iopres = *(int *)KN220IOPRES; /* Read content of IOPRES */ B1 = iopres & KN220_BOK; *memid = KN220JUMPER & KN220BLOAD; /* Update state */ wbflush(); DELAY(kn220_battdelay); iopres = *(int *)KN220IOPRES; /* Read content of IOPRES */ B2 = iopres & KN220_BOK; nvram_batteries0.nv_status[0] = BATT_OK; /* assume OK */ *memid = 0; /* Turn it off battery load*/ wbflush(); if (B1 == B2) /* check for NVRAM battery low */ { if (B1 != KN220_BOK) /* "DS5500 NVRAM battery backup disabled" */ /* battery will not back RAM */ nvram_batteries0.nv_status[0] = BATT_NONE; } else { /* "DS5500 NVRAM lost battery backup" */ /* low battery */ nvram_batteries0.nv_status[0] = BATT_ENABLED; } /* Bit 31 high is low H3602 * battery, zero is battery OK */ if (ssc_ptr->ssc_ssccr & 0x80000000) nvram_batteries0.nv_status[1] = BATT_ENABLED; else nvram_batteries0.nv_status[1] = BATT_OK; return(0);}int kn220_fakestatus = 0; /* set to 1 for old, bad ROMs */intkn220_nvram_status(){ int i; /* Status of NVRAM diagnostics * NVRAM_BAD 0 either read/write or read-only diagnostics * run unsuccessfully * NVRAM_RDWR 1 read/write diagnostics run successfully * NVRAM_RDONLY 2 read-only diagnostics run successfully * If the reply is NVRAM_RDONLY, then presto will attempt recovery, but * not allow normal operation. If the reply is NVRAM_BAD, presto will * offer the console operator a "halt or continue" choice. * */ if (kn220_fakestatus) return(NVRAM_RDWR); /* HACK UNTIL THE CONSOLE ROMS ARE UP TO DATE */ else { i = NVRAMSTATUS; return (i); }}#include "../h/socket.h"#include "../net/net/if.h"/* * Get the hardware E_net address for on-board ne0 and use it * to build a poor man's version of a unique processor ID. */u_intkn220_machineid(){ register struct ifnet *ifp = ifnet; struct ifdevea ifr; u_int i = 0; int error; if (ifnet == NULL) { printf("kn220: ifnet NULL\n"); return (i); } while (ifp != NULL) { if (ifp->if_name[0] == 'n' && ifp->if_name[1] == 'e' && ifp->if_unit == 0) { /* found ne0 */ error = (*ifp->if_ioctl)(ifp, SIOCRPHYSADDR, &ifr); if (error) return (i); i = (u_int)ifr.default_pa[2]; i = i << 8; i += (u_int)ifr.default_pa[3]; i = i << 8; i += (u_int)ifr.default_pa[4]; i = i << 8; i += (u_int)ifr.default_pa[5]; return (i); } ifp = ifp->if_next; } return (i);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -