BSD 4_3_Reno release
[unix-history] / usr / src / sys / vax / mem.c
/*
* Copyright (c) 1982, 1986, 1990 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)mem.c 7.4 (Berkeley) 4/3/90
*/
/*
* Memory special file
*/
#include "pte.h"
#include "param.h"
#include "user.h"
#include "conf.h"
#include "buf.h"
#include "systm.h"
#include "vm.h"
#include "cmap.h"
#include "mtpr.h"
mmrw(dev, uio, flags)
dev_t dev;
struct uio *uio;
int flags;
{
register int o;
register u_int c, v;
register struct iovec *iov;
int error = 0;
extern int umbabeg, umbaend;
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 |
(uio->uio_rw == UIO_READ ? PG_KR : PG_KW);
mtpr(TBIS, vmmap);
o = (int)uio->uio_offset & PGOFSET;
c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
c = MIN(c, (u_int)(NBPG - o));
c = MIN(c, (u_int)iov->iov_len);
error = uiomove((caddr_t)&vmmap[o], (int)c, uio);
continue;
/* minor device 1 is kernel memory */
case 1:
if ((caddr_t)uio->uio_offset < (caddr_t)&umbabeg &&
(caddr_t)uio->uio_offset + uio->uio_resid >= (caddr_t)&umbabeg)
goto fault;
if ((caddr_t)uio->uio_offset >= (caddr_t)&umbabeg &&
(caddr_t)uio->uio_offset < (caddr_t)&umbaend)
goto fault;
c = iov->iov_len;
if (!kernacc((caddr_t)uio->uio_offset, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
goto fault;
error = uiomove((caddr_t)uio->uio_offset, (int)c, uio);
continue;
/* minor device 2 is EOF/RATHOLE */
case 2:
if (uio->uio_rw == UIO_WRITE)
uio->uio_resid = 0;
return (0);
/* minor device 3 is unibus memory (addressed by shorts) */
case 3:
c = iov->iov_len;
if (!kernacc((caddr_t)uio->uio_offset, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
goto fault;
if (!useracc(iov->iov_base, c,
uio->uio_rw == UIO_READ ? B_WRITE : B_READ))
goto fault;
error = UNIcpy((caddr_t)uio->uio_offset, iov->iov_base,
(int)c, uio->uio_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);
}
/*
* UNIBUS Address Space <--> User Space transfer
*/
UNIcpy(uniadd, usradd, n, rw)
caddr_t uniadd, usradd;
register int n;
enum uio_rw rw;
{
register short *from, *to;
if (rw == UIO_READ) {
from = (short *)uniadd;
to = (short *)usradd;
} else {
from = (short *)usradd;
to = (short *)uniadd;
}
for (n >>= 1; n > 0; n--)
*to++ = *from++;
return (0);
}