コード例 #1
0
ファイル: dmacHw_extra.c プロジェクト: BinVul/linux2.6.32
int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
		   void *pDescriptor,	/*   [ IN ] Descriptor buffer */
		   void (*fpFree) (void *)	/*   [ IN ] Function pointer to free data memory */
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	uint32_t count = 0;

	if (fpFree == NULL) {
		return -1;
	}

	while ((pRing->pFree != pRing->pTail)
	       && (pRing->pFree->ctl.lo & dmacHw_DESC_FREE)) {
		if (pRing->pFree->devCtl == dmacHw_FREE_USER_MEMORY) {
			/* Identify, which memory to free */
			if (dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
				(*fpFree) ((void *)pRing->pFree->dar);
			} else {
				/* Destination was a peripheral */
				(*fpFree) ((void *)pRing->pFree->sar);
			}
			/* Unmark user memory to indicate it is freed */
			pRing->pFree->devCtl = ~dmacHw_FREE_USER_MEMORY;
		}
		dmacHw_NEXT_DESC(pRing, pFree);

		count++;
	}

	return count;
}
コード例 #2
0
int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig,	
		   void *pDescriptor,	
		   void (*fpFree) (void *)	
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	uint32_t count = 0;

	if (fpFree == NULL) {
		return -1;
	}

	while ((pRing->pFree != pRing->pTail)
	       && (pRing->pFree->ctl.lo & dmacHw_DESC_FREE)) {
		if (pRing->pFree->devCtl == dmacHw_FREE_USER_MEMORY) {
			
			if (dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
				(*fpFree) ((void *)pRing->pFree->dar);
			} else {
				
				(*fpFree) ((void *)pRing->pFree->sar);
			}
			
			pRing->pFree->devCtl = ~dmacHw_FREE_USER_MEMORY;
		}
		dmacHw_NEXT_DESC(pRing, pFree);

		count++;
	}

	return count;
}
コード例 #3
0
ファイル: dmacHw_extra.c プロジェクト: BinVul/linux2.6.32
int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
				void *pDescriptor,	/*   [ IN ] Descriptor buffer */
				uint32_t ctlAddress,	/*   [ IN ] Address of the device control register */
				uint32_t control	/*   [ IN ] Device control information */
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);

	if (ctlAddress == 0) {
		return -1;
	}

	/* Check the availability of descriptors in the ring */
	if ((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) {
		return -1;
	}
	/* Set control information */
	pRing->pHead->devCtl = control;
	/* Set source and destination address */
	pRing->pHead->sar = (uint32_t) &pRing->pHead->devCtl;
	pRing->pHead->dar = ctlAddress;
	/* Set control parameters */
	if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) {
		pRing->pHead->ctl.lo = pConfig->transferType |
		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
		    pConfig->dstMaxTransactionWidth |
		    dmacHw_SRC_BURST_WIDTH_0 |
		    dmacHw_DST_BURST_WIDTH_0 |
		    pConfig->srcMasterInterface |
		    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
	} else {
		uint32_t transferType = 0;
		switch (pConfig->transferType) {
		case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
			transferType = dmacHw_REG_CTL_TTFC_PM_PERI;
			break;
		case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
			transferType = dmacHw_REG_CTL_TTFC_MP_PERI;
			break;
		default:
			dmacHw_ASSERT(0);
		}
		pRing->pHead->ctl.lo = transferType |
		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
		    pConfig->dstMaxTransactionWidth |
		    dmacHw_SRC_BURST_WIDTH_0 |
		    dmacHw_DST_BURST_WIDTH_0 |
		    pConfig->srcMasterInterface |
		    pConfig->dstMasterInterface |
		    pConfig->flowControler | dmacHw_REG_CTL_INT_EN;
	}

	/* Set block transaction size to one 32 bit transaction */
	pRing->pHead->ctl.hi = dmacHw_REG_CTL_BLOCK_TS_MASK & 1;

	/* Remember the descriptor to initialize the registers */
	if (pRing->pProg == dmacHw_DESC_INIT) {
		pRing->pProg = pRing->pHead;
	}
	pRing->pEnd = pRing->pHead;

	/* Advance the descriptor */
	dmacHw_NEXT_DESC(pRing, pHead);

	/* Update Tail pointer if destination is a peripheral */
	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
		pRing->pTail = pRing->pHead;
	}
	return 0;
}
コード例 #4
0
ファイル: dmacHw.c プロジェクト: Blackburn29/PsycoKernel
int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig,	
			     void *pDescriptor,	
			     void *pSrcAddr,	
			     void *pDstAddr,	
			     size_t dataLen	
    ) {
	dmacHw_TRANSACTION_WIDTH_e dstTrWidth;
	dmacHw_TRANSACTION_WIDTH_e srcTrWidth;
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	dmacHw_DESC_t *pStart;
	dmacHw_DESC_t *pProg;
	int srcTs = 0;
	int blkTs = 0;
	int oddSize = 0;
	int descCount = 0;
	int count = 0;
	int dstTrSize = 0;
	int srcTrSize = 0;
	uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE;

	dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth);
	srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth);

	
	if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) {
		
		return -1;
	}

	
	if ((pConfig->srcGatherWidth % srcTrSize)
	    || (pConfig->dstScatterWidth % dstTrSize)) {
		return -2;
	}


	
	dstTrWidth = pConfig->dstMaxTransactionWidth;
	while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) {
		dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth);
		dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth);
	}

	
	srcTrWidth = pConfig->srcMaxTransactionWidth;
	while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) {
		srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth);
		srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth);
	}

	
	if (pConfig->maxDataPerBlock
	    && ((pConfig->maxDataPerBlock / srcTrSize) <
		dmacHw_MAX_BLOCKSIZE)) {
		maxBlockSize = pConfig->maxDataPerBlock / srcTrSize;
	}

	
	srcTs = dataLen / srcTrSize;
	
	if (srcTs && (dstTrSize > srcTrSize)) {
		oddSize = dataLen % dstTrSize;
		
		srcTs = srcTs - (oddSize / srcTrSize);
	} else {
		oddSize = dataLen % srcTrSize;
	}
	
	if (oddSize) {
		descCount++;
	}
	
	if (srcTs) {
		descCount += ((srcTs - 1) / maxBlockSize) + 1;
	}

	
	pProg = pRing->pHead;
	for (count = 0; (descCount <= pRing->num) && (count < descCount);
	     count++) {
		if ((pProg->ctl.hi & dmacHw_DESC_FREE) == 0) {
			
			return -3;
		}
		pProg = (dmacHw_DESC_t *) pProg->llp;
	}

	
	pStart = pProg = pRing->pHead;
	
	while (count) {
		
		pProg->ctl.lo = 0;
		
		if (pConfig->srcGatherWidth) {
			pProg->ctl.lo |= dmacHw_REG_CTL_SG_ENABLE;
		}
		
		if (pConfig->dstScatterWidth) {
			pProg->ctl.lo |= dmacHw_REG_CTL_DS_ENABLE;
		}
		
		pProg->sar = (uint32_t) pSrcAddr;
		pProg->dar = (uint32_t) pDstAddr;
		
		if (pProg == pRing->pHead) {
			pProg->devCtl = dmacHw_FREE_USER_MEMORY;
		} else {
			pProg->devCtl = 0;
		}

		blkTs = srcTs;

		
		if (count == 1) {
			
			pProg->ctl.lo &=
			    ~(dmacHw_REG_CTL_LLP_DST_EN |
			      dmacHw_REG_CTL_LLP_SRC_EN);
			
			if (oddSize) {
				
				switch (pConfig->transferType) {
				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
					dstTrWidth =
					    dmacHw_DST_TRANSACTION_WIDTH_8;
					blkTs =
					    (oddSize / srcTrSize) +
					    ((oddSize % srcTrSize) ? 1 : 0);
					break;
				case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
					srcTrWidth =
					    dmacHw_SRC_TRANSACTION_WIDTH_8;
					blkTs = oddSize;
					break;
				case dmacHw_TRANSFER_TYPE_MEM_TO_MEM:
					srcTrWidth =
					    dmacHw_SRC_TRANSACTION_WIDTH_8;
					dstTrWidth =
					    dmacHw_DST_TRANSACTION_WIDTH_8;
					blkTs = oddSize;
					break;
				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL:
					
					break;
				}
			} else {
				srcTs -= blkTs;
			}
		} else {
			if (srcTs / maxBlockSize) {
				blkTs = maxBlockSize;
			}
			
			srcTs -= blkTs;
		}
		
		dmacHw_ASSERT(blkTs > 0);
		
		if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) {
			pProg->ctl.lo |= pConfig->transferType |
			    pConfig->srcUpdate |
			    pConfig->dstUpdate |
			    srcTrWidth |
			    dstTrWidth |
			    pConfig->srcMaxBurstWidth |
			    pConfig->dstMaxBurstWidth |
			    pConfig->srcMasterInterface |
			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
		} else {
			uint32_t transferType = 0;
			switch (pConfig->transferType) {
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
				transferType = dmacHw_REG_CTL_TTFC_PM_PERI;
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
				transferType = dmacHw_REG_CTL_TTFC_MP_PERI;
				break;
			default:
				dmacHw_ASSERT(0);
			}
			pProg->ctl.lo |= transferType |
			    pConfig->srcUpdate |
			    pConfig->dstUpdate |
			    srcTrWidth |
			    dstTrWidth |
			    pConfig->srcMaxBurstWidth |
			    pConfig->dstMaxBurstWidth |
			    pConfig->srcMasterInterface |
			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
		}

		
		pProg->ctl.hi = blkTs & dmacHw_REG_CTL_BLOCK_TS_MASK;
		
		if (count > 1) {
			
			pProg = (dmacHw_DESC_t *) pProg->llp;

			
			switch (pConfig->transferType) {
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
				if (pConfig->dstScatterWidth) {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->dstScatterWidth) *
					     pConfig->dstScatterJump);
				} else {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
				if (pConfig->srcGatherWidth) {
					pSrcAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->srcGatherWidth) *
					     pConfig->srcGatherJump);
				} else {
					pSrcAddr =
					    (char *)pSrcAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_MEM:
				if (pConfig->dstScatterWidth) {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->dstScatterWidth) *
					     pConfig->dstScatterJump);
				} else {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize;
				}

				if (pConfig->srcGatherWidth) {
					pSrcAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->srcGatherWidth) *
					     pConfig->srcGatherJump);
				} else {
					pSrcAddr =
					    (char *)pSrcAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL:
				
				break;
			default:
				dmacHw_ASSERT(0);
			}
		} else {
			
			dmacHw_ASSERT(srcTs == 0);
		}
		count--;
	}

	
	if (pRing->pProg == dmacHw_DESC_INIT) {
		pRing->pProg = pStart;
	}
	
	pRing->pEnd = pProg;
	
	pRing->pHead = (dmacHw_DESC_t *) pProg->llp;
	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
		pRing->pTail = pRing->pHead;
	}
	return 0;
}
コード例 #5
0
ファイル: dmacHw.c プロジェクト: BinVul/linux2.6.32
int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
			     void *pDescriptor,	/*   [ IN ] Descriptor buffer */
			     void *pSrcAddr,	/*   [ IN ] Source (Peripheral/Memory) address */
			     void *pDstAddr,	/*   [ IN ] Destination (Peripheral/Memory) address */
			     size_t dataLen	/*   [ IN ] Data length in bytes */
    ) {
	dmacHw_TRANSACTION_WIDTH_e dstTrWidth;
	dmacHw_TRANSACTION_WIDTH_e srcTrWidth;
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	dmacHw_DESC_t *pStart;
	dmacHw_DESC_t *pProg;
	int srcTs = 0;
	int blkTs = 0;
	int oddSize = 0;
	int descCount = 0;
	int count = 0;
	int dstTrSize = 0;
	int srcTrSize = 0;
	uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE;

	dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth);
	srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth);

	/* Skip Tx if buffer is NULL  or length is unknown */
	if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) {
		/* Do not initiate transfer */
		return -1;
	}

	/* Ensure scatter and gather are transaction aligned */
	if ((pConfig->srcGatherWidth % srcTrSize)
	    || (pConfig->dstScatterWidth % dstTrSize)) {
		return -2;
	}

	/*
	   Background 1: DMAC can not perform DMA if source and destination addresses are
	   not properly aligned with the channel's transaction width. So, for successful
	   DMA transfer, transaction width must be set according to the alignment of the
	   source and destination address.
	 */

	/* Adjust destination transaction width if destination address is not aligned properly */
	dstTrWidth = pConfig->dstMaxTransactionWidth;
	while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) {
		dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth);
		dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth);
	}

	/* Adjust source transaction width if source address is not aligned properly */
	srcTrWidth = pConfig->srcMaxTransactionWidth;
	while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) {
		srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth);
		srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth);
	}

	/* Find the maximum transaction per descriptor */
	if (pConfig->maxDataPerBlock
	    && ((pConfig->maxDataPerBlock / srcTrSize) <
		dmacHw_MAX_BLOCKSIZE)) {
		maxBlockSize = pConfig->maxDataPerBlock / srcTrSize;
	}

	/* Find number of source transactions needed to complete the DMA transfer */
	srcTs = dataLen / srcTrSize;
	/* Find the odd number of bytes that need to be transferred as single byte transaction width */
	if (srcTs && (dstTrSize > srcTrSize)) {
		oddSize = dataLen % dstTrSize;
		/* Adjust source transaction count due to "oddSize" */
		srcTs = srcTs - (oddSize / srcTrSize);
	} else {
		oddSize = dataLen % srcTrSize;
	}
	/* Adjust "descCount" due to "oddSize" */
	if (oddSize) {
		descCount++;
	}
	/* Find the number of descriptor needed for total "srcTs" */
	if (srcTs) {
		descCount += ((srcTs - 1) / maxBlockSize) + 1;
	}

	/* Check the availability of "descCount" discriptors in the ring */
	pProg = pRing->pHead;
	for (count = 0; (descCount <= pRing->num) && (count < descCount);
	     count++) {
		if ((pProg->ctl.hi & dmacHw_DESC_FREE) == 0) {
			/* Sufficient descriptors are not available */
			return -3;
		}
		pProg = (dmacHw_DESC_t *) pProg->llp;
	}

	/* Remember the link list item to program the channel registers */
	pStart = pProg = pRing->pHead;
	/* Make a link list with "descCount(=count)" number of descriptors */
	while (count) {
		/* Reset channel control information */
		pProg->ctl.lo = 0;
		/* Enable source gather if configured */
		if (pConfig->srcGatherWidth) {
			pProg->ctl.lo |= dmacHw_REG_CTL_SG_ENABLE;
		}
		/* Enable destination scatter if configured */
		if (pConfig->dstScatterWidth) {
			pProg->ctl.lo |= dmacHw_REG_CTL_DS_ENABLE;
		}
		/* Set source and destination address */
		pProg->sar = (uint32_t) pSrcAddr;
		pProg->dar = (uint32_t) pDstAddr;
		/* Use "devCtl" to mark that user memory need to be freed later if needed */
		if (pProg == pRing->pHead) {
			pProg->devCtl = dmacHw_FREE_USER_MEMORY;
		} else {
			pProg->devCtl = 0;
		}

		blkTs = srcTs;

		/* Special treatmeant for last descriptor */
		if (count == 1) {
			/* Mark the last descriptor */
			pProg->ctl.lo &=
			    ~(dmacHw_REG_CTL_LLP_DST_EN |
			      dmacHw_REG_CTL_LLP_SRC_EN);
			/* Treatment for odd data bytes */
			if (oddSize) {
				/* Adjust for single byte transaction width */
				switch (pConfig->transferType) {
				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
					dstTrWidth =
					    dmacHw_DST_TRANSACTION_WIDTH_8;
					blkTs =
					    (oddSize / srcTrSize) +
					    ((oddSize % srcTrSize) ? 1 : 0);
					break;
				case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
					srcTrWidth =
					    dmacHw_SRC_TRANSACTION_WIDTH_8;
					blkTs = oddSize;
					break;
				case dmacHw_TRANSFER_TYPE_MEM_TO_MEM:
					srcTrWidth =
					    dmacHw_SRC_TRANSACTION_WIDTH_8;
					dstTrWidth =
					    dmacHw_DST_TRANSACTION_WIDTH_8;
					blkTs = oddSize;
					break;
				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL:
					/* Do not adjust the transaction width  */
					break;
				}
			} else {
				srcTs -= blkTs;
			}
		} else {
			if (srcTs / maxBlockSize) {
				blkTs = maxBlockSize;
			}
			/* Remaining source transactions for next iteration */
			srcTs -= blkTs;
		}
		/* Must have a valid source transactions */
		dmacHw_ASSERT(blkTs > 0);
		/* Set control information */
		if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) {
			pProg->ctl.lo |= pConfig->transferType |
			    pConfig->srcUpdate |
			    pConfig->dstUpdate |
			    srcTrWidth |
			    dstTrWidth |
			    pConfig->srcMaxBurstWidth |
			    pConfig->dstMaxBurstWidth |
			    pConfig->srcMasterInterface |
			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
		} else {
			uint32_t transferType = 0;
			switch (pConfig->transferType) {
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
				transferType = dmacHw_REG_CTL_TTFC_PM_PERI;
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
				transferType = dmacHw_REG_CTL_TTFC_MP_PERI;
				break;
			default:
				dmacHw_ASSERT(0);
			}
			pProg->ctl.lo |= transferType |
			    pConfig->srcUpdate |
			    pConfig->dstUpdate |
			    srcTrWidth |
			    dstTrWidth |
			    pConfig->srcMaxBurstWidth |
			    pConfig->dstMaxBurstWidth |
			    pConfig->srcMasterInterface |
			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
		}

		/* Set block transaction size */
		pProg->ctl.hi = blkTs & dmacHw_REG_CTL_BLOCK_TS_MASK;
		/* Look for next descriptor */
		if (count > 1) {
			/* Point to the next descriptor */
			pProg = (dmacHw_DESC_t *) pProg->llp;

			/* Update source and destination address for next iteration */
			switch (pConfig->transferType) {
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
				if (pConfig->dstScatterWidth) {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->dstScatterWidth) *
					     pConfig->dstScatterJump);
				} else {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
				if (pConfig->srcGatherWidth) {
					pSrcAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->srcGatherWidth) *
					     pConfig->srcGatherJump);
				} else {
					pSrcAddr =
					    (char *)pSrcAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_MEM_TO_MEM:
				if (pConfig->dstScatterWidth) {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->dstScatterWidth) *
					     pConfig->dstScatterJump);
				} else {
					pDstAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize;
				}

				if (pConfig->srcGatherWidth) {
					pSrcAddr =
					    (char *)pDstAddr +
					    blkTs * srcTrSize +
					    (((blkTs * srcTrSize) /
					      pConfig->srcGatherWidth) *
					     pConfig->srcGatherJump);
				} else {
					pSrcAddr =
					    (char *)pSrcAddr +
					    blkTs * srcTrSize;
				}
				break;
			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL:
				/* Do not adjust the address */
				break;
			default:
				dmacHw_ASSERT(0);
			}
		} else {
			/* At the end of transfer "srcTs" must be zero */
			dmacHw_ASSERT(srcTs == 0);
		}
		count--;
	}

	/* Remember the descriptor to initialize the registers */
	if (pRing->pProg == dmacHw_DESC_INIT) {
		pRing->pProg = pStart;
	}
	/* Indicate that the descriptor is updated */
	pRing->pEnd = pProg;
	/* Head pointing to the next descriptor */
	pRing->pHead = (dmacHw_DESC_t *) pProg->llp;
	/* Update Tail pointer if destination is a peripheral,
	   because no one is going to read from the pTail
	 */
	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
		pRing->pTail = pRing->pHead;
	}
	return 0;
}
コード例 #6
0
int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig,	
				void *pDescriptor,	
				uint32_t ctlAddress,	
				uint32_t control	
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);

	if (ctlAddress == 0) {
		return -1;
	}

	
	if ((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) {
		return -1;
	}
	
	pRing->pHead->devCtl = control;
	
	pRing->pHead->sar = (uint32_t) &pRing->pHead->devCtl;
	pRing->pHead->dar = ctlAddress;
	
	if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) {
		pRing->pHead->ctl.lo = pConfig->transferType |
		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
		    pConfig->dstMaxTransactionWidth |
		    dmacHw_SRC_BURST_WIDTH_0 |
		    dmacHw_DST_BURST_WIDTH_0 |
		    pConfig->srcMasterInterface |
		    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
	} else {
		uint32_t transferType = 0;
		switch (pConfig->transferType) {
		case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
			transferType = dmacHw_REG_CTL_TTFC_PM_PERI;
			break;
		case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
			transferType = dmacHw_REG_CTL_TTFC_MP_PERI;
			break;
		default:
			dmacHw_ASSERT(0);
		}
		pRing->pHead->ctl.lo = transferType |
		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
		    pConfig->dstMaxTransactionWidth |
		    dmacHw_SRC_BURST_WIDTH_0 |
		    dmacHw_DST_BURST_WIDTH_0 |
		    pConfig->srcMasterInterface |
		    pConfig->dstMasterInterface |
		    pConfig->flowControler | dmacHw_REG_CTL_INT_EN;
	}

	
	pRing->pHead->ctl.hi = dmacHw_REG_CTL_BLOCK_TS_MASK & 1;

	
	if (pRing->pProg == dmacHw_DESC_INIT) {
		pRing->pProg = pRing->pHead;
	}
	pRing->pEnd = pRing->pHead;

	
	dmacHw_NEXT_DESC(pRing, pHead);

	
	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
		pRing->pTail = pRing->pHead;
	}
	return 0;
}