date and time created 85/07/21 20:20:52 by sam
[unix-history] / usr / src / sys / tahoe / tahoe / mem.c
/* mem.c 1.1 85/07/21 */
/*
* Memory special file
*/
#include "../machine/pte.h"
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/systm.h"
#include "../h/vm.h"
#include "../h/cmap.h"
#include "../h/uio.h"
#include "../machine/mtpr.h"
mmread(dev, uio)
dev_t dev;
struct uio *uio;
{
return (mmrw(dev, uio, UIO_READ));
}
mmwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
return (mmrw(dev, uio, UIO_WRITE));
}
mmrw(dev, uio, rw)
dev_t dev;
struct uio *uio;
enum uio_rw rw;
{
register int o;
register u_int c, v;
register struct iovec *iov;
int error = 0;
extern int vmembeg, vmemend;
while (uio->uio_resid > 0 && error == 0) {
iov = uio->uio_iov;
if (iov->iov_len == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
if (uio->uio_iovcnt < 0)
panic("mmrw");
continue;
}
switch (minor(dev)) {
/* minor device 0 is physical memory */
case 0:
v = btop(uio->uio_offset);
if (v >= physmem)
goto fault;
*(int *)mmap = v | PG_V |
(rw == UIO_READ ? PG_KR : PG_KW);
mtpr(vmmap, TBIS);
o = (int)uio->uio_offset & PGOFSET;
c = min((u_int)(NBPG - o), (u_int)iov->iov_len);
c = min(c, (u_int)(NBPG - ((int)iov->iov_base&PGOFSET)));
error = uiomove((caddr_t)&vmmap[o], (int)c, rw, uio);
continue;
/* minor device 1 is kernel memory */
case 1:
if ((caddr_t)uio->uio_offset < (caddr_t)&vmembeg &&
(caddr_t)uio->uio_offset + uio->uio_resid >= (caddr_t)&vmembeg)
goto fault;
if ((caddr_t)uio->uio_offset >= (caddr_t)&vmembeg &&
(caddr_t)uio->uio_offset < (caddr_t)&vmemend)
goto fault;
c = iov->iov_len;
if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE))
goto fault;
error = uiomove((caddr_t)uio->uio_offset, (int)c, rw, uio);
continue;
/* minor device 2 is EOF/RATHOLE */
case 2:
if (rw == UIO_READ)
return (0);
c = iov->iov_len;
break;
/* minor device 3 is versabus memory (addressed by shorts) */
case 3:
c = iov->iov_len;
if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE))
goto fault;
if (!useracc(iov->iov_base, c, rw == UIO_READ ? B_WRITE : B_READ))
goto fault;
error = VERSAcpy((caddr_t)uio->uio_offset, iov->iov_base,
(int)c, rw);
break;
}
if (error)
break;
iov->iov_base += c;
iov->iov_len -= c;
uio->uio_offset += c;
uio->uio_resid -= c;
}
return (error);
fault:
return (EFAULT);
}
/*
* VERSABUS Address Space <--> User Space transfer
*/
VERSAcpy(versaadd, usradd, n, rw)
caddr_t versaadd, usradd;
register int n;
enum uio_rw rw;
{
register short *from, *to;
if(((int)versaadd&1) || ((int)usradd&1))
return (EFAULT);
if (rw == UIO_READ) {
from = (short *)versaadd;
to = (short *)usradd;
} else {
from = (short *)usradd;
to = (short *)versaadd;
}
for (n >>= 1; n > 0; n--)
*to++ = *from++;
return (0);
}