diff options
Diffstat (limited to 'cpsw/src/lwiplib.c')
-rwxr-xr-x | cpsw/src/lwiplib.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/cpsw/src/lwiplib.c b/cpsw/src/lwiplib.c new file mode 100755 index 0000000..aeb78e2 --- /dev/null +++ b/cpsw/src/lwiplib.c @@ -0,0 +1,389 @@ +/** +* \file lwiplib.c +* +* \brief lwip related initializations +*/ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. + * + * Author: Adam Dunkels <adam@sics.se> + * +*/ + +/* +** Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ +** ALL RIGHTS RESERVED +*/ +#include "lwiplib.h" +#include "beaglebone.h" +#include "cpsw.h" +#include "netif/cpswif.h" +#include "delay.h" +#include "lwip/netif.h" +#include "lwip/prot/dhcp.h" +#include "lwip/dhcp.h" +#include "lwip/sys.h" +#include "lwip/autoip.h" +#include <sched.h> + +/* when the link is down, show a message, wait for a while and reboot */ +#define REBOOT_DELAY_SECONDS 5 + +#define DEFAULT_INST_NUM 0 +#define DEFAULT_PORT_NUMBER 1 + +#define LWIP_NOT_INITIALIZED 0 +#define LWIP_INITIALIZED 1 +//#define NUM_DHCP_TRIES 20 + +#define SECONDS_TO_MILISECONDS 1000 + +/****************************************************************************** +** INTERNAL FUNCTION PROTOTYPES +******************************************************************************/ +static bool lwIPDHCPComplete(unsigned int ifNum); +static void CPSWCore0RxIsr(void*); +static void CPSWCore0TxIsr(void*); +static void interruptSetup(void); + + +/****************************************************************************** +** INTERNAL VARIABLE DEFINITIONS +******************************************************************************/ +/* +** The lwIP network interface structure for CPSW ports. +*/ +#ifdef CPSW_DUAL_MAC_MODE +static struct netif cpswNetIF[MAX_CPSW_INST * MAX_SLAVEPORT_PER_INST]; +#else +static struct netif cpswNetIF[MAX_CPSW_INST]; +#endif + +/* +** Helper to identify ports +*/ +static struct cpswportif cpswPortIf[MAX_CPSW_INST * MAX_SLAVEPORT_PER_INST]; + +/****************************************************************************** +** FUNCTION DEFINITIONS +******************************************************************************/ +/** + * @brief checks if the dhcp has changed its state for + * (LWIP_DHCP_TIMEOUT * 10) ms + * + * @param state A pointer to the volatile state to check. + */ +static inline void dhcpCheck(volatile unsigned char * const state) +{ + unsigned int cnt = LWIP_DHCP_TIMEOUT; + + /* Check for DHCP completion for 'cnt' number of times, each 10ms */ + while( cnt-- && *state != DHCP_STATE_BOUND) + { + if(cnt % 2 == 0) + sched_yield(); + delay(10); + } +} + +/** + * @brief This function waits for DHCP completion with a timeout + * + * @param ifNum The netif number for the interface + * + * @return True if IP acquired succesfully, false otherwise. +*/ +static bool lwIPDHCPComplete(const unsigned int ifNum) +{ + bool ret = true; + unsigned int dhcpTries = 0; + volatile unsigned char * state; + struct netif* const netif = &cpswNetIF[ifNum]; + + do + { + ++dhcpTries; + dhcp_start(netif); + state = (volatile unsigned char *) &(netif->state); + LWIP_PRINTF("\n\rDHCP Trial %d ", (dhcpTries)); + dhcpCheck(state); + }while((dhcpTries < NUM_DHCP_TRIES) && (*state != DHCP_STATE_BOUND)); + + if (*state != DHCP_STATE_BOUND) + { + LWIP_PRINTF("\n\rUnable to complete DHCP! \n\r"); + ret = false; + } + return ret; +} + +/** + * @brief Starts the interface in Lwip according to its mode. + * + * @param lwipIf The addresses and modes to set. + * @param ifNum The interface to set. + * + * @return True if mode ok, false otherwise. + */ +static bool netifStart(LWIP_IF* const lwipIf, const unsigned int ifNum) +{ + bool ret = true; + switch(lwipIf->ipMode) + { + case IPADDR_USE_DHCP: + ret = lwIPDHCPComplete(ifNum); + break; + case IPADDR_USE_AUTOIP: + autoip_start(&cpswNetIF[ifNum]); + /*This has no break on purpose, since both autoip and static must do netif_set_up*/ + case IPADDR_USE_STATIC: + netif_set_up(&cpswNetIF[ifNum]); + break; + default: + ret = false; + } + return ret; +} + +/** + * @brief Resets Addresses if the mode is not static. + * + * @param lwipIf the addresses to configure. + */ +static inline void startLwipIf(LWIP_IF* const lwipIf) +{ + if(lwipIf->ipMode != IPADDR_USE_STATIC) + { + lwipIf->ipAddr.addr = 0; + lwipIf->netMask.addr = 0; + lwipIf->gwAddr.addr = 0; + } +} + +/** + * @brief Configures cpswPortIf for de desired interface, setting its + * instance number, port number and mac address. + * + * @param lwipIf The lwip interface that has the mac address + * @param ifNum The interface to configure + */ +static inline void setPortIf(LWIP_IF* const lwipIf, const unsigned int ifNum) +{ + unsigned int macIndex; + cpswPortIf[ifNum].inst_num = ifNum; + cpswPortIf[ifNum].port_num = DEFAULT_PORT_NUMBER; + + /* set MAC hardware address */ + for(macIndex = 0; macIndex < LEN_MAC_ADDRESS; ++macIndex) + { + cpswPortIf[ifNum].eth_addr[macIndex] = + lwipIf->macArray[(LEN_MAC_ADDRESS - 1) - macIndex]; + } +} + +/** + * + * @brief Initializes the lwIP TCP/IP stack. + * + * @param lwipIf The interface structure for lwIP + * + * @return true if everything ok, false otherwise. +*/ +static bool lwIPInit(LWIP_IF *const lwipIf, const unsigned int ifNum) +{ + static unsigned int lwipInitFlag = LWIP_NOT_INITIALIZED; + bool ret = true; + + /* do lwip library init only once */ + if(LWIP_NOT_INITIALIZED == lwipInitFlag) + { + tcpip_init(NULL, NULL); + } + setPortIf(lwipIf, ifNum); + + if(netif_add(&cpswNetIF[ifNum], &lwipIf->ipAddr, &lwipIf->netMask, + &lwipIf->gwAddr,&cpswPortIf[ifNum], cpswif_init, tcpip_input) != NULL) + { + if(LWIP_NOT_INITIALIZED == lwipInitFlag) + { + netif_set_default(&cpswNetIF[ifNum]); + lwipInitFlag = LWIP_INITIALIZED; + } + //lwipIf->ipMode = IPADDR_USE_DHCP; + ret = netifStart(lwipIf, ifNum); + } + else + { + LWIP_PRINTF("\n\rUnable to add interface for interface %d", ifNum); + ret = false; + } + return ret; +} + +/** + * @brief Interrupt handler for Receive Interrupt. Directly calls the + * cpsw interface receive interrupt handler. + * + * @param instNum The instance number of CPSW module for which receive + * interrupt happened +*/ +static inline void lwIPRxIntHandler(const unsigned int instNum) +{ + cpswif_rx_inthandler(instNum); +} + +/** + * @brief Interrupt handler for Transmit Interrupt. Directly calls the + * cpsw interface transmit interrupt handler. + * + * @param instNum The instance number of CPSW module for which transmit + * interrupt happened +*/ +static inline void lwIPTxIntHandler(const unsigned int instNum) +{ + cpswif_tx_inthandler(instNum); +} + +/** + * @brief Initializes low level device. + * + */ +static inline void cpswInit(void) +{ + CPSWPinMuxSetup(); + CPSWClkEnable(); +} + +/** + * @brief Initializes Phy and returns MAC Address. + * + * @param lwipIfPort The addresses, to return the MAC address. + */ +static inline void phyInit(LWIP_IF* const lwipIfPort) +{ + /* Chip configuration RGMII selection */ + EVMPortMIIModeSelect(); + + /* Get the MAC address */ + EVMMACAddrGet(0, lwipIfPort->macArray); +} + +/** + * @brief Prints a message wait a delay time and reboot the board(calling exit). + */ +static inline void ipFailed(void) +{ + printk("\n\r\n\rIP Address Acquisition Failed. Please Verify Your Cable/Link Status..."); + printk("\n\r\n\rSystem Will Automatically Reboot In %d Seconds.\r\n", REBOOT_DELAY_SECONDS); + delay(REBOOT_DELAY_SECONDS * SECONDS_TO_MILISECONDS); + exit(1); +} + +/** + * @brief Interrupt Handler for Core Receive interrupt + * + * @param instNum The device Instance number + */ +static void CPSWCore0RxIsr(void* instNum) +{ + lwIPRxIntHandler((unsigned int)instNum); +} + +/** + * @brief Interrupt Handler for Core Transmit interrupt + * + * @param instNum The device Instance number + */ +static void CPSWCore0TxIsr(void* instNum) +{ + lwIPTxIntHandler((unsigned int)instNum); +} + +/** + * @brief Displays the IP address on the Console + * + * @param ipAddr The desired IP address to display. + */ +static inline void IpAddrDisplay(const ip4_addr_t* const ipAddr) +{ + printk("\n\r\n\rIP Address Assigned: %s\r\n", ip4addr_ntoa(ipAddr)); +} + +/** + * @brief Sets up the ARM Interrupt Controller for generating timer interrupt. + */ +static void interruptSetup(void) +{ +rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_interrupt_handler_install( + AM335X_INT_3PGSWRXINT0, + "EthRX", + RTEMS_INTERRUPT_UNIQUE, + CPSWCore0RxIsr, + (void*)DEFAULT_INST_NUM + ); + LWIP_ASSERT("Install interrupt handler rx", sc == RTEMS_SUCCESSFUL); + + sc = rtems_interrupt_handler_install( + AM335X_INT_3PGSWTXINT0, + "EthTX", + RTEMS_INTERRUPT_UNIQUE, + CPSWCore0TxIsr, + (void*)DEFAULT_INST_NUM + ); + LWIP_ASSERT("Install interrupt handler tx", sc == RTEMS_SUCCESSFUL); +} + +bool startLwip(LWIP_IF* const lwipIfPort) +{ + const unsigned int ifNum = DEFAULT_INST_NUM; + bool ret; + + /*Initialization of low level device*/ + cpswInit(); + /*Initialization of the PHY and getting of MAC Address.*/ + phyInit(lwipIfPort); + /*Set ISR for the device*/ + interruptSetup(); + printk("Acquiring IP Address... \n\r" ); + /*Set up lwipIfPort properly for the desired mode*/ + startLwipIf(lwipIfPort); + /*Start Lwip stack with the desired address*/ + ret = lwIPInit(lwipIfPort, ifNum); + + if(ret) + { + IpAddrDisplay((ip4_addr_t *)&cpswNetIF[ifNum].ip_addr); + } + else /*Failed lwipinit, Print a message and reset the board*/ + { + ipFailed(); + } + return ret; +} |