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

📄 vba.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1987, 1988 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. * *	@(#)vba.c	7.6 (Berkeley) 12/16/90 *//* * Tahoe VERSAbus adapator support routines. */#include "sys/param.h"#include "sys/buf.h"#include "sys/cmap.h"#include "sys/conf.h"#include "dk.h"#include "sys/map.h"#include "sys/systm.h"#include "sys/user.h"#include "sys/vmparam.h"#include "sys/vmmac.h"#include "sys/proc.h"#include "sys/syslog.h"#include "sys/malloc.h"#include "../include/mtpr.h"#include "../include/pte.h"#include "../vba/vbavar.h"/* * Allocate private page map and intermediate buffer * for a VERSAbus device, large enough for maximum transfer size. * Intermediate buffer  * Make intermediate buffer uncacheable. */vbainit(vb, xsize, flags)	register struct vb_buf *vb;	int xsize, flags;{	register struct pte *pte;	register n;	vb->vb_flags = flags;	if (vbmapalloc((int)btoc(xsize) + 1, &vb->vb_map, &vb->vb_utl) == 0) {		printf("vbmap exhausted\n");		return (0);	}	n = roundup(xsize, NBPG);	vb->vb_bufsize = n;	if (vb->vb_rawbuf == 0)		vb->vb_rawbuf = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT);	if (vb->vb_rawbuf == 0) {		printf("no memory for device buffer\n");		return (0);	}	if ((int)vb->vb_rawbuf & PGOFSET)		panic("vbinit pgoff");	vb->vb_physbuf = (u_long)kvtophys(vb->vb_rawbuf);	if (flags & VB_20BIT)		vb->vb_maxphys = btoc(VB_MAXADDR20);	else if (flags & VB_24BIT)		vb->vb_maxphys = btoc(VB_MAXADDR24);	else		vb->vb_maxphys = btoc(VB_MAXADDR32);	if (btoc(vb->vb_physbuf + n) > vb->vb_maxphys)		panic("vbinit physbuf");		/*	 * Make raw buffer pages uncacheable.	 */	pte = kvtopte(vb->vb_rawbuf);	for (n = btoc(n); n--; pte++)		pte->pg_nc = 1;	mtpr(TBIA, 0);	return (1);}/* * Due to unknown hardware or software errors, some sites have problems * with strange crashes or corruption of text images when DMA is attempted * to kernel addresses spanning a page boundary, or to user addresses * (even if the buffer is physically contiguous).  To avoid this behavior, * the following toggles inhibit such transfers when set. *	vba_copyk: copy transfers to kernel address that span a page boundary *	vba_copyu: copy transfers to user addresses */#ifndef VBA_TRICKYint vba_copyk = 1;int vba_copyu = 1;#elseint vba_copyk = 0;int vba_copyu = 0;#endif/* * Check a transfer to see whether it can be done directly * to the destination buffer, or whether it must be copied. * On Tahoe, the lack of a bus I/O map forces data to be copied * to a physically-contiguous buffer whenever one of the following is true: *	1) The data length is not a multiple of sector size. *	   (The swapping code does this, unfortunately.) *	2) The buffer is not physically contiguous and the controller *	   does not support scatter-gather operations. *	3) The physical address for I/O is higher than addressible *	   by the device. * This routine is called by the start routine. * If copying is necessary, the intermediate buffer is mapped; * if the operation is a write, the data is copied into the buffer. * It returns the physical address of the first byte for DMA, to * be presented to the controller. */u_longvbasetup(bp, vb, sectsize)	register struct buf *bp;	register struct vb_buf *vb;	int sectsize;{	register struct pte *spte, *dpte;	register int p, i;	int npf, o, v;	o = (int)bp->b_un.b_addr & PGOFSET;	npf = btoc(bp->b_bcount + o);	vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);	if (vb->vb_iskernel) {		spte = kvtopte(bp->b_un.b_addr);if (vba_copyk && (o != 0 || npf > 1)) goto copy;	} else {		spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,		    btop(bp->b_un.b_addr));if (vba_copyu) goto copy;	}	if (bp->b_bcount % sectsize != 0 || (o & (sizeof(long) - 1)) != 0)		goto copy;	else if ((vb->vb_flags & VB_SCATTER) == 0 ||	    vb->vb_maxphys != btoc(VB_MAXADDR32)) {		dpte = spte;		p = (dpte++)->pg_pfnum;		for (i = npf; --i > 0; dpte++) {			if ((v = dpte->pg_pfnum) != p + CLSIZE &&			    (vb->vb_flags & VB_SCATTER) == 0)				goto copy;			if (p >= vb->vb_maxphys)				goto copy;			p = v;		}		if (p >= vb->vb_maxphys)			goto copy;	}	vb->vb_copy = 0;	if (vb->vb_iskernel)		vbastat.k_raw++;	else		vbastat.u_raw++;	return ((spte->pg_pfnum << PGSHIFT) + o);copy:	vb->vb_copy = 1;	if (bp->b_bcount > vb->vb_bufsize)		panic("vba xfer too large");	if (vb->vb_iskernel) {		if ((bp->b_flags & B_READ) == 0)			bcopy(bp->b_un.b_addr, vb->vb_rawbuf,			    (unsigned)bp->b_bcount);		vbastat.k_copy++;	} else  {		dpte = vb->vb_map;		for (i = npf, p = (int)vb->vb_utl; i--; p += NBPG) {			*(int *)dpte++ = (spte++)->pg_pfnum |			    PG_V | PG_KW | PG_N;			mtpr(TBIS, p);		}		if ((bp->b_flags & B_READ) == 0)			bcopy(vb->vb_utl + o, vb->vb_rawbuf,			    (unsigned)bp->b_bcount);		vbastat.u_copy++;	}	return (vb->vb_physbuf);}/* * Called by the driver's interrupt routine, after DMA is completed. * If the operation was a read, copy data to final buffer if necessary * or invalidate data cache for cacheable direct buffers. * Similar to the vbastart routine, but in the reverse direction. */vbadone(bp, vb)	register struct buf *bp;	register struct vb_buf *vb;{	register npf;	register caddr_t v;	int o;	if (bp->b_flags & B_READ) {		o = (int)bp->b_un.b_addr & PGOFSET;		if (vb->vb_copy) {			if (vb->vb_iskernel)				bcopy(vb->vb_rawbuf, bp->b_un.b_addr,				    (unsigned)(bp->b_bcount - bp->b_resid));			else {				bcopy(vb->vb_rawbuf, vb->vb_utl + o,				    (unsigned)(bp->b_bcount - bp->b_resid));				dkeyinval(bp->b_proc);			}		} else {			if (vb->vb_iskernel) {				npf = btoc(bp->b_bcount + o);				for (v = bp->b_un.b_addr; npf--; v += NBPG)					mtpr(P1DC, (int)v);			} else				dkeyinval(bp->b_proc);		}	}}/* * Set up a scatter-gather operation for SMD/E controller. * This code belongs half-way between {hd,vd}.c and this file. */#include "dk.h"#if NVD > 0#include "vdreg.h"vd_sgsetup(bp, vb, sg)	register struct buf *bp;	struct vb_buf *vb;	struct trsg *sg;{	register struct pte *spte;	register struct addr_chain *adr;	register int i;	int o;	vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);	vb->vb_copy = 0;	if (vb->vb_iskernel) {		spte = kvtopte(bp->b_un.b_addr);		vbastat.k_sg++;	} else {		spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,		    btop(bp->b_un.b_addr));		vbastat.u_sg++;	}	o = (int)bp->b_un.b_addr & PGOFSET;	i = min(NBPG - o, bp->b_bcount);	sg->start_addr.wcount = i >> 1;	sg->start_addr.memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;	i = bp->b_bcount - i;	if (i > VDMAXPAGES * NBPG)		panic("vba xfer too large");	i = i >> 1;	for (adr = sg->addr_chain; i > 0; adr++, i -= NBPG / 2) {		adr->nxt_addr = (spte++)->pg_pfnum << PGSHIFT;		adr->nxt_len = imin(i, NBPG / 2);	}	adr->nxt_addr = 0;	adr++->nxt_len = 0;	return ((adr - sg->addr_chain) * sizeof(*adr) / sizeof(long));}#endif#include "hd.h"#if NHD > 0#include "hdreg.h"hd_sgsetup(bp, vb, sg)	register struct buf *bp;	struct vb_buf *vb;	struct chain *sg;{	register struct pte *spte;	register struct addr_chain *adr;	register int i, cnt;	int o;	if (bp->b_bcount > HDC_MAXBC ||	    bp->b_bcount % sizeof(long) - 1 ||	    (u_int)bp->b_un.b_addr % sizeof(long) - 1)		return(0);	vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);	vb->vb_copy = 0;	if (vb->vb_iskernel) {		spte = kvtopte(bp->b_un.b_addr);		vbastat.k_sg++;	} else {		spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,		    btop(bp->b_un.b_addr));		vbastat.u_sg++;	}	o = (int)bp->b_un.b_addr & PGOFSET;	i = min(NBPG - o, bp->b_bcount);	sg->wcount = i >> 2;	sg->memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;	cnt = 0;	for (i = (bp->b_bcount - i) >> 2; i > 0; i -= NBPG / sizeof(long)) {		if (++cnt == HDC_MAXCHAIN)			return(0);		sg->wcount |= LWC_DATA_CHAIN;		++sg;		sg->wcount = imin(i, NBPG / sizeof(long));		sg->memadr = (spte++)->pg_pfnum << PGSHIFT;	}	return(1);}#endif

⌨️ 快捷键说明

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