EXTERN_C VOID WINAPI PlatformResumeSystem (void) { SETFNAME (_T ("PlatformResumeSystem")); PMLOGMSG (ZONE_RESUME, (_T ("+%s: suspend flag is %d\r\n"), pszFname, gfSystemSuspended)); // Was this an unexpected resume event? If so, there may be a thread priority problem // or some piece of software suspended the system without calling SetSystemPowerState(). DEBUGCHK (gfSystemSuspended); if (!gfSystemSuspended) { // Unexpected resume -- go to the resuming state. This should not happen unless // somebody is illegally calling PowerOffSystem() directly. PMLOGMSG (ZONE_WARN || ZONE_RESUME, (_T ("%s: WARNING: unexpected resume!\r\n"), pszFname)); // Go into the new state. OEMs that choose to support unexpected resumes may want to // lock PM variables with PMLOCK(), then set the curDx and actualDx values for all // devices to PwrDeviceUnspecified before calling PmSetSystemPowerState_I(). This will // force an update IOCTL to all devices. DEBUGCHK (ghevRestartTimers != NULL); SetEvent (ghevRestartTimers); } else { DWORD dwWakeSource, dwBytesReturned; BOOL fOk; // Get the system wake source to help determine which power state we resume into: fOk = KernelIoControl (IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0, &dwWakeSource, sizeof (dwWakeSource), &dwBytesReturned); if (fOk) { // IOCTL succeeded (not all platforms necessarily support it), but sanity check // the return value, just in case. if (dwBytesReturned != sizeof (dwWakeSource)) { PMLOGMSG (ZONE_WARN, (_T ("%s: KernelIoControl() returned an invalid size %d\r\n"), pszFname, dwBytesReturned)); } else { // Look for an activity timer corresponding to this wake source. PACTIVITY_TIMER pat = ActivityTimerFindByWakeSource (dwWakeSource); if (pat != NULL) { PMLOGMSG (ZONE_RESUME, (_T ("%s: signaling '%s' activity at resume\r\n"), pszFname, pat->pszName)); // Is there an activity timer we need to reset? if (pat->hevReset != NULL) { // Found a timer, elevate the timer management priority thread so that it // executes before the suspending thread. DWORD dwOldPriority = CeGetThreadPriority (ghtActivityTimers); DWORD dwNewPriority = (CeGetThreadPriority (GetCurrentThread ()) - 1); DEBUGCHK (dwNewPriority >= 0); SetEvent (pat->hevReset); CeSetThreadPriority (ghtActivityTimers, dwNewPriority); CeSetThreadPriority (ghtActivityTimers, dwOldPriority); } } } } } PMLOGMSG (ZONE_RESUME, (_T ("-%s\r\n"), pszFname)); }
void S3C2450DISP::SetVisibleSurface( GPESurf *pTempSurf, BOOL bWaitForVBlank) { static int timeoutcnt=0; DWORD we; #ifdef HIGH_PRIORITY_INTR int iPriority; HANDLE hThread; hThread = GetCurrentThread(); iPriority = CeGetThreadPriority(hThread); CeSetThreadPriority(hThread, DISPDRV_IST_PRIORITY); #endif S3C2450Surf *pSurf = (S3C2450Surf *) pTempSurf; EnterCriticalSection(&m_CS); // assume Synchronous to VSYNC EnableInterrupt(); we = WaitForSingleObject(m_hVSYNCInterruptEvent,1000/*INFINITE*/); DisableInterrupt(); InterruptDone(m_dwVSYNCSysIntr); if(we != WAIT_OBJECT_0) { timeoutcnt++; RETAILMSG(1,(TEXT("Surface Flipping Time Out %d !!!\n"), timeoutcnt)); for(int i=0;i<78;i++) RETAILMSG(1,(TEXT("0x%08X = 0x%08X\n"),(DWORD*)((DWORD*)m_pLCDReg + i),*(DWORD*)((DWORD*)m_pLCDReg + i))); RETAILMSG(1,(TEXT("saved_x=%d"),saved_x)); RETAILMSG(1,(TEXT("saved_y=%d"),saved_y)); RETAILMSG(1,(TEXT("saved_width=%d"),saved_width)); RETAILMSG(1,(TEXT("saved_height=%d"),saved_height)); while(1); } if(pSurf->m_bIsOverlay == FALSE) { //RETAILMSG(1,(TEXT("pSurf->OffsetInVideoMemory()=0x%08X\n"),pSurf->OffsetInVideoMemory())); m_pVisibleSurface = pSurf; m_pLCDReg->VIDW00ADD0B0 = (UINT32)(pSurf->OffsetInVideoMemory() + IMAGE_FRAMEBUFFER_DMA_BASE); // buffer end address m_pLCDReg->VIDW00ADD1B0 = (UINT32)(pSurf->OffsetInVideoMemory() + IMAGE_FRAMEBUFFER_DMA_BASE) + (LCD_XSIZE_TFT*LCD_YSIZE_TFT*2); // buffer size m_pLCDReg->VIDW00ADD2B0 = (0<<VIDWxADD2_OFFSET_SIZE_S)|(LCD_XSIZE_TFT*2); } else { m_pLCDReg->VIDW01ADD0 = (UINT32)(pSurf->OffsetInVideoMemory() + IMAGE_FRAMEBUFFER_DMA_BASE); // buffer end address m_pLCDReg->VIDW01ADD1 = (UINT32)(pSurf->OffsetInVideoMemory() + IMAGE_FRAMEBUFFER_DMA_BASE) + (pSurf->Width()*pSurf->Height()*2); // buffer size m_pLCDReg->VIDW01ADD2 = (0<<VIDWxADD2_OFFSET_SIZE_S)|(pSurf->Width()*2); } RETAILMSG(DBGLCD, (TEXT("S3C2450DISP::SetVisibleSurface\r\n"))); LeaveCriticalSection(&m_CS); #ifdef HIGH_PRIORITY_INTR CeSetThreadPriority(hThread, iPriority); #endif }
EXTERN_C DWORD WINAPI PlatformSetSystemPowerState (LPCTSTR pszName, BOOL fForce, BOOL fInternal) { DWORD dwStatus = ERROR_SUCCESS; PSYSTEM_POWER_STATE pNewSystemPowerState = NULL; PDEVICE_POWER_RESTRICTION pNewCeilingDx = NULL; BOOL fDoTransition = FALSE; INT iPreSuspendPriority = 0; static BOOL fFirstCall = TRUE; SETFNAME (_T ("PlatformSetSystemPowerState")); // Read system power state variables and construct new lists: if (gfFileSystemsAvailable) PmUpdateSystemPowerStatesIfChanged (); dwStatus = RegReadSystemPowerState (pszName, &pNewSystemPowerState, &pNewCeilingDx); // Did we get registry information about the new power state? if (dwStatus == ERROR_SUCCESS) { BOOL fSuspendSystem = FALSE; static BOOL fWantStartupScreen = FALSE; DWORD dwNewStateFlags = pNewSystemPowerState->dwFlags; // Assume we will update the system power state: fDoTransition = TRUE; // Are we going to suspend the system as a whole? if ((dwNewStateFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL | POWER_STATE_RESET)) != 0) { fSuspendSystem = TRUE; } // A "critical" suspend might mean we have totally lost battery power and need // to suspend really quickly. Depending on the platform, OEMs may be able // to bypass driver notification entirely and rely on xxx_PowerDown() notifications // to suspend gracefully. Or they may be able to implement a critical suspend // kernel ioctl. This sample implementation is very generic and simply sets the // POWER_FORCE flag, which is not used. if (dwNewStateFlags & (POWER_STATE_CRITICAL | POWER_STATE_OFF | POWER_STATE_RESET)) { fForce = TRUE; } // If everything seems OK, do the set operation: if (fDoTransition) { POWER_BROADCAST_BUFFER pbb; PDEVICE_LIST pdl; BOOL fResumeSystem = FALSE; // Send out system power state change notifications: pbb.Message = PBT_TRANSITION; pbb.Flags = pNewSystemPowerState->dwFlags; pbb.Length = _tcslen (pNewSystemPowerState->pszName) + 1; // Char count not byte count for now if (pbb.Length > MAX_PATH) { // Truncate the system power state name -- note, we actually have MAX_PATH + 1 // characters available. pbb.Length = MAX_PATH; } _tcsncpy_s (pbb.SystemPowerState, _countof (pbb.SystemPowerState), pNewSystemPowerState->pszName, pbb.Length); pbb.Length *= sizeof (pbb.SystemPowerState[0]); // Convert to byte count GenerateNotifications ((PPOWER_BROADCAST) & pbb); // Is GWES ready? if (!gfGwesReady) { if (WaitForAPIReady (SH_GDI, 0) == WAIT_OBJECT_0) { gfGwesReady = TRUE; } } // Are we suspending? if (fSuspendSystem && gpfnGwesPowerDown != NULL) { // Start the process of suspending GWES: if (gfGwesReady) { fWantStartupScreen = gpfnGwesPowerDown (); } } // Update global system state variables: PMLOCK (); PSYSTEM_POWER_STATE pOldSystemPowerState = gpSystemPowerState; PDEVICE_POWER_RESTRICTION pOldCeilingDx = gpCeilingDx; if (gpSystemPowerState != NULL && (gpSystemPowerState-> dwFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL)) != 0) { // We are exiting a suspended state: fResumeSystem = TRUE; } gpSystemPowerState = pNewSystemPowerState; gpCeilingDx = pNewCeilingDx; PMUNLOCK (); // Are we suspending, resuming, or neither? if (fSuspendSystem) { INT iCurrentPriority; // We're suspending: update all devices other than block devices, // in case any of them need to access the registry or write files. PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: suspending - notifying non-block drivers\r\n"), pszFname)); for (pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) { if (*pdl->pGuid != idBlockDevices) { UpdateClassDeviceStates (pdl); } } // Notify the kernel that we are about to suspend. This gives the // kernel an opportunity to clear wake source flags before we initiate // the suspend process. If we don't do this and a wake source interrupt // occurs between the time we call PowerOffSystem() and the time // OEMPowerOff() is invoked, it is hard for the kernel to know whether or // not to suspend. PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: calling KernelIoControl(IOCTL_HAL_PRESUSPEND)\r\n"), pszFname)); KernelIoControl (IOCTL_HAL_PRESUSPEND, NULL, 0, NULL, 0, NULL); iCurrentPriority = CeGetThreadPriority (GetCurrentThread ()); DEBUGCHK (iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN); if (iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN) { CeSetThreadPriority (GetCurrentThread (), giPreSuspendPriority); Sleep (0); CeSetThreadPriority (GetCurrentThread (), iCurrentPriority); } // Notify file systems that their block drivers will soon go away. // After making this call, this thread is the only one that can access // the file system (including registry and device drivers) without // blocking. Unfortunately, this API takes and holds the file system // critical section, so other threads attempting to access the registry // or files may cause priority inversions. To avoid priority problem // that may starve the Power Manager, we may raise our own priority to a // high level. Do this if giSuspendPriority is non-zero. if (giSuspendPriority != 0) { iPreSuspendPriority = CeGetThreadPriority (GetCurrentThread ()); DEBUGCHK (iPreSuspendPriority != THREAD_PRIORITY_ERROR_RETURN); PMLOGMSG (ZONE_PLATFORM, (_T ("%s: suspending: raising thread priority for 0x%08x from %d to %d\r\n"), pszFname, GetCurrentThreadId (), iPreSuspendPriority, giSuspendPriority)); CeSetThreadPriority (GetCurrentThread (), giSuspendPriority); } // Discard code pages from drivers. This is a diagnostic tool to // forcibly expose paging-related bugs that could cause apparently // random system crashes or hangs. Optionally, OEMs can disable this // for production systems to speed up resume times. We have to call // PageOutMode before FileSys Shutdown. Otherwise, it cause dead lock // between filesystem and loader. if (gfPageOutAllModules) { ForcePageout (); } if (g_pSysRegistryAccess) g_pSysRegistryAccess->EnterLock (); gfFileSystemsAvailable = FALSE; if ((dwNewStateFlags & POWER_STATE_RESET) != 0) { // Is this to be a cold boot? if (_tcscmp (pszName, _T ("coldreboot")) == 0) { SetCleanRebootFlag (); } } FileSystemPowerFunction (FSNOTIFY_POWER_OFF); // Update block device power states: PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: suspending - notifying block drivers\r\n"), pszFname)); pdl = GetDeviceListFromClass (&idBlockDevices); if (pdl != NULL) { UpdateClassDeviceStates (pdl); } // Handle resets and shutdowns here, after flushing files. Since Windows CE does // not define a standard mechanism for handling shutdown (via POWER_STATE_OFF), // OEMs will need to fill in the appropriate code here. Similarly, if an OEM does // not support IOCTL_HAL_REBOOT, they should not support POWER_STATE_RESET. if ((dwNewStateFlags & POWER_STATE_RESET) != 0) { // Should not return from this call, but if we do just suspend the system: KernelLibIoControl ((HANDLE) KMOD_OAL, IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL); RETAILMSG (TRUE, (_T ("PM: PlatformSetSystemPowerState: KernelIoControl(IOCTL_HAL_REBOOT) returned!\r\n"))); DEBUGCHK (FALSE); // Break into the debugger. } } else if (fResumeSystem) { // We're waking up from a resume -- update block device power states // so we can access the registry and/or files. PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: resuming - notifying block drivers\r\n"), pszFname)); pdl = GetDeviceListFromClass (&idBlockDevices); if (pdl != NULL) { UpdateClassDeviceStates (pdl); } // Notify file systems that their block drivers are back. FileSystemPowerFunction (FSNOTIFY_POWER_ON); gfFileSystemsAvailable = TRUE; if (g_pSysRegistryAccess) g_pSysRegistryAccess->LeaveLock (); // Update all devices other than block devices: PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: resuming - notifying block drivers\r\n"), pszFname)); for (pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) { if (*pdl->pGuid != idBlockDevices) { UpdateClassDeviceStates (pdl); } } // Tell GWES to wake up: if (gpfnGwesPowerUp != NULL && gfGwesReady) { gpfnGwesPowerUp (fWantStartupScreen); fWantStartupScreen = FALSE; } // Send out resume notification: pbb.Message = PBT_RESUME; pbb.Flags = 0; pbb.Length = 0; pbb.SystemPowerState[0] = 0; GenerateNotifications ((PPOWER_BROADCAST) & pbb); } else { // Update all devices without any particular ordering: UpdateAllDeviceStates (); } // Release the old state information: SystemPowerStateDestroy (pOldSystemPowerState); while (pOldCeilingDx != NULL) { PDEVICE_POWER_RESTRICTION pdpr = pOldCeilingDx->pNext; PowerRestrictionDestroy (pOldCeilingDx); pOldCeilingDx = pdpr; } // Are we suspending? if (fSuspendSystem) { // Set a flag to notify the resume thread that this was a controlled suspend. gfSystemSuspended = TRUE; PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: calling PowerOffSystem()\r\n"), pszFname)); PowerOffSystem (); // Sets a flag in the kernel for the scheduler. Sleep (0); // Force the scheduler to run. PMLOGMSG (ZONE_PLATFORM || ZONE_RESUME, (_T ("%s: back from PowerOffSystem()\r\n"), pszFname)); // Clear the suspend flag: gfSystemSuspended = FALSE; } } else { // Release the unused new state information: SystemPowerStateDestroy (pNewSystemPowerState); while (pNewCeilingDx != NULL) { PDEVICE_POWER_RESTRICTION pdpr = pNewCeilingDx->pNext; PowerRestrictionDestroy (pNewCeilingDx); pNewCeilingDx = pdpr; } } } // Restore our priority if we updated it during a suspend transition: if (giSuspendPriority != 0 && iPreSuspendPriority != 0) { PMLOGMSG (ZONE_PLATFORM, (_T ("%s: restoring thread priority to %d\r\n"), pszFname, iPreSuspendPriority)); CeSetThreadPriority (GetCurrentThread (), iPreSuspendPriority); } return dwStatus; }