int wlan_eth_init() { int status; ETH_A_NUM_RX_BD = min(queue_total_size()/2,200); xil_printf("Setting up %d DMA BDs\n", ETH_A_NUM_RX_BD); //The TEMAC driver is only used during init - all packet interactions are handed via the DMA driver XAxiEthernet_Config *ETH_A_MAC_CFG_ptr; XAxiEthernet ETH_A_MAC_Instance; ETH_A_MAC_CFG_ptr = XAxiEthernet_LookupConfig(ETH_A_MAC_DEVICE_ID); status = XAxiEthernet_CfgInitialize(Ð_A_MAC_Instance, ETH_A_MAC_CFG_ptr, ETH_A_MAC_CFG_ptr->BaseAddress); if (status != XST_SUCCESS) {xil_printf("Error in XAxiEthernet_CfgInitialize! Err = %d\n", status); return -1;}; //Setup the TEMAC options status = XAxiEthernet_ClearOptions(Ð_A_MAC_Instance, XAE_LENTYPE_ERR_OPTION | XAE_FLOW_CONTROL_OPTION | XAE_JUMBO_OPTION); status |= XAxiEthernet_SetOptions(Ð_A_MAC_Instance, XAE_FCS_STRIP_OPTION | XAE_PROMISC_OPTION | XAE_MULTICAST_OPTION | XAE_BROADCAST_OPTION | XAE_FCS_INSERT_OPTION); status |= XAxiEthernet_SetOptions(Ð_A_MAC_Instance, XAE_RECEIVER_ENABLE_OPTION | XAE_TRANSMITTER_ENABLE_OPTION); if (status != XST_SUCCESS) {xil_printf("Error in XAxiEthernet_Set/ClearOptions! Err = %d\n", status); return -1;}; XAxiEthernet_SetOperatingSpeed(Ð_A_MAC_Instance, ETH_A_LINK_SPEED); //Initialize the axi_dma attached to the TEMAC status = wlan_eth_dma_init(); XAxiEthernet_Start(Ð_A_MAC_Instance); return 0; }
void init_axiemac(xaxiemacif_s *xaxiemac, struct netif *netif) { int rdy; unsigned mac_address = (unsigned)(netif->state); unsigned link_speed = 1000; unsigned options; unsigned lock_message_printed = 0; XAxiEthernet *xaxiemacp; XAxiEthernet_Config *mac_config; /* obtain config of this emac */ mac_config = lookup_config(mac_address); xaxiemacp = &xaxiemac->axi_ethernet; XAxiEthernet_CfgInitialize(xaxiemacp, mac_config, mac_config->BaseAddress); options = XAxiEthernet_GetOptions(xaxiemacp); options |= XAE_FLOW_CONTROL_OPTION; #ifdef XLLTEMACIF_USE_JUMBO_FRAMES_EXPERIMENTAL options |= XAE_JUMBO_OPTION; #endif options |= XAE_TRANSMITTER_ENABLE_OPTION; options |= XAE_RECEIVER_ENABLE_OPTION; options |= XAE_FCS_STRIP_OPTION; options |= XAE_MULTICAST_OPTION; XAxiEthernet_SetOptions(xaxiemacp, options); XAxiEthernet_ClearOptions(xaxiemacp, ~options); /* set mac address */ XAxiEthernet_SetMacAddress(xaxiemacp, (Xuint8*)(netif->hwaddr)); /* set PHY <--> MAC data clock */ #ifdef CONFIG_LINKSPEED_AUTODETECT link_speed = get_IEEE_phy_speed(xaxiemacp); xil_printf("auto-negotiated link speed: %d\r\n", link_speed); #elif defined(CONFIG_LINKSPEED1000) link_speed = 1000; #elif defined(CONFIG_LINKSPEED100) link_speed = 100; #elif defined(CONFIG_LINKSPEED10) link_speed = 10; #endif XAxiEthernet_SetOperatingSpeed(xaxiemacp, 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++); } #ifdef NOTNOW /* 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 (!(XAxiEthernet_ReadReg(xaxiemacp->Config.BaseAddress, XAE_IS_OFFSET) & XAE_INT_RXDCMLOCK_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"); #endif /* start the temac */ XAxiEthernet_Start(xaxiemacp); /* enable MAC interrupts */ XAxiEthernet_IntEnable(xaxiemacp, XAE_INT_RECV_ERROR_MASK); }
static err_t xaxiemacif_mac_filter_update (struct netif *netif, struct ip_addr *group, u8_t action) { err_t return_val = ERR_OK; u8_t multicast_mac_addr[6]; u8_t multicast_mac_addr_to_clr[6]; u8_t temp_mask; int entry; int i; u8_t * ip_addr_temp = (u8_t *)group; struct xemac_s *xemac = (struct xemac_s *)(netif->state); xaxiemacif_s *xaxiemacif = (xaxiemacif_s *)(xemac->state); if (action == IGMP_ADD_MAC_FILTER) { if ((ip_addr_temp[0] >= 224) && (ip_addr_temp[0] <= 239)) { if (xaxiemac_mcast_entry_mask >= 0x0F) { LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: No multicast address registers left.\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" Multicast MAC address add operation failure !!\r\n")); return_val = ERR_MEM; } else { for (i = 0; i < 4; i++) { temp_mask = (0x01) << i; if ((xaxiemac_mcast_entry_mask & temp_mask) == temp_mask) { continue; } else { entry = i; xaxiemac_mcast_entry_mask |= temp_mask; multicast_mac_addr[0] = 0x01; multicast_mac_addr[1] = 0x00; multicast_mac_addr[2] = 0x5E; multicast_mac_addr[3] = ip_addr_temp[1] & 0x7F; multicast_mac_addr[4] = ip_addr_temp[2]; multicast_mac_addr[5] = ip_addr_temp[3]; XAxiEthernet_Stop (&xaxiemacif->axi_ethernet); XAxiEthernet_MulticastAdd (&xaxiemacif->axi_ethernet, multicast_mac_addr,entry); XAxiEthernet_Start (&xaxiemacif->axi_ethernet); LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: Muticast MAC address successfully added.\r\n")); return_val = ERR_OK; break; } } if (i == 4) { LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: No multicast address registers left.\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" Multicast MAC address add operation failure !!\r\n")); return_val = ERR_MEM; } } } else { LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: The requested MAC address is not a multicast address.\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" Multicast address add operation failure !!\r\n")); return_val = ERR_ARG; } } else if (action == IGMP_DEL_MAC_FILTER) { if ((ip_addr_temp[0] < 224) || (ip_addr_temp[0] > 239)) { LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: The requested MAC address is not a multicast address.\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" Multicast address add operation failure !!\r\n")); return_val = ERR_ARG; } else { for (i = 0; i < 4; i++) { temp_mask = (0x01) << i; if ((xaxiemac_mcast_entry_mask & temp_mask) == temp_mask) { XAxiEthernet_MulticastGet (&xaxiemacif->axi_ethernet, multicast_mac_addr_to_clr, i); if ((ip_addr_temp[3] == multicast_mac_addr_to_clr[5]) && (ip_addr_temp[2] == multicast_mac_addr_to_clr[4]) && ((ip_addr_temp[1] & 0x7f) == multicast_mac_addr_to_clr[3])) { XAxiEthernet_Stop (&xaxiemacif->axi_ethernet); XAxiEthernet_MulticastClear (&xaxiemacif->axi_ethernet, i); XAxiEthernet_Start (&xaxiemacif->axi_ethernet); LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: Muticast MAC address successfully removed.\r\n")); return_val = ERR_OK; xaxiemac_mcast_entry_mask &= (~temp_mask); break; } else { continue; } } else { continue; } } if (i == 4) { LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_mac_filter_update: No multicast address registers present with\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" the requested Multicast MAC address.\r\n")); LWIP_DEBUGF(NETIF_DEBUG, (" Multicast MAC address removal failure!!.\r\n")); return_val = ERR_MEM; } } } return return_val; }
/** * * This example sends and receives a single packet in loopback mode with * extended VLAN support. * * The transmit frame will have VLAN field populated. * * On receive, HW should pass the VLAN field to receive BDs. * * @param AxiEthernetInstancePtr is a pointer to the instance of the * AxiEthernet component. * @param DmaInstancePtr is a pointer to the instance of the Dma * component. * * @return -XST_SUCCESS to indicate success. * -XST_FAILURE to indicate failure. * * @note Summary of VLAN tags handling in this example * * Frame setup with Tpid1+Cfi1+TxPid => 0x88A83111 * Frame translated to TxTransVid => 0x88A83222 * Frame tagged to Tpid2+Cfi2+TxTagVid => 0x9100C333 + 0x88A83222 * Frame sent and loopbacked. * * Frame stripped with RxStrpVid(0x333) => 0x88A83222 * Frame translated (key:RxVid:0x222) RxTransVid => 0x88A83444 * ******************************************************************************/ int AxiEthernetSgDmaIntrExtVlanExample(XAxiEthernet *AxiEthernetInstancePtr, XAxiDma *DmaInstancePtr) { int Status; u32 TxFrameLength; u32 RxFrameLength; int PayloadSize = PAYLOAD_SIZE; u16 Tpid1 = 0x88A8; u16 Tpid2 = 0x9100; u8 Cfi1 = 0x03; u8 Cfi2 = 0x0C; u16 TxVid = 0x0111; u16 TxTransVid = 0x0222; u16 TxTagVid = 0x0333; u16 RxVid = 0x0222; u16 RxTransVid = 0x0444; u16 RxStrpVid = 0x0333; u32 VTagCfiVid; u16 RxCfiVid; u16 RxTpid; u32 RxStatusControlWord; int Valid; XAxiDma_BdRing *RxRingPtr = XAxiDma_GetRxRing(DmaInstancePtr); XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(DmaInstancePtr); XAxiDma_Bd *BdPtr; XAxiDma_Bd *BdCurPtr; u32 BdSts; /* * Cannot run this example if extended features support is not enabled */ if (!(XAxiEthernet_IsTxVlanTran(AxiEthernetInstancePtr) && XAxiEthernet_IsTxVlanStrp(AxiEthernetInstancePtr) && XAxiEthernet_IsTxVlanTag(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanTran(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanStrp(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanTag(AxiEthernetInstancePtr))) { AxiEthernetUtilErrorTrap("Extended VLAN not available"); return XST_FAILURE; } /* * Clear variables shared with callbacks */ FramesRx = 0; FramesTx = 0; DeviceErrors = 0; memset(RxFrame,0,sizeof(RxFrame)); memset(TxFrame,0,sizeof(TxFrame)); /* * Calculate frame length (not including FCS) plus one VLAN tag */ TxFrameLength = XAE_HDR_VLAN_SIZE + PayloadSize; /* * Setup the packet with one VALN tag = VtagCfiVid to be transmitted * initially. */ VTagCfiVid = (((u32)Tpid1 << 16) | ((u32)Cfi1 << 12) | TxVid); AxiEthernetUtilFrameMemClear(&TxFrame); AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC); AxiEthernetUtilFrameHdrVlanFormatVid(&TxFrame, 0, VTagCfiVid); AxiEthernetUtilFrameHdrVlanFormatType(&TxFrame, PayloadSize, 1); AxiEthernetUtilFrameSetVlanPayloadData(&TxFrame, PayloadSize, 1); /* Intended VLAN setup: * TX translation and tagging. RX stripping and translation. * * Frame setup with Tpid1+Cfi1+TxPid => 0x88A83111 * Frame translated to TxTransVid => 0x88A83222 * Frame tagged to Tpid2+Cfi2+TxTagVid => 0x9100C333 + 0x88A83222 * Frame sent and loopbacked. * * Frame stripped with RxStrpVid(0x333) => 0x88A83222 * Frame translated (key:RxVid:0x222) RxTransVid => 0x88A83444 */ /* Extended VLAN transmit side. Stripping->Translation->Tagging */ /* * Configure VLAN TX tag mode, set to XAE_VTAG_SELECT. */ Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_EXT_TXVLAN_TAG_OPTION); Status |= XAxiEthernet_SetVTagMode(AxiEthernetInstancePtr, XAE_VTAG_SELECT, XAE_TX); /* * TX VLAN translation from TxVid to TxTransVid and enable tagging. */ Status |= XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_EXT_TXVLAN_TRAN_OPTION); Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, TxVid, TxTransVid,0, 1, XAE_TX); /* * TX VLAN tagging is keyed on TxVid to add one additional tag based * on register XAE_TTAG_OFFSET value. */ VTagCfiVid = (((u32)Tpid2 << 16) | ((u32)Cfi2 << 12) | TxTagVid); Status |= XAxiEthernet_SetVTagValue(AxiEthernetInstancePtr, VTagCfiVid, XAE_TX); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting TX VLAN"); return XST_FAILURE; } /* Extended VLAN receive side. Stripping->Translation->Tagging */ /* * Configure VLAN RX strip mode, set to XAE_VSTRP_SELECT. */ Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_EXT_RXVLAN_STRP_OPTION); Status |= XAxiEthernet_SetVStripMode(AxiEthernetInstancePtr, XAE_VSTRP_SELECT, XAE_RX); /* * RX VLAN strips based on RxStrpVid and enable stripping. */ Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, RxStrpVid, RxStrpVid, 1, 0, XAE_RX); /* * RX VLAN translation from RxVid to RxTransVid only. */ Status |= XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_EXT_RXVLAN_TRAN_OPTION); Status |= XAxiEthernet_SetVidTable(AxiEthernetInstancePtr, RxVid, RxTransVid, 0, 0, XAE_RX); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting RX VLAN"); return XST_FAILURE; } /* Configure VLAN TPIDs for HW to recognize. */ Status = XAxiEthernet_SetTpid(AxiEthernetInstancePtr, Tpid1, 0); Status |= XAxiEthernet_SetTpid(AxiEthernetInstancePtr, Tpid2, 1); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting TPIDs"); return XST_FAILURE; } /* * Flush the TX frame before giving it to DMA TX channel to transmit. */ Xil_DCacheFlushRange((u32)&TxFrame, TxFrameLength); /* * Clear out receive packet memory area */ AxiEthernetUtilFrameMemClear(&RxFrame); /* * Invalidate the RX frame before giving it to DMA RX channel to * receive data. */ Xil_DCacheInvalidateRange((u32)&RxFrame, TxFrameLength + 4); /* * Interrupt coalescing parameters are set to their default settings * which is to interrupt the processor after every frame has been * processed by the DMA engine. */ Status = XAxiDma_BdRingSetCoalesce(TxRingPtr, 1, 1); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting coalescing for transmit"); return XST_FAILURE; } Status = XAxiDma_BdRingSetCoalesce(RxRingPtr, 1, 1); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting coalescing for recv"); return XST_FAILURE; } /* * Make sure Tx and Rx are enabled */ Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_RECEIVER_ENABLE_OPTION | XAE_TRANSMITTER_ENABLE_OPTION ); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting options"); return XST_FAILURE; } Status = XAxiEthernet_SetOptions(AxiEthernetInstancePtr, XAE_JUMBO_OPTION); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting options"); return XST_FAILURE; } /* * Start the AxiEthernet and enable its ERROR interrupts */ XAxiEthernet_Start(AxiEthernetInstancePtr); XAxiEthernet_IntEnable(&AxiEthernetInstance, XAE_INT_RECV_ERROR_MASK); /* * Enable DMA receive related interrupts */ XAxiDma_BdRingIntEnable(RxRingPtr, XAXIDMA_IRQ_ALL_MASK); /* * Allocate 1 RxBD. */ Status = XAxiDma_BdRingAlloc(RxRingPtr, 1, &BdPtr); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error allocating RxBD"); return XST_FAILURE; } /* * Setup the BD. */ XAxiDma_BdSetBufAddr(BdPtr, (u32)&RxFrame); #ifndef XPAR_AXIDMA_0_ENABLE_MULTI_CHANNEL XAxiDma_BdSetLength(BdPtr, sizeof(RxFrame)); #else XAxiDma_BdSetLength(BdPtr, sizeof(RxFrame), RxRingPtr->MaxTransferLen); #endif XAxiDma_BdSetCtrl(BdPtr, 0); /* * Enqueue to HW */ Status = XAxiDma_BdRingToHw(RxRingPtr, 1, BdPtr); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error committing RxBD to HW"); return XST_FAILURE; } /* * Start DMA RX channel. Now it's ready to receive data. */ Status = XAxiDma_BdRingStart(RxRingPtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Enable DMA transmit related interrupts */ XAxiDma_BdRingIntEnable(TxRingPtr, XAXIDMA_IRQ_ALL_MASK); /* * Allocate 1 TxBD */ Status = XAxiDma_BdRingAlloc(TxRingPtr, 1, &BdPtr); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error allocating TxBD"); return XST_FAILURE; } /* * Setup the TxBD */ XAxiDma_BdSetBufAddr(BdPtr, (u32)&TxFrame); #ifndef XPAR_AXIDMA_0_ENABLE_MULTI_CHANNEL XAxiDma_BdSetLength(BdPtr, TxFrameLength); #else XAxiDma_BdSetLength(BdPtr, TxFrameLength, TxRingPtr->MaxTransferLen); #endif XAxiDma_BdSetCtrl(BdPtr, XAXIDMA_BD_CTRL_TXSOF_MASK | XAXIDMA_BD_CTRL_TXEOF_MASK); /* * Enqueue to HW */ Status = XAxiDma_BdRingToHw(TxRingPtr, 1, BdPtr); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error committing TxBD to HW"); return XST_FAILURE; } /* * Start DMA TX channel. Transmission starts at once. */ Status = XAxiDma_BdRingStart(TxRingPtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Wait for transmission to complete */ while (!FramesTx); /* * Now that the frame has been sent, post process our TxBDs. * Since we have only submitted 2 to HW, then there should be only 2 * ready for post processing. */ if (XAxiDma_BdRingFromHw(TxRingPtr, 1, &BdPtr) == 0) { AxiEthernetUtilErrorTrap("TxBDs were not ready for post processing"); return XST_FAILURE; } /* * Examine the TxBDs. * * There isn't much to do. The only thing to check would be DMA * exception bits. But this would also be caught in the error handler. * So we just return these BDs to the free list */ Status = XAxiDma_BdRingFree(TxRingPtr, 1, BdPtr); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error freeing up TxBDs"); return XST_FAILURE; } /* * Wait for Rx indication */ while (!FramesRx); /* * Now that the frame has been received, post process our RxBD. * Since we have only submitted 1 to HW, then there should be only 1 * ready for post processing. */ if (XAxiDma_BdRingFromHw(RxRingPtr, 1, &BdPtr) == 0) { AxiEthernetUtilErrorTrap("RxBD was not ready for post processing"); return XST_FAILURE; } BdCurPtr = BdPtr; BdSts = XAxiDma_BdGetSts(BdCurPtr); if ((BdSts & XAXIDMA_BD_STS_ALL_ERR_MASK) || (!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK))) { AxiEthernetUtilErrorTrap("Rx Error"); return XST_FAILURE; } else { RxFrameLength = (XAxiDma_BdRead(BdCurPtr,XAXIDMA_BD_USR4_OFFSET)) & 0x0000FFFF; } /* Expected RX TPID+CFI+VID !!! */ VTagCfiVid = (((u32)Tpid2 << 16) | ((u32)Cfi2 << 12) | RxStrpVid); /* Check on the VLAN CFI and VID */ RxStatusControlWord = XAxiDma_BdGetAppWord(BdPtr, BD_VLAN_VID_OFFSET, &Valid); if(Valid) { RxCfiVid = RxStatusControlWord >> 16; RxCfiVid = Xil_Ntohs(RxCfiVid); if(RxCfiVid != (VTagCfiVid & 0x0000FFFF)) { AxiEthernetUtilErrorTrap("VLAN CFI and VID mismatch\n"); return XST_FAILURE; } } else {