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 function demonstrates the usage usage of the Axi Ethernet by sending * and receiving frames in interrupt driven SGDMA mode. * * * @param IntcInstancePtr is a pointer to the instance of the Intc * component. * @param AxiEthernetInstancePtr is a pointer to the instance of the * AxiEthernet component. * @param DmaInstancePtr is a pointer to the instance of the AXIDMA * component. * @param AxiEthernetDeviceId is Device ID of the Axi Ethernet Device , * typically XPAR_<AXIETHERNET_instance>_DEVICE_ID value from * xparameters.h. * @param AxiDmaDeviceId is Device ID of the Axi DMAA Device , * typically XPAR_<AXIDMA_instance>_DEVICE_ID value from * xparameters.h. * @param AxiEthernetIntrId is the Interrupt ID and is typically * XPAR_<INTC_instance>_<AXIETHERNET_instance>_VEC_ID * value from xparameters.h. * @param DmaRxIntrId is the interrupt id for DMA Rx and is typically * taken from XPAR_<AXIETHERNET_instance>_CONNECTED_DMARX_INTR * @param DmaTxIntrId is the interrupt id for DMA Tx and is typically * taken from XPAR_<AXIETHERNET_instance>_CONNECTED_DMATX_INTR * * @return -XST_SUCCESS to indicate success. * -XST_FAILURE to indicate failure. * * @note AxiDma hardware must be initialized before initializing * AxiEthernet. Since AxiDma reset line is connected to the * AxiEthernet reset line, a reset of AxiDma hardware during its * initialization would reset AxiEthernet. * ******************************************************************************/ int AxiEthernetExtVlanExample(INTC *IntcInstancePtr, XAxiEthernet *AxiEthernetInstancePtr, XAxiDma *DmaInstancePtr, u16 AxiEthernetDeviceId, u16 AxiDmaDeviceId, u16 AxiEthernetIntrId, u16 DmaRxIntrId, u16 DmaTxIntrId) { int Status; int LoopbackSpeed; XAxiEthernet_Config *MacCfgPtr; XAxiDma_BdRing *RxRingPtr = XAxiDma_GetRxRing(DmaInstancePtr); XAxiDma_BdRing *TxRingPtr = XAxiDma_GetTxRing(DmaInstancePtr); XAxiDma_Bd BdTemplate; XAxiDma_Config* DmaConfig; /*************************************/ /* Setup device for first-time usage */ /*************************************/ /* * Get the configuration of AxiEthernet hardware. */ MacCfgPtr = XAxiEthernet_LookupConfig(AxiEthernetDeviceId); /* * Check if DMA is present or not. */ if(MacCfgPtr->AxiDevType != XPAR_AXI_DMA) { AxiEthernetUtilErrorTrap ("Device HW not configured for SGDMA mode\r\n"); return XST_FAILURE; } DmaConfig = XAxiDma_LookupConfig(AxiDmaDeviceId); /* * Initialize AXIDMA engine. AXIDMA engine must be initialized before * AxiEthernet. During AXIDMA engine initialization, AXIDMA hardware is * reset, and since AXIDMA reset line is connected to AxiEthernet, this * would ensure a reset of AxiEthernet. */ Status = XAxiDma_CfgInitialize(DmaInstancePtr, DmaConfig); if(Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error initializing DMA\r\n"); return XST_FAILURE; } /* * Initialize AxiEthernet hardware. */ Status = XAxiEthernet_CfgInitialize(AxiEthernetInstancePtr, MacCfgPtr, MacCfgPtr->BaseAddress); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error in initialize"); return XST_FAILURE; } /* * Set the MAC address */ Status = XAxiEthernet_SetMacAddress(AxiEthernetInstancePtr, AxiEthernetMAC); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting MAC address"); return XST_FAILURE; } /* * Setup RxBD space. * * We have already defined a properly aligned area of memory to store * RxBDs at the beginning of this source code file so just pass its * address into the function. No MMU is being used so the physical and * virtual addresses are the same. * * 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. */ /* * Create the RxBD ring */ Status = XAxiDma_BdRingCreate(RxRingPtr, (u32) &RxBdSpace, (u32) &RxBdSpace, BD_ALIGNMENT, RXBD_CNT); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting up RxBD space"); return XST_FAILURE; } XAxiDma_BdClear(&BdTemplate); Status = XAxiDma_BdRingClone(RxRingPtr, &BdTemplate); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error initializing RxBD space"); return XST_FAILURE; } /* * Setup TxBD space. * * Like RxBD space, we have already defined a properly aligned area of * memory to use. */ /* * Create the TxBD ring */ Status = XAxiDma_BdRingCreate(TxRingPtr, (u32) &TxBdSpace, (u32) &TxBdSpace, BD_ALIGNMENT, TXBD_CNT); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting up TxBD space"); return XST_FAILURE; } /* * We reuse the bd template, as the same one will work for both rx and * tx. */ Status = XAxiDma_BdRingClone(TxRingPtr, &BdTemplate); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error initializing TxBD space"); return XST_FAILURE; } /* * Set PHY to loopback, speed depends on phy type. * MII is 100 and all others are 1000. */ if (XAxiEthernet_GetPhysicalInterface(AxiEthernetInstancePtr) == XAE_PHY_TYPE_MII){ LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED; } else { LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED_1G; } AxiEthernetUtilEnterLoopback(AxiEthernetInstancePtr, LoopbackSpeed); /* * Set PHY<-->MAC data clock */ Status = XAxiEthernet_SetOperatingSpeed(AxiEthernetInstancePtr, (u16)LoopbackSpeed); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setting the operating speed of the MAC needs a delay. There * doesn't seem to be register to poll, so please consider this * during your application design. */ AxiEthernetUtilPhyDelay(2); /* * Connect to the interrupt controller and enable interrupts */ Status = AxiEthernetSetupIntrSystem(IntcInstancePtr, AxiEthernetInstancePtr, DmaInstancePtr, AxiEthernetIntrId, DmaRxIntrId, DmaTxIntrId); /****************************/ /* Run the example */ /****************************/ /* Run the new VLAN feature. Make sure HW has the capability */ if (XAxiEthernet_IsTxVlanTran(AxiEthernetInstancePtr) && XAxiEthernet_IsTxVlanStrp(AxiEthernetInstancePtr) && XAxiEthernet_IsTxVlanTag(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanTran(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanStrp(AxiEthernetInstancePtr) && XAxiEthernet_IsRxVlanTag(AxiEthernetInstancePtr)) { Status = AxiEthernetSgDmaIntrExtVlanExample (AxiEthernetInstancePtr,DmaInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } } /* * Disable the interrupts for the AxiEthernet device */ AxiEthernetDisableIntrSystem(IntcInstancePtr, AxiEthernetIntrId, DmaRxIntrId, DmaTxIntrId); /* * Stop the device */ XAxiEthernet_Stop(AxiEthernetInstancePtr); return XST_SUCCESS; }