/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:vm_subr.c 12.0$ */
/* $ACIS:vm_subr.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/sys/RCS/vm_subr.c,v $ */

#if !defined(lint) && !defined(NO_RCS_HDRS)
static char *rcsid = "$Header:vm_subr.c 12.0$";
#endif

/*	vm_subr.c	6.1	83/07/29	*/

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

#include "param.h"
#include "systm.h"
#include "dir.h"
#include "user.h"
#include "vm.h"
#include "proc.h"
#include "cmap.h"
#ifndef VFS
#include "inode.h"
#endif !VFS
#include "buf.h"
#include "text.h"
#ifndef VFS
#include "fs.h"
#else !VFS
#include "../h/vfs.h"
#include "vnode.h"
#endif !VFS

#ifdef vax
#include "../vax/mtpr.h"
#endif

/*
 * Make uarea of process p addressible at kernel virtual
 * address uarea through sysmap locations starting at map.
#ifdef ibm032
 *
 * Note: uarea is the address of the u struct, not the address of the u area.
 * This is because Vax put the u struct at the start of the u area, and we
 * put it at the end (to keep the kernel stack from crashing into it.  It is
 * ok here, as it is used only by alias, which needs only the mmu segment
 * number.
#endif ibm032
 */
#ifndef ibm032
uaccess(p, map, uarea)
	register struct proc *p;
	struct pte *map;
	register struct user *uarea;
{
	register int i;
	register struct pte *mp = map;

	for (i = 0; i < UPAGES; i++) {
		*(int *)mp = 0;
		mp->pg_pfnum = p->p_addr[i].pg_pfnum;
		mp++;
	}
	vmaccess(map, (caddr_t)uarea, UPAGES);
}
#else ibm032
uaccess(p, map, uarea)
	register struct proc *p;
	register struct pte *map;
	register caddr_t uarea;
{
	register int i;

	for (i=0; i<UPAGES; ++i)
	       *(unsigned *)(map+i) = PG_PFNUM & (*(unsigned *)(p->p_addr + i));
	alias(map, btop(uarea));
}
#endif ibm032

/*
 * Validate the kernel map for size ptes which
 * start at ppte in the sysmap, and which map
 * kernel virtual addresses starting with vaddr.
 */
#ifndef ibm032
vmaccess(ppte0, vaddr, size0)
	struct pte *ppte0;
	register caddr_t vaddr;
	int size0;
{
	register struct pte *ppte = ppte0;
	register int size = size0;

	while (size != 0) {
		mapin(ppte, btop(vaddr), (unsigned)(*(int *)ppte & PG_PFNUM), 1,
			(int)(PG_V|PG_KW));
		ppte++;
		vaddr += NBPG;
		--size;
	}
}
#else ibm032
vmaccess(ppte, vaddr, size)
	register struct pte *ppte;
	register caddr_t vaddr;
	register int size;
{
	register unsigned model;  /* THIS IS REALLY A STRUCT PTE */

	while (size--) {
		if ((model = *(unsigned	*)ppte) & PG_PROT);
			else model |= PG_V|PG_KW;
			mapin(ppte, btop(vaddr), model, 1);
			alias(ppte, btop(vaddr));
		ppte++;
		vaddr += NBPG;
	}
}
#endif ibm032

/*
 * Convert a pte pointer to
 * a virtual page number.
 */
ptetov(p, pte)
	register struct proc *p;
	register struct pte *pte;
{

	if (isatpte(p, pte))
		return (tptov(p, ptetotp(p, pte)));
	else if (isadpte(p, pte))
		return (dptov(p, ptetodp(p, pte)));
	else
		return (sptov(p, ptetosp(p, pte)));
}

/*
 * Convert a virtual page
 * number to a pte address.
 */
struct pte *
vtopte(p, v)
	register struct proc *p;
	register unsigned v;
{

	if (isatsv(p, v))
		return (tptopte(p, vtotp(p, v)));
	else if (isadsv(p, v))
		return (dptopte(p, vtodp(p, v)));
#ifndef ibm032
	else
		return (sptopte(p, vtosp(p, v)));
#else ibm032
	else if (isassv(p, v))
		return (sptopte(p, vtosp(p, v)));
	else return(0);
#endif ibm032
}

/*
 * Initialize the page tables for paging from an inode,
 * by scouring up the indirect blocks in order.
 * Corresponding area of memory should have been vmemfree()d
 * first or just created.
 */
#ifndef VFS
vinifod(pte, fileno, ip, bfirst, count)
#else !VFS
vinifod(pte, fileno, vp, bfirst, count)
#endif !VFS
	register struct fpte *pte;
	int fileno;
#ifndef VFS
	register struct inode *ip;
#else !VFS
	register struct vnode *vp;
#endif !VFS
	daddr_t bfirst;
	size_t count;
{
	int blast = bfirst + howmany(count, CLSIZE);
	register int i, j;
	int bn;
#ifndef VFS
	register struct fs *fs = ip->i_fs;
	int nclpbsize = fs->fs_bsize / CLBYTES;
	int nclpbshift = fs->fs_bshift - CLSHIFT;
#else !VFS
	int nclpbsize = vp->v_vfsp->vfs_bsize / CLBYTES;
#endif !VFS

	while (bfirst < blast) {
#ifdef ibm032
		i = bfirst & (nclpbsize-1);
#ifndef VFS
		bn = fsbtodb(fs, bmap(ip, bfirst >> nclpbshift, B_READ, 0));
#else !VFS
		(void) VOP_BMAP(vp, bfirst / nclpbsize, (struct vnode *)0, &bn);
#endif !VFS
#else
		i = bfirst % nclpbsize;
#ifndef VFS
		bn = fsbtodb(fs, bmap(ip, bfirst / nclpbsize, B_READ, 0));
#else !VFS
		(void) VOP_BMAP(vp, bfirst / nclpbsize, (struct vnode *)0, &bn);
#endif !VFS
#endif
		for ( ; i < nclpbsize; i++) {
			pte->pg_fod = 1;
			pte->pg_fileno = fileno;
			if (u.u_error || bn < 0) {
				pte->pg_blkno = 0;
				pte->pg_fileno = PG_FZERO;
				cnt.v_nzfod += CLSIZE;
			} else {
				pte->pg_blkno = bn + btodb(i * CLBYTES);
				cnt.v_nexfod += CLSIZE;
			}
#if CLSIZE != 1
			for (j = 1; j < CLSIZE; j++)
				pte[j] = pte[0];
#endif
			pte += CLSIZE;
			bfirst++;
			if (bfirst == blast)
				break;
		}
	}
}
