/** * This function resets the device but preserves the options set by the user. * * The descriptor list could be reinitialized with the same calls to * XLlTemac_SgSetSpace() as used in main(). Doing this is a matter of preference. * In many cases, an OS may have resources tied up in the descriptors. * Reinitializing in this case may bad for the OS since its resources may be * permamently lost. * * @param TemacInstancePtr is a pointer to the instance of the Temac * component. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * ******************************************************************************/ static int TemacResetDevice(XLlTemac * TemacInstancePtr, XLlDma * DmaInstancePtr) { int Status; u8 MacSave[6]; u32 Options; //u32 RxThreshold = 1; //u32 TxThreshold = 1; //u32 RxWaitbound = 0; //u32 TxWaitbound = 0; //XLlDma_BdRing * RxRingPtr = &XLlDma_GetRxRing(DmaInstancePtr); //XLlDma_BdRing * TxRingPtr = &XLlDma_GetTxRing(DmaInstancePtr); /* * Stop LLTEMAC device */ XLlTemac_Stop(TemacInstancePtr); /* * Save the device state */ XLlTemac_GetMacAddress(TemacInstancePtr, MacSave); Options = XLlTemac_GetOptions(TemacInstancePtr); /* * Stop and reset the device */ XLlTemac_Reset(TemacInstancePtr, XTE_NORESET_HARD); /* * Restore the state */ Status = XLlTemac_SetMacAddress(TemacInstancePtr, MacSave); Status |= XLlTemac_SetOptions(TemacInstancePtr, Options); Status |= XLlTemac_ClearOptions(TemacInstancePtr, ~Options); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error restoring state after reset"); return XST_FAILURE; } /* * Restart the device */ XLlTemac_Start(TemacInstancePtr); return XST_SUCCESS; }
/** * This function resets the device but preserves the options set by the user. * * @param None. * * @return XST_SUCCESS if successful, else XST_FAILURE. * * @note None. * ******************************************************************************/ int TemacResetDevice(void) { int Status; u8 MacSave[6]; u32 Options; /* * Stop device */ XLlTemac_Stop(&TemacInstance); /* * Save the device state */ XLlTemac_GetMacAddress(&TemacInstance, MacSave); Options = XLlTemac_GetOptions(&TemacInstance); /* * Stop and reset both the fifo and the temac the devices */ XLlFifo_Reset(&FifoInstance); XLlTemac_Reset(&TemacInstance, XTE_NORESET_HARD); /* * Restore the state */ Status = XLlTemac_SetMacAddress(&TemacInstance, MacSave); Status |= XLlTemac_SetOptions(&TemacInstance, Options); Status |= XLlTemac_ClearOptions(&TemacInstance, ~Options); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error restoring state after reset"); return XST_FAILURE; } return XST_SUCCESS; }
void init_lltemac(xlltemacif_s *xlltemacif, struct netif *netif) { int rdy; unsigned mac_address = (unsigned)(netif->state); unsigned link_speed = 1000; unsigned options; unsigned lock_message_printed = 0; /* obtain config of this emac */ XLlTemac_Config *mac_config = lookup_config(mac_address); XLlTemac *xlltemacp = &xlltemacif->lltemac; XLlTemac_CfgInitialize(xlltemacp, mac_config, mac_config->BaseAddress); options = XLlTemac_GetOptions(xlltemacp); options |= XTE_FLOW_CONTROL_OPTION; options |= XTE_JUMBO_OPTION; options |= XTE_TRANSMITTER_ENABLE_OPTION; options |= XTE_RECEIVER_ENABLE_OPTION; options |= XTE_FCS_STRIP_OPTION; options |= XTE_MULTICAST_OPTION; XLlTemac_SetOptions(xlltemacp, options); XLlTemac_ClearOptions(xlltemacp, ~options); /* set mac address */ XLlTemac_SetMacAddress(xlltemacp, (Xuint8*)(netif->hwaddr)); /* make sure the hard TEMAC is ready */ rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress, XTE_RDY_OFFSET); while ((rdy & XTE_RDY_HARD_ACS_RDY_MASK) == 0) { rdy = XLlTemac_ReadReg(xlltemacp->Config.BaseAddress, XTE_RDY_OFFSET); } link_speed = Phy_Setup(xlltemacp); XLlTemac_SetOperatingSpeed(xlltemacp, link_speed); /* Setting the operating speed of the MAC needs a delay. */ { volatile int wait; for (wait=0; wait < 100000; wait++); for (wait=0; wait < 100000; wait++); } /* in a soft temac implementation, we need to explicitly make sure that * the RX DCM has been locked. See xps_ll_temac manual for details. * This bit is guaranteed to be 1 for hard temac's */ lock_message_printed = 0; while (!(XLlTemac_ReadReg(xlltemacp->Config.BaseAddress, XTE_IS_OFFSET) & XTE_INT_RXDCM_LOCK_MASK)) { int first = 1; if (first) { print("Waiting for RX DCM to lock.."); first = 0; lock_message_printed = 1; } } if (lock_message_printed) print("RX DCM locked.\r\n"); /* start the temac */ XLlTemac_Start(xlltemacp); /* enable TEMAC interrupts */ XLlTemac_IntEnable(xlltemacp, XTE_INT_RECV_ERROR_MASK); }
/** * * This example sends frames with the interrupt coalescing settings altered * from their defaults. * * The default settings will interrupt the processor after every frame has been * sent. This example will increase the threshold resulting in lower CPU * utilization since it spends less time servicing interrupts. * * @param TemacInstancePtr is a pointer to the instance of the Temac * component. * * @return XST_SUCCESS to indicate success, otherwise XST_FAILURE. * * @note None. * ******************************************************************************/ int TemacSgDmaIntrCoalescingExample(XLlTemac * TemacInstancePtr, XLlDma * DmaInstancePtr) { int Status; u32 TxFrameLength; int TxFramesToSend = 1000; int TxFramesSent = 0; int PayloadSize = XTE_MTU; u32 Index; u32 NumBd; u16 Threshold = 64; XLlDma_BdRing *RxRingPtr = &XLlDma_mGetRxRing(DmaInstancePtr); XLlDma_BdRing *TxRingPtr = &XLlDma_mGetTxRing(DmaInstancePtr); XLlDma_Bd *BdPtr, *BdCurPtr; /* * Clear variables shared with callbacks */ FramesRx = 0; FramesTx = 0; DeviceErrors = 0; /* * Calculate the frame length (not including FCS) */ TxFrameLength = XTE_HDR_SIZE + PayloadSize; /* * Setup packet to be transmitted. The same packet will be transmitted * over and over */ TemacUtilFrameHdrFormatMAC(&TxFrame, TemacMAC); TemacUtilFrameHdrFormatType(&TxFrame, PayloadSize); TemacUtilFrameSetPayloadData(&TxFrame, PayloadSize); /* * Flush the TX frame before giving it to DMA TX channel to transmit, * in case D-Caching is turned on. */ XCACHE_FLUSH_DCACHE_RANGE(&TxFrame, TxFrameLength); /* * We don't care about the receive channel for this example, so turn it off */ Status = XLlTemac_ClearOptions(TemacInstancePtr, XTE_RECEIVER_ENABLE_OPTION); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error clearing option"); return XST_FAILURE; } /* * Set the interrupt coalescing parameters for the test. The waitbound timer * is set to 1 (ms) to catch the last few frames. * * If you set variable Threshold to some value larger than TXBD_CNT, then * there can never be enough frames sent to meet the threshold. In this case * the waitbound timer will always cause the interrupt to occur. */ Status = XLlDma_BdRingSetCoalesce(TxRingPtr, Threshold, 1); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error setting coalescing settings"); return XST_FAILURE; } /* * Prime the engine, allocate all BDs and assign them to the same buffer */ Status = XLlDma_BdRingAlloc(TxRingPtr, TXBD_CNT, &BdPtr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error allocating TxBDs prior to starting"); return XST_FAILURE; } /* * Setup the TxBDs */ BdCurPtr = BdPtr; for (Index = 0; Index < TXBD_CNT; Index++) { XLlDma_mBdSetBufAddr(BdCurPtr, &TxFrame); XLlDma_mBdSetLength(BdCurPtr, TxFrameLength); XLlDma_mBdSetStsCtrl(BdCurPtr, XLLDMA_BD_STSCTRL_SOP_MASK | XLLDMA_BD_STSCTRL_EOP_MASK); BdCurPtr = XLlDma_mBdRingNext(TxRingPtr, BdCurPtr); } /* * Enqueue all TxBDs to HW */ Status = XLlDma_BdRingToHw(TxRingPtr, TXBD_CNT, BdPtr); TxFramesSent += TXBD_CNT; if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error committing TxBDs prior to starting"); return XST_FAILURE; } /* * Enable the send interrupts. Nothing should be transmitted yet as the * device has not been started */ XLlDma_mBdRingIntEnable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); /* Enable temac interrupts to capture errors */ XLlTemac_IntEnable(TemacInstancePtr, XTE_INT_RECV_ERROR_MASK); /* * Start the device. Transmission commences now! */ XLlTemac_Start(TemacInstancePtr); /* * As DMA TX channel has been started in * TemacSgDmaIntrSingleFrameExample() above, there is no need to start * it again here */ while (TxFramesSent < TxFramesToSend) { /* * Wait for the interrupt */ while (!FramesTx); /* * Some TxBDs are ready for post processing. Get all that are available * at the moment, free them, then allocate the same number and * re-enqueue back to HW. At the same time this all occurs here, * the DMA engine should be processing other TxBDs. If we can stay ahead * of the transmitter like this, then throughput should be at or near * line-rate. * * Note that this retrieves up to TXBD_CNT outstanding packets, * so we may be processing more packets here than the threshold * value, which may result in a seemingly spurious interrupt * next time if we grab twice (or more) of the threshold value * this time around (clear as mud, eh!). Bottom line is that we * ignore if NumBd returns as zero. */ NumBd = XLlDma_BdRingFromHw(TxRingPtr, TXBD_CNT, &BdPtr); if (NumBd > 0) { TxFramesSent += NumBd; /* * Don't bother to check the BDs status, just free them */ Status = XLlDma_BdRingFree(TxRingPtr, NumBd, BdPtr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error freeing TxBDs"); } /* * Allocate the same number of BDs just freed */ Status = XLlDma_BdRingAlloc(TxRingPtr, NumBd, &BdPtr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error allocating TxBDs"); return XST_FAILURE; } /* * Setup the TxBDs */ BdCurPtr = BdPtr; for (Index = 0; Index < NumBd; Index++) { XLlDma_mBdSetBufAddr(BdCurPtr, &TxFrame); XLlDma_mBdSetLength(BdCurPtr, TxFrameLength); XLlDma_mBdSetStsCtrl(BdCurPtr, XLLDMA_BD_STSCTRL_SOP_MASK | XLLDMA_BD_STSCTRL_EOP_MASK); BdCurPtr = XLlDma_mBdRingNext(TxRingPtr, BdCurPtr); } /* * Enqueue TxBDs to HW */ Status = XLlDma_BdRingToHw(TxRingPtr, NumBd, BdPtr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap ("Error committing TxBDs prior to starting"); return XST_FAILURE; } } /* * Re-enable the interrupts */ FramesTx = 0; XLlDma_mBdRingIntEnable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK); } /* * Wait a second and collect any remaining frames that had been * queued up but not post processed */ #ifndef __MICROBLAZE__ usleep(1000000); #else /* * Not sure if we should depend on there being a timer core in a * microblaze system */ TemacUtilPhyDelay(1); #endif NumBd = XLlDma_BdRingFromHw(TxRingPtr, 0xFFFFFFFF, &BdPtr); if (NumBd > 0) { Status = XLlDma_BdRingFree(TxRingPtr, NumBd, BdPtr); if (Status != XST_SUCCESS) { TemacUtilErrorTrap("Error freeing TxBDs"); } } /* * Done sending frames. Stop the device */ XLlTemac_Stop(TemacInstancePtr); return XST_SUCCESS; }