📄 mcd_dmaapi.c
字号:
contextSaveSpace)[CURRBD + CSAVE_OFFSET]; /* See if they match: */ if (prevRep.lastSrcAddr != progRep->lastSrcAddr || prevRep.lastDestAddr != progRep->lastDestAddr || prevRep.dmaSize != progRep->dmaSize || prevRep.currBufDesc != progRep->currBufDesc) { /* If they don't match, remember previous values and try again: */ prevRep.lastSrcAddr = progRep->lastSrcAddr; prevRep.lastDestAddr = progRep->lastDestAddr; prevRep.dmaSize = progRep->dmaSize; prevRep.currBufDesc = progRep->currBufDesc; again = MCD_TRUE; } else again = MCD_FALSE; } while (again == MCD_TRUE); /* Update the dCount, srcAddr and destAddr */ /* To calculate dmaCount, we consider destination address. C overs M1,P1,Z for destination */ switch (MCD_remVariants.remDestRsdIncr[channel]) { case MINUS1: subModVal = ((int)progRep-> lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); addModVal = ((int)progRep->currBufDesc-> destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - addModVal; LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; bytesNotXfered = (destDiffBytes / MCD_remVariants.remDestIncr[channel]) * (MCD_remVariants.remDestIncr[channel] + MCD_remVariants.remXferSize[channel]); progRep->dmaSize = destDiffBytes - bytesNotXfered + addModVal - subModVal; break; case ZERO: progRep->lastDestAddr = progRep->currBufDesc->destAddr; break; case PLUS1: /* This value has to be subtracted from the final calculated dCount. */ subModVal = ((int)progRep->currBufDesc-> destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); /* These bytes are already in lastDestAddr. */ addModVal = ((int)progRep-> lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - subModVal; LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); numIterations = (LWAlignedCurrDestAddr - LWAlignedInitDestAddr) / MCD_remVariants.remDestIncr[channel]; bytesNotXfered = numIterations * (MCD_remVariants.remDestIncr[channel] - MCD_remVariants.remXferSize[channel]); progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; break; default: break; } /* This covers M1,P1,Z for source */ switch (MCD_remVariants.remSrcRsdIncr[channel]) { case MINUS1: progRep->lastSrcAddr = progRep->currBufDesc->srcAddr + (MCD_remVariants.remSrcIncr[channel] * (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); break; case ZERO: progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; break; case PLUS1: progRep->lastSrcAddr = progRep->currBufDesc->srcAddr + (MCD_remVariants.remSrcIncr[channel] * (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); break; default: break; } return (MCD_OK);}/******************* End of MCD_XferProgrQuery() ********************//********************************************************************//* MCD_resmActions() does the majority of the actions of a DMA resume. * It is called from MCD_killDma() and MCD_resumeDma(). It has to be * a separate function because the kill function has to negate the task * enable before resuming it, but the resume function has to do nothing * if there is no DMA on that channel (i.e., if the enable bit is 0). */static void MCD_resmActions(int channel){ MCD_dmaBar->debugControl = DBG_CTL_DISABLE; MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; /* This register is selected to know which initiator is actually asserted. */ MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) MCD_chStatus[channel] = MCD_RUNNING; else MCD_chStatus[channel] = MCD_IDLE;}/********************* End of MCD_resmActions() *********************//********************************************************************//* Function: MCD_killDma * Purpose: Halt the DMA on the requested channel, without any * intention of resuming the DMA. * Arguments: channel - requested channel * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK * * Notes: * A DMA may be killed from any state, including paused state, and it * always goes to the MCD_HALTED state even if it is killed while in * the MCD_NO_DMA or MCD_IDLE states. */int MCD_killDma(int channel){ /* MCD_XferProg progRep; */ if ((channel < 0) || (channel >= NCHANNELS)) return (MCD_CHANNEL_INVALID); MCD_dmaBar->taskControl[channel] = 0x0; MCD_resumeDma(channel); /* * This must be after the write to the TCR so that the task doesn't * start up again momentarily, and before the status assignment so * as to override whatever MCD_resumeDma() may do to the channel * status. */ MCD_chStatus[channel] = MCD_HALTED; /* * Update the current buffer descriptor's lastDestAddr field * * MCD_XferProgrQuery (channel, &progRep); * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; */ return (MCD_OK);}/************************ End of MCD_killDma() **********************//********************************************************************//* Function: MCD_continDma * Purpose: Continue a DMA which as stopped due to encountering an * unready buffer descriptor. * Arguments: channel - channel to continue the DMA on * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK * * Notes: * This routine does not check to see if there is a task which can * be continued. Also this routine should not be used with single DMAs. */int MCD_continDma(int channel){ if ((channel < 0) || (channel >= NCHANNELS)) return (MCD_CHANNEL_INVALID); MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; MCD_chStatus[channel] = MCD_RUNNING; return (MCD_OK);}/********************** End of MCD_continDma() **********************//********************************************************************* * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit * to freeze a task and resume it. We freeze a task by breakpointing * on the stated task. That is, not any specific place in the task, * but any time that task executes. In particular, when that task * executes, we want to freeze that task and only that task. * * The bits of the debug control register influence interrupts vs. * breakpoints as follows: * - Bits 14 and 0 enable or disable debug functions. If enabled, you * will get the interrupt but you may or may not get a breakpoint. * - Bits 2 and 1 decide whether you also get a breakpoint in addition * to an interrupt. * * The debug unit can do these actions in response to either internally * detected breakpoint conditions from the comparators, or in response * to the external breakpoint pin, or both. * - Bits 14 and 1 perform the above-described functions for * internally-generated conditions, i.e., the debug comparators. * - Bits 0 and 2 perform the above-described functions for external * conditions, i.e., the breakpoint external pin. * * Note that, although you "always" get the interrupt when you turn * the debug functions, the interrupt can nevertheless, if desired, be * masked by the corresponding bit in the PTD's IMR. Note also that * this means that bits 14 and 0 must enable debug functions before * bits 1 and 2, respectively, have any effect. * * NOTE: It's extremely important to not pause more than one DMA channel * at a time. ********************************************************************//********************************************************************//* Function: MCD_pauseDma * Purpose: Pauses the DMA on a given channel (if any DMA is running * on that channel). * Arguments: channel * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK */int MCD_pauseDma(int channel){ /* MCD_XferProg progRep; */ if ((channel < 0) || (channel >= NCHANNELS)) return (MCD_CHANNEL_INVALID); if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) { MCD_dmaBar->debugComp1 = channel; MCD_dmaBar->debugControl = DBG_CTL_ENABLE | (1 << (channel + 16)); MCD_chStatus[channel] = MCD_PAUSED; /* * Update the current buffer descriptor's lastDestAddr field * * MCD_XferProgrQuery (channel, &progRep); * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; */ } return (MCD_OK);}/************************* End of MCD_pauseDma() ********************//********************************************************************//* Function: MCD_resumeDma * Purpose: Resumes the DMA on a given channel (if any DMA is * running on that channel). * Arguments: channel - channel on which to resume DMA * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK */int MCD_resumeDma(int channel){ if ((channel < 0) || (channel >= NCHANNELS)) return (MCD_CHANNEL_INVALID); if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) MCD_resmActions(channel); return (MCD_OK);}/************************ End of MCD_resumeDma() ********************//********************************************************************//* Function: MCD_csumQuery * Purpose: Provide the checksum after performing a non-chained DMA * Arguments: channel - channel to report on * csum - pointer to where to write the checksum/CRC * Returns: MCD_ERROR if the channel is invalid, else MCD_OK * * Notes: * */int MCD_csumQuery(int channel, u32 * csum){#ifdef MCD_INCLUDE_EU if ((channel < 0) || (channel >= NCHANNELS)) return (MCD_CHANNEL_INVALID); *csum = MCD_relocBuffDesc[channel].csumResult; return (MCD_OK);#else return (MCD_ERROR);#endif}/*********************** End of MCD_resumeDma() *********************//********************************************************************//* Function: MCD_getCodeSize * Purpose: Provide the size requirements of the microcoded tasks * Returns: Size in bytes */int MCD_getCodeSize(void){#ifdef MCD_INCLUDE_EU return (0x2b5c);#else return (0x173c);#endif}/********************** End of MCD_getCodeSize() ********************//********************************************************************//* Function: MCD_getVersion * Purpose: Provide the version string and number * Arguments: longVersion - user supplied pointer to a pointer to a char * which points to the version string * Returns: Version number and version string (by reference) */char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)";#define MCD_REV_MAJOR 0x00#define MCD_REV_MINOR 0x03int MCD_getVersion(char **longVersion){ *longVersion = MCD_versionString; return ((MCD_REV_MAJOR << 8) | MCD_REV_MINOR);}/********************** End of MCD_getVersion() *********************//********************************************************************//* Private version of memcpy() * Note that everything this is used for is longword-aligned. */static void MCD_memcpy(int *dest, int *src, u32 size){ u32 i; for (i = 0; i < size; i += sizeof(int), dest++, src++) *dest = *src;}#endif /* CONFIG_FSLDMAFEC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -