88年属什么生肖配对:KernelIoControl和OEMIoControl

来源:百度文库 编辑:偶看新闻 时间:2024/04/26 06:29:04
转)KernelIoControl和OEMIoControl

        对于KernelIoControl这个函数我们并不陌生,在2440 5.0BSP当中,这个函数在很多驱动中出现了,主要是用来申请中断,比如下面

BOOL RetVal = KernelIoControl( IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof( Irq ),
                                   pSysIntr,   sizeof( *pSysIntr ), NULL );

-------------------其实他的作用远远不止申请/释放中断那么简单,下面来看看PB的帮助文档。

http://www.360doc.com/

This function provides the kernel with a generic I/O control for carrying out I/O operations.

BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned
);对于这个函数的参数,非常类似EVC中的DeviceIoControl,从说明可以了解参数的使用方法。
Parameters
dwIoControlCode
[in] I/O control code, which should support the OAL I/O controls. For a list of these I/O controls, see OAL IOCTLs.
lpInBuf
[out] Pointer to a buffer that contains the data required to perform the operation.
Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.

nInBufSize
[in] Size, in bytes, of the buffer pointed to by lpInBuf.
lpOutBuf
[out] Pointer to a buffer that receives the output data for the operation.
Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.

nOutBufSize
[in] Size, in bytes, of the buffer pointed to by lpOutBuf.
lpBytesReturned
[in] Long pointer to a variable that receives the size, in bytes, of the data stored in the buffer pointed to by lpOutBuf. Even when an operation produces no output data, and lpOutBuf is NULL, the KernelIoControl function uses the variable pointed to by lpBytesReturned. After such an operation, the value of the variable has no meaning.
Return Values
TRUE indicates success; FALSE indicates failure.

Remarks
The kernel calls the OEMIoControl function when a device driver or application calls the kernel function KernelIoControl and passes an I/O control code.

(当应用程序或者驱动调用KernelIoControl 的时候,KernelIoControl 就会调用OEMIoControl 去实现。)

This function is also called when the SystemParametersInfo function is called with SPI_GETOEMINFO or SPI_GETPLATFORMINFO.

The system is fully preemptible when this function is called. The kernel does no processing, but it passes all parameters directly to the function supplied by you. (当这个函数被调用的时候系统完全可能被抢占,内核没有处理,直接传递参数到你提供的函数。这个我觉得说的很别扭,估计是直接传递参数到OEMIoControl )

This function is provided solely to allow your device driver or application to communicate with an OAL and its specific functionality.

(该函数用来提供驱动/应用程序和OAL的通信)

Requirements
OS Versions: Windows CE 2.10 and later.
Header: Pkfuncs.h.(原来是个不开源的函数)
Link Library: Coredll.lib.

========================现在来看看OEMIoControl 这个函数============================

C:\WINCE500\PLATFORM\COMMON\SRC\COMMON\IOCTL\ioctl.c(45):// Function: OEMIoControl

// File: ioctl.c
//
// File implements OEMIoControl function.
//
#include
#include    //这个很关键,不然oal_ioctl_tab.h设置就没有办法传递进来。

//------------------------------------------------------------------------------
//
// Global: g_ioctlState;
//
// This state variable contains critical section used to serialize IOCTL
// calls.
//
static struct {
    BOOL postInit;
    CRITICAL_SECTION cs;
} g_ioctlState = { FALSE };

//------------------------------------------------------------------------------
//
// Include: intioctl.c
//
// This include file is used to add internal testing IOCTL hadlers.
//
#ifdef OAL_HAL_INTERNAL_TESTING
#include "intioctl.c"
#endif


//------------------------------------------------------------------------------
//
// Function: OEMIoControl
//
// The function is called by kernel a device driver or application calls
// KernelIoControl. The system is fully preemtible when this function is
// called. The kernel does no processing of this API. It is provided to
// allow an OEM device driver to communicate with kernel mode code.
//
BOOL OEMIoControl(
    DWORD code, VOID *pInBuffer, DWORD inSize, VOID *pOutBuffer, DWORD outSize,
    DWORD *pOutSize
) {
    BOOL rc = FALSE;
    UINT32 i;

    OALMSG(OAL_IOCTL&&OAL_FUNC, (
        L"+OEMIoControl(0x%x, 0x%x, %d, 0x%x, %d, 0x%x)\r\n",
        code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
    ));

    // Search the IOCTL table for the requested code.
    for (i = 0; g_oalIoCtlTable[i].pfnHandler != NULL; i++) {
        if (g_oalIoCtlTable[i].code == code) break;
    }

    // Indicate unsupported code
    if (g_oalIoCtlTable[i].pfnHandler == NULL) {
#ifdef OAL_HAL_INTERNAL_TESTING
        rc = InternalHalTesting(
            code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
        );
#else
        NKSetLastError(ERROR_NOT_SUPPORTED);
        OALMSG(OAL_WARN, (
            L"OEMIoControl: Unsupported Code 0x%x - device 0x%04x func %d\r\n",
            code, code >> 16, (code >> 2)
        ));
#endif
        goto cleanUp;
    }        

    // Take critical section if required (after postinit & no flag)
    if (
        g_ioctlState.postInit &&
        (g_oalIoCtlTable[i].flags & OAL_IOCTL_FLAG_NOCS) == 0
    ) {
        // Take critical section            
        EnterCriticalSection(&g_ioctlState.cs);
    }

    // Execute the handler 调用函数指针,用来实现相应功能
    rc = g_oalIoCtlTable[i].pfnHandler(
        code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
    );

    // Release critical section if it was taken above
    if (
        g_ioctlState.postInit &&
        (g_oalIoCtlTable[i].flags & OAL_IOCTL_FLAG_NOCS) == 0
    ) {
        // Take critical section            
        LeaveCriticalSection(&g_ioctlState.cs);
    } else if (!g_ioctlState.postInit && code == IOCTL_HAL_POSTINIT) {
        // Initialize critical section
        InitializeCriticalSection(&g_ioctlState.cs);
        g_ioctlState.postInit = TRUE;
    }                

cleanUp:
    OALMSG(OAL_IOCTL&&OAL_FUNC, (L"-OEMIoControl(rc = %d)\r\n", rc ));
    return rc;
}

//------------------------------------------------------------------------------

——再来看oal_ioctl.h

//------------------------------------------------------------------------------
//
// File: oal_ioctl.h
//
// This header file defines IO Control OAL module. This module implements
// OEMIoControl function which is used to call kernel functions from user
// space.
//
#ifndef __OAL_IOCTL_H
#define __OAL_IOCTL_H

#if __cplusplus
extern "C" {
#endif

//------------------------------------------------------------------------------
//
// Definition: OAL_IOCTL_FLAG_xxx
//
// This definition specifies flag codes for IOCTL table. When NOCS flag is
// set handler function will be called in deserialized mode (so no critical
// section will be taken/release before/after handler is called).
//
#define OAL_IOCTL_FLAG_NOCS     (1 << 0)

//------------------------------------------------------------------------------
//
// Type: IOCTL_HANDLER    
//
// This type defines the procedure to be called for an IOCTL code. The
// global g_oalIoctlTable is an array of these types.
//
typedef struct {
    UINT32 code;
    UINT32 flags;
    BOOL    (*pfnHandler)(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
} OAL_IOCTL_HANDLER, *POAL_IOCTL_HANDLER;

//------------------------------------------------------------------------------
//
// Extern: g_oalIoCtlPlatformType/OEM
//
// Platform Type/OEM
//
extern LPCWSTR g_oalIoCtlPlatformType;
extern LPCWSTR g_oalIoCtlPlatformOEM;

//------------------------------------------------------------------------------
//
// Global: g_oalIoCtlProcessorVendor/Name/Core
//
// Processor information
//
extern LPCWSTR g_oalIoCtlProcessorVendor;
extern LPCWSTR g_oalIoCtlProcessorName;
extern LPCWSTR g_oalIoCtlProcessorCore;

//------------------------------------------------------------------------------
//
// Global: g_oalIoCtlInstructionSet/g_oalIoCtlClockSpeed
//
// Processor instruction set identifier and clock speed
//

extern UINT32 g_oalIoCtlInstructionSet;
extern UINT32 g_oalIoCtlClockSpeed;

//------------------------------------------------------------------------------
//
// Globaal: g_oalIoctlTable
//
// This extern references the global IOCTL table that is defined in
// the platform code.
//
extern const OAL_IOCTL_HANDLER g_oalIoCtlTable[];

//------------------------------------------------------------------------------
//
// Function: OALIoCtlXxx
//
// This functions implement basic IOCTL code handlers.
// 这些函数在哪里实现的呢?功能好强大
BOOL OALIoCtlHalGetDeviceId(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlHalGetDeviceInfo(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlProcessorInfo(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlHalInitRegistry(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlHalReboot(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);
BOOL OALIoCtlHalGetUUID (UINT32, VOID *, UINT32, VOID *, UINT32, UINT32 *);

//------------------------------------------------------------------------------
//
// Function: OALIoCtlHalDDIXxx
//
// This functions implement IOCTL code handler used by HAL flat display
// driver.
//
BOOL OALIoCtlHalDDI(UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);

//------------------------------------------------------------------------------


#if __cplusplus
}
#endif

#endif // __OAL_IOCTL_H
    再看oal_ioctl_tab.h

//------------------------------------------------------------------------------
// 这个头文件很关键,只要在这里填入相应的IOCTL_XXXXX以及相应的函数
// (在别的地方实现这个函数)就大功告成了。
// File: oal_ioctl_tab.h
//
// This file contains part of global IOCTL handler table for codes which
// must (or should) be implemented on all platforms. Table in platform
// will usually include this file.
//
// This file is included by the platform's IOCTL table, g_oalIoCtlTable[].
// Therefore, this file may ONLY define OAL_IOCTL_HANDLER entries.
//
// IOCTL CODE,                          Flags   Handler Function
//------------------------------------------------------------------------------

{ IOCTL_HAL_TRANSLATE_IRQ,                  0, OALIoCtlHalRequestSysIntr   },
{ IOCTL_HAL_REQUEST_SYSINTR,                0, OALIoCtlHalRequestSysIntr   },
{ IOCTL_HAL_RELEASE_SYSINTR,                0, OALIoCtlHalReleaseSysIntr   },
{ IOCTL_HAL_REQUEST_IRQ,                    0, OALIoCtlHalRequestIrq       },

{ IOCTL_HAL_INITREGISTRY,                   0, OALIoCtlHalInitRegistry     },
{ IOCTL_HAL_INIT_RTC,                       0, OALIoCtlHalInitRTC          },
{ IOCTL_HAL_REBOOT,                         0, OALIoCtlHalReboot           },

{ IOCTL_HAL_DDK_CALL,                       0, OALIoCtlHalDdkCall          },

{ IOCTL_HAL_DISABLE_WAKE,                   0, OALIoCtlHalDisableWake      },
{ IOCTL_HAL_ENABLE_WAKE,                    0, OALIoCtlHalEnableWake       },
{ IOCTL_HAL_GET_WAKE_SOURCE,                0, OALIoCtlHalGetWakeSource    },

{ IOCTL_HAL_GET_CACHE_INFO,                 0, OALIoCtlHalGetCacheInfo     },
{ IOCTL_HAL_GET_DEVICEID,                   0, OALIoCtlHalGetDeviceId      },
{ IOCTL_HAL_GET_DEVICE_INFO,                0, OALIoCtlHalGetDeviceInfo    },
{ IOCTL_HAL_GET_UUID,                       0, OALIoCtlHalGetUUID          },
{ IOCTL_PROCESSOR_INFORMATION,              0, OALIoCtlProcessorInfo       },

{ IOCTL_VBRIDGE_802_3_MULTICAST_LIST,       0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_ADD_MAC,                    0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_CURRENT_PACKET_FILTER,      0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_GET_ETHERNET_MAC,           0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_GET_RX_PACKET,              0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_GET_RX_PACKET_COMPLETE,     0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_GET_TX_PACKET,              0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_GET_TX_PACKET_COMPLETE,     0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_SHARED_ETHERNET,            0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_WILD_CARD,                  0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_WILD_CARD_RESET_BUFFER,     0, OALIoCtlVBridge             },
{ IOCTL_VBRIDGE_WILD_CARD_VB_INITIALIZED,   0, OALIoCtlVBridge             },

在初始化阶段内核就会调用KernelIoControl来和OAL通信,其实就是通过调用KernelIoControl来执行OEMIoControl

很神奇吧。申请中断什么的,都在这里弄好了。牛B!

==============================例子:重启

如何在程序中关闭、重起和硬起动Pocket PC?

--------------------------------------------------------------------------------

时间:2003-2-28 18:18:44 来源:BIPLIP.com 作者:Daric 阅读210次


关闭(suspend)
方法1:
//虚拟关机键
::keybd_event(VK_OFF, 0, 0, 0);
::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0);
方法2:
//调用未公开函数PowerOffSystem()
extern "C" __declspec(dllimport) void PowerOffSystem();
重起(soft reset)
//Soft reset the device
#include
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern "C" __declspec(dllimport) BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned);
BOOL ResetPocketPC()
{
return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}
硬起动(hard reset)
//注意!!!使用此段代码会将您的Pocket PC的用户数据全部清空,
//请勿非法使用,用者后果自负.
#include
#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern "C" __declspec(dllimport)void SetCleanRebootFlag(void);
extern "C" __declspec(dllimport) BOOL KernelIoControl(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned);
BOOL HardResetPocketPC()
{
SetCleanRebootFlag();
return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
}


本文来自CSDN博客,转载请标明出处:http://www.360doc.com/

WinCE OAL中的OEMIoControl函数

http://www.360doc.com/

关于OEMIoControl函数,我在2008年1月份写过一篇blog叫“WinCE BSP中OAL层中的OEMIoControl介绍”,已经比较详细的介绍了OEMIoControl,今天在这里只是对OEMIoControl中比较常用的case说一说。看看PB的文档就知道OEMIoControl可以包含很多case而且被分了类。下面就我个人接触到的和比较常用的做个说明:

1. IOCTL_HAL_INIT_RTC

对应OALIoctlHalInitRTC函数,该case用于重新初始化RTC。在系统冷启动的时候,内核会调用它来设置时钟。

dwIoControlCode:IOCTL_HAL_INIT_RTC

lpInBuf:要设置的时钟结构体

实际上在该case中一般都是注册RTC的ALARM中断,然后调用OEMSetRealTime函数来进行设置。关于OAL中的RTC的说明,可以参考我在2008年1月写的“WinCE中RTC驱动开发介绍”。

2. IOCTL_HAL_POSTINIT

对应OALIoctlHalPostInit函数,该case会被内核调用,不传入任何数据,也不返回任何数据。在系统进程启动之前,它提供了最后一次机会让我们在OAL中做一些动作。

3. IOCTL_HAL_ILTIMING

对应OALIoctlHalILTiming函数,该case实现了对ILTiming的支持,当Iltiming.exe运行时,该case会被调用。

dwIoControlCode:IOCTL_HAL_ILTIMING

lpInBuf:传入ILTiming结构

4. IOCTL_HAL_REBOOT

对应OALIoctlHalReboot函数,该case用于热启动系统。

5. IOCTL_HAL_ENABLE_WAKE

对应OALIoctlHalEnableWake函数,该case用于添加可唤醒系统的中断源。

dwIoControlCode:IOCTL_HAL_ENABLE_WAKE

lpInBuf:可唤醒系统的系统中断号

6. IOCTL_HAL_DISABLE_WAKE

对应OALIoctlHalDisableWake函数,该case用于删除可唤醒系统的中断源。

dwIoControlCode:IOCTL_HAL_DISABLE_WAKE

lpInBuf:被删除的系统中断号

7. IOCTL_HAL_GET_HIVE_CLEAN_FLAG

对应OALIoctlHalGetHiveCleanFlag函数,该case会被Filesys模块调用,用于确定是否清除系统Hive和用户Hive。

dwIoControlCode:IOCTL_HAL_GET_HIVE_CLEAN_FLAG

lpInBuf:HIVECLEANFLAG_SYSTEM表示查询系统Hive;HIVECLEANFLAG_USERS表示查询用户Hive

lpOutBuf:返回TRUE表示清除,返回FALSE表示不清除

8. IOCTL_HAL_GET_HIVE_RAM_REGION

对应OALIoctlHalGetHiveRamRegion函数,该case会被Filesys模块调用,返回一块内存区域用来存放Hive,此时系统Hive和用户Hive是存放在一起的,所以所有的用户都使用同一个用户Hive。

dwIoControlCode:IOCTL_HAL_GET_HIVE_RAM_REGION

lpOutBuf:返回一个存放Hive的RAM结构信息

9. IOCTL_HAL_QUERY_FORMAT_PARTITION

对应OALIoctlHalQueryFormatPartition函数,该case会被Filesys模块调用,返回是否需要格式化某个分区。对于一块存储介质来说,如果在该介质驱动的注册表配置中设置了CheckForFormat项,Filesys模块才会调用该case,例如:

[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\MyProfile\FATFS]

    "CheckForFormat"=dword:1

dwIoControlCode:IOCTL_HAL_QUERY_FORMAT_PARTITION

lpInBuf:传入存储介质的信息

lpOutBuf:返回TRUE表示该分区需要格式化,返回FALSE表示不需要格式化

..........

在WinCE的BSP中的OAL部分,会有一个ioctl.c或者oemioctl.c文件,里面主要定义了一个叫OEMIoControl(..)的函数。可以说OEMIoControl是一个很有用的WinCE内核输入/输出函数。

在WinCE5.0中,应用程序和驱动程序可以通过调用KernelIoControl(..)函数来访问WinCE内核,导致调用OEMIoControl函数,这样应用程序和驱动程序就可以访问到OAL中的资源了。但在WinCE6.0中,提供了更好的安全性,应用程序能够访问OEMIoControl中的case受到了限制,只有下面的这些case是可以让应用程序访问的:

IOCTL_HAL_GET_CACHE_INFO

IOCTL_HAL_GET_DEVICE_INFO

IOCTL_HAL_GET_DEVICEID

IOCTL_HAL_GET_UUID

IOCTL_PROCESSOR_INFORMATION

如果用户在应用程序中试图访问其他的case,肯定会返回失败的。在WinCE6.0中,驱动程序还像以前一样,可以访问OEMIoControl中的任何case。也许有人会问,那么我们如何让应用程序也访问到一些case呢??

办法还是有的,可以看一下\WINCE600\public\common\oak\oalioctl\oalioctl.c,这个文件中定义了应用程序可以访问的case,把你的应用程序要访问的case加到这个文件中的IOControl(..)函数中就可以了。当然,你需要重新编译\public目录。

在WinCE5.0中,OEMIoControl函数被定义在BSP中的OAL部分,上面已经提到,应该是ioctl.c或者oemioctl.c,但是在WinCE6.0中,这个函数的定义被移到了\WINCE600\platform\common\src\common\ioctl\ioctl.c中了,这里面的OEMIoControl函数和以前也有了变化,该函数会查一个表:g_oalIoCtlTable[]。该表实际上是一个结构数组,定义了OEMIoControl中所有的case,已经针对这个case的处理函数,还包括一个针对每个case的flag,该flag表示是否使用临界区保护。具体定义如下:

typedef struct { UINT32 code; UINT32 flags; BOOL (*pfnHandler) (UINT32, VOID*, UINT32, VOID*, UINT32, UINT32*);} OAL_IOCTL_HANDLER, *POAL_IOCTL_HANDLER;

所以,在WinCE6.0的BSP中,我们只需要实现g_oalIoCtlTable[]就可以了。例如:

const OAL_IOCTL_HANDLER g_oalIoCtlTable[]={

{ IOCTL_HAL_POSTINIT,                                               0, OALIoCtlHalPostInit         },

{ IOCTL_HAL_GET_HIVE_CLEAN_FLAG,                  0, OALIoCtlHalGetHiveCleanFlag },

{ IOCTL_HAL_GET_HWENTROPY,                             0, OALIoCtlHalGetHWEntropy     },

{ IOCTL_HAL_GET_IMAGE_SIGNED_STATE,          0, OALIoCtlHalGetImageSignedState },

{ IOCTL_HAL_QUERY_FORMAT_PARTITION,         0, OALIoCtlHalQueryFormatPartition },

{ 0,                                                                                      0, NULL}

};

在OEMIoControl函数中,我们不光要实现OEMIoControl中的case,有一些全局的OAL变量我们也需要定义:

g_oalIoCtlClockSpeed

This global variable contains information about the processor clock speed.

g_oalIoCtlInstructionSet

This global variable contains the processor instruction set identifier.

g_oalIoCtlPlatformOEM

This global variable contains information about the hardware platform OEM.

g_oalIoCtlPlatformType

This global variable contains information about the hardware platform type.

g_oalIoCtlProcessorCore

This global variable contains information about the processor core.

g_oalIoCtlProcessorName

This global variable contains information about the processor name.

g_oalIoCtlProcessorVendor

This global variable contains information about the processor vendor.

其实都是一些硬件及平台的相关信息,定义一下就可以了。

有时根据具体需要,我们还希望在OEMIoControl函数中添加自己定义的case,这个比较简单,只要定义个case,然后在这个case下写你的实现代码就可以了,驱动程序通过KernelIoControl调用同样的case就可以调用到你在OEMIoControl中定义的case了。关于case值得定义,一般都在2048到4096之间会比较安全,我记得在WinCE6.0下,看微软的代码好像256以上就可以了,具体没有试过,要是保险的话,还是用2048以上的值吧。