⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emlcpu.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
字号:
/******************************************************
Copyright(c) 版权所有,1998-2003微逻辑。保留所有权利。
******************************************************/

/*****************************************************
文件说明:cpu模拟器
版本号:2.0.0
开发时期:2000
作者:李林
修改记录:
******************************************************/
//typedef void * HKEY;
#include <windows.h>
#include <eversion.h>
//#include <ewindows.h>
#include <w32intr.h>
//#include <ekeydrv.h>
#include <cpu.h>
#include <crtdbg.h>

#define WM_RTCMSG (WM_USER+2000)
#define WM_TIMERMSG (WM_USER+2001)
/*
typedef struct _KERNEL_DATA
{
	_INTRBITS intrBits;
	_INTRMASK intrMask;
	int IntrEnable;
	MSG IntrMsg[32];
	MSG msgCurrent;
	HANDLE hKingmosThread;
	HANDLE hIntrThread;
	HANDLE hHardwareEvent;
	CONTEXT  ctSave;
	UINT uiLockSegStart;
	UINT uiLockSegEnd;
	CRITICAL_SECTION csMsg;
	LONG nLockCount;
}KERNEL_DATA, FAR * LPKERNEL_DATA;
*/
volatile LPKERNEL_DATA lpKernelData;
static BOOL bPowerOff = FALSE;
static BOOL bPowerKeyDown = FALSE;
static BOOL CPU_CheckIRQEvent( void );

extern UINT LockSeg_Start( void );
extern UINT LockSeg_End( void );
extern void INTR_Interrupt( void );
extern void KingmosStart( LPVOID );

void CPU_IRQTrap( void );
extern void JmpBack( TSS *, volatile int * lpIntrEnable );

//VOID ReleaseKernelData( void )
//{
//	LONG lOldProtect;
//	if( InterlockedDecrement( &lpKernelData->nLockCount ) == 0 )
//	    VirtualProtect( lpKernelData, 1024 * 4, PAGE_NOACCESS, &lOldProtect );	
//}

//VOID GetKernelData( void )
//{
//	LONG lOldProtect;
//	if( InterlockedIncrement( &lpKernelData->nLockCount ) > 0 )
//	    VirtualProtect( lpKernelData, 1024 * 4, PAGE_READWRITE, &lOldProtect );
//	else
//	{
//		_ASSERT( 0 );
//	}	
//}

void UnlockIRQRestore( UINT * lpuiSave )
{
//    GetKernelData();
	InterlockedExchange( (LPVOID)&lpKernelData->IntrEnable, *lpuiSave );
//	ReleaseKernelData();
}

void LockIRQSave( UINT * lpuiSave )
{
  //  GetKernelData();
	*lpuiSave = (UINT)InterlockedExchange( (LPVOID)&lpKernelData->IntrEnable, FALSE );
	//ReleaseKernelData();
}

#ifdef __DEBUG

static char * lpFileName;
static int iLine;
void _INTR_OFF( char * lpfn, int line )
{  
	lpFileName = lpfn;
	iLine = line;

	//GetKernelData();
	//_ASSERT( lpKernelData->IntrEnable );
	InterlockedExchange( (LPLONG)&lpKernelData->IntrEnable, FALSE );
	//ReleaseKernelData();

	lpFileName = lpfn;
	iLine = line;
}

void _INTR_ON( char * lpfn, int line )
{
	//GetKernelData();
	InterlockedExchange( (LPLONG)&lpKernelData->IntrEnable, TRUE );
	//ReleaseKernelData();
}

#else

void INTR_OFF( void )
{
	//GetKernelData();
	InterlockedExchange( (LPLONG)&IntrEnable, FALSE );
	//ReleaseKernelData();
}

void INTR_ON( void )
{
	//GetKernelData();
	InterlockedExchange( (LPLONG)&IntrEnable, TRUE );
	//ReleaseKernelData();
}

#endif


//中断源
void CPU_SetIRQEvent( MSG * lpmsg )
{
	EnterCriticalSection( &lpKernelData->csMsg );
    //GetKernelData();
	lpKernelData->msgCurrent = *lpmsg;
	if( CPU_CheckIRQEvent() )
		SetEvent(lpKernelData->hHardwareEvent);
	//ReleaseKernelData();
	LeaveCriticalSection( &lpKernelData->csMsg );
}
//检查中断源是否可以使用
static BOOL CPU_CheckIRQEvent( void ) //MSG * lpmsg )
{
	int * lpIntr;
	int * lpMask;
	MSG * lpmsg;
	BOOL bRetv = TRUE;
//	UINT uiSave;
//	LockIRQSave( &uiSave );

	EnterCriticalSection( &lpKernelData->csMsg );
    //GetKernelData();

    lpIntr = (int *)&lpKernelData->intrBits;
	lpMask = (int *)&lpKernelData->intrMask;
	lpmsg = &lpKernelData->msgCurrent;

	if( lpmsg->message == WM_RTCMSG )
	{
	    lpKernelData->intrBits.timer1 = 1;
        lpKernelData->IntrMsg[ID_INTR_TIMER1] = *lpmsg;// = *lpmsg;
	}
   
    else if( lpmsg->message >= WM_MOUSEFIRST &&
		lpmsg->message <= WM_MOUSELAST )
	{
		if( lpmsg->message == WM_MOUSEMOVE && 
			(lpmsg->wParam & MK_LBUTTON) == 0 )
		{
			bRetv = FALSE; // nothing to do
		}
        else
		{
			lpKernelData->intrBits.mouse = 1;        
			lpKernelData->IntrMsg[ID_INTR_MOUSE] = *lpmsg;
		}
    }
    else if( lpmsg->message == WM_KEYDOWN || 
             lpmsg->message == WM_KEYUP )
    {
		if( bPowerOff )
		{
			bRetv = FALSE;
			if( lpmsg->message == WM_KEYDOWN )
			{
				if( bPowerKeyDown == FALSE )
				{	//wake up event
					lpKernelData->intrBits.keyboard = 1;
					lpKernelData->IntrMsg[ID_INTR_KEYBOARD] = *lpmsg;
					bRetv = TRUE;
				}
			}
			else if( lpmsg->message == WM_KEYUP )
			{
				bPowerKeyDown = FALSE;
			}
		}
		else
		{
			lpKernelData->intrBits.keyboard = 1;
			lpKernelData->IntrMsg[ID_INTR_KEYBOARD] = *lpmsg;
		}
    }
    else if( lpmsg->message == WM_CLOSE )
    {
        lpKernelData->intrBits.keyboard = 1;
		lpKernelData->IntrMsg[ID_INTR_KEYBOARD].message = WM_KEYDOWN;
		lpKernelData->IntrMsg[ID_INTR_KEYBOARD].wParam = 0X06;//=VK_POWEROFF;
		lpKernelData->IntrMsg[ID_INTR_KEYBOARD].lParam = 0;
	}
    else if( lpmsg->message == WM_TIMERMSG )
    {
		lpKernelData->intrBits.timer0 = 1;
        //lpKernelData->IntrMsg[ID_INTR_TIMER0] = *lpmsg;
		lpKernelData->IntrMsg[ID_INTR_TIMER0].message = WM_TIMER;
    }
	else
	{
		bRetv = FALSE;
	}


	//ReleaseKernelData();

	LeaveCriticalSection( &lpKernelData->csMsg );
	return bRetv;

	

    //if( *lpMask & *lpIntr )
	//{
		//UnlockIRQRestore( &uiSave );
	    //SetEvent(hHardwareEvent);
	//}
	//else
      //  UnlockIRQRestore( &uiSave );


	//Sleep(1);
}
/*
static void IRQ_Handler( void )
{	
	extern void INTR_Interrupt(void);
	int * lpIntr = (int *)&intrBits;
	int * lpMask = (int *)&intrMask;

	if( *lpMask & *lpIntr )
	{
        INTR_Interrupt();
	}
}
*/

// the  CPU_IRQTrap is called by cpu_eml_thread
//static CONTEXT * lpJumpContext = NULL;
void CPU_IRQTrap( void )
{
	//CONTEXT context;
	TSS tss;
	//extern LPVOID lpCurThread;
	//extern LPVOID DoTlsGetValue( LPVOID lpThread, DWORD dwTlsIndex );
	//extern LPVOID DoTlsSetValue( LPVOID lpThread, DWORD dwTlsIndex );
	
	//context = *((CONTEXT*)lpKernelData->bCPUConext);
	//GetKernelData();
	tss.eax = ((CONTEXT*)lpKernelData->bCPUConext)->Eax;
	tss.ebx = ((CONTEXT*)lpKernelData->bCPUConext)->Ebx;
	tss.ecx = ((CONTEXT*)lpKernelData->bCPUConext)->Ecx;
	tss.edx = ((CONTEXT*)lpKernelData->bCPUConext)->Edx;
	tss.edi = ((CONTEXT*)lpKernelData->bCPUConext)->Edi;
	tss.esi = ((CONTEXT*)lpKernelData->bCPUConext)->Esi;
	
	tss.ebp = ((CONTEXT*)lpKernelData->bCPUConext)->Ebp;
	tss.eip = ((CONTEXT*)lpKernelData->bCPUConext)->Eip;
	tss.esp = ((CONTEXT*)lpKernelData->bCPUConext)->Esp;

	tss.ss = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegSs;
	tss.cs = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegCs;

    tss.gs = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegGs;
    tss.fs = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegFs;
    tss.es = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegEs;
    tss.ds = (WORD)((CONTEXT*)lpKernelData->bCPUConext)->SegDs;


	tss.eflags = ((CONTEXT*)lpKernelData->bCPUConext)->EFlags;

	_ASSERT( tss.eip != (long)CPU_IRQTrap );

	{
		int * lpIntr = (int *)&lpKernelData->intrBits;
		int * lpMask = (int *)&lpKernelData->intrMask;
		
		_ASSERT( *lpIntr && *lpMask );

	}
	_ASSERT( lpKernelData->IntrEnable == 0 );
	//ReleaseKernelData();

    INTR_Interrupt();

	// here to restart the thread
	//
	//lpKernelData->IntrEnable = 0;
	INTR_OFF();
	//lpJumpContext = &context;
	//SetEvent( lpKernelData->hJumpEvent );
	//Sleep( INFINITE );

	JmpBack( &tss, &lpKernelData->IntrEnable );

	_ASSERT(0);
	while(1);

}


#define MEM_SIZE (1024*1024*16)
extern LPBYTE  lpbSysMainMem;// = _mem;
extern ULONG    ulSysMainMemLength;// = MEM_SIZE;
int  __ebp;
extern int fEnter;
BOOL bExitEsoft = 0;
extern HWND hwndDeskTop;


BOOL IsESOFTExit( void )
{
	return bExitEsoft;
}

extern void WINAPI KL_DebugOutString( LPTSTR );
static DWORD WINAPI CPU_StartUpThread( LPVOID lParam )
{
	int win32Stack[MEM_SIZE/sizeof(int)];	
	
	lpbSysMainMem = (LPBYTE)win32Stack;
	ulSysMainMemLength = MEM_SIZE;

	_asm{
		mov  __ebp, ebp
	}

	lpKernelData->intrMask.timer0 = 1;
//	intrMask.timer1 = 1;

	KL_DebugOutString( "begin Kingmos.......\r\n" );

    KingmosStart( lParam );

	return 0;
}


int CPU_PowerOff( DWORD dwReserve )
{
//	MSG msg;
	
	lpKernelData->intrMask.timer0 = 0;
	lpKernelData->intrMask.mouse = 0;
	lpKernelData->intrMask.keyboard = 1;
	lpKernelData->intrBits.timer0 = 0; 
	lpKernelData->intrBits.mouse = 0;
	lpKernelData->intrBits.keyboard = 0;

	//lpKernelData->intrBits.
	bPowerOff = TRUE;	
	bPowerKeyDown = TRUE;
	SuspendThread( lpKernelData->hKingmosThread );  //wait to be wakeup
	bPowerOff = FALSE;
	lpKernelData->intrMask.timer0 = 1;
	lpKernelData->intrMask.mouse = 1;
	return 0;
}

void CPU_Reset( void )
{
    PostMessage( hwndDeskTop, WM_CLOSE, 0, 0 );	
    bExitEsoft = 1;
	SetEvent( lpKernelData->hHardwareEvent );
}

WINBASEAPI
BOOL
WINAPI
IsDebuggerPresent(
    VOID
    );

DWORD WINAPI CPU_InterruptControlerThread( LPVOID lParam )
{
	int * lpIntr = (int *)&lpKernelData->intrBits;
	int * lpMask = (int *)&lpKernelData->intrMask;
	int intrCount = 0;
	//HANDLE hEvent;//s[2] ;

	//if( IsDebuggerPresent() )
	//{			
	//}
	//hEvents[0] = lpKernelData->hHardwareEvent;
	//hEvents[1] = lpKernelData->hJumpEvent;
	while( bExitEsoft == 0 )
	{
		int retv;
		UINT uiSuspendCount;
		retv = WaitForSingleObject( lpKernelData->hHardwareEvent, INFINITE );

		//retv = WaitForMultipleObjects( 2, hEvents, FALSE, INFINITE );
		/*
		if( retv == WAIT_OBJECT_0 + 1 )
		{
			BOOL bRetv;
			while( (uiSuspendCount = SuspendThread( lpKernelData->hKingmosThread )) == 0xFFFFFFFF )
				Sleep(1);
			_ASSERT( lpJumpContext );
			bRetv = SetThreadContext( lpKernelData->hKingmosThread, lpJumpContext );
			lpJumpContext = NULL;
			_ASSERT( bRetv );
			lpKernelData->IntrEnable = TRUE;
			ResumeThread( lpKernelData->hKingmosThread );
			continue;
		}
		*/

		if( bExitEsoft )
			break;

		if( lpKernelData->IntrEnable == FALSE )
		{			
			intrCount++;
			if( intrCount > 1000 )
			{
				KL_DebugOutString( "intrCount==1000.\r\n" );
				intrCount = 0;
			}
		}

#ifdef KINGMOS_DEMO
	    if( IsDebuggerPresent() )
		    break;
#endif
	    //while( IsDebuggerPresent() )
		//{
			//OutputDebugString( "debuger...\r\n" );
		    //Sleep(1000);
		//}
		//while( SuspendThread( lpKernelData->hRTCControllerThread ) == 0xFFFFFFFF )
			//Sleep(1);

		while( (uiSuspendCount = SuspendThread( lpKernelData->hKingmosThread )) == 0xFFFFFFFF )
			Sleep(1);

		//while( *lpMask & *lpIntr )
		_ASSERT( bPowerOff || uiSuspendCount == 0 );
		//if( retv == WAIT_TIMEOUT )
		//{
		    //lpKernelData->intrBits.timer0 = 1;
            //lpKernelData->IntrMsg[ID_INTR_TIMER0].message = WM_TIMER;// = *lpmsg;
		//}
//		else
		//{
			//CPU_CheckIRQEvent();
		//}

		if( (*lpMask & *lpIntr) && lpKernelData->IntrEnable )
		{
			BOOL bRetv;
			if( bPowerOff )
			{	// 触发了一个唤醒中断事件
				ResumeThread( lpKernelData->hKingmosThread );
				bPowerOff = FALSE;
			}

			// ok, the thread suspended
			((CONTEXT*)lpKernelData->bCPUConext)->ContextFlags = CONTEXT_FULL;
			bRetv = GetThreadContext( lpKernelData->hKingmosThread, (CONTEXT*)&lpKernelData->bCPUConext );
			_ASSERT( bRetv );
			_ASSERT( ((CONTEXT*)lpKernelData->bCPUConext)->Eip != (UINT)CPU_IRQTrap );
			if( !( ((CONTEXT*)lpKernelData->bCPUConext)->Eip >= (DWORD)lpKernelData->uiLockSegStart &&
				((CONTEXT*)lpKernelData->bCPUConext)->Eip < (DWORD)lpKernelData->uiLockSegEnd ) )
			{
				CONTEXT newct = *( (CONTEXT*)&lpKernelData->bCPUConext );//&lpKernelData->ctSave;
				
				lpKernelData->IntrEnable = FALSE;
				newct.Eip = (UINT)CPU_IRQTrap;
				bRetv = SetThreadContext( lpKernelData->hKingmosThread, &newct );
				_ASSERT( bRetv );
			}
		}
		ResumeThread( lpKernelData->hKingmosThread );
		//ResumeThread( lpKernelData->hRTCControllerThread );
		//Sleep(1);
	}
	return 0;
}

VOID CPU_SetRTCTime( DWORD dwSeconds )
{
	lpKernelData->lRTCCount = (int)(dwSeconds * 1000); //to 毫秒
}

int CALLBACK CPU_RTCControllerThread( LPVOID lpv )
{
	MSG msgTimer0;
	MSG msgRTC;
	lpKernelData->lRTCCount = MAXLONG; //max value
	msgRTC.message = WM_RTCMSG;
	msgTimer0.message = WM_TIMERMSG;
	while( 1 )
	{
		Sleep(RESCHED_PERIOD);
		lpKernelData->lRTCCount -= RESCHED_PERIOD;
		if( lpKernelData->lRTCCount <= 0 )
		{
			CPU_SetIRQEvent( &msgRTC );
			lpKernelData->lRTCCount = MAXLONG;
		}
		else
		{
			CPU_SetIRQEvent( &msgTimer0 );
		}		
	}
}

void CPU_Init( void )
{
	DWORD dwId;
	DWORD dwStartAdr = 0x70000000;

	while( lpKernelData == NULL )
	{
	    lpKernelData = (LPKERNEL_DATA)VirtualAlloc( (LPVOID)dwStartAdr, 1024 * 4, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE | PAGE_NOCACHE );
		dwStartAdr -= 0x10000000;
	}
	if( lpKernelData )
	    memset( lpKernelData, 0, 1024 * 4 );
	else
		return;

    InitializeCriticalSection( &lpKernelData->csMsg );

    lpKernelData->uiLockSegStart = LockSeg_Start();
    lpKernelData->uiLockSegEnd = LockSeg_End();

    lpKernelData->hHardwareEvent = CreateEvent(0,FALSE,FALSE,0);
	lpKernelData->hJumpEvent = CreateEvent(0,FALSE,FALSE,0);
	// create main thread
	lpKernelData->hKingmosThread = CreateThread( 0, MEM_SIZE + 1024 * 10, CPU_StartUpThread, 0, 0, &dwId );
	lpKernelData->hIntrThread = CreateThread( 0, 0, CPU_InterruptControlerThread, 0, 0, &dwId );
//	SetThreadPriority(lpKernelData->hIntrThread, THREAD_PRIORITY_TIME_CRITICAL);
	lpKernelData->hRTCControllerThread = CreateThread( 0, 0, CPU_RTCControllerThread, 0, 0, &dwId );
	
}

void CPU_Deinit( void )
{
	//CloseHandle( hResetEsoftEvent );
	TerminateThread( lpKernelData->hRTCControllerThread, 0 );
	CloseHandle( lpKernelData->hKingmosThread );
	CloseHandle( lpKernelData->hIntrThread );
	CloseHandle( lpKernelData->hHardwareEvent );
	
	VirtualFree( lpKernelData, 0, MEM_RELEASE );
	lpKernelData = NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -