📄 ibmdma.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 + -