File:  [MW Coherent from dump] / coherent / b / STREAMS / i386 / fakedma.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * these routines are written in C until the 386 compiler/assembler
 * are available
 *
 * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
 */

#include <sys/debug.h>
#include <kernel/reg.h>

#include <sys/coherent.h>
#include <sys/clist.h>
#include <sys/errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>
#include <sys/buf.h>

#define	min(a, b)	((a) < (b) ? (a) : (b))

/*
 * dmacopy()
 *
 * Copy "npage" 4 kbyte pages from phys addr "from" to phys addr "to".
 */

dmacopy(npage, from, to) 
long	npage;
cseg_t	*from, *to;
{
	int work = workAlloc ();	/* Get a virtual click pair. */

	ASSERT (npage > 0);

	for (;;) {
		ptable1_v [work] = * from ++ | SEG_SRW;
		ptable1_v [work + 1] = * to ++ | SEG_SRW;
		memcpy (ctob (work + 1), ctob (work), NBPC);

		if (-- npage == 0)
			break;

		mmuupd ();		/* flush paging TLB */
	}

	workFree(work);
}

/*
 * dmaclear()
 *
 * Given a byte count, and a system global address, zero-fill the memory.
 */

void
dmaclear (nbytes, to)
long	nbytes;
paddr_t	to;
{
	unsigned off;
	int	n;
	cseg_t *base;
	int work = workAlloc ();	/* Get a virtual click pair. */

	off = to & (NBPC - 1);
	base = & sysmem.u.pbase [btocrd (to)];
	n = min (nbytes, NBPC - off);
	ptable1_v [work] = * base ++ | SEG_SRW;

	memset (ctob (work) + off, 0, n);
	nbytes -= n;

	while (nbytes > 0) {
		n = min (nbytes, NBPC);
		ptable1_v [work] = * base ++ | SEG_SRW;
		mmuupd ();

		memset (ctob (work), 0, n);
		nbytes -= n;
	}

	workFree(work);
}

/*
 * dmain()
 * 
 * Copy in "nbytes" from system global address "to" to kernel address
 * "vaddr".
 */
dmain(nbytes, to, vaddr)
long	nbytes;
paddr_t	to;
caddr_t	vaddr;
{
	unsigned off;
	unsigned	n, n1;
	cseg_t* base;
	int work = workAlloc ();	/* Get a virtual click pair. */

	off = to & (NBPC - 1);
	base = & sysmem.u.pbase [btocrd (to)];

	n = min (nbytes, NBPC - off);
	ptable1_v [work] = * base ++ | SEG_SRW;

	memcpy (vaddr, ctob (work) + off, n);
	vaddr += n;
	nbytes -= n;

	while (nbytes > 0) {
		n = min (nbytes, NBPC);
		ptable1_v [work] = * base ++ | SEG_SRW;
		mmuupd ();

		memcpy (vaddr, ctob (work), n);
		vaddr += n;
		nbytes -= n;
	}

	workFree (work);
}

/*
 * dmaout()
 * 
 * Copy out "nbytes" from kernel address "vaddr" to system global address
 * "to".
 */
dmaout(nbytes, to, vaddr)
long	nbytes;
paddr_t	to;
caddr_t	vaddr;
{
	unsigned off;
	unsigned	n, n1;
	cseg_t *base;
	int work = workAlloc ();	/* Get a virtual click pair. */

	off = to & (NBPC - 1);
	base = & sysmem.u.pbase [btocrd (to)];

	n = min (nbytes, NBPC - off);
	ptable1_v [work] = * base ++ | SEG_SRW;

	memcpy (ctob (work) + off, vaddr, n);
	vaddr += n;
	nbytes -= n;

	while (nbytes > 0) {
		n = min (nbytes, NBPC);
		ptable1_v [work] = * base ++ | SEG_SRW;
		mmuupd ();

		memcpy (ctob (work), vaddr, n);
		vaddr += n;
		nbytes -= n;
	}

	workFree(work);
}

/*
 * dmaio2()
 * 
 * Copy in "nbytes" from an I/O port "port" to the system global address
 * "to".
 */
dmaio2(nbytes, to, port)
long	nbytes, port;
paddr_t	to;
{
	unsigned off;
	int	n;
	cseg_t *base;
	int work = workAlloc ();	/* Get a virtual click pair. */

	off = to & (NBPC - 1);
	base = & sysmem.u.pbase [btocrd (to)];

	n = min (nbytes, NBPC - off);
	ptable1_v [work] = * base ++ | SEG_SRW;
	
	io2seg (n, ctob (work) + off, port);
	nbytes -= n;

	while (nbytes > 0) {
		n = min (nbytes, NBPC);
		ptable1_v [work] = * base ++ | SEG_SRW;
		mmuupd ();
		io2seg(n, ctob (work), port);
		nbytes -= n;
	}

	workFree(work);
}

/*
 * dma2io()
 * 
 * Copy out "nbytes" from the system global address "from" to an I/O port
 * "port".
 */
dma2io(nbytes, to, port)
long	nbytes, port;
paddr_t	to;
{
	unsigned off;
	int	n;
	cseg_t *base;
	int work = workAlloc ();	/* Get a virtual click pair. */

	off = to & (NBPC - 1);
	base = & sysmem.u.pbase [btocrd (to)];

	n = min (nbytes, NBPC - off);
	ptable1_v [work] = * base ++ | SEG_SRW;
	
	seg2io (n, ctob (work) + off, port);
	nbytes -= n;

	while (nbytes > 0) {
		n = min (nbytes, NBPC);
		ptable1_v [work] = * base ++ | SEG_SRW;
		mmuupd ();
		seg2io (n, ctob (work), port);
		nbytes -= n;
	}

	workFree(work);
}

/*
 * pxcopy()
 *
 * copy "n" bytes of data at kernel address "v" from address "uo" in:
 * 	system global address space		(space & SEG_VIRT)
 * 	physical memory				! (space & SEG_VIRT)
 * Rights are determined by (space & ~ SEG_VIRT):
 * 	"v" can be anywhere in kernel address space	SEG_386_KD
 * 	"v" must be an address accessible to the user	SEG_386_UD
 * Up to one click of data can be copied. No alignment restrictions
 * on "uo" apply.
 */
pxcopy(uo, v, n, space)
unsigned	uo;
char	*v;
register int n;
{
	cseg_t	      *	base;
	int		save;
	int		err;
	int		work;

	if (n > NBPC)
		return 0;

	work = workAlloc ();

	if (space & SEG_VIRT) {
		space &= ~ SEG_VIRT;
		base = & sysmem.u.pbase [btocrd (uo)];
		ptable1_v [work] = * base ++ | SEG_SRW;
		ptable1_v [work + 1] = * base ++ | SEG_SRW;
	} else {
		ptable1_v [work] = (uo & ~ (NBPC - 1)) + SEG_SRW;
		ptable1_v [work + 1] = (uo & ~ (NBPC - 1)) + NBPC + SEG_SRW;
	}

	save = setspace (space);
	err = kucopy (ctob (work) + (uo & (NBPC - 1)), v, n);
	setspace (save);

	workFree (work);
	return err;
}


/*
 * xpcopy()
 * 
 * copy "n" bytes of data from kernel address "v" to address "uo" in:
 *      system global address space                      (space&SEG_VIRT)
 *      physical memory                                 !(space&SEG_VIRT)
 * Rights are determined by (space&~SEG_VIRT):
 *      "v" can be anywhere in kernel address space      SEG_386_KD
 *      "v" must be an address accessible to the user    SEG_386_UD
 * Up to one click of data can be copied. No alignment restrictions on "uo"
 * apply.
 */

xpcopy(v, uo, n, space)
char	*v;
unsigned uo;
register int n;
{
	cseg_t	      *	base;
	int		save;
	int		err;
	int		work;

	if (n > NBPC)
		return 0;

	work = workAlloc ();

	if (space & SEG_VIRT) {
		space &= ~ SEG_VIRT;
		base = & sysmem.u.pbase [btocrd (uo)];
		ptable1_v [work] = * base ++ | SEG_SRW;
		ptable1_v [work + 1] = * base ++ | SEG_SRW;
	} else {
		ptable1_v [work] = (uo & ~ (NBPC - 1)) + SEG_SRW;
		ptable1_v [work + 1] = (uo & ~ (NBPC - 1)) + NBPC + SEG_SRW;
	}

	save = setspace (space);
	err = ukcopy (v, ctob (work) + (uo & (NBPC - 1)), n);
	setspace (save);

	workFree (work);
	return err;
}

unix.superglobalmegacorp.com

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