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

📄 uba.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
				if (pte) 					pte++;				else					mips_pfn++;			}#else			if (user_addr &&			    (((int)pte & PGOFSET) < CLSIZE*sizeof(struct pte)			     || pte->pg_pfnum == 0))				pte = vtopte(rp, v);			if (pte->pg_pfnum == 0)				panic("uba zero uentry");			*(int *)io++ = pte++->pg_pfnum | temp;			v++;#endif mips		}		*(int *)io++ = 0;	/* Set up fire wall */		WBFLUSH;	} else	{		ubinfo = contigphys( ubinfo, bp->b_bcount, pte);		++reg;		a = spl6();		rmfree( uh->uh_map, (long)npf, (long)reg);		splx(a);	}	return (ubinfo);}/* * Non buffer setup interface... set up a buffer and call ubasetup. */uballoc(uban, addr, bcnt, flags)	int uban;	caddr_t addr;	int bcnt, flags;{	struct buf ubabuf;	ubabuf.b_un.b_addr = addr;	ubabuf.b_flags = B_BUSY;	ubabuf.b_bcount = bcnt;	/* that's all the fields ubasetup() needs */	return (ubasetup(uban, &ubabuf, flags));} /* * Release resources on uba uban, and then unblock resource waiters. * The map register parameter is by value since we need to block * against uba resets on 11/780's. */ubarelse(uban, amr)	int *amr;{	register struct uba_hd *uh = &uba_hd[uban];	register int bdp, reg, npf, s;	int mr; 	/*	 * Carefully see if we should release the space, since	 * it may be released asynchronously at uba reset time.	 */	s = spl6();	mr = *amr;	if (mr == 0) {		/*		 * A ubareset() occurred before we got around		 * to releasing the space... no need to bother.		 */		splx(s);		return;	}	*amr = 0;	splx(s);		/* let interrupts in, we're safe for a while */	bdp = (mr >> 28) & 0x0f;	if (bdp) {		if (uh->uba_type&UBABUA){			bdp = bdp & 0x07;			((struct bua_regs *)uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;		}		else if (uh->uba_type&UBA780)					uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;		else if (uh->uba_type&UBA750)			uh->uh_uba->uba_dpr[bdp] |=				    UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;		uh->uh_bdpfree |= 1 << (bdp-1);		/* atomic */		if (uh->uh_bdpwant) {			uh->uh_bdpwant = 0;			wakeup((caddr_t)&uh->uh_bdpwant);		}	}	/*	 * Put back the registers in the resource map.	 * The map code must not be reentered, so we do this	 * at high ipl.	 */	npf = (mr >> 18) & 0x3ff;	reg = ((mr >> 9) & 0x1ff) + 1;	s = spl6();	rmfree(uh->uh_map, (long)npf, (long)reg);	splx(s);	/*	 * Wakeup sleepers for map registers,	 * and also, if there are processes blocked in dgo(),	 * give them a chance at the UNIBUS.	 */	if (uh->uh_mrwant) {		uh->uh_mrwant = 0;		wakeup((caddr_t)&uh->uh_mrwant);	}	while (uh->uh_actf && ubago(uh->uh_actf))		;}ubapurge(um)	register struct uba_ctlr *um;{	register struct uba_hd *uh = um->um_hd;	register int bdp = (um->um_ubinfo >> 28) & 0x0f;	if (uh->uba_type & UBABUA) {		bdp = bdp & 0x07;		((struct bua_regs *)uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;	}	else if (uh->uba_type & UBA780)		uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;	else if (uh->uba_type & UBA750)		uh->uh_uba->uba_dpr[bdp]|=UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;}ubainitmaps(uhp)	register struct uba_hd *uhp;{	rminit(uhp->uh_map, (long)NUBMREG, (long)1, "uba", UAMSIZ);	if (uhp->uba_type&UBABUA) 		uhp->uh_bdpfree = (1<<NBDP_BUA) - 1;		else if(uhp->uba_type & UBA780)			uhp->uh_bdpfree = (1<<NBDP8600) - 1;	else if(uhp->uba_type & UBA750)		uhp->uh_bdpfree = (1<<NBDP750) - 1;}/* * Generate a reset on uba number uban.  Then * call each device in the character device table, * giving it a chance to clean up so as to be able to continue. */ubareset(uban)	int uban;{	register struct cdevsw *cdp;	register struct uba_hd *uh = &uba_hd[uban];	int s;	s = spl6();	uh->uh_users = 0;	uh->uh_zvcnt = 0;	uh->uh_xclu = 0;	uh->uh_actf = uh->uh_actl = 0;	uh->uh_bdpwant = 0;	uh->uh_mrwant = 0;	ubainitmaps(uh);	wakeup((caddr_t)&uh->uh_bdpwant);	wakeup((caddr_t)&uh->uh_mrwant);	if (uh->uba_type & UBABDA) {		printf("bda%d: reset",uban);	}	else if (uh->uba_type & UBAXMI) {		printf("kdm%d: reset",uban);	}	else {		printf("uba%d: reset", uban);		ubainit(uh->uh_uba,uh->uba_type);	}	/* reallocate global unibus space for tty drivers */	if (tty_ubinfo[uban] != 0)		tty_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,	    		nclist*sizeof (struct cblock), 0);	for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++)		(*cdp->d_reset)(uban);#ifdef INET	ifubareset(uban);#endif	printf("\n");	splx(s);}/* * Init a uba.  This is called with a pointer * rather than a virtual address since it is called * by code which runs with memory mapping disabled. * In these cases we really don't need the interrupts * enabled, but since we run with ipl high, we don't care * if they are, they will never happen anyways. */ubainit(uba,ubatype)	register int ubatype;	register struct uba_regs *uba;{	extern struct ssc_regs *ssc_ptr;	if (ubatype&UBA780) {		uba->uba_cr = UBACR_ADINIT;		uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;		while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0)			;	}	else if (ubatype&UBABUA) 		buainit(uba);#ifdef vax	else if (ubatype&(UBA750|UBA730|UBAUVI)) {		mtpr(IUR, 0);		/* give devices time to recover from power fail */		DELAY(500000);	}#endif vax	else if (ubatype&UBAUVII) {#define LMEA 0x20			/* Local memory access enable	*/#define QIPCR 0x1f40			/* Q-bus Inter-processor csr	*/		/*		 * Reset the bus and wait for the devices to		 * settle down		 */#ifdef vax		mtpr(IUR, 0);#endif vax#ifdef mips		ssc_ptr->ssc_ioreset = 0;  /* equiv to mtpr(IUR, 0) */#endif mips		DELAY(500000);		/*		 * The bus reset turns off the q-bus map (unfortunately)		 * The problem is further agravated by the fact that the		 * enable bit is in the IPC register which is in I/O space		 * instead of local register space.  Because of this we		 * have to figure out if we're virtual or physical.		 */#ifdef vax		if( mfpr(MAPEN) & 0x1 ) {			/*			 * Virtual			 */			*(u_short *)((char *)qmem+QMEMSIZEUVI+QIPCR) = LMEA;		} else {			/*			 * Physical			 */			*(u_short *)((char *)QDEVADDRUVI+QIPCR) = LMEA;		}#endif vax#ifdef mips		/*		 * We are on a Qbus mips machine.  The bus reset we just		 * did turned off the Qbus map.  We need to allow		 * external access to Qbus memory space via the Qbus map.		 * Since on a mips we always have memory management,		 * we access the IPCR (implemented in the CQBIC chip) 		 * through Kseg 1 space		 *		 * IPCR is a 16-bit register located in offset		 * 0x1f40 from the Q bus I/O space.  		 */		*(u_short *)((char *)qmem+QMEMSIZEUVI+QIPCR) = LMEA;#endif mips	}}int	ubawedgecnt = 10;int	ubacrazy = 500;/* * This routine is called by the locore code to * process a UBA error on an 11/780.  The arguments are passed * on the stack, and value-result (through some trickery). * In particular, the uvec argument is used for further * uba processing so the result aspect of it is very important. * It must not be declared register. *//*ARGSUSED*/ubaerror(uban, uh, xx, uvec, uba, ubapc)	register int uban;	register struct uba_hd *uh;	int uvec;	register struct uba_regs *uba;	int *ubapc;{	register int sr, s;	struct el_rec *elrp;	/*	 *	Start a timer to time the rate of zero vectors.	 *	The counting is done in locore.s.	 */	if (uvec == 0) {		if (uh->uh_zvflg)			mprintf("ubaerror: zero vector flag shouldn't be set\n");		else {			uh->uh_zvcnt++;			uh->uh_zvflg++;			timeout(ubatimer, uban, hz * zvintvl);		}		return;	}	if (uh->uba_type&UBABUA) {		sr = ((struct bua_regs *)uh->uh_uba)->bua_ctrl;		s = spl7();		printf("bua%d: bua error ctrl=%x",uban,sr); 		splx(s);		((struct bua_regs *)uh->uh_uba)->bua_ctrl = sr;		ubareset(uban);	}	else if ((uh->uba_type&UBABDA)==0) {			if (uba->uba_cnfgr & NEX_CFGFLT) {			elrp = ealloc(EL_UBASIZE,EL_PRILOW);			if (elrp != NULL) {			    LSUBID(elrp,ELCT_ADPTR,ELADP_UBA,EL_UNDEF,EL_UNDEF,uban,EL_UNDEF);		 	    elrp->el_body.eluba780.uba_cf = uba->uba_cnfgr;		 	    elrp->el_body.eluba780.uba_cr = uba->uba_cr;			    elrp->el_body.eluba780.uba_sr = uba->uba_sr;		 	    elrp->el_body.eluba780.uba_dcr = uba->uba_dcr;		 	    elrp->el_body.eluba780.uba_fmer = uba->uba_fmer;			    elrp->el_body.eluba780.uba_fubar = uba->uba_fubar;		 	    elrp->el_body.eluba780.uba_pc = *ubapc;		 	    elrp->el_body.eluba780.uba_psl = *++ubapc;			    EVALID(elrp);			}				else {				cprintf("uba%d: sbi fault sr=%b cnfgr=%b\n",				    uban, uba->uba_sr, ubasr_bits,				    uba->uba_cnfgr, NEXFLT_BITS);			}			ubareset(uban);			uvec = 0;			return;		}		sr = uba->uba_sr;		s = spl7();		elrp = ealloc(EL_UBASIZE,EL_PRILOW);		if (elrp != NULL) {		    LSUBID(elrp,ELCT_ADPTR,ELADP_UBA,EL_UNDEF,EL_UNDEF,uban,EL_UNDEF);	 	    elrp->el_body.eluba780.uba_cf = uba->uba_cnfgr;	 	    elrp->el_body.eluba780.uba_cr = uba->uba_cr;		    elrp->el_body.eluba780.uba_sr = uba->uba_sr;	 	    elrp->el_body.eluba780.uba_dcr = uba->uba_dcr;	 	    elrp->el_body.eluba780.uba_fmer = uba->uba_fmer;		    elrp->el_body.eluba780.uba_fubar = uba->uba_fubar;	 	    elrp->el_body.eluba780.uba_pc = *ubapc;	 	    elrp->el_body.eluba780.uba_psl = *++ubapc;		    EVALID(elrp);		}			else {			cprintf("uba%d: uba error sr=%b fmer=%x fubar=%o\n",			    uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);		}		splx(s);		uba->uba_sr = sr;		uvec &= UBABRRVR_DIV;	}	if (++uh->uh_errcnt % ubawedgecnt == 0) {		if (uh->uh_errcnt > ubacrazy)			panic("uba crazy");		printf("ERROR LIMIT ");		ubareset(uban);		uvec = 0;		return;	}	return;}/* * Allocate UNIBUS memory.  Allocates and initializes * sufficient mapping registers for access.  On a 780, * the configuration register is setup to disable UBA * response on DMA transfers to addresses controlled * by the disabled mapping registers. */ubamem(uban, addr, npg, doalloc)	int uban, addr, npg, doalloc;{	register struct uba_hd *uh = &uba_hd[uban];	register int a;	if (doalloc) {		int s = spl6();		a = rmget(uh->uh_map, npg, (addr >> 9) + 1);		splx(s);	} else		a = (addr >> 9) + 1;	if (a) {		register int i, *m;		m = (int *)&uh->uh_uba->uba_map[a - 1];		for (i = 0; i < npg; i++)			*m++ = 0;	/* All off, especially 'valid' */		/*		 * On a 780 and 8600, set up the map register disable

⌨️ 快捷键说明

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