#if defined(LOCAL) || defined(RCI)

#include "../h/types.h"
#include "../h/param.h"
#include "../h/file.h"
#include "../h/buf.h"
#include "../h/dir.h"
#include "../h/signal.h"
#include "../h/user.h"

#include "../machine/pte.h"
#include "../machine/mtpr.h"

#ifdef LOCAL
firewall_hole()
{
 struct a {
   int (*fxn)();
   int arg; } *uap = (struct a *) u.u_ap;

#if 0				/* we have to remove this check so that */
 if (! suser())			/* normal users can use RCCL */
  { u.u_error = EPERM;
    u.u_r.r_val1 = -1;
  }
#endif
 u.u_error = 0;
 u.u_r.r_val1 = (*uap->fxn)(uap->arg);
}
#endif

#ifdef LOCAL
load_averages()
{
 extern double avenrun[3];
 struct a {
   double *dp; } *uap = (struct a *) u.u_ap;
 register int i;

 if (!useracc(uap->dp,sizeof(avenrun),B_WRITE))
  { u.u_error = EFAULT;
    return;
  }
 for (i=0;i<(sizeof(avenrun)/sizeof(avenrun[0]));i++)
  { uap->dp[i] = avenrun[i];
  }
}
#endif

#if defined(LOCAL) || defined(RCI)
/* Read physical memory.  Caller is responsible for checking that
   nb bytes exist at physical address addr. */
read_physical(addr,buf,nb)
int addr;
caddr_t buf;
int nb;
{
 static char kpagebuf[1024];
 static char *kpage = 0;
 int pa;
 int left;
 caddr_t bp;
 int todo;
 int s;
 struct pte *kpte;
 int kpfn;

 if (kpage == 0) kpage = (char *) (((int)&kpagebuf[511])&~511);
 left = nb;
 pa = addr;
 bp = buf;
 while (left > 0)
  { todo = ((pa+512)&~511) - pa;
    if (todo > left) todo = left;
    s = splhigh();
    kpte = (struct pte *) (0x80000000+mfpr(SBR)+(((0x7fffffff&(int)kpage)>>9)<<2));
    kpfn = kpte->pg_pfnum;
    kpte->pg_pfnum = (pa >> 9);
    mtpr(TBIS,(int)kpage);
    switch (todo)
     { default:
	  bcopy((caddr_t)(kpage+(pa&511)),bp,todo);
	  break;
       case 1:
	  *(char *)bp = *(char *)&kpage[pa&511];
	  break;
       case 2:
	  *(short int *)bp = *(short int *)&kpage[pa&511];
	  break;
       case 4:
	  *(long int *)bp = *(long int *)&kpage[pa&511];
	  break;
     }
    kpte->pg_pfnum = kpfn;
    mtpr(TBIS,(int)kpage);
    splx(s);
    bp += todo;
    pa += todo;
    left -= todo;
  }
}
#endif

#if defined(LOCAL) || defined(RCI)
/* Read physical memory.  Caller is responsible for checking that
   nb bytes exist at physical address addr. */
write_physical(addr,buf,nb)
int addr;
caddr_t buf;
int nb;
{
 static char kpagebuf[1024];
 static char *kpage = 0;
 int pa;
 int left;
 caddr_t bp;
 int todo;
 int s;
 struct pte *kpte;
 int kpfn;

 if (kpage == 0) kpage = (char *) (((int)&kpagebuf[511])&~511);
 left = nb;
 pa = addr;
 bp = buf;
 while (left > 0)
  { todo = ((pa+512)&~511) - pa;
    if (todo > left) todo = left;
    s = splhigh();
    kpte = (struct pte *) (0x80000000+mfpr(SBR)+(((0x7fffffff&(int)kpage)>>9)<<2));
    kpfn = kpte->pg_pfnum;
    kpte->pg_pfnum = (pa >> 9);
    mtpr(TBIS,(int)kpage);
    switch (todo)
     { default:
	  bcopy(bp,(caddr_t)(kpage+(pa&511)),todo);
	  break;
       case 1:
	  *(char *)&kpage[pa&511] = *(char *)bp;
	  break;
       case 2:
	  *(short int *)&kpage[pa&511] = *(short int *)bp;
	  break;
       case 4:
	  *(long int *)&kpage[pa&511] = *(long int *)bp;
	  break;
     }
    kpte->pg_pfnum = kpfn;
    mtpr(TBIS,(int)kpage);
    splx(s);
    bp += todo;
    pa += todo;
    left -= todo;
  }
}
#endif

#endif /* LOCAL || RCI */
