/*
 * This optional function does a "fast" set of critical region protection to the
 * value specified by pval. See the documentation for sys_arch_protect() for
 * more information. This function is only required if your port is supporting
 * an operating system.
 */
void
sys_arch_unprotect(sys_prot_t lev)
{
#ifdef __arm__
#ifdef PEEP
	EmacEnableIntr();
#else
	mtcpsr(lev);
#endif
#else
	mtmsr(lev);
#endif
}
Exemple #2
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;
}