#include "SupervisorMode.h"
#include <iostream.h>
#include <stdlib.h>

unsigned long getPVR(void);
unsigned long getL2CR(void);

unsigned long superCode(register unsigned long);

void main(void)
{
	cout.setf(ios::hex,ios::basefield);
	cout << "Level 2 Cache Disabler\n\n";
	if(!InstallSupervisorPatch((unsigned long*)getPVR,8))
	{
		cout << "Getting PVR to test super mode code\n";
		unsigned long PVR = CallSupervisorPatch(nil);
		RemoveSupervisorPatch();
		cout << "PVR = 0x" << PVR << "\n";
		if((PVR & 0xFFFF0000) != 0x00080000)
		{
			cout << "This chip is not an Arthur 750 and therefore the cache disabler will not function.  Exiting...\n";
			exit(EXIT_FAILURE);
		}
	}
	else
	{
		cout << "This code to enter supervisor mode can't work on this computer.  Exiting...\n";
		exit(EXIT_FAILURE);
	}
	
	unsigned long L2CR;
	
	// Read the L2CR reg just for fun
	cout << "Reading original L2CR state\n";
	InstallSupervisorPatch((unsigned long*)getL2CR,2*4);
	L2CR = CallSupervisorPatch(nil);
	RemoveSupervisorPatch();
	cout << "L2CR = 0x" << L2CR << "\n";
	if(!(L2CR & 0x80000000))
	{
		cout << "The L2 cache was already disabled!  Exiting...\n";
		exit(EXIT_FAILURE);
	}
	
	// Disable the cache
	cout << "Calling Super Code\n";
	InstallSupervisorPatch((unsigned long*)superCode,7*4);
	L2CR = CallSupervisorPatch(nil);
	RemoveSupervisorPatch();
	
	cout << "L2CR = " << L2CR << "\nCache should now be disabled.\nChoose Quit from the file menu to quit.\n";
}

asm unsigned long getPVR(void)
{
	mfspr	r3,287;
	blr;
}

asm unsigned long getL2CR(void)
{
	mfspr	r3,1017;
	blr;
}

asm unsigned long superCode(register unsigned long)
{
	// See if the L2 cache has already been enabled
	mfspr	r3,1017;
	cmpwi	r3,0;
	beq		@exit;
	
	// Flush the L2 cache by flushing the first 2048K sectors
@flushL2Cache:
	lis		r3,0x0020;	// 2048K
	@flushLoop:
		dcbf		r0,r3;
		subi		r3,r3,32;
		cmplwi	r3,0;
		bne		@flushLoop;
	
	// Disable the cache
	sync;
	mtspr	1017,r4;	// Turn off L2E bit
	sync;
	li		r3,0;
	mtspr	1017,r3;	// Zero the L2CR
	sync;
	
@exit:
	blr;
}