V8/usr/sys/dev/mem.c
/* mem.c 4.3 81/03/08 */
/*
* Memory special file
* minor device 0 is physical memory
* minor device 1 is kernel memory
* minor device 2 is EOF/RATHOLE
* minor device 3 is unibus memory (addressed by shorts)
* minor device 4 is public part of kernel memory (read only)
* minor device 5 is processor registers
*/
#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/pte.h"
#include "../h/mtpr.h"
#include "../h/vm.h"
#include "../h/cmap.h"
#include "sparam.h"
#define SYSADR ((caddr_t)0x80000000) /* virtual address of system seg. */
#ifndef NBLKBIG
#define NBLKBIG 0
#endif
#define NBLKDATA (1024*NBLKBIG + 64*NBLK64 + 16*NBLK16 + 4*NBLK4)
extern u_char blkdata[];
mmread(dev)
{
register int o; long lbuf;
register unsigned c, v;
switch (minor(dev)) {
case 0:
while (u.u_count != 0 && u.u_error == 0) {
if (fubyte(u.u_base) == -1)
goto fault;
v = btop(u.u_offset);
*(int *)mmap = v | (PG_V | PG_KR);
mtpr(TBIS, vmmap);
o = (int)u.u_offset & PGOFSET;
c = min((unsigned)(NBPG - o), u.u_count);
c = min(c, (unsigned)(NBPG - ((int)u.u_base&PGOFSET)));
if (copyout((caddr_t)&vmmap[o], u.u_base, c))
goto fault;
u.u_count -= c;
u.u_base += c;
u.u_offset += c;
}
return;
case 1:
c = u.u_count;
if (copyout((caddr_t)u.u_offset, u.u_base, c))
goto fault;
u.u_count = 0;
u.u_base += c;
u.u_offset += c;
return;
case 2:
return;
case 3:
if (!useracc(u.u_base, u.u_count, B_WRITE))
goto fault;
if (UNIcpy((caddr_t)u.u_offset, u.u_base, u.u_count, B_READ))
goto fault;
c = u.u_count;
u.u_count = 0;
u.u_base += c;
u.u_offset += c;
return;
case 4:
if ((u_long)u.u_offset < (u_long)SYSADR)
goto fault;
c = u.u_count;
#define EXCLUDE(laddr, maddr) \
if ((u_long)u.u_offset >= (u_long)(laddr)) { \
if ((u_long)u.u_offset < (u_long)(maddr)) \
goto fault; \
} else \
c = min(c, (u_long)(laddr) - (u_long)u.u_offset)
/* cf. startup() in machdep.c */
EXCLUDE(buffers, buffers + BUFSIZE*nbuf);
EXCLUDE(blkdata, blkdata + NBLKDATA);
EXCLUDE(ecmap, 0xffffffff);
if (!kernacc((caddr_t)u.u_offset, c, B_READ))
goto fault;
if (copyout((caddr_t)u.u_offset, u.u_base, c))
goto fault;
u.u_count -= c;
u.u_base += c;
u.u_offset += c;
return;
case 5:
c = min(u.u_count, sizeof(long));
lbuf = umfpr(u.u_offset/sizeof(long));
if (copyout((caddr_t)&lbuf, u.u_base, c))
goto fault;
u.u_count -= c;
u.u_base += c;
u.u_offset += c;
return;
}
fault:
u.u_error = EFAULT;
return;
}
mmwrite(dev)
{
register int o; long lbuf;
register unsigned c, v;
switch (minor(dev)) {
case 0:
while (u.u_count != 0 && u.u_error == 0) {
if (fubyte(u.u_base) == -1)
goto fault;
v = btop(u.u_offset);
*(int *)mmap = v | (PG_V | PG_KW);
mtpr(TBIS, vmmap);
o = (int)u.u_offset & PGOFSET;
c = min((unsigned)(NBPG - o), u.u_count);
c = min(c, (unsigned)(NBPG - ((int)u.u_base&PGOFSET)));
if (copyin(u.u_base, (caddr_t)&vmmap[o], c))
goto fault;
u.u_count -= c;
u.u_base += c;
u.u_offset += c;
}
return;
case 1:
if (copyin(u.u_base, (caddr_t)u.u_offset, u.u_count))
goto fault;
u.u_base += u.u_count;
u.u_offset += u.u_count;
u.u_count = 0;
return;
case 2:
u.u_offset += u.u_count;
u.u_count = 0;
return;
case 3:
if (!useracc(u.u_base, u.u_count, B_READ))
goto fault;
if (UNIcpy((caddr_t)u.u_offset, u.u_base, u.u_count, B_WRITE))
goto fault;
u.u_base += u.u_count;
u.u_offset += u.u_count;
u.u_count = 0;
return;
case 5:
if (u.u_count < sizeof(long))
goto fault;
if (copyin(u.u_base, (caddr_t)&lbuf, sizeof(long)))
goto fault;
if (umtpr(u.u_offset / sizeof(long), lbuf) == 0)
goto fault;
u.u_count -= sizeof(long);
u.u_base += sizeof(long);
u.u_offset += sizeof(long);
return;
}
fault:
u.u_error = EFAULT;
return;
}