ddk_dmac.c
来自「i.mx27 soc for wince 6.0」· C语言 代码 · 共 1,172 行 · 第 1/3 页
C
1,172 行
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, MOTOROLA, INC. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// MOTOROLA, INC.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// File: ddk_dmac.c
//
// Provides the DDK (driver development kit) for the DMA controller (DMAC).
//
// NOTES:
// To use a DMA channel:
// =====================
// 1. In INC/bsp_cfg.h, add the following defines:
// - desired channel identifier
// 2. Allocate DMA buffers using HalAllocateCommonBuffer(), request and bind
// the desired channel. Example, look at SDHC or audio drivers.
// 3. If using DMA interrupts, add handling in driver for the
// SYSINTR assigned to the channel.
//
// WARNING:
// ========
// The DMAC status registers MUST BE CLEARED after every DMA transfer
// in order for the channel to be restarted. The user driver must call
// ClearChannelInterrupt() before calling TransStart() even if
// interrupts are not enabled/used.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include <csp.h>
#ifdef DEBUG
DBGPARAM dpCurSettings = {
L"MX27DMAC", {
L"Info", L"Function", L"Warnings", L"Errors",
L"Init", L"Undefined", L"Undefined", L"Undefined",
L"Undefined", L"Undefined", L"Undefined", L"Undefined",
L"Undefined", L"Undefined", L"Undefined", L"Undefined"
},
0x0008
};
#define ZONE_INFO DEBUGZONE(0)
#define ZONE_FUNCTION DEBUGZONE(1)
#define ZONE_WARN DEBUGZONE(2)
#define ZONE_ERROR DEBUGZONE(3)
#define ZONE_INIT DEBUGZONE(4)
#endif
//-----------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------
// External Variables
//-----------------------------------------------------------------------------
// Defines
#define CHAN_MASK(chan) (1 << (chan))
//-----------------------------------------------------------------------------
// Types
typedef struct {
BOOL Register2DFlagA; // flag for using status of 2D registers set A
BOOL Register2DFlagB; // flag for using status of 2D registers set B
UINT16 BurstTimeout; // burst timeout count down data
UINT16 ChannelAllocated; // flags for channel allocation status
} DMAC_DLL_SHARED, *PDMAC_DLL_SHARED;
//DMAC channel data structure
typedef struct {
UINT32 SAR;
UINT32 DAR;
UINT32 CNTR;
UINT32 CCR;
UINT32 RSSR;
UINT32 BLR;
UINT32 RTOR_BUCR;
} DMAC_CHANNEL_DATA, *PDMAC_CHANNEL_DATA;
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// Local Variables
static HANDLE g_hFileMap = NULL;
static PDMAC_DLL_SHARED g_pDllShared = NULL;
static CSP_DMAC_REGS *g_pDMAC = NULL;
//-----------------------------------------------------------------------------
// Local Functions
BOOL DmacAlloc(void);
BOOL DmacDealloc(void);
BOOL DmacInit(void);
BOOL DmacDeinit(void);
static BOOL DmacTranslateCfg(DMAC_CHANNEL_CFG *pChannelCfg, DMAC_CHANNEL_DATA *pChannelData);
static void DmacShowRegister(UINT32 channelMask);
//-----------------------------------------------------------------------------
//
// Function: DmacDeinit
//
// This function deinitializes the DMAC. Called by the Device Manager to
// de-initialize a device.
//
// Parameters:
// None.
//
// Returns:
// Returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL DmacDeinit(void)
{
BOOL rc = TRUE;
UINT8 chan;
DEBUGMSG(ZONE_INIT, (_T("DmacDeinit+\r\n")));
// Disable all channels
for (chan = 1; chan < DMAC_NUM_CHANNELS; chan++)
{
g_pDMAC->CHANNEL[chan].CCR = 0;
}
// Deallocate DMAC driver data structures
DmacDealloc();
DEBUGMSG(ZONE_INIT, (_T("DmacDeinit- (rc = %d)\r\n"), rc));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: DmacInit
//
// This function initializes the DMAC. Called by the CSPDDK Init() function to
// initialize the DMA controller.
//
// Parameters:
// None.
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DmacInit(void)
{
BOOL rc = FALSE;
UINT32 i;
DEBUGMSG(ZONE_INIT, (_T("DmacInit+\r\n")));
// Set 2D memory registers use status flag as free
g_pDllShared->Register2DFlagA = DMAC_CHANNEL_INVALID;
g_pDllShared->Register2DFlagB = DMAC_CHANNEL_INVALID;
// reset DMAC
INSREG32BF(&g_pDMAC->DCR, DMAC_DCR_DRST, DMAC_DCR_DRST_RESET);
// Default to burst time out disabled
DEBUGMSG(ZONE_INIT, (TEXT("DMAC: Burst time out disabled!\r\n")));
INSREG32BF(&g_pDMAC->DBTOCR, DMAC_DBTOCR_EN, DMAC_DBTOCR_EN_DISABLE);
// Clear 2D memory registers
g_pDMAC->XSRA = 0;
g_pDMAC->YSRA = 0;
g_pDMAC->WSRA = 0;
g_pDMAC->XSRB = 0;
g_pDMAC->YSRB = 0;
g_pDMAC->WSRB = 0;
// Default to disable all DMA channels
for(i = 0; i < DMAC_NUM_CHANNELS; i++)
{
g_pDMAC->CHANNEL[i].CCR = 0;
}
// Enable DMAC for priviledged access only
g_pDMAC->DCR = (CSP_BITFVAL(DMAC_DCR_DEN, DMAC_DCR_DEN_ENABLE) |
CSP_BITFVAL(DMAC_DCR_DRST, DMAC_DCR_DRST_NOEFFECT) |
CSP_BITFVAL(DMAC_DCR_DAM, DMAC_DCR_DAM_PRIVILEGED));
rc = TRUE;
if(!rc)
DmacDeinit();
DEBUGMSG(ZONE_INIT, (_T("DmacInit- (rc = %d)\r\n"), rc));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: DDKDmacRequestChan
//
// This function checks that the desired channel is currently not in use and is
// available. If not, the next highest free channel is returned. The channel is
// allocated if successful.
//
// Parameters:
// chan
// [in] - the desired channel number
//
// Returns:
// Returns channel ID if available channel,
// otherwise returns DMAC_CHANNEL_INVALID.
//
//-----------------------------------------------------------------------------
UINT8 DDKDmacRequestChan(UINT8 chan)
{
INT8 i = 0;
UINT32 mask;
DEBUGMSG(ZONE_FUNCTION, (_T("DDKDmacRequestChan+:(chan = %d)\r\n"), chan));
if(chan >= DMAC_NUM_CHANNELS)
return DMAC_CHANNEL_INVALID;
// Check channel allocation status for availability
mask = CHAN_MASK(chan);
if((g_pDllShared->ChannelAllocated & mask) != 0)
{
// Walk the channel allocation status to find available channel
for(i = DMAC_NUM_CHANNELS - 1 , mask = (1 << (DMAC_NUM_CHANNELS - 1));
i >= 0; i--, mask >>= 1)
{
if((g_pDllShared->ChannelAllocated & mask) == 0)
{
chan = i;
break;
}
}
}
if(i < 0)
{
DEBUGMSG(ZONE_ERROR,
(_T("DDKDmacRequestChan: No channel available\r\n")));
chan = DMAC_CHANNEL_INVALID;
}
else
{
g_pDllShared->ChannelAllocated |= CHAN_MASK(chan);
}
DEBUGMSG(ZONE_FUNCTION, (_T("DDKDmacRequestChan-:(chan = %d)\r\n"), chan));
return chan;
}
//-----------------------------------------------------------------------------
//
// Function: DDKDmacReleaseChan
//
// This function releases a channel previously requested by the DDKDmacRequestChan
// routine.
//
// Parameters:
// chan
// [in] - channel returned by DDKDmacRequestChan function.
//
// Returns:
// Returns TRUE if the release operation was successful, otherwise
// returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKDmacReleaseChan(UINT8 chan)
{
BOOL rc = FALSE;
UINT32 mask;
DEBUGMSG(ZONE_FUNCTION, (_T("DDKDmacReleaseChan+\r\n")));
// Validate channel parameter
if (chan >= DMAC_NUM_CHANNELS)
{
DEBUGMSG(ZONE_ERROR, (_T("DDKDmacReleaseChan: Invalid channel %d\r\n"), chan));
goto cleanUp;
}
// Make sure this channel is really in use
mask = CHAN_MASK(chan);
if((g_pDllShared->ChannelAllocated & mask) == 0)
{
DEBUGMSG(ZONE_WARN, (_T("DDKDmacReleaseChan: Channel%d not allocated.\r\n"), chan));
goto cleanUp;
}
// Disable the channel first
INSREG32BF(&g_pDMAC->CHANNEL[chan].CCR, DMAC_CCR_CEN, DMAC_CCR_CEN_DISABLE);
// Mask channel interrupt & clear all interrupt status
g_pDMAC->DIMR |= mask;
g_pDMAC->DISR = mask;
g_pDMAC->DBTOSR = mask;
g_pDMAC->DRTOSR = mask;
g_pDMAC->DSESR = mask;
g_pDMAC->DBOSR = mask;
// Clear global allocation flag
g_pDllShared->ChannelAllocated &= ~mask;
// Clear 2D register set usage flag if used
if(g_pDllShared->Register2DFlagA == chan)
g_pDllShared->Register2DFlagA = DMAC_CHANNEL_INVALID;
if(g_pDllShared->Register2DFlagB == chan)
g_pDllShared->Register2DFlagB = DMAC_CHANNEL_INVALID;
DEBUGMSG(ZONE_INFO, (TEXT("DDKDmacReleaseChan: Channel%d is released.\r\n"), chan));
rc = TRUE;
cleanUp:
DEBUGMSG(ZONE_FUNCTION, (_T("DDKDmacReleaseChan- (rc = %d)\r\n"), rc));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: DDKDmacConfigureChan
//
// This function configures a channel after a request is successful.
//
// Parameters:
// chan
// [in] - channel to bind.
//
// pChannelCfg
// [in] - Configuration for the desired channel.
//
// Returns:
// Returns channel ID if the open operation was successful,
// otherwise returns DMAC_CHANNEL_INVALID.
//
//-----------------------------------------------------------------------------
UINT8 DDKDmacConfigureChan(UINT8 chan, DMAC_CHANNEL_CFG *pChannelCfg)
{
DMAC_CHANNEL_DATA ChannelData;
DMAC_CHANNEL_DATA *pChannelData = &ChannelData;
BOOL bSetB2DinUse = FALSE;
DEBUGMSG(ZONE_FUNCTION, (_T("DDKDmacConfigureChan+\r\n")));
// Check if the channel is already allocated
if((g_pDllShared->ChannelAllocated & CHAN_MASK(chan)) == 0)
{
DEBUGMSG(ZONE_ERROR, (TEXT("DDKDmacConfigureChan: Channel%d is not allocated!!\r\n"), chan));
chan = DMAC_CHANNEL_INVALID;
goto cleanup;
}
// Check if 2D memory is needed
if ((pChannelCfg->DstMode== DMAC_TRANSFER_MODE_2D_MEMORY) ||
(pChannelCfg->SrcMode == DMAC_TRANSFER_MODE_2D_MEMORY))
{
// use 2D memory registers
if(g_pDllShared->Register2DFlagA == DMAC_CHANNEL_INVALID)
{
// Set A is free
// keep track track of usage
g_pDllShared->Register2DFlagA = chan;
// Configure A set registers
INSREG32BF(&g_pDMAC->XSRA, DMAC_XSR_XS, pChannelCfg->XSR);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?