Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ar8031.c Source File

ar8031.c

Go to the documentation of this file.
00001 /**
00002  * @file ar8031.c
00003  * @brief AR8031 Gigabit Ethernet PHY transceiver
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "drivers/ar8031.h"
00035 #include "debug.h"
00036 
00037 
00038 /**
00039  * @brief AR8031 Ethernet PHY driver
00040  **/
00041 
00042 const PhyDriver ar8031PhyDriver =
00043 {
00044    ar8031Init,
00045    ar8031Tick,
00046    ar8031EnableIrq,
00047    ar8031DisableIrq,
00048    ar8031EventHandler,
00049 };
00050 
00051 
00052 /**
00053  * @brief AR8031 PHY transceiver initialization
00054  * @param[in] interface Underlying network interface
00055  * @return Error code
00056  **/
00057 
00058 error_t ar8031Init(NetInterface *interface)
00059 {
00060    //Debug message
00061    TRACE_INFO("Initializing AR8031...\r\n");
00062 
00063    //Initialize external interrupt line driver
00064    if(interface->extIntDriver != NULL)
00065       interface->extIntDriver->init();
00066 
00067    //Reset PHY transceiver
00068    ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR, BMCR_RESET);
00069    //Wait for the reset to complete
00070    while(ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMCR) & BMCR_RESET);
00071 
00072    //Chip configuration register
00073    ar8031WritePhyReg(interface, AR8031_PHY_REG_CHIP_CONFIG,
00074       CHIP_CONFIG_BT_BX_REG_SEL | CHIP_CONFIG_PRIORITY_SEL);
00075 
00076    //Basic mode control register
00077    ar8031WritePhyReg(interface, AR8031_PHY_REG_BMCR,
00078       BMCR_SPEED_SEL_LSB | BMCR_AN_EN | BMCR_DUPLEX_MODE);
00079 
00080    //Auto-negotiation advertisement register
00081    ar8031WritePhyReg(interface, AR8031_PHY_REG_ANAR,
00082       ANAR_XNP_ABLE | ANAR_ASYMMETRIC_PAUSE | ANAR_PAUSE | ANAR_100BTX_FD |
00083       ANAR_100BTX_HD | ANAR_10BT_FD | ANAR_10BT_HD | ANAR_SELECTOR0);
00084 
00085    //1000 BASE-T control register
00086    ar8031WritePhyReg(interface, AR8031_PHY_REG_1000BT_CTRL,
00087       _1000BT_CTRL_1000BT_FD);
00088 
00089    //Function control register
00090    ar8031WritePhyReg(interface, AR8031_PHY_REG_FUNCTION_CTRL,
00091       FUNCTION_ASSERT_CRS_ON_TX | FUNCTION_MDI_CROSSOVER_MODE1 |
00092       FUNCTION_MDI_CROSSOVER_MODE0 | FUNCTION_POLARITY_REVERSAL);
00093 
00094    //Dump PHY registers for debugging purpose
00095    ar8031DumpPhyReg(interface);
00096 
00097    //The PHY will generate interrupts when link status changes are detected
00098    ar8031WritePhyReg(interface, AR8031_PHY_REG_INT_EN,
00099       INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS);
00100 
00101    //Force the TCP/IP stack to poll the link state at startup
00102    interface->phyEvent = TRUE;
00103    //Notify the TCP/IP stack of the event
00104    osSetEvent(&netEvent);
00105 
00106    //Successful initialization
00107    return NO_ERROR;
00108 }
00109 
00110 
00111 /**
00112  * @brief AR8031 timer handler
00113  * @param[in] interface Underlying network interface
00114  **/
00115 
00116 void ar8031Tick(NetInterface *interface)
00117 {
00118    uint16_t value;
00119    bool_t linkState;
00120 
00121    //No external interrupt line driver?
00122    if(interface->extIntDriver == NULL)
00123    {
00124       //Read basic status register
00125       value = ar8031ReadPhyReg(interface, AR8031_PHY_REG_BMSR);
00126       //Retrieve current link state
00127       linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE;
00128 
00129       //Link up event?
00130       if(linkState && !interface->linkState)
00131       {
00132          //Set event flag
00133          interface->phyEvent = TRUE;
00134          //Notify the TCP/IP stack of the event
00135          osSetEvent(&netEvent);
00136       }
00137       //Link down event?
00138       else if(!linkState && interface->linkState)
00139       {
00140          //Set event flag
00141          interface->phyEvent = TRUE;
00142          //Notify the TCP/IP stack of the event
00143          osSetEvent(&netEvent);
00144       }
00145    }
00146 }
00147 
00148 
00149 /**
00150  * @brief Enable interrupts
00151  * @param[in] interface Underlying network interface
00152  **/
00153 
00154 void ar8031EnableIrq(NetInterface *interface)
00155 {
00156    //Enable PHY transceiver interrupts
00157    if(interface->extIntDriver != NULL)
00158       interface->extIntDriver->enableIrq();
00159 }
00160 
00161 
00162 /**
00163  * @brief Disable interrupts
00164  * @param[in] interface Underlying network interface
00165  **/
00166 
00167 void ar8031DisableIrq(NetInterface *interface)
00168 {
00169    //Disable PHY transceiver interrupts
00170    if(interface->extIntDriver != NULL)
00171       interface->extIntDriver->disableIrq();
00172 }
00173 
00174 
00175 /**
00176  * @brief AR8031 event handler
00177  * @param[in] interface Underlying network interface
00178  **/
00179 
00180 void ar8031EventHandler(NetInterface *interface)
00181 {
00182    uint16_t status;
00183 
00184    //Read status register to acknowledge the interrupt
00185    status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_INT_STATUS);
00186 
00187    //Link status change?
00188    if(status & (INT_STATUS_LINK_FAIL | INT_STATUS_LINK_SUCCESS))
00189    {
00190       //Read PHY status register
00191       status = ar8031ReadPhyReg(interface, AR8031_PHY_REG_PHY_STATUS);
00192 
00193       //Link is up?
00194       if(status & PHY_STATUS_LINK)
00195       {
00196          //Check current speed
00197          switch(status & PHY_STATUS_SPEED_MASK)
00198          {
00199          //10BASE-T
00200          case PHY_STATUS_SPEED_10:
00201             interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
00202             break;
00203          //100BASE-TX
00204          case PHY_STATUS_SPEED_100:
00205             interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
00206             break;
00207          //1000BASE-T
00208          case PHY_STATUS_SPEED_1000:
00209             interface->linkSpeed = NIC_LINK_SPEED_1GBPS;
00210             break;
00211          //Unknown speed
00212          default:
00213             //Debug message
00214             TRACE_WARNING("Invalid speed\r\n");
00215             break;
00216          }
00217 
00218          //Check current duplex mode
00219          if(status & PHY_STATUS_DUPLEX)
00220             interface->duplexMode = NIC_FULL_DUPLEX_MODE;
00221          else
00222             interface->duplexMode = NIC_HALF_DUPLEX_MODE;
00223 
00224          //Update link state
00225          interface->linkState = TRUE;
00226 
00227          //Adjust MAC configuration parameters for proper operation
00228          interface->nicDriver->updateMacConfig(interface);
00229       }
00230       else
00231       {
00232          //Update link state
00233          interface->linkState = FALSE;
00234       }
00235 
00236       //Process link state change event
00237       nicNotifyLinkChange(interface);
00238    }
00239 }
00240 
00241 
00242 /**
00243  * @brief Write PHY register
00244  * @param[in] interface Underlying network interface
00245  * @param[in] address PHY register address
00246  * @param[in] data Register value
00247  **/
00248 
00249 void ar8031WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
00250 {
00251    uint8_t phyAddr;
00252 
00253    //Get the address of the PHY transceiver
00254    if(interface->phyAddr < 32)
00255       phyAddr = interface->phyAddr;
00256    else
00257       phyAddr = AR8031_PHY_ADDR;
00258 
00259    //Write the specified PHY register
00260    interface->nicDriver->writePhyReg(phyAddr, address, data);
00261 }
00262 
00263 
00264 /**
00265  * @brief Read PHY register
00266  * @param[in] interface Underlying network interface
00267  * @param[in] address PHY register address
00268  * @return Register value
00269  **/
00270 
00271 uint16_t ar8031ReadPhyReg(NetInterface *interface, uint8_t address)
00272 {
00273    uint8_t phyAddr;
00274 
00275    //Get the address of the PHY transceiver
00276    if(interface->phyAddr < 32)
00277       phyAddr = interface->phyAddr;
00278    else
00279       phyAddr = AR8031_PHY_ADDR;
00280 
00281    //Read the specified PHY register
00282    return interface->nicDriver->readPhyReg(phyAddr, address);
00283 }
00284 
00285 
00286 /**
00287  * @brief Dump PHY registers for debugging purpose
00288  * @param[in] interface Underlying network interface
00289  **/
00290 
00291 void ar8031DumpPhyReg(NetInterface *interface)
00292 {
00293    uint8_t i;
00294 
00295    //Loop through PHY registers
00296    for(i = 0; i < 32; i++)
00297    {
00298       //Display current PHY register
00299       TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, ar8031ReadPhyReg(interface, i));
00300    }
00301 
00302    //Terminate with a line feed
00303    TRACE_DEBUG("\r\n");
00304 }
00305