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

📄 kn5800.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* clear warm and cold boot flags */	ccabase->cca_hflag |=(CCA_V_BOOTIP|CCA_V_REBOOT|CCA_V_WARMIP);}/* * ISIS halt interrupt recieved, for now we just reboot */kn5800halt(){	prom_reboot ();}/* * print processor module info */x3p_init(nxv,nxp,cpup,xminumber,xminode)char *nxv;char *nxp;struct cpusw *cpup;int xminumber,xminode;{#ifdef lint	nxv=nxv; nxp=nxp;	cpup = cpup;	xminumber=xminumber;	xminode = xminode;#endif lint	printf("x3p cpu at xmi%x node %x\n",xminumber,xminode);}/* * kn5800nexaddr -- return a physical address for a particular nexus. * * Only 1 XMI bus on ISIS, thus the xminumber is ignored. * */kn5800nexaddr(xminumber,xminode) int	xminumber;int	xminode;{	return((XMI_START_PHYS + (xminode * 0x80000)));}/* * ISISumaddr -- return BI  */kn5800umaddr(binumber,binode) int	binumber;int	binode;{    return(((int) bidata[binumber].biphys) + 0x400000 + (0x40000 * binode));}/* * ISISudevaddr - return */kn5800udevaddr(binumber,binode) int	binumber;int	binode;{    return (((int) bidata[binumber].biphys)				+ 0x400000 + 0x3e000 + (0x40000 * binode));}/* * write buffer flush for kn5800 */kn5800_wbflush(){	KN5800_WBFLUSH();	return (0);}kn5800_clean_icache(addr, len)caddr_t	addr;int	len;{	kn5800_cln_icache(addr, len, kn5800_wbflush_addr);	return (0);}kn5800_clean_dcache(addr, len)caddr_t	addr;int	len;{	kn5800_cln_dcache(addr, len, kn5800_wbflush_addr);	return (0);}kn5800_page_iflush(addr)caddr_t	addr;{	kn5800_pg_iflush(addr, kn5800_wbflush_addr);	return (0);}kn5800_page_dflush(addr)caddr_t	addr;{	kn5800_pg_dflush(addr, kn5800_wbflush_addr);	return (0);}kn5800_flush_cache(){	int	s;	s = splextreme();	kn5800_flsh_cache(&v5800csr->csr1);	v5800csr->csr1 &= ~RINVAL;	splx(s);	return (0);}/* returns the cpu id (XMI node number) */kn5800_cpuid(){	return(v5800csr->csr1 & XMI_NODE_ID); }/* initialization code that the secondary processor must run   before starting up */kn5800_init_secondary(){	struct xcp_reg *xcp_node;	register struct xmidata *xmidata ;	init_ssc();	xmidata = get_xmi(0);	xcp_node =(struct xcp_reg *)xmidata->xmivirt +					(v5800csr->csr1 & XMI_NODE_ID);	xcp_node->xcp_csr2 = xcp_node->xcp_csr2 & ~(0x4000); /* CRDID is set						   disabled on secondary */	xcp_node->xcp_xbe = xcp_node->xcp_xbe;	kn5800_enable_cache();	if (!CURRENT_CPUDATA->cpu_machdep) 		/* Allocate memory to store machine check information */		KM_ALLOC(CURRENT_CPUDATA->cpu_machdep,char *,			 sizeof(struct el_xcpsoft),KM_DEVBUF,KM_NOW_CL_CO_CA);	kn5800_enable_softlog();}kn5800_enable_softlog(){	/*	 * Enable cache soft error logging	 */	CURRENT_CPUDATA->cpu_state &= ~(CPU_SOFT_DISABLE);	if (memintvl > 0)		timeout (kn5800_enable_softlog, (caddr_t) 0, memintvl * hz);	return(0);}/* * init_ssc -- set up ssc address, set to interrupt at proper level. * */init_ssc (){	ssc_ptr = (struct ssc_regs *)PHYS_TO_K1(DEFAULT_SSC_PHYS);	ssc_ptr->ssc_adc0mask = 0x00000004;	/* required for cache *//*	ssc_ptr->ssc_ssccr &= (~SSCCR_IPLMASK);	*/	ssc_ptr->ssc_ssccr |= SSCCR_CPT;	/* enable ^p detect */}reprime_ssc_clock(){	v5800csr->csr1 &= ~EINTMR;	v5800csr->csr1 |= EINTMR;	return (0);}/* * kn5800_start_clock */kn5800_start_clock(){	v5800csr->csr1 |= EINTMR;	return (0);}kn5800_stop_clock(){	v5800csr->csr1 &= (~EINTMR);	v5800csr->csr1 |= EINTMR;	v5800csr->csr1 &= (~EINTMR);	return (0);}/* * taken from cvax.c */cca_setup(){	register int i, j;	register int num_cpu = 0;	register int stkpaddr;	int timeout;	ccabase = (struct cca *)xtob((char *)(prom_getenv ("cca")));	/* sanity check CCA */	if ((ccabase->cca_indent0 != 'C') ||	    (ccabase->cca_indent1 != 'C')) {		panic("no CCA");	}	/* Start processors upto the number configured */	for (i=0; i < ccabase->cca_nproc; i++ ) {		if (ccabase->cca_console & (1 << i)) {			num_cpu++;		} 	}	if( !(ccabase->cca_console & (1 << (v5800csr->csr1 & XMI_NODE_ID)))) 			    /* if the boot cpu's console bit is not cleared */		num_cpu++; /* for backward compatibilty with a bug in console			      ROM. Because of the bug, cca_console was not			      cleared even after the processor was started */	return(num_cpu);}/* * taken from cvax.c */cca_startcpu(cpunum)int cpunum;{	int timeout;	if (ccabase->cca_console & (1 << cpunum)) {	    if( (ccabase->cca_enabled & (1 << cpunum)) && get_cpudata(cpunum)) {	    /*	     * Init the slave	     */	    /* The start address for the kernel is set by the loader to  be	       0x80030000. If this value is ever changed (through config),	       this string should also be changed. Since the command is being	       sent to the CVAX chip and not R3000, use the EXIT command and	       not 'go'.*/		    cca_send("EXIT 80030000\r", cpunum);		    timeout=10;		    while ( (ccabase->cca_console & (1<<cpunum)) ) { 			    DELAY(1000000)				    if (--timeout < 0) break;		    }		    if(!(ccabase->cca_console & (1 << cpunum))) {			    return(1);		    } 	   }	}	return(0); }cca_send(str,cpunum) register char *str;register int cpunum;{	register int index;	int timeout;	timeout=10;	while ( (ccabase->cca_buf[cpunum].flags & RXRDY) != 0) {		DELAY(1000000);		if (--timeout < 0) {			printf("processor %x not ready\n",cpunum);			return;		}	}	index = 0;	while (*str != '\0') {		ccabase->cca_buf[cpunum].rx[index] = *str;		str++;		index++;	}	ccabase->cca_buf[cpunum].rxlen = index;	ccabase->cca_buf[cpunum].flags |= RXRDY;	timeout=10;	while ( (ccabase->cca_buf[cpunum].flags & RXRDY) != 0) {		DELAY(1000000);		if (--timeout < 0) {			printf("processor %x not ready\n",cpunum);			return;		}		}}		/* * nxaccess for kn5800. This is tricky stuff. The 5800 systems exchange * bit 28 and 29 of addresses comming out of the CPU/MMU area to split * accesses from KSEG0 and 1 between memory and I/O. This exchange happens * for all addresses output from the processor area independent of the * virtual address. (In other words, accesses to KSEG0, 1 and 2 as well * as KUSEG.) When we map I/O space, upper XMI addresses in the range * 0x30000000 to 0x3fffffff are ok as both bit 28 and 29 are set so * the exchange is a nop. For nexi in lower xmi slots where the XMI * physical address is in the range of 0x20000000 to 0x2fffffff we must * exchange 28 and 29 in the pte so that the hardware exchange puts * it back. Confused? */#define	XMI_IO_BITS	0x30000000nxaccess(physa, pte, nexsize)struct nexus *physa;register struct pte *pte;int nexsize;{	register int i = btop(nexsize);	register unsigned pfn;	register int vpn = (((pte - Sysmap)/4) + btop(K2BASE));	if (((int)physa & XMI_IO_BITS) == 0x20000000)		physa = (struct nexus *)((int)physa - 0x10000000);	pfn = btop(physa);/*cprintf("kn5800_nxaccess: phys = 0x%x, pte = 0x%x, size = 0x%x, nptes = 0x%x\n",physa, pte, nexsize, i);*/	do {	    *(int *)pte++ = ((pfn << PTE_PFNSHIFT)|PG_V|PG_KW|PG_N|PG_M|PG_G);	    pfn++;#ifdef PROBE_BUG	    CKPROBE(tlbdropin(0, ptob(vpn), *(int *)pte));#else	    tlbdropin(0, ptob(vpn), *(int *)pte);#endif	    vpn++;	} while (--i > 0);/**	mtpr(TBIA, 0); What to do for ISIS ?? **/}/* * Routine to handle trap errors: user-mode ibe & dbe, & all kernel mode traps. * We try to recover from user-mode errors and panic on kernel mode errors. */kn5800_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 */	struct xcp_reg *xcp_node;	register struct xmidata *xmidata;	register struct kn5800_regs *reg;	xcp_node = (struct xcp_reg *)PHYS_TO_K1(XMI_START_PHYS) +					(v5800csr->csr1 & XMI_NODE_ID);	reg = kn5800_regp;	reg->kn5800_csr1 = v5800csr->csr1;	reg->kn5800_dtype = xcp_node->xcp_dtype;	reg->kn5800_xbe = xcp_node->xcp_xbe;	reg->kn5800_fadr = xcp_node->xcp_fadr;	reg->kn5800_gpr = xcp_node->xcp_gpr;	reg->kn5800_csr2 = xcp_node->xcp_csr2;	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.		 * TBD: on a non-modified page, re-read the page (page fault),		 *	and continue the process.		 * TBD: on a shared page terminate all proc's sharing the page,		 *	instead of crash system.		 * TBD: on hard errors map out the page.		 */		pa = vatophys(ep[EF_BADVADDR]);		if ( (int)pa != -1 && (btop((int)pa) < physmem) ) {			if (SHAREDPG(pa)) {				kn5800_memerr(ep, reg, EL_PRISEVERE);				kn5800_consprint(MEMPKT, ep);				panic("memory parity error in shared page");			} else {				kn5800_memerr(ep, reg, EL_PRIHIGH);				printf("pid %d (%s) was killed on memory parity error\n",					p->p_pid, u.u_comm);				uprintf("pid %d (%s) was killed on memory parity error\n",					p->p_pid, u.u_comm);			}		} else {			uprintf("pid %d (%s) was killed on bus error\n",				p->p_pid, u.u_comm);		}	} else {		/*		 * Kernel mode errors.		 * They all panic, its just a matter of what we log		 * and what panic message we issue.		 */		switch (code) {		case EXC_DBE:		case EXC_IBE:			/*			 * Figure out if its a memory parity error			 *     or a read bus timeout error			 */			pa = vatophys(ep[EF_BADVADDR]);			if ( (int)pa != -1 && (btop((int)pa) < physmem) ) {				kn5800_memerr(ep, reg, EL_PRISEVERE);				kn5800_consprint(MEMPKT, ep);				panic("memory parity error in kernel mode");			} else {				kn5800_logesrpkt(ep, reg, EL_PRISEVERE);				kn5800_consprint(ESRPKT, ep);				panic("bus timeout");			}			break;		case EXC_CPU:			kn5800_logesrpkt(ep, reg, EL_PRISEVERE);			kn5800_consprint(ESRPKT, ep);			panic("coprocessor unusable");			break;		case EXC_RADE:		case EXC_WADE:			kn5800_logesrpkt(ep, reg, EL_PRISEVERE);			kn5800_consprint(ESRPKT, ep);			panic("unaligned access");			break;		default:			kn5800_logesrpkt(ep, reg, EL_PRISEVERE);			kn5800_consprint(ESRPKT, ep);			panic("trap");			break;		}	}	/*	 * Default user-mode action is to terminate the process	 */	*signo = SIGBUS;	return(0);}/* * Log Error & Status Registers to the error log buffer. */kn5800_logesrpkt(ep, ptr, priority)register u_int *ep;			/* exception frame ptr */struct kn5800_regs *ptr;		/* pointer to saved processor register */int priority;				/* for pkt priority */{	struct el_rec *elrp;	elrp = ealloc(sizeof(struct el_esr), priority);	if (elrp != NULL) {		LSUBID(elrp,ELCT_ESR,ELESR_5800,EL_UNDEF,EL_UNDEF,EL_UNDEF,EL_UNDEF);		elrp->el_body.elesr.elesr.el_esr5800.esr_cause = ep[EF_CAUSE];		elrp->el_body.elesr.elesr.el_esr5800.esr_epc = ep[EF_EPC];		elrp->el_body.elesr.elesr.el_esr5800.esr_status = ep[EF_SR];		elrp->el_body.elesr.elesr.el_esr5800.esr_badva = ep[EF_BADVADDR];		elrp->el_body.elesr.elesr.el_esr5800.esr_sp = ep[EF_SP];		elrp->el_body.elesr.elesr.el_esr5800.x3p_csr1 = ptr->kn5800_csr1;		elrp->el_body.elesr.elesr.el_esr5800.x3p_dtype = ptr->kn5800_dtype;		elrp->el_body.elesr.elesr.el_esr5800.x3p_xbe = ptr->kn5800_xbe;		elrp->el_body.elesr.elesr.el_esr5800.x3p_fadr = ptr->kn5800_fadr;		elrp->el_body.elesr.elesr.el_esr5800.x3p_gpr = ptr->kn5800_gpr;		elrp->el_body.elesr.elesr.el_esr5800.x3p_csr2 = ptr->kn5800_csr2;		EVALID(elrp);	}}/* * Print error packet to the console. * This is only done when we are about to panic on the error. */kn5800_consprint(pkt, ep)int pkt;		/* error pkt: Error & Stat Regs / memory pkt */register u_int *ep;	/* exception frame ptr */{	switch (pkt) {	case ESRPKT:		cprintf("\nException condition\n");		break;	case MEMPKT:		cprintf("\nMemory Error\n");		break;	default:		cprintf("bad consprint\n");		break;	}	cprintf("\tCause reg\t= 0x%x\n", ep[EF_CAUSE]);	cprintf("\tException PC\t= 0x%x\n", ep[EF_EPC]);	cprintf("\tStatus reg\t= 0x%x\n", ep[EF_SR]);	cprintf("\tBad virt addr\t= 0x%x\n", ep[EF_BADVADDR]);	return;}bbssi(bitpos,base)register u_long bitpos;                   /* bitmask */register u_long *base;                    /* interlock target address */{	register u_long data;	register int s;	/*	 * Lock and read target address.	 */	s = splextreme();	data = interlock_read(base);	/*	 * Check if bit set.  If no, set it while location is locked, then unlock location.         * If already set, unlock location.	 */	if ((data & (1<<bitpos)) == 0) {		data |= (1<<bitpos);		*base = data; /* To sync cache with memory */		unlock_write(base, data);		splx(s);		return(1);	} 	else {		*base = data; /* Hardware folks insist on this */		unlock_write(base, data);		splx(s);		return(0);	}}bbcci(bitpos,base)register u_long bitpos;                   /* bitmask */register u_long *base;                    /* interlock target address */{	register u_long data;	register int s;	/*	 * Lock and read target address.	 */	s = splextreme();	data = interlock_read(base);	/*	 * Check if bit clear.  If no, clear it while location is locked, 	 * then unlock location. If already clear, unlock location.	 */	if ((data & (1<<bitpos))) {		data &= ~(1<<bitpos);		*base = data; /* To sync cache with memory */		unlock_write(base, data);		splx(s);		return(1);	} 	else {		*base = data; /* Hardware folks insist on this */		unlock_write(base, data);		splx(s);		return(0);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -