📄 dma.c
字号:
*
* description: set current src, dest, byte count registers
* according to the desp for a given channel
* return DMASUCCESS if no error.
*
* note:
**************************************************************/
static
DMAStatus DMA_Bld_Curr( LOCATION host,
unsigned int eumbbar,
unsigned int channel,
DMA_CURR desp )
{
DMA_SR status;
if ( channel != 0 && channel != 1 )
{
/* channel number out of range */
return DMAINVALID;
}
if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
{
return DMAINVALID;
}
if ( status.cb == 1 )
{
/* channel busy */
return DMACHNBUSY;
}
desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */
store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
#endif
store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
#endif
store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
#endif
return DMASUCCESS;
}
#if 0
/**************************************************************
* function: DMA_Poke_Curr
*
* description: poke the current src, dest, byte count registers
* for a given channel.
*
* return DMASUCCESS if no error
*
* note: Due to the undeterministic parallelism, in chaining
* mode, the value returned by this function shall
* be taken as reference when the query is made rather
* than the absolute snapshot when the value is returned.
**************************************************************/
static
DMAStatus DMA_Poke_Curr( LOCATION host,
unsigned int eumbbar,
unsigned int channel,
DMA_CURR* desp )
{
if ( channel != 0 && channel != 1 || desp == 0 )
{
return DMAINVALID;
}
desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
#endif
desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
#endif
desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
#ifdef DMADBG0
PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
( host == LOCALA ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
#endif
return DMASUCCESS;
}
/**************************************************/
/* Delay routine */
/**************************************************/
void delay(deciseconds)
int deciseconds;
{
int j,k;
k = 0xfffff;
for(j=0;j<deciseconds;j++)
{
while(k)
{
k = k-1;
}
}
return;
}
/**************************************************/
/*****************************************************************
* function: dma_error_func
*
* description: display the error information
*
* note: This seems like a highly convoluted way to handle messages,
* but I'll leave it as it was in device.c when I moved it into the
* DMA library source.
****************************************************************/
static
DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
{
unsigned char *msg[] =
{
"Local Memory Error",
"PCI Error",
"Channel Busy",
"End-of-Segment Interrupt",
"End-of-Chain/Direct Interrupt",
};
if ( err >= DMALMERROR && err <= DMAEOCAINT )
{
PRINT( "DMA Status: channel %d %s\n", chn, msg[err-DMASUCCESS-1] );
}
return err;
}
/*************************************************************
* function: DMA_ISR
*
* description: DMA interrupt service routine
* return DMAStatus value based on
* the status
*
*************************************************************/
static
DMAStatus DMA_ISR( unsigned int eumbbar,
unsigned int channel,
DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
{
DMA_SR stat;
DMAStatus rval = DMANOEVENT;
unsigned int temp;
if ( channel != 0 && channel != 1 )
{
return DMAINVALID;
}
if ( DMA_Get_Stat( LOCALA, eumbbar, channel, &stat ) != DMASUCCESS )
{
return DMAINVALID;
}
if ( stat.lme == 1 )
{
/* local memory error */
rval = DMALMERROR;
if ( lme_func != 0 )
{
rval = (*lme_func)(eumbbar, channel, DMALMERROR );
}
}
else if ( stat.pe == 1 )
{
/* PCI error */
rval = DMAPERROR;
if ( pe_func != 0 )
{
rval = (*pe_func)(eumbbar, channel, DMAPERROR );
}
}
else if ( stat.eosi == 1 )
{
/* end-of-segment interrupt */
rval = DMAEOSINT;
if ( eosi_func != 0 )
{
rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
}
}
else
{
/* End-of-chain/direct interrupt */
rval = DMAEOCAINT;
if ( eocai_func != 0 )
{
rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
}
}
temp = ( stat.reserved0 & 0xffffff ) << 8;
temp |= ( ( stat.lme & 0x1 ) << 7 ); /* write one to clear */
temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
temp |= ( ( stat.pe & 0x1 ) << 4 ); /* write one to clear */
temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
temp |= ( ( stat.cb & 0x1 ) << 2 ); /* write one to clear */
temp |= ( ( stat.eosi & 0x1 ) << 1 ); /* write one to clear */
temp |= ( stat.eocai & 0x1 ); /* write one to clear */
store_runtime_reg( eumbbar, dma_reg_tb[LOCALA][channel*NUM_DMA_REG + DMA_SR_REG], temp );
#ifdef DMADBG0
PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
#endif
return rval;
}
#endif
void DMA0ISR(void)
{
DMA_SR stat;
DMA_MR mode;
DMA_CHAIN_QUEUE *qu;
/* unsigned int xTime;*/
qu = (DMA_CHAIN_QUEUE *)pDMAQueue;
/* if(runled12%2) */
/*led12(0);
else
led12(1);*/
/*GTPRINT("\n I am in interrupt",0,0,0,0,0,0);*/
/*runled12++;*/
/*DMA_Get_Stat_Epic( LOCAL, get_eumbbar(), 0, &stat ) ;*/
DMA_Get_Stat( LOCALA, get_eumbbar(), 0, &stat ) ;
DMA_Get_Mode( LOCALA, get_eumbbar(), 0, &mode );
/* Check the DMA status register to see if the DMA transaction was OK, if not
* status register PE bit 4 was set. If so, print an appropriate message and
* clear the bit. Write a 1 to stat.pe to clear it.
* Leave everything else in the register unchanged.
* Subsequent DMA transactions do not work until the stat.pe bit is cleared.
* We might want to do the same thing for the Local Memory Error bit as well.
*/
if (stat.pe == 1)
{
union {
DMA_SR stat;
unsigned int temp;
} s;
GTPRINT("PCI Error on DMA transfer.\n",0,0,0,0,0,0);
s.stat = stat;
GTPRINT("DMA Status is : 0x%x.\n",s.temp,0,0,0,0,0);
s.temp &= 0xffffff6c; /* leave rest of status register unchanged */
s.stat.pe = 1; /* clear the pe bit by writing 1 to it */
store_runtime_reg( get_eumbbar(),0x1104, s.temp );
}
if (mode.ctm==0)
{
if ( stat.eosi == 1 )
{
/*union {
DMA_SR stat;
unsigned int temp;
} s;
s.stat = stat;*/
/* GTPRINT("DMA Status is : 0x%x,intnum:%d\n",s.temp,intnum,0,0,0,0);
GTPRINT("segment interrupt ......",0,0,0,0,0,0);*/
dma_chain_deq(qu);
store_runtime_reg( get_eumbbar(),0x1104, 0x2 );
}
if ( stat.eocai == 1 )
{
/*union {
DMA_SR stat;
unsigned int temp;
} s;
dma_chain_deq(qu);
s.stat = stat;*/
/* GTPRINT("DMA Status is : 0x%x,intnum:%d\n",s.temp,intnum,0,0,0,0);
GTPRINT("DMA end Interupt ......",0,0,0,0,0,0);*/
/*GTPRINT("Clearing Interupt\n",0,0,0,0,0,0);*/
store_runtime_reg( get_eumbbar(),0x1104, 0x1 );
/*semGive(dmaSemId);*/
}
}
if (mode.ctm ==1)
{
if ( stat.eocai == 1 )
{
/*GTPRINT("Direct Mode Interupt ......",0,0,0,0,0,0);
GTPRINT("Clearing Interupt\n",0,0,0,0,0,0);*/
store_runtime_reg( get_eumbbar(),0x1104, 1 );
}
semGive(dmaSemId);
}
}
STATUS Initdma(/*DMA_INTERRUPT_STEER int_steer*/void)
{
/*int ret ;*/
DMA_CHAIN_QUEUE *qu;
pDMADesp = (UINT32 *) (((UINT32) DMAdespArray + 8) & 0xfffffff8);
pDMAQueue = DMAQueueArray;
if (initnum==0)
{
(void)intConnect(INUM_TO_IVEC(DMA0_INT_LVL),(VOIDFUNCPTR)DMA0ISR,NULL);
/*if(ret == ERROR)
{
#ifdef DMADBG0
PRINT("BSP:can't connect dma int! \n");
#endif
return (ERROR);
}*/
intEnable(DMA0_INT_LVL);
if ( Global_eumbbard == 0)
Global_eumbbard = get_eumbbar();
if ( Global_eumbbard == 0)
{
PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
return (ERROR);
}
dmaTaskSemId = semBCreate ( SEM_Q_PRIORITY,SEM_FULL);
if(dmaTaskSemId ==NULL)
{
#ifdef DMADBG0
PRINT("BSP:can't create dma task sem for send! \n");
#endif
return (ERROR);
}
dmaSemId = semBCreate ( SEM_Q_PRIORITY ,SEM_EMPTY);
if(dmaSemId ==NULL)
{
#ifdef DMADBG0
PRINT("BSP:can't create dma sem for send! \n");
#endif
return (ERROR);
}
/*qu = (QUEUE *)0x2080000;
qu->q=(DMA_DESP *)0x2000000;*/
qu = (DMA_CHAIN_QUEUE *)pDMAQueue;
qu->q=(DMA_DESP *)pDMADesp;
qu->f = qu->r = 0;
initnum=1;
}
return OK;
}
static STATUS dma_chain_enq(DMA_CHAIN_QUEUE *qu,DMA_DESP *cdesp)
{
if((qu->r+1)%(n0+1)==qu->f)
return (ERROR);
else{
qu->q[qu->r].src_addr = cdesp->src_addr;
qu->q[qu->r].dest_addr = cdesp->dest_addr;
qu->q[qu->r].next_desp = cdesp->next_desp;
qu->q[qu->r].byte_cnt = cdesp->byte_cnt;
qu->q[qu->r].reserved0 = 0;
qu->q[qu->r].reserved1 = 0;
qu->q[qu->r].reserved2 = 0;
qu->q[qu->r].reserved3 = 0;
qu->r = (qu->r+1)%(n0+1);
return OK;
}
}
static void dma_chain_deq(DMA_CHAIN_QUEUE *qu)
{
if(qu->r==qu->f)
{}
else
qu->f = (qu->f+1)%(n0+1);
}
unsigned long dmacwrite(unsigned int *src,unsigned int *dst,unsigned int *len,unsigned int num)
{
int rc;
rc = DMA_chaining_transfer(0,1,src,dst,len,num,0,1);
return (rc);
}
unsigned long dmacread(unsigned int *src,unsigned int *dst,unsigned int *len,unsigned int num)
{
int rc;
rc = DMA_chaining_transfer(0,2,src,dst,len,num,0,1);
return(rc);
}
unsigned long dmadwrite(unsigned int src,unsigned int dst,unsigned int len)
{
int rc;
rc = DMA_direct_transfer(0,1,(unsigned long )src,(unsigned long )dst,(unsigned long)len,0,1);
return (rc);
}
unsigned long dmadread(unsigned int src,unsigned int dst,unsigned int len)
{
int rc;
rc = DMA_direct_transfer(0,2,(unsigned long )src,(unsigned long )dst,(unsigned long )len,0,1);
return(rc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -