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

📄 cspiclass.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// 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 <Devload.h>

#include "csp.h"
#include "cspibus.h"
#include "cspiClass.h"

//------------------------------------------------------------------------------
// External Functions
extern "C" UINT32 BSPCSPICalculateDivRate(UINT32 dwFrequency);
extern "C" BOOL BSPCSPISetIOMux(UINT32 Index);
extern "C" BOOL BSPCSPIReleaseIOMux(UINT32 dwIndex);
extern "C" BOOL BSPCSPIEnableClock(UINT32 dwIndex, BOOL bEnable);

//------------------------------------------------------------------------------
// External Variables

//------------------------------------------------------------------------------
// Defines

//------------------------------------------------------------------------------
// Types

//------------------------------------------------------------------------------
// Global Variables

//------------------------------------------------------------------------------
// Local Variables

//------------------------------------------------------------------------------
// Local Functions

//------------------------------------------------------------------------------
//
// Function: cspiClass
//
// The constructor of the class.
//
// Parameters:
//		None.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
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_bUsePolling   = FALSE;
    
	DEBUGMSG(ZONE_INIT, (TEXT("cspiClass -\r\n")));
}

//------------------------------------------------------------------------------
//
// Function: ~cspiClass
//
// The destructor of the class.
//
// Parameters:
//		None.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
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_nIndex = 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;
    }
   
    if (Index == 1) { 			// If request is for CSPI1
        phyAddr.QuadPart = CSP_BASE_REG_PA_CSPI1;
        irq = IRQ_CSPI1;
    } else if (Index == 2) { 	// If request is for CSPI2
        phyAddr.QuadPart = CSP_BASE_REG_PA_CSPI2;
        irq = IRQ_CSPI2;
    } else if (Index == 3) { 	// If request is for CSPI3
        phyAddr.QuadPart = CSP_BASE_REG_PA_CSPI3;
        irq = IRQ_CSPI3;
    } else { 					// Else invalid CSPI instance
        DEBUGMSG(ZONE_ERROR, (TEXT("CspiInitialize: Invalid CSPI instance!\r\n")));
        goto Error;
    }

	// Configure IOMUX 
	BSPCSPISetIOMux(Index);

    // Map peripheral physical address to virtual address
    m_pCSPI = (PCSP_CSPI_REGS)MmMapIoSpace(phyAddr, sizeof(CSP_CSPI_REGS), 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
    INSREG32BF(&m_pCSPI->CONTROLREG, CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_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_nIndex);

    // 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_REGS));
        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")));
    return;
}

//------------------------------------------------------------------------------
//
// 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
#if 0 //CE5
    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);
#else //CE6 directly
    pMappedXchPtr = (PCSPI_XCH_PKT_T)pXchPkt;

    // Now we can dereference the mapped pointer and map other caller pointers
    pXchListEntry->xchPkt.pBusCnfg = (PCSPI_BUSCONFIG_T)pMappedXchPtr->pBusCnfg;
    pXchListEntry->xchPkt.pTxBuf = (LPVOID) pMappedXchPtr->pTxBuf;
    pXchListEntry->xchPkt.pRxBuf = (LPVOID) pMappedXchPtr->pRxBuf;
#endif

    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 + -