|
|
researchv9-SUN3
#ifndef lint
static char sccsid[] = "@(#)mem.c 1.1 86/02/03 Copyr 1985 Sun Micro";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
/*
* Memory special file
*/
#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 "../machine/pte.h"
#include "../machine/mmu.h"
#include "../machine/cpu.h"
#include "../machine/eeprom.h"
#define M_MEM 0 /* /dev/mem - physical main memory */
#define M_KMEM 1 /* /dev/kmem - virtual kernel memory & I/O */
#define M_NULL 2 /* /dev/null - EOF & Rathole */
#define M_MBMEM 3 /* /dev/mbmem - (not supported) */
#define M_MBIO 4 /* /dev/mbio - (not supported) */
#define M_VME16D16 5 /* /dev/vme16d16 - VME 16bit addr/16bit data */
#define M_VME24D16 6 /* /dev/vme24d16 - VME 24bit addr/16bit data */
#define M_VME32D16 7 /* /dev/vme32d16 - VME 32bit addr/16bit data */
#define M_VME16D32 8 /* /dev/vme16d32 - VME 16bit addr/32bit data */
#define M_VME24D32 9 /* /dev/vme24d32 - VME 24bit addr/32bit data */
#define M_VME32D32 10 /* /dev/vme32d32 - VME 32bit addr/32bit data */
#define M_EEPROM 11 /* /dev/eeprom - on board eeprom device */
#define M_KMEMR 12 /* /dev/kmemr - public part of kernel memory
* (read only) */
/*
* Check bus type memory spaces for accessibility on this machine
*/
mmopen(dev, flag)
dev_t dev;
{
switch (minor(dev)) {
case M_MEM:
case M_KMEM:
case M_KMEMR:
case M_NULL:
/* standard devices */
break;
case M_EEPROM:
/* all Sun-3 machines must have EEPROM */
break;
case M_VME16D16:
case M_VME24D16:
case M_VME32D16:
case M_VME16D32:
case M_VME24D32:
case M_VME32D32:
/* SUN3_50 is the only Sun-3 machine w/o VMEbus */
if (cpu == CPU_SUN3_50) {
u.u_error = EINVAL;
return;
}
break;
case M_MBMEM:
case M_MBIO:
default:
/* Unsupported or unknown type */
u.u_error = EINVAL;
return;
}
return;
}
mmread(dev)
dev_t dev;
{
mmrw(dev, B_READ);
}
mmwrite(dev)
dev_t dev;
{
mmrw(dev, B_WRITE);
}
mmrw(dev, rw)
dev_t dev;
{
register int o;
register u_int c, v;
register struct iovec *iov;
int error = 0;
int pgsp;
while (u.u_count > 0 && u.u_error == 0) {
switch (minor(dev)) {
case M_MEM:
v = btop(u.u_offset);
if (v >= physmem)
goto fault;
mapin(mmap, btop(vmmap), v, 1, PG_V | PG_KR);
o = (int)u.u_offset & PGOFSET;
c = min((u_int)(NBPG - o), u.u_count);
c = min(c, (u_int)(NBPG -((int)u.u_base&PGOFSET)));
iomove((caddr_t)&vmmap[o], c, rw);
break;
case M_KMEM:
c = u.u_count;
if (kernacc((caddr_t)u.u_offset, c, rw))
iomove((caddr_t)u.u_offset, c, rw);
else
mmpeekio(rw, (caddr_t)u.u_offset, (int)c);
break;
case M_KMEMR:
if (rw == B_WRITE)
goto fault;
c = u.u_count;
if ((u_long)u.u_offset < (u_long)KERNELBASE)
goto fault;
if (!kernacc((caddr_t)u.u_offset, c, B_READ))
goto fault;
iomove((caddr_t)u.u_offset, c, rw);
break;
case M_NULL:
if (rw == B_WRITE) {
u.u_offset += u.u_count;
u.u_count = 0;
}
return;
case M_EEPROM:
mmeeprom(rw, (caddr_t)u.u_offset, u.u_count);
break;
case M_VME16D16:
if (u.u_offset >= VME16_SIZE)
goto fault;
v = u.u_offset + VME16_BASE;
pgsp = PGT_VME_D16;
goto vme;
case M_VME16D32:
if (u.u_offset >= VME16_SIZE)
goto fault;
v = u.u_offset + VME16_BASE;
pgsp = PGT_VME_D32;
goto vme;
case M_VME24D16:
if (u.u_offset >= VME24_SIZE)
goto fault;
v = u.u_offset + VME24_BASE;
pgsp = PGT_VME_D16;
goto vme;
case M_VME24D32:
if (u.u_offset >= VME24_SIZE)
goto fault;
v = u.u_offset + VME24_BASE;
pgsp = PGT_VME_D32;
goto vme;
case M_VME32D16:
pgsp = PGT_VME_D16;
goto vme;
case M_VME32D32:
pgsp = PGT_VME_D32;
/* FALL THROUGH */
vme:
v = btop(v);
mapin(mmap, btop(vmmap), pgsp | v, 1,
rw == B_WRITE ? PG_V|PG_KW : PG_V|PG_KR);
o = (int)u.u_offset & PGOFSET;
c = min((u_int)(NBPG - o), u.u_count);
mmpeekio(rw, &vmmap[o], (int)c);
break;
}
}
return;
fault:
u.u_error = EFAULT;
return;
}
mmpeekio(rw, addr, len)
caddr_t addr;
int len;
{
register int c, o;
short sh;
char cm;
while (len > 0) {
if ((len|(int)addr) & 1) {
c = sizeof (char);
if (rw == B_READ) {
if ((o = peekc(addr)) == -1)
goto fault;
cm = o;
}
iomove((caddr_t)&cm, c, rw);
if (u.u_error)
return;
if (rw == B_WRITE && pokec(addr, c))
goto fault;
} else {
c = sizeof (short);
if (rw == B_READ) {
if ((o = peek((short *)addr)) == -1)
goto fault;
sh = o;
}
iomove((caddr_t)&sh, c, rw);
if (u.u_error)
return;
if (rw == B_WRITE && poke((short *)addr, sh))
goto fault;
}
addr += c;
len -= c;
}
return;
fault:
u.u_error = EFAULT;
return;
}
/*
* If eeprombusy is true, then the eeprom has just
* been written to and cannot be read or written
* until the required 10 MS has passed. It is
* assumed that the only way the EEPROM is written
* is thru the mmeeprom routine.
*/
int eeprombusy = 0;
mmeepromclear()
{
eeprombusy = 0;
wakeup((caddr_t)&eeprombusy);
}
mmeeprom(rw, addr, len)
caddr_t addr;
int len;
{
int o, oo;
int s;
char c;
if ((int)addr > EEPROM_SIZE)
return (EFAULT);
while (len > 0) {
if ((int)addr == EEPROM_SIZE)
goto fault; /* EOF */
s = splclock();
while (eeprombusy)
sleep((caddr_t)&eeprombusy, PUSER);
(void) splx(s);
if (rw == B_WRITE) {
iomove((caddr_t)&c, 1, rw);
if (u.u_error)
return;
o = c;
if ((oo = peekc(EEPROM_ADDR + addr)) == -1)
goto fault;
/*
* Check to make sure that the data is actually
* changing before committing to doing the write.
* This avoids the unneeded eeprom lock out
* and reduces the number of times the eeprom
* is actually written to.
*/
if (o != oo) {
if (pokec(EEPROM_ADDR + addr, (char)o))
goto fault;
/*
* Block out access to the eeprom for
* two clock ticks (longer than > 10 MS).
*/
eeprombusy = 1;
timeout(mmeepromclear, (caddr_t)0, 2);
}
} else {
if ((o = peekc(EEPROM_ADDR + addr)) == -1)
goto fault;
c = o;
iomove((caddr_t)&c, 1, rw);
if (u.u_error)
return;
}
addr += sizeof (char);
len -= sizeof (char);
}
return;
fault:
u.u_error = EFAULT;
return;
}
/*ARGSUSED*/
mmmmap(dev, off, prot)
dev_t dev;
off_t off;
{
int pf;
switch (minor(dev)) {
case M_MEM:
pf = btop(off);
if (pf < physmem)
return (PGT_OBMEM | pf);
break;
case M_VME16D16:
if (off >= VME16_SIZE)
break;
return (PGT_VME_D16 | btop(off + VME16_BASE));
case M_VME16D32:
if (off >= VME16_SIZE)
break;
return (PGT_VME_D32 | btop(off + VME16_BASE));
case M_VME24D16:
if (off >= VME24_SIZE)
break;
return (PGT_VME_D16 | btop(off + VME24_BASE));
case M_VME24D32:
if (off >= VME24_SIZE)
break;
return (PGT_VME_D32 | btop(off + VME24_BASE));
case M_VME32D16:
return (PGT_VME_D16 | btop(off));
case M_VME32D32:
return (PGT_VME_D32 | btop(off));
}
return (-1);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.