📄 ka9000.c
字号:
ka9000mckaddrtype(mcp)register struct el_mc9000frame *mcp;{ int addr_type = CSYS; if(mcp->mc_misc_info & MCHK_9K_MISC_PA_VALID) { /* Physical address is valid. Go into cmap to * get the type of the page. */ addr_type = cmap[pgtocm(clbase(btop(mcp->mc_paddr)))].c_type; } else if(mcp->mc_misc_info & MCHK_9K_MISC_VA_VALID) { int v; /* Virtual address is valid. Figure out its type. */ if(mcp->mc_vaddr & 0x80000000) { addr_type = CSYS; } else { v = clbase(btop(mcp->mc_vaddr)); if(isatsv(u.u_procp, v)) { addr_type = CTEXT; } else if (isadsv(u.u_procp, v)) { addr_type = CDATA; if(vtodp(u.u_procp, v) >= u.u_procp->p_dsize) { addr_type = CSMEM; } } else if (isassv(u.u_procp, v)) { addr_type = CSTACK; } } } return(addr_type);}/* On MBOX error, see if we can find all processes that reference * this particular address and kill them. Returns 1 if successful, * 0 otherwise. */ka9000addrkill(mcp, addr_type, msg)register struct el_mc9000frame *mcp;int addr_type;char * msg;{ int i; struct proc *p; struct smem *smp; if((addr_type == CTEXT) || (addr_type == CDATA) || (addr_type == CSTACK) || (addr_type == CSMEM)) { /* We can't kill the proc if it's in system space * or if it's the init proc. */ if(!USERMODE(mcp->mc_psl) || (u.u_procp->p_pid == 1)) { return(0); } /* If it's a text or shared data page, kill everyone * ELSE who's using it first! */ if(addr_type == CTEXT) { p = u.u_procp->p_xlink; while(p != u.u_procp) { swkill(p, msg); p = p->p_xlink; } } if(addr_type == CSMEM) { if(!(mcp->mc_misc_info & MCHK_9K_MISC_VA_VALID)) { /* We need the virtual address. If we don't have * it, then we can't do this... */ return(0); } p = (struct proc *)NULL; /* Look for the shared memory segment that contains * this virtual address. */ for(i = 0; i < sminfo.smseg; i++) { if(u.u_procp->p_sm[i].sm_p == NULL) { continue; } if(mcp->mc_vaddr >= u.u_procp->p_sm[i].sm_saddr && mcp->mc_vaddr < u.u_procp->p_sm[i].sm_eaddr) p = u.u_procp->p_sm[i].sm_link; smp = u.u_procp->p_sm[i].sm_p; break; } } /* If we can't find it, we're sunk */ if(!p) { return(0); } /* Kill everyone who's sharing this segment */ while(p != u.u_procp) { struct proc * nextp; nextp = (struct proc *)NULL; for(i = 0; i < sminfo.smseg; i++) { if(p->p_sm[i].sm_p == smp) { nextp = p->p_sm[i].sm_link; } } if(!nextp) { /* This shouldn't happen! */ return(0); } swkill(p, msg); p = nextp; } /* Killed anyone else that has to be killed... * now kill ourselves! */ swkill(u.u_procp, msg); return(1); } else { /* Not a user address... */ return(0); }} /* * ka9000badmchk is called when we have an unrecoverable machine check, * and we need to log the machine check stack frame to the console */ka9000badmchk(mcp, reason)register struct el_mc9000frame *mcp;char * reason;{ register struct el_rec *elp; int cpu_num; cpu_num = CURRENT_CPUDATA->cpu_num; printf("Unrecoverable machine check: %s\n", reason); cprintf("Machine check stack frame:\n"); cprintf(" Length: 0x%x\n", mcp->mc_length); cprintf(" Type: 0x%x\n", mcp->mc_type); if(mcp->mc_type == MCHK_9000_TYPE_EBOX) { struct el_mc9000eboxframe * emcp = (struct el_mc9000eboxframe *)mcp; cprintf(" PC: 0x%x\n", emcp->mc_pc); cprintf(" PSL: 0x%x\n", emcp->mc_psl); } else { cprintf(" ID: 0x%x\n", mcp->mc_id); cprintf(" ERR SUMM: 0x%x\n", mcp->mc_err_summ); cprintf(" SYS SUMM: 0x%x\n", mcp->mc_sys_summ); cprintf(" Virt addr: 0x%x\n", mcp->mc_vaddr); cprintf(" Phys addr: 0x%x\n", mcp->mc_paddr); cprintf(" Misc info: 0x%x\n", mcp->mc_misc_info); cprintf(" PC: 0x%x\n", mcp->mc_pc); cprintf(" PSL: 0x%x\n", mcp->mc_psl); /* fatal non-ebox mach chk must log at EL_PRISEVERE */ if((elp=ealloc(sizeof(struct el_mck),EL_PRISEVERE))!= EL_FULL){ LSUBID(elp, ELCT_MCK, ELMCKT_9000, EL_UNDEF, EL_UNDEF, EL_UNDEF, EL_UNDEF);#define ELP_ELMCK elp->el_body.elmck.elmck_frame.el9000mcf ELP_ELMCK.mc_length = mcp->mc_length; ELP_ELMCK.mc_type = mcp->mc_type; ELP_ELMCK.mc_id = mcp->mc_id; ELP_ELMCK.mc_err_summ = mcp->mc_err_summ; ELP_ELMCK.mc_sys_summ = mcp->mc_sys_summ; ELP_ELMCK.mc_vaddr = mcp->mc_vaddr; ELP_ELMCK.mc_paddr = mcp->mc_paddr; ELP_ELMCK.mc_misc_info = mcp->mc_misc_info; ELP_ELMCK.mc_pc = mcp->mc_pc; ELP_ELMCK.mc_psl = mcp->mc_psl; if(((mfpr(CPUCNF) >> 8) & 0xf) == (1 << cpu_num)) { /* VBOX present */ ELP_ELMCK.mc_vpsr = mfpr(VPSR); } else { /* VBOX absent */ ELP_ELMCK.mc_vpsr = 0; } EVALID(elp); } } panic("Unrecoverable machine check");}/* This routine updates the soft error statistics for a particular * module. If the module should be failed, this routine returns * 0; otherwise, it returns 1. */ka9000softerr(es)struct mc9000_softerr_stats *es;{ unsigned long todr = mfpr(TODR); /* If we've never had an error or the error occurred a * long time ago, then treat this as the first error ever. */ if((es->err_cnt == 0) || ((es->lasterr_time + MCHK_9K_ERR_TIMEOUT) < todr)) { es->err_cnt = 1; es->lasterr_time = todr; return(1); } /* Bump error count. If it exceeds the threshold then * recommend failing the module. */ es->err_cnt++; es->lasterr_time = todr; if(es->err_cnt > MCHK_9K_MAX_ERRS) { return(0); } else { return(1); }} /* * Function: * ka9000memerr() * * Description: * log memory errors in kernel buffer * * Arguments: * none * * Return value: * none * * Side effects: * none */ka9000memerr(){ struct el_rec *elrp; struct el_mem *mrp;/* Todo: what to do on these errors is not defined yet */ return(0);}/* * this routine sets the cache to the state passed. enabled/disabled */ka9000setcache(state)int state;{/* Todo: CSWP only has 1 usefull bit: the Initiate sweep bit * need to set whatever cache config reg is appropriate for Aquarius */ mtpr (CSWP, state); return(0);}/* * ka9000memenable enables the memory controller corrected data reporting. * This runs at regular intervals, turning on the interrupt. * The interrupt is turned off, per memory controller, when error * reporting occurs. Thus we report at most once per memintvl. */ka9000memenable (){ register struct mcr *mcr;/* Todo: what to do for this is not defined yet */ return(0);}ka9000tocons (c) register int c;{ /* This routine is ONLY used to send Logical Console * commands. Since the use of the Logical Console * is discouraged on Aquarius in favor of TXFCT commands, * we'll just map the one into the other. */ c &= TXDB_DATA; c |= TXDB_ID; switch (c) { case TXDB_BOOT: /* Reboot */ printf( "ka9000tocons REBOOT: Should use TXFCT instead\n"); ka9000_spu_request(TXFCT_REBOOT_SYSTEM, 0, 0, 0); break; case TXDB_CWSI: /* Clear warm start */ printf( "ka9000tocons Clear Warmstart: Should use TXFCT instead\n"); ka9000_spu_request(TXFCT_CLEAR_WS, boot_cpu_num, 0, 1); break; case TXDB_CCSI: /* Clear cold start */ printf( "ka9000tocons Clear Coldstart: Should use TXFCT instead\n"); ka9000_spu_request(TXFCT_CLEAR_CS, boot_cpu_num, 0, 1); break; default: printf("ka9000tocons: Unrecognized logical console cmd 0x%x\n", c); break; } return(0);}/* * Enable cache and enable floating point accelerator */extern int cache_state;ka9000cachenbl(){/* Todo: what to do here is not defined yet */ return(0);}ka9000nexaddr(xminumber,xminode) int xminode,xminumber;{ return((XMI_START_PHYS+(xminumber * 0x800000) + (xminode * 0x80000))); }u_short *ka9000umaddr(ioadpt,ubanumber) int ioadpt,ubanumber;{}u_short *ka9000udevaddr(ioadpt,ubanumber) int ioadpt,ubanumber;{}ka9000logsbi(sbi_num,sbi_type,pc_psl)long sbi_num;long sbi_type;long *pc_psl;{extern int cold; /* Cold start flag */if (cold) { /* booting, may not be able to access XMI yet */ if (head_xmidata) { /* We can access XMI */ ka9000_clear_err(); } return(0);}}/* Initialize the state of the Service Processor Unit * at boot time */ka9000_init_spu(){ /* Enable RXFCT interrupts... */ mtpr(RXFCT, mfpr(RXFCT) | RXFCT_IE );}/* Re-initialize the state of the SPU if an SPU reboot * has been detected */ka9000_reinit_spu(){ u_long timo; int i; struct dmd * dmd; struct dmd * dmd_next; extern struct tty cons[2]; long txcs; long rxcs; /* Back out any datagram allocations */ dmd = spu_dmdlist; while(dmd) { dmd_next = (struct dmd *)dmd->dmd_link; KM_FREE(dmd->dmd_bufaddr, KM_SPU); KM_FREE(dmd, KM_SPU); dmd = dmd_next; } spu_dmdlist = (struct dmd *)NULL; /* Re-initialize the SPU's state */ /* Set SPU interrupt delivery mode such that all interrupts * are delivered in absolute mode to the boot cpu only */ /* Wait for TXFCT to become available */ timo = 20000000; while((mfpr(TXFCT) & TXFCT_RDY) == 0) { if(--timo == 0) { panic("ka9000_reinit_spu: TXFCT not ready"); } } mtpr(TXPRM, boot_cpu_mask); /* Select boot cpu only */ mtpr(TXFCT, TXFCT_SET_INTMODE | /* Func: set interrupt mode */ (INTMODE_ABSOLUTE /* Select absolute mode */ << TXFCT_SPARAM_SHIFT)); /* Initialize the TTY lines */ txcs = TXCS_IE | TXCS_NO_TTY; rxcs = RXCS_IE; if(cons[0].t_state & TS_ISOPEN) { txcs |= (TXCS_CTY_ENA | TXCS_WM); } if(cons[1].t_state & TS_ISOPEN) { txcs |= (TXCS_RTY_ENA | TXCS_WM); rxcs |= RXCS_RDTR; } mtpr(RXCS,rxcs); mtpr(TXCS,txcs); /* Enable RXFCT interrupts... */ mtpr(RXFCT, mfpr(RXFCT) | RXFCT_IE ); /* If error logging was enabled before the SPU rebooted, then * we have to re-enable it. */ if(ka9000_errlog_enabled) { ka9000_errlog_enabled = 0; ka9000_enable_errlog(); }}/* * Routine to periodically send a keepalive message */ka9000_keepalive_timeout(){ extern int hz; int ka9000_keepalive_done(); /* We may get called ONCE even though keepalives are disabled, * if there was a race condition on dequeueing the timeout * request... */ if(!ka9000_keepalive_enabled) { return; } if(ka9000_keepalive_misses > SPU_MAX_KEEPALIVE_MISS) { /* We poked it several times and no response; * reboot the SPU. */ mtpr(CRBT, 1); /* Disable keepalive system; it's up to the SPU to * re-enable it when it comes up... */ ka9000_keepalive_enabled = 0; ka9000_keepalive_misses = 0; return; } /* Record this as a miss (until it hits) */ ka9000_keepalive_misses++; /* Schedule another timeout in 10 seconds */ timeout(ka9000_keepalive_done, 0, 10 * hz); /* Send a keepalive message down to the SPU */ ka9000_spu_request(TXFCT_KEEPALIVE, 0, 0, 0);}/* * Routine called on successful acknowledgement of * keepalive message. */ka9000_keepalive_done(){ ka9000_keepalive_misses = 0;}/* * Send a request to the SPU */ka9000_spu_request(func, sparam, txprm, wait)int func;int sparam;int txprm;int wait;{ unsigned long txfct; unsigned long timeout; /* Construct txfct register */ txfct = func | ((sparam << TXFCT_SPARAM_SHIFT) & TXFCT_SPARAM); timeout = 20000000; while((mfpr(TXFCT) & TXFCT_RDY) == 0) { if(--timeout == 0) { panic("ka9000_spu_request: TXFCT not ready"); } } mtpr(TXPRM, txprm); /* Send the request down! */ mtpr(TXFCT, txfct); /* If the caller wants to wait for the request to complete * then wait for it... */ if(wait) { int status; timeout = 20000000; while(((txfct = mfpr(TXFCT)) & TXFCT_RDY) == 0) { if(--timeout == 0) { panic("ka9000_spu_request: TXFCT not ready"); } /* Delay 0.1ms and check again */ DELAY(100); } status = TXFCT_GET_STATUS(txfct); return(status ? 0 : -1); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -