Hint dma_transfer(XAxiCdma *dma, Huint SrcAddr, Huint DstAddr, Hint byte_Length) { Hint Status, CDMA_Status; // Wait for the dma controller to not be busy while(dma_getbusy(dma)); Status = XAxiCdma_SimpleTransfer(dma, SrcAddr, DstAddr, byte_Length, NULL, NULL); if (Status != SUCCESS) { CDMA_Status = dma_geterror(dma); if (CDMA_Status != SUCCESS) { TRACE_PRINTF( TRACE_ERR, TRACE_DMA, "DMA ERROR: (CDMA Status=0x%08x)\n", CDMA_Status ); // Reset the device dma_reset(dma); } else TRACE_PRINTF( TRACE_ERR, TRACE_DMA, "DMA ERROR: (Perhaps an existing transfer ongoing?)\n"); return FAILURE; } return SUCCESS; }
int XAxiCdma_Transfer(XAxiCdma *InstancePtr, u32 SrcAddr, u32 DstAddr, int byte_Length, XAxiCdma_CallBackFn SimpleCallBack, void *CallbackRef) { int Status, CDMA_Status; Status = XAxiCdma_SimpleTransfer(InstancePtr, (u32) SrcAddr , (u32) DstAddr, byte_Length, NULL, NULL); if (Status != XST_SUCCESS) { CDMA_Status = XAxiCdma_GetError(InstancePtr); if (CDMA_Status != 0x0) { XAxiCdma_Reset(InstancePtr); //xil_xil_printf("Error Code = %x\r\r\n",CDMA_Status); } return XST_FAILURE; } while (XAxiCdma_IsBusy(InstancePtr)); // Wait CDMA_Status = XAxiCdma_GetError(InstancePtr); if (CDMA_Status != 0x0) { XAxiCdma_Reset(InstancePtr); //xil_xil_printf("Error Code = %x\r\r\n",CDMA_Status); return XST_FAILURE; } return XST_SUCCESS; }
int wlan_mac_cdma_start_transfer(void* dest, void* src, u32 size){ //This is a wrapper function around the central DMA simple transfer call. It's arguments //are intended to be similar to memcpy. Note: This function does not block on the transfer. int return_value; while(XAxiCdma_IsBusy(&cdma_inst)) {} return_value = XAxiCdma_SimpleTransfer(&cdma_inst, (u32)src, (u32)dest, size, NULL, NULL); return return_value; }
void mpdu_transmit(packet_bd* tx_queue) { wlan_ipc_msg ipc_msg_to_low; tx_frame_info* tx_mpdu = (tx_frame_info*) TX_PKT_BUF_TO_ADDR(tx_pkt_buf); station_info* station = (station_info*)(tx_queue->metadata_ptr); if(is_tx_buffer_empty()){ //For now, this is just a one-shot DMA transfer that effectively blocks while(XAxiCdma_IsBusy(&cdma_inst)) {} XAxiCdma_SimpleTransfer(&cdma_inst, (u32)(tx_queue->buf_ptr), (u32)TX_PKT_BUF_TO_ADDR(tx_pkt_buf), ((tx_packet_buffer*)(tx_queue->buf_ptr))->frame_info.length + sizeof(tx_frame_info) + PHY_TX_PKT_BUF_PHY_HDR_SIZE, NULL, NULL); while(XAxiCdma_IsBusy(&cdma_inst)) {} if(station == NULL){ //Broadcast transmissions have no station information, so we default to a nominal rate tx_mpdu->AID = 0; tx_mpdu->rate = WLAN_MAC_RATE_6M; } else { //Request the rate to use for this station tx_mpdu->AID = station->AID; tx_mpdu->rate = wlan_mac_util_get_tx_rate(station); //tx_mpdu->rate = default_unicast_rate; } tx_mpdu->state = TX_MPDU_STATE_READY; tx_mpdu->retry_count = 0; ipc_msg_to_low.msg_id = IPC_MBOX_MSG_ID(IPC_MBOX_TX_MPDU_READY); ipc_msg_to_low.arg0 = tx_pkt_buf; ipc_msg_to_low.num_payload_words = 0; if(unlock_pkt_buf_tx(tx_pkt_buf) != PKT_BUF_MUTEX_SUCCESS){ warp_printf(PL_ERROR,"Error: unable to unlock tx pkt_buf %d\n",tx_pkt_buf); } else { set_cpu_low_not_ready(); /* WMP START */ tx_pkt_buf_prev_acc = 0; /* WMP END */ ipc_mailbox_write_msg(&ipc_msg_to_low); } } else { warp_printf(PL_ERROR, "Bad state in mpdu_transmit. Attempting to transmit but tx_buffer %d is not empty\n",tx_pkt_buf); } return; }
/* * * This function does one simple transfer * * @param InstancePtr is a pointer to the XAxiCdma instance * @param Length is the transfer length * @param Retries is how many times to retry on submission * * @return * - XST_SUCCESS if transfer is successful * - XST_FAILURE if either the transfer fails or the data has * error. * * @note None. * ******************************************************************************/ static int DoSimpleTransfer(XAxiCdma *InstancePtr, int Length, int Retries) { u32 Index; u8 *SrcPtr; u8 *DestPtr; int Status; Done = 0; Error = 0; /* Initialize the source buffer bytes with a pattern and the * the destination buffer bytes to zero */ SrcPtr = (u8 *)SrcBuffer; DestPtr = (u8 *)DestBuffer; for (Index = 0; Index < Length; Index++) { SrcPtr[Index] = Index & 0xFF; DestPtr[Index] = 0; } /* Flush the SrcBuffer before the DMA transfer, in case the Data Cache * is enabled */ Xil_DCacheFlushRange((u32)&SrcBuffer, Length); /* Try to start the DMA transfer */ while (Retries) { Retries -= 1; Status = XAxiCdma_SimpleTransfer(InstancePtr, (u32)SrcBuffer, (u32)DestBuffer, Length, Example_SimpleCallBack, InstancePtr); if (Status == XST_SUCCESS) { break; } } if (!Retries) { xdbg_printf(XDBG_DEBUG_ERROR, "Submit transfer failed\r\n"); return XST_FAILURE; } /* Wait until the DMA transfer is done */ while (!Done && !Error) { /* Wait */ } if (Error) { xdbg_printf(XDBG_DEBUG_ERROR, "Simple transfer has error %x\r\n", (unsigned int)XAxiCdma_GetError(InstancePtr)); return XST_FAILURE; } /* Transfer completes successfully, check data */ Status = CheckData(SrcPtr, DestPtr, Length); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_ERROR, "Check data failed for simple " "transfer\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/** * This function transfers data from Source Address to Destination Address * using the AXI CDMA. * User has to specify the Source Address, Destination Address and Transfer * Length in AXICDMA_SRC_ADDR, AXICDMA_DEST_ADDR and AXICDMA_LENGTH defines * respectively. * * @param DeviceId is device ID of the XAxiCdma Device. * * @return - XST_SUCCESS if successful * - XST_FAILURE.if unsuccessful. * * @note If the hardware system is not built correctly, this function * may never return to the caller. * ******************************************************************************/ int DmaDataTransfer (u16 DeviceID) { int Status; volatile int Error; XAxiCdma_Config *ConfigPtr; Error = 0; /* * Make sure we have a valid addresses for Src and Dst. */ if (AXICDMA_SRC_ADDR == 0) { return XST_FAILURE; } if (AXICDMA_DEST_ADDR == 0) { return XST_FAILURE; } /* * Initialize the AXI CDMA IP. */ ConfigPtr = XAxiCdma_LookupConfig(DeviceID); if (ConfigPtr == NULL) { return XST_FAILURE; } Status = XAxiCdma_CfgInitialize(&CdmaInstance, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Reset the AXI CDMA device. */ XAxiCdma_Reset(&CdmaInstance); /* * Disable AXI CDMA Interrupts */ XAxiCdma_IntrDisable(&CdmaInstance, XAXICDMA_XR_IRQ_ALL_MASK); /* * Start Transferring Data from source to destination in polled mode */ XAxiCdma_SimpleTransfer (&CdmaInstance, AXICDMA_SRC_ADDR, AXICDMA_DEST_ADDR, AXICDMA_LENGTH, 0, 0); /* * Poll Status register waiting for either Completion or Error */ while (XAxiCdma_IsBusy(&CdmaInstance)); Error = XAxiCdma_GetError(&CdmaInstance); if (Error != 0x0) { xil_printf("AXI CDMA Transfer Error = %8.8x\r\n"); return XST_FAILURE; } xil_printf("AXI CDMA Transfer is Complete\r\n"); return XST_SUCCESS; }
u32 GetRequestCmd(P_HOST_CMD hostCmd) { u32 hostAddr, isDmaError; P_REQUEST_IO reqInfoAddr = (P_REQUEST_IO)(REQUEST_IO_BASE_ADDR); barAddrPtr.UpperAddr = Xil_In32(CONFIG_SPACE_REQUEST_BASE_ADDR_U); barAddrPtr.LowerAddr = Xil_In32(CONFIG_SPACE_REQUEST_BASE_ADDR_L); //DebugPrint("BarAddrPtr.UpperAddr = 0x%x\n\r", BarAddrPtr.UpperAddr); //DebugPrint("BarAddrPtr.LowerAddr = 0x%x\n\r", BarAddrPtr.LowerAddr); while(XAxiCdma_IsBusy(&devCdma)) { } while(1) { XAxiPcie_SetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtr); XAxiPcie_GetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtrForTest); if(barAddrPtr.LowerAddr == barAddrPtrForTest.LowerAddr) { if(barAddrPtr.UpperAddr == barAddrPtrForTest.UpperAddr) { break; } } } hostAddr = Xil_In32(CONFIG_SPACE_REQUEST_BASE_ADDR_L) & DMA_ADDR_MASK; hostAddr = XPAR_AXIPCIE_0_AXIBAR_0 + hostAddr; //wait until cdma is idle while(XAxiCdma_IsBusy(&devCdma)) { } do { isDmaError = XAxiCdma_SimpleTransfer(&devCdma, hostAddr, (u32)reqInfoAddr, sizeof(REQUEST_IO), NULL, NULL); if(isDmaError) DebugPrint("%s, %d\n\r", __FUNCTION__, __LINE__); } while(isDmaError); //wait until dma operation is done DebugPrint("getting requst cmd... "); while(XAxiCdma_IsBusy(&devCdma)) { } DebugPrint("done!\n\r"); *((u32*)(&hostCmd->reqInfo)) = Xil_In32((u32)(reqInfoAddr)); hostCmd->reqInfo.currentSect = Xil_In32((u32)(&reqInfoAddr->currentSect)); hostCmd->reqInfo.ReqSect = Xil_In32((u32)(&reqInfoAddr->ReqSect)); hostCmd->reqInfo.HostScatterAddrU = Xil_In32((u32)(&reqInfoAddr->HostScatterAddrU)); hostCmd->reqInfo.HostScatterAddrL = Xil_In32((u32)(&reqInfoAddr->HostScatterAddrL)); hostCmd->reqInfo.HostScatterLen = Xil_In32((u32)(&reqInfoAddr->HostScatterLen)); DebugPrint("Cmd = 0x%x\n\r", hostCmd->reqInfo.Cmd); DebugPrint("currentSect = 0x%x\n\r", hostCmd->reqInfo.currentSect); DebugPrint("ReqSect = 0x%x\n\r", hostCmd->reqInfo.ReqSect); DebugPrint("HostScatterAddrU = 0x%x\n\r", hostCmd->reqInfo.HostScatterAddrU); DebugPrint("HostScatterAddrL = 0x%x\n\r", hostCmd->reqInfo.HostScatterAddrL); DebugPrint("HostScatterLen = 0x%x\n\r\n\r", hostCmd->reqInfo.HostScatterLen); return TRUE; }
void CompleteCmd(P_HOST_CMD hostCmd) { u32 hostAddr, isDmaError; barAddrPtr.UpperAddr = Xil_In32(CONFIG_SPACE_COMPLETION_BASE_ADDR_U); barAddrPtr.LowerAddr = Xil_In32(CONFIG_SPACE_COMPLETION_BASE_ADDR_L); while(XAxiCdma_IsBusy(&devCdma)) { } XAxiPcie_SetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtr); //DebugPrint("Completion IO addr: 0x%x\n\r", Xil_In32(COMPLETION_IO_BASE_ADDR)); pCompletionIO->CmdStatus = hostCmd->CmdStatus; pCompletionIO->ErrorStatus = hostCmd->ErrorStatus; pCompletionIO->Done = 0; pCompletionIO->debug_ReqCount++; hostAddr = Xil_In32(CONFIG_SPACE_COMPLETION_BASE_ADDR_L) & DMA_ADDR_MASK; hostAddr = XPAR_AXIPCIE_0_AXIBAR_0 + hostAddr; //DebugPrint("i = 0x%x\n\r", hostAddr); //wait until cdma is idle while(XAxiCdma_IsBusy(&devCdma)) { } do { isDmaError = XAxiCdma_SimpleTransfer(&devCdma, COMPLETION_IO_BASE_ADDR, hostAddr, sizeof(COMPLETION_IO), NULL, NULL); if(isDmaError) DebugPrint("%s, %d\n\r", __FUNCTION__, __LINE__); } while(isDmaError); //DebugPrint("posting completion cmd without deadface... "); while(XAxiCdma_IsBusy(&devCdma)) { } //DebugPrint("done!\n\r"); pCompletionIO->Done = 0xdeadface; do { isDmaError = XAxiCdma_SimpleTransfer(&devCdma, COMPLETION_IO_BASE_ADDR, hostAddr, sizeof(COMPLETION_IO), NULL, NULL); if(isDmaError) DebugPrint("%s, %d\n\r", __FUNCTION__, __LINE__); } while(isDmaError); //DebugPrint("posting completion cmd with deadface... "); while(XAxiCdma_IsBusy(&devCdma)) { } //DebugPrint("done!\n\r"); DebugPrint("return CompleteCmd\n\r\n\r\n\r"); }
void DmaHostToDevice(P_HOST_CMD hostCmd, u32 deviceAddr, u32 reqSize, u32 scatterLength) { u32 hostAddr; u32 flag; u32 deviceAddrOffset; u32 curScatterRegionNum; u32 curDmaSize; u32 remainedCurrentScatterRegionSize; u32 acc; u32 isDmaError; ///////////////////////////////////////////////////////////////////// //get HOST_SCATTER_REGION array from HOST ///////////////////////////////////////////////////////////////////// barAddrPtr.UpperAddr = hostCmd->reqInfo.HostScatterAddrU; barAddrPtr.LowerAddr = hostCmd->reqInfo.HostScatterAddrL; //DebugPrint("scatterRegionAddrU = 0x%x\n\r", barAddrPtr.UpperAddr); //DebugPrint("scatterRegionAddrL = 0x%x\n\r", barAddrPtr.LowerAddr); while(XAxiCdma_IsBusy(&devCdma)) { } while(1) { XAxiPcie_SetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtr); XAxiPcie_GetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtrForTest); if(barAddrPtr.LowerAddr == barAddrPtrForTest.LowerAddr) { if(barAddrPtr.UpperAddr == barAddrPtrForTest.UpperAddr) { break; } } } hostAddr = hostCmd->reqInfo.HostScatterAddrL & DMA_ADDR_MASK; hostAddr = XPAR_AXIPCIE_0_AXIBAR_0 + hostAddr; //wait until cdma is idle while(XAxiCdma_IsBusy(&devCdma)) { } DebugPrint("hostAddr = 0x%x\n\r", hostAddr); //get host scatter region do { isDmaError = XAxiCdma_SimpleTransfer(&devCdma, hostAddr, HOST_SCATTER_REGION_BASE_ADDR, sizeof(HOST_SCATTER_REGION) * scatterLength, NULL, NULL); if(isDmaError) DebugPrint("%s, %d\n\r", __FUNCTION__, __LINE__); } while(isDmaError); DebugPrint("getting HOST_SCATTER_REGION data... "); while(XAxiCdma_IsBusy(&devCdma)) { } DebugPrint("done!\n\r"); ///////////////////////////////////////////////////////////////////// //start data dma ///////////////////////////////////////////////////////////////////// flag = 0; deviceAddrOffset = 0; curScatterRegionNum = 0; acc = 0; while(curScatterRegionNum < scatterLength) { remainedCurrentScatterRegionSize = pHostScaterRegion[curScatterRegionNum].Length - acc; DebugPrint("remainedCurrentScatterRegionSize = 0x%x\n\r", remainedCurrentScatterRegionSize); if(flag == 0)//normal transfer { DebugPrint("flag 0\n\r"); //set host address barAddrPtr.UpperAddr = pHostScaterRegion[curScatterRegionNum].DmaAddrU; barAddrPtr.LowerAddr = pHostScaterRegion[curScatterRegionNum].DmaAddrL; hostAddr = barAddrPtr.LowerAddr & DMA_ADDR_MASK; hostAddr = XPAR_AXIPCIE_0_AXIBAR_0 + hostAddr; //if blabla~ if(((XPAR_AXIPCIE_0_AXIBAR_HIGHADDR_0 + 1) - hostAddr) < remainedCurrentScatterRegionSize)// { flag = 1; curDmaSize = (XPAR_AXIPCIE_0_AXIBAR_HIGHADDR_0 + 1) - hostAddr; acc += curDmaSize; } //if blabla~ else { curDmaSize = remainedCurrentScatterRegionSize; curScatterRegionNum += 1; } } else//partial transfer { DebugPrint("flag 1\n\r"); //set host address if((barAddrPtr.LowerAddr + curDmaSize) < barAddrPtr.LowerAddr) { barAddrPtr.UpperAddr += 1; } barAddrPtr.LowerAddr += curDmaSize; hostAddr = barAddrPtr.LowerAddr & DMA_ADDR_MASK; hostAddr = XPAR_AXIPCIE_0_AXIBAR_0 + hostAddr; //if blabla~ if(((XPAR_AXIPCIE_0_AXIBAR_HIGHADDR_0 + 1) - hostAddr) < remainedCurrentScatterRegionSize)// { curDmaSize = (XPAR_AXIPCIE_0_AXIBAR_HIGHADDR_0 + 1) - hostAddr; acc += curDmaSize; } //if blabla~ else//last { curDmaSize = remainedCurrentScatterRegionSize; flag = 0; acc = 0; curScatterRegionNum += 1; } } DebugPrint("dmaAddrU = 0x%x\n\r", barAddrPtr.UpperAddr); DebugPrint("dmaAddrL = 0x%x\n\r", barAddrPtr.LowerAddr); while(XAxiCdma_IsBusy(&devCdma)) { } while(1) { XAxiPcie_SetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtr); XAxiPcie_GetLocalBusBar2PcieBar(&devPcie, 0x00, &barAddrPtrForTest); if(barAddrPtr.LowerAddr == barAddrPtrForTest.LowerAddr) { if(barAddrPtr.UpperAddr == barAddrPtrForTest.UpperAddr) { break; } } } while(XAxiCdma_IsBusy(&devCdma)) { } do { isDmaError = XAxiCdma_SimpleTransfer(&devCdma, hostAddr, deviceAddr + deviceAddrOffset, curDmaSize, NULL, NULL); if(isDmaError) DebugPrint("%s, %d\n\r", __FUNCTION__, __LINE__); } while(isDmaError); while(XAxiCdma_IsBusy(&devCdma)) { } deviceAddrOffset += curDmaSize; } DebugPrint("%x\n\r", Xil_In32(deviceAddr)); }
/* * This function does one simple transfer in polled mode * * @param InstancePtr is a pointer to the XAxiCdma instance * @param Length is the transfer length * @param Retries is how many times to retry on submission * * @return * - XST_SUCCESS if transfer is successful * - XST_FAILURE if either the transfer fails or the data has * error * * @note None * ******************************************************************************/ static int DoSimplePollTransfer(XAxiCdma *InstancePtr, int Length, int Retries) { int Index; u8 *SrcPtr; u8 *DestPtr; int Status; /* Initialize the source buffer bytes with a pattern and the * the destination buffer bytes to zero */ SrcPtr = (u8 *)SrcBuffer; DestPtr = (u8 *)DestBuffer; for (Index = 0; Index < BUFFER_BYTESIZE; Index++) { SrcPtr[Index] = Index & 0xFF; DestPtr[Index] = 0; } /* Flush the SrcBuffer before the DMA transfer, in case the Data Cache * is enabled */ Xil_DCacheFlushRange((u32)&SrcBuffer, Length); /* Try to start the DMA transfer */ while (Retries) { Retries -= 1; Status = XAxiCdma_SimpleTransfer(InstancePtr, (u32)SrcBuffer, (u32)DestBuffer, Length, NULL, NULL); if (Status == XST_SUCCESS) { break; } } /* Return failure if failed to submit the transfer */ if (!Retries) { return XST_FAILURE; } /* Wait until the DMA transfer is done */ while (XAxiCdma_IsBusy(InstancePtr)) { /* Wait */ } /* If the hardware has errors, this example fails * This is a poll example, no interrupt handler is involved. * Therefore, error conditions are not cleared by the driver. */ Error = XAxiCdma_GetError(InstancePtr); if (Error != 0x0) { int TimeOut = RESET_LOOP_COUNT; /* Need to reset the hardware to restore to the correct state */ XAxiCdma_Reset(InstancePtr); while (TimeOut) { if (XAxiCdma_ResetIsDone(InstancePtr)) { break; } TimeOut -= 1; } /* Reset has failed, print a message to notify the user */ return XST_FAILURE; } /* Transfer completes successfully, check data */ Status = CheckData(SrcPtr, DestPtr, Length); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; }