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