Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ksz8031.c
Go to the documentation of this file.
00001 /** 00002 * @file ksz8031.c 00003 * @brief KSZ8031 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/ksz8031.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief KSZ8031 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver ksz8031PhyDriver = 00043 { 00044 ksz8031Init, 00045 ksz8031Tick, 00046 ksz8031EnableIrq, 00047 ksz8031DisableIrq, 00048 ksz8031EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief KSZ8031 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t ksz8031Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing KSZ8031...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver 00068 ksz8031WritePhyReg(interface, KSZ8031_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(ksz8031ReadPhyReg(interface, KSZ8031_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Dump PHY registers for debugging purpose 00073 ksz8031DumpPhyReg(interface); 00074 00075 //The PHY will generate interrupts when link status changes are detected 00076 ksz8031WritePhyReg(interface, KSZ8031_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 KSZ8031 timer handler 00090 * @param[in] interface Underlying network interface 00091 **/ 00092 00093 void ksz8031Tick(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 = ksz8031ReadPhyReg(interface, KSZ8031_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 ksz8031EnableIrq(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 ksz8031DisableIrq(NetInterface *interface) 00145 { 00146 //Disable PHY transceiver interrupts 00147 if(interface->extIntDriver != NULL) 00148 interface->extIntDriver->disableIrq(); 00149 } 00150 00151 00152 /** 00153 * @brief KSZ8031 event handler 00154 * @param[in] interface Underlying network interface 00155 **/ 00156 00157 void ksz8031EventHandler(NetInterface *interface) 00158 { 00159 uint16_t value; 00160 00161 //Read status register to acknowledge the interrupt 00162 value = ksz8031ReadPhyReg(interface, KSZ8031_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 = ksz8031ReadPhyReg(interface, KSZ8031_PHY_REG_BMSR); 00170 value = ksz8031ReadPhyReg(interface, KSZ8031_PHY_REG_BMSR); 00171 00172 //Link is up? 00173 if(value & BMSR_LINK_STATUS) 00174 { 00175 //Read PHY control register 00176 value = ksz8031ReadPhyReg(interface, KSZ8031_PHY_REG_PHYCON1); 00177 00178 //Check current operation mode 00179 switch(value & PHYCON1_OP_MODE_MASK) 00180 { 00181 //10BASE-T 00182 case PHYCON1_OP_MODE_10BT: 00183 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00184 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00185 break; 00186 //10BASE-T full-duplex 00187 case PHYCON1_OP_MODE_10BT_FD: 00188 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00189 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00190 break; 00191 //100BASE-TX 00192 case PHYCON1_OP_MODE_100BTX: 00193 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00194 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00195 break; 00196 //100BASE-TX full-duplex 00197 case PHYCON1_OP_MODE_100BTX_FD: 00198 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00199 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00200 break; 00201 //Unknown operation mode 00202 default: 00203 //Debug message 00204 TRACE_WARNING("Invalid Duplex mode\r\n"); 00205 break; 00206 } 00207 00208 //Update link state 00209 interface->linkState = TRUE; 00210 00211 //Adjust MAC configuration parameters for proper operation 00212 interface->nicDriver->updateMacConfig(interface); 00213 } 00214 else 00215 { 00216 //Update link state 00217 interface->linkState = FALSE; 00218 } 00219 00220 //Process link state change event 00221 nicNotifyLinkChange(interface); 00222 } 00223 } 00224 00225 00226 /** 00227 * @brief Write PHY register 00228 * @param[in] interface Underlying network interface 00229 * @param[in] address PHY register address 00230 * @param[in] data Register value 00231 **/ 00232 00233 void ksz8031WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00234 { 00235 uint8_t phyAddr; 00236 00237 //Get the address of the PHY transceiver 00238 if(interface->phyAddr < 32) 00239 phyAddr = interface->phyAddr; 00240 else 00241 phyAddr = KSZ8031_PHY_ADDR; 00242 00243 //Write the specified PHY register 00244 interface->nicDriver->writePhyReg(phyAddr, address, data); 00245 } 00246 00247 00248 /** 00249 * @brief Read PHY register 00250 * @param[in] interface Underlying network interface 00251 * @param[in] address PHY register address 00252 * @return Register value 00253 **/ 00254 00255 uint16_t ksz8031ReadPhyReg(NetInterface *interface, uint8_t address) 00256 { 00257 uint8_t phyAddr; 00258 00259 //Get the address of the PHY transceiver 00260 if(interface->phyAddr < 32) 00261 phyAddr = interface->phyAddr; 00262 else 00263 phyAddr = KSZ8031_PHY_ADDR; 00264 00265 //Read the specified PHY register 00266 return interface->nicDriver->readPhyReg(phyAddr, address); 00267 } 00268 00269 00270 /** 00271 * @brief Dump PHY registers for debugging purpose 00272 * @param[in] interface Underlying network interface 00273 **/ 00274 00275 void ksz8031DumpPhyReg(NetInterface *interface) 00276 { 00277 uint8_t i; 00278 00279 //Loop through PHY registers 00280 for(i = 0; i < 32; i++) 00281 { 00282 //Display current PHY register 00283 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, ksz8031ReadPhyReg(interface, i)); 00284 } 00285 00286 //Terminate with a line feed 00287 TRACE_DEBUG("\r\n"); 00288 } 00289
Generated on Tue Jul 12 2022 17:10:14 by
