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

📄 cspiclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
//
//  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 + -