dma.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* DMA.C - DMA functions and definitions */
  2. /* Copyright Galileo Technology. */
  3. /*
  4. DESCRIPTION
  5. This file gives the user a complete interface to the powerful DMA engines,
  6. including functions for controling the priority mechanism.
  7. To fully understand the capabilities of the DMA engines please spare some
  8. time to go trough the spec.
  9. */
  10. /* includes */
  11. #ifdef __linux__
  12. #include <asm/galileo/evb64120A/core.h>
  13. #include <asm/galileo/evb64120A/dma.h>
  14. #else
  15. #include "Core.h"
  16. #include "DMA.h"
  17. #endif
  18. /********************************************************************
  19. * dmaCommand - Write a command to a DMA channel
  20. *
  21. * Inputs: DMA_ENGINE channel - choosing one of the four engine.
  22. *         unsigned int command - The command to be written to the control register.
  23. * Returns: false if one of the parameters is erroneous else returns true.
  24. *********************************************************************/
  25. bool dmaCommand(DMA_ENGINE channel, unsigned int command)
  26. {
  27. if (channel > LAST_DMA_ENGINE)
  28. return false;
  29. GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
  30. return true;
  31. }
  32. /********************************************************************
  33. * dmaTransfer - transfer data from sourceAddr to destAddr on DMA channel
  34. * Inputs:
  35. *   DMA_RECORED *nextRecoredPointer: If we are using chain mode DMA transfer,
  36. *   then this pointer should point to the next recored,otherwise it should be
  37. *   NULL.
  38. *   VERY IMPORTANT !!! When using chain mode, the records must be 16 Bytes
  39. *   aligned, the function will take care of that for you, but you need to
  40. *   allocate one more record for that, meaning: if you are having 3 records ,
  41. *   declare 4 (see the example bellow) and start using the second one.
  42. *   Example:
  43. *   Performing a chain mode DMA transfer(Copy a 1/4 mega of data using
  44. *   chain mode DMA):
  45. *    DMA_RECORED dmaRecoredArray[4];
  46. *    dmaRecoredArray[1].ByteCnt = _64KB;
  47. *    dmaRecoredArray[1].DestAdd = destAddress + _64KB;
  48. *    dmaRecoredArray[1].SrcAdd  = sourceAddress + _64KB;
  49. *    dmaRecoredArray[1].NextRecPtr = &dmaRecoredArray[2];
  50. *    dmaRecoredArray[2].ByteCnt = _64KB;
  51. *    dmaRecoredArray[2].DestAdd = destAddress + 2*_64KB;
  52. *    dmaRecoredArray[2].SrcAdd  = sourceAddress + 2*_64KB;
  53. *    dmaRecoredArray[2].NextRecPtr = &dmaRecoredArray[3];
  54. *    dmaRecoredArray[3].ByteCnt = _64KB;
  55. *    dmaRecoredArray[3].DestAdd = destAddress + 3*_64KB;
  56. *    dmaRecoredArray[3].SrcAdd  = sourceAddress + 3*_64KB;
  57. *    dmaRecoredArray[3].NextRecPtr = NULL;
  58. *    performCmDma(0,sourceAddress,destAddress,_64KB,PLAIN,WAIT_TO_END,
  59. *                            &dmaRecoredArray[1]);
  60. * Returns: NO_SUCH_CHANNEL if channel does not exist, CHANNEL_BUSY if channel
  61. *          is active and true if the transfer ended successfully
  62. *********************************************************************/
  63. DMA_STATUS dmaTransfer(DMA_ENGINE channel, unsigned int sourceAddr,
  64.        unsigned int destAddr, unsigned int numOfBytes,
  65.        unsigned int command,
  66.        DMA_RECORED * nextRecoredPointer)
  67. {
  68. unsigned int tempData, checkBits, alignmentOffset = 0;
  69. DMA_RECORED *next = nextRecoredPointer;
  70. if (channel > LAST_DMA_ENGINE)
  71. return NO_SUCH_CHANNEL;
  72. if (numOfBytes > 0xffff)
  73. return GENERAL_ERROR;
  74. if (isDmaChannelActive(channel))
  75. return CHANNEL_BUSY;
  76. if (next != NULL) { /* case of chain Mode */
  77. alignmentOffset = ((unsigned int) next % 16);
  78. }
  79. checkBits = command & 0x6000000;
  80. if (checkBits == 0) {
  81. while (next != NULL) {
  82. WRITE_WORD((unsigned int) next - alignmentOffset,
  83.    next->ByteCnt);
  84. tempData = (unsigned int) next->SrcAdd;
  85. WRITE_WORD((unsigned int) next + 4 -
  86.    alignmentOffset, tempData & 0x5fffffff);
  87. tempData = (unsigned int) next->DestAdd;
  88. WRITE_WORD((unsigned int) next + 8 -
  89.    alignmentOffset, tempData & 0x5fffffff);
  90. tempData = (unsigned int) next->NextRecPtr;
  91. WRITE_WORD((unsigned int) next + 12 -
  92.    alignmentOffset,
  93.    tempData & 0x5fffffff -
  94.    alignmentOffset);
  95. next = (DMA_RECORED *) tempData;
  96. if (next == nextRecoredPointer)
  97. next = NULL;
  98. }
  99. }
  100. GT_REG_WRITE(CHANNEL0_DMA_BYTE_COUNT + channel * 4, numOfBytes);
  101. tempData = sourceAddr;
  102. GT_REG_WRITE(CHANNEL0_DMA_SOURCE_ADDRESS + channel * 4,
  103.      tempData & 0x5fffffff);
  104. tempData = destAddr;
  105. GT_REG_WRITE(CHANNEL0_DMA_DESTINATION_ADDRESS + channel * 4,
  106.      tempData & 0x5fffffff);
  107. if (nextRecoredPointer != NULL) {
  108. tempData =
  109.     (unsigned int) nextRecoredPointer - alignmentOffset;
  110. GT_REG_WRITE(CHANNEL0NEXT_RECORD_POINTER + 4 * channel,
  111.      tempData & 0x5fffffff);
  112. command = command | CHANNEL_ENABLE;
  113. } else {
  114. command = command | CHANNEL_ENABLE | NON_CHAIN_MOD;
  115. }
  116. /* Activate DMA engine By writting to dmaControlRegister */
  117. GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command);
  118. return DMA_OK;
  119. }
  120. /********************************************************************
  121. * isDmaChannelActive - check if channel is busy
  122. *
  123. * Inputs: channel number
  124. * RETURNS: True if the channel is busy, false otherwise.
  125. *********************************************************************/
  126. bool isDmaChannelActive(DMA_ENGINE channel)
  127. {
  128. unsigned int data;
  129. if (channel > LAST_DMA_ENGINE)
  130. return false;
  131. GT_REG_READ(CHANNEL0CONTROL + 4 * channel, &data);
  132. if (data & DMA_ACTIVITY_STATUS)
  133. return true;
  134. else
  135. return false;
  136. }
  137. /********************************************************************
  138. * changeDmaPriority - update the arbiter`s priority for channels 0-3
  139. *
  140. * Inputs: priority  for channels 0-1, priority  for channels 2-3,
  141.           priority for groups and other priority options
  142. * RETURNS: false if one of the parameters is erroneous and true else
  143. *********************************************************************/
  144. bool changeDmaPriority(PRIO_CHAN_0_1 prio_01, PRIO_CHAN_2_3 prio_23,
  145.        PRIO_GROUP prioGrp, PRIO_OPT prioOpt)
  146. {
  147. unsigned int prioReg = 0;
  148. prioReg = (prio_01 & 0x3) + ((prio_23 & 0x3) << 2) +
  149.     ((prioGrp & 0x3) << 4) + (prioOpt << 6);
  150. GT_REG_WRITE(ARBITER_CONTROL, prioReg);
  151. return true;
  152. }