📄 drv.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
drv.c I2C (logical) MDD
Abstract:
Streams interface driver
Functions:
Notes:
--*/
#include <windows.h>
#include <nkintr.h>
#include <winreg.h>
#include <winioctl.h>
#include <ceddk.h>
#include <devload.h>
#include "drv.h"
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("I2C"), {
TEXT("Error"), TEXT("Warn"), TEXT("Init"), TEXT("Open"),
TEXT("Read"), TEXT("Write"), TEXT("IOCTL"), TEXT("IST"),
TEXT("Power"), TEXT("9"), TEXT("10"), TEXT("11"),
TEXT("12"), TEXT("13"), TEXT("14"), TEXT("Trace"),
},
0x0003 // ZONE_WRN|ZONE_ERR
};
#endif // DEBUG
BOOL
I2C_PowerUp(
PVOID Context
);
BOOL
I2C_PowerDown(
PVOID Context
);
BOOL
DllEntry(
HINSTANCE hinstDll, /*@parm Instance pointer. */
DWORD dwReason, /*@parm Reason routine is called. */
LPVOID lpReserved /*@parm system parameter. */
)
{
if ( dwReason == DLL_PROCESS_ATTACH ) {
DEBUGREGISTER(hinstDll);
DEBUGMSG (ZONE_INIT, (TEXT("I2C: Process Attach\r\n")));
}
if ( dwReason == DLL_PROCESS_DETACH ) {
DEBUGMSG (ZONE_INIT, (TEXT("I2C: Process Detach\r\n")));
}
return(TRUE);
}
BOOL
GetRegistryData(PI2C_CONTEXT pI2C, LPCTSTR regKeyPath)
{
LONG regError;
HKEY hKey;
DWORD dwDataSize;
DEBUGMSG(ZONE_INIT, (TEXT("Try to open %s\r\n"), regKeyPath));
// We've been handed the name of a key in the registry that was generated
// on the fly by device.exe. We're going to open that key and pull from it
// a value that is the name of this drivers's real key. That key
// will have the DeviceArrayIndex that we're trying to find.
hKey = OpenDeviceKey(regKeyPath);
if ( hKey == NULL ) {
DEBUGMSG(ZONE_INIT | ZONE_ERR,(TEXT("Failed to open device key\r\n")));
return ( FALSE );
}
dwDataSize = REG_MODE_VAL_LEN;
regError = RegQueryValueEx(
hKey,
REG_MODE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pI2C->Mode),
&dwDataSize);
if (regError)
goto _done;
dwDataSize = REG_SLAVEADDR_VAL_LEN;
regError = RegQueryValueEx(
hKey,
REG_SLAVEADDR_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pI2C->SlaveAddress),
&dwDataSize);
if (regError)
goto _done;
_done:
RegCloseKey (hKey);
if ( regError != ERROR_SUCCESS ) {
DEBUGMSG(ZONE_ERR, (TEXT("Failed to get registry values, Error 0x%X\r\n"),regError));
return ( FALSE );
}
DEBUGMSG (ZONE_INIT,(TEXT("I2C_Init - Mode: %s\r\n"),
pI2C->Mode == POLLING ? L"POLLING" : L"INTERRUPT"));
return ( TRUE );
}
#ifdef UTLDRV
static
DWORD
InternalMapRegisters(
PI2C_CONTEXT pI2C
)
{
HANDLE hUtil;
UTL_FASTCALL utlFc = {0};
DWORD dwErr = ERROR_SUCCESS, bytes;
// Open the util driver so we can map in our registers VA
hUtil = CreateFile( TEXT("UTL0:"), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hUtil) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("CreateFile ERROR: %d\n"), dwErr));
goto _error_exit;
}
// get it's FAST CALL function pointers.
if( !DeviceIoControl(hUtil,
IOCTL_UTL_GET_FASTCALL,
NULL, 0,
&utlFc, sizeof(utlFc),
&bytes, NULL)) {
dwErr = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("DeviceIoControl ERROR: %d\n"), dwErr));
goto _error_exit;
}
// map in I2C registers
dwErr = utlFc.GetRegisterVA(utlFc.pContext,
IIC_BASE,
sizeof(IICreg),
FALSE,
(DWORD *)&pI2C->pI2CReg);
if ( dwErr ) {
DEBUGMSG(ZONE_ERR, (TEXT("GetRegisterVA(IIC_BASE) ERROR: %d\n"), dwErr));
goto _error_exit;
}
// map in GPIO
dwErr = utlFc.GetRegisterVA(utlFc.pContext,
IOP_BASE,
sizeof(IOPreg),
FALSE,
(DWORD *)&pI2C->pIOPReg);
if ( dwErr ) {
DEBUGMSG(ZONE_ERR, (TEXT("GetRegisterVA(IOP_BASE) ERROR: %d\n"), dwErr));
goto _error_exit;
}
// map in CLK/PWR registers
dwErr = utlFc.GetRegisterVA(utlFc.pContext,
CLKPWR_BASE,
sizeof(CLKPWRreg),
FALSE,
(DWORD *)&pI2C->pCLKPWRReg);
if ( dwErr ) {
DEBUGMSG(ZONE_ERR, (TEXT("GetRegisterVA(CLKPWR_BASE) ERROR: %d\n"), dwErr));
goto _error_exit;
}
_error_exit:
// We only mapped in registers, which remain in utildrv forever.
// If we mapped in memory we would need to keep the handle and FreeMemVA later.
if (INVALID_HANDLE_VALUE != hUtil)
CloseHandle(hUtil);
return dwErr;
}
#else
static
DWORD
InternalMapRegisters(
PI2C_CONTEXT pI2C
)
{
PUCHAR pVMem;
BOOL bMapReturn;
DWORD err = ERROR_SUCCESS;
// reserve enough space for our registers
pVMem = (PUCHAR)VirtualAlloc(0, PAGE_SIZE*3, MEM_RESERVE, PAGE_NOACCESS);
if (pVMem) {
// map in I2C registers
bMapReturn = VirtualCopy( pVMem,
(LPVOID)(S3C2440A_BASE_REG_PA_IICBUS>>8),
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);
if (!bMapReturn) {
err = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("Virtual Copy ERROR for IICBUS regs: %d\r\n"), err));
return err;
}
pI2C->pI2CReg = (volatile S3C2440A_IICBUS_REG*)(pVMem);
// map in GPIO registers
pVMem += PAGE_SIZE;
bMapReturn = VirtualCopy(pVMem,
(LPVOID)(S3C2440A_BASE_REG_PA_IOPORT>>8),
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);
if (!bMapReturn) {
err = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("Virtual Copy ERROR for IOP regs: %d\r\n"), err));
return err;
}
pI2C->pIOPReg = (volatile S3C2440A_IOPORT_REG*)(pVMem);
// map in CLK/PWR registers
pVMem += PAGE_SIZE;
bMapReturn = VirtualCopy(pVMem,
(LPVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER>>8),
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);
if (!bMapReturn) {
err = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("Virtual Copy ERROR for CLK power regs: %d\r\n"), err));
return err;
}
pI2C->pCLKPWRReg = (volatile S3C2440A_CLKPWR_REG*)(pVMem);
} else {
err = GetLastError();
DEBUGMSG(ZONE_ERR, (TEXT("Virtual Alloc ERROR: %d\r\n"), err));
}
return err;
}
#endif
BOOL
I2C_Deinit(
PI2C_CONTEXT pI2C
)
{
DEBUGMSG(ZONE_INIT, (TEXT(">I2C_Deinit\n")));
if (!pI2C)
return FALSE;
HW_Deinit(pI2C);
#ifndef UTLDRV
if (pI2C->pI2CReg)
VirtualFree((PVOID)pI2C->pI2CReg, 0, MEM_RELEASE);
if (pI2C->pIOPReg)
VirtualFree((PVOID)pI2C->pIOPReg, 0, MEM_RELEASE);
if (pI2C->pCLKPWRReg)
VirtualFree((PVOID)pI2C->pCLKPWRReg, 0, MEM_RELEASE);
#endif
LocalFree(pI2C);
DEBUGMSG(ZONE_INIT, (TEXT("<I2C_Deinit\n")));
return TRUE;
}
/*++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -