int SetupIntrSystem( XScuTimer * TimerInstancePtr, u16 TimerIntrId) { Xil_ExceptionInit(); XScuGic_DeviceInitialize(INTC_DEVICE_ID); /* * Connect the interrupt controller interrupt handler to the hardware * interrupt handling logic in the processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, (void *)INTC_DEVICE_ID); /* * 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, TimerIntrId, (Xil_ExceptionHandler)timer_callback, (void *)&TimerInstance); /* * Enable the interrupt for scu timer. */ XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TimerIntrId); return XST_SUCCESS; }
int cortexa9_init(void) { Xil_ExceptionInit(); XScuGic_DeviceInitialize(0); /* * Connect the interrupt controller interrupt handler to the hardware * interrupt handling logic in the processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, (Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler, (void *)0); /* * 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(SCUGIC_CPU_BASEADDR, PROFILE_TIMER_INTR_ID, (Xil_ExceptionHandler)profile_intr_handler, (void *)0); /* * Enable the interrupt for scu timer. */ XScuGic_EnableIntr(SCUGIC_DIST_BASEADDR, PROFILE_TIMER_INTR_ID); /* * Enable interrupts in the Processor. */ Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); /* * Initialize the timer with Timer Ticks */ scu_timer_init() ; Xil_ExceptionEnable(); return 0; }
XStatus init_dma(struct xemac_s *xemac) { XEmacPs_Bd bdtemplate; XEmacPs_BdRing *rxringptr, *txringptr; XEmacPs_Bd *rxbd; struct pbuf *p; XStatus status; s32_t i; u32_t bdindex; volatile u32_t tempaddress; xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; /* * The BDs need to be allocated in uncached memory. Hence the 1 MB * address range allocated for Bd_Space is made uncached * by setting appropriate attributes in the translation table. * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures * a reserved uncached area used only for BDs. */ if (bd_space_attr_set == 0) { Xil_SetTlbAttributes((s32_t)bd_space, 0xc02); // addr, attr bd_space_attr_set = 1; } rxringptr = &XEmacPs_GetRxRing(&xemacpsif->emacps); txringptr = &XEmacPs_GetTxRing(&xemacpsif->emacps); LWIP_DEBUGF(NETIF_DEBUG, ("rxringptr: 0x%08x\r\n", rxringptr)); LWIP_DEBUGF(NETIF_DEBUG, ("txringptr: 0x%08x\r\n", txringptr)); /* Allocate 64k for Rx and Tx bds each to take care of extreme cases */ tempaddress = (u32_t)&(bd_space[bd_space_index]); xemacpsif->rx_bdspace = (void *)tempaddress; bd_space_index += 0x10000; tempaddress = (u32_t)&(bd_space[bd_space_index]); xemacpsif->tx_bdspace = (void *)tempaddress; bd_space_index += 0x10000; LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: 0x%08x\r\n", xemacpsif->rx_bdspace)); LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: 0x%08x\r\n", xemacpsif->tx_bdspace)); if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) { xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors", __FILE__, __LINE__); return ERR_IF; } /* * Setup RxBD space. * * Setup a BD template for the Rx channel. This template will be copied to * every RxBD. We will not have to explicitly set these again. */ XEmacPs_BdClear(&bdtemplate); /* * Create the RxBD ring */ status = XEmacPs_BdRingCreate(rxringptr, (u32) xemacpsif->rx_bdspace, (u32) xemacpsif->rx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_RX_DESC); if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n")); return ERR_IF; } status = XEmacPs_BdRingClone(rxringptr, &bdtemplate, XEMACPS_RECV); if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n")); return ERR_IF; } XEmacPs_BdClear(&bdtemplate); XEmacPs_BdSetStatus(&bdtemplate, XEMACPS_TXBUF_USED_MASK); /* * Create the TxBD ring */ status = XEmacPs_BdRingCreate(txringptr, (u32) xemacpsif->tx_bdspace, (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_TX_DESC); if (status != XST_SUCCESS) { return ERR_IF; } /* We reuse the bd template, as the same one will work for both rx and tx. */ status = XEmacPs_BdRingClone(txringptr, &bdtemplate, XEMACPS_SEND); if (status != XST_SUCCESS) { return ERR_IF; } /* * Allocate RX descriptors, 1 RxBD at a time. */ for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) { p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); if (!p) { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif printf("unable to alloc pbuf in init_dma\r\n"); return ERR_IF; } status = XEmacPs_BdRingAlloc(rxringptr, 1, &rxbd); if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n")); pbuf_free(p); return ERR_IF; } /* Enqueue to HW */ status = XEmacPs_BdRingToHw(rxringptr, 1, rxbd); if (status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n")); pbuf_free(p); XEmacPs_BdRingUnAlloc(rxringptr, 1, rxbd); return ERR_IF; } Xil_DCacheInvalidateRange((u32_t)p->payload, (u32_t)XEMACPS_MAX_FRAME_SIZE); XEmacPs_BdSetAddressRx(rxbd, (u32_t)p->payload); bdindex = XEMACPS_BD_TO_INDEX(rxringptr, rxbd); rx_pbufs_storage[bdindex] = (s32_t)p; } /* * 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. */ XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr); emac_intr_num = (u32) xtopologyp->scugic_emac_intr; return 0; }
static err_t low_level_init(struct netif *netif) { struct xemac_s *xemac; XEmacLite_Config *config; XEmacLite *xemaclitep; struct xtopology_t *xtopologyp; xemacliteif_s *xemacliteif; unsigned link_speed = 1000; xemaclitep = mem_malloc(sizeof *xemaclitep); #ifndef XLWIP_CONFIG_INCLUDE_EMACLITE_ON_ZYNQ #if XPAR_INTC_0_HAS_FAST == 1 xemaclitep_fast = xemaclitep; #endif #endif if (xemaclitep == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("xemacliteif_init: out of memory\r\n")); return ERR_MEM; } xemac = mem_malloc(sizeof *xemac); if (xemac == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("xemacliteif_init: out of memory\r\n")); return ERR_MEM; } xemacliteif = mem_malloc(sizeof *xemacliteif); if (xemacliteif == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("xemacliteif_init: out of memory\r\n")); return ERR_MEM; } /* obtain pointer to topology structure for this emac */ xemac->topology_index = xtopology_find_index((unsigned)(netif->state)); xtopologyp = &xtopology[xemac->topology_index]; /* obtain config of this emaclite */ config = xemaclite_lookup_config((unsigned)(netif->state)); /* maximum transfer unit */ netif->mtu = XEL_MTU_SIZE; /* broadcast capability */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* initialize the mac */ XEmacLite_Initialize(xemaclitep, config->DeviceId); xemaclitep->NextRxBufferToUse = 0; #if XLWIP_CONFIG_INCLUDE_EMACLITE_ON_ZYNQ == 1 XScuGic_RegisterHandler(xtopologyp->scugic_baseaddr, xtopologyp->intc_emac_intr, (Xil_ExceptionHandler)XEmacLite_InterruptHandler, xemaclitep); XScuGic_SetPriTrigTypeByDistAddr(INTC_DIST_BASE_ADDR, xtopologyp->intc_emac_intr, EMACLITE_INTR_PRIORITY_SET_IN_GIC, TRIG_TYPE_RISING_EDGE_SENSITIVE); XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xtopologyp->intc_emac_intr); #else #if NO_SYS #if XPAR_INTC_0_HAS_FAST == 1 XIntc_RegisterFastHandler(xtopologyp->intc_baseaddr, xtopologyp->intc_emac_intr, (XFastInterruptHandler)XEmacLite_FastInterruptHandler); #else XIntc_RegisterHandler(xtopologyp->intc_baseaddr, xtopologyp->intc_emac_intr, (XInterruptHandler)XEmacLite_InterruptHandler, xemaclitep); #endif #else xPortInstallInterruptHandler( XPAR_INTC_0_EMACLITE_0_VEC_ID, ( XInterruptHandler ) XEmacLite_InterruptWrapper, xemaclitep ); vPortEnableInterrupt( XPAR_INTC_0_EMACLITE_0_VEC_ID ); #endif #endif /* set mac address */ XEmacLite_SetMacAddress(xemaclitep, (unsigned char*)(netif->hwaddr)); /* flush any frames already received */ XEmacLite_FlushReceive(xemaclitep); /* set Rx, Tx interrupt handlers */ XEmacLite_SetRecvHandler(xemaclitep, (void *)(xemac), xemacif_recv_handler); XEmacLite_SetSendHandler(xemaclitep, (void *)(xemac), xemacif_send_handler); /* enable Rx, Tx interrupts */ XEmacLite_EnableInterrupts(xemaclitep); #if !NO_SYS sys_sem_new(&xemac->sem_rx_data_available, 0); #endif /* replace the state in netif (currently the base address of emaclite) * with the xemacliteif instance pointer. * this contains a pointer to the config table entry */ xemac->type = xemac_type_xps_emaclite; xemac->state = (void *)xemacliteif; netif->state = (void *)xemac; xemacliteif->instance = xemaclitep; xemacliteif->recv_q = pq_create_queue(); if (!xemacliteif->recv_q) return ERR_MEM; xemacliteif->send_q = pq_create_queue(); if (!xemacliteif->send_q) return ERR_MEM; /* Initialize PHY */ /* set PHY <--> MAC data clock */ #ifdef CONFIG_LINKSPEED_AUTODETECT link_speed = get_IEEE_phy_speed_emaclite(xemaclitep); xil_printf("auto-negotiated link speed: %d\r\n", link_speed); #elif defined(CONFIG_LINKSPEED1000) xil_printf("Link speed of 1000 Mbps not possible\r\n"); #elif defined(CONFIG_LINKSPEED100) link_speed = 100; configure_IEEE_phy_speed_emaclite(xemaclitep, link_speed); xil_printf("link speed: %d\r\n", link_speed); #elif defined(CONFIG_LINKSPEED10) link_speed = 10; configure_IEEE_phy_speed_emaclite(xemaclitep, link_speed); xil_printf("link speed: %d\r\n", link_speed); #endif return ERR_OK; }
XStatus init_dma(struct xemac_s *xemac) { XEmacPs_Bd BdTemplate; XEmacPs_BdRing *RxRingPtr, *TxRingPtr; XEmacPs_Bd *rxbd; struct pbuf *p; XStatus Status; int i; unsigned int BdIndex; char *endAdd = &_end; /* * Align the BD starte address to 1 MB boundary. */ char *endAdd_aligned = (char *)(((int)endAdd + 0x100000) & (~0xFFFFF)); xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state); struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; /* * The BDs need to be allocated in uncached memory. Hence the 1 MB * address range that starts at address 0xFF00000 is made uncached * by setting appropriate attributes in the translation table. */ Xil_SetTlbAttributes((int)endAdd_aligned, 0xc02); // addr, attr RxRingPtr = &XEmacPs_GetRxRing(&xemacpsif->emacps); TxRingPtr = &XEmacPs_GetTxRing(&xemacpsif->emacps); LWIP_DEBUGF(NETIF_DEBUG, ("RxRingPtr: 0x%08x\r\n", RxRingPtr)); LWIP_DEBUGF(NETIF_DEBUG, ("TxRingPtr: 0x%08x\r\n", TxRingPtr)); xemacpsif->rx_bdspace = (void *)endAdd_aligned; /* * We allocate 65536 bytes for Rx BDs which can accomodate a * maximum of 8192 BDs which is much more than any application * will ever need. */ xemacpsif->tx_bdspace = (void *)(endAdd_aligned + 0x10000); LWIP_DEBUGF(NETIF_DEBUG, ("rx_bdspace: 0x%08x\r\n", xemacpsif->rx_bdspace)); LWIP_DEBUGF(NETIF_DEBUG, ("tx_bdspace: 0x%08x\r\n", xemacpsif->tx_bdspace)); if (!xemacpsif->rx_bdspace || !xemacpsif->tx_bdspace) { xil_printf("%s@%d: Error: Unable to allocate memory for TX/RX buffer descriptors", __FILE__, __LINE__); return XST_FAILURE; } /* * Setup RxBD space. * * Setup a BD template for the Rx channel. This template will be copied to * every RxBD. We will not have to explicitly set these again. */ XEmacPs_BdClear(&BdTemplate); /* * Create the RxBD ring */ Status = XEmacPs_BdRingCreate(RxRingPtr, (u32) xemacpsif->rx_bdspace, (u32) xemacpsif->rx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_RX_DESC); if (Status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error setting up RxBD space\r\n")); return XST_FAILURE; } Status = XEmacPs_BdRingClone(RxRingPtr, &BdTemplate, XEMACPS_RECV); if (Status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error initializing RxBD space\r\n")); return XST_FAILURE; } XEmacPs_BdClear(&BdTemplate); XEmacPs_BdSetStatus(&BdTemplate, XEMACPS_TXBUF_USED_MASK); /* * Create the TxBD ring */ Status = XEmacPs_BdRingCreate(TxRingPtr, (u32) xemacpsif->tx_bdspace, (u32) xemacpsif->tx_bdspace, BD_ALIGNMENT, XLWIP_CONFIG_N_TX_DESC); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* We reuse the bd template, as the same one will work for both rx and tx. */ Status = XEmacPs_BdRingClone(TxRingPtr, &BdTemplate, XEMACPS_SEND); if (Status != XST_SUCCESS) { return ERR_IF; } /* * Allocate RX descriptors, 1 RxBD at a time. */ for (i = 0; i < XLWIP_CONFIG_N_RX_DESC; i++) { Status = XEmacPs_BdRingAlloc(RxRingPtr, 1, &rxbd); if (Status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("init_dma: Error allocating RxBD\r\n")); return ERR_IF; } p = pbuf_alloc(PBUF_RAW, XEMACPS_MAX_FRAME_SIZE, PBUF_POOL); if (!p) { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif LWIP_DEBUGF(NETIF_DEBUG, ("unable to alloc pbuf in recv_handler\r\n")); return -1; } XEmacPs_BdSetAddressRx(rxbd, (u32)p->payload); BdIndex = XEMACPS_BD_TO_INDEX(RxRingPtr, rxbd); rx_pbufs_storage[BdIndex] = (int)p; /* Enqueue to HW */ Status = XEmacPs_BdRingToHw(RxRingPtr, 1, rxbd); if (Status != XST_SUCCESS) { LWIP_DEBUGF(NETIF_DEBUG, ("Error: committing RxBD to HW\r\n")); return XST_FAILURE; } } /* * 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. */ XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, (u32) xtopologyp->scugic_emac_intr); EmacIntrNum = (u32) xtopologyp->scugic_emac_intr; return 0; }
XStatus init_axi_fifo(struct xemac_s *xemac) { xaxiemacif_s *xaxiemacif = (xaxiemacif_s *)(xemac->state); #if XPAR_INTC_0_HAS_FAST == 1 xaxiemacif_fast = xaxiemacif; xemac_fast = xemac; #endif #if NO_SYS struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; #endif #ifdef OS_IS_FREERTOS struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index]; #endif /* initialize ll fifo */ XLlFifo_Initialize(&xaxiemacif->axififo, XAxiEthernet_AxiDevBaseAddress(&xaxiemacif->axi_ethernet)); /* Clear any pending FIFO interrupts */ XLlFifo_IntClear(&xaxiemacif->axififo, XLLF_INT_ALL_MASK); /* enable fifo interrupts */ XLlFifo_IntEnable(&xaxiemacif->axififo, XLLF_INT_ALL_MASK); #if XLWIP_CONFIG_INCLUDE_AXIETH_ON_ZYNQ == 1 XScuGic_RegisterHandler(xtopologyp->scugic_baseaddr, xaxiemacif->axi_ethernet.Config.TemacIntr, (XInterruptHandler)xaxiemac_error_handler, &xaxiemacif->axi_ethernet); XScuGic_RegisterHandler(xtopologyp->scugic_baseaddr, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XInterruptHandler)xllfifo_intr_handler, xemac); XScuGic_SetPriTrigTypeByDistAddr(INTC_DIST_BASE_ADDR, xaxiemacif->axi_ethernet.Config.TemacIntr, AXIETH_INTR_PRIORITY_SET_IN_GIC, TRIG_TYPE_RISING_EDGE_SENSITIVE); XScuGic_SetPriTrigTypeByDistAddr(INTC_DIST_BASE_ADDR, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, AXIFIFO_INTR_PRIORITY_SET_IN_GIC, TRIG_TYPE_RISING_EDGE_SENSITIVE); XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xaxiemacif->axi_ethernet.Config.TemacIntr); XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xaxiemacif->axi_ethernet.Config.AxiFifoIntr); #else #if NO_SYS #if XPAR_INTC_0_HAS_FAST == 1 /* Register temac interrupt with interrupt controller */ XIntc_RegisterFastHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.TemacIntr, (XFastInterruptHandler)xaxiemac_fasterror_handler); /* connect & enable FIFO interrupt */ XIntc_RegisterFastHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XFastInterruptHandler)xllfifo_fastintr_handler); #else /* Register temac interrupt with interrupt controller */ XIntc_RegisterHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.TemacIntr, (XInterruptHandler)xaxiemac_error_handler, &xaxiemacif->axi_ethernet); /* connect & enable FIFO interrupt */ XIntc_RegisterHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XInterruptHandler)xllfifo_intr_handler, xemac); #endif /* Enable EMAC interrupts in the interrupt controller */ do { /* read current interrupt enable mask */ unsigned int cur_mask = XIntc_In32(xtopologyp->intc_baseaddr + XIN_IER_OFFSET); /* form new mask enabling SDMA & ll_temac interrupts */ cur_mask = cur_mask | (1 << xaxiemacif->axi_ethernet.Config.AxiFifoIntr) | (1 << xaxiemacif->axi_ethernet.Config.TemacIntr); /* set new mask */ XIntc_EnableIntr(xtopologyp->intc_baseaddr, cur_mask); } while (0); #else #ifdef OS_IS_XILKERNEL /* connect & enable TEMAC interrupts */ register_int_handler(xaxiemacif->axi_ethernet.Config.TemacIntr, (XInterruptHandler)xaxiemac_error_handler, &xaxiemacif->axi_ethernet); enable_interrupt(xaxiemacif->axi_ethernet.Config.TemacIntr); /* connect & enable FIFO interrupts */ register_int_handler(xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XInterruptHandler)xllfifo_intr_handler, xemac); enable_interrupt(xaxiemacif->axi_ethernet.Config.AxiFifoIntr); #else #if XPAR_INTC_0_HAS_FAST == 1 /* Register temac interrupt with interrupt controller */ XIntc_RegisterFastHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.TemacIntr, (XFastInterruptHandler)xaxiemac_fasterror_handler); /* connect & enable FIFO interrupt */ XIntc_RegisterFastHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XFastInterruptHandler)xllfifo_fastintr_handler); #else /* Register temac interrupt with interrupt controller */ XIntc_RegisterHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.TemacIntr, (XInterruptHandler)xaxiemac_error_handler, &xaxiemacif->axi_ethernet); /* connect & enable FIFO interrupt */ XIntc_RegisterHandler(xtopologyp->intc_baseaddr, xaxiemacif->axi_ethernet.Config.AxiFifoIntr, (XInterruptHandler)xllfifo_intr_handler, xemac); #endif /* Enable EMAC interrupts in the interrupt controller */ do { /* read current interrupt enable mask */ unsigned int cur_mask = XIntc_In32(xtopologyp->intc_baseaddr + XIN_IER_OFFSET); /* form new mask enabling SDMA & ll_temac interrupts */ cur_mask = cur_mask | (1 << xaxiemacif->axi_ethernet.Config.AxiFifoIntr) | (1 << xaxiemacif->axi_ethernet.Config.TemacIntr); /* set new mask */ XIntc_EnableIntr(xtopologyp->intc_baseaddr, cur_mask); } while (0); #endif #endif #endif return 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; }