/*
	MMU040 V1.0 for the Progressive Peripipherals & Software 040/A3000
        by Greg Tibbs; some code from  SetCPU V1.4 by Dave Haynie

	MAIN PROGRAM

        Assumptions: The PPS 040 for the A3000 only works under 2.0+, so 
                     assumptions that exec knows about an 040, that ROMsize
                     is 512K. The PPS 040 has no onboard memory, so the
                     area mapped from 0x0100000 on to the base of the A3000
                     motherboard Ram is made invalid in the Address translation
                     cache and accesses there will yield an address error
                     exception. Zorro III memory area is made data &
                     instruciton cachable, with ZorroII I/o space not
                     cachable at all (040 limitation in that there is no
                     ddistinction in the ATC between data accesses and 
                     instruction accesses. The only way around this is
                      with the mTTX registers which will be used primarily
                     in fast ram. 
	
*/

#define PROGRAM_VERSION	"V1.0"

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/interrupts.h>
#include <stdio.h>

/* ====================================================================== */

/* Define all bit components used for manipulation of the Cache Control
   Register. */

#define CACR_INST	(1L<<15)
#define CACR_DATA	(1L<<31)


/* ====================================================================== */

/* Define important bits used in various MMU registers. */
/* Here are the TC definitions.  The TC register is 32 bits long. */

#define	TC_ENB		((1L<<15)+(1L<<14))      /* Enable the MMU with 8K pages*/

/* Here are the page descriptor definitions, for short desctriptors only,
   since that's all I'm using at this point. */
   
/* ====================================================================== */

/* Some external declarations. */

void SetCACR(), DumpCache(), SetCRP(), SetTC(), SetVBR();
void SetITT0(), SetITT1(), SetDTT0(), SetDTT1();
ULONG GetCACR(), GetTC(), GetCPUType(), GetCRP(), GetSRP();
ULONG GetDTT0(), GetDTT1(), GetITT0(), GetITT1(), GetVBR(), GetMMUStatus();

/* ====================================================================== */

/* This replaces the Lattice "stricmp()" function, plus it's a better form
   for my needs here. */
   
static BOOL striequ(s1,s2)
char *s1,*s2;
{
   BOOL aok;
   
   while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
   return (BOOL) (!*s1 && aok);
}

void pdata(itt0)
ULONG itt0;
{
UBYTE *enabled, *cmmode, *affects;
ULONG temp;

  temp=(itt0&0x60)>>5;
  switch(temp)
  {
    case 0: cmmode = "WT";
            break;
    case 1: cmmode = "CB";
 	    break;
    case 2: cmmode = "NS";
            break;
    case 3: cmmode = "NN";
            break;
  }
  temp=(itt0&0x6000)>>13;
  switch(temp)
  {
    case 0: affects = "User Space";
            break;
    case 1: affects = "Supervisor Space";
 	    break;
    case 2:
    case 3: affects = "Both U & S Space";
            break;
  }
  if (itt0&0x8000)  
    enabled="YES";
  else
  {
    enabled="NO ";
  }
  printf("%s       %s     %s\n",cmmode, enabled, affects);
}

/* This be the main program. */

int main(argc,argv)
int argc;
char *argv[];
{
   ULONG myTC,cpu,crp,srp,cacr,itt0,itt1,dtt0,dtt1,vbr,status;

   /* If they're just asking for help */

   if (argc >= 2 && argv[1][0] == '?') {
      printf("\2337mMMU040 %s\2330m\n",PROGRAM_VERSION);
      exit(0);
   }

  /* Let's find out what we have, and perform the ROM translation, if it's
     requested and hasn't been done already. */

   printf("\n\2337mMMU040 %s\2330m\n\n",PROGRAM_VERSION);

   cpu = GetCPUType();
   if(cpu != 68040) 
   {
      printf("040 Not Present!!!\n");
      exit(5L);
   }
   else
   {
      printf("68040 MMU is set up as follows:\n");
   }

   status=GetMMUStatus();
   vbr = GetVBR();   
   myTC=GetTC();
   cacr=GetCACR();
   crp=GetCRP();
   srp=GetSRP();
   dtt0=GetDTT0();
   dtt1=GetDTT1();
   itt0=GetITT0();
   itt1=GetITT1();

   printf("Vector Base Register: 0x%0lx\n",vbr);
   printf("Translation Control Register (TC): ");
   if(!(myTC & 0x8000)) 
     printf("Disabled");
   else
     printf("Enabled ");

   if(myTC & 0x4000)
     printf("  Page Size = 8K\n");
   else
     printf("  Page Size = 4K\n");
   printf("Supervisor Space Root Pointer (SRP) = 0x%08x\n",srp);
   printf("User Space Root Pointer (URP) = 0x%08x\n",crp);
   if(cacr & 0x8000) 
     printf("Instruction Cache (IC): Enabled  ");
   else
     printf("Instruction Cache (IC): Disabled ");  
  if(cacr & 0x80000000) 
     printf("   Data Cache (DC): Enabled  \n");
   else
     printf("   Data Cache (DC): Disabled \n");
  printf("MMU Status Register = 0x%08x\n",status); 
 
  printf("\nTransparent Translation Registers (mTTx): \n");

  printf("ITT0: Address         Mask    CMMode  Enabled     Affects\n");
  printf("      0x%02xXXXXXX   0x%02xXXXXXX  ",
     (itt0&0xff000000)>>24, (itt0&0x00ff0000)>>16);
  pdata(itt0);
 
  printf("ITT1: Address         Mask    CMMode  Enabled     Affects\n");
  printf("      0x%02xXXXXXX   0x%02xXXXXXX  ",
     (itt1&0xff000000)>>24, (itt1&0x00ff0000)>>16);
  pdata(itt1);

  printf("DTT0: Address         Mask    CMMode  Enabled     Affects\n");
  printf("      0x%02xXXXXXX   0x%02xXXXXXX  ",
     (dtt0&0xff000000)>>24, (dtt0&0x00ff0000)>>16);
  pdata(dtt0);

  printf("DTT1: Address         Mask    CMMode  Enabled     Affects\n");
  printf("      0x%02xXXXXXX   0x%02xXXXXXX  ",
     (dtt1&0xff000000)>>24, (dtt1&0x00ff0000)>>16);
  pdata(dtt1);
    
   printf("\nBinary Equivalent (Hex):\n\n");
   printf("TC =   %04x        CACR = %08x   SRP = %08x\n",myTC,cacr,srp);
   printf("ITT0 = %08x    DTT0 = %08x   URP = %08x\n",itt0,dtt0, crp);
   printf("ITT1 = %08x    DTT1 = %08x\n\n",itt1,dtt1);

   /* For safety's sake, or personal paranoia, or whatever, I dump the
      data cache before I go away. */

   DumpCache();
   exit(0L);
}

