277 lines
9.2 KiB
C
277 lines
9.2 KiB
C
/*
|
|
* 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
|
|
}
|