os/boardsupport/emulator/emulatorbsp/specific/variant.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/variant.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,748 @@
     1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// wins\specific\variant.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "variant.h"
    1.22 +#include "mconf.h"
    1.23 +#include <kernel/kern_priv.h>
    1.24 +#include <stdlib.h>
    1.25 +#include <property.h>
    1.26 +#include <emulator.h>
    1.27 +
    1.28 +const TInt KDefaultRam = 63;				// 63MB default internal RAM
    1.29 +const TInt KUnlimitedRam = 0x400;			// 1GB ~= unlimited memory
    1.30 +const TInt KDefaultRamDrive = 0x400000;		// 4MB default RAM drive limit
    1.31 +
    1.32 +_LIT(KLitWins,"Wins");
    1.33 +
    1.34 +GLDEF_D Wins TheVariant;
    1.35 +
    1.36 +GLDEF_D TActualMachineConfig TheConfig;
    1.37 +
    1.38 +EXPORT_C Asic* VariantInitialise(TBool aRunExe)
    1.39 +	{
    1.40 +	return TheVariant.Init(aRunExe) == KErrNone ? &TheVariant : NULL;
    1.41 +	}
    1.42 +
    1.43 +void AsicInitialise()
    1.44 +	{
    1.45 +	}
    1.46 +
    1.47 +class DWinsPowerController : public DPowerController
    1.48 +	{
    1.49 +public: // from DPowerComtroller
    1.50 +	void CpuIdle();
    1.51 +	void EnableWakeupEvents();
    1.52 +	void AbsoluteTimerExpired();
    1.53 +	void DisableWakeupEvents();
    1.54 +	void PowerDown(TTimeK aWakeupTime);
    1.55 +public:
    1.56 +	static DWinsPowerController* New();
    1.57 +	void AssertWakeupSignal();
    1.58 +	void WakeupEvent();
    1.59 +private:
    1.60 +	HANDLE	iStandbySem;
    1.61 +	TUint	iStandby;
    1.62 +	TBool	iWakeupSignal;
    1.63 +	};
    1.64 +
    1.65 +Wins::Wins()
    1.66 +	:iUi(0), iRealCpuSpeed(0), iCpuSpeed(0),
    1.67 +	iDebugOutput(INVALID_HANDLE_VALUE), iLogTimeStamp(ETrue),
    1.68 +	iPurgedImages(EFalse), iPowerController(0), iLogToDebugger(EFalse),
    1.69 +	iLogToFile(ETrue)
    1.70 +	{}
    1.71 +
    1.72 +TInt Wins::Init(TBool aRunExe)
    1.73 +	{
    1.74 +	TInt r = InitProperties(aRunExe);
    1.75 +	if (r == KErrNone)
    1.76 +		{
    1.77 +		iProperties.GetInt("LogTimeStamp",iLogTimeStamp);
    1.78 +		TInt logThreadId=ETrue;
    1.79 +		iProperties.GetInt("LogThreadId",logThreadId);
    1.80 +		TInt cpu=NThread::ECpuSingle;
    1.81 +		iProperties.GetInt("HostCPU",cpu);
    1.82 +		NThread::SetProperties(logThreadId,cpu);
    1.83 +		iProperties.GetInt("LogToDebugger",iLogToDebugger);
    1.84 +		iProperties.GetInt("LogToFile",iLogToFile);
    1.85 +
    1.86 +		TInt mask;
    1.87 +		Kern::SuperPage().iDebugMask[0] = DebugMask();  // get int or text mask value
    1.88 +		// check to see if DebugMask0 was used instead of DebugMask
    1.89 +		if ( (iProperties.GetInt("DebugMask", mask) != KErrNone) &&
    1.90 +			 (iProperties.GetInt("DebugMask0", mask) == KErrNone) )
    1.91 +			Kern::SuperPage().iDebugMask[0] = ((iProperties.GetInt("DebugMask0", mask) == KErrNone) ? mask : 0);
    1.92 +			
    1.93 +		// only int entries are supported for DebugMasks 1-7
    1.94 +		Kern::SuperPage().iDebugMask[1] = ((iProperties.GetInt("DebugMask1", mask) == KErrNone) ? mask : 0);
    1.95 +		Kern::SuperPage().iDebugMask[2] = ((iProperties.GetInt("DebugMask2", mask) == KErrNone) ? mask : 0);
    1.96 +		Kern::SuperPage().iDebugMask[3] = ((iProperties.GetInt("DebugMask3", mask) == KErrNone) ? mask : 0);
    1.97 +		Kern::SuperPage().iDebugMask[4] = ((iProperties.GetInt("DebugMask4", mask) == KErrNone) ? mask : 0);
    1.98 +		Kern::SuperPage().iDebugMask[5] = ((iProperties.GetInt("DebugMask5", mask) == KErrNone) ? mask : 0);
    1.99 +		Kern::SuperPage().iDebugMask[6] = ((iProperties.GetInt("DebugMask6", mask) == KErrNone) ? mask : 0);
   1.100 +		Kern::SuperPage().iDebugMask[7] = ((iProperties.GetInt("DebugMask7", mask) == KErrNone) ? mask : 0);
   1.101 +
   1.102 +		// initial values for fast trace...
   1.103 +		Kern::SuperPage().iInitialBTraceFilter[0] = ((iProperties.GetInt("BTrace0", mask) == KErrNone) ? mask : 0);
   1.104 +		Kern::SuperPage().iInitialBTraceFilter[1] = ((iProperties.GetInt("BTrace1", mask) == KErrNone) ? mask : 0);
   1.105 +		Kern::SuperPage().iInitialBTraceFilter[2] = ((iProperties.GetInt("BTrace2", mask) == KErrNone) ? mask : 0);
   1.106 +		Kern::SuperPage().iInitialBTraceFilter[3] = ((iProperties.GetInt("BTrace3", mask) == KErrNone) ? mask : 0);
   1.107 +		Kern::SuperPage().iInitialBTraceFilter[4] = ((iProperties.GetInt("BTrace4", mask) == KErrNone) ? mask : 0);
   1.108 +		Kern::SuperPage().iInitialBTraceFilter[5] = ((iProperties.GetInt("BTrace5", mask) == KErrNone) ? mask : 0);
   1.109 +		Kern::SuperPage().iInitialBTraceFilter[6] = ((iProperties.GetInt("BTrace6", mask) == KErrNone) ? mask : 0);
   1.110 +		Kern::SuperPage().iInitialBTraceFilter[7] = ((iProperties.GetInt("BTrace7", mask) == KErrNone) ? mask : 0);
   1.111 +		Kern::SuperPage().iInitialBTraceBuffer = ((iProperties.GetInt("BTraceBuffer", mask) == KErrNone) ? mask : 0);
   1.112 +		Kern::SuperPage().iInitialBTraceMode = ((iProperties.GetInt("BTraceMode", mask) == KErrNone) ? mask : 0);
   1.113 +
   1.114 +		Kern::SuperPage().SetKernelConfigFlags(KernelConfigFlags());
   1.115 +
   1.116 +		SCapabilitySet caps;
   1.117 +		DisabledCapabilities(caps);
   1.118 +		memcpy(&Kern::SuperPage().iDisabledCapabilities,&caps,sizeof(caps));
   1.119 +		}
   1.120 +	CalibrateCpuSpeed();
   1.121 +	return r;
   1.122 +	}
   1.123 +
   1.124 +inline void Wins::InstallUi(DWinsUiBase& aUi)
   1.125 +	{iUi = &aUi;}
   1.126 +
   1.127 +void Wins::Init1()
   1.128 +	{
   1.129 +	__KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init1()"));
   1.130 +
   1.131 +	TInt tickperiod = WinsTimer::EDefaultPeriod;
   1.132 +	iProperties.GetInt("TimerResolution",tickperiod);
   1.133 +	iTimer.Init(tickperiod);
   1.134 +	TUint speed;
   1.135 +	if (iProperties.GetInt("CPUSpeed", (TInt&)speed) == KErrNone)
   1.136 +		SetCpuSpeed(speed);
   1.137 +	}
   1.138 +
   1.139 +static TInt emulatorHal(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
   1.140 +	{
   1.141 +	return ((Wins*)aPtr)->EmulatorHal(aFunction, a1, a2);
   1.142 +	}
   1.143 +
   1.144 +void Wins::Init3()
   1.145 +//
   1.146 +// Initialise timer tick and add emulator hal function
   1.147 +//
   1.148 +	{
   1.149 +	__KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init3()"));
   1.150 +
   1.151 +	Kern::AddHalEntry(EHalGroupEmulator,&emulatorHal,this);
   1.152 +
   1.153 +	iPowerController = DWinsPowerController::New();
   1.154 +	if (iPowerController == 0)
   1.155 +		__PM_PANIC("Can't create 'DWinsPowerController'");
   1.156 +
   1.157 +	iTimer.Enable();
   1.158 +	}
   1.159 +
   1.160 +void Wins::AddressInfo(SAddressInfo& aInfo)
   1.161 +	{
   1.162 +	TInt megabytes = KDefaultRam;
   1.163 +	iProperties.GetInt("MegabytesOfFreeMemory", megabytes);
   1.164 +	if (megabytes == 0)
   1.165 +		megabytes = KUnlimitedRam;
   1.166 +	aInfo.iTotalRamSize = megabytes << 20;
   1.167 +//
   1.168 +	TInt ramdisk = KDefaultRamDrive;
   1.169 +	iProperties.GetInt("RamDriveMaxSize", ramdisk);
   1.170 +	aInfo.iRamDriveMaxSize = ramdisk;
   1.171 +	}
   1.172 +
   1.173 +void Wins::PurgeImages()
   1.174 +//
   1.175 +// Use the idle thread to clean up remnants of the emulator from the image path
   1.176 +//
   1.177 +	{
   1.178 +	char path[KMaxFileName+1];
   1.179 +
   1.180 +	const char* imgPath=0;
   1.181 +	iProperties.GetString("EmulatorImagePath", imgPath);
   1.182 +	strcpy(path, imgPath);
   1.183 +	char* name = path +strlen(path);
   1.184 +	strcpy(name,"*");
   1.185 +
   1.186 +	Emulator::Lock();
   1.187 +
   1.188 +	WIN32_FIND_DATAA fdata;
   1.189 +	HANDLE finder = FindFirstFileA(path, &fdata);
   1.190 +	if (finder != INVALID_HANDLE_VALUE)
   1.191 +		{
   1.192 +		do
   1.193 +			{
   1.194 +			if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
   1.195 +				{
   1.196 +				strcpy(name, fdata.cFileName);
   1.197 +				DeleteFileA(path);
   1.198 +				}
   1.199 +			} while (FindNextFileA(finder, &fdata));
   1.200 +		FindClose(finder);
   1.201 +		}
   1.202 +
   1.203 +	Emulator::Unlock();
   1.204 +	}
   1.205 +
   1.206 +void Wins::Idle()
   1.207 +//
   1.208 +// Use the win32 NKern idle function
   1.209 +//
   1.210 +	{
   1.211 +	iTimer.SetIdleThread();
   1.212 +	if (!iPurgedImages)
   1.213 +		{
   1.214 +		PurgeImages();
   1.215 +		iPurgedImages = ETrue;
   1.216 +		}
   1.217 +	NThread::Idle();
   1.218 +	}
   1.219 +
   1.220 +TInt Wins::MsTickPeriod()
   1.221 +//
   1.222 +// Provide the 'millisecond' timer tick period in microseconds
   1.223 +//
   1.224 +	{
   1.225 +	return 1000 * iTimer.Period();
   1.226 +	}
   1.227 +
   1.228 +TInt Wins::SystemTimeInSecondsFrom2000(TInt& aTime)
   1.229 +	{
   1.230 +	aTime = iTimer.SystemTime();
   1.231 +	__KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
   1.232 +	return KErrNone;
   1.233 +	}
   1.234 +
   1.235 +TInt Wins::SetSystemTimeInSecondsFrom2000(TInt aTime)
   1.236 +// 
   1.237 +// Set the emulator time. We must not change the Win32 time so
   1.238 +// we just adjust the offset value to account for the difference
   1.239 +//
   1.240 +	{
   1.241 +	__KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
   1.242 +	iTimer.SetSystemTime(aTime);
   1.243 +	return KErrNone;
   1.244 +	}
   1.245 +
   1.246 +TInt Wins::VariantHal(TInt aFunction, TAny* a1, TAny* /*a2*/)
   1.247 +	{
   1.248 +	TInt r=KErrNone;
   1.249 +	switch(aFunction)
   1.250 +		{
   1.251 +		case EVariantHalVariantInfo:
   1.252 +			{
   1.253 +			TVariantInfoV01Buf infoBuf;
   1.254 +			TVariantInfoV01& info=infoBuf();
   1.255 +
   1.256 +//			info.iRomVersion=TVersion(KRomMajorVersionNumber,KRomMinorVersionNumber,KRomBuildVersionNumber);
   1.257 +			info.iMachineUniqueId=0;
   1.258 +			info.iLedCapabilities=0x0;
   1.259 +			info.iProcessorClockInKHz=iCpuSpeed ? iCpuSpeed*1000 : 1;
   1.260 +			info.iSpeedFactor=0;
   1.261 +			if (iUi)
   1.262 +				iUi->Info(info);
   1.263 +
   1.264 +			Kern::InfoCopy(*(TDes8*)a1,infoBuf);
   1.265 +			break;
   1.266 +			}
   1.267 +
   1.268 +		case EVariantHalCustomRestartReason:
   1.269 +			{
   1.270 +			//This will take value from c:\data\epoc.ini.
   1.271 +			TInt x = Property::GetInt("CustomRestartReason");    
   1.272 +			kumemput32(a1, &x, sizeof(TInt));
   1.273 +			}
   1.274 +			break;
   1.275 +
   1.276 +		case EVariantHalCustomRestart:
   1.277 +			{
   1.278 +			if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EVariantHalCustomRestart")))
   1.279 +				return KErrPermissionDenied;
   1.280 +			//This will only shut down epoc as Custom Restart Reason is not supported on wins.
   1.281 +			Kern::Restart((TInt)a1);
   1.282 +			break;
   1.283 +			}
   1.284 +
   1.285 +		default:
   1.286 +			r=KErrNotSupported;
   1.287 +			break;
   1.288 +		}
   1.289 +	return r;
   1.290 +	}
   1.291 +
   1.292 +TPtr8 Wins::MachineConfiguration()
   1.293 +	{
   1.294 +	return TPckg<TActualMachineConfig>(TheConfig);
   1.295 +	}
   1.296 +
   1.297 +void Wins::CalibrateCpuSpeed()
   1.298 +//
   1.299 +// calculate approx. CPU speed in MHz, 0 if we can't tell
   1.300 +//
   1.301 +	{
   1.302 +    TInt cycleCount =200*1000*20;   //take 20ms at 20MHz
   1.303 +    
   1.304 +    // This loop will double the cyclecount until the difference is non-zero.
   1.305 +    FOREVER
   1.306 +    	{
   1.307 +      	if (cycleCount > (KMaxTUint / 2))
   1.308 +    		{
   1.309 +    		break;
   1.310 +    		}
   1.311 +    
   1.312 +		SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
   1.313 +		LARGE_INTEGER start;
   1.314 +		if (QueryPerformanceCounter(&start))
   1.315 +    		{
   1.316 +	   		__asm mov eax, cycleCount
   1.317 + 	noploop: 
   1.318 + 			__asm dec eax
   1.319 +			__asm dec eax
   1.320 +			__asm dec eax
   1.321 +			__asm dec eax
   1.322 +			__asm dec eax
   1.323 +			__asm dec eax
   1.324 +			__asm dec eax
   1.325 +			__asm dec eax
   1.326 +			__asm dec eax
   1.327 +			__asm dec eax
   1.328 +			__asm dec eax
   1.329 +			__asm dec eax
   1.330 +			__asm dec eax
   1.331 +			__asm dec eax
   1.332 +			__asm dec eax
   1.333 +			__asm dec eax
   1.334 +			__asm dec eax
   1.335 +			__asm dec eax
   1.336 +			__asm dec eax
   1.337 +			__asm dec eax
   1.338 +			__asm dec eax
   1.339 +			__asm dec eax
   1.340 +			__asm dec eax
   1.341 +			__asm dec eax
   1.342 +			__asm dec eax
   1.343 +			__asm dec eax
   1.344 +			__asm dec eax
   1.345 +			__asm dec eax
   1.346 +			__asm dec eax
   1.347 +			__asm dec eax
   1.348 +			__asm dec eax
   1.349 +			__asm dec eax
   1.350 +			__asm dec eax
   1.351 +			__asm dec eax
   1.352 +			__asm dec eax
   1.353 +			__asm dec eax
   1.354 +			__asm dec eax
   1.355 +			__asm dec eax
   1.356 +			__asm dec eax
   1.357 +			__asm dec eax
   1.358 +			__asm dec eax
   1.359 +			__asm dec eax
   1.360 +			__asm dec eax
   1.361 +			__asm dec eax
   1.362 +			__asm dec eax
   1.363 +			__asm dec eax
   1.364 +			__asm dec eax
   1.365 +			__asm dec eax
   1.366 +			__asm sub eax, 2
   1.367 +			__asm jnz noploop
   1.368 +			//
   1.369 +			LARGE_INTEGER end;
   1.370 +			QueryPerformanceCounter(&end);
   1.371 +			LARGE_INTEGER f;
   1.372 +			QueryPerformanceFrequency(&f);
   1.373 +			
   1.374 +			TInt64 diff = (end.QuadPart - start.QuadPart);
   1.375 +	    	if(diff!=0)
   1.376 +	    		{
   1.377 +				TInt64 hz = (TInt64(cycleCount) / 1000000) * (f.QuadPart / diff);
   1.378 +				iRealCpuSpeed = (TUint)(hz);
   1.379 +				break;
   1.380 +		     	}
   1.381 +  	  	    }
   1.382 +    	cycleCount *= 2;  // Double the count!!
   1.383 + 		}
   1.384 +    
   1.385 +   	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
   1.386 +	}
   1.387 +
   1.388 +TInt Wins::SetCpuSpeed(TUint aSpeed)
   1.389 +	{
   1.390 +	if (iRealCpuSpeed == 0)
   1.391 +		return KErrNotSupported;	// don't know the real CPUSpeed
   1.392 +
   1.393 +	if (IsDebuggerPresent())
   1.394 +		return KErrGeneral;			// nobbling not avaliable when debugging
   1.395 +
   1.396 +	if (aSpeed == 0)
   1.397 +		aSpeed = iRealCpuSpeed;		// reset to maximum
   1.398 +	else if (aSpeed > iRealCpuSpeed)
   1.399 +		aSpeed = iRealCpuSpeed;
   1.400 +	else if (aSpeed * 20u  < iRealCpuSpeed)
   1.401 +		aSpeed = (iRealCpuSpeed + 19u) / 20u;
   1.402 +
   1.403 +	__KTRACE_OPT(KHARDWARE,Kern::Printf("Set CPUSpeed: %d",aSpeed));
   1.404 +	iCpuSpeed = aSpeed;
   1.405 +
   1.406 +	// calculate CPU time to nobble in parts-per-million
   1.407 +	TUint nobble = ((iRealCpuSpeed - aSpeed) * 1000000u) / iRealCpuSpeed;
   1.408 +	iTimer.Nobble(nobble);
   1.409 +	return KErrNone;
   1.410 +	}
   1.411 +
   1.412 +HANDLE Wins::DebugOutput()
   1.413 +//
   1.414 +// Return a handle to the trace file, creating the file if required.
   1.415 +//
   1.416 +// The log file name can be specified by a property or environment
   1.417 +// variable called 'EmulatorLog', otherwise it defaults to 
   1.418 +// 'epocwind.out' in the temporary directory.
   1.419 +//
   1.420 +	{
   1.421 +	HANDLE file = iDebugOutput;
   1.422 +	if (file == INVALID_HANDLE_VALUE)
   1.423 +		{
   1.424 +		CHAR debugfile[MAX_PATH];
   1.425 +		const char* logpath;
   1.426 +		if (iProperties.GetString("EmulatorLog",logpath)==KErrNone)
   1.427 +			strcpy(debugfile,logpath);
   1.428 +		else
   1.429 +			{
   1.430 +			DWORD len = GetEnvironmentVariableA("EmulatorLog", debugfile, MAX_PATH);
   1.431 +			debugfile[len]=0;
   1.432 +			if (len == 0)
   1.433 +				{
   1.434 +				len=GetTempPathA(MAX_PATH,debugfile);
   1.435 +				strcpy(debugfile+len,"epocwind.out");	// EPOC WINS DEBUG output file
   1.436 +				}
   1.437 +			}
   1.438 +		file=CreateFileA(debugfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
   1.439 +		if (file!=INVALID_HANDLE_VALUE)
   1.440 +			{
   1.441 +			SetFilePointer(file, NULL, NULL, FILE_END);
   1.442 +			iDebugOutput = file;
   1.443 +			}
   1.444 +		}
   1.445 +	return file;
   1.446 +	}
   1.447 +
   1.448 +const TInt MaxOutputMsg = 599;
   1.449 +
   1.450 +void Wins::EarlyLogging(const char* aMessage1,const char* aMessage2)
   1.451 +	{
   1.452 +	char message[MaxOutputMsg+3];
   1.453 +	TInt len = min(strlen(aMessage1), MaxOutputMsg);
   1.454 +	memcpy(message,aMessage1,len);
   1.455 +	if(aMessage2)
   1.456 +		{
   1.457 +		TInt len2 = min((TInt)strlen(aMessage2), MaxOutputMsg-len);
   1.458 +		memcpy(message+len,aMessage2,len2);
   1.459 +		len+=len2;
   1.460 +		}
   1.461 +	message[len++] = '\r';
   1.462 +	message[len++] = '\n';
   1.463 +	message[len] = 0;
   1.464 +
   1.465 +	if (iLogToFile)
   1.466 +		{
   1.467 +		DWORD bytes;
   1.468 +		WriteFile(DebugOutput(), message, len, &bytes, NULL);
   1.469 +		}
   1.470 +	if (iLogToDebugger)
   1.471 +		{
   1.472 +		OutputDebugStringA(message);
   1.473 +		}
   1.474 +	}
   1.475 +
   1.476 +void Wins::DebugPrint(const TDesC8& aDes)
   1.477 +//
   1.478 +// Send the string to the debug output (Win32 debug trace) and trace file
   1.479 +//
   1.480 +	{
   1.481 +	char message[MaxOutputMsg+1];
   1.482 +	TInt len = aDes.Length();
   1.483 +	const char* ptr = (const char*)aDes.Ptr();
   1.484 +	if (iLogTimeStamp)
   1.485 +		{
   1.486 +		strcpy(message,"          ");
   1.487 +		_ultoa(NKern::TickCount() * iTimer.Period(), message + 10, 10);
   1.488 +		int n = strlen(message);
   1.489 +		len = min(len, MaxOutputMsg - n - 2);
   1.490 +		char* msg = message + n;
   1.491 +		msg[0] = msg[-1];
   1.492 +		msg[-1] = n < 10+2 ? '0' : msg[-2];
   1.493 +		msg[-2] = n < 10+3 ? '0' : msg[-3];
   1.494 +		msg[-3] = '.';
   1.495 +		if (n < 10+4)
   1.496 +			msg[-4] = '0';
   1.497 +		++msg;
   1.498 +		*msg++ = '\t';
   1.499 +		strncpy(msg, ptr, len);
   1.500 +		msg[len] = 0;
   1.501 +		ptr = msg - 11;
   1.502 +		len += 11;
   1.503 +		}
   1.504 +	else
   1.505 +		{
   1.506 +		len = min(len, MaxOutputMsg);
   1.507 +		strncpy(message, ptr, len);
   1.508 +		message[len] = 0;
   1.509 +		ptr = message;
   1.510 +		}
   1.511 +	TInt irq = NKern::DisableAllInterrupts();
   1.512 +	if (iLogToFile)
   1.513 +		{
   1.514 +		DWORD bytes;
   1.515 +		WriteFile(DebugOutput(), ptr, len, &bytes, NULL);
   1.516 +		}
   1.517 +	if (iLogToDebugger)
   1.518 +		{
   1.519 +		OutputDebugStringA(message);
   1.520 +		}
   1.521 +
   1.522 +	NKern::RestoreInterrupts(irq);
   1.523 +	}
   1.524 +
   1.525 +const char* const KErrorTitles[] =
   1.526 +	{
   1.527 +	"Symbian OS Fatal Error",
   1.528 +	"Symbian OS Application Error"
   1.529 +	};
   1.530 +
   1.531 +const TText8* const KErrorMsg[] =
   1.532 +	{
   1.533 +	_S8("An error has been detected in the Symbian OS emulator."),
   1.534 +	_S8("A call to User::Panic() has occured, indicating\n"
   1.535 +		"a programming fault in the running application.\n"
   1.536 +		"Please refer to the documentation for more details.")
   1.537 +	};
   1.538 +
   1.539 +_LIT8(KProgram, "\n\nProgram\t");
   1.540 +_LIT8(KError, "\nError\t");
   1.541 +_LIT8(KIDFC, "an IDFC");
   1.542 +_LIT8(KEscaped, "an escaped thread");
   1.543 +_LIT8(KInterrupt, "an interrupt thread");
   1.544 +_LIT8(KNThread, "an NThread");
   1.545 +_LIT8(KColon, " : ");
   1.546 +_LIT8(KDebugQuery, "\n\nDo you wish to Debug the error?\0");
   1.547 +
   1.548 +TBool Wins::ErrorDialog(TError aType, const TDesC8& aPanic, TInt aVal)
   1.549 +	{
   1.550 +	// Must be called with interrupts enabled to allow thread running windows message loop to run
   1.551 +	
   1.552 +	TBuf8<512> message(KErrorMsg[aType]);
   1.553 +	message.Append(KProgram);
   1.554 +	TInt context = NKern::CurrentContext();
   1.555 +	switch(context)
   1.556 +		{
   1.557 +		case NKern::EIDFC:
   1.558 +			message.Append(KIDFC);
   1.559 +			break;
   1.560 +		case NKern::EEscaped:
   1.561 +			message.Append(KEscaped);
   1.562 +			break;
   1.563 +		case NKern::EInterrupt:
   1.564 +			message.Append(KInterrupt);
   1.565 +			break;
   1.566 +		case NKern::EThread:
   1.567 +			DThread *thread = Kern::NThreadToDThread(NKern::CurrentThread());
   1.568 +			if (thread)
   1.569 +				thread->TraceAppendFullName(message, ETrue);
   1.570 +			else
   1.571 +				message.Append(KNThread);
   1.572 +			break;
   1.573 +		}
   1.574 +	message.Append(KError);
   1.575 +	message.Append(aPanic);
   1.576 +	message.Append(KColon);
   1.577 +	message.AppendNum(aVal);
   1.578 +#ifdef _DEBUG
   1.579 +	message.Append(KDebugQuery);
   1.580 +	UINT type = MB_YESNO | MB_DEFBUTTON2;
   1.581 +#else
   1.582 +	UINT type = MB_OK;
   1.583 +#endif
   1.584 +	type |= MB_SETFOREGROUND  | MB_ICONERROR;
   1.585 +	message.Append('\0');
   1.586 +
   1.587 +	TInt r = MessageBoxA(iUi ? iUi->HWnd() : NULL, (LPCSTR)message.Ptr(), KErrorTitles[aType], type);
   1.588 +	return r == IDYES;
   1.589 +	}
   1.590 +
   1.591 +// UI installation
   1.592 +
   1.593 +EXPORT_C DWinsUiBase::DWinsUiBase()
   1.594 +	{
   1.595 +	TheVariant.InstallUi(*this);
   1.596 +	}
   1.597 +
   1.598 +
   1.599 +TInt BinaryPowerInit();
   1.600 +
   1.601 +DWinsPowerController* DWinsPowerController::New()
   1.602 +	{
   1.603 +	DWinsPowerController* self = new DWinsPowerController();
   1.604 +	if (!self)
   1.605 +		return NULL;
   1.606 +	self->iStandbySem = CreateSemaphore(NULL, 0, 1, NULL);
   1.607 +	if (self->iStandbySem == NULL)
   1.608 +		return NULL;
   1.609 +	TInt r = BinaryPowerInit();
   1.610 +	if (r != KErrNone)
   1.611 +		return NULL;
   1.612 +	self->Register();
   1.613 +	return self; 
   1.614 +	}
   1.615 +
   1.616 +void DWinsPowerController::CpuIdle()
   1.617 +	{
   1.618 +	Arch::TheAsic()->Idle();
   1.619 +	}
   1.620 +		
   1.621 +void DWinsPowerController::EnableWakeupEvents()
   1.622 +	{
   1.623 +	iWakeupSignal = EFalse;
   1.624 +	}
   1.625 +
   1.626 +void DWinsPowerController::DisableWakeupEvents()
   1.627 +	{
   1.628 +	}
   1.629 +
   1.630 +void DWinsPowerController::AbsoluteTimerExpired()
   1.631 +	{
   1.632 +	if (iTargetState == EPwStandby)
   1.633 +		DWinsPowerController::WakeupEvent();	
   1.634 +	}
   1.635 +
   1.636 +void DWinsPowerController::WakeupEvent()
   1.637 +	{
   1.638 +	if (iTargetState == EPwStandby)
   1.639 +		{
   1.640 +		iWakeupSignal = ETrue;
   1.641 +		DPowerController::WakeupEvent();
   1.642 +		}
   1.643 +	}
   1.644 +
   1.645 +// called in Epoc thread
   1.646 +void DWinsPowerController::PowerDown(TTimeK aWakeupTime)
   1.647 +	{
   1.648 +	if (iTargetState == EPwStandby)
   1.649 +		{
   1.650 +		UINT timeoutMs;
   1.651 +		if (aWakeupTime == 0)
   1.652 +			timeoutMs = INFINITE;
   1.653 +		else 
   1.654 +			{
   1.655 +			TTimeK now = Kern::SystemTime();
   1.656 +			if (now > aWakeupTime)
   1.657 +				timeoutMs = 0;
   1.658 +			else
   1.659 +				timeoutMs = (UINT)((aWakeupTime - now) / 1000);
   1.660 +			}
   1.661 +		TInt l = NKern::DisableAllInterrupts();
   1.662 +		if (!iWakeupSignal && timeoutMs)
   1.663 +			{
   1.664 +			iStandby = ETrue;
   1.665 +			TheVariant.iTimer.Standby();
   1.666 +			NKern::RestoreInterrupts(l);
   1.667 +			DWORD r = WaitForSingleObject(iStandbySem, timeoutMs);
   1.668 +			if (r == WAIT_TIMEOUT)
   1.669 +				{
   1.670 +				l = NKern::DisableAllInterrupts();
   1.671 +				if (!iStandby)
   1.672 +					WaitForSingleObject(iStandbySem, INFINITE);
   1.673 +				else
   1.674 +					iStandby = EFalse;
   1.675 +				NKern::RestoreInterrupts(l);
   1.676 +				}
   1.677 +			TheVariant.iTimer.Wakeup();
   1.678 +			}
   1.679 +		else
   1.680 +			NKern::RestoreInterrupts(l);
   1.681 +
   1.682 +		}
   1.683 +	else
   1.684 +		Kern::Restart(0x80000000);
   1.685 +	}
   1.686 +
   1.687 +// called in the interrupt context
   1.688 +void DWinsPowerController::AssertWakeupSignal()
   1.689 +	{
   1.690 +	iWakeupSignal = ETrue;
   1.691 +	if (iStandby)
   1.692 +		{
   1.693 +		iStandby = EFalse;
   1.694 +		ReleaseSemaphore(iStandbySem, 1, NULL);
   1.695 +		}
   1.696 +	}
   1.697 +
   1.698 +
   1.699 +EXPORT_C void Wins::AssertWakeupSignal()
   1.700 +	{
   1.701 +	iPowerController->AssertWakeupSignal();
   1.702 +	}
   1.703 +
   1.704 +EXPORT_C void Wins::WakeupEvent()
   1.705 +	{
   1.706 +	iPowerController->DWinsPowerController::WakeupEvent();
   1.707 +	}
   1.708 +
   1.709 +// MMC emulation support
   1.710 +
   1.711 +TBool Wins::MediaDoorOpen;
   1.712 +TInt Wins::CurrentPBusDevice;
   1.713 +TAny* Wins::MediaChangeCallbackParam;
   1.714 +TMediaChangeCallBack Wins::MediaChangeCallBackPtr;
   1.715 +
   1.716 +
   1.717 +EXPORT_C TBool* Wins::MediaDoorOpenPtr()
   1.718 +//
   1.719 +// For media change simulation
   1.720 +//
   1.721 +	{
   1.722 +
   1.723 +	return(&MediaDoorOpen);
   1.724 +	}
   1.725 +
   1.726 +EXPORT_C TInt* Wins::CurrentPBusDevicePtr()
   1.727 +//
   1.728 +// For media change simulation
   1.729 +//
   1.730 +	{
   1.731 +
   1.732 +	return(&CurrentPBusDevice);
   1.733 +	}
   1.734 +
   1.735 +EXPORT_C void Wins::SetMediaChangeCallBackPtr(TMediaChangeCallBack aPtr, TAny* aMediaChangeCallbackParam)
   1.736 +//
   1.737 +// For media change simulation
   1.738 +//
   1.739 +	{
   1.740 +	MediaChangeCallbackParam=aMediaChangeCallbackParam;
   1.741 +	MediaChangeCallBackPtr=aPtr;
   1.742 +	}
   1.743 +
   1.744 +EXPORT_C void Wins::MediaChangeCallBack()
   1.745 +//
   1.746 +// Perform the simulated media change callback
   1.747 +//
   1.748 +	{
   1.749 +	if(MediaChangeCallBackPtr)
   1.750 +		(*MediaChangeCallBackPtr)(MediaChangeCallbackParam);
   1.751 +	}