/*************************************************************************/
/*                                                                       */
/*        MMU_MON.c written by Michael R. Mossman in Oct 89              */
/*                and released to Public Domain.                         */
/*                                                                       */
/*************************************************************************/


#include <exec/types.h>
#include <stdio.h>
#include <string.h>
#include <proto/exec.h>

#define PHY_MASK 0xffffff00
#define LOG_MASK 0x000000ff
#define VERSION  1

struct MMUM
          {
	   ULONG LOGICAL_ADDRESS,*PHYSICAL_ADDRESS;
	  }; 


struct MMU
          {
	   struct MMUM myMMUM;
	   ULONG UCRP,LCRP,USRP,LSRP,UDRP,LDRP,TC;
           UWORD AC,PSR,PCSR;
	   UBYTE CAL,VAL,SCC,BLANK;
          }myMMU;

extern ULONG far MMU_PRESENT;
extern USHORT far EXCEPTION;

ULONG WhatReg(),Read(),Table_Lookup(),Startup(),DisplayMem(),Read_MMU();
ULONG Read_Table(),Write_MMU(),Translate();
void MyExit(),CheckException(),Help(),EditMem();	  

main()

{
   UBYTE c;
   ULONG error;
   
   error=Startup();
   if(error==0 && MMU_PRESENT==0) exit(0L); 
   printf("[3;37;40mCommand>[0;31;40m");
   while (c=getchar())
         {
           switch (c)
	      {
		case'\n':
		     continue;
		case 'r':
		case 'R':
                     error=Read();
		     if(error==0) MyExit();
		     break;
		case 'd':
		case 'D':
		     error=DisplayMem();
		     if(error==0) MyExit();
		     break;
		case 'w':
		case 'W':
		     error=WhatReg();
		     if(error==0) MyExit();
		     break;
		case 'e':
		case 'E':
		     EditMem();
		     break;
		case 't':
		case 'T':
		     error=Translate();
		     if(error==0) MyExit();
		     break;     
		case 'x':
		case 'X':
		     MyExit();
		case 'h':
		case 'H':
		case '?':
		     Help();
		     break;
		default:
		     printf("Unrecognized Character\n\n");
		     break;
		}
	     printf("[3;37;40mCommand>[0;31;40m");
	  }
}	
	

ULONG Read()

{
	ULONG error;

        error=Read_MMU();
	if (error==0) return(0L);
	printf("\n\n[3;37;40mCRP[0;31;40m %08.X %08.X      ",myMMU.UCRP,myMMU.LCRP);
	printf("[3;37;40mSRP[0;31;40m %08.X %08.X      ",myMMU.USRP,myMMU.LSRP);
	printf("[3;37;40mDRP[0;31;40m %08.X %08.X\n\n",myMMU.UDRP,myMMU.LDRP);
	printf("[3;37;40mTC[0;31;40m %08.X   ",myMMU.TC);
	printf("[3;37;40mAC[0;31;40m %04.X   ",myMMU.AC);
	printf("[3;37;40mPSR[0;31;40m %04.X   ",myMMU.PSR);
	printf("[3;37;40mPCSR[0;31;40m %04.X   ",myMMU.PCSR);
	printf("[3;37;40mCAL[0;31;40m %02.X   ",myMMU.CAL);
	printf("[3;37;40mVAL[0;31;40m %02.X   ",myMMU.VAL);
	printf("[3;37;40mSCC[0;31;40m %02.X\n\n",myMMU.SCC);
	return(1L);
}




ULONG Table_Lookup()

{
      ULONG error,paddress,laddress;
      
      error=Read_Table();
      if(error==0 & MMU_PRESENT!=0)
        {
	  printf("There is an MMU, but no address translation is being done.\n\n");
          return (0L);
	}
      if(error==0 & MMU_PRESENT==0) return (0L);
      laddress=myMMU.myMMUM.LOGICAL_ADDRESS & LOG_MASK;
      paddress=(*myMMU.myMMUM.PHYSICAL_ADDRESS & PHY_MASK)+laddress;
      printf("[3;37;40mLOGICAL ADDRESS[0;31;40m %08.X       IS MAPPED TO       [3;37;40mPHYSICAL ADDRESS[0;31;40m %08.X\n\n",myMMU.myMMUM.LOGICAL_ADDRESS,paddress);
      return(1L);
      
}      


ULONG Startup()

{
	ULONG error;
	
	printf("\n\n[3;37;40mMMU MON[0;31;40m is a  monitor for the MC68851 Paged Memory Management Unit.\n\n");
        printf("Select \"H\" for help.\n\n");
	printf("Written by Michael R. Mossman in October 1989.\n");
	printf("I can be contacted on CompuServe UI 76515,3017 or Punter Net node 94.\n");
        error=Read();
        if (error==0 & MMU_PRESENT==0)
	   {
	     printf("\n\nI can't help if no MMU is in your system!!!\n\n\n");
	     return(0L);
	   }
        myMMU.myMMUM.LOGICAL_ADDRESS=0xfc0000;
	error=Table_Lookup();
	if (error==0) return (0L);
	return(1L);
	
}	

ULONG WhatReg()

{
  UBYTE buff[20];
  ULONG num,error;
  USHORT x=1,y=0;
	
  
  while(x!=0)
       {
	 printf("What register (eg.- CRP) ?\n>");
         scanf("%5s",buff);
	
         if((x=strcmpi(buff,"CRP"))==0) 
            {
		y=1;
                continue;
	    }
          if((x=strcmpi(buff,"SRP"))==0) 
            {
		y=2;
                continue;
	    }
	  if((x=strcmpi(buff,"DRP"))==0) 
            {
		y=3;
                continue;
	    }
  
          if((x=strcmpi(buff,"TC"))==0) 
            {
		y=4;
                continue;
	    }

          if((x=strcmpi(buff,"AC"))==0) 
            {
		y=5;
                continue;
	    }

          if((x=strcmpi(buff,"PSR"))==0) 
            {
		y=6;
                continue;
	    }
          
	  if((x=strcmpi(buff,"PCSR"))==0) 
            {
		y=7;
                continue;
	    }
          
	  if((x=strcmpi(buff,"CAL"))==0) 
            {
		y=8;
                continue;
	    }

          if((x=strcmpi(buff,"VAL"))==0) 
            {
		y=9;
                continue;
	    }
          
	  if((x=strcmpi(buff,"SCC"))==0) 
            {
		y=10;
                continue;
	    }

         }
     if(y!=7) printf("Hex value for ");
     switch (y)
          {
	    case 1:
	        printf("upper long word ?\n>");
		scanf("%lx",&num);
                myMMU.UCRP=num;
		printf("lower long word ?\n>");
		scanf("%lx",&num);
		myMMU.LCRP=num;
                error=Write_MMU(&myMMU.UCRP);
                break;
            case 2:
	        printf("upper long word ?\n>");
		scanf("%lx",&num);
                myMMU.USRP=num;
		printf("lower long word ?\n>");
		scanf("%lx",&num);
		myMMU.LSRP=num;
                error=Write_MMU(&myMMU.USRP);
                break;

            case 3:
	        printf("upper long word ?\n>");
		scanf("%lx",&num);
                myMMU.UDRP=num;
		printf("lower long word ?\n>");
		scanf("%lx",&num);
		myMMU.LDRP=num;
                error=Write_MMU(&myMMU.UDRP);
                break;

            case 4:
	        printf("long word ?\n>");
		scanf("%lx",&num);
                myMMU.TC=num;
                error=Write_MMU(&myMMU.TC);
                break;

            case 5:
	        printf("word ?\n>");
		scanf("%lx",&num);
		if(num>0xffff) printf("Number bigger then \"word\" size entered.\n");
                myMMU.AC=(USHORT)num;
                error=Write_MMU(&myMMU.AC);
                break;
            
	    case 6:
	        printf("word ?\n>");
		scanf("%lx",&num);
		if(num>0xffff) printf("Number bigger then \"word\" size entered.\n");
                myMMU.PSR=(USHORT)num;
                error=Write_MMU(&myMMU.PSR);
                break;
            
	    case 7:
	        printf("This is a read only register.\n");
                break;
            
	    case 8:
	        printf("byte ?\n>");
		scanf("%lx",&num);
		if(num>0xff) printf("Number bigger then \"byte\" size entered.\n");
                myMMU.CAL=(UBYTE)num;
                error=Write_MMU(&myMMU.CAL);
                break;

            case 9:
	        printf("byte ?\n>");
		scanf("%lx",&num);
		if(num>0xff) printf("Number bigger then \"byte\" size entered.\n");
                myMMU.VAL=(UBYTE)num;
                error=Write_MMU(&myMMU.VAL);
                break;

            case 10:
	        printf("byte ?\n>");
		scanf("%lx",&num);
		if(num>0xff) printf("Number bigger then \"byte\" size entered.\n");
                myMMU.SCC=(BYTE)num;
                error=Write_MMU(&myMMU.SCC);
                break;
	  }
    if(EXCEPTION!=0) CheckException();	  
    Read();
    return(error);  
}	  
	  
ULONG DisplayMem()
{
	
   UBYTE *c,*d;
   ULONG start,end;
   
   printf("Start address in hex ?\n>");
   scanf("%lx",&start);
   printf("End address in hex ?\n>");
   scanf("%lx",&end);
   if(end<=start) end=start+352;
     
   	
   
   printf("\n");
   
   for(;start<end;)
    {
	c=(UBYTE *)start;
	printf("[3;37;40m%08X[0;31;40m ",c);
	
	for(d=(UBYTE *)start+16;c<d;c++)
	   {
		
		printf("%02X ",*c);
	   
	   }
	
	printf(" \"");
	
	for(c=(UBYTE *)start,d=(UBYTE *)start+16;c<d;c++)
	   {
	     if(*c>31 & *c<127 | *c>159 & *c<=255)
	       {
		 printf("%c",*c);
	       }
	     else printf(".");
	    
	   }
	
	printf("\"\n");
	start=start+16;
    }
   return(1L); 	
}


ULONG Translate()

{
   ULONG num,error;
	
   printf("Enter logical address (for logical to physical translation) ?\n>"); 
   scanf("%lx",&num);
   myMMU.myMMUM.LOGICAL_ADDRESS=num;
   printf("\n");
   error=Table_Lookup();
   if(error==0) printf("TC register must be 0x80000000 or greater for mappings to take place!\n\n"); 
   return(1L);
   
}   

void CheckException()

{
  printf("\n[3;37;40mYour last write operation caused a %#04.X exception error!!!![0;31;40m\n\n",EXCEPTION);
  if(EXCEPTION==56) printf("Bad data was moved into the TC, CRP, SRP or DRP register.\n");
  if(EXCEPTION==57) printf("PLoad instruction was executed with the enable bit of the TC register clear.\n");
  if(EXCEPTION==58) printf("PValid instruction failed\n");
  EXCEPTION=0L;
}

void MyExit()

{
	
  End(); 
  exit(0L);
    
}   


void Help()

{
   printf("\n\n\n\n                         [3;37;40m MMU MON     HELP FILE[0;31;40m\n\n\n\n\n\n");
   printf("[3;37;40m R[0;31;40m - Read the MMU registers.\n\n");
   printf("[3;37;40m W[0;31;40m - Write to one of the MMU registers.\n\n");
   printf("[3;37;40m T[0;31;40m - Translate a logical address to a physical address.\n\n");
   printf("[3;37;40m D[0;31;40m - Display memory in hex and ascii.\n\n");
   printf("[3;37;40m E[0;31;40m - Edit memory in hex.\n\n");
   printf("[3;37;40m X[0;31;40m - Exit this program.\n\n");
   printf("[3;37;40m H[0;31;40m - This help file. (I wonder how you got here?)\n\n");
   
}
   

void EditMem()

{
  ULONG start,num;
  UBYTE *c,ch;

  printf("\n\n");
  printf("Enter start address in hex for editing. Return to exit edit mode.\n>");
  scanf("%lx",&start);
  getchar();
  printf("\n\n");
  while (1)
      {
        c=(UBYTE *)start;
        printf("[3;37;40m%08X[0;31;40m %02X     ",c,*c);
	if((ch=getchar())!='\n') ungetc(ch,stdin);
	if(ch=='\n') { printf("\n\n"); return; }
        scanf("%lx",&num);
	getchar();
	*c=(UBYTE)num;
	start++;
      }
}
