ipl4main.c 6.67 KB
/********************************************************************************
						   NINTENDO64 Disk Drive IPL4

								  main module

								 July 17, 1997
 ********************************************************************************/

#include <ultra64.h>
#include <PR/os_internal.h>
#include "ipl4.h"


static OSThread idleThread;						/* idle thread record				*/
static OSThread mainThread;						/* main thread record				*/
static OSThread grphThread;						/* graphics thread record			*/
static OSThread diskThread;						/* disk thread record				*/
static OSThread rmonThread;						/* disk thread record				*/

uwlong			bootStack[STACKSIZE64];			/* boot process stack memory		*/
static uwlong	idleStack[STACKSIZE64];			/* idle thread stack memory			*/
static uwlong	mainStack[STACKSIZE64];			/* main thread stack memory			*/
static uwlong	grphStack[STACKSIZE64];			/* graphics thread stack memory		*/
static uwlong	diskStack[STACKSIZE64];			/* disk thread stack memory			*/
static uwlong	rmonStack[STACKSIZE64];			/* idle thread stack memory			*/


OSMesgQueue mainMesgque;						/* main thread message queue		*/
OSMesgQueue grphMesgque;						/* graphics thread message queue	*/
OSMesgQueue	diskMesgque;						/* disk drive thread message queue	*/
OSMesgQueue	PimgMesgque;						/* PI manager message queue			*/

static OSMesg	mainMesgbuf[NUM_MAIN_MESGS];	/* main thread message buffer		*/
static OSMesg	grphMesgbuf[NUM_GRPH_MESGS];	/* graphics thread message buffer	*/
static OSMesg	diskMesgbuf[NUM_DISK_MESGS];	/* disk thread message buffer		*/
static OSMesg	PimgMesgbuf[NUM_PIMG_MESGS];	/* PI manager message buffer		*/


IPLHeader	bootHeader;							/* application boot header			*/
DiskStatus	diskStatus;							/* disk I/O status					*/
int			diskErrorNo;						/* disk I/O error number			*/

int			memoryPack;							/* memory pack active				*/
int			clockSetting = FALSE;				/* clock setting active				*/
int			systemReset  = FALSE;				/* Pre-NMI active					*/


/********************************************************************************/
/*																				*/
/*	Read a data block from ROM.													*/
/*																				*/
/********************************************************************************/
extern long
osPiStartDma(OSIoMesg *IOMesg, long prio, long dir, ulong romStart, void *ramAddr, ulong size, OSMesgQueue *mesgque)
{
#ifdef DISKROM
	OSPiHandle *PiHandle = osDriveRomInit();
#else
	OSPiHandle *PiHandle = osCartRomInit();
#endif


	IOMesg->hdr.pri		 = prio;
	IOMesg->hdr.retQueue = mesgque;
	IOMesg->dramAddr	 = ramAddr;
	IOMesg->devAddr		 = romStart;
	IOMesg->size		 = size;

	PiHandle->transferInfo.cmdType = OS_OTHERS;
	osEPiStartDma(PiHandle, IOMesg, dir);
	return(0);
}

long
osPiStartDma_DriveRomOnly(OSIoMesg *IOMesg, long prio, long dir, ulong romStart, void *ramAddr, ulong size, OSMesgQueue *mesgque)
{
	OSPiHandle *PiHandle = osDriveRomInit();

	IOMesg->hdr.pri		 = prio;
	IOMesg->hdr.retQueue = mesgque;
	IOMesg->dramAddr	 = ramAddr;
	IOMesg->devAddr		 = romStart;
	IOMesg->size		 = size;

	PiHandle->transferInfo.cmdType = OS_OTHERS;
	osEPiStartDma(PiHandle, IOMesg, dir);
	return(0);
}

/********************************************************************************/
/*																				*/
/*	Main loop.																	*/
/*																				*/
/********************************************************************************/
static void
MainLoop(void)
{
    OSMesg	event;
    ulong	status = 0;


    while (TRUE) {
		osRecvMesg(&mainMesgque, &event, OS_MESG_BLOCK);

		if (event == MESG_MAIN_LOADDONE) {
			if (diskStatus == DISK_STAT_LOADEND) {
		        osSendMesg(&grphMesgque, MESG_GRPH_STOPGFX, OS_MESG_BLOCK);
				status |= MAIN_STAT_LOADDONE;
		    }
		}
		else if (event == MESG_MAIN_GRPHDONE) {
	 	    status |= MAIN_STAT_GRPHDONE;
		}
		if (!systemReset && status == (MAIN_STAT_LOADDONE|MAIN_STAT_GRPHDONE)) {
		    BootDiskImage(&bootHeader);
		}
    }
}
/********************************************************************************/
/*																				*/
/*	Get memory size.															*/
/*																				*/
/********************************************************************************/
static ulong
GetMemorySize(void)
{
	ulong *memory;
	ulong memsize = 0x00300000;

	do {
		memsize += 0x00100000;
		memory   = (ulong *)(0xA0000000L + memsize);

		memory[0x00000] = 0x12345678L;
		memory[0x3ffff] = 0x87654321L;
	} while (memory[0x00000] == 0x12345678L && memory[0x3ffff] == 0x87654321L);

	return(memsize);
}
/********************************************************************************/
/*																				*/
/*	Main process.																*/
/*																				*/
/********************************************************************************/
static void
MainProcess(void *arg)
{
//	memoryPack = (osMemSize >= 0x00800000);
	memoryPack = (GetMemorySize() >= 0x00800000);

    osCreateMesgQueue(&mainMesgque, mainMesgbuf, NUM_MAIN_MESGS);
    osCreateMesgQueue(&grphMesgque, grphMesgbuf, NUM_GRPH_MESGS);
    osCreateMesgQueue(&diskMesgque, diskMesgbuf, NUM_DISK_MESGS);


	osCreateThread(&diskThread, DISK_THREAD_ID, DiskProcess, arg, diskStack + STACKSIZE64, DISK_PRIORITY);
	osCreateThread(&grphThread, GRPH_THREAD_ID, GrphProcess, arg, grphStack + STACKSIZE64, GRPH_PRIORITY);

	osStartThread(&diskThread);		/* must start before graphics thread	*/
	osStartThread(&grphThread);
	MainLoop();
}
/********************************************************************************/
/*																				*/
/*	Idle process.																*/
/*																				*/
/********************************************************************************/
static void
IdleProcess(void *arg)
{
	osCreateViManager(OS_PRIORITY_VIMGR);
	osViSetMode(&osViModeTable[OS_VI_NTSC_LAN1]);
	osViBlack(TRUE);
	osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON);
	osViSetSpecialFeatures(OS_VI_GAMMA_OFF		 );

	osCreatePiManager((OSPri)OS_PRIORITY_PIMGR, &PimgMesgque, PimgMesgbuf, NUM_PIMG_MESGS);

    /* Start RMON  */
//	osCreateThread(&rmonThread, 0, rmonMain, NULL, rmonStack + STACKSIZE64, OS_PRIORITY_RMON);
//	osStartThread(&rmonThread);

	osCreateThread(&mainThread, MAIN_THREAD_ID, MainProcess, arg, mainStack + STACKSIZE64, MAIN_PRIORITY);
	osStartThread(&mainThread);

	osSetThreadPri(NULL, OS_PRIORITY_IDLE);
	while(1);
}
/********************************************************************************/
/*																				*/
/*	Boot process.																*/
/*																				*/
/********************************************************************************/
extern void
BootProcess(void)
{
	osInitialize();
	__osSetHWIntrRoutine((OSHWIntr)1, __osLeoInterrupt);

	osCreateThread(&idleThread, IDLE_THREAD_ID, IdleProcess, NULL, idleStack + STACKSIZE64, BOOT_PRIORITY);
	osStartThread(&idleThread);
}