
/*
================================ COPYRIGHT ================================
The contents of this file are subject to the VTech Informations Ltd. License
of VT-OS Ver. 1.1 operating system (the "License"); you may not use this
file except in compliance with the License.

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
for the specific language governing rights and limitations under the License.
  
The Original Code is VT-OS Ver. 1.1 Operating System, released
on October 1st, 1999
	
The Initial Developer of the Original Code is VTech Informations Ltd.  All
codes are Copyright (C) VTech Informations Ltd. 1999.  All Rights Reserved.
===========================================================================
*/

/*
===========================================================================
File		:	chkmem.c
Author(s)   :   Kenny Ng, Andrew Hui
Company 	:	VTech Informations Ltd.
Project 	:	Helio
Date:		:	October 1st, 1999
Purpose:    :   memory checking and erase all user data
Revision	:	1.1
Note		:	None
===========================================================================
*/

//#define ESD_TEST 11

#include "datatype.h"
#include "Pr31700c.h"
#include "Pr31700s.h"
#include "mmu.h"
#include "kernel.h"
#include "lcddrv.h"
#include "dev_pwr.h"
#include	"CpuIoReg.h"
#include    "init.h"

#define ERASE_ALL_DATA		1
#define DO_NOT_ERASE_DATA	2

/* erase all data ? */
#define ERASE_ALL_DATA_BMP_SIZE 85
const UWORD EraseAllDataBmp[ERASE_ALL_DATA_BMP_SIZE] =
{
	
	
	0x3ff80000, 0x00000000, 0x00e70003, 0x80000000, 0x00f00000,
		0x3ff80000, 0x00000000, 0x00e70003, 0x80008000, 0x01fc0000,
		0x3ff80000, 0x00000000, 0x00e70003, 0x80038000, 0x03fc0000,
		0x38000000, 0x00000000, 0x00e70003, 0x80038000, 0x079e0000,
		0x38000000, 0x00000000, 0x00e70003, 0x80038000, 0x070e0000,
		0x3801dc7c, 0x0f81e001, 0xf0e7007b, 0x87c7e1f0, 0x070e0000,
		0x3801fcff, 0x1fc3f803, 0xfce700ff, 0x8ff7e3fc, 0x000e0000,
		0x3ff9f9e7, 0x3fe3f807, 0x9ce700ff, 0x9e77e79c, 0x001c0000,
		0x3ff9e0c7, 0x38e71c03, 0x1ce701e7, 0x8c73831c, 0x003c0000,
		0x3ff9c00f, 0x3e071c00, 0x3ce701c3, 0x80f3803c, 0x00780000,
		0x3801c07f, 0x1fc7fc01, 0xfce701c3, 0x87f381fc, 0x00700000,
		0x3801c0f7, 0x0fe7fc03, 0xdce701c3, 0x8f7383dc, 0x00700000,
		0x3801c1c7, 0x01e70007, 0x1ce701c3, 0x9c73871c, 0x00700000,
		0x3801c1c7, 0x38e79c07, 0x1ce701e7, 0x9c73871c, 0x00000000,
		0x3ff9c1cf, 0x3fe3f807, 0x3ce700ff, 0x9cf3e73c, 0x00700000,
		0x3ff9c0ff, 0x1fc3f803, 0xfce700ff, 0x8ff3e3fc, 0x00700000,
		0x3ff9c07b, 0x8f81f001, 0xeee7007b, 0x87b9e1ee, 0x00700000
		
		
		/*
        0x7fc00000, 0x00000000, 0xe7000700, 0x020003e0, 0x00000000,
        0x7fc00000, 0x00000000, 0xe7000700, 0x0e0007f0, 0x00000000,
        0x70000000, 0x00000000, 0xe7000700, 0x0e000738, 0x00000000,
        0x70000000, 0x00000000, 0xe7000700, 0x0e000e38, 0x00000000,
        0x700ec7c1, 0xe07800f8, 0xe700770f, 0x9f8f8e38, 0x00000000,
        0x700fcfe7, 0xf8fc01fc, 0xe700ff1f, 0xdf9fc038, 0x00000000,
        0x7fcf1ce7, 0x38cc039c, 0xe701ef39, 0xce39c078, 0x00000000,
        0x7fce00e7, 0x01ce001c, 0xe701c701, 0xce01c0f0, 0x00000000,
        0x700e01e7, 0xc1fe003c, 0xe701c703, 0xce03c1e0, 0x00000000,
        0x700e0fe3, 0xf1fe01fc, 0xe701c71f, 0xce1fc1e0, 0x00000000,
        0x700e1ee0, 0xf9c003dc, 0xe701c73d, 0xce3dc1c0, 0x00000000,
        0x700e1ce0, 0x39ce039c, 0xe701c739, 0xce39c1c0, 0x00000000,
        0x700e1ce7, 0x38ce039c, 0xe701ef39, 0xce39c000, 0x00000000,
        0x7fce1fe3, 0xf0fc03fc, 0xe700ff3f, 0xcfbfc1c0, 0x00000000,
        0x7fce0ee1, 0xe07801dc, 0xe700771d, 0xc79dc1c0, 0x00000000,
		*/
};


/* YES - "up" / "down" button  */
#define ERASE_ALL_DATA_YES_BMP_SIZE 85
const UWORD EraseAllDataYesBmp[ERASE_ALL_DATA_YES_BMP_SIZE] =
{
	0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x01800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x03800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x07800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x0ffe417c, 0x70078000, 0x00041000, 0x00404002, 0x20000000,
		0x1ffe2240, 0x88044000, 0x00041000, 0x00404002, 0x20000000,
		0x3ffe2240, 0x890454e3, 0x1804d392, 0x56405917, 0x73960000,
		0x7ffe1440, 0x80045914, 0xa4013452, 0x59006512, 0x24590000,
		0xfffe087c, 0x70079114, 0x20011455, 0x51004512, 0x24510000,
		0x7ffe0840, 0x080411f3, 0x18011455, 0x51004512, 0x24510000,
		0x3ffe0840, 0x88041100, 0x84011455, 0x51004512, 0x24510000,
		0x1ffe0840, 0x88041114, 0xa4013455, 0x51006532, 0x24510000,
		0x0ffe087c, 0x710410e3, 0x1800d388, 0x910058d3, 0x33910000,
		0x07800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x03800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x01800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		
		
		
		/*
		0xcdf3c000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0xcd866000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x49860000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x79f78000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x3181e000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x31806000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x31866000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x31f3c000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		*/
		
		/*
		0x0000cdf3, 0xc0000000, 0x00000000, 0x00000000, 0x64030000,
		0x0000cd86, 0x60000000, 0x00000000, 0x00000000, 0x0c030000,
		0x00004986, 0x00001cfb, 0x1873379e, 0x3cf07993, 0x7e73e000,
		0x000079f7, 0x800026cd, 0xb0db3633, 0x66c0cdbb, 0x6cdb3000,
		0x00003181, 0xe0001ecd, 0xb0c3363c, 0x66c0f1bb, 0x6cc33000,
		0x00003180, 0x61fc36cd, 0xb0c3360f, 0x66c03cee, 0x6cc33000,
		0x00003186, 0x600036cc, 0xe0db3633, 0x66c0ccee, 0x6cdb3000,
		0x000031f3, 0xc0001ecc, 0xe071f61e, 0x3cc078c6, 0x66733000,
		0x00000000, 0x00000000, 0xc0000000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x80000000, 0x00000000, 0x00000000,
		*/
		/*
		0x00066f9e, 0x0001b000, 0x3608d860, 0x00000d8c, 0x00110000,
		0x00066c33, 0x0001b000, 0x3608d860, 0x00000d8c, 0x00330000,
		0x00024c30, 0x0001bcdf, 0x3610dbe7, 0x9937cd8f, 0x99ff9e7c,
		0x0003cfbc, 0x00000cd9, 0x8010066c, 0xdbb6600c, 0xd9b33366,
		0x00018c0f, 0x00000cd9, 0x8010066c, 0xdbb6600c, 0xd9b33366,
		0x00018c03, 0x0fe00cd9, 0x8010066c, 0xcee6600c, 0xd9b33366,
		0x00018c33, 0x00000cd9, 0x8020066c, 0xcee6600c, 0xd9b33366,
		0x00018f9e, 0x000007df, 0x002003e7, 0x8c66600f, 0x8f999e66,
		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
		*/
};


/* No - any other button  */
#define ERASE_ALL_DATA_NO_BMP_SIZE 60
const UWORD EraseAllDataNoBmp[ERASE_ALL_DATA_NO_BMP_SIZE] =
{
	
	0x0000210c, 0x00078000, 0x00000000, 0x05000000, 0x00000000,
		0x00003112, 0x00044000, 0x00000000, 0x05000020, 0x01100000,
		0x00003121, 0x010454e3, 0x181cb220, 0xef639420, 0x01100000,
		0x00002921, 0x00045914, 0xa422ca21, 0x1594582c, 0x8bb9cb00,
		0x00002921, 0x00079114, 0x20028941, 0x15145032, 0x89122c80,
		0x00002521, 0x000411f3, 0x181e8941, 0x1517d022, 0x89122880,
		0x00002321, 0x00041100, 0x84228941, 0x15141022, 0x89122880,
		0x00002312, 0x00041114, 0xa4228881, 0x15145022, 0x89122880,
		0x0000210c, 0x010410e3, 0x181e8880, 0xe7139032, 0x99122880,
		0x00000000, 0x00000000, 0x00000080, 0x0000002c, 0x6999c880,
		0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0x00000300, 0x00000000, 0x00000000,
		
		
		/*
		0x0000cc70, 0x00000000, 0x00009800, 0x00600088, 0x00000000,
		0x0000cc88, 0x00000000, 0x00019800, 0x00600198, 0x00000000,
		0x0000ed8c, 0x00001cfb, 0x187bdf1e, 0x787ccffc, 0xf3e00000,
		0x0000ed8c, 0x000026cd, 0xb0cd99b3, 0x6066cd99, 0x9b300000,
		0x0000dd8c, 0x00001ecd, 0xb0cd99bf, 0x6066cd99, 0x9b300000,
		0x0000dd8c, 0x01fc36cd, 0xb0cd99b0, 0x6066cd99, 0x9b300000,
		0x0000cc88, 0x000036cc, 0xe0cd99b3, 0x6066cd99, 0x9b300000,
		0x0000cc70, 0x00001ecc, 0xe078d99e, 0x607c7ccc, 0xf3300000,
		0x00000000, 0x00000000, 0xc0000000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x80000000, 0x00000000, 0x00000000,
		*/
		/*
		0x00066380, 0x00000000, 0x00026000, 0x01800220, 0x00000000,
		0x000666c0, 0x00000000, 0x00066000, 0x01800660, 0x00000000,
		0x00076c60, 0x000073ec, 0x61ef7c79, 0xe1f33ff3, 0xcf800000,
		0x00076c60, 0x00009b36, 0xc33666cd, 0x819b3666, 0x6cc00000,
		0x0006ec60, 0x00007b36, 0xc33666fd, 0x819b3666, 0x6cc00000,
		0x0006ec60, 0x07f0db36, 0xc33666c1, 0x819b3666, 0x6cc00000,
		0x000666c0, 0x0000db33, 0x833666cd, 0x819b3666, 0x6cc00000,
		0x00066380, 0x00007b33, 0x81e36679, 0x81f1f333, 0xccc00000,
		0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
		0x00000000, 0x0000000e, 0x00000000, 0x00000000, 0x00000000,
		*/
		
};

#define ERASE_LINE_1_OFFSET 20*1
#define ERASE_LINE_2_OFFSET 20*45
#define ERASE_LINE_3_OFFSET 20*70




#ifdef ESD_TEST



#define MEMORY_1_OFFSET 20*52
#define MEMORY_2_OFFSET 20*76
#define MEMORY_3_OFFSET 20*89



#define MEMORY_CHK_OK_BMP_SIZE 40
const UWORD MemoryCheckOkBmp[MEMORY_CHK_OK_BMP_SIZE] =
{	 /* OK */
	0x00000000, 0x00000000, 0xe3300000, 0x00000000, 0x00000000,
		0x00000000, 0x00000001, 0xb3600000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x1b600000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x1bc00000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x1be00000, 0x00000000, 0x00000000,
		0x00000000, 0x00000003, 0x1b600000, 0x00000000, 0x00000000,
		0x00000000, 0x00000001, 0xb3300000, 0x00000000, 0x00000000,
		0x00000000, 0x00000000, 0xe3300000, 0x00000000, 0x00000000,
};

#define MEMORY_CHK_ERROR_BMP_SIZE 40
const UWORD MemoryCheckErrorBmp[MEMORY_CHK_ERROR_BMP_SIZE] =
{	 /* error */
	0x00000000, 0x0000001f, 0x7cf871f0, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x66ccd998, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x66cd8d98, 0x00000000, 0x00000000,
		0x00000000, 0x0000001f, 0x66cd8d98, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x7cf98df0, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x6cd98db0, 0x00000000, 0x00000000,
		0x00000000, 0x00000018, 0x66ccd998, 0x00000000, 0x00000000,
		0x00000000, 0x0000001f, 0x63c6718c, 0x00000000, 0x00000000,
};


#define MEMORY_READING_BMP_SIZE 50
const UWORD MemoryReadingBmp[MEMORY_READING_BMP_SIZE] =
{  /* reading */
	0x1f00001b, 0x000038e0, 0x00000000, 0x00000000, 0x00000000,
		0x19800018, 0x000038e0, 0x00000000, 0x00000000, 0x00000000,
		0x199e38fb, 0x7c7c3de7, 0x9ff1e7e3, 0x00000000, 0x00000000,
		0x19b34d9b, 0x66cc3dec, 0xd99b3636, 0x00000000, 0x00000000,
		0x1f3f3d9b, 0x66cc356f, 0xd99b3636, 0x00000000, 0x00000000,
		0x1b306d9b, 0x66cc376c, 0x199b3636, 0x00000000, 0x00000000,
		0x19b36d9b, 0x66cc376c, 0xd99b361c, 0x1b600000, 0x00000000,
		0x18de3cfb, 0x667c3267, 0x9999e61c, 0x1b600000, 0x00000000,
		0x00000000, 0x008c0000, 0x00000018, 0x00000000, 0x00000000,
		0x00000000, 0x00780000, 0x00000070, 0x00000000, 0x00000000,
};


#define MEMORY_WRITING_BMP_SIZE 50
const UWORD MemoryWritingBmp[MEMORY_WRITING_BMP_SIZE] =
{  /* writing */
	0x31183260, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x33980600, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x1bb7bf6f, 0x8f87fc79, 0xff1e7e30, 0x00000000, 0x00000000,
		0x1ab6366c, 0xd98666cd, 0x99b36360, 0x00000000, 0x00000000,
		0x1ab6366c, 0xd98666fd, 0x99b36360, 0x00000000, 0x00000000,
		0x1ef6366c, 0xd98666c1, 0x99b36360, 0x00000000, 0x00000000,
		0x0c66366c, 0xd98666cd, 0x99b361c1, 0xb6000000, 0x00000000,
		0x0c66336c, 0xcf866679, 0x999e61c1, 0xb6000000, 0x00000000,
		0x00000000, 0x11800000, 0x00000180, 0x00000000, 0x00000000,
		0x00000000, 0x0f000000, 0x00000700, 0x00000000, 0x00000000,
};

#endif


#define LEFT_ARROW_BMP_SIZE   15*5
const UWORD LeftArrowBmp[LEFT_ARROW_BMP_SIZE] =
{   /* <- arrorw */
	0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x07000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x0f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x1f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x3fff8000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x7fff8000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0xffff8000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x7fff8000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x3fff8000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x1f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x0f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x07000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x03000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
		0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
};






int toggle_lcd;

BOOLEAN mem_chk;
WORD *reset_type;
void	pUartInit(WORD port, WORD baud, WORD config);
void CpuIdle();

#define CS0_1ACCESS 	CS0ACCVAL1_4	/* wait state of CS0 first	access */
#define CS0_2ACCESS 	CS0ACCVAL2_4	/* wait state of CS0 second access */

void Dummy1()
{
	register int i;
	__asm(" .globl ResetChk");
	__asm("ResetChk:");
	
	//              CPU->REG_MEM_CONFIG_4 = ENWATCH|WATCHTIMEVAL_27_5usec|RFSHVAL1_15usec|RFSHVAL0_15usec |ENRFSH1 |ENRFSH0 ;
	//
	//              i=0x2ffff;
	//              while (i--);
	//
	//    reset_type=(WORD*)0xb0f00000;
	//    reset_type[0]=0x000C0080;
	//    reset_type=(WORD*)0xb0e00000;
	//    reset_type[0]=0x000C0080;
	//
	//
	//              reset_type    = (int*)0xb0f00000;     /* mode register */
	//              reset_type[0] = 0x31000000;           /* 16bit Little Endian */
	//
	//              reset_type    = (int*)0xb0e00000;     /* mode register */
	//              reset_type[0] = 0x31000000;           /* 16bit Little Endian */
	//
	
	
	
	
	
	
	reset_type = (WORD *)0x80000020;
	
	if ((WORD)*reset_type == (WORD)BOOT_WARM_PATT)	 /* warm start */
	{
		__asm("la   $26, ResetHandler");  /* AH: routine in HwInit.c      */
		//		  __asm("la   $26, Reset");
		__asm("jr   $26");
		__asm("nop");
	}
	else	  /* cold start */
	{
		
		
		__asm("la   $26, ResetHandler");  /* AH: routine in HwInit.c      */
		__asm("jr   $26");                /* AH: going to init cpu io reg */
		__asm("nop");                     /* AH: then jump to Reset()     */
	}
}



/* This routine is modified by Andrew 991120 */

void LcdOpen();
void writeram();
void Dummy2()
{
	
	__asm(" .globl Reset");
	__asm("Reset:");
	
	
	__asm(" la  $29, mem_alloc_start + 0x1000");
	
    reset_type = (WORD *)0x80000020;
	
	
#ifdef ESD_TEST
	
	
	__asm(" subu    $29, $29, 24");
	__asm(" sw      $31, 0($29)");
	
	if ((WORD)*reset_type == (WORD)BOOT_COLD_PATT)	 /* force to warm start */
	{
		
		mem_chk = ConfirmEraseUserData();
		
		if (mem_chk==ERASE_ALL_DATA)   /* Erase all user data */
			writeram();
		else
			checkram();
	}
	else
		checkram();
	
    while (1)   ;  /*====  for ever loop  =====*/
	
	__asm(" lw      $31, 0($29)");
	__asm(" addu    $29, $29, 24");
	
	
#endif
	
	
	/* check memory  */
	
	__asm(" subu    $29, $29, 24");
	__asm(" sw      $31, 0($29)");
	
	mem_chk = SysMemCheck();
	__asm(" lw      $31, 0($29)");
	__asm(" addu    $29, $29, 24");
	
	
	if ( mem_chk==FALSE )	/* cold start is required */
	{
		*reset_type = (UWORD)BOOT_COLD_PATT;
		
		__asm("la  $26, start");
		__asm("jr  $26");
		__asm("nop");
	}
	else	/* memory is ok, then prompt for warm start or cold start */
	{
		
		if ((UWORD)*reset_type == BOOT_COLD_PATT)	/* force to warm start */
		{
			//			  CPU->REG_VIDEO_CTRL_1 |= (1<<2);
			
			/* prompt user for "Erase all data ?" */
			__asm(" subu    $29, $29, 24");
			__asm(" sw      $31, 0($29)");
			
			mem_chk = ConfirmEraseUserData();
			__asm(" lw      $31, 0($29)");
			__asm(" addu    $29, $29, 24");
			
			if (mem_chk==ERASE_ALL_DATA)   /* Erase all user data */
			{
				*reset_type = (UWORD)BOOT_COLD_PATT;
				
				__asm("la  $26, start");
				__asm("jr  $26");
				__asm("nop");
			}
			
		}
		
		*reset_type = (UWORD)BOOT_WARM_PATT;
		__asm("la   $26, wstart");
		__asm("jr  $26");
		__asm("nop");
	}
	
	
	
	
}




/*===========================================================
The following routine is created by Andrew Hui 991122
===========================================================*/



/* ============= CP0 Access ========== */

#include "pr3910.h"
__asm(".text
	  
	  
	  .globl	pCP0ReadStatusReg;
.ent	pCP0ReadStatusReg;
pCP0ReadStatusReg:
.frame	$29, 0, $31
mfc0	$2, $12
j		$31
.end	pCP0ReadStatusReg


.globl	pCP0WriteStatusReg;
.ent	pCP0WriteStatusReg;
pCP0WriteStatusReg:

.frame $29, 0, $31
mtc0	$4, $12
j		$31
.end	pCP0WriteStatusReg


.globl	pCP0ReadConfigReg;
.ent	pCP0ReadConfigReg;
pCP0ReadConfigReg:

.frame	$29, 0, $31
mfc0	$2, $3
j		$31

.end	pCP0ReadConfigReg

.globl	pCP0WriteConfigReg;
.ent	pCP0WriteConfigReg;
pCP0WriteConfigReg:
.frame	$29, 0, $31
mtc0	$4, $3
j		$31
.end	pCP0WriteConfigReg



.globl	pCP0ReadCauseReg;
.ent	pCP0ReadCauseReg;
pCP0ReadCauseReg:
.frame	$29, 0, $31
mfc0	$2, $13
j		$31
.end	pCP0ReadCauseReg

.globl	pCP0WriteCauseReg;
.ent	pCP0WriteCauseReg;
pCP0WriteCauseReg:
.frame	$29, 0, $31
mtc0	$4, $13
j		$31
.end	pCP0WriteCauseReg





" );

/* ============= CP0 Access ========== */
void SaveAndClearInterruptRegisters();
void pClearInterruptRegisters();
void pTurnLcdOff(void);
int checkram();
void pTurnLcdOn(void);
void DisplayText ( WORD DMOffset, UWORD *Bitmap, WORD length);


#define KEY_INT_DOWN	(1<<10)
#define KEY_INT_UP		(1<<11)

#define ERASE_WAIT_INT_ENABLE_1   0
#define ERASE_WAIT_INT_ENABLE_2   0
#define ERASE_WAIT_INT_ENABLE_3   KEY_INT_RECORD
#define ERASE_WAIT_INT_ENABLE_4   0

#define ERASE_WAIT_INT_ENABLE_5   ( PERINT \
	| KEY_INT_UP  | KEY_INT_DOWN \
	| KEY_INT_SCHEDULE  | KEY_INT_TO_DO \
	| KEY_INT_PHONEBOOK | KEY_INT_PLAY \
| KEY_INT_STOP 	 | KEY_INT_POWER_ON )

//									  | RTCINT	| ALARMINT



#define TMRBASE50MS 	57600

extern UWORD lcd_mem[];
WORD ConfirmEraseUserData()
{
    int i, j;                 // init lcd
	WORD  NotConfirm, Action;
	SHORT DMOffset;
	
	volatile WORD tmp;	  /* cpu idle */
	volatile WORD Cp0status;
	volatile WORD CpuClkSpeed;
	
	register WORD *SaveTo;
	register WORD TimerCounter;
	
	register WORD tmp2,tmp3;	/* power down cpu */
	register WORD *cpu_reg;
	
	pCP0WriteCauseReg(0);
	
	pCP0WriteStatusReg(SR_PE |SR_IEC);
	
	NotConfirm=TRUE;
	Action = 0;
	
	TimerCounter =0;
	
	/* clear lcd display */
	i=LCD_SIZE;
	while(i--) lcd_mem[i]=0;
    pTurnLcdOn();
	
	
	/*======================= Display =======================*/
	
	/* Display confirmation message " Erase all data ? " */
	DisplayText ( (int)ERASE_LINE_1_OFFSET, (UWORD*)EraseAllDataBmp, (int)ERASE_ALL_DATA_BMP_SIZE);
	/* Display confirmation message " YES - "up" / "down" button   " */
	DisplayText ( (int)ERASE_LINE_2_OFFSET, (UWORD*)EraseAllDataYesBmp, (int)ERASE_ALL_DATA_YES_BMP_SIZE);
	/* Display confirmation message " No - any other button   " */
	DisplayText ( (int)ERASE_LINE_3_OFFSET, (UWORD*)EraseAllDataNoBmp, (int)ERASE_ALL_DATA_NO_BMP_SIZE);
	
	
	CPU->REG_CLK_CTRL |= ENTIMERCLK ;
	CPU->REG_PERIODIC_TIMER = PERVAL(57600);
	CPU->REG_TIMER_CTRL |= ENPERTIMER ;
	
	/* enable cpu wake-up interrupt */
	CPU->REG_INT_ENABLE_1  =ERASE_WAIT_INT_ENABLE_1;
	CPU->REG_INT_ENABLE_2  =ERASE_WAIT_INT_ENABLE_2;
	CPU->REG_INT_ENABLE_3  =ERASE_WAIT_INT_ENABLE_3;
	CPU->REG_INT_ENABLE_4  =ERASE_WAIT_INT_ENABLE_4;
	CPU->REG_INT_ENABLE_5  =ERASE_WAIT_INT_ENABLE_5;
	
	pClearInterruptRegisters();
	
	
    i=0xffff;       /* delay for on-button to become stable */
    while(i--);
	
	while (NotConfirm)
	{
		
		/* ========== set CPU to idle mode and wait for the interrupt =========*/
		
		
		/* ===================== Read Key ======================= */
		/* Disable global interrupt */
		/* clear Timer & key interrupt	*/
		/* Setup Timer	 1 min	*/
		/* Setup Key Interrupt	*/
		/* Start timer and enable timer interrupt */
		/* Enable key interrupt */
		
        CpuIdle();
		
		
		
		
		/* if key interrupt  , if up / down key interrupt ,
		set action to erase_data and NotConfirm = FALSE	*/
		
        if (  CPU->REG_INT_STATUS_5 & ( KEY_INT_DOWN ) )
		{
			Action	   = ERASE_ALL_DATA;
			NotConfirm = FALSE;
            CPU->REG_INT_STATUS_5  = ( KEY_INT_DOWN );
			
			
		}
		else
		{
			
		/* if timer interrupt and action = 0, power-off the system and wait
			for on-button interrupt, and then goto the top of this loop */
			
			if (  ( CPU->REG_INT_STATUS_5 &   (   KEY_INT_SCHEDULE
				| KEY_INT_TO_DO
				| KEY_INT_PHONEBOOK
				| KEY_INT_UP
				| KEY_INT_PLAY
				| KEY_INT_POWER_ON
				| KEY_INT_STOP ))
				|| ( CPU->REG_INT_STATUS_3 &  ( KEY_INT_RECORD ) )	 )
			{
			/*	if key interrupt and not up / down key,
				set action to not_erase_data and NotConfirm = FALSE */
				
				Action		= DO_NOT_ERASE_DATA ;
				NotConfirm	= FALSE;
				CPU->REG_INT_STATUS_5 = 		 KEY_INT_SCHEDULE
					| KEY_INT_TO_DO
					| KEY_INT_PHONEBOOK
					| KEY_INT_UP
					| KEY_INT_PLAY
					| KEY_INT_POWER_ON
					| KEY_INT_STOP	;
				
				CPU->REG_INT_STATUS_3 =   KEY_INT_RECORD;
				
				
			}
			else
				if (( CPU->REG_INT_STATUS_5 &  PERINT) && NotConfirm )
				{
					
					CPU->REG_INT_STATUS_5 =  PERINT;
					
					if ( TimerCounter >1200 ) /* wait for 1 min then power off */
						//                if ( TimerCounter >50 ) /* wait for 1 min then power off */
					{
						/*	=======    power off the system    =======	*/
						/* power off routine */
						pTurnLcdOff();
						CPU->REG_TIMER_CTRL &= ~ENPERTIMER ;
						CPU->REG_CLK_CTRL	&= ~ENTIMERCLK ;
						
						/* ============= turn off LCD ========= */
						
						PowerOffWholeSystem();
						
						pTurnLcdOn();
						
						CPU->REG_PERIODIC_TIMER = PERVAL(57600);
						CPU->REG_CLK_CTRL	|= ENTIMERCLK ;
						CPU->REG_TIMER_CTRL |= ENPERTIMER ;
						CPU->REG_INT_STATUS_5 = PERINT;
						TimerCounter =0;
						
						__asm("nop");
						__asm("nop");
						__asm("nop");
						__asm("nop");
						CPU->REG_INT_STATUS_5 = KEY_INT_POWER_ON ;
						
					}
					else
					{
						TimerCounter ++;
					}
					
					
				}
				
		}
		
		
	}
	
	/* change it to 37 MHz */
	tmp = pCP0ReadConfigReg() ;
	CpuClkSpeed = tmp & CPU_IDLE_SPEED_MASK ;	/* save CPU clock speed */
	pCP0WriteConfigReg( ( (tmp&~(CPU_IDLE_SPEED_MASK)) | (CPU_CLK_75M) ) );
	
	CPU->REG_TIMER_CTRL &= ~ENPERTIMER ;
	CPU->REG_CLK_CTRL	&= ~ENTIMERCLK ;
	
	pClearInterruptRegisters();
	
	
	return (Action);
}

void pClearInterruptRegisters()
{
	/* clear all interrupt and disable all interrupt */
	CPU->REG_INT_STATUS_1 =0xffffffff;
	CPU->REG_INT_STATUS_2 =0xffffffff;
	CPU->REG_INT_STATUS_3 =0xffffffff;
	CPU->REG_INT_STATUS_4 =0xffffffff;
	CPU->REG_INT_STATUS_5 =0xffffffff;
}

void SaveAndClearInterruptRegisters()
{
	volatile WORD *SaveTo;
	
	SaveTo = SaveIoRegLoc;
	SaveTo [pINT_ENABLE_1	 ] = CPU->REG_INT_ENABLE_1	  ;
	SaveTo [pINT_ENABLE_2	 ] = CPU->REG_INT_ENABLE_2	  ;
	SaveTo [pINT_ENABLE_3	 ] = CPU->REG_INT_ENABLE_3	  ;
	SaveTo [pINT_ENABLE_4	 ] = CPU->REG_INT_ENABLE_4	  ;
	SaveTo [pINT_ENABLE_5	 ] = CPU->REG_INT_ENABLE_5	  ;
	
	pClearInterruptRegisters();
}

RestoreInterruptRegisters()
{
	volatile WORD *SaveTo;
	
	SaveTo = SaveIoRegLoc;
	
	/* restore interrupt enable registers*/
	CPU->REG_INT_ENABLE_1 = SaveTo [pINT_ENABLE_1];
	CPU->REG_INT_ENABLE_2 = SaveTo [pINT_ENABLE_2];
	CPU->REG_INT_ENABLE_3 = SaveTo [pINT_ENABLE_3];
	CPU->REG_INT_ENABLE_4 = SaveTo [pINT_ENABLE_4];
	CPU->REG_INT_ENABLE_5 = SaveTo [pINT_ENABLE_5];
}


void pTurnLcdOff(void)
{
	CPU->REG_VIDEO_CTRL_2 = VIDRATE(A_LCD_VIDRATE) | HORZVAL(LCD_WIDTH / 4 - 1)
		| LINEVAL(LCD_HEIGHT+30);
	
	while ( ((CPU->REG_VIDEO_CTRL_1 >>22)&0x3ff)<161  ) ;
	CPU->REG_VIDEO_CTRL_1 |= ENFREEZEFRAME;
	while ( ((CPU->REG_VIDEO_CTRL_1 >>22)&0x3ff)!=0  ) ;
	
	CPU->REG_VIDEO_CTRL_1 &= ~ENVID;
	CPU->REG_CLK_CTRL &= ~ENVIDCLK;
	CPU->REG_VIDEO_CTRL_1 &= ~DISPON;
	CPU->REG_MFIO_SEL |= (1<<3);
	CPU->REG_MFIO_DIRECTN |= (1<<3);
	CPU->REG_MFIO_DATA_OUT &= ~(1<<3);
	
	CPU->REG_VIDEO_CTRL_2 = VIDRATE(A_LCD_VIDRATE) | HORZVAL(LCD_WIDTH / 4 - 1)
		| LINEVAL(LCD_HEIGHT-1);
	CPU->REG_VIDEO_CTRL_1 &= ~ENFREEZEFRAME;
}


void pTurnLcdOn(void)
{
	int i;
	
	/* ============= init LCD and turn it on ===========  */
	CPU->REG_POWER_CTRL &= ~VIDRF(3);
	CPU->REG_POWER_CTRL |= VIDRF(VIDEO_RF);
	CPU->REG_VIDEO_CTRL_1 = BAUDVAL(A_LCD_BAUD) | VIDDONEVAL(0x4) | BITSEL(2)
								| (CPU->REG_VIDEO_CTRL_1 & (1<<2)) ;
	CPU->REG_VIDEO_CTRL_2 = VIDRATE(A_LCD_VIDRATE) | HORZVAL(LCD_WIDTH / 4 - 1) | LINEVAL(LCD_HEIGHT - 1);
	
	CPU->REG_VIDEO_CTRL_3 = VIDBANK(0x000) | VIDBASEHI(((UWORD)lcd_mem & 0x0FFFFFFF)>>4);
	CPU->REG_VIDEO_CTRL_4 = FRAMEMASKVAL(0) | VIDBASELO((((UWORD)lcd_mem & 0x0FFFFFFF) + LCD_WIDTH * LCD_HEIGHT * 4 / 8)>>4);
	
	CPU->REG_VIDEO_CTRL_7 = 0xFA50;
	CPU->REG_VIDEO_CTRL_8 = 0x7DA;
	CPU->REG_VIDEO_CTRL_9 = 0x7DBEA5A5;
	CPU->REG_VIDEO_CTRL_10 = 0x7DFBE;
	CPU->REG_VIDEO_CTRL_11 = 0x7A5AD;
	CPU->REG_VIDEO_CTRL_12 = 0xFBFDFE7;
	CPU->REG_VIDEO_CTRL_13 = 0x7B5ADEF;
	CPU->REG_VIDEO_CTRL_14 = 0xB9DC663;
	
	/* clear LCD memory */
	//				  i=LCD_SIZE;
	//				  while(i--) lcd_mem[i]=0;
	
	/* turn the display on */
	CPU->REG_CLK_CTRL |= ENVIDCLK;
	CPU->REG_VIDEO_CTRL_1 |= ENVID;
	CPU->REG_VIDEO_CTRL_1 |= DISPON;
	
	CPU->REG_MFIO_SEL	  |=  (1<<3);
	CPU->REG_MFIO_DIRECTN |=  (1<<3);
	CPU->REG_MFIO_DATA_OUT |= (1<<3);
}


void DisplayText ( WORD DMOffset, UWORD *Bitmap, WORD length)
{
	
	int i,j;
	
	for (i=0; i<length; i++)
	{
		for (j=0; j<32; j++)
		{
			
			if( (Bitmap[i] >>(31-j)) &1 )
				if ((j&1))
					lcd_mem[i*4 + j/8  + DMOffset] |= (0x0f<<((j-1)%8)*4);
				else
					lcd_mem[i*4 + j/8  + DMOffset] |= (0x0f<<((j+1)%8)*4);
		}
	}
}


#ifdef ESD_TEST

#define SDRAM_ADR1	0x82000000
#define RAM_SIZE1	0x00200000

#define SDRAM_ADR2	0x82400000
#define RAM_SIZE2	0x00200000

#define MEMORY_1_OFFSET 20*52
#define MEMORY_2_OFFSET 20*76
#define MEMORY_3_OFFSET 20*89


int checkram()
{
	
	register char *mem8;
	
	int ramerr;
	int i;
	int tmp;
	volatile WORD Cp0status;
	volatile WORD CpuClkSpeed;
	
	
	CPU->REG_SIB_CTRL &=  ~(SCLKDIV(7));
	CPU->REG_SIB_CTRL |=  SCLKDIV(0);
	
	/* config SIB clock */
	CPU->REG_CLK_CTRL &=  ~(SIBMCLKDIV(7));
	CPU->REG_CLK_CTRL |=  SIBMCLKDIR | ENSIBMCLK | SIBMCLKDIV(2)| CSERSEL;
	
	CPU->REG_SIB_CTRL |=  ENSIB |ENSF0 |ENSF1 ; 	 /* Enable subframe 0 */
	
	
	
	pUartInit(UART_A, UART_BAUD115200, UART_DATABIT8|UART_PARITY_NONE|UART_STOPBIT1);
	
	stdoutput = (void *)UartPrints;
	
	
	//    printf("\n.........Checking memory...........\n");
	
	
	/* clear lcd display */
	i=LCD_SIZE;
	while(i--) lcd_mem[i]=0;
	
	DisplayText ( (int)MEMORY_1_OFFSET, (UWORD*)MemoryReadingBmp, (int)MEMORY_READING_BMP_SIZE);
	pTurnLcdOn();
	
	ramerr=0;
	
	mem8=(char*)SDRAM_ADR1;
	
	/*	read  and check */
	for (i=0; i<(RAM_SIZE1-1); i++)
	{
		if (mem8[i] != (char)(1 << (i%8)))
		{
			//                printf("\n\t\t\t\t%x : %02x <> %2x",&mem8[i],  (0xff&(~(1<<(i%8)))),(0xff&mem8[i]));
			ramerr++;
		}
	}
	
	if (ramerr) DisplayText ( (int)MEMORY_2_OFFSET, (UWORD*)MemoryCheckErrorBmp, (int)MEMORY_CHK_ERROR_BMP_SIZE);
	else DisplayText ( (int)MEMORY_2_OFFSET, (UWORD*)MemoryCheckOkBmp, (int)MEMORY_CHK_OK_BMP_SIZE);
	
	ramerr=0;
	mem8=(char*)SDRAM_ADR2;
	
	/*	read  and check */
	for (i=0; i<(RAM_SIZE2-1); i++)
	{
		
		if (mem8[i] != (char)(1 << (i%8)))
		{
			//                printf("\n\t\t\t\t%x : %02x <> %2x",&mem8[i],  (0xff&(~(1<<(i%8)))),(0xff&mem8[i]));
			ramerr++;
		}
	}
	
	if (ramerr) DisplayText ( (int)MEMORY_3_OFFSET, (UWORD*)MemoryCheckErrorBmp, (int)MEMORY_CHK_ERROR_BMP_SIZE);
	else DisplayText ( (int)MEMORY_3_OFFSET, (UWORD*)MemoryCheckOkBmp, (int)MEMORY_CHK_OK_BMP_SIZE);
	
	for (i=0; i<(0xffffff); i++);
	
	
	CPU->REG_INT_ENABLE_1  =ERASE_WAIT_INT_ENABLE_1;
	CPU->REG_INT_ENABLE_2  =ERASE_WAIT_INT_ENABLE_2;
	CPU->REG_INT_ENABLE_3  =ERASE_WAIT_INT_ENABLE_3;
	CPU->REG_INT_ENABLE_4  =ERASE_WAIT_INT_ENABLE_4;
	CPU->REG_INT_ENABLE_5  =ERASE_WAIT_INT_ENABLE_5;
	SaveAndClearInterruptRegisters();
	
	
	
	/* Disable Interrupt */
	tmp = pCP0ReadStatusReg();
	Cp0status= tmp & CP0_IDLE_MASK; 	/* save CP0 status register */
	pCP0WriteStatusReg(tmp&~(CP0_IDLE_MASK));
	
	
	/* Disable SIB Module */
	CPU->REG_CLK_CTRL &=  ~(ENSIBMCLK);
	CPU->REG_SIB_CTRL &= ~(ENSIB |ENSF0 |ENSF1);
	
	/* Set CPU_CLK to slow speed  (9 MHz)*/
	tmp = pCP0ReadConfigReg() ;
	CpuClkSpeed = tmp & CPU_IDLE_SPEED_MASK ;	/* save CPU clock speed */
	pCP0WriteConfigReg( ( (tmp&~(CPU_IDLE_SPEED_MASK)) | (CPU_CLK_9M) ) );
	
	ENA_GBL_INT;
	CPU->REG_POWER_CTRL |= STOPCPU;
	CPU->REG_POWER_CTRL &= ~(STOPCPU);
	DIS_GBL_INT;
	
	/* Restore CPU_CLK */
	tmp = pCP0ReadConfigReg() ;
	pCP0WriteConfigReg( (tmp & ~(CPU_IDLE_SPEED_MASK)) | CpuClkSpeed);
	
	/* Restore Enabled Interrupt */
	tmp = pCP0ReadStatusReg();
	pCP0WriteStatusReg((tmp&~(CP0_IDLE_MASK))|Cp0status);
	
	
	/* restore interrupt enable registers*/
	RestoreInterruptRegisters();
	
	/* Display confirmation message " Erase all data ? " */
	DisplayText ( (int)ERASE_LINE_1_OFFSET, (UWORD*)EraseAllDataBmp, (int)ERASE_ALL_DATA_BMP_SIZE);
	
	while (1);
}





void writeram()
{
	register char *mem8;
	
	int i;
	int ramerr;
	int tmp;
	volatile WORD Cp0status;
	volatile WORD CpuClkSpeed;
	
	
	/* clear lcd display */
	i=LCD_SIZE;
	while(i--) lcd_mem[i]=0;
	
	DisplayText ( (int)MEMORY_1_OFFSET, (UWORD*)MemoryWritingBmp, (int)MEMORY_WRITING_BMP_SIZE);
	
	pTurnLcdOn();
	
	mem8=(char*)SDRAM_ADR1;
	
	
	/* walking 1 */
	for (i=0; i<(RAM_SIZE1-1); i++)
		mem8[i]= 1 << (i%8);
	
	DisplayText ( (int)MEMORY_2_OFFSET, (UWORD*)MemoryCheckOkBmp, (int)MEMORY_CHK_OK_BMP_SIZE);
	
	mem8=(char*)SDRAM_ADR2;
	
	/* walking 1 */
	for (i=0; i<(RAM_SIZE2-1); i++)
		mem8[i]= 1 << (i%8);
	
	DisplayText ( (int)MEMORY_3_OFFSET, (UWORD*)MemoryCheckOkBmp, (int)MEMORY_CHK_OK_BMP_SIZE);
	
	
	for (i=0; i<(0xffffff); i++) ;
	
	CPU->REG_INT_ENABLE_1  =ERASE_WAIT_INT_ENABLE_1;
	CPU->REG_INT_ENABLE_2  =ERASE_WAIT_INT_ENABLE_2;
	CPU->REG_INT_ENABLE_3  =ERASE_WAIT_INT_ENABLE_3;
	CPU->REG_INT_ENABLE_4  =ERASE_WAIT_INT_ENABLE_4;
	CPU->REG_INT_ENABLE_5  =ERASE_WAIT_INT_ENABLE_5;
	
	SaveAndClearInterruptRegisters();
	
	
	
	/* Disable Interrupt */
	tmp = pCP0ReadStatusReg();
	Cp0status= tmp & CP0_IDLE_MASK; 	/* save CP0 status register */
	pCP0WriteStatusReg(tmp&~(CP0_IDLE_MASK));
	
	
	/* Disable SIB Module */
	CPU->REG_CLK_CTRL &=  ~(ENSIBMCLK);
	CPU->REG_SIB_CTRL &= ~(ENSIB |ENSF0 |ENSF1);
	
	/* Set CPU_CLK to slow speed  (9 MHz)*/
	tmp = pCP0ReadConfigReg() ;
	CpuClkSpeed = tmp & CPU_IDLE_SPEED_MASK ;	/* save CPU clock speed */
	pCP0WriteConfigReg( ( (tmp&~(CPU_IDLE_SPEED_MASK)) | (CPU_CLK_9M) ) );
	
	ENA_GBL_INT;
	CPU->REG_POWER_CTRL |= STOPCPU;
	CPU->REG_POWER_CTRL &= ~(STOPCPU);
	DIS_GBL_INT;
	
	/* Restore CPU_CLK */
	tmp = pCP0ReadConfigReg() ;
	pCP0WriteConfigReg( (tmp & ~(CPU_IDLE_SPEED_MASK)) | CpuClkSpeed);
	
	/* Restore Enabled Interrupt */
	tmp = pCP0ReadStatusReg();
	pCP0WriteStatusReg((tmp&~(CP0_IDLE_MASK))|Cp0status);
	
	
	/* restore interrupt enable registers*/
	RestoreInterruptRegisters();
	
	
	/* Display confirmation message " Erase all data ? " */
	DisplayText ( (int)ERASE_LINE_1_OFFSET, (UWORD*)EraseAllDataBmp, (int)ERASE_ALL_DATA_BMP_SIZE);
	
	while (1);
	
	
	
}






/*---------------------------------------------------------------------------
Prototype 	:	void  UartInit(WORD port, WORD baud, WORD config );
Purpose		:	initialize the UART port for serial communication
Scope 		:	OS
input 		:	port	: UART_A / UART_B
baud	: e.g.	38400
config	: data_bits, Parity, stop_bit : "8N1"
(defined in UART_DRV.H)
output		:	None
return		:	None
---------------------------------------------------------------------------*/
#define UART_A_CTS	(1<<2)	/* input */
#define UART_A_RTS	(1<<4)	/* output */
void	pUartInit(WORD port, WORD baud, WORD config)
{
	int tmp;
	
	/* config UART port */
	if (port == UART_A)  /* UART A */
	{
		/* config UART clock */
		CPU->REG_CLK_CTRL &= ~CSERDIV(7) ;
		CPU->REG_CLK_CTRL |= CSERDIV(3) | ENCSERCLK | ENUARTACLK;
		
		CPU ->REG_UARTA_CTRL_1		= config;		/* set data, stop, parity*/
		CPU ->REG_UARTA_CTRL_2		= baud; 		/* baud rate			 */
		CPU ->REG_UARTA_DMA_CTRL_1	= 0;			/* DMA buf start Address */
		CPU ->REG_UARTA_DMA_CTRL_2	= 0;			/* DMA buf length		 */
		
		
		/* Uart Tranciever */
		CPU->REG_MFIO_SEL		  |= UART_TX_ENABLE |UART_RX_DISABLE
			|UART_A_CTS |UART_A_RTS ;
		CPU->REG_MFIO_DIRECTN	  |= UART_TX_ENABLE |UART_RX_DISABLE |UART_A_RTS;
		CPU->REG_MFIO_DIRECTN	  &= ~ UART_A_CTS;
		CPU->REG_MFIO_DATA_OUT	  |=  UART_TX_ENABLE  ;  /* disable uart tx */
		CPU->REG_MFIO_DATA_OUT	  &= ~(UART_RX_DISABLE | UART_A_RTS) ;
		CPU->REG_MFIO_POWER_DOWN  |= (UART_A_RTS |UART_A_CTS);
		CPU->REG_MFIO_POWER_DOWN  &= ~(UART_TX_ENABLE |UART_RX_DISABLE);
		
		/* Uart Module */
		tmp = CPU->REG_UARTA_HLDG;				/* dummy read			*/
		tmp = CPU->REG_UARTA_HLDG;				/* dummy read			*/
		CPU->REG_UARTA_CTRL_1  |= ENUART;		/* enable  UART A		*/
		CPU->REG_UARTA_CTRL_1 &= ~DISTXD;		/* enable Tx			*/
		
		
		
		
		
		
		
		
		
	}
}


#endif


void CpuIdle()
{
    volatile WORD tmp;    /* cpu idle */
	volatile WORD Cp0status;
	volatile WORD CpuClkSpeed;
	
	/* save interrupt enable registers*/
	//		  SaveAndClearInterruptRegisters();
	CPU->REG_INT_ENABLE_1  =ERASE_WAIT_INT_ENABLE_1;
	CPU->REG_INT_ENABLE_2  =ERASE_WAIT_INT_ENABLE_2;
	CPU->REG_INT_ENABLE_3  =ERASE_WAIT_INT_ENABLE_3;
	CPU->REG_INT_ENABLE_4  =ERASE_WAIT_INT_ENABLE_4;
	CPU->REG_INT_ENABLE_5  =ERASE_WAIT_INT_ENABLE_5;
	
	/* Disable Interrupt */
	tmp = pCP0ReadStatusReg();
	Cp0status= tmp & CP0_IDLE_MASK; 	/* save CP0 status register */
	pCP0WriteStatusReg(tmp&~(CP0_IDLE_MASK));
	
	/* Disable SIB Module */
	CPU->REG_CLK_CTRL &=  ~(ENSIBMCLK);
	CPU->REG_SIB_CTRL &= ~(ENSIB |ENSF0 |ENSF1);
	
	/* Set CPU_CLK to slow speed  (9 MHz)*/
	tmp = pCP0ReadConfigReg() ;
	CpuClkSpeed = tmp & CPU_IDLE_SPEED_MASK ;	/* save CPU clock speed */
	pCP0WriteConfigReg( ( (tmp&~(CPU_IDLE_SPEED_MASK)) | (CPU_CLK_9M) ) );
	
	ENA_GBL_INT;
	CPU->REG_POWER_CTRL |= STOPCPU;
	CPU->REG_POWER_CTRL &= ~(STOPCPU);
	DIS_GBL_INT;
	
	/* Restore CPU_CLK */
	tmp = pCP0ReadConfigReg() ;
	pCP0WriteConfigReg( (tmp & ~(CPU_IDLE_SPEED_MASK)) | CpuClkSpeed);
	
	
	tmp=0xf;
	while (tmp--);
	
	/* Restore Enabled Interrupt */
	tmp = pCP0ReadStatusReg();
	pCP0WriteStatusReg((tmp&~(CP0_IDLE_MASK))|Cp0status);
	
	
	/* restore interrupt enable registers*/
	RestoreInterruptRegisters();
	
}

PowerOffWholeSystem()
{
	
    register WORD i,j,tmp,tmp2,tmp3;    /* power down cpu */
	register WORD *cpu_reg;
	
	
    SaveAndClearInterruptRegisters();
	
	CPU->REG_INT_ENABLE_1 =0;
	CPU->REG_INT_ENABLE_2 =0;
	CPU->REG_INT_ENABLE_3 =0;
	CPU->REG_INT_ENABLE_4 =0;
	//                    CPU->REG_INT_ENABLE_5 = KEY_INT_POWER_ON ;
	CPU->REG_INT_ENABLE_5 = 0;
	
	
	/* power off CPU */
	
	tmp = pCP0ReadStatusReg() ;
	tmp &= ~( RUNTIME_INTERRUPT_MASK) ;
	tmp |= SR_PE |SR_IEC ;
	
	pCP0WriteStatusReg(tmp);
	
				ENA_GBL_INT;
				
				tmp2 = CPU->REG_MEM_CONFIG_4;
				tmp3 = CPU->REG_POWER_CTRL;
				
				
				pCP0WriteCauseReg(0);
				
				for (i=0; i<2; i++)
				{
					cpu_reg=(WORD*)0xb0e00000;		 /* precharge of SDRAM */
					cpu_reg[0]=0x000c0080;		/* Little Endian */
					cpu_reg=(WORD*)0xb0f00000;
					cpu_reg[0]=0x000c0080;
					
					CPU->REG_MEM_CONFIG_4 = tmp2;	/* power down memory (SDRAM) */
					CPU->REG_POWER_CTRL=tmp3;		/* power down CPU			 */
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					
					
					CPU->REG_MEM_CONFIG_4 &= ~MEMPOWERDOWN;
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					__asm("nop");
					
					
					tmp2 |= MEMPOWERDOWN;
					
					
					tmp3  &= (~(VCCON|PWRCS));
					tmp3  |= (COLDSTART);
					
					
					j=0;
					do
					{
						j++  ;
					} while (j<0x1fff);
					
				}
				
				j=0;
				do
				{
					j++  ;
				} while (j<0x1fff);
				
				
				/* Restore all interrupt enable register */
				
				//									CPU->REG_MEM_CONFIG_4 = ENWATCH|WATCHTIMEVAL_27_5usec|RFSHVAL1_15usec|RFSHVAL0_15usec |ENRFSH1 |ENRFSH0 ;
				//
				//									i=0x2ffff;
				//									while (i--);
				//
				//						  reset_type=(WORD*)0xb0f00000;
				//						  reset_type[0]=0x000C0080;
				//						  reset_type=(WORD*)0xb0e00000;
				//						  reset_type[0]=0x000C0080;
				//
				//
				//									reset_type	  = (int*)0xb0f00000;	  /* mode register */
				//									reset_type[0] = 0x31000000; 		  /* 16bit Little Endian */
				//
				//									reset_type	  = (int*)0xb0e00000;	  /* mode register */
				//									reset_type[0] = 0x31000000; 		  /* 16bit Little Endian */
				
				
				DIS_GBL_INT;
				
				/* Restore Enabled Interrupt */
				tmp = pCP0ReadStatusReg();
				tmp |= SR_PE | SR_IEC | RUNTIME_INTERRUPT_MASK ;
				
				
				pCP0WriteStatusReg(tmp);
				//                    printf("\n   power on  1");
				
				pClearInterruptRegisters();
				RestoreInterruptRegisters();
				
				pClearInterruptRegisters();
				
				
}
