os/boardsupport/emulator/emulatorbsp/specific/variant.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	}