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

📄 lmidma.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
字号:

#include "LMIfuncs.h"
#include "Dma.h"

//LMI DMA peripheral number
#define LMI_Tx_ID 30

/*! \brief  allocate dma channel for lmi data transfer.
 *          and initalize interrupt
 *  \params hHead     :the LMI driver head structure point
 *  \return BOOL      :indicate success or not.
 */
BOOL LMIInitDma(PLMI_Header pHead)
{
   BOOL fRC = TRUE;
   DWORD   dwRet;  
   
    	//LMI DMA -         
        PLMI_DMA_INFO pDma = &(pHead->DmaInfo);
        ALLOCATE_DMA_PARAMS AllocateDMAParams;
        ALLOCATE_DMA_RESULT AllocateDMAResult;
        
                
        // UART Tx Channel Alloc.
        AllocateDMAParams.ucSourceDevice = 0;         // Memory
        AllocateDMAParams.ucDestDevice = LMI_Tx_ID;   // Tx
        AllocateDMAParams.ucPreferedPriority = 0xff;  // no preference
        
        if(!KernelIoControl(IOCTL_HAL_ALLOCATE_DMA_CHANNEL,
            &AllocateDMAParams, sizeof(AllocateDMAParams),
            &AllocateDMAResult, sizeof(AllocateDMAResult), &dwRet))
        {            
            // No channels available
            SetLastError(ERROR_ALREADY_ASSIGNED);
            LMICloseDma(pDma);
            return FALSE;
        }
	
        // Save the channel number and interrupt id
        pDma->ucTxDMAChannel = AllocateDMAResult.ucChannelNumber;
        pDma->dwTxDMASysIntr = AllocateDMAResult.dwInterruptID;

        // Create the DMA interrupt event for the Tx
        pDma->hTxUDmaISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if(pDma->hTxUDmaISTEvent == NULL)
        {
            RETAILMSG(1, 
                (TEXT("PDD_Open: Error creating Tx DMA Interrupt event\r\n")));
            LMICloseDma(pDma);
            return FALSE;
        }        
        // Enable the DMA interrupt for Tx
        if(!InterruptInitialize(pDma->dwTxDMASysIntr, pDma->hTxUDmaISTEvent, NULL, 0))
        {
            RETAILMSG(1, 
                (TEXT("PDD_Open: Error enabling Tx DMA interrupt (%d)\r\n"), 
                GetLastError()));
            LMICloseDma(pDma);
            return FALSE;
        }
	
    //End of LMI DMA   
    
    return fRC;
}


/*! \brief  initialize dma channel and start dma for lmi data transfer.
 *  
 *  \params hHead     :the LMI driver head structure point
 *  \params pTxBuffer : the source of the Txbuffer
 *  \params pBuffLen  : the length of the data in buffer.
 *  \return void
 */
void LMIStartDma(PLMI_Header  pHead,ULONG* pTxBuffer, ULONG *pBuffLen)
{	
        PLMI_DMA_INFO pLmiDma = (PLMI_DMA_INFO)(&(pHead->DmaInfo));
        INITIALIZE_DMA_PARAMS   InitializeDMAParams;
        INITIALIZE_DMA_RESULT   InitializeDMAResult;
        START_DMA_PARAMS        StartDMAParams;
        START_DMA_RESULT        StartDMAResult;
        PVOID   pvSourceBuffer = pTxBuffer;
        ULONG   dwRet,Dest,DbufOffset;
        int dwPages;
        unsigned long   *Dbuf;
        ULONG BufLen=*pBuffLen,BufLenByte=0;
        int i=0;
        
        //UART Tx Channel Init.
        InitializeDMAParams.ucChannelNumber = pLmiDma->ucTxDMAChannel;
        InitializeDMAParams.ucSourceWidth = TRANSFER_WIDTH_DWORD; // Mem - DWORD
        InitializeDMAParams.ucDestWidth = TRANSFER_WIDTH_WORD; // Tx 16 bit

        InitializeDMAParams.ucSourceBurstSize = BURST_SIZE_4;
        InitializeDMAParams.ucDestBurstSize = BURST_SIZE_16;

        //Mem->Per, DMA as flow controller
        InitializeDMAParams.ucFlowControl = FLOW_MEM_PER_DMAC;

        // Increment source and keep destination constant
        InitializeDMAParams.fIncrementSource = TRUE;
        InitializeDMAParams.fIncrementDest = FALSE;

        if(!KernelIoControl(IOCTL_HAL_INITIALIZE_DMA_CHANNEL,
            &InitializeDMAParams, sizeof(InitializeDMAParams),
            &InitializeDMAResult, sizeof(InitializeDMAResult), &dwRet))
        {
            RETAILMSG (1,
               (TEXT("PDD: Tx, Error - Cannot initialize DMA channel\r\n")));
            *pBuffLen = 0;
            return;
        }

		//Only transfer DWORD aligned size
        BufLen = (BufLen >> 2)<< 2;
        BufLenByte = BufLen<<2;
        // map the pointer to callers memory
	    Dbuf = (unsigned long *)MapPtrToProcess(pvSourceBuffer, GetCallerProcess());
	    //Dbuf = (unsigned long *)pvSourceBuffer;
		
		//the offset from the page edge. add (3.8)
		DbufOffset = (unsigned long)BYTE_OFFSET(Dbuf);

	    dwPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Dbuf,BufLenByte);
	    
        //we need to use DMA API
        pLmiDma->pdwTxSourcePageList = (PDWORD)malloc(dwPages*sizeof(DWORD));
        
        if (pLmiDma->pdwTxSourcePageList == NULL)
        {
            RETAILMSG (1,
                (TEXT("PDD: Error - Cannot allocate for TxSourcePageList\r\n")));
            *pBuffLen = 0;
            return;
        }
         //change (3.8.2005)                    
        if(!LockPages((unsigned long*)(((unsigned long)Dbuf)-DbufOffset),
			BufLenByte+DbufOffset, (pLmiDma->pdwTxSourcePageList),LOCKFLAG_READ))
        {
            RETAILMSG (1, (TEXT("PDD: Error - Cannot lock pages\r\n")));
            free(pLmiDma->pdwTxSourcePageList);
            *pBuffLen = 0;
            return;
        }
        // Just double check page alignment
        for(i=0;i<dwPages;i++)
		{
			pLmiDma->pdwTxSourcePageList[i] &= ~(unsigned long)(PAGE_SIZE - 1);
		}
		//change 3.8
        pLmiDma->pdwTxSourcePageList[0]+=DbufOffset;

        pLmiDma->dwTxSourceSize = BufLen;
        StartDMAParams.ucChannelNumber = pLmiDma->ucTxDMAChannel;
        
        Dest = (ULONG) (&(((LMIReg*)LMI_BASE)->DATA));    // LMI Physical address
        
        StartDMAParams.pdwDestBuffer = &Dest;
        StartDMAParams.pdwSourceBuffer = pLmiDma->pdwTxSourcePageList;
        StartDMAParams.dwTransferSize = BufLenByte;
        
        if(!KernelIoControl(IOCTL_HAL_START_DMA_TRANSFER,
            &StartDMAParams, sizeof(StartDMAParams),
            &StartDMAResult, sizeof(StartDMAResult), &dwRet))
        {
            RETAILMSG (1, 
                (TEXT("PDD: Error - Cannot start DMA transfer\r\n")));
            // Unlock the virtual pages so that they can be paged out
            UnlockPages(pvSourceBuffer, PAGE_SIZE);
            free(pLmiDma->pdwTxSourcePageList);
            *pBuffLen = 0;
            return;
        }        
        dwRet = WaitForSingleObject(pLmiDma->hTxUDmaISTEvent, INFINITE);
        
        UnlockPages(Dbuf, BufLenByte);
        free(pLmiDma->pdwTxSourcePageList);
        InterruptDone(pLmiDma->dwTxDMASysIntr);                
}



BOOL LMICloseDma(PLMI_DMA_INFO pDma)
{
    BOOL RetCode = TRUE;
    DWORD   dwRet;
    FREE_DMA_PARAMS FreeDMAParams;
    FREE_DMA_RESULT FreeDMAResult;
   
    if ( pDma->OpenCnt ) 
    {
        --(pDma->OpenCnt);

        //VirtualFree(pDma->pvRxDestBuffer, PAGE_SIZE, MEM_DECOMMIT);
        //VirtualFree(pDma->pvTxSourceBuffer, PAGE_SIZE, MEM_DECOMMIT);
        RETAILMSG (1, (TEXT("PDD Dma_Close: (%d handles)\r\n"), pDma->OpenCnt));

        // Free DMA Rx channel
        /*FreeDMAParams.ucChannelNumber = pDma->ucRxDMAChannel;
        if(!KernelIoControl(IOCTL_HAL_FREE_DMA_CHANNEL,
            &FreeDMAParams, sizeof(FreeDMAParams),
            &FreeDMAResult, sizeof(FreeDMAResult), &dwRet))
        {
            RETAILMSG (ZONE_ERROR, (TEXT("!!PDD Dma_Close: Cannot free DMA Rx channel!\r\n")));
            return FALSE;
        }*/

        // Free DMA Tx channel
        FreeDMAParams.ucChannelNumber = pDma->ucTxDMAChannel;
        if(!KernelIoControl(IOCTL_HAL_FREE_DMA_CHANNEL,
            &FreeDMAParams, sizeof(FreeDMAParams),
            &FreeDMAResult, sizeof(FreeDMAResult), &dwRet))
        {
            RETAILMSG (1, (TEXT("!!PDD Dma_Close: Cannot free DMA Tx channel!\r\n")));
            return FALSE;
        }

        //if(pDma->hRxUDmaISTEvent) 
         //   CloseHandle(pDma->hRxUDmaISTEvent);
        if(pDma->hTxUDmaISTEvent) 
            CloseHandle(pDma->hTxUDmaISTEvent);
        //InterruptDisable(pDma->dwRxDMASysIntr);
        InterruptDisable(pDma->dwTxDMASysIntr);
    } 
    else 
    {
        RETAILMSG (1, (TEXT("!!Close of non-open device\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);        
        RetCode = FALSE;
    }
    
    return RetCode;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -