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

📄 uba.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)uba.c	7.10 (Berkeley) 12/16/90 */#include "sys/param.h"#include "sys/systm.h"#include "sys/map.h"#include "sys/buf.h"#include "sys/vm.h"#include "sys/user.h"#include "sys/proc.h"#include "sys/conf.h"#include "sys/dkstat.h"#include "sys/kernel.h"#include "../include/pte.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "../vax/nexus.h"#include "ubareg.h"#include "ubavar.h"#ifdef DW780char	ubasr_bits[] = UBASR_BITS;#endif#define	spluba	spl7		/* IPL 17 *//* * Do transfer on device argument.  The controller * and uba involved are implied by the device. * We queue for resource wait in the uba code if necessary. * We return 1 if the transfer was started, 0 if it was not. * * The onq argument must be zero iff the device is not on the * queue for this UBA.  If onq is set, the device must be at the * head of the queue.  In any case, if the transfer is started, * the device will be off the queue, and if not, it will be on. * * Drivers that allocate one BDP and hold it for some time should * set ud_keepbdp.  In this case um_bdp tells which BDP is allocated * to the controller, unless it is zero, indicating that the controller * does not now have a BDP. */ubaqueue(ui, onq)	register struct uba_device *ui;	int onq;{	register struct uba_ctlr *um = ui->ui_mi;	register struct uba_hd *uh;	register struct uba_driver *ud;	register int s, unit;	uh = &uba_hd[um->um_ubanum];	ud = um->um_driver;	s = spluba();	/*	 * Honor exclusive BDP use requests.	 */	if (ud->ud_xclu && uh->uh_users > 0 || uh->uh_xclu)		goto rwait;	if (ud->ud_keepbdp) {		/*		 * First get just a BDP (though in fact it comes with		 * one map register too).		 */		if (um->um_bdp == 0) {			um->um_bdp = uballoc(um->um_ubanum,				(caddr_t)0, 0, UBA_NEEDBDP|UBA_CANTWAIT);			if (um->um_bdp == 0)				goto rwait;		}		/* now share it with this transfer */		um->um_ubinfo = ubasetup(um->um_ubanum,			um->um_tab.b_actf->b_actf,			um->um_bdp|UBA_HAVEBDP|UBA_CANTWAIT);	} else		um->um_ubinfo = ubasetup(um->um_ubanum,			um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT);	if (um->um_ubinfo == 0)		goto rwait;	uh->uh_users++;	if (ud->ud_xclu)		uh->uh_xclu = 1;	splx(s);	if (ui->ui_dk >= 0) {		unit = ui->ui_dk;		dk_busy |= 1<<unit;		dk_xfer[unit]++;		dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6;	}	if (onq)		uh->uh_actf = ui->ui_forw;	(*ud->ud_dgo)(um);	return (1);rwait:	if (!onq) {		ui->ui_forw = NULL;		if (uh->uh_actf == NULL)			uh->uh_actf = ui;		else			uh->uh_actl->ui_forw = ui;		uh->uh_actl = ui;	}	splx(s);	return (0);}ubadone(um)	register struct uba_ctlr *um;{	register struct uba_hd *uh = &uba_hd[um->um_ubanum];	if (um->um_driver->ud_xclu)		uh->uh_xclu = 0;	uh->uh_users--;	if (um->um_driver->ud_keepbdp)		um->um_ubinfo &= ~BDPMASK;	/* keep BDP for misers */	ubarelse(um->um_ubanum, &um->um_ubinfo);}/* * Allocate and setup UBA 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 encodes map register plus page offset, * bdp number and number of map registers. */ubasetup(uban, bp, flags)	int uban;	register struct buf *bp;	register int flags;{	register struct uba_hd *uh = &uba_hd[uban];	register struct pte *pte, *io;	register int npf;	int pfnum, temp;	int reg, bdp;	unsigned v;	struct proc *rp;	int a, o, ubinfo;#ifdef DW730	if (uh->uh_type == DW730)		flags &= ~UBA_NEEDBDP;#endif#ifdef QBA	if (uh->uh_type == QBA)		flags &= ~UBA_NEEDBDP;#endif	o = (int)bp->b_un.b_addr & PGOFSET;	npf = btoc(bp->b_bcount + o) + 1;	if (npf > UBA_MAXNMR)		panic("uba xfer too big");	a = spluba();	while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) {		if (flags & UBA_CANTWAIT) {			splx(a);			return (0);		}		uh->uh_mrwant++;		sleep((caddr_t)&uh->uh_mrwant, PSWP);	}	if ((flags & UBA_NEED16) && reg + npf > 128) {		/*		 * Could hang around and try again (if we can ever succeed).		 * Won't help any current device...		 */		rmfree(uh->uh_map, (long)npf, (long)reg);		splx(a);		return (0);	}	bdp = 0;	if (flags & UBA_NEEDBDP) {		while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) {			if (flags & UBA_CANTWAIT) {				rmfree(uh->uh_map, (long)npf, (long)reg);				splx(a);				return (0);			}			uh->uh_bdpwant++;			sleep((caddr_t)&uh->uh_bdpwant, PSWP);		}		uh->uh_bdpfree &= ~(1 << (bdp-1));	} else if (flags & UBA_HAVEBDP)		bdp = (flags >> 28) & 0xf;	splx(a);	reg--;	ubinfo = UBAI_INFO(o, reg, npf, bdp);	temp = (bdp << 21) | UBAMR_MRV;	if (bdp && (o & 01))		temp |= UBAMR_BO;	if ((bp->b_flags & B_PHYS) == 0)		pte = kvtopte(bp->b_un.b_addr);	else if (bp->b_flags & B_PAGET)		pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];	else {		rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;		v = btop(bp->b_un.b_addr);		if (bp->b_flags & B_UAREA)			pte = &rp->p_addr[v];		else			pte = vtopte(rp, v);	}	io = &uh->uh_mr[reg];	while (--npf > 0) {		pfnum = pte->pg_pfnum;		if (pfnum == 0)			panic("uba zero uentry");		pte++;		*(int *)io++ = pfnum | temp;	}	*(int *)io = 0;	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 = spluba();	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;	bdp = UBAI_BDP(mr);	if (bdp) {		switch (uh->uh_type) {#ifdef DWBUA		case DWBUA:			BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;			break;#endif#ifdef DW780		case DW780:			uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;			break;#endif#ifdef DW750		case DW750:			uh->uh_uba->uba_dpr[bdp] |=			    UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;			break;#endif		default:			break;		}		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,	 * nor can the registers be freed twice.	 * Unblock interrupts once this is done.	 */	npf = UBAI_NMR(mr);	reg = UBAI_MR(mr) + 1;	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 && ubaqueue(uh->uh_actf, 1))		;}ubapurge(um)	register struct uba_ctlr *um;{	register struct uba_hd *uh = um->um_hd;	register int bdp = UBAI_BDP(um->um_ubinfo);	switch (uh->uh_type) {#ifdef DWBUA	case DWBUA:		BUA(uh->uh_uba)->bua_dpr[bdp] |= BUADPR_PURGE;		break;#endif#ifdef DW780	case DW780:		uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;		break;#endif#ifdef DW750	case DW750:		uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;		break;#endif	default:		break;	}

⌨️ 快捷键说明

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