📄 pwrbutton.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/* Copyright 1999,2000,2001 Intel Corp. */
/*++
Module Name:
pwrbutton.c
Abstract:
This module is intended as a home for threads that monitor and manage platform features.
Intial implementation was for for monitoring SW21 on a Mainstone platform which is used
to trigger SUSPEND/RESUME.
Notes:
--*/
#include <windows.h>
#include <windev.h>
#include <pm.h>
#include <bsp.h>
#include <xllp_pm.h>
#define SIZEOFARRAY(a) (sizeof(a) / sizeof(a[0]))
#define QUEUE_ENTRIES 16
#define MAX_NAMELEN 64
#define QUEUE_SIZE (QUEUE_ENTRIES*(sizeof(POWER_BROADCAST)+MAX_NAMELEN))
#define BULVERDE_BASE_REG_PA_PWRMGR 0x40F00000
#define MSCWR3_BIT_GPIO_RESET (1<<1)
#define MSCWR3_BIT_GPIO_RESET_EN (1<<2)
//volatile MAINSTONEII_BLR_REGS *g_pBCRRegs = NULL;
BOOL g_FlagExitThrd = FALSE;
UINT32 g_Irq = IRQ_GPIO1;
UINT32 g_SysIntr = SYSINTR_PWRBTN;
HANDLE g_ButtonEvent = NULL;
HANDLE g_ButtonThread = NULL;
HANDLE g_PwrMonThread = NULL;
HANDLE m_hReadMsgQ = NULL;
// Power state monitor thread
INT WINAPI PwrMonThread(void)
{
HANDLE hNotifications;
MSGQUEUEOPTIONS msgOptions = {0};
// Create a message queue for Power Manager notifications.
msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
msgOptions.dwFlags = 0;
msgOptions.dwMaxMessages = QUEUE_ENTRIES;
msgOptions.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
msgOptions.bReadAccess = TRUE;
m_hReadMsgQ = CreateMsgQueue(NULL, &msgOptions);
if ( m_hReadMsgQ == NULL )
{
DEBUGMSG(1, (TEXT("PWM: CreateMsgQueue(Read): error %d\r\n"), GetLastError()));
g_FlagExitThrd = TRUE;
}
// Request Power notifications
hNotifications = RequestPowerNotifications(m_hReadMsgQ, POWER_NOTIFY_ALL);
if ( ! hNotifications )
{
DEBUGMSG(1, (TEXT("PWM: RequestPowerNotifications: error %d\r\n"), GetLastError()));
g_FlagExitThrd = TRUE;
}
while(!g_FlagExitThrd)
{
int iBytesInQueue = 0;
DWORD dwFlags;
UCHAR buf[QUEUE_SIZE];
PPOWER_BROADCAST pB = (PPOWER_BROADCAST) buf;
memset(buf, 0, QUEUE_SIZE);
DEBUGMSG(1, (TEXT("PWM: Waiting for PM state transition notification\r\n")));
// Read message from queue.
if ( ! ReadMsgQueue(m_hReadMsgQ, buf, QUEUE_SIZE, &iBytesInQueue, INFINITE, &dwFlags) )
{
if(g_FlagExitThrd)
break;
DEBUGMSG(1, (TEXT("PWM: ReadMsgQueue: ERROR:%d\r\n"), GetLastError()));
}
else if ( iBytesInQueue < sizeof(POWER_BROADCAST) )
{
DEBUGMSG(1, (TEXT("PWM: Received short message: %d bytes, expected: %d\r\n"),
iBytesInQueue, sizeof(POWER_BROADCAST)));
}
else
{
switch ( pB->Message )
{
case PBT_TRANSITION:
RETAILMSG(1, (TEXT("PWM: PBT_TRANSITION to system power state [Flags: 0x%x]: '%s'\r\n"),
pB->Flags, pB->SystemPowerState));
switch ( POWER_STATE(pB->Flags) )
{
case POWER_STATE_ON:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_ON\r\n")));
break;
case POWER_STATE_OFF:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_OFF\r\n")));
break;
case POWER_STATE_CRITICAL:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_CRITICAL\r\n")));
break;
case POWER_STATE_BOOT:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_BOOT\r\n")));
break;
case POWER_STATE_IDLE:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_IDLE\r\n")));
break;
case POWER_STATE_SUSPEND:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_SUSPEND\r\n")));
break;
case POWER_STATE_RESET:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_RESET\r\n")));
break;
case POWER_STATE_PASSWORD:
DEBUGMSG(1, (TEXT("PWM: POWER_STATE_PASSWORD\r\n")));
break;
case 0:
DEBUGMSG(1,(TEXT("PWM: Power State Flags:0x%x\r\n"),pB->Flags));
break;
default:
DEBUGMSG(1,(TEXT("PWM: Unknown Power State Flags:0x%x\r\n"),pB->Flags));
break;
}
break;
case PBT_RESUME:
{
RETAILMSG(1, (TEXT("PWM: PBT_RESUME\r\n")));
// If GPIO1 resumed the system set the system state to ON
{
DWORD wakeSrc = SYSWAKE_UNKNOWN;
DWORD bytesRet= 0;
if (KernelIoControl(IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0, &wakeSrc, sizeof(wakeSrc), &bytesRet) &&
(bytesRet == sizeof(wakeSrc))) {
if (SYSINTR_PWRBTN == wakeSrc) {
SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
}
}
else {
NKDbgPrintfW(L"PWM: Error getting wake source\r\n");
}
}
break;
}
case PBT_POWERSTATUSCHANGE:
RETAILMSG(1, (TEXT("PWM: PBT_POWERSTATUSCHANGE\r\n")));
break;
case PBT_POWERINFOCHANGE:
{
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;
RETAILMSG(1, (TEXT("PWM: PBT_POWERINFOCHANGE\r\n")));
RETAILMSG(1, (TEXT("PWM: \tAC line status %u, battery flag %u, backup flag %u, %d levels\r\n"),
ppbpi->bACLineStatus, ppbpi->bBatteryFlag,
ppbpi->bBackupBatteryFlag, ppbpi->dwNumLevels));
break;
}
default:
DEBUGMSG(1, (TEXT("PWM: Unknown Message:%d\r\n"), pB->Message));
break;
}
}
}
if ( hNotifications )
{
StopPowerNotifications(hNotifications);
hNotifications = NULL;
}
if ( m_hReadMsgQ )
{
CloseMsgQueue(m_hReadMsgQ);
m_hReadMsgQ = NULL;
}
DEBUGMSG(1, (TEXT("PWM: PwrMonThread Exiting\r\n")));
return 0;
}
// Power Button event thread
INT WINAPI ButtonThread(void)
{
DWORD dwPwrFlags;
TCHAR szPowerState[MAX_PATH];
// Mainstone II general purpose switch settings
UINT32 dwGPSWR = 0;
while(!g_FlagExitThrd)
{
WaitForSingleObject(g_ButtonEvent, INFINITE);
if(g_FlagExitThrd)
break;
// Delay 250ms and get switch settings. Will suspend or reset the device
// if stays in the position for longer than 250ms.
// dwGPSWR = g_pBCRRegs->gpsw;
if(dwGPSWR & SW21_MASK)
{
// If any of the additional boot switch is sPBT_TRANSITIONet, reboot the device, else suspend.
if(dwGPSWR & (CLEAN_BOOT_FLAG | HIVE_CLEAN_FLAG | FORMAT_PART_FLAG))
{
RETAILMSG(1, (TEXT("Reboot\r\n")));
// Suspend the device
SetSystemPowerState(NULL, POWER_STATE_RESET, POWER_FORCE);
// Should not come back. Failed if it gets here.
RETAILMSG(1, (TEXT("Reboot failed\r\n")));
}
else
{
// Suspend the device
SetSystemPowerState(NULL, POWER_STATE_SUSPEND, 0);
// ZZZzzzz.....
//Note: After system resumes, PwrMonThread (PBT_RESUME) will set the system to 'ON' state
}
}
else
{
// Back to "on" state if we are in "unattaneded" mode or "screenoff" mode.
GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
if((wcscmp(szPowerState,L"unattended")==0) || (wcscmp(szPowerState,L"screenoff")==0))
{
// We are in"unattended" or "screenoff" mode. Go back to "on" state.
SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);
// Block until the system is back to the "on" state.
do
{
Sleep(10);
GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
DEBUGMSG(1, (TEXT("PWB: Power State: '%s'\r\n"), szPowerState));
} while(!(POWER_STATE(dwPwrFlags) & POWER_STATE_ON));
}
}
InterruptDone(g_SysIntr);
}
DEBUGMSG(1, (TEXT("PWB: PwrButtonThread Exiting\r\n")));
return 0;
} // PWB_ButtonThread()
BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DEBUGMSG(1, (TEXT("DllEntry: DLL_PROCESS_ATTACH (PID=x%08x)\r\n"), GetCurrentProcessId()));
// don't need thread attach/detach messages
DisableThreadLibraryCalls ((HMODULE)hInstDll);
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(1, (TEXT("DllEntry: DLL_PROCESS_DETACH (PID=x%08x)\r\n"), GetCurrentProcessId()));
break;
}
return (TRUE);
}
VOID PWB_PowerUp(VOID)
{
DEBUGMSG(1, (TEXT("PWB_PowerUp:\r\n")));
// GPIO1 follows SW21
//
// g_pBCRRegs->misc_wr3 &= ~MSCWR3_BIT_GPIO_RESET_EN;
return;
} // PWB_PowerUp
BOOL PWB_PowerDown(VOID)
{
DEBUGMSG(1, (TEXT("PWB_PowerDown:\r\n")));
return(TRUE);
} // PWB_PowerDown
void PWB_UnMapAddresses(void)
{
/* if(g_pBCRRegs)
{
MmUnmapIoSpace((void*)g_pBCRRegs, 0);
g_pBCRRegs = NULL;
}*/
return;
}
BOOL PWB_MapAddresses(void)
{
/* if (g_pBCRRegs==NULL)
{
PHYSICAL_ADDRESS PA = { MAINSTONEII_BASE_REG_PA_FPGA, 0 };
g_pBCRRegs =(MAINSTONEII_BLR_REGS *) MmMapIoSpace(PA, sizeof(MAINSTONEII_BLR_REGS), FALSE);
}
if(!g_pBCRRegs)
{
goto CleanUp;
}
*/
return TRUE;
CleanUp:
DEBUGMSG(1, (TEXT("PWB_InitializeAddresses Failed\r\n")));
PWB_UnMapAddresses();
return FALSE;
}
BOOL PWB_Deinit(DWORD p1)
{
DEBUGMSG(1, (TEXT("PWB_DeInit(x%08x):\r\n"), p1));
g_FlagExitThrd = TRUE;
if(g_ButtonEvent)
{
SetEvent(g_ButtonEvent);
InterruptDisable(g_SysIntr);
CloseHandle(g_ButtonEvent);
}
// Signal PwrMonThread to finish (closing the handle will force ReadMsgQueue to return)
if ( m_hReadMsgQ )
{
CloseMsgQueue(m_hReadMsgQ);
m_hReadMsgQ = NULL;
}
// Wait for threads to finish
WaitForSingleObject(g_ButtonThread, INFINITE);
WaitForSingleObject(g_PwrMonThread, INFINITE);
if(g_ButtonThread)
CloseHandle(g_ButtonThread);
if(g_PwrMonThread)
CloseHandle(g_PwrMonThread);
PWB_UnMapAddresses();
return (TRUE);
}
DWORD PWB_Init(DWORD p1, DWORD p2)
{
BOOL result;
DEBUGMSG(1, (TEXT("PWB_Init(x%08x,x%08x):\r\n"), p1, p2));
if (!PWB_MapAddresses())
{
DEBUGMSG(1, (TEXT("PWB_Init: PWB_InitializeAddresses Failed\r\n")));
goto CleanUp;
}
g_ButtonEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if( !g_ButtonEvent)
{
DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Intterupt Event\r\n")));
goto CleanUp;
}
result = InterruptInitialize(g_SysIntr, g_ButtonEvent, NULL, 0);
if(!result)
{
DEBUGMSG(1, (TEXT("InterruptInitialize() failed. GetLastError=0x%x\r\n"),GetLastError()));
goto CleanUp;
}
g_ButtonThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ButtonThread, NULL, 0, NULL);
if ( g_ButtonThread == NULL )
{
DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Button Intterupt Thread\r\n")));
goto CleanUp;
}
g_PwrMonThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PwrMonThread, NULL, 0, NULL);
if ( g_PwrMonThread == NULL )
{
DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Power Monitor Thread\r\n")));
goto CleanUp;
}
PWB_PowerUp();
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &g_SysIntr, sizeof(g_SysIntr), NULL, 0, NULL);
DEBUGMSG(1, (TEXT("PWB_Init: Success\r\n")));
return(TRUE);
CleanUp:
PWB_Deinit(0);
return (FALSE);
}
DWORD PWB_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
DEBUGMSG(1, (TEXT("PWB_Open:\r\n")));
return(0x12345678);
}
BOOL PWB_Close(DWORD dwData)
{
DEBUGMSG(1, (TEXT("PWB_Close:\r\n")));
return (TRUE);
}
DWORD PWB_Read (DWORD dwData, LPVOID pBuf, DWORD Len)
{
return (0);
}
DWORD PWB_Write(DWORD dwData, LPCVOID pBuf, DWORD Len)
{
return (0);
}
DWORD PWB_Seek (DWORD dwData, long pos, DWORD type)
{
return (DWORD)-1;
}
BOOL PWB_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -