#include <windows.h>
#include <bsp.h>
#include "oal.h"

#include <XSRTypes.h>
#include <BML.h>
#include <loader.h>
#include <bsp_args.h>

#include "menu.h"
#include "Eboot_cfg.h"
#include "Externals.h"
#include "Bsp_egpio.h"
#include "onenand.h"
#include "Image_cfg.h"
#include "onedram.h"
#include "BDKMgr.h"


#define MODEM_SYNC_CODE	0x45674567
#define MODEM_ACK_CODE		0xABCDABCD

static volatile GPIO_REG *g_VGPIOReg;
volatile UINT32 *g_pOneDRAMShared;
volatile UINT32 *g_pOneDRAMSFR;

void AllocResources()
{
	g_VGPIOReg		= (GPIO_REG *)OALPAtoVA(BASE_REG_PA_IOPORT, FALSE);
	g_pOneDRAMShared	= (UINT32 *)OALPAtoVA(BASE_REG_PA_ONEDRAM_SHARED, FALSE);
	g_pOneDRAMSFR		= (UINT32 *)OALPAtoVA(BASE_REG_PA_ONEDRAM_SFR, FALSE);	
}

void process_packets(void);

void PhoneOn()
{
	// nINT_ONEDRAM_AP : Modem -> AP
	Set_PinFunction(g_VGPIOReg, nINT_ONEDRAM_AP);
	Set_PinPullUD(g_VGPIOReg, nINT_ONEDRAM_AP, sgip_PULL_UP);

	// set PHONE ACTIVE
	Set_PinFunction(g_VGPIOReg, PHONE_ACTIVE);
	Set_PinPullUD(g_VGPIOReg, PHONE_ACTIVE, sgip_PULL_DISABLE);

	// set PDA ACTIVE 
	Set_PinFunction(g_VGPIOReg, PDA_ACTIVE);
	Set_PinPullUD(g_VGPIOReg, PDA_ACTIVE, sgip_PULL_DISABLE);
    Set_PinData(g_VGPIOReg, PDA_ACTIVE, TRUE); 		
	

#if(BSP_HW_ID<2)
	// _nINT_ONEDRAM_AP : AP -> Modem
	Set_PinFunction(g_VGPIOReg, _nINT_ONEDRAM_AP);
	Set_PinPullUD(g_VGPIOReg, _nINT_ONEDRAM_AP, sgip_PULL_UP);
#endif
	// USIM_BOOT
	Set_PinFunction(g_VGPIOReg, USIM_BOOT);
	Set_PinPullUD(g_VGPIOReg, USIM_BOOT, sgip_PULL_DISABLE);
	Set_PinData(g_VGPIOReg, USIM_BOOT, TRUE);
	
	// FLM_SEL
	Set_PinFunction(g_VGPIOReg, FLM_SEL);
	Set_PinPullUD(g_VGPIOReg, FLM_SEL, sgip_PULL_DISABLE);
	Set_PinData(g_VGPIOReg, FLM_SEL, TRUE);

	// Phone Power-On Sequence
	Set_PinFunction(g_VGPIOReg, PHONE_ON);
	Set_PinPullUD(g_VGPIOReg, PHONE_ON, sgip_PULL_DISABLE);
	Set_PinFunction(g_VGPIOReg, CP_RST);
	Set_PinPullUD(g_VGPIOReg, CP_RST, sgip_PULL_DISABLE);

	Set_PinData(g_VGPIOReg, CP_RST, TRUE);
	msWait(200);
	
	// Assert PHONE_ON
	Set_PinData(g_VGPIOReg, PHONE_ON, TRUE);	
	// Phone Reset (CP_RST ---____---)
	Set_PinData(g_VGPIOReg, CP_RST, FALSE);
	msWait(100);
	Set_PinData(g_VGPIOReg, CP_RST, TRUE);

	// needs below delay time for PMIC's stable operation...
	msWait(600);
	
}

void PhoneOff()
{

	// Phone Reset (CP_RST ---____---) //phoneOff

	Set_PinFunction(g_VGPIOReg, CP_RST);
	Set_PinPullUD(g_VGPIOReg, CP_RST, sgip_PULL_DISABLE);
	Set_PinFunction(g_VGPIOReg, PHONE_ON);
	Set_PinPullUD(g_VGPIOReg, PHONE_ON, sgip_PULL_DISABLE);
	Set_PinData(g_VGPIOReg, PHONE_ON, FALSE);
	
	Set_PinData(g_VGPIOReg, CP_RST, TRUE);
	msWait(500);
	
	Set_PinData(g_VGPIOReg, CP_RST, FALSE);
}



int MenuHandlerPhoneTest(void *arg)
{

	UINT32 CheckPhoneBootTime= OEMEthGetSecs();
	
	AllocResources();

	EdbgOutputDebugString("EOND: +----------------------------+\r\n");
	EdbgOutputDebugString("EOND: |   PHONE IMAGE READ START   |\r\n");
	EdbgOutputDebugString("EOND: +----------------------------+\r\n");
			
	OALMSG(1, (L"PBOOT : g_pOneDRAMSFR=0x%x ,Phone Active(%x)\n\r",g_pOneDRAMSFR,Get_PinData(g_VGPIOReg, PHONE_ACTIVE)));

			
	// 1. Load DBL Binary...
	ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, MAX_DBLIMG_SIZE, MAX_DBLIMG_SIZE);
	
	// 2. Phone PMIC on
	PhoneOff();
	PhoneOn();

	// 3. transfer DBL code to Modem			

	process_packets();

	msWait(150);

	Set_PinData(g_VGPIOReg, USIM_BOOT, FALSE);	
	Set_PinData(g_VGPIOReg, FLM_SEL, FALSE);
	Set_PinData(g_VGPIOReg, PHONE_ON, FALSE);

#if 1

	// 4. Wait for semaphore release
	while(*((int *)BASE_REG_UA_ONEDRAM_SFR) == 0 || *(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) != 0x12341234) {
		OALMSG(1, (L"."));
		msWait(400);
	}
#endif
	OALMSG(1, (L"PBOOT : Modem Boot OK - ABBOX(%x)\n\r",*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) ));		
//	OALMSG(1, (L"\r\nPBOOT : Modem released semaphore\r\n"));	


	// 5. Read Modem Image and NV data
	
	if(!CheckNVPartition(PARTITION_ID_NVDATA))
		EdbgOutputDebugString("CheckNVPartition failed\r\n");
	
	ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, MAX_DBLIMG_SIZE, (MAX_MODEMIMG_SIZE-NV_DATA_LENGTH));

	if(!ReadNVData(MK_ACCESS_DATA, (BYTE *)(BASE_REG_UA_ONEDRAM_NVOFF), NV_DATA_LENGTH, 0, PARTITION_ID_NVDATA))
		EdbgOutputDebugString("ReadNVData failed\r\n");
	
	// 6. release semaphore to Modem

	// write semaphore
	*((int *)BASE_REG_UA_ONEDRAM_SFR) = 0x0; // Virtual


	//msWait(100);

	// 7. write sync code to Modem
	// write mailbox
	*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x10)) = MODEM_SYNC_CODE; // Virtual

	msWait(600);

	OALMSG(1, (L"PBOOT : Wait the Modem Boot OK Ack 0xABCDABCD \n\r"));
	
	OALMSG(1, (L"PBOOT : Phone Active(%x)\n\r",Get_PinData(g_VGPIOReg, PHONE_ACTIVE)));
	
	// 8. Wait for ack code from Modem side... (7 seconds timeout)

	while(1) {
		if(OEMEthGetSecs()-CheckPhoneBootTime > 7)
		{ 
			OALMSG(OAL_ERROR, (L"PBOOT : Modem Boot 7 sec Timeout\n\r"));
			break;
		}
		if(Get_PinData(g_VGPIOReg, PHONE_ACTIVE) == TRUE)
		{
	        OALMSG(1, (L"PBOOT : Phone Active(%x)\n\r",Get_PinData(g_VGPIOReg, PHONE_ACTIVE)));
			if(*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) == MODEM_ACK_CODE)
				break;
		}
		msWait(400);
		OALMSG(1, (L"."));
	}
	OALMSG(1, (L"PBOOT : Modem Boot OK - BOOT TIME(%d sec)\n\r",(OEMEthGetSecs()-CheckPhoneBootTime)));	
	OALMSG(1, (L"PBOOT : Modem Boot OK - ABBOX(%x)\n\r",*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) ));


	return 0;
}

int MenuHandlerPhoneTestEx(void *arg)
{

	UINT32 CheckPhoneBootTime= OEMEthGetSecs();

	AllocResources();
	
	ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, MAX_DBLIMG_SIZE, MAX_MODEMIMG_SIZE);
	
	PhoneOn();

	process_packets();

	msWait(150);

	Set_PinData(g_VGPIOReg, USIM_BOOT, FALSE);	
	Set_PinData(g_VGPIOReg, FLM_SEL, FALSE);	

	if(!CheckNVPartition(PARTITION_ID_NVDATA))
		EdbgOutputDebugString("CheckNVPartition failed\r\n");
	
	ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, MAX_DBLIMG_SIZE, (MAX_MODEMIMG_SIZE-NV_DATA_LENGTH));

	if(!ReadNVData(MK_ACCESS_DATA, (BYTE *)(BASE_REG_UA_ONEDRAM_NVOFF), NV_DATA_LENGTH, 0, PARTITION_ID_NVDATA))
		EdbgOutputDebugString("ReadNVData failed\r\n");
	
	// 6. release semaphore to Modem

	// write semaphore
	*((int *)BASE_REG_UA_ONEDRAM_SFR) = 0x0; // Virtual

	//msWait(100);

	// 7. write sync code to Modem
	// write mailbox
	*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x10)) = 0x45674568; // Virtual

	msWait(600);

	OALMSG(1, (L"PBOOT : Wait the Modem Boot OK Ack 0xABCDABCD \n\r"));
	
	// 8. Wait for ack code from Modem side... (7 seconds timeout)

	while(1) {
		if(OEMEthGetSecs()-CheckPhoneBootTime > 7)
		{ 
			OALMSG(OAL_ERROR, (L"PBOOT : Modem Boot 7 sec Timeout\n\r"));
			break;
		}
		if(Get_PinData(g_VGPIOReg, nINT_ONEDRAM_AP) == FALSE)
		{
			if(*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) == MODEM_ACK_CODE)
				break;
		}
		msWait(400);
		OALMSG(1, (L"."));
	}
	OALMSG(1, (L"PBOOT : Modem Boot OK - BOOT TIME(%d sec)\n\r",(OEMEthGetSecs()-CheckPhoneBootTime)));	
	OALMSG(1, (L"PBOOT : Modem Boot OK - ABBOX(%x)\n\r",*(((int *)BASE_REG_UA_ONEDRAM_SFR+0x08)) ));

	return 0;
}

static int MenuHandlerPhoneTestDBLOnly(void *arg)
{
	AllocResources();
	
	//ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, 20*1024, MAX_MODEMIMG_SIZE);
	
	//PhoneOn(1);

	msWait(150);

	process_packets();

	return 0;
}

static int MenuHandlerOneDRAMTest(void *arg)
{	
	int i=0;

	AllocResources();

	ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, MAX_DBLIMG_SIZE, MAX_MODEMIMG_SIZE);
	
	PhoneOn(1);

	msWait(500);

	process_packets();

	msWait(150);

	Set_PinData(g_VGPIOReg, USIM_BOOT, FALSE);	
	Set_PinData(g_VGPIOReg, FLM_SEL, FALSE);	

	// write semaphore
	g_pOneDRAMSFR[SEMAPHORE] = 0x0;
	// write mailbox
	g_pOneDRAMSFR[MAILBOX_BA] = MODEM_SYNC_CODE;
	
	EdbgOutputDebugString("\r\nwait 3 sec...\r\n");
	msWait(3000);

	while(1) {
	//for(i=0;i<1000;i++) {
		EdbgOutputDebugString("\r\nMAILBOX_AB = 0x%x\r\n", g_pOneDRAMSFR[MAILBOX_AB]);
		
		//EdbgOutputDebugString("wait 3 sec...\r\n");
		msWait(10);
		//EdbgOutputDebugString("give semaphore to modem & write MAILBOX_BA 0x%x\r\n", i);
		g_pOneDRAMSFR[SEMAPHORE] = 0x0;
		g_pOneDRAMSFR[MAILBOX_BA] = i;	
	}

	return 0;
}

static int MenuHandlerPhoneOff(void *arg)
{
	AllocResources();

	OALMSG(1, (L"before : Phone Active(%x)\n\r",Get_PinData(g_VGPIOReg, PHONE_ACTIVE)));
	
	//ReadPhoneFile((byte *)BASE_REG_UA_ONEDRAM, (byte *)BASE_REG_UA_ONEDRAM_SHARED, 20*1024, MAX_MODEMIMG_SIZE);
	
	PhoneOff();

	OALMSG(1, (L"after : Phone Active(%x)\n\r",Get_PinData(g_VGPIOReg, PHONE_ACTIVE)));

	return 0;
}


MENU_ITEM m_menuPhoneProc[] =
{
	{ '1', "Phone Boot", NULL, MenuHandlerPhoneTest, NULL, NULL, NULL, NULL},
	{ '2', "Phone Test (write mailbox 0x45674568)", NULL, MenuHandlerPhoneTestEx, NULL, NULL, NULL, NULL},
	{ '3', "Phone Test (DBL Only)", NULL, MenuHandlerPhoneTestDBLOnly, NULL, NULL, NULL, NULL},
	{ '5', "Phone Off", NULL, MenuHandlerPhoneOff, NULL, NULL, NULL, NULL},
	{ '9', "OneDRAM Loopback Test", NULL, MenuHandlerOneDRAMTest, NULL, NULL, NULL, NULL},
	{ '\0', "", NULL, NULL, NULL, NULL, NULL, NULL}
};
