/** * 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; }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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 {