Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:10:12 by
