/**
 * Set the control bits for a BD.
 *
 * @param BdPtr is the BD to operate on.
 * @param Data is the bit value to set
 *
 * @return
 * None
 *
 *****************************************************************************/
void XAxiDma_BdSetCtrl(XAxiDma_Bd* BdPtr, u32 Data) {
	u32 RegValue = XAxiDma_BdRead(BdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);

	RegValue &= ~XAXIDMA_BD_CTRL_ALL_MASK;

	RegValue |= (Data & XAXIDMA_BD_CTRL_ALL_MASK);

	XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET, RegValue);

	return;
}
Exemple #2
0
/**
 * Get the APP word at the specified APP word offset for a BD.
 *
 * @param	BdPtr is the BD to operate on.
 * @param	Offset is the offset inside the APP word, it is valid from
 *		0 to 4
 * @param	Valid is to tell the caller whether parameters are valid
 *
 * @returns
 *		The APP word. Passed in parameter Valid holds 0 for failure,
 *		and 1 for success.
 *
 * @note	This function can be used only when DMA is in SG mode
 *
 *****************************************************************************/
u32 XAxiDma_BdGetAppWord(XAxiDma_Bd* BdPtr, int Offset, int *Valid)
{
	*Valid = 0;

	if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: no sts cntrl "
			"stream in hardware build, no app word available\r\n");

		return (u32)0;
	}

	if((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingGetAppWord: invalid"
			" offset %d", Offset);

		return (u32)0;
	}

	*Valid = 1;

	return XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4);
}
Exemple #3
0
/**
 * Set the length field for the given BD.
 *
 * Length has to be non-zero and less than LengthMask.
 *
 * For TX channels, the value passed in should be the number of bytes to
 * transmit from the TX buffer associated with the given BD.
 *
 * For RX channels, the value passed in should be the size of the RX buffer
 * associated with the given BD in bytes. This is to notify the RX channel
 * the capability of the RX buffer to avoid buffer overflow.
 *
 * The actual receive length can be equal or smaller than the specified length.
 * The actual transfer length will be updated by the hardware in the
 * XAXIDMA_BD_STS_OFFSET word in the BD.
 *
 * @param	BdPtr is the BD to operate on.
 * @param	LenBytes is the requested transfer length
 * @param	LengthMask is the maximum transfer length
 *
 * @returns
 *		- XST_SUCCESS for success
 *		- XST_INVALID_PARAM for invalid BD length
 *
 * @note	This function can be used only when DMA is in SG mode
 *
 *****************************************************************************/
int XAxiDma_BdSetLength(XAxiDma_Bd *BdPtr, u32 LenBytes, u32 LengthMask)
{
	if (LenBytes <= 0 || (LenBytes > LengthMask)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "invalid length %d\n",
		    (int)LenBytes);

		return XST_INVALID_PARAM;
	}

	XAxiDma_BdWrite((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET,
		((XAxiDma_BdRead((BdPtr), XAXIDMA_BD_CTRL_LEN_OFFSET) & \
		~LengthMask)) | LenBytes);

	return XST_SUCCESS;
}
/**
 * Set the BD's buffer address.
 *
 * @param  BdPtr is the BD to operate on
 * @param  Addr is the address to set
 *
 * @return
 * - XST_SUCCESS if buffer address set successfully
 * - XST_INVALID_PARAM if hardware has no DRE and address is not aligned 
 *
 *****************************************************************************/
int XAxiDma_BdSetBufAddr(XAxiDma_Bd* BdPtr, u32 Addr) {
	u32 HasDRE;
	u8 WordLen;

	HasDRE = XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_DRE_OFFSET);
	WordLen = HasDRE & XAXIDMA_BD_WORDLEN_MASK;

	if (Addr & (WordLen - 1)) {
		if ((HasDRE & XAXIDMA_BD_HAS_DRE_MASK) == 0) {
			xil_printf("Error set buf addr %x with %x and %x, %x\n\r",
			    Addr, HasDRE, (WordLen - 1), Addr & (WordLen - 1));

			return XST_INVALID_PARAM;
		}
	}

	XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_BUFA_OFFSET, Addr);

	return XST_SUCCESS;

}
Exemple #5
0
/**
 * Set the APP word at the specified APP word offset for a BD.
 *
 * @param	BdPtr is the BD to operate on.
 * @param	Offset is the offset inside the APP word, it is valid from
 *		0 to 4
 * @param	Word is the value to set
 *
 * @returns
 *		- XST_SUCCESS for success
 *		- XST_INVALID_PARAM under following error conditions:
 *		1) StsCntrlStrm is not built in hardware
 *		2) Offset is not in valid range
 *
 * @note
 *		If the hardware build has C_SG_USE_STSAPP_LENGTH set to 1,
 *		then the last APP word, XAXIDMA_LAST_APPWORD, must have
 *		non-zero value when AND with 0x7FFFFF. Not doing so will cause
 *		the hardware to stall.
 *		This function can be used only when DMA is in SG mode
 *
 *****************************************************************************/
int XAxiDma_BdSetAppWord(XAxiDma_Bd* BdPtr, int Offset, u32 Word)
{
	if (XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET) == 0) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: no sts cntrl"
			"stream in hardware build, cannot set app word\r\n");

		return XST_INVALID_PARAM;
	}

	if ((Offset < 0) || (Offset > XAXIDMA_LAST_APPWORD)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetAppWord: invalid"
			"offset %d",Offset);

		return XST_INVALID_PARAM;
	}

	XAxiDma_BdWrite(BdPtr, XAXIDMA_BD_USR0_OFFSET + Offset * 4, Word);

	return XST_SUCCESS;
}
Exemple #6
0
/**
 * Dump the fields of a BD.
 *
 * @param	BdPtr is the BD to operate on.
 *
 * @return	None
 *
 * @note	This function can be used only when DMA is in SG mode
 *
 *****************************************************************************/
void XAxiDma_DumpBd(XAxiDma_Bd* BdPtr)
{

	xil_printf("Dump BD %x:\r\n", (unsigned int)BdPtr);
	xil_printf("\tNext Bd Ptr: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_NDESC_OFFSET));
	xil_printf("\tBuff addr: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_BUFA_OFFSET));
	xil_printf("\tMCDMA Fields: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_MCCTL_OFFSET));
	xil_printf("\tVSIZE_STRIDE: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr,
					XAXIDMA_BD_STRIDE_VSIZE_OFFSET));
	xil_printf("\tContrl len: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET));
	xil_printf("\tStatus: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_STS_OFFSET));

	xil_printf("\tAPP 0: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR0_OFFSET));
	xil_printf("\tAPP 1: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR1_OFFSET));
	xil_printf("\tAPP 2: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR2_OFFSET));
	xil_printf("\tAPP 3: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR3_OFFSET));
	xil_printf("\tAPP 4: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_USR4_OFFSET));

	xil_printf("\tSW ID: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_ID_OFFSET));
	xil_printf("\tStsCtrl: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr,
	           XAXIDMA_BD_HAS_STSCNTRL_OFFSET));
	xil_printf("\tDRE: %x\r\n",
	    (unsigned int)XAxiDma_BdRead(BdPtr, XAXIDMA_BD_HAS_DRE_OFFSET));

	xil_printf("\r\n");
}
int main()
{	
	int bufId = 0;
    init_platform();

    printf("Hello World\n\r");
    if(i2c_init_clk() != XST_SUCCESS)
    	return -1;

    // Actual test
    // We'll allocate four packets on the heap
    uint8_t* buf[4];
    for(bufId = 0; bufId < 4; bufId++)
    {
    	//buf[bufId] = malloc(TEST_PKT_SIZE);
    	buf[bufId] = memalign(8, TEST_PKT_SIZE);

    	if(buf[bufId] == 0)
    		printf("ERROR: Buffer %d allocation failed\r\n", bufId);

    	// Sanity check the alignment
    	if((uint32_t)buf[bufId] & 0x7)
    	{
    		printf("ERROR: Buffer %d allocated at %p has invalid alignment\r\n", bufId, buf[bufId]);
    		return -1;
    	}
    }

    uint8_t destMac[6] = {0x00, 0x11, 0x22, 0x33, 0x01, 0x00};
    uint8_t srcMac[6] = {0x00, 0x11, 0x22, 0x33, 0x00, 0x00};

    // First, set up the actual contents of those packets
    for(bufId = 0; bufId < 4; bufId++)
    {
    	int i = 0;

    	// Fill in the MAC addresses
	    for(i = 0; i < 6; i++)
	    {
	    	buf[bufId][i]   = destMac[i];
	    	buf[bufId][i+6] = srcMac[i];
	    }

	    // Fill out the ethertype
    	buf[bufId][12] = 0x08;
    	buf[bufId][13] = 0x00;
    	memset(&buf[bufId][14], bufId+0xAA, TEST_PKT_SIZE - 14);
	}

    // Now fill in the bd descriptors
    // Alloc the BD descriptors
    XAxiDma_Bd* bd[4];
    for(bufId = 0; bufId < 4; bufId++)
    {
    	//bd[bufId] = malloc(sizeof(XAxiDma_Bd));
    	bd[bufId] = memalign(64, sizeof(XAxiDma_Bd));
    	if(bd[bufId] == 0)
    		printf("ERROR: Buffer BD descriptor %d allocation failed\r\n", bufId);

    	memset(bd[bufId], 0, sizeof(XAxiDma_Bd));

    	// Sanity check that they're aligned appropriately
    	// They need to be on a 16-word (i.e. 64-byte) boundary
    	if((uint32_t)bd[bufId] & 0x3F)
    	{
    		printf("ERROR: Buffer BD descriptor %d allocated at %p has invalid alignment\r\n", bufId, bd[bufId]);
    		return -1;
    	}

    	// Fill in the descriptor fields
    	//XAxiDma_BdSetBufAddr(bd[bufId], (uint32_t)buf[bufId]);
    	//XAxiDma_BdSetLength(bd[bufId], TEST_PKT_SIZE, DMA_BUF_MAX);

    	// Just do those manually - the driver appears to expect some metadata to be
    	// added by the ring manager, which we don't add ourselves.
    	XAxiDma_BdWrite(bd[bufId], XAXIDMA_BD_BUFA_OFFSET, (uint32_t)buf[bufId]);
    	XAxiDma_BdWrite(bd[bufId], XAXIDMA_BD_CTRL_LEN_OFFSET, TEST_PKT_SIZE);

    	// Need to set SOF and EOF bits too
    	// Do that manually - the API doesn't appear to expose it properly
    	// XAxiDma_Bd is actually an array behind the scenes, hence this syntax
    	uint32_t tmp = XAxiDma_BdRead(bd[bufId], XAXIDMA_BD_CTRL_LEN_OFFSET);
    	tmp |= (XAXIDMA_BD_CTRL_TXSOF_MASK | XAXIDMA_BD_CTRL_TXEOF_MASK);
    	XAxiDma_BdWrite(bd[bufId], XAXIDMA_BD_CTRL_LEN_OFFSET, tmp);
   	}

	for(bufId = 0; bufId < 4; bufId++)
	{
		// Set the "next" descriptor pointers now everything has been allocated properly.
    	XAxiDma_BdWrite(bd[bufId], XAXIDMA_BD_NDESC_OFFSET, (uint32_t)(bd[(bufId + 1) % 4]));

		// Debugging sanity check
		XAxiDma_DumpBd(bd[bufId]);
	}

	// Buffers should now be set up
	// Set up the DMA core and (hopefully) start!
	// Flush caches to ensure that everything is coherent
	for(bufId = 0; bufId < 4; bufId++)
	{
		XAXIDMA_CACHE_FLUSH(bd[bufId]);

		// Also flush packets
		// Syntax stolen from xaxidma_bd.h
		Xil_DCacheFlushRange((uint32_t)buf[bufId], TEST_PKT_SIZE);
	}

	// First, reset the DMA core
	uint32_t reg = 0;
	reg = DMA_GET_REG(XAXIDMA_CR_OFFSET);
	reg |= XAXIDMA_CR_RESET_MASK;
	DMA_SET_REG(XAXIDMA_CR_OFFSET, reg);
	while(DMA_GET_REG(XAXIDMA_CR_OFFSET) & XAXIDMA_CR_RESET_MASK);

	printf("DMA Reset\r\n");

	// Update the "next" pointer
	DMA_SET_REG(XAXIDMA_CDESC_OFFSET, (uint32_t)bd[0]);

	// The tail pointer should already be zero. Leave it.
	// Enable cyclic BD mode
	reg = DMA_GET_REG(XAXIDMA_CR_OFFSET);
	reg |= XAXIDMA_CR_CYCLIC_MASK;
	DMA_SET_REG(XAXIDMA_CR_OFFSET, reg);

	// Set run mode!
	reg = DMA_GET_REG(XAXIDMA_CR_OFFSET);
	reg |= XAXIDMA_CR_RUNSTOP_MASK;
	DMA_SET_REG(XAXIDMA_CR_OFFSET, reg);

	// Quickly check we can read the base address from the ethernet...
	printf("TEST: 0x%x\r\n", DMA_GET_REG(XAXIDMA_CR_OFFSET));

	// Cyclic mode seems to require that we write something to the tail descriptor
	DMA_SET_REG(XAXIDMA_TDESC_OFFSET, 0x0);

	while(1)
	{
		volatile int x = 0;
		uint32_t tmp = 0;
		uint32_t tmpHigh = 0;

		tmp = DMA_GET_REG(XAXIDMA_SR_OFFSET);
		printf("DMA STATUS: 0x%x\r\n", tmp);

		tmp = TENGIG_GET_REG(0x200); // LSW bytes recv
		tmpHigh = TENGIG_GET_REG(0x204); // MSW bytes recv
		printf("RX BYTES: 0x%x%x\r\n", tmpHigh, tmp);

		tmp = TENGIG_GET_REG(0x208); // LSW bytes tx
		tmpHigh = TENGIG_GET_REG(0x20C); // MSW bytes tx
		printf("TX BYTES: 0x%x%x\r\n", tmpHigh, tmp);

		tmp = TENGIG_GET_REG(0x2D8);
		tmpHigh = TENGIG_GET_REG(0x2DC);
		printf("TX OK: 0x%x%x\r\n", tmpHigh, tmp);

		tmp = TENGIG_GET_REG(0x2E0);
		tmpHigh = TENGIG_GET_REG(0x2E4);
		printf("TX BROADCAST: 0x%x%x\r\n", tmpHigh, tmp);

		tmp = TENGIG_GET_REG(0x2F0);
		tmpHigh = TENGIG_GET_REG(0x2F4);
		printf("TX UNDERRUN: 0x%x%x\r\n", tmpHigh, tmp);

		tmp = DMA_GET_REG(0x8);
		printf("CURDES: 0x%x\r\n", tmp);

		printf("\r\n");

		for(x = 0 ; x < 100000000; x++);
	}

    cleanup_platform();
    return 0;
}
/**
*
* This example sends and receives a single packet in loopback mode with
* extended VLAN support.
*
* The transmit frame will have VLAN field populated.
*
* On receive, HW should pass the VLAN field to receive BDs.
*
* @param	AxiEthernetInstancePtr is a pointer to the instance of the
*		AxiEthernet component.
* @param	DmaInstancePtr   is a pointer to the instance of the Dma
*		component.
*
* @return	-XST_SUCCESS to indicate success.
*		-XST_FAILURE to indicate failure.
*
* @note		Summary of VLAN tags handling in this example
*
* Frame setup with Tpid1+Cfi1+TxPid => 0x88A83111
* Frame translated to TxTransVid => 0x88A83222
* Frame tagged to Tpid2+Cfi2+TxTagVid => 0x9100C333 + 0x88A83222
* Frame sent and loopbacked.
*
* Frame stripped with RxStrpVid(0x333) => 0x88A83222
* Frame translated (key:RxVid:0x222) RxTransVid => 0x88A83444
*
******************************************************************************/
int AxiEthernetSgDmaIntrExtVlanExample(XAxiEthernet *AxiEthernetInstancePtr,
				XAxiDma *DmaInstancePtr)
{
	int Status;
	u32 TxFrameLength;
	u32 RxFrameLength;
	int PayloadSize = PAYLOAD_SIZE;
	u16 Tpid1 = 0x88A8;
	u16 Tpid2 = 0x9100;
	u8  Cfi1  = 0x03;
	u8  Cfi2  = 0x0C;
	u16 TxVid      = 0x0111;
	u16 TxTransVid = 0x0222;
	u16 TxTagVid   = 0x0333;
	u16 RxVid      = 0x0222;
	u16 RxTransVid = 0x0444;
	u16 RxStrpVid  = 0x0333;
	u32 VTagCfiVid;
	u16 RxCfiVid;
	u16 RxTpid;
	u32 RxStatusControlWord;
	int Valid;


	XAxiDma_BdRing *RxRingPtr = XAxiDma_GetRxRing(DmaInstancePtr);
	XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(DmaInstancePtr);
	XAxiDma_Bd *BdPtr;
	XAxiDma_Bd *BdCurPtr;
	u32 BdSts;

	/*
	 * Cannot run this example if extended features support is not enabled
	 */
	if (!(XAxiEthernet_IsTxVlanTran(AxiEthernetInstancePtr) &&
		XAxiEthernet_IsTxVlanStrp(AxiEthernetInstancePtr) &&
		XAxiEthernet_IsTxVlanTag(AxiEthernetInstancePtr)  &&
		XAxiEthernet_IsRxVlanTran(AxiEthernetInstancePtr) &&
		XAxiEthernet_IsRxVlanStrp(AxiEthernetInstancePtr) &&
		XAxiEthernet_IsRxVlanTag(AxiEthernetInstancePtr))) {
		AxiEthernetUtilErrorTrap("Extended VLAN not available");
		return XST_FAILURE;
	}

	/*
	 * Clear variables shared with callbacks
	 */
	FramesRx = 0;
	FramesTx = 0;
	DeviceErrors = 0;
	memset(RxFrame,0,sizeof(RxFrame));
	memset(TxFrame,0,sizeof(TxFrame));

	/*
	 * Calculate frame length (not including FCS) plus one VLAN tag
	 */
	TxFrameLength = XAE_HDR_VLAN_SIZE + PayloadSize;

	/*
	 * Setup the packet with one VALN tag = VtagCfiVid to be transmitted
	 * initially.
	 */
	VTagCfiVid = (((u32)Tpid1 << 16) | ((u32)Cfi1 << 12) | TxVid);
	AxiEthernetUtilFrameMemClear(&TxFrame);
	AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC);
	AxiEthernetUtilFrameHdrVlanFormatVid(&TxFrame, 0, VTagCfiVid);
	AxiEthernetUtilFrameHdrVlanFormatType(&TxFrame, PayloadSize, 1);
	AxiEthernetUtilFrameSetVlanPayloadData(&TxFrame, PayloadSize, 1);

	/* Intended VLAN setup:
	 * TX translation and tagging. RX stripping and translation.
	 *
	 * Frame setup with Tpid1+Cfi1+TxPid => 0x88A83111
	 * Frame translated to TxTransVid => 0x88A83222
	 * Frame tagged to Tpid2+Cfi2+TxTagVid => 0x9100C333 + 0x88A83222
	 * Frame sent and loopbacked.
	 *
	 * Frame stripped with RxStrpVid(0x333) => 0x88A83222
	 * Frame translated (key:RxVid:0x222) RxTransVid => 0x88A83444
	 */

	/* Extended VLAN transmit side. Stripping->Translation->Tagging */
	/*
	 * Configure VLAN TX tag mode, set to XAE_VTAG_SELECT.
	 */
	Status  = XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
						XAE_EXT_TXVLAN_TAG_OPTION);
	Status |= XAxiEthernet_SetVTagMode(AxiEthernetInstancePtr,
						XAE_VTAG_SELECT, XAE_TX);

	/*
	 * TX VLAN translation from TxVid to TxTransVid and enable tagging.
	 */
	Status |= XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
						XAE_EXT_TXVLAN_TRAN_OPTION);
	Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, TxVid,
						TxTransVid,0, 1, XAE_TX);

	/*
	 * TX VLAN tagging is keyed on TxVid to add one additional tag based
	 * on register XAE_TTAG_OFFSET value.
	 */
	VTagCfiVid = (((u32)Tpid2 << 16) | ((u32)Cfi2 << 12) | TxTagVid);
	Status |= XAxiEthernet_SetVTagValue(AxiEthernetInstancePtr,
							VTagCfiVid, XAE_TX);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting TX VLAN");
		return XST_FAILURE;
	}

	/* Extended VLAN receive side. Stripping->Translation->Tagging */
	/*
	 * Configure VLAN RX strip mode, set to XAE_VSTRP_SELECT.
	 */
	Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
						XAE_EXT_RXVLAN_STRP_OPTION);
	Status |= XAxiEthernet_SetVStripMode(AxiEthernetInstancePtr,
						XAE_VSTRP_SELECT, XAE_RX);

	/*
	 * RX VLAN strips based on RxStrpVid and enable stripping.
	 */
	Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, RxStrpVid,
						RxStrpVid, 1, 0, XAE_RX);

	/*
	 * RX VLAN translation from RxVid to RxTransVid only.
	 */
	Status |= XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
						XAE_EXT_RXVLAN_TRAN_OPTION);
	Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, RxVid,
						RxTransVid, 0, 0, XAE_RX);

	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting RX VLAN");
		return XST_FAILURE;
	}

	/* Configure VLAN TPIDs for HW to recognize. */
	Status  = XAxiEthernet_SetTpid(AxiEthernetInstancePtr, Tpid1, 0);
	Status |= XAxiEthernet_SetTpid(AxiEthernetInstancePtr, Tpid2, 1);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting TPIDs");
		return XST_FAILURE;
	}

	/*
	 * Flush the TX frame before giving it to DMA TX channel to transmit.
	 */
	Xil_DCacheFlushRange((u32)&TxFrame, TxFrameLength);

	/*
	 * Clear out receive packet memory area
	 */
	AxiEthernetUtilFrameMemClear(&RxFrame);

	/*
	 * Invalidate the RX frame before giving it to DMA RX channel to
	 * receive data.
 	 */
	Xil_DCacheInvalidateRange((u32)&RxFrame, TxFrameLength + 4);

	/*
	 * Interrupt coalescing parameters are set to their default settings
	 * which is to interrupt the processor after every frame has been
	 * processed by the DMA engine.
	 */

	Status = XAxiDma_BdRingSetCoalesce(TxRingPtr, 1, 1);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting coalescing for transmit");
		return XST_FAILURE;
	}

	Status = XAxiDma_BdRingSetCoalesce(RxRingPtr, 1, 1);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting coalescing for recv");
		return XST_FAILURE;
	}

	/*
	 * Make sure Tx and Rx are enabled
	 */
	Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
					XAE_RECEIVER_ENABLE_OPTION |
					XAE_TRANSMITTER_ENABLE_OPTION );
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting options");
		return XST_FAILURE;
	}

	Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr,
					XAE_JUMBO_OPTION);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error setting options");
		return XST_FAILURE;
	}

	/*
	 * Start the AxiEthernet and enable its ERROR interrupts
	 */
	XAxiEthernet_Start(AxiEthernetInstancePtr);
	XAxiEthernet_IntEnable(&AxiEthernetInstance,
					XAE_INT_RECV_ERROR_MASK);

	/*
	 * Enable DMA receive related interrupts
	 */
	XAxiDma_BdRingIntEnable(RxRingPtr, XAXIDMA_IRQ_ALL_MASK);

	/*
	 * Allocate 1 RxBD.
	 */
	Status = XAxiDma_BdRingAlloc(RxRingPtr, 1, &BdPtr);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error allocating RxBD");
		return XST_FAILURE;
	}

	/*
	 * Setup the BD.
	 */
	XAxiDma_BdSetBufAddr(BdPtr, (u32)&RxFrame);
#ifndef XPAR_AXIDMA_0_ENABLE_MULTI_CHANNEL
	XAxiDma_BdSetLength(BdPtr, sizeof(RxFrame));
#else
	XAxiDma_BdSetLength(BdPtr, sizeof(RxFrame),
				RxRingPtr->MaxTransferLen);
#endif
	XAxiDma_BdSetCtrl(BdPtr, 0);

	/*
	 * Enqueue to HW
	 */
	Status = XAxiDma_BdRingToHw(RxRingPtr, 1, BdPtr);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error committing RxBD to HW");
		return XST_FAILURE;
	}

	/*
	 * Start DMA RX channel. Now it's ready to receive data.
	 */
	Status = XAxiDma_BdRingStart(RxRingPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Enable DMA transmit related interrupts
	 */
	XAxiDma_BdRingIntEnable(TxRingPtr, XAXIDMA_IRQ_ALL_MASK);

	/*
	 * Allocate 1 TxBD
	 */
	Status = XAxiDma_BdRingAlloc(TxRingPtr, 1, &BdPtr);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error allocating TxBD");
		return XST_FAILURE;
	}

	/*
	 * Setup the TxBD
	 */
	XAxiDma_BdSetBufAddr(BdPtr, (u32)&TxFrame);
#ifndef XPAR_AXIDMA_0_ENABLE_MULTI_CHANNEL
	XAxiDma_BdSetLength(BdPtr, TxFrameLength);
#else
	XAxiDma_BdSetLength(BdPtr, TxFrameLength,
				TxRingPtr->MaxTransferLen);
#endif
	XAxiDma_BdSetCtrl(BdPtr, XAXIDMA_BD_CTRL_TXSOF_MASK |
						XAXIDMA_BD_CTRL_TXEOF_MASK);

	/*
	 * Enqueue to HW
	 */
	Status = XAxiDma_BdRingToHw(TxRingPtr, 1, BdPtr);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error committing TxBD to HW");
		return XST_FAILURE;
	}

	/*
	 * Start DMA TX channel. Transmission starts at once.
	 */
	Status = XAxiDma_BdRingStart(TxRingPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait for transmission to complete
	 */
	while (!FramesTx);

	/*
	 * Now that the frame has been sent, post process our TxBDs.
	 * Since we have only submitted 2 to HW, then there should be only 2
	 * ready for post processing.
	 */
	if (XAxiDma_BdRingFromHw(TxRingPtr, 1, &BdPtr) == 0) {
		AxiEthernetUtilErrorTrap("TxBDs were not ready for post processing");
		return XST_FAILURE;
	}

	/*
	 * Examine the TxBDs.
	 *
	 * There isn't much to do. The only thing to check would be DMA
	 * exception bits. But this would also be caught in the error handler.
	 * So we just return these BDs to the free list
	 */
	Status = XAxiDma_BdRingFree(TxRingPtr, 1, BdPtr);
	if (Status != XST_SUCCESS) {
		AxiEthernetUtilErrorTrap("Error freeing up TxBDs");
		return XST_FAILURE;
	}

	/*
	 * Wait for Rx indication
	 */
	while (!FramesRx);
	/*
	 * Now that the frame has been received, post process our RxBD.
	 * Since we have only submitted 1 to HW, then there should be only 1
	 * ready for post processing.
	 */
	if (XAxiDma_BdRingFromHw(RxRingPtr, 1, &BdPtr) == 0) {
		AxiEthernetUtilErrorTrap("RxBD was not ready for post processing");
		return XST_FAILURE;
	}

	BdCurPtr = BdPtr;
	BdSts = XAxiDma_BdGetSts(BdCurPtr);

	if ((BdSts & XAXIDMA_BD_STS_ALL_ERR_MASK) ||
		(!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK))) {
			AxiEthernetUtilErrorTrap("Rx Error");
			return XST_FAILURE;
	}
	else {

		RxFrameLength =
		(XAxiDma_BdRead(BdCurPtr,XAXIDMA_BD_USR4_OFFSET)) & 0x0000FFFF;
	}

	/* Expected RX TPID+CFI+VID !!! */
	VTagCfiVid = (((u32)Tpid2 << 16) | ((u32)Cfi2 << 12) | RxStrpVid);

	/* Check on the VLAN CFI and VID */
	RxStatusControlWord = XAxiDma_BdGetAppWord(BdPtr,
						BD_VLAN_VID_OFFSET, &Valid);
	if(Valid) {
		RxCfiVid = RxStatusControlWord >> 16;
		RxCfiVid = Xil_Ntohs(RxCfiVid);
		if(RxCfiVid != (VTagCfiVid & 0x0000FFFF)) {
			AxiEthernetUtilErrorTrap("VLAN CFI and VID mismatch\n");
			return XST_FAILURE;
		}
	}
	else {