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

📄 kn02.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * This must be done very early on at boot time and must	 * be done before any interrupt is allowed.	 */	bcopy((int *)kn02intr_vec, c0vec_tbl, c0vec_tblsize);	bcopy(kn02iplmask, iplmask, IPLSIZE * sizeof(int));	bcopy(kn02splm, splm, (SPLMSIZE) * sizeof(int));	/* Initialize the spl dispatch table and the intr dispatch routine */	spl_init();	/*	 * Set up the system specific value for "hz", the number of clock	 * interrupts per second; and corresponding tick and tickadj values.	 */	hz = cpup->HZ;	tick = 1000000 / hz;	tickadj = 240000 / (60 * hz);	fixtick = 1000000 - (tick * hz);	/*	 * Assign the rt_clock_addr for this processor	 */	rt_clock_addr = (char *)PHYS_TO_K1(KN02CLOCK_ADDR);	/*	 * Clear the memory error counters.	 */	for (i = 0; i < MEM_MODULES; i++)		kn02memerrs[i] = 0;		/* Initialize the TURBOchannel */	tc_init();	/* Fill in the TURBOchannel slot addresses */	for (i = 0; i < TC_IOSLOTS; i++)	    tc_slotaddr[i] = kn02_slotaddr[i];	/* Fill in the TURBOchannel switch table */	tc_sw.enable_option = kn02enable_option;	tc_sw.disable_option = kn02disable_option;	tc_sw.clear_errors = kn02clear_errors;	tc_sw.config_order = kn02config_order;	/*	 * Fixed 3max IO devices (slots 3 & 4 unused)	 */	tc_slot[3].slot = 3;	tc_slot[4].slot = 4;	strcpy(tc_slot[5].devname,"asc");	strcpy(tc_slot[5].modulename, "PMAZ-AA ");	tc_slot[5].slot = 5;	tc_slot[5].module_width = 1;	tc_slot[5].physaddr = SLOT_5_ADDR;	tc_slot[5].intr_b4_probe = 0;	tc_slot[5].intr_aft_attach = 1;	tc_slot[5].adpt_config = 0;	strcpy(tc_slot[6].devname,"ln");	strcpy(tc_slot[6].modulename, "PMAD-AA ");	tc_slot[6].slot = 6;	tc_slot[6].module_width = 1;	tc_slot[6].physaddr = SLOT_6_ADDR;	tc_slot[6].intr_b4_probe = 0;	tc_slot[6].intr_aft_attach = 1;	tc_slot[6].adpt_config = 0;	strcpy(tc_slot[7].devname,"dc");	tc_slot[7].slot = 7;	tc_slot[7].module_width = 1;	tc_slot[7].physaddr = KN02DC_ADDR;	tc_slot[7].intr_b4_probe = 0;	tc_slot[7].intr_aft_attach = 1;	tc_slot[7].adpt_config = 0;	return(0);}/* * Configuration routine for kn02 processor (3max). */kn02conf(){	extern int cold;	extern u_int cpu_systype;	cold = 1;	/* 	 * Initialize PROM environment entries.	 */	hwconf_init();	/* 	 * Report what system we are on	 */	printf("KN02 processor - system rev %d\n", (GETHRDREV(cpu_systype)));	coproc_find();	/* Turn off all interrupts in the CSR */	*(u_int *)PHYS_TO_K1(KN02CSR_ADDR) &= (~0x00ff0000);	wbflush();	/*	 * Probe the TURBOchannel and find all devices	 */	tc_find();	timeout (kn02crdenable, (caddr_t) 0, kn02crdintvl * hz);	timeout (kn02pscheck, (caddr_t) 0, kn02psintvl * hz);	cold = 0;	/*	 * configure nvram option, this enables	 * Prestoserve if the NVRAM is present.	 *	 * This will go out an probe for NVRAM.	 *	 */	 kn02_config_nvram();	return (0);	/* tell configure() we have configured correctly */}/* *	kn02clear_errors() * *	Clears any pending errors in the error register */kn02clear_errors(){        *(u_int *)PHYS_TO_K1(KN02ERR_ADDR) = 0;	wbflush();}/* *	kn02enable_option() *	 *	Takes a slot number as an argument. * *	This function enables an option's interrupt on the TURBOchannel *	to interrupt the system at the I/O interrupt level.   *	This is done by setting the option's slot number as a valid *	interrupt to service. */kn02enable_option(slot)        int slot;{	kn02ie_mask |= (1 << slot);	*(u_int *)PHYS_TO_K1(KN02CSR_ADDR) |= (1 << slot+KN02IE_OFFSET);	wbflush();}/* *	kn02disable_option() *	 *	Takes a slot number as an argument. * *	This function disables an option's interrupt on the TURBOchannel *	to interrupt the system at the I/O interrupt level.   *	This is done by resetting the option's slot number as a valid *	interrupt to service. */	kn02disable_option(slot)        int slot;{	kn02ie_mask &= ~(1 << slot);	*(u_int *)PHYS_TO_K1(KN02CSR_ADDR) &= ~(1 << slot+KN02IE_OFFSET);	wbflush();}/* * 3max halt interrupt routine. * It calls the console PROM halt routine with an address (ep) where it will * start dumping out values & the length to dump (size of exception frame, in * long words). */kn02halt(ep){	extern int rex_base;	if(rex_base)		rex_halt(ep, EF_SIZE/4); /* TURBOchannel'd 3max ROM callback */	else		prom_halt(ep, EF_SIZE/4);}/* * 3max stray interrupt routine. */kn02stray(ep)	u_int *ep;		/* exception frame ptr */{	printf("Stray interrupt, CAUSE = 0x%x, STATUS = 0x%x\n",		ep[EF_CAUSE], ep[EF_SR]);}/* * Check Power Supply over-heat Warning. * If its overheating, warn to shut down the system. * If its gone from overheat to OK, cancel the warning. */kn02pscheck(){	register u_int kn02csr;		/* a copy of the real csr */	kn02csr = *(u_int *)PHYS_TO_K1(KN02CSR_ADDR);	if (kn02csr & KN02CSR_PSWARN) {		printf("System Overheating - suggest immediate shutdown and power-off\n");		kn02pswarn = 1;	} else {		if (kn02pswarn) {			printf("System OK - cancel overheat shutdown\n");			kn02pswarn = 0;		}	}	timeout (kn02pscheck, (caddr_t) 0, kn02psintvl * hz);}/* * Enable CRD (single bit ECC) error logging */kn02crdenable(){	kn02crdlog = 1;	timeout (kn02crdenable, (caddr_t) 0, kn02crdintvl * hz);}/* * 3max I/O interrupt routine. * The IOint bits in the CSR tell which slot interrupted. * Look up the slot number in the tc_slot table to determine which *	interrupt routine to call. * * Note that more than 1 interrupt bit can be set in the CSR. * Also note that software does not need to clear the IO bits in the CSR, * they are cleared when the Interrupt line is cleared. */kn02iointr(ep)	u_int *ep;{	register u_int kn02csr;		/* a copy of the real csr */	register int ioint;		/* the ioint bits in the CSR */	kn02csr = *(u_int *)PHYS_TO_K1(KN02CSR_ADDR);	/*	 * This is a clever way of making a fast jump table which converts	 * a bit set in the ioint portion of the kn02 csr to an index into	 * the tc_slot table.  We are handling interrupts, so speed	 * is of the essence.	 */	ioint = (kn02csr >> KN02IE_OFFSET) & (kn02csr & 0xff);	if (ioint != 0) {		/*		 * Check for bits set in the high nibble		 */		switch (ioint & 0xf0) {		case 0xf0:		case 0xe0:		case 0xd0:		case 0xc0:		case 0xb0:		case 0xa0:		case 0x90:		case 0x80:			/*			 * We always handle the serial line ctlr first.			 * This will give the mouse highest priority.			 * For debug: pass ep to dcintr() so it can print epc			 */			(*(tc_slot[7].intr))(tc_slot[7].unit, ep);			break;		case 0x70:		case 0x60:		case 0x50:		case 0x40:			(*(tc_slot[6].intr))(tc_slot[6].unit);			break;		case 0x30:		case 0x20:			(*(tc_slot[5].intr))(tc_slot[5].unit);			break;		/*		 * slot 4 unused on 3max		 */		}		/*		 * Check for bits set in the low nibble		 */		switch (ioint & 0xf) {		/*		 * slot 3 unused on 3max		 */		case 0x7:		case 0x6:		case 0x5:		case 0x4:			(*(tc_slot[2].intr))(tc_slot[2].unit);			break;		case 0x3:		case 0x2:			(*(tc_slot[1].intr))(tc_slot[1].unit);			break;		case 0x1:			(*(tc_slot[0].intr))(tc_slot[0].unit);			break;		}	}}/* * 3max delay routine. * Tested from 5 seconds down to 4,000 usecs (4 mSec clock accuracy). */int kn02_delay_mult = 13;		/* multiplier for DELAY (optimized) */kn02delay(n)	int n;{	register int N = kn02_delay_mult*(n); 	while (--N > 0); 	return(0);}/* * Error interrupt. * With buffered writes, these are not reported synchronously, thus * there is no process context to terminate a user process, so we panic. * * Causes: *   Memory Errors: *	CPU read single bit ECC *	DMA read overrun, DMA write overrun *	CPU partial memory write ECC, DMA memory read ECC *   Timeout Errors: *	CPU I/O write timeout */kn02errintr(ep)	u_int *ep;			/* exception frame ptr */{	register int s;	register u_int kn02csr;		/* copy of csr reg */	register u_int erradr;		/* copy of erradr reg */	register u_int chksyn;		/* copy of chksyn reg */	register u_int chksyn_plus;	/* valid half of chksyn + errcnt + pc */	int errtype;			/* local record of error type */	int pa;				/* the physical address of the error */	int module;			/* module number with error */	long currtime;			/* current time value */        struct kn02consinfo_t *pcons;   /* pointer to console info */        struct kn02log_errinfo_t *plog; 	/* pointer to log info */	kn02csr = *(u_int *)PHYS_TO_K1(KN02CSR_ADDR);	erradr = *(u_int *)PHYS_TO_K1(KN02ERR_ADDR);	chksyn = *(u_int *)PHYS_TO_K1(KN02CHKSYN_ADDR);	if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_RECC) &&	    (((chksyn & CHKSYN_VLDLO) && (chksyn & CHKSYN_SNGLO)) ||	     ((chksyn & CHKSYN_VLDHI) && (chksyn & CHKSYN_SNGHI))))		errtype = ERR_RECC;	/* singlebit memory read ECC */	else if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_DMARECC) &&	    ((chksyn & CHKSYN_VLDLO) || (chksyn & CHKSYN_VLDHI)))		errtype = ERR_DMARECC;	/* DMA memory read ECC */	else if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_WECC) &&	    ((chksyn & CHKSYN_VLDLO) || (chksyn & CHKSYN_VLDHI)))		errtype = ERR_WECC;	/* CPU partial mem write ECC */	else if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_DMAROVR))		errtype = ERR_DMAROVR;	/* DMA read overrun */	else if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_DMAWOVR))		errtype = ERR_DMAWOVR;	/* DMA write overrun */	else if ((erradr & ERR_VALID) && ((erradr & ERR_TYPE) == ERR_WTMO))		errtype = ERR_WTMO;	/* CPU write timeout */	else errtype = ERR_UKN;	switch (errtype) {	case ERR_RECC:	case ERR_DMARECC:	case ERR_WECC:		erradr = (erradr & (~ERR_COLADDR)) | (((int)erradr -5) & ERR_COLADDR);		pa = (erradr & ERR_ADDR) << 2;		if (kn02csr & KN02CSR_BNK32M)			module = pa / (32*(1024*1024));		else	module = pa / (8*(1024*1024));		if (module >= 0 && module < MEM_MODULES) {			kn02memerrs[module]++;			if (kn02memerrs[module] > MAXERRCNT) {				kn02memerrs[module] = 0;				mprintf("Error count on memory module %d reached %d, resetting count to zero.\n", module, MAXERRCNT);			}		} else			module = -1;		/*		 * Build chksyn_plus.		 */		chksyn_plus = 0;		if (chksyn & CHKSYN_VLDLO) {			chksyn_plus = (chksyn & CPLUS_CHK);		} else			chksyn_plus = ((chksyn >> CPLUS_MOFF) & CPLUS_CHK);		if (module == -1) {

⌨️ 快捷键说明

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