📄 vxdmaintctrl.c
字号:
/*******************************************************************************
* 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 + -