📄 dma1.c
字号:
if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS ) { return DMAINVALID; } if ( stat.cb == 1 ) { /* DMA is not free */ return DMACHNBUSY; } mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] ); /* clear DMA_MR(CS) */ mode &= 0xfffffffe; store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); /* set DMA_MR(CS) */ mode |= CS; store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); return DMASUCCESS;}/*********************************************************** * function: DMA_Halt * * description: halt the current dma transaction on the specified * channel. * return DMASUCCESS if success otherwise return DMAINVALID * * note: if the specified DMA channel is idle, nothing happens *************************************************************/staticDMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel ){ unsigned int mode; if ( channel != 0 && channel != 1 ) { return DMAINVALID; } mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]); /* clear DMA_MR(CS) */ mode &= 0xfffffffe; store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); return DMASUCCESS;}/************************************************************* * function: DMA_Chn_Cnt * * description: set the DMA_MR(CC) bit for a given channel * that is in chaining mode. * return DMASUCCESS if successfule, otherwise return * DMAINVALID. * * note: if the given channel is not in chaining mode, nothing * happen. * *************************************************************/staticDMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel ){ DMA_MR mode; if ( channel != 0 && channel != 1 ) { return DMAINVALID; } if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS ) { return DMAINVALID; } if ( mode.ctm == 0 ) { /* either illegal mode or not chaining mode */ return DMAINVALID; } mode.cc = 1; return DMA_Set_Mode( host, eumbbar, channel, mode );}/************************************************************** * function: DMA_Bld_Desp * * description: set current descriptor address register * according to the desp for a given channel * * if the given channel is busy return DMACHNBUSY * and no change made, otherwise return DMASUCCESS. * * note: **************************************************************/staticDMAStatus DMA_Bld_Desp( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_CDAR desp ){ DMA_SR status; unsigned int temp; 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; } temp = ( desp.cda & 0x7ffffff ) << 5; temp |= (( desp.snen & 0x1 ) << 4 ); temp |= (( desp.eosie & 0x1 ) << 3 ); temp |= (( desp.ctt & 0x3 ) << 1 ); temp |= ( desp.eotd & 0x1 ); store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );#ifdef DMADBG0 PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__, ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );#endif return DMASUCCESS;}/************************************************************** * function: DMA_Poke_Desp * * description: poke the current descriptor address register * for a given channel * * return DMASUCCESS if no error * * note: Due to the undeterministic parallellism of DMA operation, * the value returned by this function shall be taken as * the most recently used descriptor when the last time * DMA starts a chaining mode operation. **************************************************************/staticDMAStatus DMA_Poke_Desp( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_CDAR *desp ){ unsigned int cdar; if ( channel != 0 && channel != 1 || desp == 0 ) { return DMAINVALID; } cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );#ifdef DMADBG0 PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__, ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );#endif desp->cda = ( cdar & 0xffffffe0 ) >> 5; desp->snen = ( cdar & 0x00000010 ) >> 4; desp->eosie = ( cdar & 0x00000008 ) >> 3; desp->ctt = ( cdar & 0x00000006 ) >> 1; desp->eotd = ( cdar & 0x00000001 ); return DMASUCCESS;}/************************************************************** * function: DMA_Bld_Curr * * description: set current src, dest, byte count registers * according to the desp for a given channel * return DMASUCCESS if no error. * * note: **************************************************************/staticDMAStatus 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 == LOCAL ? "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 == LOCAL ? "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 == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );#endif return DMASUCCESS;}/************************************************************** * 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. **************************************************************/staticDMAStatus 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 == LOCAL ? "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 == LOCAL ? "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 == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );#endif return DMASUCCESS;}/***************************************************************** * 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. ****************************************************************/staticDMAStatus 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 * *************************************************************/staticDMAStatus 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( LOCAL, 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[LOCAL][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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -