⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioctl.c

📁 老外的一个开源项目
💻 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 + -