/** * Configure buffer addresses for one DMA channel * * The buffer addresses are physical addresses. * Access to 32 Frame Buffer Addresses in direct mode is done through * XAxiVdma_ChannelHiFrmAddrEnable/Disable Functions. * 0 - Access Bank0 Registers (0x5C - 0x98) * 1 - Access Bank1 Registers (0x5C - 0x98) * * @param Channel is the pointer to the channel to work on * @param BufferAddrSet is the set of addresses for the transfers * @param NumFrames is the number of frames to set the address * * @return * - XST_SUCCESS if successful * - XST_FAILURE if channel has not being initialized * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned * address with no DRE built in the hardware * *****************************************************************************/ int XAxiVdma_ChannelSetBufferAddr(XAxiVdma_Channel *Channel, u32 *BufferAddrSet, int NumFrames) { int i; u32 WordLenBits; int HiFrmAddr = 0; int FrmBound = (XAXIVDMA_MAX_FRAMESTORE)/2 - 1; int Loop16 = 0; if (!Channel->IsValid) { xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); return XST_FAILURE; } WordLenBits = (u32)(Channel->WordLength - 1); /* If hardware has no DRE, then buffer addresses must * be word-aligned */ for (i = 0; i < NumFrames; i++) { if (!Channel->HasDRE) { if (BufferAddrSet[i] & WordLenBits) { xdbg_printf(XDBG_DEBUG_ERROR, "Unaligned address %d: %x without DRE\r\n", i, BufferAddrSet[i]); return XST_INVALID_PARAM; } } } for (i = 0; i < NumFrames; i++, Loop16++) { XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr + i * sizeof(XAxiVdma_Bd)); if (Channel->HasSG) { XAxiVdma_BdSetAddr(BdPtr, BufferAddrSet[i]); } else { if ((i > FrmBound) && !HiFrmAddr) { XAxiVdma_ChannelHiFrmAddrEnable(Channel); HiFrmAddr = 1; Loop16 = 0; } XAxiVdma_WriteReg(Channel->StartAddrBase, XAXIVDMA_START_ADDR_OFFSET + Loop16 * XAXIVDMA_START_ADDR_LEN, BufferAddrSet[i]); if ((NumFrames > FrmBound) && (i == (NumFrames - 1))) XAxiVdma_ChannelHiFrmAddrDisable(Channel); } } return XST_SUCCESS; }
/** * Configure buffer addresses for one DMA channel * * The buffer addresses are physical addresses. * Access to 32 Frame Buffer Addresses in direct mode is done through * XAxiVdma_ChannelHiFrmAddrEnable/Disable Functions. * 0 - Access Bank0 Registers (0x5C - 0x98) * 1 - Access Bank1 Registers (0x5C - 0x98) * * @param Channel is the pointer to the channel to work on * @param BufferAddrSet is the set of addresses for the transfers * @param NumFrames is the number of frames to set the address * * @return * - XST_SUCCESS if successful * - XST_FAILURE if channel has not being initialized * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned * address with no DRE built in the hardware * *****************************************************************************/ int XAxiVdma_ChannelSetBufferAddr(XAxiVdma_Channel *Channel, UINTPTR *BufferAddrSet, int NumFrames) { int i; u32 WordLenBits; int HiFrmAddr = 0; int FrmBound; if (Channel->AddrWidth > 32) { FrmBound = (XAXIVDMA_MAX_FRAMESTORE_64)/2 - 1; } else { FrmBound = (XAXIVDMA_MAX_FRAMESTORE)/2 - 1; } int Loop16 = 0; if (!Channel->IsValid) { //xil_printf("channel not initialized \r\n"); xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); return XST_FAILURE; } WordLenBits = (u32)(Channel->WordLength - 1); /* If hardware has no DRE, then buffer addresses must * be word-aligned */ for (i = 0; i < NumFrames; i++) { if (!Channel->HasDRE) { if (BufferAddrSet[i] & WordLenBits) { xdbg_printf(XDBG_DEBUG_ERROR, "Unaligned address %d: %x without DRE\r\n", i, BufferAddrSet[i]); //xil_printf("Unaligned address %d: %x without DRE\r\n", //i, BufferAddrSet[i]);///////////// return XST_INVALID_PARAM; } } } for (i = 0; i < NumFrames; i++, Loop16++) { XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr + i * sizeof(XAxiVdma_Bd)); if (Channel->HasSG) { XAxiVdma_BdSetAddr(BdPtr, BufferAddrSet[i]); } else { if ((i > FrmBound) && !HiFrmAddr) { XAxiVdma_ChannelHiFrmAddrEnable(Channel); HiFrmAddr = 1; Loop16 = 0; } if (Channel->AddrWidth > 32) { /* For a 40-bit address XAXIVDMA_MAX_FRAMESTORE * value should be set to 16 */ XAxiVdma_WriteReg(Channel->StartAddrBase, XAXIVDMA_START_ADDR_OFFSET + Loop16 * XAXIVDMA_START_ADDR_LEN + i*4, LOWER_32_BITS(BufferAddrSet[i])); XAxiVdma_WriteReg(Channel->StartAddrBase, XAXIVDMA_START_ADDR_MSB_OFFSET + Loop16 * XAXIVDMA_START_ADDR_LEN + i*4, UPPER_32_BITS((u64)BufferAddrSet[i])); } else { XAxiVdma_WriteReg(Channel->StartAddrBase, XAXIVDMA_START_ADDR_OFFSET + Loop16 * XAXIVDMA_START_ADDR_LEN, BufferAddrSet[i]); } if ((NumFrames > FrmBound) && (i == (NumFrames - 1))) XAxiVdma_ChannelHiFrmAddrDisable(Channel); } } return XST_SUCCESS; }