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

📄 vxdmaintctrl.c

📁 sbc7410的vxworksbsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
*                   Copyright 2002, GALILEO TECHNOLOGY, LTD.                   *
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.                      *
* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT  *
* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE        *
* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.     *
* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,       *
* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.   *
*                                                                              *
* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL    *
* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.  *
* (MJKK), GALILEO TECHNOLOGY LTD. (GTL) AND GALILEO TECHNOLOGY, INC. (GTI).    *
********************************************************************************
* vxDmaIntCtrl.c - GT DMA interrurpt controller library
*
* DESCRIPTION:
*       This driver provides various interface routines to manipulate and
*       connect the hardware interrupts concerning the GT DMA facility.
*
*       Main features:
*        - The controller provides an easy way to hook a C Interrupt Service
*          Routine (ISR) to a specific interrupt caused by the GT DMA engines.
*        - The controller interrupt mechanism provides a way for the programmer
*          to set the priority of an interrupt.
*        - Full interrupt control over the GT DMA facility.
*
*       Overall Interrupt Architecture description:
*        The GT handles interrupts in two stages:
*        STAGE 1: Main Cause register that summarize the interrupts generated 
*                 by each Internal GT unit.
*        STAGE 2: Unit specified cause registers, that distinguish between each
*                 specific interrupt event.
*        This DMA Interrupt Controller Driver handles the various interrupts 
*        generated by the second stage.
*
*       All DMA various interrupt causes are numbered using the DMA_CAUSE
*       enumerator. Thus there are 64 interrupts causes (most of them are
*       Reserved) divided into two groups:
*       The DMA channels 0-3 interrupt causes (DMA_CAUSE 0 - 31)
*       and DMA channels 4-7 interrupt causes (DMA_CAUSE 32 - 63).
*
*       The driver's execution flow has three phases:
*        1) Driver initialization. This initiation includes hooking driver's 
*           ISR to the GT Interrupt controller. Composed of vxDmaIntCtrlInit() 
*           routine.
*        2) User ISR connecting. Here information about user ISR and interrupt 
*           priority is gathered. Composed of vxDmaIntConnect() routine.
*        3) Interrupt handler. Here an interrupt is being handle by the 
*           Interrupt Handlers (driver's ISR). Composed of vxDmaInt(), 
*
*       Full API:    
*         vxDmaInit()        - Initiate the DMA driver.
*         vxDmaIntConnect()  - Connect a user ISR to a DMA interrupt event.
*         vxDmaIntEnable()   - Enable a given DMA interrupt cause.
*         vxDmaIntDisable()  - Disable a given DMA interrupt cause.
*         dma0_1CompInt() 	 - Handle DMA 0-1 completion interrupts.
*         dma2_3CompInt() 	 - Handle DMA 2-3 completion interrupts.
*         dma4_5CompInt() 	 - Handle DMA 4-5 completion interrupts.
*         dma6_7CompInt() 	 - Handle DMA 6-7 completion interrupts.
*         dmaErrorInt() 	 - Handle DMA 0-7 Error interrupts.
*
*       The controller concept is very simple:
*        Each of the Interrupt handlers has a table which holds information on 
*        the connected ISR. For example, dma2_3CompInt() has dma2_3Array[] 
*        which holds the ISR concerning DMA engines 2 and 3.
*        An Interrupt generated by one of those DMA engines will result a 
*        search through this table in order to allocate the generating 
*        interrupt cause.
*        After the initiating interrupt cause is identify, the ISR reside in 
*        the same table entry is executed.
*       
*       The controller interface also includes interrupt control routines which
*       can enable/disable specific interrupts: vxDmaIntDisable() and
*       vxDmaIntEnable().
*   
* DEPENDENCIES:
*		GT Interrupt Control Driver.
*		VxWorks types and interrupt lib.
*
*******************************************************************************/

/* includes */
#include <vxWorks.h>
#include <intLib.h>
#include <logLib.h>
#include "gt64260def.h"
#include "sysGt64260IntrCtl.h"
#include "drv/gtDma/vxDmaIntCtrl.h" 
#define NONE_CACHEABLE(address) (address) 

#ifndef GT64260_BASE_ADRS
#define GT64260_BASE_ADRS 0xf1000000
#endif

#define REG_ADDR(offset)    (NONE_CACHEABLE(GT64260_BASE_ADRS| (offset)))
#define REG_CONTENT(offset) ((volatile unsigned int)                           \
                                               *(unsigned int*)REG_ADDR(offset))
#define GT_WORD_SWAP(x) LONGSWAP(x)
#define SWAP_CAUSE_BIT(cause)     (GT_WORD_SWAP(1 << ((cause) % 32)))
/* defines  */
#define DMA0_3_CAUSE        ( 0 <= cause && cause <= 31)
#ifdef INCLUDE_DMA_4_7
    #define DMA4_7_CAUSE    (32 <= cause && cause <= 63)
#endif

#define DMA0_3_CAUSE_REG     REG_CONTENT(DMA_CH0_3_INT_CAUSE)
#define DMA0_3_MASK_REG      REG_CONTENT(DMA_CH0_3_INT_MASK)

#ifdef INCLUDE_DMA_4_7
    #define DMA4_7_CAUSE_REG REG_CONTENT(DMA_CH4_7_INT_CAUSE)
    #define DMA4_7_MASK_REG  REG_CONTENT(DMA_CH4_7_INT_MASK)
#endif


#ifndef true
#define true 1
#endif


#ifndef INUM_TO_IVEC
#define INUM_TO_IVEC(x)  (void *)(x)
#endif 

/* typedefs */
typedef struct _gtIsrEntry {
    UINT        causeBit;  /* A specific cause bit in the cause register.*/
    VOIDFUNCPTR userISR;   /* A user ISR pointer.*/
    int         arg;       /* An argument to interrupt ISR. */
    int         prio;      /* An interrupt priority. */
} GT_ISR_ENTRY;


/* locals   */

/* GT_ISR_ENTRY array accumulates user ISR information for each dma group. */
LOCAL GT_ISR_ENTRY dma0_1Array[2];          /* DMA completion interrupt */
LOCAL GT_ISR_ENTRY dma2_3Array[2];          /* DMA completion interrupt */
#ifdef INCLUDE_DMA_4_7
LOCAL GT_ISR_ENTRY dma4_5Array[2];          /* DMA completion interrupt */
LOCAL GT_ISR_ENTRY dma6_7Array[2];          /* DMA completion interrupt */
#endif

LOCAL GT_ISR_ENTRY dmaError0_3Array[32];    /* DMA 0-3 Error condition  */
#ifdef INCLUDE_DMA_4_7
LOCAL GT_ISR_ENTRY dmaError4_7Array[32];    /* DMA 4-7 Error condition  */
#endif

/* Each counter accumulate the number of connection done to a cause array.*/
/* For example dma6_7Count counts the number of connection done to        */
/* dma6_7Array.                                                           */
LOCAL int dma0_1Count = 0; 
LOCAL int dma2_3Count = 0;   
#ifdef INCLUDE_DMA_4_7
LOCAL int dma4_5Count = 0;   
LOCAL int dma6_7Count = 0; 
#endif

LOCAL int dmaError0_3Count = 0; 
#ifdef INCLUDE_DMA_4_7
LOCAL int dmaError4_7Count = 0; 
#endif

LOCAL int vxDmaIntCtrlInitialized = 0;

/* Interrupt Controller's ISR */
LOCAL void  dma0_1CompInt (void);    /* DMA 0-1 completion event handler */
LOCAL void  dma2_3CompInt (void);    /* DMA 2-3 completion event handler */
#ifdef INCLUDE_DMA_4_7
LOCAL void  dma4_5CompInt (void);    /* DMA 4-5 completion event handler */
LOCAL void  dma6_7CompInt (void);    /* DMA 6-7 completion event handler */
#endif
LOCAL void  dmaErrorInt   (void);    /* general DMA event handler        */

                                                        
/*******************************************************************************
* vxDmaIntCtrlInit - Initiating the DMA Interrupt Controller driver.
*
* DESCRIPTION:
*       This routines connects the drivers interrupt handlers, each to its 
*       corresponding bit in the GT main Interrupt Controller using the
*       gtIntConnect() routine.
*
* INPUT:
*       None.
*
* OUTPUT:
*       The DMA Engine casue & mask register are initiated (set to zero).
*       Driver's ISR are connected to the main cause register. 
*       interrupts are unmasked.
*
* RETURN:
*       None.
*
*******************************************************************************/
void vxDmaIntCtrlInit(void)
{
    if(vxDmaIntCtrlInitialized)
        return;

    DMA0_3_CAUSE_REG = 0;  /* Clean Cause regiser (case of warm reboot)	*/
    DMA0_3_MASK_REG  = 0;  /* Clean Mask regiser (case of warm reboot)	*/
#ifdef INCLUDE_DMA_4_7
    DMA4_7_CAUSE_REG = 0;  /* Clean Cause regiser (case of warm reboot)	*/
    DMA4_7_MASK_REG  = 0;  /* Clean Mask regiser (case of warm reboot)	*/
#endif

    /* Connect the user ISR's to the DMA bits in the main cause register */
    intConnect(INUM_TO_IVEC(INT_VEC_IDMA0_1), dma0_1CompInt, 0);
    intConnect(INUM_TO_IVEC(INT_VEC_IDMA2_3), dma2_3CompInt, 0);
#ifdef INCLUDE_DMA_4_7
    intConnect(INUM_TO_IVEC(INT_VEC_IDMA4_5), dma4_5CompInt, 0);
    intConnect(INUM_TO_IVEC(INT_VEC_IDMA6_7), dma6_7CompInt, 0);
#endif    
    intConnect(INUM_TO_IVEC(INT_VEC_DMA), dmaErrorInt, 0);

    /* Unmask those bits */
    intEnable(INT_VEC_IDMA0_1);
    intEnable(INT_VEC_IDMA2_3);
#ifdef INCLUDE_DMA_4_7
    intEnable(INT_VEC_IDMA4_5);
    intEnable(INT_VEC_IDMA6_7);
#endif    
    intEnable(INT_VEC_DMA);

    vxDmaIntCtrlInitialized = true;
}


/*******************************************************************************
* vxDmaIntConnect - connect a C routine to a specific DMA interrupt.
*
* DESCRIPTION:
*       This routine connects a specified user ISR to a specified GT DMA 
*       interrupt cause (0x8c0 or 0x9c0).
*       Each ISR handler has its own user ISR array. 
*       The connection is done by setting the desired routine and parameter in 
*       the corresponding cause array (i.e. dma0_1Array[]):
*         1) Locating the correct Array to make the connction.
*            This is made according to the cause. 
*            DMA channel completion events has unique ISRs.
*         2) Check for existing connection for the cause bit in the table.
*         3) Connecting the user ISR by inserting the given parameters into 
*           an entry according to the user ISR given priority.
*
* INPUT:
*       cause     - DMA interrupt cause. See DMA_INT_CAUSE. 
*       routine   - user ISR.
*       parameter - user ISR parameter.
*       prio      - Interrupt handling priority where 0 is highest.
*
* OUTPUT:
*       An appropriate table entry is filled.
*
* RETURN:
*       OK    - if the table entry of the cause bit, was filled. 
*       ERROR - if cause argument is invalid or connected cause is already 
*                found in table.
*
*******************************************************************************/
STATUS vxDmaIntConnect(DMA_CAUSE cause, VOIDFUNCPTR routine, int parameter,
                       int prio)
{
    GT_ISR_ENTRY *intCauseArray; /* Pointer to the selected cause table    */
    int *intConnectCount;   		/* Pointer to the table connection counter*/
    int i, sysIntOldConfig;

    /* Make sure that this is an atomic operation */
    sysIntOldConfig = intLock();

    /* Check the validity of the parameters */
    if(routine == NULL)
    {
        logMsg("\nvxDmaIntConnect: NULL pointer routine\n",0,0,0,0,0,0);
        intUnlock(sysIntOldConfig);
        return ERROR;
    }
    else if(prio < 0)
    {
        logMsg("\nvxDmaIntConnect: Invalid interrupt priority\n",0,0,0,0,0,0);
        intUnlock(sysIntOldConfig);
        return ERROR;
    }
    else if(cause == DMA_CHAN0_COMPLITION || cause == DMA_CHAN1_COMPLITION)
    {
        intCauseArray   = dma0_1Array;
        intConnectCount = &dma0_1Count;
    }
    else if(cause == DMA_CHAN2_COMPLITION || cause == DMA_CHAN3_COMPLITION)
    {
        intCauseArray   = dma2_3Array;
        intConnectCount = &dma2_3Count;
    }
#ifdef INCLUDE_DMA_4_7
    else if(cause == DMA_CHAN4_COMPLITION || cause == DMA_CHAN5_COMPLITION)
    {
        intCauseArray   = dma4_5Array;
        intConnectCount = &dma4_5Count;
    }
    else if(cause == DMA_CHAN6_COMPLITION || cause == DMA_CHAN7_COMPLITION)
    {
        intCauseArray   = dma6_7Array;
        intConnectCount = &dma6_7Count;
    }
#endif
    else if(DMA0_3_CAUSE) /* cause bit is from DMA 0-3 cause register (0x8C0)*/
    {
        intCauseArray   = dmaError0_3Array;
        intConnectCount = &dmaError0_3Count;
    }
#ifdef INCLUDE_DMA_4_7
    else if(DMA4_7_CAUSE) /* cause bit is from DMA 4-7 cause register (0x9C0)*/
    {
        intCauseArray   = dmaError4_7Array;
        intConnectCount = &dmaError4_7Count;
    }
#endif
    else
    {
        logMsg("\nvxDmaIntConnect: Invalid cause %d\n",cause,0,0,0,0,0);
        intUnlock(sysIntOldConfig);
        return ERROR;
    }

    /* Scan the table to check for double connection to the same cause bit */
    for(i = *intConnectCount; i >= 0; i--)
        if(intCauseArray[i].causeBit == SWAP_CAUSE_BIT(cause))
        {
            logMsg("\nvxDmaIntConnect(cause %d): ERROR\n",cause,0,0,0,0,0);
            logMsg("   An attempt to reconnect ISR to an existing cause bit.\n",
                   0,0,0,0,0,0); 
            intUnlock(sysIntOldConfig);
            return ERROR;
        }

    /* Connection phase */
    /* The search starts from the bottom of the table, because:     */
    /*  1) if the priority is the highest, we can put it straight   */
    /*     in the end of the table                                  */
    /*  2) we can push the highests priority down the table,right   */
    /*     away, with out the need to copy the struct.              */

    for(i = *intConnectCount; i >= 0; i--)
    {

⌨️ 快捷键说明

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