📄 triton.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.
//
#include <windows.h>
#include <ceddk.h>
#include <ceddkex.h>
#include <omap2420.h>
#include <i2c.h>
#include <twl.h>
#include <bsp_menelaus.h>
#include <bsp_i2c_cfg.h>
#include "triton.h"
//------------------------------------------------------------------------------
//
// Global: dpCurSettings
//
// Set debug zones names and initial setting for driver
//
#ifndef SHIP_BUILD
//------------------------------------------------------------------------------
//
// Global: dpCurSettings
//
DBGPARAM dpCurSettings = {
L"Triton (TWL)", {
L"Errors", L"Warnings", L"Function", L"Init",
L"Info", L"Undefined", L"Undefined", L"Undefined",
L"Undefined", L"Undefined", L"Undefined", L"Undefined",
L"Undefined", L"Undefined", L"Undefined", L"RTC"
},
0x8003
};
#endif
//------------------------------------------------------------------------------
// Global variables
static const GUID DEVICE_IFC_TWL_GUID;
static const GUID DEVICE_IFC_I2C_GUID;
//------------------------------------------------------------------------------
// Device registry parameters
static const DEVICE_REGISTRY_PARAM s_deviceRegParams[] = {
{
L"Irq", PARAM_DWORD, TRUE, offset(Device_t, irq),
fieldsize(Device_t, irq), NULL
}, {
L"Priority256", PARAM_DWORD, FALSE, offset(Device_t, priority256),
fieldsize(Device_t, priority256), (VOID*)100
}, {
L"I2CAddress", PARAM_DWORD, FALSE, offset(Device_t, i2cAddress),
fieldsize(Device_t, i2cAddress), (VOID*)0x2D
}
};
//------------------------------------------------------------------------------
// Function : GetTritonIrqStatus
//
// Return status register
//
BOOL GetTritonIrqStatus(VOID *pContext, UINT16 *pStatus)
{
Device_t *pDevice = (Device_t*)pContext;
I2CTRANS trans;
ZeroMemory(&trans,sizeof(trans));
trans.mClk_HL_Divisor = I2C_CLOCK_100Khz;
/* write out the register address to read from */
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 1;
trans.mBuffer[0] = MENELAUS_INTSTATUS1_OFFSET;
/* now read the byte at that location */
trans.mOpCode[1] = I2C_OPCODE_READ;
trans.mBufferOffset[1] = 0;
trans.mTransLen[1] = 1;
/* write out the second address to read from */
trans.mOpCode[2] = I2C_OPCODE_WRITE;
trans.mBufferOffset[2] = 1;
trans.mTransLen[2] = 1;
trans.mBuffer[1] = MENELAUS_INTSTATUS2_OFFSET;
/* now read back the byte at that location */
trans.mOpCode[3] = I2C_OPCODE_READ;
trans.mBufferOffset[3] = 1;
trans.mTransLen[3] = 1;
I2CTransact(pDevice->hI2C, &trans);
if (trans.mErrorCode)
return FALSE;
*pStatus = (((UINT16)trans.mBuffer[1])<<8) | trans.mBuffer[0];
return TRUE;
}
//------------------------------------------------------------------------------
// Function : GetTritonIrqMask
//
// Return mask register
//
BOOL GetTritonIrqMask(VOID *pContext, UINT16 *pStatus)
{
Device_t *pDevice = (Device_t*)pContext;
I2CTRANS trans;
ZeroMemory(&trans,sizeof(trans));
trans.mClk_HL_Divisor = I2C_CLOCK_100Khz;
// write out the register address to read from
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 1;
trans.mBuffer[0] = MENELAUS_INTMASK1_OFFSET;
// now read the byte at that location
trans.mOpCode[1] = I2C_OPCODE_READ;
trans.mBufferOffset[1] = 0;
trans.mTransLen[1] = 1;
// write out the second address to read from
trans.mOpCode[2] = I2C_OPCODE_WRITE;
trans.mBufferOffset[2] = 1;
trans.mTransLen[2] = 1;
trans.mBuffer[1] = MENELAUS_INTMASK2_OFFSET;
// now read back the byte at that location
trans.mOpCode[3] = I2C_OPCODE_READ;
trans.mBufferOffset[3] = 1;
trans.mTransLen[3] = 1;
I2CTransact(pDevice->hI2C, &trans);
*pStatus = (((UINT16)trans.mBuffer[1])<<8) | trans.mBuffer[0];
return (trans.mErrorCode == 0);
}
BOOL SetTritonIrqMask(VOID *pContext, UINT16 status)
{
Device_t *pDevice = (Device_t*)pContext;
I2CTRANS trans;
UCHAR mask;
ZeroMemory(&trans,sizeof(trans));
trans.mClk_HL_Divisor = I2C_CLOCK_100Khz;
mask = status & 0xff;
if (mask) {
// read current mask setting
// write out the register address to read from
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 1;
trans.mBuffer[0] = MENELAUS_INTMASK1_OFFSET;
// now read the byte at that location
trans.mOpCode[1] = I2C_OPCODE_READ;
trans.mBufferOffset[1] = 0;
trans.mTransLen[1] = 1;
I2CTransact(pDevice->hI2C, &trans);
// mask the pending interrupt
mask |= trans.mBuffer[0];
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 2;
trans.mBuffer[0] = MENELAUS_INTMASK1_OFFSET;
trans.mBuffer[1] = mask;
I2CTransact(pDevice->hI2C, &trans);
}
mask = (status >> 8) & 0xff;
if (mask) {
// read current mask setting
// write out the register address to read from
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 1;
trans.mBuffer[0] = MENELAUS_INTMASK2_OFFSET;
// now read the byte at that location
trans.mOpCode[1] = I2C_OPCODE_READ;
trans.mBufferOffset[1] = 0;
trans.mTransLen[1] = 1;
I2CTransact(pDevice->hI2C, &trans);
// mask the pending interrupt
mask |= trans.mBuffer[0];
trans.mOpCode[0] = I2C_OPCODE_WRITE;
trans.mBufferOffset[0] = 0;
trans.mTransLen[0] = 2;
trans.mBuffer[0] = MENELAUS_INTMASK2_OFFSET;
trans.mBuffer[1] = mask;
I2CTransact(pDevice->hI2C, &trans);
}
return (trans.mErrorCode == 0);
}
//------------------------------------------------------------------------------
//
BOOL
InitializeTritonInterrupts(
Device_t *pDevice
)
{
// Disable all interrupts
return SetTritonIrqMask(pDevice, 0xffff);
}
//------------------------------------------------------------------------------
//
// Function: TWL_Init
//
// Called by device manager to initialize device.
//
DWORD
TWL_Init(
LPCWSTR szContext,
LPCVOID pBusContext
)
{
DWORD rc = (DWORD)NULL;
Device_t *pDevice = NULL;
DEBUGMSG(ZONE_FUNCTION, (
L"+TWL_Init(%s, 0x%08x)\r\n", szContext, pBusContext
));
// Create device structure
pDevice = (Device_t *)LocalAlloc(LPTR, sizeof(Device_t));
if (pDevice == NULL)
{
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed allocate TWL controller structure\r\n"
));
goto cleanUp;
}
// Set cookie
pDevice->cookie = TWL_DEVICE_COOKIE;
// Initalize critical section
InitializeCriticalSection(&pDevice->cs);
// Read device parameters
if (GetDeviceRegistryParams(
szContext, pDevice, dimof(s_deviceRegParams), s_deviceRegParams
) != ERROR_SUCCESS)
{
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed read TWL driver registry parameters\r\n"
));
goto cleanUp;
}
// Open parent bus
pDevice->hI2C = I2COpen(I2C_DEVICE_NAME);
if (pDevice->hI2C == NULL) {
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed open I2C bus driver\r\n"
));
goto cleanUp;
}
// Set Triton I2C address
if (!I2CSetSlaveAddress(pDevice->hI2C, 7, I2C_MENELAUS_ADDRESS)) {
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed set I2C bus slave address\r\n"
));
goto cleanUp;
}
// Disable all interrupts
if (InitializeTritonInterrupts(pDevice) == FALSE) goto cleanUp;
pDevice->irq = IRQ_SYS_NIRQ;
// Map interrupt
if (!KernelIoControl(
IOCTL_HAL_REQUEST_SYSINTR, &pDevice->irq, sizeof(pDevice->irq),
&pDevice->sysIntr, sizeof(pDevice->sysIntr), NULL) ) {
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed map Triton interrupt (%d)\r\n", pDevice->irq
));
goto cleanUp;
}
// Create interrupt event
pDevice->hIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (pDevice->hIntrEvent == NULL) {
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed create interrupt event\r\n"
));
goto cleanUp;
}
// Initialize interrupt
if (!InterruptInitialize(pDevice->sysIntr, pDevice->hIntrEvent, NULL, 0)) {
DEBUGMSG (ZONE_ERROR, (L"ERROR: TWL_Init: "
L"InterruptInitialize failed\r\n"
));
goto cleanUp;
}
// Start interrupt service thread
pDevice->intrThreadExit = FALSE;
pDevice->hIntrThread = CreateThread(NULL, 0, TWL_IntrThread, pDevice, 0,NULL);
if (!pDevice->hIntrThread) {
DEBUGMSG (ZONE_ERROR, (L"ERROR: TWL_Init: "
L"Failed create interrupt thread\r\n"
));
goto cleanUp;
}
// Set thread priority
CeSetThreadPriority(pDevice->hIntrThread, pDevice->priority256);
// Return non-null value
rc = (DWORD)pDevice;
cleanUp:
if (rc == 0) TWL_Deinit((DWORD)pDevice);
DEBUGMSG(ZONE_FUNCTION, (L"-TWL_Init(rc = %d\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: TWL_Deinit
//
// Called by device manager to uninitialize device.
//
BOOL
TWL_Deinit(
DWORD context
)
{
BOOL rc = FALSE;
Device_t *pDevice = (Device_t*)context;
DEBUGMSG(ZONE_FUNCTION, (L"+TWL_Deinit(0x%08x)\r\n", context));
// Check if we get correct context
if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE))
{
DEBUGMSG (ZONE_ERROR, (L"ERROR: TWL_Deinit: "
L"Incorrect context paramer\r\n"
));
goto cleanUp;
}
// Close interrupt thread
if (pDevice->hIntrThread != NULL)
{
// Signal stop to thread
pDevice->intrThreadExit = TRUE;
// Set event to wake it
SetEvent(pDevice->hIntrEvent);
// Wait until thread exits
WaitForSingleObject(pDevice->hIntrThread, INFINITE);
// Close handle
CloseHandle(pDevice->hIntrThread);
}
// Disable interrupt
if (pDevice->sysIntr != 0)
{
InterruptDisable(pDevice->sysIntr);
KernelIoControl(
IOCTL_HAL_RELEASE_SYSINTR, &pDevice->sysIntr,
sizeof(pDevice->sysIntr), NULL, 0, NULL
);
}
// Close interrupt handler
if (pDevice->hIntrEvent != NULL) CloseHandle(pDevice->hIntrEvent);
// Close I2C bus
if (pDevice->hI2C != NULL) I2CClose(pDevice->hI2C);
if (pDevice->hICX != NULL) CloseHandle(pDevice->hICX);
// Delete critical section
DeleteCriticalSection(&pDevice->cs);
// Free device structure
LocalFree(pDevice);
// Done
rc = TRUE;
cleanUp:
DEBUGMSG(ZONE_FUNCTION, (L"-TWL_Deinit(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: TWL_Open
//
// Called by device manager to open a device for reading and/or writing.
//
DWORD
TWL_Open(
DWORD context,
DWORD accessCode,
DWORD shareMode
)
{
return context;
}
//------------------------------------------------------------------------------
//
// Function: TWL_Close
//
// This function closes the device context.
//
BOOL
TWL_Close(
DWORD context
)
{
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: TWL_IOControl
//
// This function sends a command to a device.
//
BOOL
TWL_IOControl(
DWORD context,
DWORD code,
UCHAR *pInBuffer,
DWORD inSize,
UCHAR *pOutBuffer,
DWORD outSize,
DWORD *pOutSize
)
{
BOOL rc = FALSE;
Device_t *pDevice = (Device_t*)context;
DEVICE_IFC_TWL ifc;
DWORD address, size;
DEBUGMSG(ZONE_FUNCTION, (
L"+TWL_IOControl(0x%08x, 0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x)\r\n",
context, code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
));
// Check if we get correct context
if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE))
{
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IOControl: "
L"Incorrect context paramer\r\n"
));
goto cleanUp;
}
switch (code)
{
case IOCTL_DDK_GET_DRIVER_IFC:
// We can give interface only to our peer in device process
if (GetCurrentProcessId() != (DWORD)GetCallerProcess())
{
DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IOControl: "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -