📄 kn230.c
字号:
/* * get memory bank sizes for isloating parity errors. Can not * call it any sooner than this because it uses the values * calculated by mapinit which is called before this in the * startup routine. * */ kn230_getSIMMsizes(); /* *Initialize PROM environment entries (hwconf.promenv[0-5].name fields) */ hwconf_init(); /* * Report what system we are on */ printf("KN230 processor - system rev %d\n", (GETHRDREV(cpu_systype))); /* * Deal with the CPU and FPU */ coproc_find(); /* * probe for all the I/O contollers and * devices (DZ UART, LANCE, SII) */ kn230_config_devices(); /* * configure nvram option, this enables * Prestoserve if the nvram modules are present * */ kn230_config_nvram(); /* * configure the expansion option card * */ kn230_expansion_conf(); /* report console state * * report state of console security and failed attempts if secure. * report the state of HALT enable bit in the LED register * to the console so the user knows how it is currently * set, it can be changed through a prom env var. */ printf("console status: \n"); if ( *(int *)WEAR_ADDR & WEAR_SECURE) printf("\tsecurity mode disabled\n"); else { printf("\tsecurity can be used\n"); /* security enabled */ if ( *(int *)PASSWD_ADDR & PASSWD_FIELD ) /* passwd is set */ { printf("\tconsole password is set\n"); if ( *(int *)PASSWD_ADDR & PASSWD_FAILS ) printf("\tfailed attempts: %d\n", *(int *)PASSWD_ADDR &PASSWD_FAILS); } } if ( *(int *)LED_ADDR & KN230_LED0 ) printf("\thalt is enabled\n\n"); else printf("\treset is enabled\n\n"); /* * call transenable every 15 minutes to reenable transient partiy * error logging */ timeout (kn230transenable, (caddr_t) 0, kn230transintvl * hz); cold = 0; /* * Safe to take all interrupts now, turn them on. */ splnone(); return(0);}/****************************************************************************** * * kn230_config_devices: configure all system devices and controllers, * called by kn230_conf. * * - probe all I/O devices and controllers in one place * and set the appropriate states/flags for further use. * (LANCE, SII, I/O EXPANSION, DZ UART) * * On board devices sit on a virtual bus called the "ibus" * *****************************************************************************/kn230_config_devices() { int s; config_set_alive("ibus",0,0,0); /* * Probe the system console subsystem * * If the option card is not installed and the config file has * the devices in it nMDC > 1 and the mdc driver will attempt * to configure a non-existant device which results in a hang. * This case will probably only be hit during debug, but it * can also happen if the option board is removed after installation * and the kernel is not remade. */ if ( *(int *)WEAR_ADDR & WEAR_IOPRESENT ) /* not present */ { nMDC = 1 ; /* safeguard against config file error */ } /* if it is present - driver will configure all mdc devices */ ib_config_dev(PHYS_TO_K1(KN230_DZ0_CSR), KN230_DZ0_CSR, 0, "mdc",(int)scb+DZ_UART_INDEX); /* * Probe the sii based scsi bus. */ ib_config_cont(PHYS_TO_K1(KN230_SII),KN230_SII,0,"sii", (int)scb+SII_INDEX); /* * Config the Lance */ ib_config_dev(PHYS_TO_K1(KN230_LANCE),KN230_LANCE,0, "ln",PHYS_TO_K1((int)scb+LANCE_INDEX)); return(0);} /**************************************************************************** * * kn230_expansion_conf() * * configure the I/O expansion slot, called by kn230_conf * * check WEAR register IOPRESENT bit to see if option card * is present. if present, read option ID register and use * data file to map id number to option info. If id# is not * in kn230_option_data.c report configuration error, otherwise * use info to configure option card device(s). * * NOTE: The dc7085 device driver (mdc.c) is a special case. * It provides support for the console and the kn230 async * card devices for a total of three dc7085 devices. The driver * is already configured at this point, it is set up for * the probe and attach routines to just return, so it is * cool to configure them thru ib_config_dev. * ****************************************************************************/kn230_expansion_conf(){ extern struct kn230_option kn230_option[]; int option_id; int i=0; int found=0 ; u_int scb_addr, csr_addr; if ( !( *(int *)WEAR_ADDR & WEAR_IOPRESENT) ) { option_id = *(int *)OID_ADDR & OID_NUMBER_MSK ; printf("expansion option card present"); config_set_alive("ibus",0,0,0); for ( i=0 ; kn230_option[i].option_id != -1 ; i++) { if ( kn230_option[i].option_id == option_id) { found += 1; if (found > 2) { printf("data file error: only 2 devices per option\n"); break; } if (found == 1) { printf(": %s\n",kn230_option[i].option_name); csr_addr = kn230_option[i].exp0_csr; scb_addr = (int)scb+EXP0_INDEX; } else { scb_addr = (int)scb+EXP1_INDEX; csr_addr = kn230_option[i].exp1_csr; } if (csr_addr == 0) { printf("data file error: bad csr address\n"); found = 0; break; } if (nMDC>1) printf("\t"); /* for looks */ if ( kn230_option[i].type == 'D') { ib_config_dev(PHYS_TO_K1(csr_addr), csr_addr, 0, kn230_option[i].driver_name, scb_addr ); } else if ( kn230_option[i].type == 'C') { ib_config_cont(PHYS_TO_K1(csr_addr), csr_addr, 0, kn230_option[i].driver_name, scb_addr ); } else printf("data file error: type field incorrect\n"); } } if (found == 0) { printf("\nOPTION CARD NOT CONFIGURED\n"); printf("\tconfiguration error: could not match value in\n"); printf("\toption id register with entries in data file,\n"); printf("\tprobable cause is the 'iooption' console variable\n"); } } else printf("expansion option card not present\n");}/***************************************************************************** * * kn230_delay: MIPSMATE delay routine * * - delay for n microseconds * ****************************************************************************/int kn230_delay_mult = 11 ; /* optimized delay multiplier */kn230_delay(n) int n; /* number of usecs to delay for */{ register int N = kn230_delay_mult * (n); while (--N > 0); return(0);}/***************************************************************************** * * kn230_haltintr: Entry point for HALT interrupt * * call console prom halt routine to do the rest * *****************************************************************************/kn230_haltintr(ep)int *ep;{ prom_halt(ep) ;}/****************************************************************************** * * kn230_hardintr0() : Entry for interrupts from DZ UART or IO EXPAN CARD * * - determine source of interupt and dispatch it. * - must be in order of priority, handle only one * and get out, we will return here if more than * one IRQ bit is set, this will preserve priority. * *****************************************************************************/kn230_hardintr0(ep)int *ep;{extern int (*(scb[])) (); if ( *(int *)ICSR_ADDR & KN230_DZIRQ) (*(scb[DZ_UART_INDEX/4])) (ep,DZ_UART_INDEX/4); else if ( *(int *)ICSR_ADDR & KN230_EXPIRQ0) (*(scb[EXP0_INDEX/4])) (ep,EXP0_INDEX/4); else if ( *(int *)ICSR_ADDR & KN230_EXPIRQ1) (*(scb[EXP1_INDEX/4])) (ep,EXP1_INDEX/4); else printf("kn230: took stray interrupt on h/w intr level 0\n");}/****************************************************************************** * * kn230_hardintr1: Entry point for interrupts from LANCE or SII interrupts * * - determine source of interupt and dispatch it * - lance has higher priority, service one interupt * and get out, if net or disk intr is pending we * will be called right back - preserves priority * *****************************************************************************/kn230_hardintr1(ep)int *ep;{extern int (*(scb[])) (); if ( *(int *)ICSR_ADDR & KN230_NIIRQ) (*(scb[LANCE_INDEX/4])) (ep,LANCE_INDEX/4); else if ( *(int *)ICSR_ADDR & KN230_SCSIRQ) (*(scb[SII_INDEX/4])) (ep,SII_INDEX/4); else printf("kn230: took stray interrupt on h/w intr level 1");}/****************************************************************************** * * kn230transenable: Enable transient parity memory error logging * *****************************************************************************/kn230transenable(){ kn230translog = 1; timeout (kn230transenable, (caddr_t) 0, kn230transintvl * hz);}/****************************************************************************** * * kn230_trap_error: * * Routine to handle trap errors: user-mode,ibe & dbe, & all kernel mode traps. * Try recover from user-mode errors and panic on kernel mode errors. * *****************************************************************************/kn230_trap_error(ep, code, sr, cause, signo) register u_int *ep; /* exception frame ptr */ register u_int code; /* trap code (trap type) */ u_int sr, cause; /* status and cause regs */ int *signo; /* set if we want to kill process */{ caddr_t pa; /* the physical addr of the error */ int epc; /* the EPC of the error */ unsigned memreg; /* memory parity error info */ int pagetype; /* type of page */ int vaddr; /* virt addr of error */ register struct proc *p; /* ptr to current proc struct */ long currtime; /* current time value */ int kn230_physmem; /* adjusted value when NVRAM present*/ /* * save the state of the system registers for * error logging. * */ kn230_esr_icsr = *(int *)ICSR_ADDR; kn230_esr_leds = *(int *)LED_ADDR; kn230_esr_wear = *(int *)WEAR_ADDR; kn230_esr_oid = *(int *)OID_ADDR; /* * If nvram present adjust physmem value to include the 1Mbyte * of NVRAM which is located in memory. physmem naturally doesn't know * about the NVRAM because it is not marked in the bitmap like * regular memory. Note physmem is in pages, so 1MB is 256 pages. * */ if ( *(int *)NVRAM_DIAG & KN230_NVRAM_PRESENT ) kn230_physmem = physmem + 256; else kn230_physmem = physmem; p = u.u_procp; if (USERMODE(sr)) { /* * If address of bus error is in physical memory, then its * a parity memory error. Gather additional info in "memreg", * for the error log & to determine how to recover. * If its a transient error then continue the user process. * If its a hard or soft parity error: * a) on a private process page, terminate the process * (by setting signo = SIGBUS) * b) on a shared page, crash the system. */ pa = vatophys(ep[EF_BADVADDR]); if ( (int)pa != -1 && (btop((int)pa) < kn230_physmem)) { /* * Note that we must save anything "interesting" * from the exception frame, since kn230_isolatepar() * may cause additional bus errors which will * stomp on the exception frame in locore. */ vaddr = ep[EF_BADVADDR]; epc = ep[EF_EPC]; memreg = kn230_isolatepar(pa, vaddr); ep[EF_BADVADDR] = vaddr; ep[EF_EPC] = epc; /* * If we get 3 or more in 1 second then disable logging * them for 15 minutes. The variable "kn230translog" * is set by the kn230transenable routine. */ if (((memreg >> TYPEOFF) & TRANSPAR) == TRANSPAR) { if (kn230translog) { currtime = time.tv_sec; if (currtime = kn230_trans_errcnt.trans_prev) { kn230translog = 0; mprintf("High rate of transient parity memory errors, logging disabled for 15 minutes\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -