2.11BSD/sys/pdp/kern_pdp.c
/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)kern_pdp.c 1.4 (2.11BSD) 1998/5/12
*/
#include "param.h"
#include "../machine/autoconfig.h"
#include "../machine/seg.h"
#include "user.h"
#include "ioctl.h"
#include "proc.h"
#include "kernel.h"
#include "systm.h"
#include "cpu.h"
#include "tty.h"
/*
* used to pass result from int service to probe();
* do not declare static!!
*/
int conf_int = CONF_MAGIC;
/*
* ucall allows user level code to call various kernel functions.
* Autoconfig uses it to call the probe and attach routines of the
* various device drivers.
*/
ucall()
{
register struct a {
int priority;
int (*routine)();
int arg1;
int arg2;
} *uap = (struct a *)u.u_ap;
int s;
if (!suser())
return;
switch(uap->priority) {
case 0:
s = spl0();
break;
case 1:
s = spl1();
break;
case 2:
case 3:
case 4:
s = spl4();
break;
case 5:
s = spl5();
break;
case 6:
s = spl6();
break;
case 7:
default:
s = spl7();
break;
}
u.u_r.r_val1 = (*uap->routine)(uap->arg1,uap->arg2);
splx(s);
}
/*
* Lock user into core as much as possible. Swapping may still
* occur if core grows.
*/
lock()
{
struct a {
int flag;
};
if (!suser())
return;
if (((struct a *)u.u_ap)->flag)
u.u_procp->p_flag |= SULOCK;
else
u.u_procp->p_flag &= ~SULOCK;
}
/*
* fetch the word at iaddr from user I-space. This system call is
* required on machines with separate I/D space because the mfpi
* instruction reads from D-space if the current and previous modes
* in the program status word are both user.
*/
fetchi()
{
struct a {
caddr_t iaddr;
};
#ifdef NONSEPARATE
u.u_error = EINVAL;
#else !NONSEPARATE
u.u_error = copyiin((struct a *)u.u_ap, u.u_r.r_val1, NBPW);
#endif NONSEPARATE
}
/*
* return the floating point error registers as they were following
* the last floating point exception generated by the calling process.
* Required because the error registers may have been changed so the
* system saves them at the time of the exception.
*/
fperr()
{
u.u_r.r_val1 = (int)u.u_fperr.f_fec;
u.u_r.r_val2 = (int)u.u_fperr.f_fea;
}
/*
* set up the process to have no stack segment. The process is
* responsible for the management of its own stack, and can thus
* use the full 64K byte address space.
*/
nostk()
{
if (estabur(u.u_tsize, u.u_dsize, 0, u.u_sep, RO))
return;
expand(0,S_STACK);
u.u_ssize = 0;
}
/*
* set up a physical address
* into users virtual address space.
*/
phys()
{
register struct a {
int segno;
int size;
int phys;
} *uap = (struct a *)u.u_ap;
register int i, s;
int d;
if (!suser())
return;
i = uap->segno;
if (i < 0 || i >= 8)
goto bad;
s = uap->size;
if (s < 0 || s > 128)
goto bad;
#ifdef NONSEPARATE
d = u.u_uisd[i];
#else
d = u.u_uisd[i + 8];
#endif
if (d != 0 && (d & ABS) == 0)
goto bad;
#ifdef NONSEPARATE
u.u_uisd[i] = 0;
u.u_uisa[i] = 0;
#else
u.u_uisd[i + 8] = 0;
u.u_uisa[i + 8] = 0;
if (!u.u_sep) {
u.u_uisd[i] = 0;
u.u_uisa[i] = 0;
}
#endif
if (s) {
#ifdef NONSEPARATE
u.u_uisd[i] = ((s - 1) << 8) | RW | ABS;
u.u_uisa[i] = uap->phys;
#else
u.u_uisd[i + 8] = ((s - 1) << 8) | RW | ABS;
u.u_uisa[i + 8] = uap->phys;
if (!u.u_sep) {
u.u_uisa[i] = u.u_uisa[i + 8];
u.u_uisd[i] = u.u_uisd[i + 8];
}
#endif
}
sureg();
return;
bad:
u.u_error = EINVAL;
}
/*
* This is ugly but it's either this or always include [T]MSCP code even
* for systems without that type of device.
*/
#include "tms.h"
#include "ra.h"
#if NTMSCP > 0
extern int tmscpprintf, tmscpcache; /* see pdpuba/tmscp.c */
#endif
#if NRAC > 0
extern int mscpprintf;
#endif
extern struct tty cons[];
/*
* This was moved here when the TMSCP portion was added. At that time it
* became (even more) system specific and didn't belong in kern_sysctl.c
*/
int
cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
int *name;
u_int namelen;
void *oldp;
size_t *oldlenp;
void *newp;
size_t newlen;
{
switch (name[0])
{
case CPU_CONSDEV:
if (namelen != 1)
return(ENOTDIR);
return(sysctl_rdstruct(oldp, oldlenp, newp,
&cons[0].t_dev, sizeof &cons[0].t_dev));
#if NTMSCP > 0
case CPU_TMSCP:
/* All sysctl names at this level are terminal */
if (namelen != 2)
return(ENOTDIR);
switch (name[1])
{
case TMSCP_CACHE:
return(sysctl_int(oldp, oldlenp, newp,
newlen, &tmscpcache));
case TMSCP_PRINTF:
return(sysctl_int(oldp, oldlenp, newp,
newlen,&tmscpprintf));
default:
return(EOPNOTSUPP);
}
#endif
#if NRAC > 0
case CPU_MSCP:
/* All sysctl names at this level are terminal */
if (namelen != 2)
return(ENOTDIR);
switch (name[1])
{
case MSCP_PRINTF:
return(sysctl_int(oldp, oldlenp, newp,
newlen,&mscpprintf));
default:
return(EOPNOTSUPP);
}
#endif
default:
return(EOPNOTSUPP);
}
/* NOTREACHED */
}