Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ksz9031.c
Go to the documentation of this file.
00001 /** 00002 * @file ksz9031.c 00003 * @brief KSZ9031 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/ksz9031.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief KSZ9031 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver ksz9031PhyDriver = 00043 { 00044 ksz9031Init, 00045 ksz9031Tick, 00046 ksz9031EnableIrq, 00047 ksz9031DisableIrq, 00048 ksz9031EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief KSZ9031 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t ksz9031Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing KSZ9031...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver 00068 ksz9031WritePhyReg(interface, KSZ9031_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Dump PHY registers for debugging purpose 00073 ksz9031DumpPhyReg(interface); 00074 00075 //The PHY will generate interrupts when link status changes are detected 00076 ksz9031WritePhyReg(interface, KSZ9031_PHY_REG_ICSR, ICSR_LINK_DOWN_IE | ICSR_LINK_UP_IE); 00077 00078 //Force the TCP/IP stack to poll the link state at startup 00079 interface->phyEvent = TRUE; 00080 //Notify the TCP/IP stack of the event 00081 osSetEvent(&netEvent); 00082 00083 //Successful initialization 00084 return NO_ERROR; 00085 } 00086 00087 00088 /** 00089 * @brief KSZ9031 timer handler 00090 * @param[in] interface Underlying network interface 00091 **/ 00092 00093 void ksz9031Tick(NetInterface *interface) 00094 { 00095 uint16_t value; 00096 bool_t linkState; 00097 00098 //No external interrupt line driver? 00099 if(interface->extIntDriver == NULL) 00100 { 00101 //Read basic status register 00102 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMSR); 00103 //Retrieve current link state 00104 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE; 00105 00106 //Link up event? 00107 if(linkState && !interface->linkState) 00108 { 00109 //Set event flag 00110 interface->phyEvent = TRUE; 00111 //Notify the TCP/IP stack of the event 00112 osSetEvent(&netEvent); 00113 } 00114 //Link down event? 00115 else if(!linkState && interface->linkState) 00116 { 00117 //Set event flag 00118 interface->phyEvent = TRUE; 00119 //Notify the TCP/IP stack of the event 00120 osSetEvent(&netEvent); 00121 } 00122 } 00123 } 00124 00125 00126 /** 00127 * @brief Enable interrupts 00128 * @param[in] interface Underlying network interface 00129 **/ 00130 00131 void ksz9031EnableIrq(NetInterface *interface) 00132 { 00133 //Enable PHY transceiver interrupts 00134 if(interface->extIntDriver != NULL) 00135 interface->extIntDriver->enableIrq(); 00136 } 00137 00138 00139 /** 00140 * @brief Disable interrupts 00141 * @param[in] interface Underlying network interface 00142 **/ 00143 00144 void ksz9031DisableIrq(NetInterface *interface) 00145 { 00146 //Disable PHY transceiver interrupts 00147 if(interface->extIntDriver != NULL) 00148 interface->extIntDriver->disableIrq(); 00149 } 00150 00151 00152 /** 00153 * @brief KSZ9031 event handler 00154 * @param[in] interface Underlying network interface 00155 **/ 00156 00157 void ksz9031EventHandler(NetInterface *interface) 00158 { 00159 uint16_t value; 00160 00161 //Read status register to acknowledge the interrupt 00162 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_ICSR); 00163 00164 //Link status change? 00165 if(value & (ICSR_LINK_DOWN_IF | ICSR_LINK_UP_IF)) 00166 { 00167 //Any link failure condition is latched in the BMSR register... Reading 00168 //the register twice will always return the actual link status 00169 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMSR); 00170 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMSR); 00171 00172 //Link is up? 00173 if(value & BMSR_LINK_STATUS) 00174 { 00175 //Read PHY control register 00176 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_PHYCON); 00177 00178 //Check current speed 00179 if(value & PHYCON_SPEED_1000BT) 00180 { 00181 //1000BASE-T 00182 interface->linkSpeed = NIC_LINK_SPEED_1GBPS; 00183 } 00184 else if(value & PHYCON_SPEED_100BTX) 00185 { 00186 //100BASE-TX 00187 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00188 } 00189 else if(value & PHYCON_SPEED_10BT) 00190 { 00191 //10BASE-T 00192 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00193 } 00194 else 00195 { 00196 //Debug message 00197 TRACE_WARNING("Invalid speed!\r\n"); 00198 } 00199 00200 //Check current duplex mode 00201 if(value & PHYCON_DUPLEX_STATUS) 00202 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00203 else 00204 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00205 00206 //Update link state 00207 interface->linkState = TRUE; 00208 00209 //Adjust MAC configuration parameters for proper operation 00210 interface->nicDriver->updateMacConfig(interface); 00211 } 00212 else 00213 { 00214 //Update link state 00215 interface->linkState = FALSE; 00216 } 00217 00218 //Process link state change event 00219 nicNotifyLinkChange(interface); 00220 } 00221 } 00222 00223 00224 /** 00225 * @brief Write PHY register 00226 * @param[in] interface Underlying network interface 00227 * @param[in] address PHY register address 00228 * @param[in] data Register value 00229 **/ 00230 00231 void ksz9031WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00232 { 00233 uint8_t phyAddr; 00234 00235 //Get the address of the PHY transceiver 00236 if(interface->phyAddr < 32) 00237 phyAddr = interface->phyAddr; 00238 else 00239 phyAddr = KSZ9031_PHY_ADDR; 00240 00241 //Write the specified PHY register 00242 interface->nicDriver->writePhyReg(phyAddr, address, data); 00243 } 00244 00245 00246 /** 00247 * @brief Read PHY register 00248 * @param[in] interface Underlying network interface 00249 * @param[in] address PHY register address 00250 * @return Register value 00251 **/ 00252 00253 uint16_t ksz9031ReadPhyReg(NetInterface *interface, uint8_t address) 00254 { 00255 uint8_t phyAddr; 00256 00257 //Get the address of the PHY transceiver 00258 if(interface->phyAddr < 32) 00259 phyAddr = interface->phyAddr; 00260 else 00261 phyAddr = KSZ9031_PHY_ADDR; 00262 00263 //Read the specified PHY register 00264 return interface->nicDriver->readPhyReg(phyAddr, address); 00265 } 00266 00267 00268 /** 00269 * @brief Dump PHY registers for debugging purpose 00270 * @param[in] interface Underlying network interface 00271 **/ 00272 00273 void ksz9031DumpPhyReg(NetInterface *interface) 00274 { 00275 uint8_t i; 00276 00277 //Loop through PHY registers 00278 for(i = 0; i < 32; i++) 00279 { 00280 //Display current PHY register 00281 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, ksz9031ReadPhyReg(interface, i)); 00282 } 00283 00284 //Terminate with a line feed 00285 TRACE_DEBUG("\r\n"); 00286 } 00287
Generated on Tue Jul 12 2022 17:10:14 by
