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

📄 uba.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * field in the configuration register.  Beware		 * of callers that request memory ``out of order''.		 */		if (uh->uba_type & UBA780) {			int cr = uh->uh_uba->uba_cr;			i = (addr + npg * 512 + 8191) / 8192;			if (i > (cr >> 26))				uh->uh_uba->uba_cr |= i << 26;		}	}	return (a);}#ifdef vax#include "ik.h"#if NIK > 0/* * Map a virtual address into users address space. Actually all we * do is turn on the user mode write protection bits for the particular * page of memory involved. */maptouser(vaddress)	caddr_t vaddress;{	Sysmap[(((unsigned)(vaddress))-0x80000000) >> 9].pg_prot = (PG_UW>>27);}unmaptouser(vaddress)	caddr_t vaddress;{	Sysmap[(((unsigned)(vaddress))-0x80000000) >> 9].pg_prot = (PG_KW>>27);}#endif#endif vax/* *  Check the number of zero vectors and report if we get too many of them. *  Always reset the zero vector count and the zero vector timer flag. */ubatimer(uban)int	uban;{	struct uba_hd *uh;	uh = &uba_hd[uban];	if(uh->uh_zvcnt > zvthresh)		mprintf("ubatimer: uba%d -- %d zero vectors in %d minutes\n",			uban, uh->uh_zvcnt, zvintvl/60);	uh->uh_zvcnt = 0;	uh->uh_zvflg = 0;}#ifdef vax/* * vs_bufctl is the locking mechanism that allows the VAXSTAR disk * tape controllers to share a common I/O buffer. * * This routine MUST be called from spl5. */struct vsbuf vsbuf = { 0, 0, 0 };vs_bufctl(vsdev)struct vsdev *vsdev;{    register struct vsbuf *vs = &vsbuf;    register int rval;    struct vsdev *temp;    int action;    int s;    action = vsdev->vsd_action;    for (;;) {	switch (action) {	    case VS_DEALLOC:		if (vs->vs_active == 0)		    panic("vs_bufctl: VS_DEALLOC: no owner");		if (vs->vs_wants) {		    if (vs->vs_wants->vsd_id != vs->vs_active->vsd_id) {			vs->vs_active = vs->vs_wants;			vs->vs_status = vs->vs_active->vsd_id;			vs->vs_wants = VS_IDLE;		    }		    else {			panic("vs_bufctl: VS_DEALLOC: wanted by owner");			return;		    }		}		else {			vs->vs_active = VS_IDLE;			vs->vs_status = VS_IDLE;			return;		}		break;	    case VS_ALLOC:		if (vs->vs_active == 0) {		    vs->vs_active = vsdev;		    vs->vs_status = vsdev->vsd_id;		}		else {			vs->vs_wants = vsdev;			return;		}		break;	    case VS_KEEP:		return;		break;	  	    case VS_WANTBACK:		if (vs->vs_wants) {		    if(vs->vs_active == 0) {			panic("vs_bufctl: VS_WANTBACK: not active");		    }		    temp = vs->vs_active;		    vs->vs_active = vs->vs_wants;		    vs->vs_status = vs->vs_active->vsd_id;		    vs->vs_wants = temp;		    vs->vs_wants->vsd_action = VS_ALLOC;		}		break;	    default:		panic("vs_bufctl: unknown action");		break;	}	if (vs->vs_active != 0) {	    action = (*vs->vs_active->vsd_funcptr)(); /* call to stc or sdc driver */	    if(action == VS_ALLOC) {		panic("vs_bufctl: illegal VS_ALLOC returned");	    }	    vs->vs_active->vsd_action = action;	}	else {	    panic("vsbufctl: active pointer null");	    return;	}    } /* forever */}#endif vax/* * Allocate and setup Q-BUS map registers, and bdp's * Flags says whether bdp is needed, whether the caller can't * wait (e.g. if the caller is at interrupt level). * * Return value: *	Bits 0-8	Byte offset 		512  number of bytes *	Bits 9-21	Start map reg. no.	all the 8192 regs *	Bits 22-31	No. mapping reg's allocated, divided by 8 */qbasetup(uban, bp, flags)	struct buf *bp;{	register struct uba_hd *uh = &uba_hd[uban];	int npf, reg, fake_npf;	unsigned v;	register struct pte *pte, *io;	struct proc *rp;	int a, o, ubinfo, vax_pfn;	static int first_time = 0;	int user_addr = 0;#ifdef mips	int	mips_of;		  /* offset within a mips page	*/	int	mips_pfn;		  /* PFN of a mips pte		*/#endif mips	flags &= ~UBA_NEEDBDP;	/* The first time through to get map registers allocate 512 of them	 * and never use them or give them back.  This will allow any calls	 * from a users driver to uballoc to get these without conflicts with 	 * the ones this routine controls.	 * This is done for backward compatability.	 */	if( first_time == 0) {		first_time = 1;		rmalloc(uh->uq_map, (long)(btoc(QBNOTUB * NBPG) + 1));	}	/* Find the page, offset into the page and the number of vax	 * page frames that will be needed.  This code will work for mips	 * also because we will simulate vax pfn's when infact one mips	 * pfn is equal to eight (8) vax pfn's.	 */	v = btop(bp->b_un.b_addr);	o = (int)bp->b_un.b_addr & 0x1ff; /* offset within a VAX page */#ifdef mips	/* offset within a mips page */	mips_of = (int)bp->b_un.b_addr & PGOFSET;#endif mips	/* 	 * Number of VAX pages spanned by the buffer + 1(hence number of	 * map registers needed since we need one guard page)	 */	npf = (((unsigned)(bp->b_bcount + o)+0x1ff) >> 9) + 1; 	/* get regs in groups of 8 to allow the ubinfo word to	 * hold all the information.  This may be a waste of maps but	 * it gets us closer to using all 8K maps on a Q22 bus, we need	 * to do this because we can't get all the information into	 * the returned integer. Sigh!	 *	 * Also MIPS uses 1 map where VAX looks for 8 so if its on	 * a MIPS system fake_npf is really the vax maps needed.	 *	 */	fake_npf = (npf + (8 - (npf % 8)));	/* Allocate the map registers for use by calling rmalloc	 */	a = spl6();	while ((reg = rmalloc(uh->uq_map, (long)fake_npf)) == 0) {		if (flags & UBA_CANTWAIT) {			splx(a);			return (0);		}		uh->uh_mrwant++;		sleep((caddr_t)&uh->uh_mrwant, PSWP);	}	splx(a);	/* Setup the return value which holds the map register number	 * and related info.	 */	reg--;	ubinfo = ((reg & 0x1fff) << 9) | o;	ubinfo |= ((fake_npf /8) << 22);	/* Now load the map registers with the pfn data.  This is not a 	 * straight forward task.  The pfn data is different on the vax and 	 * mips systems AND the mips sometimes uses its pfn's and othertimes	 * it uses physical.  The following code fragment will set up the	 * map register based on this data.	 */	/* running process */	rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;	pte = 0;	if ((bp->b_flags & B_PHYS) == 0) {	/* Not Physical */#ifdef vax		pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];#else			/* mips KSEG Addressing */	        if(IS_KSEG0(bp->b_un.b_addr)){ 			/* unmapped KSEG areas */                	mips_pfn = btop(K0_TO_PHYS(bp->b_un.b_addr));	        } else if(IS_KSEG1(bp->b_un.b_addr)){			/* unmapped KSEG areas */                	mips_pfn = btop(K1_TO_PHYS(bp->b_un.b_addr));	        } else if(IS_KSEG2(bp->b_un.b_addr)){			/* mapped KSEG areas */	                pte = &Sysmap[btop(bp->b_un.b_addr - K2BASE)];        	}#endif vax	}	else if (bp->b_flags & B_UAREA)		/* User area */		pte = &rp->p_addr[v];	else if (bp->b_flags & B_PAGET)		/* Page Table */		pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];	else if ((bp->b_flags & B_SMEM)  &&	/* SHMEM */					((bp->b_flags & B_DIRTY) == 0))		pte = ((struct smem *)rp)->sm_ptaddr + v;	else {		pte = vtopte(rp, v);		user_addr++;	}	if ((uh->uba_type & UBAUVI) ==0 || (flags&UBA_MAPANYWAY)) {		/* get address of starting UNIBUS map register */		io = &uh->uh_uba->uba_map[reg];                /* Loop to load all the map registers with pte information.                 * For a mips we need to simulate vax pte structures.		 *		 * On a VAX, we have npf map registers to fill, each		 * map register is to be filled by a VAX pte.		 *		 * On a mips, we have npf map registers to fill, but		 * each mips page is 4KB, so we have fewer mips ptes		 * to use.		 *		 * The following loop iterates for each map register.                 */		while (--npf != 0) {#ifdef mips			if(pte != 0)			{	/* pte points to the mips pte */				if (pte->pg_pfnum == 0)					panic("uba zero uentry");				vax_pfn = (pte->pg_pfnum << 3) + 					  (mips_of / 0x200);			} else {				/* There are no pte's, use pfn's				 */				vax_pfn = (mips_pfn << 3) +					  (mips_of / 0x200);			}			*(int *)io++ = vax_pfn | UBAMR_MRV;			mips_of += 0x200; /* next vax page */			if (mips_of >= 0x1000) {				/* Crossing mips page boundary */				/* Go on to next mips page */				mips_of -= 0x1000;				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 | UBAMR_MRV;			v++;#endif mips		}		*(int *)io++ = 0;		WBFLUSH;	} else	{		ubinfo = contigphys( ubinfo, bp->b_bcount, pte);		++reg;		a = spl6();		rmfree( uh->uq_map, (long)fake_npf, (long)reg);		splx(a);	}	return (ubinfo);}/* * Non buffer setup interface... set up a buffer and call ubasetup. */qballoc(uban, addr, bcnt, flags)	int uban;	caddr_t addr;	int bcnt, flags;{	struct buf qbbuf;	qbbuf.b_un.b_addr = addr;	qbbuf.b_flags = B_BUSY;	qbbuf.b_bcount = bcnt;	/* that's all the fields qbasetup() needs */	return (qbasetup(uban, &qbbuf, 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. */qbarelse(uban, amr)	unsigned *amr;{	register struct uba_hd *uh = &uba_hd[uban];	register int  reg, npf, s;	unsigned 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 */	/*	 * Put back the registers in the resource map.	 * The map code must not be reentered, so we do this	 * at high ipl.	 */	npf = (mr >> 22) * 8;	reg = (((mr >> 9) & QBREGMASK) + 1);	s = spl6();	rmfree(uh->uq_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))		;}

⌨️ 快捷键说明

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