--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emulator/emulatorbsp/specific/variant.cpp Tue Feb 02 01:39:10 2010 +0200
@@ -0,0 +1,748 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// wins\specific\variant.cpp
+//
+//
+
+#include "variant.h"
+#include "mconf.h"
+#include <kernel/kern_priv.h>
+#include <stdlib.h>
+#include <property.h>
+#include <emulator.h>
+
+const TInt KDefaultRam = 63; // 63MB default internal RAM
+const TInt KUnlimitedRam = 0x400; // 1GB ~= unlimited memory
+const TInt KDefaultRamDrive = 0x400000; // 4MB default RAM drive limit
+
+_LIT(KLitWins,"Wins");
+
+GLDEF_D Wins TheVariant;
+
+GLDEF_D TActualMachineConfig TheConfig;
+
+EXPORT_C Asic* VariantInitialise(TBool aRunExe)
+ {
+ return TheVariant.Init(aRunExe) == KErrNone ? &TheVariant : NULL;
+ }
+
+void AsicInitialise()
+ {
+ }
+
+class DWinsPowerController : public DPowerController
+ {
+public: // from DPowerComtroller
+ void CpuIdle();
+ void EnableWakeupEvents();
+ void AbsoluteTimerExpired();
+ void DisableWakeupEvents();
+ void PowerDown(TTimeK aWakeupTime);
+public:
+ static DWinsPowerController* New();
+ void AssertWakeupSignal();
+ void WakeupEvent();
+private:
+ HANDLE iStandbySem;
+ TUint iStandby;
+ TBool iWakeupSignal;
+ };
+
+Wins::Wins()
+ :iUi(0), iRealCpuSpeed(0), iCpuSpeed(0),
+ iDebugOutput(INVALID_HANDLE_VALUE), iLogTimeStamp(ETrue),
+ iPurgedImages(EFalse), iPowerController(0), iLogToDebugger(EFalse),
+ iLogToFile(ETrue)
+ {}
+
+TInt Wins::Init(TBool aRunExe)
+ {
+ TInt r = InitProperties(aRunExe);
+ if (r == KErrNone)
+ {
+ iProperties.GetInt("LogTimeStamp",iLogTimeStamp);
+ TInt logThreadId=ETrue;
+ iProperties.GetInt("LogThreadId",logThreadId);
+ TInt cpu=NThread::ECpuSingle;
+ iProperties.GetInt("HostCPU",cpu);
+ NThread::SetProperties(logThreadId,cpu);
+ iProperties.GetInt("LogToDebugger",iLogToDebugger);
+ iProperties.GetInt("LogToFile",iLogToFile);
+
+ TInt mask;
+ Kern::SuperPage().iDebugMask[0] = DebugMask(); // get int or text mask value
+ // check to see if DebugMask0 was used instead of DebugMask
+ if ( (iProperties.GetInt("DebugMask", mask) != KErrNone) &&
+ (iProperties.GetInt("DebugMask0", mask) == KErrNone) )
+ Kern::SuperPage().iDebugMask[0] = ((iProperties.GetInt("DebugMask0", mask) == KErrNone) ? mask : 0);
+
+ // only int entries are supported for DebugMasks 1-7
+ Kern::SuperPage().iDebugMask[1] = ((iProperties.GetInt("DebugMask1", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[2] = ((iProperties.GetInt("DebugMask2", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[3] = ((iProperties.GetInt("DebugMask3", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[4] = ((iProperties.GetInt("DebugMask4", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[5] = ((iProperties.GetInt("DebugMask5", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[6] = ((iProperties.GetInt("DebugMask6", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iDebugMask[7] = ((iProperties.GetInt("DebugMask7", mask) == KErrNone) ? mask : 0);
+
+ // initial values for fast trace...
+ Kern::SuperPage().iInitialBTraceFilter[0] = ((iProperties.GetInt("BTrace0", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[1] = ((iProperties.GetInt("BTrace1", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[2] = ((iProperties.GetInt("BTrace2", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[3] = ((iProperties.GetInt("BTrace3", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[4] = ((iProperties.GetInt("BTrace4", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[5] = ((iProperties.GetInt("BTrace5", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[6] = ((iProperties.GetInt("BTrace6", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceFilter[7] = ((iProperties.GetInt("BTrace7", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceBuffer = ((iProperties.GetInt("BTraceBuffer", mask) == KErrNone) ? mask : 0);
+ Kern::SuperPage().iInitialBTraceMode = ((iProperties.GetInt("BTraceMode", mask) == KErrNone) ? mask : 0);
+
+ Kern::SuperPage().SetKernelConfigFlags(KernelConfigFlags());
+
+ SCapabilitySet caps;
+ DisabledCapabilities(caps);
+ memcpy(&Kern::SuperPage().iDisabledCapabilities,&caps,sizeof(caps));
+ }
+ CalibrateCpuSpeed();
+ return r;
+ }
+
+inline void Wins::InstallUi(DWinsUiBase& aUi)
+ {iUi = &aUi;}
+
+void Wins::Init1()
+ {
+ __KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init1()"));
+
+ TInt tickperiod = WinsTimer::EDefaultPeriod;
+ iProperties.GetInt("TimerResolution",tickperiod);
+ iTimer.Init(tickperiod);
+ TUint speed;
+ if (iProperties.GetInt("CPUSpeed", (TInt&)speed) == KErrNone)
+ SetCpuSpeed(speed);
+ }
+
+static TInt emulatorHal(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
+ {
+ return ((Wins*)aPtr)->EmulatorHal(aFunction, a1, a2);
+ }
+
+void Wins::Init3()
+//
+// Initialise timer tick and add emulator hal function
+//
+ {
+ __KTRACE_OPT(KBOOT,Kern::Printf("Wins::Init3()"));
+
+ Kern::AddHalEntry(EHalGroupEmulator,&emulatorHal,this);
+
+ iPowerController = DWinsPowerController::New();
+ if (iPowerController == 0)
+ __PM_PANIC("Can't create 'DWinsPowerController'");
+
+ iTimer.Enable();
+ }
+
+void Wins::AddressInfo(SAddressInfo& aInfo)
+ {
+ TInt megabytes = KDefaultRam;
+ iProperties.GetInt("MegabytesOfFreeMemory", megabytes);
+ if (megabytes == 0)
+ megabytes = KUnlimitedRam;
+ aInfo.iTotalRamSize = megabytes << 20;
+//
+ TInt ramdisk = KDefaultRamDrive;
+ iProperties.GetInt("RamDriveMaxSize", ramdisk);
+ aInfo.iRamDriveMaxSize = ramdisk;
+ }
+
+void Wins::PurgeImages()
+//
+// Use the idle thread to clean up remnants of the emulator from the image path
+//
+ {
+ char path[KMaxFileName+1];
+
+ const char* imgPath=0;
+ iProperties.GetString("EmulatorImagePath", imgPath);
+ strcpy(path, imgPath);
+ char* name = path +strlen(path);
+ strcpy(name,"*");
+
+ Emulator::Lock();
+
+ WIN32_FIND_DATAA fdata;
+ HANDLE finder = FindFirstFileA(path, &fdata);
+ if (finder != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+ {
+ strcpy(name, fdata.cFileName);
+ DeleteFileA(path);
+ }
+ } while (FindNextFileA(finder, &fdata));
+ FindClose(finder);
+ }
+
+ Emulator::Unlock();
+ }
+
+void Wins::Idle()
+//
+// Use the win32 NKern idle function
+//
+ {
+ iTimer.SetIdleThread();
+ if (!iPurgedImages)
+ {
+ PurgeImages();
+ iPurgedImages = ETrue;
+ }
+ NThread::Idle();
+ }
+
+TInt Wins::MsTickPeriod()
+//
+// Provide the 'millisecond' timer tick period in microseconds
+//
+ {
+ return 1000 * iTimer.Period();
+ }
+
+TInt Wins::SystemTimeInSecondsFrom2000(TInt& aTime)
+ {
+ aTime = iTimer.SystemTime();
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("RTC READ: %d",aTime));
+ return KErrNone;
+ }
+
+TInt Wins::SetSystemTimeInSecondsFrom2000(TInt aTime)
+//
+// Set the emulator time. We must not change the Win32 time so
+// we just adjust the offset value to account for the difference
+//
+ {
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("Set RTC: %d",aTime));
+ iTimer.SetSystemTime(aTime);
+ return KErrNone;
+ }
+
+TInt Wins::VariantHal(TInt aFunction, TAny* a1, TAny* /*a2*/)
+ {
+ TInt r=KErrNone;
+ switch(aFunction)
+ {
+ case EVariantHalVariantInfo:
+ {
+ TVariantInfoV01Buf infoBuf;
+ TVariantInfoV01& info=infoBuf();
+
+// info.iRomVersion=TVersion(KRomMajorVersionNumber,KRomMinorVersionNumber,KRomBuildVersionNumber);
+ info.iMachineUniqueId=0;
+ info.iLedCapabilities=0x0;
+ info.iProcessorClockInKHz=iCpuSpeed ? iCpuSpeed*1000 : 1;
+ info.iSpeedFactor=0;
+ if (iUi)
+ iUi->Info(info);
+
+ Kern::InfoCopy(*(TDes8*)a1,infoBuf);
+ break;
+ }
+
+ case EVariantHalCustomRestartReason:
+ {
+ //This will take value from c:\data\epoc.ini.
+ TInt x = Property::GetInt("CustomRestartReason");
+ kumemput32(a1, &x, sizeof(TInt));
+ }
+ break;
+
+ case EVariantHalCustomRestart:
+ {
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EVariantHalCustomRestart")))
+ return KErrPermissionDenied;
+ //This will only shut down epoc as Custom Restart Reason is not supported on wins.
+ Kern::Restart((TInt)a1);
+ break;
+ }
+
+ default:
+ r=KErrNotSupported;
+ break;
+ }
+ return r;
+ }
+
+TPtr8 Wins::MachineConfiguration()
+ {
+ return TPckg<TActualMachineConfig>(TheConfig);
+ }
+
+void Wins::CalibrateCpuSpeed()
+//
+// calculate approx. CPU speed in MHz, 0 if we can't tell
+//
+ {
+ TInt cycleCount =200*1000*20; //take 20ms at 20MHz
+
+ // This loop will double the cyclecount until the difference is non-zero.
+ FOREVER
+ {
+ if (cycleCount > (KMaxTUint / 2))
+ {
+ break;
+ }
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ LARGE_INTEGER start;
+ if (QueryPerformanceCounter(&start))
+ {
+ __asm mov eax, cycleCount
+ noploop:
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm dec eax
+ __asm sub eax, 2
+ __asm jnz noploop
+ //
+ LARGE_INTEGER end;
+ QueryPerformanceCounter(&end);
+ LARGE_INTEGER f;
+ QueryPerformanceFrequency(&f);
+
+ TInt64 diff = (end.QuadPart - start.QuadPart);
+ if(diff!=0)
+ {
+ TInt64 hz = (TInt64(cycleCount) / 1000000) * (f.QuadPart / diff);
+ iRealCpuSpeed = (TUint)(hz);
+ break;
+ }
+ }
+ cycleCount *= 2; // Double the count!!
+ }
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ }
+
+TInt Wins::SetCpuSpeed(TUint aSpeed)
+ {
+ if (iRealCpuSpeed == 0)
+ return KErrNotSupported; // don't know the real CPUSpeed
+
+ if (IsDebuggerPresent())
+ return KErrGeneral; // nobbling not avaliable when debugging
+
+ if (aSpeed == 0)
+ aSpeed = iRealCpuSpeed; // reset to maximum
+ else if (aSpeed > iRealCpuSpeed)
+ aSpeed = iRealCpuSpeed;
+ else if (aSpeed * 20u < iRealCpuSpeed)
+ aSpeed = (iRealCpuSpeed + 19u) / 20u;
+
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("Set CPUSpeed: %d",aSpeed));
+ iCpuSpeed = aSpeed;
+
+ // calculate CPU time to nobble in parts-per-million
+ TUint nobble = ((iRealCpuSpeed - aSpeed) * 1000000u) / iRealCpuSpeed;
+ iTimer.Nobble(nobble);
+ return KErrNone;
+ }
+
+HANDLE Wins::DebugOutput()
+//
+// Return a handle to the trace file, creating the file if required.
+//
+// The log file name can be specified by a property or environment
+// variable called 'EmulatorLog', otherwise it defaults to
+// 'epocwind.out' in the temporary directory.
+//
+ {
+ HANDLE file = iDebugOutput;
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ CHAR debugfile[MAX_PATH];
+ const char* logpath;
+ if (iProperties.GetString("EmulatorLog",logpath)==KErrNone)
+ strcpy(debugfile,logpath);
+ else
+ {
+ DWORD len = GetEnvironmentVariableA("EmulatorLog", debugfile, MAX_PATH);
+ debugfile[len]=0;
+ if (len == 0)
+ {
+ len=GetTempPathA(MAX_PATH,debugfile);
+ strcpy(debugfile+len,"epocwind.out"); // EPOC WINS DEBUG output file
+ }
+ }
+ file=CreateFileA(debugfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
+ if (file!=INVALID_HANDLE_VALUE)
+ {
+ SetFilePointer(file, NULL, NULL, FILE_END);
+ iDebugOutput = file;
+ }
+ }
+ return file;
+ }
+
+const TInt MaxOutputMsg = 599;
+
+void Wins::EarlyLogging(const char* aMessage1,const char* aMessage2)
+ {
+ char message[MaxOutputMsg+3];
+ TInt len = min(strlen(aMessage1), MaxOutputMsg);
+ memcpy(message,aMessage1,len);
+ if(aMessage2)
+ {
+ TInt len2 = min((TInt)strlen(aMessage2), MaxOutputMsg-len);
+ memcpy(message+len,aMessage2,len2);
+ len+=len2;
+ }
+ message[len++] = '\r';
+ message[len++] = '\n';
+ message[len] = 0;
+
+ if (iLogToFile)
+ {
+ DWORD bytes;
+ WriteFile(DebugOutput(), message, len, &bytes, NULL);
+ }
+ if (iLogToDebugger)
+ {
+ OutputDebugStringA(message);
+ }
+ }
+
+void Wins::DebugPrint(const TDesC8& aDes)
+//
+// Send the string to the debug output (Win32 debug trace) and trace file
+//
+ {
+ char message[MaxOutputMsg+1];
+ TInt len = aDes.Length();
+ const char* ptr = (const char*)aDes.Ptr();
+ if (iLogTimeStamp)
+ {
+ strcpy(message," ");
+ _ultoa(NKern::TickCount() * iTimer.Period(), message + 10, 10);
+ int n = strlen(message);
+ len = min(len, MaxOutputMsg - n - 2);
+ char* msg = message + n;
+ msg[0] = msg[-1];
+ msg[-1] = n < 10+2 ? '0' : msg[-2];
+ msg[-2] = n < 10+3 ? '0' : msg[-3];
+ msg[-3] = '.';
+ if (n < 10+4)
+ msg[-4] = '0';
+ ++msg;
+ *msg++ = '\t';
+ strncpy(msg, ptr, len);
+ msg[len] = 0;
+ ptr = msg - 11;
+ len += 11;
+ }
+ else
+ {
+ len = min(len, MaxOutputMsg);
+ strncpy(message, ptr, len);
+ message[len] = 0;
+ ptr = message;
+ }
+ TInt irq = NKern::DisableAllInterrupts();
+ if (iLogToFile)
+ {
+ DWORD bytes;
+ WriteFile(DebugOutput(), ptr, len, &bytes, NULL);
+ }
+ if (iLogToDebugger)
+ {
+ OutputDebugStringA(message);
+ }
+
+ NKern::RestoreInterrupts(irq);
+ }
+
+const char* const KErrorTitles[] =
+ {
+ "Symbian OS Fatal Error",
+ "Symbian OS Application Error"
+ };
+
+const TText8* const KErrorMsg[] =
+ {
+ _S8("An error has been detected in the Symbian OS emulator."),
+ _S8("A call to User::Panic() has occured, indicating\n"
+ "a programming fault in the running application.\n"
+ "Please refer to the documentation for more details.")
+ };
+
+_LIT8(KProgram, "\n\nProgram\t");
+_LIT8(KError, "\nError\t");
+_LIT8(KIDFC, "an IDFC");
+_LIT8(KEscaped, "an escaped thread");
+_LIT8(KInterrupt, "an interrupt thread");
+_LIT8(KNThread, "an NThread");
+_LIT8(KColon, " : ");
+_LIT8(KDebugQuery, "\n\nDo you wish to Debug the error?\0");
+
+TBool Wins::ErrorDialog(TError aType, const TDesC8& aPanic, TInt aVal)
+ {
+ // Must be called with interrupts enabled to allow thread running windows message loop to run
+
+ TBuf8<512> message(KErrorMsg[aType]);
+ message.Append(KProgram);
+ TInt context = NKern::CurrentContext();
+ switch(context)
+ {
+ case NKern::EIDFC:
+ message.Append(KIDFC);
+ break;
+ case NKern::EEscaped:
+ message.Append(KEscaped);
+ break;
+ case NKern::EInterrupt:
+ message.Append(KInterrupt);
+ break;
+ case NKern::EThread:
+ DThread *thread = Kern::NThreadToDThread(NKern::CurrentThread());
+ if (thread)
+ thread->TraceAppendFullName(message, ETrue);
+ else
+ message.Append(KNThread);
+ break;
+ }
+ message.Append(KError);
+ message.Append(aPanic);
+ message.Append(KColon);
+ message.AppendNum(aVal);
+#ifdef _DEBUG
+ message.Append(KDebugQuery);
+ UINT type = MB_YESNO | MB_DEFBUTTON2;
+#else
+ UINT type = MB_OK;
+#endif
+ type |= MB_SETFOREGROUND | MB_ICONERROR;
+ message.Append('\0');
+
+ TInt r = MessageBoxA(iUi ? iUi->HWnd() : NULL, (LPCSTR)message.Ptr(), KErrorTitles[aType], type);
+ return r == IDYES;
+ }
+
+// UI installation
+
+EXPORT_C DWinsUiBase::DWinsUiBase()
+ {
+ TheVariant.InstallUi(*this);
+ }
+
+
+TInt BinaryPowerInit();
+
+DWinsPowerController* DWinsPowerController::New()
+ {
+ DWinsPowerController* self = new DWinsPowerController();
+ if (!self)
+ return NULL;
+ self->iStandbySem = CreateSemaphore(NULL, 0, 1, NULL);
+ if (self->iStandbySem == NULL)
+ return NULL;
+ TInt r = BinaryPowerInit();
+ if (r != KErrNone)
+ return NULL;
+ self->Register();
+ return self;
+ }
+
+void DWinsPowerController::CpuIdle()
+ {
+ Arch::TheAsic()->Idle();
+ }
+
+void DWinsPowerController::EnableWakeupEvents()
+ {
+ iWakeupSignal = EFalse;
+ }
+
+void DWinsPowerController::DisableWakeupEvents()
+ {
+ }
+
+void DWinsPowerController::AbsoluteTimerExpired()
+ {
+ if (iTargetState == EPwStandby)
+ DWinsPowerController::WakeupEvent();
+ }
+
+void DWinsPowerController::WakeupEvent()
+ {
+ if (iTargetState == EPwStandby)
+ {
+ iWakeupSignal = ETrue;
+ DPowerController::WakeupEvent();
+ }
+ }
+
+// called in Epoc thread
+void DWinsPowerController::PowerDown(TTimeK aWakeupTime)
+ {
+ if (iTargetState == EPwStandby)
+ {
+ UINT timeoutMs;
+ if (aWakeupTime == 0)
+ timeoutMs = INFINITE;
+ else
+ {
+ TTimeK now = Kern::SystemTime();
+ if (now > aWakeupTime)
+ timeoutMs = 0;
+ else
+ timeoutMs = (UINT)((aWakeupTime - now) / 1000);
+ }
+ TInt l = NKern::DisableAllInterrupts();
+ if (!iWakeupSignal && timeoutMs)
+ {
+ iStandby = ETrue;
+ TheVariant.iTimer.Standby();
+ NKern::RestoreInterrupts(l);
+ DWORD r = WaitForSingleObject(iStandbySem, timeoutMs);
+ if (r == WAIT_TIMEOUT)
+ {
+ l = NKern::DisableAllInterrupts();
+ if (!iStandby)
+ WaitForSingleObject(iStandbySem, INFINITE);
+ else
+ iStandby = EFalse;
+ NKern::RestoreInterrupts(l);
+ }
+ TheVariant.iTimer.Wakeup();
+ }
+ else
+ NKern::RestoreInterrupts(l);
+
+ }
+ else
+ Kern::Restart(0x80000000);
+ }
+
+// called in the interrupt context
+void DWinsPowerController::AssertWakeupSignal()
+ {
+ iWakeupSignal = ETrue;
+ if (iStandby)
+ {
+ iStandby = EFalse;
+ ReleaseSemaphore(iStandbySem, 1, NULL);
+ }
+ }
+
+
+EXPORT_C void Wins::AssertWakeupSignal()
+ {
+ iPowerController->AssertWakeupSignal();
+ }
+
+EXPORT_C void Wins::WakeupEvent()
+ {
+ iPowerController->DWinsPowerController::WakeupEvent();
+ }
+
+// MMC emulation support
+
+TBool Wins::MediaDoorOpen;
+TInt Wins::CurrentPBusDevice;
+TAny* Wins::MediaChangeCallbackParam;
+TMediaChangeCallBack Wins::MediaChangeCallBackPtr;
+
+
+EXPORT_C TBool* Wins::MediaDoorOpenPtr()
+//
+// For media change simulation
+//
+ {
+
+ return(&MediaDoorOpen);
+ }
+
+EXPORT_C TInt* Wins::CurrentPBusDevicePtr()
+//
+// For media change simulation
+//
+ {
+
+ return(&CurrentPBusDevice);
+ }
+
+EXPORT_C void Wins::SetMediaChangeCallBackPtr(TMediaChangeCallBack aPtr, TAny* aMediaChangeCallbackParam)
+//
+// For media change simulation
+//
+ {
+ MediaChangeCallbackParam=aMediaChangeCallbackParam;
+ MediaChangeCallBackPtr=aPtr;
+ }
+
+EXPORT_C void Wins::MediaChangeCallBack()
+//
+// Perform the simulated media change callback
+//
+ {
+ if(MediaChangeCallBackPtr)
+ (*MediaChangeCallBackPtr)(MediaChangeCallbackParam);
+ }