File:  [MW Coherent from dump] / coherent / d / PS2_KERNEL / io.286 / dmareq.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* $Header: /var/lib/cvsd/repos/coherent/coherent/d/PS2_KERNEL/io.286/dmareq.c,v 1.1.1.1 2019/05/29 04:56:39 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */

/*
 * Like ioreq, but guarantee that no DMA straddle occurs.
 * And assume we are called by fl.c, xt.c, dv.c or someone
 * else who obeys the parameter rules that they do.
 *
 * $Log: dmareq.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:39  root
 * coherent
 *
 * Revision 1.1  92/07/17  15:24:08  bin
 * Initial revision
 * 
 * Revision 2.1	88/09/03  13:03:47	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:28	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * dmareq() now wakes &stimer only if the swap timer is active.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/dmac.h>

dmareq(bp, iop, dev, req)
register BUF *bp;
register IO *iop;
dev_t dev;
{
	register int n;
	register SEG *sp;
	register CON *cp;
	dold_t dold;
	long l;
	BUF *tbp;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	lock(bp->b_gate);
	n = cp->c_flag;
	drest(dold);
	if (blocko(iop->io_seek) != 0) {
		u.u_error = EIO;
		goto out;
	}
	if ((sp=iomapvp(iop, bp)) == NULL) {
		u.u_error = EIO;
		goto out;
	}
	bp->b_dev = dev;
	bp->b_flag = 0;
	sp->s_lrefc++;
	bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
	/*
	 * The dma address is 20 bits; 16 bit offset counter from a 4 bit
	 * base segment.  Since io_ioc is limited to 32Kb positive, we
	 * have at most two raw transfers separated by a block which
	 * straddles the segment boundary.
	 * Life would be simpler if we assumed io_ioc % BSIZE, but
	 * flioctl comes through here with it's short format buffer.
	 */
	while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
		l = dmaseg(bp->b_paddr+iop->io_ioc-1) - bp->b_paddr;
		if (l < 0)
			n = iop->io_ioc;
		else
			n = l & ~((long)BSIZE-1);
		l = blockn(iop->io_seek);
		if (n == 0) {
			/* Straddle block */
			tbp = bp;		/* Save the raw buffer */
			n = BSIZE;
			if (n > iop->io_ioc)
				n = iop->io_ioc;
			bp = bclaim(dev, l);
			bp->b_count = n;
			bp->b_req = req;
			if (req != BREAD)
				ioread(iop, FP_OFF(bp->b_faddr), n);
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) == 0) {
				if (req == BREAD)
					iowrite(iop, FP_OFF(bp->b_faddr), n);
			} else {
				tbp->b_flag = bp->b_flag;
				tbp->b_err = bp->b_err;
				if (req != BREAD)
					iop->io_ioc += bp->b_resid;
			}
			bp->b_flag |= BFERR;
			brelease(bp);
			bp = tbp;		/* Reclaim raw buffer */
		} else {
			/* Raw transfer */
			bp->b_count = n;
			bp->b_req = req;
			bp->b_bno = l;
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) != 0)
				n -= bp->b_resid;
			iop->io_ioc -= n;	/* cookedio do these */
			iop->io_base += n;	/* for everyone */
		}
		FP_OFF(bp->b_faddr) += n;
		bp->b_paddr  += n;
		iop->io_seek += n;
		/* And continue for the next chunk */
	}
	vrelse( bp->b_faddr );
	sp->s_lrefc--;
	if ( stimer.t_last != 0 )
		wakeup((char *)&stimer);
	if ((bp->b_flag&BFERR) != 0 && (u.u_error = bp->b_err) == 0)
		u.u_error = EIO;
out:
	unlock(bp->b_gate);
}

static
dmabuf(bp, dev)
register BUF *bp;
dev_t dev;
{
	register int s;
	bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
	s = sphi();
	dblock(dev, bp);
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.