示例#1
0
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;
}
示例#7
0
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;
}
示例#8
0
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");
}
示例#9
0
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;
}