예제 #1
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;
}
예제 #2
0
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;
}
예제 #3
0
int dmacHw_readTransferredData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle */
			       dmacHw_CONFIG_t *pConfig,	/*   [ IN ]  Configuration settings */
			       void *pDescriptor,	/*   [ IN ] Descriptor buffer */
			       void **ppBbuf,	/*   [ OUT ] Data received */
			       size_t *pLlen	/*   [ OUT ] Length of the data received */
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);

	(void)handle;

	if (pConfig->transferMode != dmacHw_TRANSFER_MODE_CONTINUOUS) {
		if (((pRing->pTail->ctl.hi & dmacHw_DESC_FREE) == 0) ||
		    (pRing->pTail == pRing->pHead)
		    ) {
			/* No receive data available */
			*ppBbuf = (char *)NULL;
			*pLlen = 0;

			return 0;
		}
	}

	/* Return read buffer and length */
	*ppBbuf = (char *)pRing->pTail->dar;

	/* Extract length of the received data */
	if (DmaIsFlowController(pDescriptor)) {
		uint32_t srcTrSize = 0;

		switch (pRing->pTail->ctl.lo & dmacHw_REG_CTL_SRC_TR_WIDTH_MASK) {
		case dmacHw_REG_CTL_SRC_TR_WIDTH_8:
			srcTrSize = 1;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_16:
			srcTrSize = 2;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_32:
			srcTrSize = 4;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_64:
			srcTrSize = 8;
			break;
		default:
			dmacHw_ASSERT(0);
		}
		/* Calculate length from the block size */
		*pLlen =
		    (pRing->pTail->ctl.hi & dmacHw_REG_CTL_BLOCK_TS_MASK) *
		    srcTrSize;
	} else {
		/* Extract length from the source peripheral */
		*pLlen = pRing->pTail->sstat;
	}

	/* Advance tail to next descriptor */
	dmacHw_NEXT_DESC(pRing, pTail);

	return 1;
}
예제 #4
0
int dmacHw_readTransferredData(dmacHw_HANDLE_t handle,	
			       dmacHw_CONFIG_t *pConfig,	
			       void *pDescriptor,	
			       void **ppBbuf,	
			       size_t *pLlen	
    ) {
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);

	(void)handle;

	if (pConfig->transferMode != dmacHw_TRANSFER_MODE_CONTINUOUS) {
		if (((pRing->pTail->ctl.hi & dmacHw_DESC_FREE) == 0) ||
		    (pRing->pTail == pRing->pHead)
		    ) {
			
			*ppBbuf = (char *)NULL;
			*pLlen = 0;

			return 0;
		}
	}

	
	*ppBbuf = (char *)pRing->pTail->dar;

	
	if (DmaIsFlowController(pDescriptor)) {
		uint32_t srcTrSize = 0;

		switch (pRing->pTail->ctl.lo & dmacHw_REG_CTL_SRC_TR_WIDTH_MASK) {
		case dmacHw_REG_CTL_SRC_TR_WIDTH_8:
			srcTrSize = 1;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_16:
			srcTrSize = 2;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_32:
			srcTrSize = 4;
			break;
		case dmacHw_REG_CTL_SRC_TR_WIDTH_64:
			srcTrSize = 8;
			break;
		default:
			dmacHw_ASSERT(0);
		}
		
		*pLlen =
		    (pRing->pTail->ctl.hi & dmacHw_REG_CTL_BLOCK_TS_MASK) *
		    srcTrSize;
	} else {
		
		*pLlen = pRing->pTail->sstat;
	}

	
	dmacHw_NEXT_DESC(pRing, pTail);

	return 1;
}
예제 #5
0
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;
}
예제 #6
0
int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
				     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
				     void *pDescriptor,	/*   [ IN ] Descriptor buffer */
				     uint32_t srcAddr,	/*   [ IN ] Source peripheral address */
				     void *(*fpAlloc) (int len),	/*   [ IN ] Function pointer  that provides destination memory */
				     int len,	/*   [ IN ] Number of bytes "fpAlloc" will allocate for destination */
				     int num	/*   [ IN ] Number of descriptor to set */
    ) {
	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
	dmacHw_DESC_t *pProg = NULL;
	dmacHw_DESC_t *pLast = NULL;
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	uint32_t dstAddr;
	uint32_t controlParam;
	int i;

	dmacHw_ASSERT(pConfig->transferType ==
		      dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM);

	if (num > pRing->num) {
		return -1;
	}

	pLast = pRing->pEnd;	/* Last descriptor updated */
	pProg = pRing->pHead;	/* First descriptor in the new list */

	controlParam = pConfig->srcUpdate |
	    pConfig->dstUpdate |
	    pConfig->srcMaxTransactionWidth |
	    pConfig->dstMaxTransactionWidth |
	    pConfig->srcMasterInterface |
	    pConfig->dstMasterInterface |
	    pConfig->srcMaxBurstWidth |
	    pConfig->dstMaxBurstWidth |
	    dmacHw_REG_CTL_TTFC_PM_PERI |
	    dmacHw_REG_CTL_LLP_DST_EN |
	    dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN;

	for (i = 0; i < num; i++) {
		/* Allocate Rx buffer only for idle descriptor */
		if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) ||
		    ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail)
		    ) {
			/* Rx descriptor is not idle */
			break;
		}
		/* Set source address */
		pRing->pHead->sar = srcAddr;
		if (fpAlloc) {
			/* Allocate memory for buffer in descriptor */
			dstAddr = (uint32_t) (*fpAlloc) (len);
			/* Check the destination address */
			if (dstAddr == 0) {
				if (i == 0) {
					/* Not a single descriptor is available */
					return -1;
				}
				break;
			}
			/* Set destination address */
			pRing->pHead->dar = dstAddr;
		}
		/* Set control information */
		pRing->pHead->ctl.lo = controlParam;
		/* Use "devCtl" to mark the memory that need to be freed later */
		pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY;
		/* Descriptor is now owned by the channel */
		pRing->pHead->ctl.hi = 0;
		/* Remember the descriptor last updated */
		pRing->pEnd = pRing->pHead;
		/* Update next descriptor */
		dmacHw_NEXT_DESC(pRing, pHead);
	}

	/* Mark the end of the list */
	pRing->pEnd->ctl.lo &=
	    ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN);
	/* Connect the list */
	if (pLast != pProg) {
		pLast->ctl.lo |=
		    dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN;
	}
	/* Mark the descriptors are updated */
	pCblk->descUpdated = 1;
	if (!pCblk->varDataStarted) {
		/* LLP must be pointing to the first descriptor */
		dmacHw_SET_LLP(pCblk->module, pCblk->channel,
			       (uint32_t) pProg - pRing->virt2PhyOffset);
		/* Channel, handling variable data started */
		pCblk->varDataStarted = 1;
	}

	return i;
}
예제 #7
0
void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle,	
			     dmacHw_CONFIG_t *pConfig,	
			     void *pDescriptor	
    ) {
	dmacHw_DESC_RING_t *pRing;
	dmacHw_DESC_t *pProg;
	dmacHw_CBLK_t *pCblk;

	pCblk = dmacHw_HANDLE_TO_CBLK(handle);
	pRing = dmacHw_GET_DESC_RING(pDescriptor);

	if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) {
		
		return;
	}

	if (pCblk->varDataStarted) {
		if (pCblk->descUpdated) {
			pCblk->descUpdated = 0;
			pProg =
			    (dmacHw_DESC_t *) ((uint32_t)
					       dmacHw_REG_LLP(pCblk->module,
							      pCblk->channel) +
					       pRing->virt2PhyOffset);

			
			if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) {
				dmacHw_SET_SAR(pCblk->module, pCblk->channel,
					       pProg->sar);
				dmacHw_SET_DAR(pCblk->module, pCblk->channel,
					       pProg->dar);
				dmacHw_REG_CTL_LO(pCblk->module,
						  pCblk->channel) =
				    pProg->ctl.lo;
				dmacHw_REG_CTL_HI(pCblk->module,
						  pCblk->channel) =
				    pProg->ctl.hi;
			} else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) {
				
				return;
			} else {
				dmacHw_ASSERT(0);
			}
		} else {
			return;
		}
	} else {
		if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) {
			
			pProg = pRing->pHead;
			
			dmacHw_NEXT_DESC(pRing, pHead);
		} else {
			
			if (pRing->pEnd == NULL) {
				return;
			}

			pProg = pRing->pProg;
			if (pConfig->transferMode ==
			    dmacHw_TRANSFER_MODE_CONTINUOUS) {
				
				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd->
					      llp == pRing->pProg);
				
				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg ==
					      pRing->pHead);
				
				do {
					pRing->pProg->ctl.lo |=
					    (dmacHw_REG_CTL_LLP_DST_EN |
					     dmacHw_REG_CTL_LLP_SRC_EN);
					pRing->pProg =
					    (dmacHw_DESC_t *) pRing->pProg->llp;
				} while (pRing->pProg != pRing->pHead);
			} else {
				
				while (pRing->pProg != pRing->pEnd) {
					pRing->pProg->ctl.lo |=
					    (dmacHw_REG_CTL_LLP_DST_EN |
					     dmacHw_REG_CTL_LLP_SRC_EN);
					pRing->pProg =
					    (dmacHw_DESC_t *) pRing->pProg->llp;
				}
			}
		}

		
		dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar);
		dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar);
		dmacHw_SET_LLP(pCblk->module, pCblk->channel,
			       (uint32_t) pProg - pRing->virt2PhyOffset);
		dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) =
		    pProg->ctl.lo;
		dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) =
		    pProg->ctl.hi;
		if (pRing->pEnd) {
			
			pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp;
		}
		
		pRing->pEnd = (dmacHw_DESC_t *) NULL;
	}
	
	dmacHw_DMA_START(pCblk->module, pCblk->channel);
}
예제 #8
0
파일: dmacHw.c 프로젝트: BinVul/linux2.6.32
void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
			     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
			     void *pDescriptor	/*   [ IN ] Descriptor buffer */
    ) {
	dmacHw_DESC_RING_t *pRing;
	dmacHw_DESC_t *pProg;
	dmacHw_CBLK_t *pCblk;

	pCblk = dmacHw_HANDLE_TO_CBLK(handle);
	pRing = dmacHw_GET_DESC_RING(pDescriptor);

	if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) {
		/* Not safe yet to program the channel */
		return;
	}

	if (pCblk->varDataStarted) {
		if (pCblk->descUpdated) {
			pCblk->descUpdated = 0;
			pProg =
			    (dmacHw_DESC_t *) ((uint32_t)
					       dmacHw_REG_LLP(pCblk->module,
							      pCblk->channel) +
					       pRing->virt2PhyOffset);

			/* Load descriptor if not loaded */
			if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) {
				dmacHw_SET_SAR(pCblk->module, pCblk->channel,
					       pProg->sar);
				dmacHw_SET_DAR(pCblk->module, pCblk->channel,
					       pProg->dar);
				dmacHw_REG_CTL_LO(pCblk->module,
						  pCblk->channel) =
				    pProg->ctl.lo;
				dmacHw_REG_CTL_HI(pCblk->module,
						  pCblk->channel) =
				    pProg->ctl.hi;
			} else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) {
				/* Return as end descriptor is processed */
				return;
			} else {
				dmacHw_ASSERT(0);
			}
		} else {
			return;
		}
	} else {
		if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) {
			/* Do not make a single chain, rather process one descriptor at a time */
			pProg = pRing->pHead;
			/* Point to the next descriptor for next iteration */
			dmacHw_NEXT_DESC(pRing, pHead);
		} else {
			/* Return if no more pending descriptor */
			if (pRing->pEnd == NULL) {
				return;
			}

			pProg = pRing->pProg;
			if (pConfig->transferMode ==
			    dmacHw_TRANSFER_MODE_CONTINUOUS) {
				/* Make sure a complete ring can be formed */
				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd->
					      llp == pRing->pProg);
				/* Make sure pProg pointing to the pHead */
				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg ==
					      pRing->pHead);
				/* Make a complete ring */
				do {
					pRing->pProg->ctl.lo |=
					    (dmacHw_REG_CTL_LLP_DST_EN |
					     dmacHw_REG_CTL_LLP_SRC_EN);
					pRing->pProg =
					    (dmacHw_DESC_t *) pRing->pProg->llp;
				} while (pRing->pProg != pRing->pHead);
			} else {
				/* Make a single long chain */
				while (pRing->pProg != pRing->pEnd) {
					pRing->pProg->ctl.lo |=
					    (dmacHw_REG_CTL_LLP_DST_EN |
					     dmacHw_REG_CTL_LLP_SRC_EN);
					pRing->pProg =
					    (dmacHw_DESC_t *) pRing->pProg->llp;
				}
			}
		}

		/* Program the channel registers */
		dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar);
		dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar);
		dmacHw_SET_LLP(pCblk->module, pCblk->channel,
			       (uint32_t) pProg - pRing->virt2PhyOffset);
		dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) =
		    pProg->ctl.lo;
		dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) =
		    pProg->ctl.hi;
		if (pRing->pEnd) {
			/* Remember the descriptor to use next */
			pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp;
		}
		/* Indicate no more pending descriptor  */
		pRing->pEnd = (dmacHw_DESC_t *) NULL;
	}
	/* Start DMA operation */
	dmacHw_DMA_START(pCblk->module, pCblk->channel);
}
예제 #9
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;
}
예제 #10
0
int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle,	
				     dmacHw_CONFIG_t *pConfig,	
				     void *pDescriptor,	
				     uint32_t srcAddr,	
				     void *(*fpAlloc) (int len),	
				     int len,	
				     int num	
    ) {
	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
	dmacHw_DESC_t *pProg = NULL;
	dmacHw_DESC_t *pLast = NULL;
	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
	uint32_t dstAddr;
	uint32_t controlParam;
	int i;

	dmacHw_ASSERT(pConfig->transferType ==
		      dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM);

	if (num > pRing->num) {
		return -1;
	}

	pLast = pRing->pEnd;	
	pProg = pRing->pHead;	

	controlParam = pConfig->srcUpdate |
	    pConfig->dstUpdate |
	    pConfig->srcMaxTransactionWidth |
	    pConfig->dstMaxTransactionWidth |
	    pConfig->srcMasterInterface |
	    pConfig->dstMasterInterface |
	    pConfig->srcMaxBurstWidth |
	    pConfig->dstMaxBurstWidth |
	    dmacHw_REG_CTL_TTFC_PM_PERI |
	    dmacHw_REG_CTL_LLP_DST_EN |
	    dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN;

	for (i = 0; i < num; i++) {
		
		if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) ||
		    ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail)
		    ) {
			
			break;
		}
		
		pRing->pHead->sar = srcAddr;
		if (fpAlloc) {
			
			dstAddr = (uint32_t) (*fpAlloc) (len);
			
			if (dstAddr == 0) {
				if (i == 0) {
					
					return -1;
				}
				break;
			}
			
			pRing->pHead->dar = dstAddr;
		}
		
		pRing->pHead->ctl.lo = controlParam;
		
		pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY;
		
		pRing->pHead->ctl.hi = 0;
		
		pRing->pEnd = pRing->pHead;
		
		dmacHw_NEXT_DESC(pRing, pHead);
	}

	
	pRing->pEnd->ctl.lo &=
	    ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN);
	
	if (pLast != pProg) {
		pLast->ctl.lo |=
		    dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN;
	}
	
	pCblk->descUpdated = 1;
	if (!pCblk->varDataStarted) {
		
		dmacHw_SET_LLP(pCblk->module, pCblk->channel,
			       (uint32_t) pProg - pRing->virt2PhyOffset);
		
		pCblk->varDataStarted = 1;
	}

	return i;
}