emulator/emulatorbsp/specific/variant.cpp
changeset 0 cec860690d41
equal deleted inserted replaced
-1:000000000000 0:cec860690d41
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // wins\specific\variant.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "variant.h"
       
    19 #include "mconf.h"
       
    20 #include <kernel/kern_priv.h>
       
    21 #include <stdlib.h>
       
    22 #include <property.h>
       
    23 #include <emulator.h>
       
    24 
       
    25 const TInt KDefaultRam = 63;				// 63MB default internal RAM
       
    26 const TInt KUnlimitedRam = 0x400;			// 1GB ~= unlimited memory
       
    27 const TInt KDefaultRamDrive = 0x400000;		// 4MB default RAM drive limit
       
    28 
       
    29 _LIT(KLitWins,"Wins");
       
    30 
       
    31 GLDEF_D Wins TheVariant;
       
    32 
       
    33 GLDEF_D TActualMachineConfig TheConfig;
       
    34 
       
    35 EXPORT_C Asic* VariantInitialise(TBool aRunExe)
       
    36 	{
       
    37 	return TheVariant.Init(aRunExe) == KErrNone ? &TheVariant : NULL;
       
    38 	}
       
    39 
       
    40 void AsicInitialise()
       
    41 	{
       
    42 	}
       
    43 
       
    44 class DWinsPowerController : public DPowerController
       
    45 	{
       
    46 public: // from DPowerComtroller
       
    47 	void CpuIdle();
       
    48 	void EnableWakeupEvents();
       
    49 	void AbsoluteTimerExpired();
       
    50 	void DisableWakeupEvents();
       
    51 	void PowerDown(TTimeK aWakeupTime);
       
    52 public:
       
    53 	static DWinsPowerController* New();
       
    54 	void AssertWakeupSignal();
       
    55 	void WakeupEvent();
       
    56 private:
       
    57 	HANDLE	iStandbySem;
       
    58 	TUint	iStandby;
       
    59 	TBool	iWakeupSignal;
       
    60 	};
       
    61 
       
    62 Wins::Wins()
       
    63 	:iUi(0), iRealCpuSpeed(0), iCpuSpeed(0),
       
    64 	iDebugOutput(INVALID_HANDLE_VALUE), iLogTimeStamp(ETrue),
       
    65 	iPurgedImages(EFalse), iPowerController(0), iLogToDebugger(EFalse),
       
    66 	iLogToFile(ETrue)
       
    67 	{}
       
    68 
       
    69 TInt Wins::Init(TBool aRunExe)
       
    70 	{
       
    71 	TInt r = InitProperties(aRunExe);
       
    72 	if (r == KErrNone)
       
    73 		{
       
    74 		iProperties.GetInt("LogTimeStamp",iLogTimeStamp);
       
    75 		TInt logThreadId=ETrue;
       
    76 		iProperties.GetInt("LogThreadId",logThreadId);
       
    77 		TInt cpu=NThread::ECpuSingle;
       
    78 		iProperties.GetInt("HostCPU",cpu);
       
    79 		NThread::SetProperties(logThreadId,cpu);
       
    80 		iProperties.GetInt("LogToDebugger",iLogToDebugger);
       
    81 		iProperties.GetInt("LogToFile",iLogToFile);
       
    82 
       
    83 		TInt mask;
       
    84 		Kern::SuperPage().iDebugMask[0] = DebugMask();  // get int or text mask value
       
    85 		// check to see if DebugMask0 was used instead of DebugMask
       
    86 		if ( (iProperties.GetInt("DebugMask", mask) != KErrNone) &&
       
    87 			 (iProperties.GetInt("DebugMask0", mask) == KErrNone) )
       
    88 			Kern::SuperPage().iDebugMask[0] = ((iProperties.GetInt("DebugMask0", mask) == KErrNone) ? mask : 0);
       
    89 			
       
    90 		// only int entries are supported for DebugMasks 1-7
       
    91 		Kern::SuperPage().iDebugMask[1] = ((iProperties.GetInt("DebugMask1", mask) == KErrNone) ? mask : 0);
       
    92 		Kern::SuperPage().iDebugMask[2] = ((iProperties.GetInt("DebugMask2", mask) == KErrNone) ? mask : 0);
       
    93 		Kern::SuperPage().iDebugMask[3] = ((iProperties.GetInt("DebugMask3", mask) == KErrNone) ? mask : 0);
       
    94 		Kern::SuperPage().iDebugMask[4] = ((iProperties.GetInt("DebugMask4", mask) == KErrNone) ? mask : 0);
       
    95 		Kern::SuperPage().iDebugMask[5] = ((iProperties.GetInt("DebugMask5", mask) == KErrNone) ? mask : 0);
       
    96 		Kern::SuperPage().iDebugMask[6] = ((iProperties.GetInt("DebugMask6", mask) == KErrNone) ? mask : 0);
       
    97 		Kern::SuperPage().iDebugMask[7] = ((iProperties.GetInt("DebugMask7", mask) == KErrNone) ? mask : 0);
       
    98 
       
    99 		// initial values for fast trace...
       
   100 		Kern::SuperPage().iInitialBTraceFilter[0] = ((iProperties.GetInt("BTrace0", mask) == KErrNone) ? mask : 0);
       
   101 		Kern::SuperPage().iInitialBTraceFilter[1] = ((iProperties.GetInt("BTrace1", mask) == KErrNone) ? mask : 0);
       
   102 		Kern::SuperPage().iInitialBTraceFilter[2] = ((iProperties.GetInt("BTrace2", mask) == KErrNone) ? mask : 0);
       
   103 		Kern::SuperPage().iInitialBTraceFilter[3] = ((iProperties.GetInt("BTrace3", mask) == KErrNone) ? mask : 0);
       
   104 		Kern::SuperPage().iInitialBTraceFilter[4] = ((iProperties.GetInt("BTrace4", mask) == KErrNone) ? mask : 0);
       
   105 		Kern::SuperPage().iInitialBTraceFilter[5] = ((iProperties.GetInt("BTrace5", mask) == KErrNone) ? mask : 0);
       
   106 		Kern::SuperPage().iInitialBTraceFilter[6] = ((iProperties.GetInt("BTrace6", mask) == KErrNone) ? mask : 0);
       
   107 		Kern::SuperPage().iInitialBTraceFilter[7] = ((iProperties.GetInt("BTrace7", mask) == KErrNone) ? mask : 0);
       
   108 		Kern::SuperPage().iInitialBTraceBuffer = ((iProperties.GetInt("BTraceBuffer", mask) == KErrNone) ? mask : 0);
       
   109 		Kern::SuperPage().iInitialBTraceMode = ((iProperties.GetInt("BTraceMode", mask) == KErrNone) ? mask : 0);
       
   110 
       
   111 		Kern::SuperPage().SetKernelConfigFlags(KernelConfigFlags());
       
   112 
       
   113 		SCapabilitySet caps;
       
   114 		DisabledCapabilities(caps);
       
   115 		memcpy(&Kern::SuperPage().iDisabledCapabilities,&caps,sizeof(caps));
       
   116 		}
       
   117 	CalibrateCpuSpeed();
       
   118 	return r;
       
   119 	}
       
   120 
       
   121 inline void Wins::InstallUi(DWinsUiBase& aUi)
       
   122 	{iUi = &aUi;}
       
   123 
       
   124 void Wins::Init1()
       
   125 	{
       
   126 	__KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init1()"));
       
   127 
       
   128 	TInt tickperiod = WinsTimer::EDefaultPeriod;
       
   129 	iProperties.GetInt("TimerResolution",tickperiod);
       
   130 	iTimer.Init(tickperiod);
       
   131 	TUint speed;
       
   132 	if (iProperties.GetInt("CPUSpeed", (TInt&)speed) == KErrNone)
       
   133 		SetCpuSpeed(speed);
       
   134 	}
       
   135 
       
   136 static TInt emulatorHal(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
       
   137 	{
       
   138 	return ((Wins*)aPtr)->EmulatorHal(aFunction, a1, a2);
       
   139 	}
       
   140 
       
   141 void Wins::Init3()
       
   142 //
       
   143 // Initialise timer tick and add emulator hal function
       
   144 //
       
   145 	{
       
   146 	__KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init3()"));
       
   147 
       
   148 	Kern::AddHalEntry(EHalGroupEmulator,&emulatorHal,this);
       
   149 
       
   150 	iPowerController = DWinsPowerController::New();
       
   151 	if (iPowerController == 0)
       
   152 		__PM_PANIC("Can't create 'DWinsPowerController'");
       
   153 
       
   154 	iTimer.Enable();
       
   155 	}
       
   156 
       
   157 void Wins::AddressInfo(SAddressInfo& aInfo)
       
   158 	{
       
   159 	TInt megabytes = KDefaultRam;
       
   160 	iProperties.GetInt("MegabytesOfFreeMemory", megabytes);
       
   161 	if (megabytes == 0)
       
   162 		megabytes = KUnlimitedRam;
       
   163 	aInfo.iTotalRamSize = megabytes << 20;
       
   164 //
       
   165 	TInt ramdisk = KDefaultRamDrive;
       
   166 	iProperties.GetInt("RamDriveMaxSize", ramdisk);
       
   167 	aInfo.iRamDriveMaxSize = ramdisk;
       
   168 	}
       
   169 
       
   170 void Wins::PurgeImages()
       
   171 //
       
   172 // Use the idle thread to clean up remnants of the emulator from the image path
       
   173 //
       
   174 	{
       
   175 	char path[KMaxFileName+1];
       
   176 
       
   177 	const char* imgPath=0;
       
   178 	iProperties.GetString("EmulatorImagePath", imgPath);
       
   179 	strcpy(path, imgPath);
       
   180 	char* name = path +strlen(path);
       
   181 	strcpy(name,"*");
       
   182 
       
   183 	Emulator::Lock();
       
   184 
       
   185 	WIN32_FIND_DATAA fdata;
       
   186 	HANDLE finder = FindFirstFileA(path, &fdata);
       
   187 	if (finder != INVALID_HANDLE_VALUE)
       
   188 		{
       
   189 		do
       
   190 			{
       
   191 			if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
       
   192 				{
       
   193 				strcpy(name, fdata.cFileName);
       
   194 				DeleteFileA(path);
       
   195 				}
       
   196 			} while (FindNextFileA(finder, &fdata));
       
   197 		FindClose(finder);
       
   198 		}
       
   199 
       
   200 	Emulator::Unlock();
       
   201 	}
       
   202 
       
   203 void Wins::Idle()
       
   204 //
       
   205 // Use the win32 NKern idle function
       
   206 //
       
   207 	{
       
   208 	iTimer.SetIdleThread();
       
   209 	if (!iPurgedImages)
       
   210 		{
       
   211 		PurgeImages();
       
   212 		iPurgedImages = ETrue;
       
   213 		}
       
   214 	NThread::Idle();
       
   215 	}
       
   216 
       
   217 TInt Wins::MsTickPeriod()
       
   218 //
       
   219 // Provide the 'millisecond' timer tick period in microseconds
       
   220 //
       
   221 	{
       
   222 	return 1000 * iTimer.Period();
       
   223 	}
       
   224 
       
   225 TInt Wins::SystemTimeInSecondsFrom2000(TInt& aTime)
       
   226 	{
       
   227 	aTime = iTimer.SystemTime();
       
   228 	__KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
       
   229 	return KErrNone;
       
   230 	}
       
   231 
       
   232 TInt Wins::SetSystemTimeInSecondsFrom2000(TInt aTime)
       
   233 // 
       
   234 // Set the emulator time. We must not change the Win32 time so
       
   235 // we just adjust the offset value to account for the difference
       
   236 //
       
   237 	{
       
   238 	__KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
       
   239 	iTimer.SetSystemTime(aTime);
       
   240 	return KErrNone;
       
   241 	}
       
   242 
       
   243 TInt Wins::VariantHal(TInt aFunction, TAny* a1, TAny* /*a2*/)
       
   244 	{
       
   245 	TInt r=KErrNone;
       
   246 	switch(aFunction)
       
   247 		{
       
   248 		case EVariantHalVariantInfo:
       
   249 			{
       
   250 			TVariantInfoV01Buf infoBuf;
       
   251 			TVariantInfoV01& info=infoBuf();
       
   252 
       
   253 //			info.iRomVersion=TVersion(KRomMajorVersionNumber,KRomMinorVersionNumber,KRomBuildVersionNumber);
       
   254 			info.iMachineUniqueId=0;
       
   255 			info.iLedCapabilities=0x0;
       
   256 			info.iProcessorClockInKHz=iCpuSpeed ? iCpuSpeed*1000 : 1;
       
   257 			info.iSpeedFactor=0;
       
   258 			if (iUi)
       
   259 				iUi->Info(info);
       
   260 
       
   261 			Kern::InfoCopy(*(TDes8*)a1,infoBuf);
       
   262 			break;
       
   263 			}
       
   264 
       
   265 		case EVariantHalCustomRestartReason:
       
   266 			{
       
   267 			//This will take value from c:\data\epoc.ini.
       
   268 			TInt x = Property::GetInt("CustomRestartReason");    
       
   269 			kumemput32(a1, &x, sizeof(TInt));
       
   270 			}
       
   271 			break;
       
   272 
       
   273 		case EVariantHalCustomRestart:
       
   274 			{
       
   275 			if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EVariantHalCustomRestart")))
       
   276 				return KErrPermissionDenied;
       
   277 			//This will only shut down epoc as Custom Restart Reason is not supported on wins.
       
   278 			Kern::Restart((TInt)a1);
       
   279 			break;
       
   280 			}
       
   281 
       
   282 		default:
       
   283 			r=KErrNotSupported;
       
   284 			break;
       
   285 		}
       
   286 	return r;
       
   287 	}
       
   288 
       
   289 TPtr8 Wins::MachineConfiguration()
       
   290 	{
       
   291 	return TPckg<TActualMachineConfig>(TheConfig);
       
   292 	}
       
   293 
       
   294 void Wins::CalibrateCpuSpeed()
       
   295 //
       
   296 // calculate approx. CPU speed in MHz, 0 if we can't tell
       
   297 //
       
   298 	{
       
   299     TInt cycleCount =200*1000*20;   //take 20ms at 20MHz
       
   300     
       
   301     // This loop will double the cyclecount until the difference is non-zero.
       
   302     FOREVER
       
   303     	{
       
   304       	if (cycleCount > (KMaxTUint / 2))
       
   305     		{
       
   306     		break;
       
   307     		}
       
   308     
       
   309 		SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
       
   310 		LARGE_INTEGER start;
       
   311 		if (QueryPerformanceCounter(&start))
       
   312     		{
       
   313 	   		__asm mov eax, cycleCount
       
   314  	noploop: 
       
   315  			__asm dec eax
       
   316 			__asm dec eax
       
   317 			__asm dec eax
       
   318 			__asm dec eax
       
   319 			__asm dec eax
       
   320 			__asm dec eax
       
   321 			__asm dec eax
       
   322 			__asm dec eax
       
   323 			__asm dec eax
       
   324 			__asm dec eax
       
   325 			__asm dec eax
       
   326 			__asm dec eax
       
   327 			__asm dec eax
       
   328 			__asm dec eax
       
   329 			__asm dec eax
       
   330 			__asm dec eax
       
   331 			__asm dec eax
       
   332 			__asm dec eax
       
   333 			__asm dec eax
       
   334 			__asm dec eax
       
   335 			__asm dec eax
       
   336 			__asm dec eax
       
   337 			__asm dec eax
       
   338 			__asm dec eax
       
   339 			__asm dec eax
       
   340 			__asm dec eax
       
   341 			__asm dec eax
       
   342 			__asm dec eax
       
   343 			__asm dec eax
       
   344 			__asm dec eax
       
   345 			__asm dec eax
       
   346 			__asm dec eax
       
   347 			__asm dec eax
       
   348 			__asm dec eax
       
   349 			__asm dec eax
       
   350 			__asm dec eax
       
   351 			__asm dec eax
       
   352 			__asm dec eax
       
   353 			__asm dec eax
       
   354 			__asm dec eax
       
   355 			__asm dec eax
       
   356 			__asm dec eax
       
   357 			__asm dec eax
       
   358 			__asm dec eax
       
   359 			__asm dec eax
       
   360 			__asm dec eax
       
   361 			__asm dec eax
       
   362 			__asm dec eax
       
   363 			__asm sub eax, 2
       
   364 			__asm jnz noploop
       
   365 			//
       
   366 			LARGE_INTEGER end;
       
   367 			QueryPerformanceCounter(&end);
       
   368 			LARGE_INTEGER f;
       
   369 			QueryPerformanceFrequency(&f);
       
   370 			
       
   371 			TInt64 diff = (end.QuadPart - start.QuadPart);
       
   372 	    	if(diff!=0)
       
   373 	    		{
       
   374 				TInt64 hz = (TInt64(cycleCount) / 1000000) * (f.QuadPart / diff);
       
   375 				iRealCpuSpeed = (TUint)(hz);
       
   376 				break;
       
   377 		     	}
       
   378   	  	    }
       
   379     	cycleCount *= 2;  // Double the count!!
       
   380  		}
       
   381     
       
   382    	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
       
   383 	}
       
   384 
       
   385 TInt Wins::SetCpuSpeed(TUint aSpeed)
       
   386 	{
       
   387 	if (iRealCpuSpeed == 0)
       
   388 		return KErrNotSupported;	// don't know the real CPUSpeed
       
   389 
       
   390 	if (IsDebuggerPresent())
       
   391 		return KErrGeneral;			// nobbling not avaliable when debugging
       
   392 
       
   393 	if (aSpeed == 0)
       
   394 		aSpeed = iRealCpuSpeed;		// reset to maximum
       
   395 	else if (aSpeed > iRealCpuSpeed)
       
   396 		aSpeed = iRealCpuSpeed;
       
   397 	else if (aSpeed * 20u  < iRealCpuSpeed)
       
   398 		aSpeed = (iRealCpuSpeed + 19u) / 20u;
       
   399 
       
   400 	__KTRACE_OPT(KHARDWARE,Kern::Printf("Set CPUSpeed: %d",aSpeed));
       
   401 	iCpuSpeed = aSpeed;
       
   402 
       
   403 	// calculate CPU time to nobble in parts-per-million
       
   404 	TUint nobble = ((iRealCpuSpeed - aSpeed) * 1000000u) / iRealCpuSpeed;
       
   405 	iTimer.Nobble(nobble);
       
   406 	return KErrNone;
       
   407 	}
       
   408 
       
   409 HANDLE Wins::DebugOutput()
       
   410 //
       
   411 // Return a handle to the trace file, creating the file if required.
       
   412 //
       
   413 // The log file name can be specified by a property or environment
       
   414 // variable called 'EmulatorLog', otherwise it defaults to 
       
   415 // 'epocwind.out' in the temporary directory.
       
   416 //
       
   417 	{
       
   418 	HANDLE file = iDebugOutput;
       
   419 	if (file == INVALID_HANDLE_VALUE)
       
   420 		{
       
   421 		CHAR debugfile[MAX_PATH];
       
   422 		const char* logpath;
       
   423 		if (iProperties.GetString("EmulatorLog",logpath)==KErrNone)
       
   424 			strcpy(debugfile,logpath);
       
   425 		else
       
   426 			{
       
   427 			DWORD len = GetEnvironmentVariableA("EmulatorLog", debugfile, MAX_PATH);
       
   428 			debugfile[len]=0;
       
   429 			if (len == 0)
       
   430 				{
       
   431 				len=GetTempPathA(MAX_PATH,debugfile);
       
   432 				strcpy(debugfile+len,"epocwind.out");	// EPOC WINS DEBUG output file
       
   433 				}
       
   434 			}
       
   435 		file=CreateFileA(debugfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
       
   436 		if (file!=INVALID_HANDLE_VALUE)
       
   437 			{
       
   438 			SetFilePointer(file, NULL, NULL, FILE_END);
       
   439 			iDebugOutput = file;
       
   440 			}
       
   441 		}
       
   442 	return file;
       
   443 	}
       
   444 
       
   445 const TInt MaxOutputMsg = 599;
       
   446 
       
   447 void Wins::EarlyLogging(const char* aMessage1,const char* aMessage2)
       
   448 	{
       
   449 	char message[MaxOutputMsg+3];
       
   450 	TInt len = min(strlen(aMessage1), MaxOutputMsg);
       
   451 	memcpy(message,aMessage1,len);
       
   452 	if(aMessage2)
       
   453 		{
       
   454 		TInt len2 = min((TInt)strlen(aMessage2), MaxOutputMsg-len);
       
   455 		memcpy(message+len,aMessage2,len2);
       
   456 		len+=len2;
       
   457 		}
       
   458 	message[len++] = '\r';
       
   459 	message[len++] = '\n';
       
   460 	message[len] = 0;
       
   461 
       
   462 	if (iLogToFile)
       
   463 		{
       
   464 		DWORD bytes;
       
   465 		WriteFile(DebugOutput(), message, len, &bytes, NULL);
       
   466 		}
       
   467 	if (iLogToDebugger)
       
   468 		{
       
   469 		OutputDebugStringA(message);
       
   470 		}
       
   471 	}
       
   472 
       
   473 void Wins::DebugPrint(const TDesC8& aDes)
       
   474 //
       
   475 // Send the string to the debug output (Win32 debug trace) and trace file
       
   476 //
       
   477 	{
       
   478 	char message[MaxOutputMsg+1];
       
   479 	TInt len = aDes.Length();
       
   480 	const char* ptr = (const char*)aDes.Ptr();
       
   481 	if (iLogTimeStamp)
       
   482 		{
       
   483 		strcpy(message,"          ");
       
   484 		_ultoa(NKern::TickCount() * iTimer.Period(), message + 10, 10);
       
   485 		int n = strlen(message);
       
   486 		len = min(len, MaxOutputMsg - n - 2);
       
   487 		char* msg = message + n;
       
   488 		msg[0] = msg[-1];
       
   489 		msg[-1] = n < 10+2 ? '0' : msg[-2];
       
   490 		msg[-2] = n < 10+3 ? '0' : msg[-3];
       
   491 		msg[-3] = '.';
       
   492 		if (n < 10+4)
       
   493 			msg[-4] = '0';
       
   494 		++msg;
       
   495 		*msg++ = '\t';
       
   496 		strncpy(msg, ptr, len);
       
   497 		msg[len] = 0;
       
   498 		ptr = msg - 11;
       
   499 		len += 11;
       
   500 		}
       
   501 	else
       
   502 		{
       
   503 		len = min(len, MaxOutputMsg);
       
   504 		strncpy(message, ptr, len);
       
   505 		message[len] = 0;
       
   506 		ptr = message;
       
   507 		}
       
   508 	TInt irq = NKern::DisableAllInterrupts();
       
   509 	if (iLogToFile)
       
   510 		{
       
   511 		DWORD bytes;
       
   512 		WriteFile(DebugOutput(), ptr, len, &bytes, NULL);
       
   513 		}
       
   514 	if (iLogToDebugger)
       
   515 		{
       
   516 		OutputDebugStringA(message);
       
   517 		}
       
   518 
       
   519 	NKern::RestoreInterrupts(irq);
       
   520 	}
       
   521 
       
   522 const char* const KErrorTitles[] =
       
   523 	{
       
   524 	"Symbian OS Fatal Error",
       
   525 	"Symbian OS Application Error"
       
   526 	};
       
   527 
       
   528 const TText8* const KErrorMsg[] =
       
   529 	{
       
   530 	_S8("An error has been detected in the Symbian OS emulator."),
       
   531 	_S8("A call to User::Panic() has occured, indicating\n"
       
   532 		"a programming fault in the running application.\n"
       
   533 		"Please refer to the documentation for more details.")
       
   534 	};
       
   535 
       
   536 _LIT8(KProgram, "\n\nProgram\t");
       
   537 _LIT8(KError, "\nError\t");
       
   538 _LIT8(KIDFC, "an IDFC");
       
   539 _LIT8(KEscaped, "an escaped thread");
       
   540 _LIT8(KInterrupt, "an interrupt thread");
       
   541 _LIT8(KNThread, "an NThread");
       
   542 _LIT8(KColon, " : ");
       
   543 _LIT8(KDebugQuery, "\n\nDo you wish to Debug the error?\0");
       
   544 
       
   545 TBool Wins::ErrorDialog(TError aType, const TDesC8& aPanic, TInt aVal)
       
   546 	{
       
   547 	// Must be called with interrupts enabled to allow thread running windows message loop to run
       
   548 	
       
   549 	TBuf8<512> message(KErrorMsg[aType]);
       
   550 	message.Append(KProgram);
       
   551 	TInt context = NKern::CurrentContext();
       
   552 	switch(context)
       
   553 		{
       
   554 		case NKern::EIDFC:
       
   555 			message.Append(KIDFC);
       
   556 			break;
       
   557 		case NKern::EEscaped:
       
   558 			message.Append(KEscaped);
       
   559 			break;
       
   560 		case NKern::EInterrupt:
       
   561 			message.Append(KInterrupt);
       
   562 			break;
       
   563 		case NKern::EThread:
       
   564 			DThread *thread = Kern::NThreadToDThread(NKern::CurrentThread());
       
   565 			if (thread)
       
   566 				thread->TraceAppendFullName(message, ETrue);
       
   567 			else
       
   568 				message.Append(KNThread);
       
   569 			break;
       
   570 		}
       
   571 	message.Append(KError);
       
   572 	message.Append(aPanic);
       
   573 	message.Append(KColon);
       
   574 	message.AppendNum(aVal);
       
   575 #ifdef _DEBUG
       
   576 	message.Append(KDebugQuery);
       
   577 	UINT type = MB_YESNO | MB_DEFBUTTON2;
       
   578 #else
       
   579 	UINT type = MB_OK;
       
   580 #endif
       
   581 	type |= MB_SETFOREGROUND  | MB_ICONERROR;
       
   582 	message.Append('\0');
       
   583 
       
   584 	TInt r = MessageBoxA(iUi ? iUi->HWnd() : NULL, (LPCSTR)message.Ptr(), KErrorTitles[aType], type);
       
   585 	return r == IDYES;
       
   586 	}
       
   587 
       
   588 // UI installation
       
   589 
       
   590 EXPORT_C DWinsUiBase::DWinsUiBase()
       
   591 	{
       
   592 	TheVariant.InstallUi(*this);
       
   593 	}
       
   594 
       
   595 
       
   596 TInt BinaryPowerInit();
       
   597 
       
   598 DWinsPowerController* DWinsPowerController::New()
       
   599 	{
       
   600 	DWinsPowerController* self = new DWinsPowerController();
       
   601 	if (!self)
       
   602 		return NULL;
       
   603 	self->iStandbySem = CreateSemaphore(NULL, 0, 1, NULL);
       
   604 	if (self->iStandbySem == NULL)
       
   605 		return NULL;
       
   606 	TInt r = BinaryPowerInit();
       
   607 	if (r != KErrNone)
       
   608 		return NULL;
       
   609 	self->Register();
       
   610 	return self; 
       
   611 	}
       
   612 
       
   613 void DWinsPowerController::CpuIdle()
       
   614 	{
       
   615 	Arch::TheAsic()->Idle();
       
   616 	}
       
   617 		
       
   618 void DWinsPowerController::EnableWakeupEvents()
       
   619 	{
       
   620 	iWakeupSignal = EFalse;
       
   621 	}
       
   622 
       
   623 void DWinsPowerController::DisableWakeupEvents()
       
   624 	{
       
   625 	}
       
   626 
       
   627 void DWinsPowerController::AbsoluteTimerExpired()
       
   628 	{
       
   629 	if (iTargetState == EPwStandby)
       
   630 		DWinsPowerController::WakeupEvent();	
       
   631 	}
       
   632 
       
   633 void DWinsPowerController::WakeupEvent()
       
   634 	{
       
   635 	if (iTargetState == EPwStandby)
       
   636 		{
       
   637 		iWakeupSignal = ETrue;
       
   638 		DPowerController::WakeupEvent();
       
   639 		}
       
   640 	}
       
   641 
       
   642 // called in Epoc thread
       
   643 void DWinsPowerController::PowerDown(TTimeK aWakeupTime)
       
   644 	{
       
   645 	if (iTargetState == EPwStandby)
       
   646 		{
       
   647 		UINT timeoutMs;
       
   648 		if (aWakeupTime == 0)
       
   649 			timeoutMs = INFINITE;
       
   650 		else 
       
   651 			{
       
   652 			TTimeK now = Kern::SystemTime();
       
   653 			if (now > aWakeupTime)
       
   654 				timeoutMs = 0;
       
   655 			else
       
   656 				timeoutMs = (UINT)((aWakeupTime - now) / 1000);
       
   657 			}
       
   658 		TInt l = NKern::DisableAllInterrupts();
       
   659 		if (!iWakeupSignal && timeoutMs)
       
   660 			{
       
   661 			iStandby = ETrue;
       
   662 			TheVariant.iTimer.Standby();
       
   663 			NKern::RestoreInterrupts(l);
       
   664 			DWORD r = WaitForSingleObject(iStandbySem, timeoutMs);
       
   665 			if (r == WAIT_TIMEOUT)
       
   666 				{
       
   667 				l = NKern::DisableAllInterrupts();
       
   668 				if (!iStandby)
       
   669 					WaitForSingleObject(iStandbySem, INFINITE);
       
   670 				else
       
   671 					iStandby = EFalse;
       
   672 				NKern::RestoreInterrupts(l);
       
   673 				}
       
   674 			TheVariant.iTimer.Wakeup();
       
   675 			}
       
   676 		else
       
   677 			NKern::RestoreInterrupts(l);
       
   678 
       
   679 		}
       
   680 	else
       
   681 		Kern::Restart(0x80000000);
       
   682 	}
       
   683 
       
   684 // called in the interrupt context
       
   685 void DWinsPowerController::AssertWakeupSignal()
       
   686 	{
       
   687 	iWakeupSignal = ETrue;
       
   688 	if (iStandby)
       
   689 		{
       
   690 		iStandby = EFalse;
       
   691 		ReleaseSemaphore(iStandbySem, 1, NULL);
       
   692 		}
       
   693 	}
       
   694 
       
   695 
       
   696 EXPORT_C void Wins::AssertWakeupSignal()
       
   697 	{
       
   698 	iPowerController->AssertWakeupSignal();
       
   699 	}
       
   700 
       
   701 EXPORT_C void Wins::WakeupEvent()
       
   702 	{
       
   703 	iPowerController->DWinsPowerController::WakeupEvent();
       
   704 	}
       
   705 
       
   706 // MMC emulation support
       
   707 
       
   708 TBool Wins::MediaDoorOpen;
       
   709 TInt Wins::CurrentPBusDevice;
       
   710 TAny* Wins::MediaChangeCallbackParam;
       
   711 TMediaChangeCallBack Wins::MediaChangeCallBackPtr;
       
   712 
       
   713 
       
   714 EXPORT_C TBool* Wins::MediaDoorOpenPtr()
       
   715 //
       
   716 // For media change simulation
       
   717 //
       
   718 	{
       
   719 
       
   720 	return(&MediaDoorOpen);
       
   721 	}
       
   722 
       
   723 EXPORT_C TInt* Wins::CurrentPBusDevicePtr()
       
   724 //
       
   725 // For media change simulation
       
   726 //
       
   727 	{
       
   728 
       
   729 	return(&CurrentPBusDevice);
       
   730 	}
       
   731 
       
   732 EXPORT_C void Wins::SetMediaChangeCallBackPtr(TMediaChangeCallBack aPtr, TAny* aMediaChangeCallbackParam)
       
   733 //
       
   734 // For media change simulation
       
   735 //
       
   736 	{
       
   737 	MediaChangeCallbackParam=aMediaChangeCallbackParam;
       
   738 	MediaChangeCallBackPtr=aPtr;
       
   739 	}
       
   740 
       
   741 EXPORT_C void Wins::MediaChangeCallBack()
       
   742 //
       
   743 // Perform the simulated media change callback
       
   744 //
       
   745 	{
       
   746 	if(MediaChangeCallBackPtr)
       
   747 		(*MediaChangeCallBackPtr)(MediaChangeCallbackParam);
       
   748 	}