⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ka9000.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -