Coherent4.2.10/i386/fakedma.c

Compare this file to the similar file:
Show the results in this format:

/* $Header: /ker/i386/RCS/fakedma.c,v 2.5 93/10/29 00:56:44 nigel Exp Locker: nigel $ */
/*
 * these routines are written in C until the 386 compiler/assembler
 * are available
 *
 * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
 *
 * $Log:	fakedma.c,v $
 * Revision 2.5  93/10/29  00:56:44  nigel
 * R98 (aka 4.2 Beta) prior to removing System Global memory
 * 
 * Revision 2.4  93/09/02  18:11:13  nigel
 * Remove unreferenced globals
 * 
 * Revision 2.3  93/08/19  03:40:02  nigel
 * Nigel's R83
 */

#include <sys/debug.h>
#include <sys/inline.h>
#include <sys/errno.h>
#include <sys/cmn_err.h>
#include <signal.h>

#define	_KERNEL		1

#include <kernel/reg.h>
#include <sys/mmu.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>

#include <coh/fakedma.h>

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

#define	OLD_DMA		0


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

void
dmacopy(npage, from, to) 
long	npage;
cseg_t	*from, *to;
{
	ASSERT (npage > 0);

	for (;;) {
		cseg_t		src = * from ++ & ~ (NBPC - 1);
		cseg_t		dest = * to ++ & ~ (NBPC - 1);

		memcpy (__PTOV (dest), __PTOV (src), NBPC);

		if (-- npage == 0)
			break;
	}
}


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

void
dmaclear (nbytes, to)
int	nbytes;
paddr_t	to;
{
	while (nbytes > 0) {

		unsigned int start_offset, x;

		/* Compute offset within page of starting s.g. address. */
		start_offset = to & (NBPC - 1);

		/* Compute number of bytes from "to" through end of page. */
		x = NBPC - start_offset;

		/* Bytes to clear is minimum of "nbytes" and "x". */
		if (x > nbytes)
			x = nbytes;

		/* Clear bytes.  Stay within a single system global page. */
		memset (__PTOV (P2P (to)), 0, x);

		/* Update start address and byte count. */
		to += x;
		nbytes -= x;
	}
}


/*
 * dmain()
 * 
 * Copy in "nbytes" from system global address "to" to kernel address
 * "vaddr".
 */

void
dmain(nbytes, to, vaddr)
long	nbytes;
paddr_t	to;
caddr_t	vaddr;
{
	while (nbytes > 0) {

		unsigned int start_offset, x;

		/* Compute offset within page of starting s.g. address. */
		start_offset = to & (NBPC - 1);

		/* Compute number of bytes from "to" through end of page. */
		x = NBPC - start_offset;

		/* Bytes to copy is minimum of "nbytes" and "x". */
		if (x > nbytes)
			x = nbytes;

		/* Copy bytes.  Stay within a single system global page. */
		memcpy (vaddr, __PTOV (P2P (to)), x);

		/* Update start addresses and byte count. */
		to += x;
		vaddr += x;
		nbytes -= x;
	}
}


/*
 * dmaout()
 * 
 * Copy out "nbytes" from kernel address "vaddr" to system global address
 * "to".
 */

void
dmaout(nbytes, to, vaddr)
long	nbytes;
paddr_t	to;
caddr_t	vaddr;
{
	while (nbytes > 0) {

		unsigned int start_offset, x;

		/* Compute offset within page of starting s.g. address. */
		start_offset = to & (NBPC - 1);

		/* Compute number of bytes from "to" through end of page. */
		x = NBPC - start_offset;

		/* Bytes to copy is minimum of "nbytes" and "x". */
		if (x > nbytes)
			x = nbytes;

		/* Copy bytes.  Stay within a single system global page. */
		memcpy (__PTOV (P2P (to)), vaddr, x);

		/* Update start addresses and byte count. */
		to += x;
		vaddr += x;
		nbytes -= x;
	}
}


/*
 * 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	SEL_386_KD
 * Up to one click of data can be copied. No alignment restrictions
 * on "uo" apply.
 */

#if __USE_PROTO__
int pxcopy(__paddr_t uo, __caddr_t v, int n, int space)
#else
int
pxcopy(uo, v, n, space)
__paddr_t uo;
char	*v;
int n;
int space;
#endif
{
	cseg_t	      *	base;
	int		save;
	int		err;
	int		work;

	if (n > NBPC || n == 0)
		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      SEL_386_KD
 *      "v" must be an address accessible to the user    SEL_386_UD
 * Up to one click of data can be copied. No alignment restrictions on "uo"
 * apply.
 */

#if __USE_PROTO__
int xpcopy(__caddr_t v, __paddr_t uo, int n, int space)
#else
int
xpcopy(v, uo, n, space)
__caddr_t *v;
__paddr_t uo;
int n;
int space;
#endif
{
	cseg_t	      *	base;
	int		save;
	int		err;
	int		work;

	if (n > NBPC || n == 0)
		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;
}