123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * Copyright (C) 2010 - 2019 Xilinx, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- */
- #include "netif/xemacpsif.h"
- #include "lwipopts.h"
- #if XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 || \
- XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1
- #define PCM_PMA_CORE_PRESENT
- #else
- #undef PCM_PMA_CORE_PRESENT
- #endif
- u32_t link_speed = 100;
- extern XEmacPs_Config XEmacPs_ConfigTable[];
- extern u32_t phymapemac0[32];
- extern u32_t phymapemac1[32];
- extern u32_t phyaddrforemac;
- extern enum ethernet_link_status eth_link_status;
- #ifdef OS_IS_FREERTOS
- extern long xInsideISR;
- #endif
- XEmacPs_Config *xemacps_lookup_config(unsigned mac_base)
- {
- XEmacPs_Config *cfgptr = NULL;
- s32_t i;
- for (i = 0; i < XPAR_XEMACPS_NUM_INSTANCES; i++) {
- if (XEmacPs_ConfigTable[i].BaseAddress == mac_base) {
- cfgptr = &XEmacPs_ConfigTable[i];
- break;
- }
- }
- return (cfgptr);
- }
- void init_emacps(xemacpsif_s *xemacps, struct netif *netif)
- {
- XEmacPs *xemacpsp;
- s32_t status = XST_SUCCESS;
- u32_t i;
- u32_t phyfoundforemac0 = FALSE;
- u32_t phyfoundforemac1 = FALSE;
- xemacpsp = &xemacps->emacps;
- #ifdef ZYNQMP_USE_JUMBO
- XEmacPs_SetOptions(xemacpsp, XEMACPS_JUMBO_ENABLE_OPTION);
- #endif
- #ifdef LWIP_IGMP
- XEmacPs_SetOptions(xemacpsp, XEMACPS_MULTICAST_OPTION);
- #endif
- /* set mac address */
- status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
- if (status != XST_SUCCESS) {
- xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
- }
- XEmacPs_SetMdioDivisor(xemacpsp, MDC_DIV_224);
- /* Please refer to file header comments for the file xemacpsif_physpeed.c
- * to know more about the PHY programming sequence.
- * For PCS PMA core, phy_setup_emacps is called with the predefined PHY address
- * exposed through xaparemeters.h
- * For RGMII case, assuming multiple PHYs can be present on the MDIO bus,
- * detect_phy is called to get the addresses of the PHY present on
- * a particular MDIO bus (emac0 or emac1). This address map is populated
- * in phymapemac0 or phymapemac1.
- * phy_setup_emacps is then called for each PHY present on the MDIO bus.
- */
- #ifdef PCM_PMA_CORE_PRESENT
- #ifdef XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT
- link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_1000BASEX_PHYADDR);
- #elif XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT
- link_speed = phy_setup_emacps(xemacpsp, XPAR_PCSPMA_SGMII_PHYADDR);
- #endif
- #else
- detect_phy(xemacpsp);
- for (i = 31; i > 0; i--) {
- if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
- if (phymapemac0[i] == TRUE) {
- link_speed = phy_setup_emacps(xemacpsp, i);
- phyfoundforemac0 = TRUE;
- phyaddrforemac = i;
- }
- } else {
- if (phymapemac1[i] == TRUE) {
- link_speed = phy_setup_emacps(xemacpsp, i);
- phyfoundforemac1 = TRUE;
- phyaddrforemac = i;
- }
- }
- }
- /* If no PHY was detected, use broadcast PHY address of 0 */
- if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR) {
- if (phyfoundforemac0 == FALSE)
- link_speed = phy_setup_emacps(xemacpsp, 0);
- } else {
- if (phyfoundforemac1 == FALSE)
- link_speed = phy_setup_emacps(xemacpsp, 0);
- }
- #endif
- if (link_speed == XST_FAILURE) {
- eth_link_status = ETH_LINK_DOWN;
- xil_printf("Phy setup failure %s \n\r",__func__);
- return;
- } else {
- eth_link_status = ETH_LINK_UP;
- }
- XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
- /* Setting the operating speed of the MAC needs a delay. */
- {
- volatile s32_t wait;
- for (wait=0; wait < 20000; wait++);
- }
- }
- void init_emacps_on_error (xemacpsif_s *xemacps, struct netif *netif)
- {
- XEmacPs *xemacpsp;
- s32_t status = XST_SUCCESS;
- xemacpsp = &xemacps->emacps;
- /* set mac address */
- status = XEmacPs_SetMacAddress(xemacpsp, (void*)(netif->hwaddr), 1);
- if (status != XST_SUCCESS) {
- xil_printf("In %s:Emac Mac Address set failed...\r\n",__func__);
- }
- XEmacPs_SetOperatingSpeed(xemacpsp, link_speed);
- /* Setting the operating speed of the MAC needs a delay. */
- {
- volatile s32_t wait;
- for (wait=0; wait < 20000; wait++);
- }
- }
- void setup_isr (struct xemac_s *xemac)
- {
- xemacpsif_s *xemacpsif;
- xemacpsif = (xemacpsif_s *)(xemac->state);
- /*
- * Setup callbacks
- */
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
- (void *) emacps_send_handler,
- (void *) xemac);
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
- (void *) emacps_recv_handler,
- (void *) xemac);
- XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
- (void *) emacps_error_handler,
- (void *) xemac);
- }
- void start_emacps (xemacpsif_s *xemacps)
- {
- /* start the temac */
- XEmacPs_Start(&xemacps->emacps);
- }
- void restart_emacps_transmitter (xemacpsif_s *xemacps) {
- u32_t Reg;
- Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- Reg = Reg & (~XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, Reg);
- Reg = XEmacPs_ReadReg(xemacps->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET);
- Reg = Reg | (XEMACPS_NWCTRL_TXEN_MASK);
- XEmacPs_WriteReg(xemacps->emacps.Config.BaseAddress,
- XEMACPS_NWCTRL_OFFSET, Reg);
- }
- void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord)
- {
- struct xemac_s *xemac;
- xemacpsif_s *xemacpsif;
- XEmacPs_BdRing *rxring;
- XEmacPs_BdRing *txring;
- #ifdef OS_IS_FREERTOS
- xInsideISR++;
- #endif
- xemac = (struct xemac_s *)(arg);
- xemacpsif = (xemacpsif_s *)(xemac->state);
- rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps);
- txring = &XEmacPs_GetTxRing(&xemacpsif->emacps);
- if (ErrorWord != 0) {
- switch (Direction) {
- case XEMACPS_RECV:
- if (ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Receive DMA error\r\n"));
- HandleEmacPsError(xemac);
- }
- if (ErrorWord & XEMACPS_RXSR_RXOVR_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Receive over run\r\n"));
- emacps_recv_handler(arg);
- setup_rx_bds(xemacpsif, rxring);
- }
- if (ErrorWord & XEMACPS_RXSR_BUFFNA_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Receive buffer not available\r\n"));
- emacps_recv_handler(arg);
- setup_rx_bds(xemacpsif, rxring);
- }
- break;
- case XEMACPS_SEND:
- if (ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Transmit DMA error\r\n"));
- HandleEmacPsError(xemac);
- }
- if (ErrorWord & XEMACPS_TXSR_URUN_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Transmit under run\r\n"));
- HandleTxErrors(xemac);
- }
- if (ErrorWord & XEMACPS_TXSR_BUFEXH_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Transmit buffer exhausted\r\n"));
- HandleTxErrors(xemac);
- }
- if (ErrorWord & XEMACPS_TXSR_RXOVR_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Transmit retry excessed limits\r\n"));
- HandleTxErrors(xemac);
- }
- if (ErrorWord & XEMACPS_TXSR_FRAMERX_MASK) {
- LWIP_DEBUGF(NETIF_DEBUG, ("Transmit collision\r\n"));
- // process_sent_bds(xemacpsif, txring);
- }
- break;
- }
- }
- #ifdef OS_IS_FREERTOS
- xInsideISR--;
- #endif
- }
|