/* $Header:vtop.c 12.0$ */
/* $ACIS:vtop.c 12.0$ */
/* $Source: /ibm/acis/usr/src/bin/adb_ca/RCS/vtop.c,v $ */
/* some code stolen from */
#ifndef lint
static char *rcsid = "$Header:vtop.c 12.0$";
#endif

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

#include <machine/debug.h>

#define FORADB

#ifdef FORADB
#include "defs.h"
extern endmem;
#endif
#ifdef ibm032
/****************************************************************************
  vtop - map virtual address(bytes) to physical address(bytes)
	proc must have been set for user addresses to work
	returns -1 for failure.
 ****************************************************************************/
vtop(where)
  register unsigned int where;
  {
    register struct hatipt_entry *ipte;
    register unsigned int rpage,addrtag,vpage,sid;
    register int probes;
    unsigned int page_off;
    register int tmp;
#define MAX_PROBES 100
    if ((sid = Getsid(where>>28)) == -1) return (-1);
    vpage = btop(where & 0x0FFFFFFF);
    page_off = where & PGOFSET;
    ipte = &MMU_HATIPT[MMU_HASH(sid,vpage)];
#ifdef DEBUG
    if(debug) printf("vtop:  where=%x,sid=%x,vpage=%x, hash = %x, ipte=%x\n",where,sid,vpage,MMU_HASH(sid,vpage), ipte);
#endif
    /* make sure there is an ipt chain */
    if (MMU_ENDCHAIN(tmp=readcor(&ipte->hat_ptr, sizeof ipte->hat_ptr)))
      { /* hat pointer empty...not found */
#ifdef DEBUG
    if(debug) printf("hat chain empty\n");
#endif
        return(-1);
      }
    /* chase down the hat ptr */
    ipte = &MMU_HATIPT[tmp];
#ifdef DEBUG
    if(debug) printf("ipte now at %x\n",ipte);
#endif
    addrtag = (sid << MMU_VPAGE_BITS) | vpage;
#ifdef DEBUG
    if(debug) printf("addrtag=%x\n",addrtag);
#endif
    /* check addrtag of first element of ipt chain */
    if ((readcor(&ipte->key_addrtag, sizeof ipte->key_addrtag) & 0x1fffffff) == addrtag)
      { /* same, return vpage + page offset from where */
#ifdef DEBUG
    if (debug) printf("first on chain,=%x\n",ctob(ipte-MMU_HATIPT)+page_off);
#endif
        return(ctob(ipte-MMU_HATIPT)+page_off);
      }
    /* for second element ff. */
    probes = 0;
    while(!MMU_ENDCHAIN(tmp=readcor(&ipte->ipt_ptr, sizeof ipte->ipt_ptr)))
      { /* while there is a next element */
        /* point to the next element */
        ipte = &MMU_HATIPT[tmp];
#ifdef DEBUG
	if (debug) printf("checking ipte at %x\n",ipte);
#endif
        /* check addrtag for this element against desired one */
        if ((readcor(&ipte->key_addrtag, sizeof ipte->key_addrtag) & 0x1fffffff) == addrtag)
          { /* same, return vpage + page offset from where */
#ifdef DEBUG
	if (debug) printf("found it, = %x\n",ctob(ipte-MMU_HATIPT)+page_off);
#endif
            return(ctob(ipte-MMU_HATIPT)+page_off);
          }
        if (probes++ >= MAX_PROBES)
          {
#ifdef DEBUG
	if (debug) printf("VTOP:  loop chasing down an ipt chain!!!\n");
#endif
            return(-1);
          }
      }
#ifdef DEBUG
	if (debug) printf("end of chain...not found\n");
#endif
    return(-1);
  } /* end of vtop */

Getsid(topnibble)
register unsigned int topnibble;
	{
	/* return the sid */
	if (topnibble & 0xe) return(MMU_SID_SYSTEM);
	if (topnibble & 0x0) return(proc.p_sid0);
	if (topnibble & 0x1) return(proc.p_sid1);
	return (-1);	/* failure */
	}

readcor(kernaddr,len)
register unsigned int kernaddr;
register len;
	{
	unsigned long contents, shifted;
#ifdef DEBUG
	if (debug) printf("readcor(%x, len %x)", kernaddr, len);
#endif
	if (((kernaddr&~0xe0000000) > (ctob(endmem)-4)) ||
	  len > 4 || len < 1) {
		printf("readcor bad (%x, len %x)\n", kernaddr, len);
		return(-1);
	}
	if (physrw(fcor,kernaddr&~0xe0000000, &contents, 1)) {
		printf(" readcor bad read (%x)\n", kernaddr);
		return(-1);
	}		
	/* always returns a long */
	shifted = contents>>(32 - 8*len);
#ifdef DEBUG
	if (debug) printf(" = %x -> %x\n", contents, shifted);
#endif
	return (shifted);
	}
#endif
