Coherent4.2.10/i386/fakedma.c
/* $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;
}