📄 sadma.c
字号:
/*----------------------------------------------------------------------
* Copyright (C) 1999 Intel Corp.
*
* This file contains the SA11x0 control object. This object provides
* initialization and control objects for the SA1100 and SA1110 CPUs.
*
* The current implementaiton is a partial object with a number of
* functions still made available as procedures. This will be removed
* as the object is completed.
*
*/
#include <windows.h>
#include <types.h>
#include "sa11x0.h"
#include "macros.h"
void usWait(unsigned usVal);
void msWait(unsigned msVal);
/*----------------------------------------------------------------------
* Local storage
*/
static volatile struct dmareg * dmaP;
/*----------------------------------------------------------------------
* Table 11-6
* This table is the DMA channel setup for each source. It is in the
* order of the DMA source identifiers in sa11x0.h.
*/
static unsigned dmaTab[] = {
0 | (1 << 2) | (0 << 3) | (0 << 4) | (0x80000AU << 8), /* UDC_Xmit */
1 | (1 << 2) | (0 << 3) | (1 << 4) | (0x80000AU << 8), /* UDC_Rcv */
0 | (0 << 2) | (0 << 3) | (2 << 4) | (0x80801EU << 8), /* SDLC_Xmit */
1 | (0 << 2) | (0 << 3) | (3 << 4) | (0x80801EU << 8), /* SDLC_Rcv */
0 | (0 << 2) | (0 << 3) | (4 << 4) | (0x804005U << 8), /* UART1_Xmit */
1 | (0 << 2) | (0 << 3) | (5 << 4) | (0x804005U << 8), /* UART1_Rcv */
0 | (0 << 2) | (0 << 3) | (6 << 4) | (0x81001BU << 8), /* UART2_Xmit */
1 | (0 << 2) | (0 << 3) | (7 << 4) | (0x81001BU << 8), /* UART2_Rcv */
0 | (1 << 2) | (0 << 3) | (6 << 4) | (0x80C005U << 8), /* HSSP_Xmit */
1 | (1 << 2) | (0 << 3) | (7 << 4) | (0x80C005U << 8), /* HSSP_Rcv */
0 | (0 << 2) | (0 << 3) | (8 << 4) | (0x814005U << 8), /* UART3_Xmit */
1 | (0 << 2) | (0 << 3) | (9 << 4) | (0x814005U << 8), /* UART3_Rcv */
0 | (0 << 2) | (1 << 3) |(10 << 4) | (0x818002U << 8), /* MCP_AudioXmit */
1 | (0 << 2) | (1 << 3) |(11 << 4) | (0x818002U << 8), /* MCP_AudioRcv */
0 | (0 << 2) | (1 << 3) |(12 << 4) | (0x818003U << 8), /* MCP_TelecomXmit */
1 | (0 << 2) | (1 << 3) |(13 << 4) | (0x818003U << 8), /* MCP_TelecomRcv */
0 | (0 << 2) | (1 << 3) |(14 << 4) | (0x81C01BU << 8), /* SSP_Xmit */
1 | (0 << 2) | (1 << 3) |(15 << 4) | (0x81C01BU << 8) /* SSP_Rcv */
};
/*----------------------------------------------------------------------
* Allocate a DMA channel and return a pointer to the channel
*/
void * SA_AllocateDMA(volatile struct dmareg *ddaP, int source, int endian)
{
int i;
if (source > SA11x0_SSP_Rcv)
return NULL;
for (i=0; i < SA11x0_NumDMA; i++) {
if (ddaP->dmaChannels[i].ddar.da == 0) {
RETAILMSG(1,(TEXT("DMAlib ddaP=0x%x, Channel=0%d \r\n\n"),
ddaP,i));
*(unsigned*)&ddaP->dmaChannels[i].ddar = dmaTab[source] | (endian << 1);
IOW_REG_BITSET(struct dcsrBits,&ddaP->dmaChannels[i].ddcsrSet,run,1);
return (void*)&ddaP->dmaChannels[i].ddar;
}
}
return NULL;
}
/*----------------------------------------------------------------------
* Start a DMA transfer on the channel
*/
void SA_InitiateDMA(volatile struct dmachannel * ddaP)
{
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,ie,1);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,run,1);
}
/*----------------------------------------------------------------------
* Release a previously allocated DMA channel
*/
void SA_ReleaseDMA(volatile struct dmachannel * ddaP)
{
int retryCount;
/* May need to sync with running DMA
*/
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,run,1);
retryCount = 100;
while((ddaP->ddcsrSts.run) && (--retryCount > 0))
usWait(10);
*(unsigned*)&ddaP->ddar = 0;
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,ie,1);
}
/*----------------------------------------------------------------------
* Start a DMA transfer on the channel
*/
void SA_StartDMA(volatile struct dmachannel * p, void * ba, int len, int ie)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,run,1);
if ((ddaP->ddcsrSts.biu && ddaP->ddcsrSts.strtb) ||
(!ddaP->ddcsrSts.biu && !ddaP->ddcsrSts.strta)) {
ddaP->dbsa = (unsigned)ba;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbta,tc,len);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,ie,ie);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strta,1);
}
else {
ddaP->dbsb = (unsigned)ba;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbtb,tc,len);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,ie,ie);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strtb,1);
}
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,run,1);
}
/*----------------------------------------------------------------------
* Return the channel number of a channel
*/
int SA_GetChannelDMA(volatile struct dmachannel * p)
{
return ((char*)p - (char*)dmaP->dmaChannels) / sizeof(struct dmachannel);
}
/*----------------------------------------------------------------------
* Check to see if DMA is complete
*/
int SA_CheckDMA(volatile struct dmachannel * p)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
int rc = 0;
if (ddaP->ddcsrSts.donea)
rc |= (1 << 0);
if (ddaP->ddcsrSts.doneb)
rc |= (1 << 1);
return rc;
}
/*----------------------------------------------------------------------
* Pause the DMA channel
*/
void SA_PauseDMA(volatile struct dmachannel * p)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
do {
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,run,1);
} while (ddaP->ddcsrSts.run);
}
/*----------------------------------------------------------------------
* Resume the DMA channel
*/
void SA_ResumeDMA(volatile struct dmachannel * p)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,run,1);
}
/*----------------------------------------------------------------------
* Start a DMA transfer on the channel
*/
void SA_PumpDMA(volatile struct dmachannel * ddaP, ULONG ba, int len, int use_b)
{
if (use_b) {
ddaP->dbsb = ba;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbtb,tc,len);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strtb,1);
}
else {
ddaP->dbsa = ba;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbta,tc,len);
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strta,1);
}
}
/*----------------------------------------------------------------------
* Return the current DMA pointer.
*/
int SA_GetDMABuffer(volatile struct dmachannel * p)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
int whichBuf = ddaP->ddcsrSts.biu;
if (whichBuf)
return ddaP->dbsb;
else
return ddaP->dbsa;
}
/*----------------------------------------------------------------------
* Set the current DMA pointer
*/
int SA_SetDMABuffer(volatile struct dmachannel * p, int buf, void * ba)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
int rc = 0;
int whichBuf = ddaP->ddcsrSts.biu;
int howMany;
if (whichBuf) {
/* STRTB must be clear before update will be allowed
*/
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,strtb,1);
howMany = (unsigned)ba - (unsigned)ddaP->dbsb;
ddaP->dbsb = (unsigned)ba;
rc = ddaP->dbtb.tc-howMany;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbtb,tc,rc);
if (rc > 0) {
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strtb,1);
}
}
else {
/* STRTA must be clear before update will be allowed
*/
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrClr,strta,1);
howMany = (unsigned)ba - (unsigned)ddaP->dbsa;
ddaP->dbsa = (unsigned)ba;
rc = ddaP->dbta.tc-howMany;
IOW_REG_FIELD(struct dbtBits,&ddaP->dbta,tc,rc);
if (rc > 0) {
IOW_REG_BITSET(struct dcsrBits,&ddaP->ddcsrSet,strta,1);
}
}
return rc;
}
/*----------------------------------------------------------------------
* Clear the DMA interrupt
*/
void SA_ClearDMA(volatile struct dmachannel * p, int buf)
{
volatile struct dmachannel * ddaP = (struct dmachannel *)p;
struct dcsrBits ddcsr;
*(unsigned*)&ddcsr = 0;
if (buf) {
ddcsr.doneb = 1;
IOW_REG_SET(struct dcsrBits,&ddaP->ddcsrClr,*(unsigned*)&ddcsr);
}
else {
ddcsr.donea = 1;
IOW_REG_SET(struct dcsrBits,&ddaP->ddcsrClr,*(unsigned*)&ddcsr);
}
}
/*----------------------------------------------------------------------
* Stop DMA transfer on the channel
*/
void SA_StopDMA(volatile struct dmachannel * ddaP)
{ struct dcsrBits ddcsr;
*(unsigned*)&ddcsr = 0;
ddcsr.ie = 1;
ddcsr.run = 1;
ddcsr.strta = 1;
ddcsr.strtb = 1;
IOW_REG_SET(struct dcsrBits,&ddaP->ddcsrClr,*(unsigned*)&ddcsr);
}
/*----------------------------------------------------------------------
* DMA control object. Eventually the procedures above will form the
* body of this object.
*/
void SA11x0_DMA_Init( volatile struct dmareg *pdmaP)
{
int i;
dmaP=pdmaP;
for (i=0; i < SA11x0_NumDMA; i++)
SA_ReleaseDMA(&dmaP->dmaChannels[i]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -