/* * 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 */ }