Ejemplo n.º 1
0
void restart_emacps_transmitter (xemacpsif_s *xemacps) {
	u32 Reg;
	Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
					XEMACPS_NWCTRL_OFFSET);
	Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
	XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
										XEMACPS_NWCTRL_OFFSET, Reg);

	Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
						XEMACPS_NWCTRL_OFFSET);
	Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
	XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
										XEMACPS_NWCTRL_OFFSET, Reg);
}
Ejemplo n.º 2
0
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
{
	u32_t regctrl;
	u32_t tempcntr;

	tempcntr = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET);
	if ((!tempcntr) && (!(xemacpsif->last_rx_frms_cntr))) {
		regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
				XEMACPS_NWCTRL_OFFSET);
		regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
				XEMACPS_NWCTRL_OFFSET, regctrl);
		regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
		regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
	}
	xemacpsif->last_rx_frms_cntr = tempcntr;
}
Ejemplo n.º 3
0
void HandleTxErrors(xemacpsif_s *xemacpsif)
{
	u32 netctrlreg;

	//taskENTER_CRITICAL()
	{
		netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
													XEMACPS_NWCTRL_OFFSET);
		netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
										XEMACPS_NWCTRL_OFFSET, netctrlreg);

		clean_dma_txdescs( xemacpsif );
		netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
														XEMACPS_NWCTRL_OFFSET);
		netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
		XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
											XEMACPS_NWCTRL_OFFSET, netctrlreg);
	}
	//taskEXIT_CRITICAL( );
}
Ejemplo n.º 4
0
void emacps_send_handler(void *arg)
{
	struct xemac_s *xemac;
	xemacpsif_s   *xemacpsif;
	XEmacPs_BdRing *txringptr;
	u32_t regval;
#ifdef OS_IS_FREERTOS
	xInsideISR++;
#endif
	xemac = (struct xemac_s *)(arg);
	xemacpsif = (xemacpsif_s *)(xemac->state);
	txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
	regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET);
	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval);

	/* If Transmit done interrupt is asserted, process completed BD's */
	process_sent_bds(txringptr);
#ifdef OS_IS_FREERTOS
	xInsideISR--;
#endif
}
Ejemplo n.º 5
0
/**
* Gracefully stop the Ethernet MAC as follows:
*   - Disable all interrupts from this device
*   - Stop DMA channels
*   - Disable the tansmitter and receiver
*
* Device options currently in effect are not changed.
*
* This function will disable all interrupts. Default interrupts settings that
* had been enabled will be restored when XEmacPs_Start() is called.
*
* @param InstancePtr is a pointer to the instance to be worked on.
*
* @note
* This function makes use of internal resources that are shared between the
* Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
* setting device options while another is trying to start the device, the user
* is required to provide protection of this shared data (typically using a
* semaphore).
*
* Stopping the DMA channels causes this function to block until the DMA
* operation is complete.
*
******************************************************************************/
void XEmacPs_Stop(XEmacPs *InstancePtr)
{
	u32 Reg;

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* Disable all interrupts */
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
			   XEMACPS_IXR_ALL_MASK);

	/* Disable the receiver & transmitter */
	Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
				XEMACPS_NWCTRL_OFFSET);
	Reg &= ~XEMACPS_NWCTRL_RXEN_MASK;
	Reg &= ~XEMACPS_NWCTRL_TXEN_MASK;
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_NWCTRL_OFFSET, Reg);

	/* Mark as stopped */
	InstancePtr->IsStarted = 0;
}
Ejemplo n.º 6
0
/**
* This function perform the reset sequence to the given emacps interface by 
* configuring the appropriate control bits in the emacps specifc registers.
* the emacps reset squence involves the following steps
*	Disable all the interuupts 
*	Clear the status registers
*	Disable Rx and Tx engines
*	Update the Tx and Rx descriptor queue registers with reset values
*	Update the other relevant control registers with reset value
*
* @param   BaseAddress of the interface
*
* @return N/A
*
* @note 
* This function will not modify the slcr registers that are relavant for 
* emacps controller
******************************************************************************/
void XEmacPs_ResetHw(u32 BaseAddr)
{
	u32 RegVal;

	/* Disable the interrupts  */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_IDR_OFFSET,0x0U);

	/* Stop transmission,disable loopback and Stop tx and Rx engines */
	RegVal = XEmacPs_ReadReg(BaseAddr,XEMACPS_NWCTRL_OFFSET);
	RegVal &= ~((u32)XEMACPS_NWCTRL_TXEN_MASK|
				(u32)XEMACPS_NWCTRL_RXEN_MASK|
				(u32)XEMACPS_NWCTRL_HALTTX_MASK|
				(u32)XEMACPS_NWCTRL_LOOPEN_MASK);
	/* Clear the statistic registers, flush the packets in DPRAM*/
	RegVal |= (XEMACPS_NWCTRL_STATCLR_MASK|
				XEMACPS_NWCTRL_FLUSH_DPRAM_MASK);
	XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCTRL_OFFSET,RegVal);
	/* Clear the interrupt status */					
	XEmacPs_WriteReg(BaseAddr,XEMACPS_ISR_OFFSET,XEMACPS_IXR_ALL_MASK);
	/* Clear the tx status */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_TXSR_OFFSET,(XEMACPS_TXSR_ERROR_MASK|
									(u32)XEMACPS_TXSR_TXCOMPL_MASK|
									(u32)XEMACPS_TXSR_TXGO_MASK));
	/* Clear the rx status */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_RXSR_OFFSET,
								XEMACPS_RXSR_FRAMERX_MASK);
	/* Clear the tx base address */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_TXQBASE_OFFSET,0x0U);
	/* Clear the rx base address */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_RXQBASE_OFFSET,0x0U);
	/* Update the network config register with reset value */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_NWCFG_OFFSET,XEMACPS_NWCFG_RESET_MASK);
	/* Update the hash address registers with reset value */
	XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHL_OFFSET,0x0U);
	XEmacPs_WriteReg(BaseAddr,XEMACPS_HASHH_OFFSET,0x0U);
}
Ejemplo n.º 7
0
/**
* Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
* transmitter, and the receiver.
*
* Steps to reset
* - Stops transmit and receive channels
* - Stops DMA
* - Configure transmit and receive buffer size to default
* - Clear transmit and receive status register and counters
* - Clear all interrupt sources
* - Clear phy (if there is any previously detected) address
* - Clear MAC addresses (1-4) as well as Type IDs and hash value
*
* All options are placed in their default state. Any frames in the
* descriptor lists will remain in the lists. The side effect of doing
* this is that after a reset and following a restart of the device, frames
* were in the list before the reset may be transmitted or received.
*
* The upper layer software is responsible for re-configuring (if necessary)
* and restarting the MAC after the reset. Note also that driver statistics
* are not cleared on reset. It is up to the upper layer software to clear the
* statistics if needed.
*
* When a reset is required, the driver notifies the upper layer software of
* this need through the ErrorHandler callback and specific status codes.
* The upper layer software is responsible for calling this Reset function
* and then re-configuring the device.
*
* @param InstancePtr is a pointer to the instance to be worked on.
*
******************************************************************************/
void XEmacPs_Reset(XEmacPs *InstancePtr)
{
	u32 Reg;
	u8 i;
	char EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* Stop the device and reset hardware */
	XEmacPs_Stop(InstancePtr);
	InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;

	/* Setup hardware with default values */
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			XEMACPS_NWCTRL_OFFSET,
			(XEMACPS_NWCTRL_STATCLR_MASK |
			XEMACPS_NWCTRL_MDEN_MASK) &
			~XEMACPS_NWCTRL_LOOPEN_MASK);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
					XEMACPS_NWCFG_OFFSET,
					XEMACPS_NWCFG_100_MASK |
					XEMACPS_NWCFG_FDEN_MASK |
					XEMACPS_NWCFG_UCASTHASHEN_MASK);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			XEMACPS_DMACR_OFFSET,
			((((XEMACPS_RX_BUF_SIZE / XEMACPS_RX_BUF_UNIT) +
				((XEMACPS_RX_BUF_SIZE %
				XEMACPS_RX_BUF_UNIT) ? 1 : 0)) <<
				XEMACPS_DMACR_RXBUF_SHIFT) &
				XEMACPS_DMACR_RXBUF_MASK) |
				XEMACPS_DMACR_RXSIZE_MASK |
				XEMACPS_DMACR_TXSIZE_MASK);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_TXSR_OFFSET, 0x0);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_RXQBASE_OFFSET, 0x0);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_TXQBASE_OFFSET, 0x0);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_RXSR_OFFSET, 0x0);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
			   XEMACPS_IXR_ALL_MASK);

	Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
				XEMACPS_ISR_OFFSET);
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
			   Reg);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_PHYMNTNC_OFFSET, 0x0);

	XEmacPs_ClearHash(InstancePtr);

	for (i = 1; i < 5; i++) {
		XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
		XEmacPs_SetTypeIdCheck(InstancePtr, 0x0, i);
	}

	/* clear all counters */
	for (i = 0; i < (XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4;
	     i++) {
		XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
                                   XEMACPS_OCTTXL_OFFSET + i * 4);
	}

	/* Disable the receiver */
	Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
				XEMACPS_NWCTRL_OFFSET);
	Reg &= ~XEMACPS_NWCTRL_RXEN_MASK;
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_NWCTRL_OFFSET, Reg);

	/* Sync default options with hardware but leave receiver and
         * transmitter disabled. They get enabled with XEmacPs_Start() if
	 * XEMACPS_TRANSMITTER_ENABLE_OPTION and
         * XEMACPS_RECEIVER_ENABLE_OPTION are set.
	 */
	XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
			    ~(XEMACPS_TRANSMITTER_ENABLE_OPTION |
			      XEMACPS_RECEIVER_ENABLE_OPTION));

	XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
}
Ejemplo n.º 8
0
/**
* Start the Ethernet controller as follows:
*   - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
*   - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
*   - Start the SG DMA send and receive channels and enable the device
*     interrupt
*
* @param InstancePtr is a pointer to the instance to be worked on.
*
* @return N/A
*
* @note
* Hardware is configured with scatter-gather DMA, the driver expects to start
* the scatter-gather channels and expects that the user has previously set up
* the buffer descriptor lists.
*
* This function makes use of internal resources that are shared between the
* Start, Stop, and Set/ClearOptions functions. So if one task might be setting
* device options while another is trying to start the device, the user is
* required to provide protection of this shared data (typically using a
* semaphore).
*
* This function must not be preempted by an interrupt that may service the
* device.
*
******************************************************************************/
void XEmacPs_Start(XEmacPs *InstancePtr)
{
	u32 Reg;

	/* Assert bad arguments and conditions */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
	Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);

        /* If already started, then there is nothing to do */
        if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
                return;
        }

	/* Start DMA */
	/* When starting the DMA channels, both transmit and receive sides
	 * need an initialized BD list.
	 */
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_RXQBASE_OFFSET,
			   InstancePtr->RxBdRing.BaseBdAddr);

	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XEMACPS_TXQBASE_OFFSET,
			   InstancePtr->TxBdRing.BaseBdAddr);

	/* clear any existed int status */
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
			   XEMACPS_IXR_ALL_MASK);

	/* Enable transmitter if not already enabled */
	if (InstancePtr->Options & XEMACPS_TRANSMITTER_ENABLE_OPTION) {
		Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
					XEMACPS_NWCTRL_OFFSET);
		if (!(Reg & XEMACPS_NWCTRL_TXEN_MASK)) {
			XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
					   XEMACPS_NWCTRL_OFFSET,
					   Reg | XEMACPS_NWCTRL_TXEN_MASK);
		}
	}

	/* Enable receiver if not already enabled */
	if (InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) {
		Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
					XEMACPS_NWCTRL_OFFSET);
		if (!(Reg & XEMACPS_NWCTRL_RXEN_MASK)) {
			XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
					   XEMACPS_NWCTRL_OFFSET,
					   Reg | XEMACPS_NWCTRL_RXEN_MASK);
		}
	}

        /* Enable TX and RX interrupts */
        XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
		XEMACPS_IXR_RX_ERR_MASK | XEMACPS_IXR_FRAMERX_MASK |
		XEMACPS_IXR_TXCOMPL_MASK));

	/* Mark as started */
	InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;

	return;
}
Ejemplo n.º 9
0
/**
* Master interrupt handler for EMAC driver. This routine will query the
* status of the device, bump statistics, and invoke user callbacks.
*
* This routine must be connected to an interrupt controller using OS/BSP
* specific methods.
*
* @param XEmacPsPtr is a pointer to the XEMACPS instance that has caused the
*        interrupt.
*
******************************************************************************/
void XEmacPs_IntrHandler(void *XEmacPsPtr)
{
	u32 RegISR;
	u32 RegSR;
	u32 RegCtrl;
	u32 RegQ1ISR = 0U;
	XEmacPs *InstancePtr = (XEmacPs *) XEmacPsPtr;

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);

	/* This ISR will try to handle as many interrupts as it can in a single
	 * call. However, in most of the places where the user's error handler
         * is called, this ISR exits because it is expected that the user will
         * reset the device in nearly all instances.
	 */
	RegISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_ISR_OFFSET);

	/* Read Transmit Q1 ISR */

	if (InstancePtr->Version > 2)
		RegQ1ISR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_INTQ1_STS_OFFSET);

	/* Clear the interrupt status register */
	XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
			   RegISR);

	/* Receive complete interrupt */
	if ((RegISR & XEMACPS_IXR_FRAMERX_MASK) != 0x00000000U) {
		/* Clear RX status register RX complete indication but preserve
		 * error bits if there is any */
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_RXSR_OFFSET,
				   ((u32)XEMACPS_RXSR_FRAMERX_MASK |
				   (u32)XEMACPS_RXSR_BUFFNA_MASK));
		InstancePtr->RecvHandler(InstancePtr->RecvRef);
	}

	/* Transmit Q1 complete interrupt */
	if ((InstancePtr->Version > 2) &&
			((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) {
		/* Clear TX status register TX complete indication but preserve
		 * error bits if there is any */
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_INTQ1_STS_OFFSET,
				   XEMACPS_INTQ1SR_TXCOMPL_MASK);
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_TXSR_OFFSET,
				   ((u32)XEMACPS_TXSR_TXCOMPL_MASK |
				   (u32)XEMACPS_TXSR_USEDREAD_MASK));
		InstancePtr->SendHandler(InstancePtr->SendRef);
	}

	/* Transmit complete interrupt */
	if ((RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U) {
		/* Clear TX status register TX complete indication but preserve
		 * error bits if there is any */
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_TXSR_OFFSET,
				   ((u32)XEMACPS_TXSR_TXCOMPL_MASK |
				   (u32)XEMACPS_TXSR_USEDREAD_MASK));
		InstancePtr->SendHandler(InstancePtr->SendRef);
	}

	/* Receive error conditions interrupt */
	if ((RegISR & XEMACPS_IXR_RX_ERR_MASK) != 0x00000000U) {
		/* Clear RX status register */
		RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
					  XEMACPS_RXSR_OFFSET);
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_RXSR_OFFSET, RegSR);

		/* Fix for CR # 692702. Write to bit 18 of net_ctrl
		 * register to flush a packet out of Rx SRAM upon
		 * an error for receive buffer not available. */
		if ((RegISR & XEMACPS_IXR_RXUSED_MASK) != 0x00000000U) {
			RegCtrl =
			XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
						XEMACPS_NWCTRL_OFFSET);
			RegCtrl |= (u32)XEMACPS_NWCTRL_FLUSH_DPRAM_MASK;
			XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
					XEMACPS_NWCTRL_OFFSET, RegCtrl);
		}
		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_RECV,
					  RegSR);
	}

        /* When XEMACPS_IXR_TXCOMPL_MASK is flaged, XEMACPS_IXR_TXUSED_MASK
         * will be asserted the same time.
         * Have to distinguish this bit to handle the real error condition.
         */
	/* Transmit Q1 error conditions interrupt */
        if ((InstancePtr->Version > 2) &&
			((RegQ1ISR & XEMACPS_INTQ1SR_TXERR_MASK) != 0x00000000U) &&
            ((RegQ1ISR & XEMACPS_INTQ1SR_TXCOMPL_MASK) != 0x00000000U)) {
			/* Clear Interrupt Q1 status register */
			XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_INTQ1_STS_OFFSET, RegQ1ISR);
			InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND,
					  RegQ1ISR);
	   }

	/* Transmit error conditions interrupt */
        if (((RegISR & XEMACPS_IXR_TX_ERR_MASK) != 0x00000000U) &&
            (!(RegISR & XEMACPS_IXR_TXCOMPL_MASK) != 0x00000000U)) {
		/* Clear TX status register */
		RegSR = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
					  XEMACPS_TXSR_OFFSET);
		XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
				   XEMACPS_TXSR_OFFSET, RegSR);
		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XEMACPS_SEND,
					  RegSR);
	}

}
Ejemplo n.º 10
0
void emacps_recv_handler(void *arg)
{
	struct pbuf *p;
	XEmacPs_Bd *rxbdset, *curbdptr;
	struct xemac_s *xemac;
	xemacpsif_s *xemacpsif;
	XEmacPs_BdRing *rxring;
	volatile s32_t bd_processed;
	s32_t rx_bytes, k;
	u32_t bdindex;
	u32_t regval;

	xemac = (struct xemac_s *)(arg);
	xemacpsif = (xemacpsif_s *)(xemac->state);
	rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);

#ifdef OS_IS_FREERTOS
	xInsideISR++;
#endif
	/*
	 * If Reception done interrupt is asserted, call RX call back function
	 * to handle the processed BDs and then raise the according flag.
	 */
	regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET);
	XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval);

	resetrx_on_no_rxdata(xemacpsif);

	while(1) {

		bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset);
		if (bd_processed <= 0) {
			break;
		}

		for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) {

			bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr);
			p = (struct pbuf *)rx_pbufs_storage[bdindex];

			/*
			 * Adjust the buffer size to the actual number of bytes received.
			 */
			rx_bytes = XEmacPs_BdGetLength(curbdptr);
			pbuf_realloc(p, rx_bytes);

			/* store it in the receive queue,
			 * where it'll be processed by a different handler
			 */
			if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) {
#if LINK_STATS
				lwip_stats.link.memerr++;
				lwip_stats.link.drop++;
#endif
				pbuf_free(p);
			} else {
#if !NO_SYS
				sys_sem_signal(&xemac->sem_rx_data_available);
#endif
			}
			curbdptr = XEmacPs_BdRingNext( rxring, curbdptr);
		}
		/* free up the BD's */
		XEmacPs_BdRingFree(rxring, bd_processed, rxbdset);
		setup_rx_bds(rxring);
	}

#ifdef OS_IS_FREERTOS
	xInsideISR--;
#endif
	return;
}
Ejemplo n.º 11
0
XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
{
	struct pbuf *q;
	s32_t n_pbufs;
	XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
	XEmacPs_Bd *temp_txbd;
	XStatus status;
	XEmacPs_BdRing *txring;
	u32_t bdindex;
	u32_t lev;

	lev = mfcpsr();
	mtcpsr(lev | 0x000000C0);

	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));

	/* first count the number of pbufs */
	for (q = p, n_pbufs = 0; q != NULL; q = q->next)
		n_pbufs++;

	/* obtain as many BD's */
	status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
	if (status != XST_SUCCESS) {
		mtcpsr(lev);
		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
		return XST_FAILURE;
	}

	for(q = p, txbd = txbdset; q != NULL; q = q->next) {
		bdindex = XEMACPS_BD_TO_INDEX(txring, txbd);
		if (tx_pbufs_storage[bdindex] != 0) {
			mtcpsr(lev);
			LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
			return XST_FAILURE;
		}

		/* Send the data from the pbuf to the interface, one pbuf at a
		   time. The size of the data in each pbuf is kept in the ->len
		   variable. */
		Xil_DCacheFlushRange((u32_t)q->payload, (u32_t)q->len);

		XEmacPs_BdSetAddressTx(txbd, (u32)q->payload);
		if (q->len > (XEMACPS_MAX_FRAME_SIZE - 18))
			XEmacPs_BdSetLength(txbd, (XEMACPS_MAX_FRAME_SIZE - 18) & 0x3FFF);
		else
			XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);

		tx_pbufs_storage[bdindex] = (s32_t)q;

		pbuf_ref(q);
		last_txbd = txbd;
		XEmacPs_BdClearLast(txbd);
		txbd = XEmacPs_BdRingNext(txring, txbd);
	}
	XEmacPs_BdSetLast(last_txbd);
	/* For fragmented packets, remember the 1st BD allocated for the 1st
	   packet fragment. The used bit for this BD should be cleared at the end
	   after clearing out used bits for other fragments. For packets without
	   just remember the allocated BD. */
	temp_txbd = txbdset;
	txbd = txbdset;
	txbd = XEmacPs_BdRingNext(txring, txbd);
	q = p->next;
	for(; q != NULL; q = q->next) {
		XEmacPs_BdClearTxUsed(txbd);
		txbd = XEmacPs_BdRingNext(txring, txbd);
	}
	XEmacPs_BdClearTxUsed(temp_txbd);

	status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
	if (status != XST_SUCCESS) {
		mtcpsr(lev);
		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
		return XST_FAILURE;
	}
	/* Start transmit */
	XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
	XEMACPS_NWCTRL_OFFSET,
	(XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
	XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));

	mtcpsr(lev);
	return status;
}
Ejemplo n.º 12
0
XStatus emacps_sgsend(xemacpsif_s *xemacpsif, struct pbuf *p)
{
	struct pbuf *q;
	int n_pbufs;
	XEmacPs_Bd *txbdset, *txbd, *last_txbd = NULL;
	XStatus Status;
	XEmacPs_BdRing *txring;
	unsigned int BdIndex;
	unsigned int lev;

	lev = mfcpsr();
	mtcpsr(lev | 0x000000C0);

#ifdef PEEP
    while((XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
    									XEMACPS_TXSR_OFFSET)) & 0x08);
#endif
	txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));

	/* first count the number of pbufs */
	for (q = p, n_pbufs = 0; q != NULL; q = q->next)
		n_pbufs++;

	/* obtain as many BD's */
	Status = XEmacPs_BdRingAlloc(txring, n_pbufs, &txbdset);
	if (Status != XST_SUCCESS) {
		mtcpsr(lev);
		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error allocating TxBD\r\n"));
		return ERR_IF;
	}

	for(q = p, txbd = txbdset; q != NULL; q = q->next) {
		BdIndex = XEMACPS_BD_TO_INDEX(txring, txbd);
		if (tx_pbufs_storage[BdIndex] != 0) {
			mtcpsr(lev);
			LWIP_DEBUGF(NETIF_DEBUG, ("PBUFS not available\r\n"));
			return ERR_IF;
		}

		/* Send the data from the pbuf to the interface, one pbuf at a
		   time. The size of the data in each pbuf is kept in the ->len
		   variable. */
		Xil_DCacheFlushRange((unsigned int)q->payload, (unsigned)q->len);

		XEmacPs_BdSetAddressTx(txbd, (u32)q->payload);
		if (q->len > (XEMACPS_MAX_FRAME_SIZE - 18))
			XEmacPs_BdSetLength(txbd, (XEMACPS_MAX_FRAME_SIZE - 18) & 0x3FFF);
		else
			XEmacPs_BdSetLength(txbd, q->len & 0x3FFF);

		tx_pbufs_storage[BdIndex] = (int)q;

		pbuf_ref(q);
		last_txbd = txbd;
		XEmacPs_BdClearLast(txbd);
		dsb();
 		txbd = XEmacPs_BdRingNext(txring, txbd);
	}
	XEmacPs_BdSetLast(last_txbd);
	dsb();
	for(q = p, txbd = txbdset; q != NULL; q = q->next) {
		XEmacPs_BdClearTxUsed(txbd);
		txbd = XEmacPs_BdRingNext(txring, txbd);
	}
	dsb();

	Status = XEmacPs_BdRingToHw(txring, n_pbufs, txbdset);
	if (Status != XST_SUCCESS) {
		mtcpsr(lev);
		LWIP_DEBUGF(NETIF_DEBUG, ("sgsend: Error submitting TxBD\r\n"));
		return ERR_IF;
	}
	dsb();
	/* Start transmit */
	XEmacPs_WriteReg((xemacpsif->emacps).Config.BaseAddress,
	XEMACPS_NWCTRL_OFFSET,
	(XEmacPs_ReadReg((xemacpsif->emacps).Config.BaseAddress,
	XEMACPS_NWCTRL_OFFSET) | XEMACPS_NWCTRL_STARTTX_MASK));
	dsb();
	mtcpsr(lev);
	return Status;
}
Ejemplo n.º 13
0
XStatus init_dma(xemacpsif_s *xemacpsif)
{
	NetworkBufferDescriptor_t *pxBuffer;

	int iIndex;
	UBaseType_t xRxSize;
	UBaseType_t xTxSize;
	struct xtopology_t *xtopologyp = &xXTopology;

	xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );

	xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );

	/* Also round-up to 4KB */
	xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
	/*
	 * We allocate 65536 bytes for RX BDs which can accommodate a
	 * maximum of 8192 BDs which is much more than any application
	 * will ever need.
	 */
	xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize )  );
	xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );
	xemacpsif->tx_space   = ( unsigned char *   )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );

	/* These variables will be used in XEmacPs_Start (see src/xemacps.c). */
	xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;
	xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;

	/*
	 * Allocate RX descriptors, 1 RxBD at a time.
	 */
	for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )
	{
		pxBuffer = pxDMA_rx_buffers[ iIndex ];
		if( pxBuffer == NULL )
		{
			pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );
			if( pxBuffer == NULL )
			{
				FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );
				return -1;
			}
		}

		xemacpsif->rxSegments[ iIndex ].flags = 0;
		xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;

		pxDMA_rx_buffers[ iIndex ] = pxBuffer;
		/* Make sure this memory is not in cache for now. */
		if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
		{
			Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
				(unsigned)ipTOTAL_ETHERNET_FRAME_SIZE );
		}
	}

	xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;

	memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );

	clean_dma_txdescs( xemacpsif );

	{
		uint32_t value;
		value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );

		// 1xxxx: Attempt to use INCR16 AHB bursts
		value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
		value |= XEMACPS_DMACR_TCPCKSUM_MASK;
#else
#warning Are you sure the EMAC should not calculate outgoing checksums?
		value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;
#endif
		XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );
	}
	{
		uint32_t value;
		value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );

		/* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).
		Now tell the EMAC that received messages should be stored at "address + 2". */
		value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;

#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )
		value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
#else
#warning Are you sure the EMAC should not calculate incoming checksums?
		value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
#endif
		XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );
	}

	/*
	 * Connect the device driver handler that will be called when an
	 * interrupt for the device occurs, the handler defined above performs
	 * the specific interrupt processing for the device.
	 */
	XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
		(Xil_ExceptionHandler)XEmacPs_IntrHandler,
		(void *)&xemacpsif->emacps);
	/*
	 * Enable the interrupt for emacps.
	 */
	EmacEnableIntr( );

	return 0;
}
Ejemplo n.º 14
0
XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxFirstBuffer, int iReleaseAfterSend )
{
NetworkBufferDescriptor_t *pxBuffer;
int head = xemacpsif->txHead;
int tail = xemacpsif->txTail;
int iHasSent = 0;
uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;

#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
	if( iReleaseAfterSend == pdFALSE )
	{
	NetworkBufferDescriptor_t *pxNewBuffer;

		pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxFirstBuffer, pxFirstBuffer->xDataLength );
		if( pxNewBuffer )
		{
			pxFirstBuffer = pxNewBuffer;
			iReleaseAfterSend = pdTRUE;
		}
	}
#endif

	/* Although it looks like more that 1 message can be sent,
	this possibility is NOT being used and not yet tested. */
	for( pxBuffer = pxFirstBuffer; pxBuffer != NULL;  )
	{
	NetworkBufferDescriptor_t *pxNextBuffer;

		if( ( head == tail ) && ( xemacpsif->txSegments[ head ].flags & XEMACPS_TXBUF_USED_MASK ) == 0 )
		{
//			FreeRTOS_printf( ( "emacps_send_message: All TX buffers full\n" ) );
			break;
		}
		if( xValidLength( pxBuffer->xDataLength ) )
		{
			/* Just a sanity check, the TX buffer will be assigned permanently. */
#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
			if( pxDMA_tx_buffers[ head ] != NULL )
#endif
			{
				uint32_t flags = 0;
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
				/* Move the message to unbuffered space in RAM. */
				pxDMA_tx_buffers[ head ] = ( uint32_t )pxBuffer->pucEthernetBuffer;
				if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
				{
					Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
				}
#else
				/* Copy the message to unbuffered space in RAM. */
				memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
#endif
				/* Packets will be sent one-by-one, so for each packet
				the TXBUF_LAST bit will be set. */
				flags |= XEMACPS_TXBUF_LAST_MASK;
				flags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );
				if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )
				{
					flags |= XEMACPS_TXBUF_WRAP_MASK;
				}

				/* Copy the address of the buffer and set the flags. */
				xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];
				xemacpsif->txSegments[ head ].flags = flags;

				iHasSent = pdTRUE;
			}
			if( ++head == ipconfigNIC_N_TX_DESC )
			{
				head = 0;
			}
		}
		/* Make a copy of the next field, before pxBuffer gets deleted */
		pxNextBuffer = pxBuffer->pxNextBuffer;
#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
		if( iReleaseAfterSend != pdFALSE )
		{
			vReleaseNetworkBufferAndDescriptor( pxBuffer );
		}
#endif
		pxBuffer = pxNextBuffer;
	}
	/* Update the TX-head index. These variable are declared volatile so they will be
	accessed as little as possible.	*/
	xemacpsif->txHead = head;

	/* Data Synchronization Barrier */
	dsb();

	if( iHasSent != pdFALSE )
	{
		/* Make STARTTX high */
		uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);
		/* Start transmit */
		xemacpsif->txBusy = pdTRUE;
		XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
	}
	dsb();

	return 0;
}