📄 ioctl.c
字号:
// Copyright (c) David Vescovi. All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//
// File: ioctl.c
//
// This file implements the OEM's IO Control (IOCTL) functions and declares
// global variables used by the IOCTL component.
//
//------------------------------------------------------------------------------
#include <bsp.h>
#include <devload.h>
#define IS_ALIGNED(x) ((((UINT32)(x)) & 0x3) ? FALSE : TRUE)
extern void FreqChange(BOOL turbo);
//------------------------------------------------------------------------------
//
// Global: g_oalIoctlPlatformType/OEM
//
// Platform Type/OEM
//
LPCWSTR g_oalIoCtlPlatformType = IOCTL_PLATFORM_TYPE;
LPCWSTR g_oalIoCtlPlatformOEM = IOCTL_PLATFORM_OEM;
//------------------------------------------------------------------------------
//
// Global: g_oalIoctlProcessorVendor/Name/Core
//
// Processor information
//
LPCWSTR g_oalIoCtlProcessorVendor = IOCTL_PROCESSOR_VENDOR;
LPCWSTR g_oalIoCtlProcessorName = IOCTL_PROCESSOR_NAME;
LPCWSTR g_oalIoCtlProcessorCore = IOCTL_PROCESSOR_CORE;
//------------------------------------------------------------------------------
//
// Global: g_oalIoctlInstructionSet
//
// Processor instruction set identifier
//
UINT32 g_oalIoCtlInstructionSet = IOCTL_PROCESSOR_INSTRUCTION_SET;
UINT32 g_oalIoCtlClockSpeed = 0;
//------------------------------------------------------------------------------
//
// Global: g_oalIoctlHardware
//
UINT32 g_oalIoctlHardware = 0;
UINT32 g_oalIoctlBootloaderVer = 0;
UINT32 g_oalIoctlBootFlags = 0;
//------------------------------------------------------------------------------
//
// regions for registry persistent
// default assume 16M parts
static OAL_PERREG_REGION regions[] = {
{IMAGE_WINCE_PERREG_FLASH16M_PA_START, IMAGE_WINCE_PERREG_FLASH16M_PA_START, IMAGE_WINCE_PERREG_SIZE},
{0, 0, 0} // end of record
};
static BOOL SetDeviceDriverFlags(LPCWSTR szKeyPath, DWORD flags)
{
BOOL rc = FALSE;
HKEY hKey;
UINT32 value;
// Open/create key
if (NKRegCreateKeyEx(
HKEY_LOCAL_MACHINE, szKeyPath, 0, NULL, 0, 0, NULL,
&hKey, &value
) != ERROR_SUCCESS) goto cleanUp;
// Set value
rc = NKRegSetValueEx(
hKey, L"Flags", 0, REG_DWORD, (UCHAR*)&flags, sizeof(DWORD)
) == ERROR_SUCCESS;
// Close key
NKRegCloseKey(hKey);
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// External: ARMCacheInfo
//
// Processor cache information structure
//
extern const CacheInfo ARMCacheInfo;
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalGetCacheInfo
//
// This function returns information about the CPU's instruction and data caches.
//
BOOL OALIoCtlHalGetCacheInfo(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
// Validate caller's arguments.
//
if (!pOutBuffer || (outSize < sizeof(CacheInfo)))
{
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
return(FALSE);
}
// Copy the cache information into the caller's buffer.
//
memcpy(pOutBuffer, &ARMCacheInfo, sizeof(CacheInfo));
if (pOutSize) *pOutSize = sizeof(CacheInfo);
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalPostInit
//
// This function is the next OAL routine called by the kernel after OEMInit and
// provides a context for initializing other aspects of the device prior to
// general boot.
//
BOOL OALIoCtlHalPostInit(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
volatile CLK_REG_T *pCLKRegs = (volatile CLK_REG_T *)OALPAtoVA(PXA255_BASE_REG_PA_CLK, FALSE);
OALMSG(OAL_FUNC, (L"OALIoCtlHalPostInit+\r\n"));
//
// set the speed global
switch (pCLKRegs->CCCR & CCCR_M)
{
case CCCR_M1:
g_oalIoCtlClockSpeed = OEM_CLOCK_FREQ * 27 * 1;
break;
case CCCR_M2:
g_oalIoCtlClockSpeed = OEM_CLOCK_FREQ * 27 * 2;
break;
case CCCR_M4:
g_oalIoCtlClockSpeed = OEM_CLOCK_FREQ * 27 * 4;
break;
}
//
// set the hardware configuration global
g_oalIoctlHardware = *(UINT32 *) OALArgsQuery(BSP_ARGS_QUERY_HARDWARE);
//
// set the bootloader version global
g_oalIoctlBootloaderVer = *(UINT32 *) OALArgsQuery(BSP_ARGS_QUERY_BOOTLOADERVER);
//
// set the boot flags global
g_oalIoctlBootFlags = *(UINT32 *) OALArgsQuery(BSP_ARGS_QUERY_BOOTFLAGS);
if (g_oalIoctlHardware & GUMCFG_PERREG)
{
RETAILMSG(1,(TEXT("INFO: Using persistent registry\r\n")));
if (!(g_oalIoctlHardware & GUMCFG_XM))
{
regions[0].base = IMAGE_WINCE_PERREG_FLASH4M_PA_START;
regions[0].start = IMAGE_WINCE_PERREG_FLASH4M_PA_START;
}
if (BOOTFLAGS_REGCLEAN & *(UINT32 *) OALArgsQuery(BSP_ARGS_QUERY_BOOTFLAGS))
{
if (OALPerRegInit(TRUE, regions))
{
RETAILMSG(TRUE, (L"INFO: Booting clean registry\r\n"));
}
}
else
{
OALPerRegInit(FALSE, regions);
}
}
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalInitRegistry
//
// OALIoCtlHalInitRegistry signals that the registry is active and that data
// from the OAL can now be propagated to the registry.
//
BOOL OALIoCtlHalInitRegistry(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
DWORD dwHardwareConfiguration;
dwHardwareConfiguration = *(UINT32 *) OALArgsQuery(BSP_ARGS_QUERY_HARDWARE);
if (((dwHardwareConfiguration & GUMCFG_CF) && !(dwHardwareConfiguration & GUMCFG_WIFI)) ||
(!(dwHardwareConfiguration & GUMCFG_CF) && (dwHardwareConfiguration & GUMCFG_WIFI)))
{
SetDeviceDriverFlags(L"Drivers\\BuiltIn\\PCC_GUM1", DEVFLAGS_NOLOAD);
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalReboot
//
// This function hardware-reboots the platform.
//
BOOL OALIoCtlHalReboot(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)
{
OEMReset(); // will never return!
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalInitRTC
//
// This function is called by WinCE OS to initialize the time after boot.
// Input buffer contains SYSTEMTIME structure with default time value.
// If hardware has persistent real time clock it will ignore this value
// (or all call).
//
BOOL OALIoCtlHalInitRTC(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
SYSTEMTIME *pTime = (SYSTEMTIME*)pInpBuffer;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalInitRTC(...)\r\n"));
// Validate inputs
if (pInpBuffer == NULL || inpSize < sizeof(SYSTEMTIME)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalInitRTC: INVALID PARAMETER\r\n"
));
goto cleanUp;
}
rc = OEMSetRealTime(pTime);
cleanUp:
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OALIoCtlHalInitRTC(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalPhyAdr
//
// This function can be used to read/write physical address
// or more likely SOC registers.
//
BOOL OALIoCtlHalPhyAdr(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
BOOL IntrState;
PHYSETAdrInfo *pPHYSetAdrBuf;
PHYGETAdrInfo *pPHYGetAdrBuf;
volatile UINT32 *pReg;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalPhyAdr(...)\r\n"));
// Validate inputs
if (pInpBuffer == NULL || inpSize < sizeof(PHYGETAdrInfo)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr: INVALID PARAMETER\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
goto cleanUp;
}
pPHYGetAdrBuf = (PHYGETAdrInfo *) pInpBuffer;
//
// Check subcode
//
switch (pPHYGetAdrBuf->subcode) {
case PHY_GET_ADDR:
if (pInpBuffer == NULL || inpSize != sizeof(PHYGETAdrInfo))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr: INVALID PARAMETER\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
if (!pOutBuffer || (outSize < sizeof(UINT32)))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr:PHY_GET_ADDR INSUFFICIENT BUFFER\r\n"
));
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
break;
}
if (!IS_ALIGNED(pPHYGetAdrBuf->address))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr:PHY_GET_ADDR ADDRESS ALIGNMENT ERROR\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
pReg = (volatile UINT32 *) OALPAtoUA(pPHYGetAdrBuf->address);
if (pReg == NULL)
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr:PHY_GET_ADDR ADDRESS ERROR\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
*((UINT32 *)pOutBuffer) = *pReg;
if (pOutSize)
{
*pOutSize = sizeof(UINT32);
rc = TRUE;
}
break;
case PHY_SET_ADDR:
if (pInpBuffer == NULL || inpSize != sizeof(PHYSETAdrInfo))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr: INVALID PARAMETER\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
pPHYSetAdrBuf = (PHYSETAdrInfo *) pInpBuffer;
if (!IS_ALIGNED(pPHYSetAdrBuf->address))
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr:PHY_SET_ADDR ADDRESS ALIGNMENT ERROR\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
pReg = (volatile UINT32 *) OALPAtoUA(pPHYGetAdrBuf->address);
if (pReg == NULL)
{
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr:PHY_GET_ADDR ADDRESS ERROR\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
IntrState = INTERRUPTS_ENABLE(FALSE);
*pReg = (*pReg & ~pPHYSetAdrBuf->mask) | (pPHYSetAdrBuf->value & pPHYSetAdrBuf->mask);
INTERRUPTS_ENABLE(IntrState);
rc = TRUE;
break;
default:
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalPhyAdr: INVALID PARAMETER\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
break;
}
cleanUp:
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OALIoCtlHalPhyAdr(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalFcs
//
// This function can be used to initiate a Frequency Change Sequence (FCS).
//
BOOL OALIoCtlHalFcs(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
BOOL IntrState;
DWORD Turbo;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalFcs(...)\r\n"));
// Validate inputs
if (pInpBuffer == NULL || inpSize < 1) {
OALMSG(OAL_ERROR, (
L"ERROR: OALIoCtlHalFcs: INVALID PARAMETER\r\n"
));
NKSetLastError(ERROR_INVALID_PARAMETER);
goto cleanUp;
}
Turbo = (DWORD)(*(BYTE *)pInpBuffer);
IntrState = INTERRUPTS_ENABLE(FALSE);
FreqChange(Turbo); // do frequency change sequence
INTERRUPTS_ENABLE(IntrState);
rc = TRUE;
cleanUp:
return(rc);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalBootloaderVer
//
// This function can be used to retreave the boot loader version.
//
BOOL OALIoCtlHalBootloaderVer(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalBootloaderVer(...)\r\n"));
if (!pOutBuffer || (outSize < sizeof(UINT32)))
{
OALMSG(OAL_ERROR, (L"ERROR: OALIoCtlHalBootloaderVer: INSUFFICIENT BUFFER\r\n"));
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
{
*((UINT32 *)pOutBuffer) = g_oalIoctlBootloaderVer;
if (pOutSize)
{
*pOutSize = sizeof(UINT32);
rc = TRUE;
}
}
//cleanUp:
return(rc);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalHardwareConfig
//
// This function can be used to retreave the hardware configuration DWORD.
//
BOOL OALIoCtlHalHardwareConfig(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalHardwareConfig(...)\r\n"));
if (!pOutBuffer || (outSize < sizeof(UINT32)))
{
OALMSG(OAL_ERROR, (L"ERROR: OALIoCtlHalHardwareConfig: INSUFFICIENT BUFFER\r\n"));
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
{
*((UINT32 *)pOutBuffer) = g_oalIoctlHardware;
if (pOutSize)
{
*pOutSize = sizeof(UINT32);
rc = TRUE;
}
}
//cleanUp:
return(rc);
}
//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalBootFlags
//
// This function can be used to retreave the boot loader flags.
//
BOOL OALIoCtlHalBootFlags(
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize
) {
BOOL rc = FALSE;
OALMSG(OAL_IOCTL&&OAL_FUNC, (L"+OALIoCtlHalBootFlags(...)\r\n"));
if (!pOutBuffer || (outSize < sizeof(UINT32)))
{
OALMSG(OAL_ERROR, (L"ERROR: OALIoCtlHalBFlashImage: INSUFFICIENT BUFFER\r\n"));
NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
{
*((UINT32 *)pOutBuffer) = g_oalIoctlBootFlags;
if (pOutSize)
{
*pOutSize = sizeof(UINT32);
rc = TRUE;
}
}
//cleanUp:
return(rc);
}
//------------------------------------------------------------------------------
//
// Global: g_oalIoCtlTable[]
//
// IOCTL handler table. This table includes the IOCTL code/handler pairs
// defined in the IOCTL configuration file. This global array is exported
// via oal_ioctl.h and is used by the OAL IOCTL component.
//
const OAL_IOCTL_HANDLER g_oalIoCtlTable[] = {
#include "ioctl_tab.h"
};
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -