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

📄 ibmdma.c

📁 移植好的Ibm405ep bsp板极支持包
💻 C
字号:
/* ibmDma.c - IBM DMA controller driver */

/*******************************************************************************
   This source and object code has been made available to you by IBM on an
   AS-IS basis.

   IT IS PROVIDED WITHOUT WARRANTY OF ANY KIND, INCLUDING THE WARRANTIES OF
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE OR OF NONINFRINGEMENT
   OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL IBM OR ITS LICENSORS BE LIABLE
   FOR INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES.  IBM扴 OR ITS LICENSOR扴
   DAMAGES FOR ANY CAUSE OF ACTION, WHETHER IN CONTRACT OR IN TORT, AT LAW OR
   AT EQUITY, SHALL BE LIMITED TO A MAXIMUM OF $1,000 PER LICENSE.  No license
   under IBM patents or patent applications is to be implied by the copyright
   license.

   Any user of this software should understand that neither IBM nor its
   licensors will be responsible for any consequences resulting from the use
   of this software.

   Any person who transfers this source code or any derivative work must
   include the IBM copyright notice, this paragraph, and the preceding two
   paragraphs in the transferred software.

   Any person who transfers this object code or any derivative work must
   include the IBM copyright notice in the transferred software.

   COPYRIGHT   I B M   CORPORATION 2000
   LICENSED MATERIAL  -  PROGRAM PROPERTY OF  I B M

*******************************************************************************/

#include "vxWorks.h"
#include "semaphore.h"
#include "intLib.h"
#include "ibmDma.h"
#include "sysDcr.h"

/* modification history
-----------------------
01c,16jul02,mcg  use constants for transfer widths in ibmDmaMemToMem
01b,18apr01,ajm  fix uninitialized return code in ibmDmaMemToMem
01a,18dec00,mcg  created
*/

/*
This driver provides functions to initialize and configure the IBM 4 channel DMA
controller macro.
*/

#undef  DMA_DEBUG

typedef struct ibmDma
    {
    int channel;
    SEM_ID dmaChnMutex;
    SEM_ID dmaChnIntSem;
    } IBM_DMA_CTRL;


/*
 * Locals
 */

LOCAL UINT ibmDmaInit = FALSE;
LOCAL IBM_DMA_CTRL ibmDmaCtrl[4];



/*******************************************************************************
*
* ibmDmaInt - Interrupt handler for DMA channel interrupts
*
* This routine performs a software reset on the Memory Access Layer (MAL) core.
*
* RETURNS: N/A
*
*/
void ibmDmaInt(IBM_DMA_CTRL * pDmaChan)
    {

    /* Clear the interrupt source (Terminal Count Status) */

    switch (pDmaChan->channel)
        {
        case 0 :
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_0);
            break;
        case 1 :
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_1);
            break;
        case 2 :
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_2);
            break;
        case 3 :
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_3);
            break;
        default:
            break;
        }

    /* Give the semaphore back */

    semGive(pDmaChan->dmaChnIntSem);

    }

/*******************************************************************************
*
* ibmDmaDrvInit - initialize the IBM DMA controller driver
*
* This routine initializes the IBM DMA controller and driver.
*
* RETURNS: OK, or ERROR
*
*/
STATUS ibmDmaDrvInit(void)
    {

    int i;

    if (ibmDmaInit != FALSE)
        return(ERROR);

    /* Disable all channels */

    sysDcrOutLong(DMA0_CR0, 0x00000000);
    sysDcrOutLong(DMA0_CR0, 0x00000000);
    sysDcrOutLong(DMA0_CR0, 0x00000000);
    sysDcrOutLong(DMA0_CR0, 0x00000000);

    /* Clear all DMA status */

    sysDcrOutLong(DMA0_SR, 0xFFFFFFFF);

    memset(ibmDmaCtrl, 0x0, sizeof(ibmDmaCtrl));

    /*
     * Create two semaphores for each channel. One is for mutual exclusion,
     * the other for channel interrupts.
     */

    for (i=0; i< 4; i++)
        {
        ibmDmaCtrl[i].channel = i;
        ibmDmaCtrl[i].dmaChnMutex  = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
        ibmDmaCtrl[i].dmaChnIntSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
        }

    /* Connect interrupt handler for each channel */

    intConnect((VOIDFUNCPTR *)INT_VEC_DMA_CH0, ibmDmaInt, (int)&ibmDmaCtrl[0]);
    intConnect((VOIDFUNCPTR *)INT_VEC_DMA_CH1, ibmDmaInt, (int)&ibmDmaCtrl[1]);
    intConnect((VOIDFUNCPTR *)INT_VEC_DMA_CH2, ibmDmaInt, (int)&ibmDmaCtrl[2]);
    intConnect((VOIDFUNCPTR *)INT_VEC_DMA_CH3, ibmDmaInt, (int)&ibmDmaCtrl[3]);

    /* Enable interrupt for each channel in the interrupt controller */

    intEnable(INT_LVL_DMA_CH0);
    intEnable(INT_LVL_DMA_CH1);
    intEnable(INT_LVL_DMA_CH2);
    intEnable(INT_LVL_DMA_CH3);


    ibmDmaInit = TRUE;

    return(0);
    }

/*******************************************************************************
*
* ibmDmaDrvShutdown - shutdown the IBM DMA controller driver and controller
*
* This routine shuts down the IBM DMA controller and driver.
*
* RETURNS: OK, or ERROR
*
*/
STATUS ibmDmaDrvShutdown(void)
    {
    if (ibmDmaInit != TRUE)
        return(ERROR);

    /* Take all of the mutual exclusion semaphores, then delete them */

    semTake(ibmDmaCtrl[0].dmaChnMutex, WAIT_FOREVER);
    semTake(ibmDmaCtrl[1].dmaChnMutex, WAIT_FOREVER);
    semTake(ibmDmaCtrl[2].dmaChnMutex, WAIT_FOREVER);
    semTake(ibmDmaCtrl[3].dmaChnMutex, WAIT_FOREVER);

    semDelete(ibmDmaCtrl[0].dmaChnMutex);
    semDelete(ibmDmaCtrl[1].dmaChnMutex);
    semDelete(ibmDmaCtrl[2].dmaChnMutex);
    semDelete(ibmDmaCtrl[3].dmaChnMutex);

    intDisable(INT_LVL_DMA_CH0);
    intDisable(INT_LVL_DMA_CH1);
    intDisable(INT_LVL_DMA_CH2);
    intDisable(INT_LVL_DMA_CH3);

    /* Disable all channels */

    sysDcrOutLong(DMA0_CR0, 0x00000000);
    sysDcrOutLong(DMA0_CR1, 0x00000000);
    sysDcrOutLong(DMA0_CR2, 0x00000000);
    sysDcrOutLong(DMA0_CR3, 0x00000000);

    /* Clear all DMA status */

    sysDcrOutLong(DMA0_SR, 0xFFFFFFFF);

    memset(ibmDmaCtrl, 0x0, sizeof(ibmDmaCtrl));

    ibmDmaInit = FALSE;

    return(0);
    }


/*******************************************************************************
*
* ibmDmaMemToMem - perform a software initiated memory-to-memory DMA transfer
*
* This routine performs a software initiated memory-to-memory DMA transfer.
*
* RETURNS: OK, or ERROR
*
*/
STATUS ibmDmaMemToMem(UINT src,
                      UINT dst,
                      int lenBytes,
                      int channel,
                      int transferWidth)
    {

    STATUS   rc=OK;
    UINT     transferWidthMask;


#ifdef DMA_DEBUG
    logMsg("ibmDmaMemToMem src = 0x%x dst = 0x%x\n",
               src, dst, 3, 4, 5, 6);
    logMsg("               len = 0x%x chn = %d width = %d\n",
               lenBytes, channel, transferWidth, 4, 5, 6);
#endif

    switch (transferWidth)
        {
        case IBM_DMA_BYTE  :
            transferWidthMask = DMA_CR_PW_BYTE;
            break;
        case IBM_DMA_HWORD :
            transferWidthMask = DMA_CR_PW_HW;
            break;
        case IBM_DMA_WORD  :
            transferWidthMask = DMA_CR_PW_WORD;
            break;
        case IBM_DMA_DWORD :
            transferWidthMask = DMA_CR_PW_DW;
            break;
        default :
            return(ERROR);      /* unsupported transfer width */
            break;
        }

    /*
     * For the specified DMA channel:
     *   Set the source and destination address registers
     *   Set the number of transfers in the count register
     *   Clear channel specific bits in the status register
     *   Set parameters in the control register to start transfer
     */

    switch (channel)
        {
        case 0 :
            semTake(ibmDmaCtrl[0].dmaChnMutex, WAIT_FOREVER);
            sysDcrOutLong(DMA0_SA0,(UINT32)src);
            sysDcrOutLong(DMA0_DA0,(UINT32)dst);
            sysDcrOutLong(DMA0_CT0,lenBytes / transferWidth * 8);
            sysDcrOutLong(DMA0_SR, DMA_SR_CS_0 | DMA_SR_TS_0 | DMA_SR_RI_0);
            sysDcrOutLong(DMA0_CR0,DMA_CR_CIE        |
                            DMA_CR_DAI        |
                            DMA_CR_SAI        |
                            DMA_CR_BEN        |
                            DMA_CR_TM_SWMM    |
                            DMA_CR_ETD        |
                            DMA_CR_TCE        |
                            DMA_CR_CP_MEDH    |
                            transferWidthMask |
                            DMA_CR_CE);          /* let it rip */

            /* Wait for interrupt */
            semTake(ibmDmaCtrl[0].dmaChnIntSem, WAIT_FOREVER);
            semGive(ibmDmaCtrl[0].dmaChnMutex);
            break;

        case 1 :
            semTake(ibmDmaCtrl[1].dmaChnMutex, WAIT_FOREVER);
            sysDcrOutLong(DMA0_SA1,(UINT32)src);
            sysDcrOutLong(DMA0_DA1,(UINT32)dst);
            sysDcrOutLong(DMA0_CT1,lenBytes / transferWidth * 8);
            sysDcrOutLong(DMA0_SR, DMA_SR_CS_1 | DMA_SR_TS_1 | DMA_SR_RI_1);
            sysDcrOutLong(DMA0_CR1,DMA_CR_CIE        |
                            DMA_CR_DAI        |
                            DMA_CR_SAI        |
                            DMA_CR_BEN        |
                            DMA_CR_TM_SWMM    |
                            DMA_CR_ETD        |
                            DMA_CR_TCE        |
                            DMA_CR_CP_MEDH    |
                            transferWidthMask |
                            DMA_CR_CE);          /* let it rip */

            /* Wait for interrupt */
            semTake(ibmDmaCtrl[1].dmaChnIntSem, WAIT_FOREVER);
            semGive(ibmDmaCtrl[1].dmaChnMutex);
            break;

        case 2 :
            semTake(ibmDmaCtrl[2].dmaChnMutex, WAIT_FOREVER);
            sysDcrOutLong(DMA0_SA2,(UINT32)src);
            sysDcrOutLong(DMA0_DA2,(UINT32)dst);
            sysDcrOutLong(DMA0_CT2,lenBytes / transferWidth * 8);
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_2 | DMA_SR_TS_2 | DMA_SR_RI_2);
            sysDcrOutLong(DMA0_CR2,DMA_CR_CIE        |
                            DMA_CR_DAI        |
                            DMA_CR_SAI        |
                            DMA_CR_BEN        |
                            DMA_CR_TM_SWMM    |
                            DMA_CR_ETD        |
                            DMA_CR_TCE        |
                            DMA_CR_CP_MEDH    |
                            transferWidthMask |
                            DMA_CR_CE);          /* let it rip */

            /* Wait for interrupt */
            semTake(ibmDmaCtrl[2].dmaChnIntSem, WAIT_FOREVER);
            semGive(ibmDmaCtrl[2].dmaChnMutex);
            break;

        case 3 :
            semTake(ibmDmaCtrl[3].dmaChnMutex, WAIT_FOREVER);
            sysDcrOutLong(DMA0_SA3,(UINT32)src);
            sysDcrOutLong(DMA0_DA3,(UINT32)dst);
            sysDcrOutLong(DMA0_CT3,lenBytes / transferWidth * 8);
            sysDcrOutLong(DMA0_SR,DMA_SR_CS_3 | DMA_SR_TS_3 | DMA_SR_RI_3);
            sysDcrOutLong(DMA0_CR3,DMA_CR_CIE        |
                            DMA_CR_DAI        |
                            DMA_CR_SAI        |
                            DMA_CR_BEN        |
                            DMA_CR_TM_SWMM    |
                            DMA_CR_ETD        |
                            DMA_CR_TCE        |
                            DMA_CR_CP_MEDH    |
                            transferWidthMask |
                            DMA_CR_CE);          /* let it rip */

            /* Wait for interrupt */
            semTake(ibmDmaCtrl[3].dmaChnIntSem, WAIT_FOREVER);
            semGive(ibmDmaCtrl[3].dmaChnMutex);
            break;

        default :
            return(ERROR);
            break;
        }


    return(rc);

    }

⌨️ 快捷键说明

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