📄 cspiclass.cpp
字号:
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// File: cspiClass.cpp
//
// Provides the implementation of the CSPI bus driver to support CSPI
// transactions from multiple client drivers.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <linklist.h>
#include "mxarm11.h"
#include "cspibus.h"
#include "cspiClass.h"
#include <Devload.h>
//-----------------------------------------------------------------------------
// External Functions
extern "C" UINT32 BSPCSPICalculateDivRate(UINT32 dwFrequency);
extern "C" BOOL BSPCSPISetIOMux(UINT32 Index);
extern "C" BOOL BSPCSPIEnableClock(UINT32 Index, BOOL bEnable);
extern "C" BOOL BSPCSPIReleaseIOMux(UINT32 dwIndex);
extern "C" DWORD CspCSPIGetBaseRegAddr(UINT32 index);
extern "C" DWORD CspCSPIGetIRQ(UINT32 index);
extern "C" UINT8 BSPCspiGetChannelPriority(void);
extern "C" DDK_DMA_REQ CspCSPIGetDmaReqTx(UINT32 index);
extern "C" DDK_DMA_REQ CspCSPIGetDmaReqRx(UINT32 index);
extern "C" BOOL BSPCspiIsDMAEnabled(UINT8 Index);
extern "C" BOOL BSPCspiAcquireGprBit(UINT8 Index);
//-----------------------------------------------------------------------------
// External Variables
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// Local Functions
cspiClass::cspiClass()
{
DEBUGMSG(ZONE_INIT, (TEXT("cspiClass +\r\n")));
m_pCSPI = NULL;
m_cspiOpenCount = 0;
m_hIntrEvent = NULL;
m_hEnQEvent = NULL;
m_hThread = NULL;
m_hHeap = NULL;
m_dwSysIntr = SYSINTR_UNDEFINED;
m_bTerminate = FALSE;
m_dxCurrent = D0;
m_Index = 0;
m_bUsePolling = FALSE;
DEBUGMSG(ZONE_INIT, (TEXT("cspiClass -\r\n")));
}
cspiClass::~cspiClass()
{
DEBUGMSG(ZONE_INIT, (TEXT("~cspiClass\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: CspiInitialize
//
// Initializes the CSPI interface and data structures.
//
// Parameters:
// Index
// [in] CSPI instance (1 = CSPI1, 2 = CSP2) to initialize
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
BOOL cspiClass::CspiInitialize(DWORD Index)
{
PHYSICAL_ADDRESS phyAddr;
DWORD irq;
m_Index = Index;
// create global heap for internal queues/buffers
// flOptions = 0 => no options
// dwInitialSize = 0 => zero bytes initial size
// dwMaximumSize = 0 => heap size limited only by available memory
DEBUGMSG(ZONE_INIT, (TEXT("CspiInitialize: m_hHeap=0x%x\r\n"),m_hHeap));
m_hHeap = HeapCreate(0, 0, 0);
// check if HeapCreate failed
if (m_hHeap == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: HeapCreate failed!\r\n")));
goto Error;
}
// create event for CSPI interrupt signaling
// pEventAttributes = NULL (must be NULL)
// bManualReset = FALSE => resets automatically to nonsignaled
// state after waiting thread released
// bInitialState = FALSE => initial state is non-signaled
// lpName = NULL => object created without a name
m_hIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// check if CreateEvent failed
if (m_hIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: CreateEvent failed!\r\n")));
goto Error;
}
// create event for process queue thread signaling
// pEventAttributes = NULL (must be NULL)
// bManualReset = FALSE => resets automatically to nonsignaled
// state after waiting thread released
// bInitialState = FALSE => initial state is non-signaled
// lpName = NULL => object created without a name
m_hEnQEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// check if CreateEvent failed
if (m_hEnQEvent == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: CreateEvent failed!\r\n")));
goto Error;
}
// Get the Base Address and IRQ according to Index
phyAddr.QuadPart = CspCSPIGetBaseRegAddr(Index);
irq = CspCSPIGetIRQ(Index);
if(!irq || !phyAddr.QuadPart)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: invalid CSPI instance!\r\n")));
goto Error;
}
m_bUseDMA = BSPCspiIsDMAEnabled((UINT8)Index);
if (m_bUseDMA)
{
InitCspiDMA(Index);
BSPCspiAcquireGprBit((UINT8)Index);
}
// Configure IOMUX
BSPCSPISetIOMux(Index);
// Map peripheral physical address to virtual address
m_pCSPI = (PCSP_CSPI_REG) MmMapIoSpace(phyAddr, sizeof(CSP_CSPI_REG),
FALSE);
// Check if virtual mapping failed
if (m_pCSPI == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: MmMapIoSpace failed!\r\n")));
goto Error;
}
// Call the OAL to translate the IRQ into a SysIntr value.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(DWORD),
&m_dwSysIntr, sizeof(DWORD), NULL))
{
RETAILMSG(1, (TEXT("ERROR: Failed to obtain sysintr value for CSPI interrupt.\r\n")));
goto Error;
}
// register CSPI interrupt
if (!InterruptInitialize(m_dwSysIntr, m_hIntrEvent, NULL, 0))
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: InterruptInitialize failed!\r\n")));
goto Error;
}
// create CSPI critical section
InitializeCriticalSection(&m_cspiCs);
// create CSPI Data Exchange critical section
InitializeCriticalSection(&m_cspiDataXchCs);
// initialize CSPI linked list of client queue entries
InitializeListHead(&m_ListHead);
DEBUGMSG(ZONE_INIT, (TEXT("CspiInitialize: &m_pCSPI=0x%x\r\n"),&m_pCSPI));
// disable CSPI to reset internal logic
INSREG32(&m_pCSPI->CONREG, CSP_BITFMASK(CSPI_CONREG_EN),
CSP_BITFVAL(CSPI_CONREG_EN, CSPI_CONREG_EN_DISABLE));
// create CSPI queue processing thread if it does not exist
if (!m_hThread)
{
// set global termination flag
m_bTerminate=FALSE;
// create processing thread
// pThreadAttributes = NULL (must be NULL)
// dwStackSize = 0 => default stack size determined by linker
// lpStartAddress = CspiProcessQueue => thread entry point
// lpParameter = NULL => point to thread parameter
// dwCreationFlags = 0 => no flags
// lpThreadId = NULL => thread ID is not returned
m_hThread = ::CreateThread(NULL, 0, CspiProcessQueue, this, 0, NULL);
DEBUGMSG(ZONE_INIT, (TEXT("CspiInitialize: this=0x%x\r\n"),this));
// check if CreateThread failed
if (m_hThread == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: CreateThread failed!\r\n")));
goto Error;
}
}
m_cspiOpenCount++;
return TRUE;
Error:
CspiRelease();
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: CspiRelease
//
// Frees allocated memory, closes reference to handles, and resets the state
// of global member variables.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void cspiClass::CspiRelease()
{
DEBUGMSG(ZONE_CLOSE, (TEXT("CspiRelease +\r\n")));
// kill the exchange packet processing thread
if (m_hThread)
{
m_bTerminate=TRUE;
// try to signal the thread so that it can wake up and terminate
if (m_hEnQEvent)
{
SetEvent(m_hEnQEvent);
}
CloseHandle(m_hThread);
m_hThread = NULL;
}
// Release IOMUX pins
BSPCSPIReleaseIOMux(m_Index);
// Release SYSINTR
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &m_dwSysIntr, sizeof(DWORD), NULL, 0, NULL);
m_dwSysIntr = SYSINTR_UNDEFINED;
// destroy the heap
if (m_hHeap != NULL)
{
HeapDestroy(m_hHeap);
m_hHeap = NULL;
}
// close interrupt event handle
if (m_hIntrEvent)
{
CloseHandle(m_hIntrEvent);
m_hIntrEvent = NULL;
}
// close enqueue event handle
if (m_hEnQEvent)
{
CloseHandle(m_hEnQEvent);
m_hEnQEvent = NULL;
}
// free the virtual space allocated for CSPI memory map
if (m_pCSPI != NULL)
{
MmUnmapIoSpace(m_pCSPI, sizeof(CSP_CSPI_REG));
m_pCSPI = NULL;
}
// deregister the system interrupt
if (m_dwSysIntr != SYSINTR_UNDEFINED)
{
InterruptDisable(m_dwSysIntr);
m_dwSysIntr = SYSINTR_UNDEFINED;
}
// delete the critical section
DeleteCriticalSection(&m_cspiCs);
// delete the Data Exchange critical section
DeleteCriticalSection(&m_cspiDataXchCs);
DEBUGMSG(ZONE_CLOSE, (TEXT("CspiRelease -\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: CspiEnqueue
//
// This function is invoked as a result of a CSPI client driver calling
// the CSPI DeviceIoControl with CSPI_IOCTL_EXCHANGE. This function
//
//
// Parameters:
// pData
// [in]
//
// Returns:
// Returns a handle to the newly created msg queue, or NULL if the
// msg queue creation failed.
//
//-----------------------------------------------------------------------------
BOOL cspiClass::CspiEnqueue(PCSPI_XCH_PKT_T pXchPkt)
{
PCSPI_XCH_LIST_ENTRY_T pXchListEntry = NULL;
PCSPI_XCH_PKT_T pMappedXchPtr;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CspiEnqueue +\r\n")));
// allocate space for new list entry
pXchListEntry = (PCSPI_XCH_LIST_ENTRY_T) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY,
sizeof(CSPI_XCH_LIST_ENTRY_T));
// check if HeapAlloc failed (fatal error, terminate thread)
if (pXchListEntry == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("CspiProcessQueue: HeapAlloc failed!\r\n")));
return FALSE;
}
// map caller exchange packet pointer to our process space
pMappedXchPtr = (PCSPI_XCH_PKT_T) MapCallerPtr(pXchPkt,
sizeof(CSPI_XCH_PKT_T));
// now we can dereference the mapped pointer and map other caller pointers
pXchListEntry->xchPkt.pBusCnfg = (PCSPI_BUSCONFIG_T) MapCallerPtr(pMappedXchPtr->pBusCnfg,
sizeof(CSPI_BUSCONFIG_T));
pXchListEntry->xchPkt.pTxBuf = (LPVOID) MapCallerPtr(pMappedXchPtr->pTxBuf,
pMappedXchPtr->xchCnt);
pXchListEntry->xchPkt.pRxBuf = (LPVOID) MapCallerPtr(pMappedXchPtr->pRxBuf,
pMappedXchPtr->xchCnt);
pXchListEntry->xchPkt.xchCnt = pMappedXchPtr->xchCnt;
pXchListEntry->xchPkt.xchEvent = pMappedXchPtr->xchEvent;
// Check whether the completion event is NULL
// If it's NULL, then send the package immediately
if (pXchListEntry->xchPkt.xchEvent == NULL)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("CspiEnqueue: Sending the package immediately\r\n")));
// Wrap the exchange in critical section to
// serialize accesses with CspiProcessQueue thread
EnterCriticalSection(&m_cspiDataXchCs);
pXchListEntry->xchPkt.xchCnt = CspiDataExchange(&pXchListEntry->xchPkt);
LeaveCriticalSection(&m_cspiDataXchCs);
return TRUE;
}
// wrap linked list insert operation in critical section to
// serialize accesses with CspiProcessQueue thread
EnterCriticalSection(&m_cspiCs);
// insert exchange packet into our list
InsertTailList(&m_ListHead, &(pXchListEntry->link));
LeaveCriticalSection(&m_cspiCs);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CspiEnqueue -\r\n")));
// signal queue processing thread that a new packet is ready
return SetEvent(m_hEnQEvent);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -