Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dm9161.c
00001 /** 00002 * @file dm9161.c 00003 * @brief DM9161 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/dm9161.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief DM9161 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver dm9161PhyDriver = 00043 { 00044 dm9161Init, 00045 dm9161Tick, 00046 dm9161EnableIrq, 00047 dm9161DisableIrq, 00048 dm9161EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief DM9161 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t dm9161Init(NetInterface *interface) 00059 { 00060 volatile uint32_t status; 00061 00062 //Debug message 00063 TRACE_INFO("Initializing DM9161...\r\n"); 00064 00065 //Initialize external interrupt line driver 00066 if(interface->extIntDriver != NULL) 00067 interface->extIntDriver->init(); 00068 00069 //Reset PHY transceiver 00070 dm9161WritePhyReg(interface, DM9161_PHY_REG_BMCR, BMCR_RESET); 00071 //Wait for the reset to complete 00072 while(dm9161ReadPhyReg(interface, DM9161_PHY_REG_BMCR) & BMCR_RESET); 00073 00074 //Dump PHY registers for debugging purpose 00075 dm9161DumpPhyReg(interface); 00076 00077 //The PHY will generate interrupts when link status changes are detected 00078 dm9161WritePhyReg(interface, DM9161_PHY_REG_MDINTR, ~(MDINTR_LINK_MASK | MDINTR_INTR_MASK)); 00079 00080 //Force the TCP/IP stack to poll the link state at startup 00081 interface->phyEvent = TRUE; 00082 //Notify the TCP/IP stack of the event 00083 osSetEvent(&netEvent); 00084 00085 //Successful initialization 00086 return NO_ERROR; 00087 } 00088 00089 00090 /** 00091 * @brief DM9161 timer handler 00092 * @param[in] interface Underlying network interface 00093 **/ 00094 00095 void dm9161Tick(NetInterface *interface) 00096 { 00097 uint16_t value; 00098 bool_t linkState; 00099 00100 //No external interrupt line driver? 00101 if(interface->extIntDriver == NULL) 00102 { 00103 //Read basic status register 00104 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_BMSR); 00105 //Retrieve current link state 00106 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE; 00107 00108 //Link up event? 00109 if(linkState && !interface->linkState) 00110 { 00111 //Set event flag 00112 interface->phyEvent = TRUE; 00113 //Notify the TCP/IP stack of the event 00114 osSetEvent(&netEvent); 00115 } 00116 //Link down event? 00117 else if(!linkState && interface->linkState) 00118 { 00119 //Set event flag 00120 interface->phyEvent = TRUE; 00121 //Notify the TCP/IP stack of the event 00122 osSetEvent(&netEvent); 00123 } 00124 } 00125 } 00126 00127 00128 /** 00129 * @brief Enable interrupts 00130 * @param[in] interface Underlying network interface 00131 **/ 00132 00133 void dm9161EnableIrq(NetInterface *interface) 00134 { 00135 //Enable PHY transceiver interrupts 00136 if(interface->extIntDriver != NULL) 00137 interface->extIntDriver->enableIrq(); 00138 } 00139 00140 00141 /** 00142 * @brief Disable interrupts 00143 * @param[in] interface Underlying network interface 00144 **/ 00145 00146 void dm9161DisableIrq(NetInterface *interface) 00147 { 00148 //Disable PHY transceiver interrupts 00149 if(interface->extIntDriver != NULL) 00150 interface->extIntDriver->disableIrq(); 00151 } 00152 00153 00154 /** 00155 * @brief DM9161 event handler 00156 * @param[in] interface Underlying network interface 00157 **/ 00158 00159 void dm9161EventHandler(NetInterface *interface) 00160 { 00161 uint16_t value; 00162 bool_t end; 00163 00164 //Read status register to acknowledge the interrupt 00165 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_MDINTR); 00166 00167 //Link status change? 00168 if(value & MDINTR_LINK_CHANGE) 00169 { 00170 //Any link failure condition is latched in the BMSR register... Reading 00171 //the register twice will always return the actual link status 00172 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_BMSR); 00173 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_BMSR); 00174 00175 //Link is up? 00176 if(value & BMSR_LINK_STATUS) 00177 { 00178 //Wait for the auto-negotiation to complete 00179 do 00180 { 00181 //Read DSCSR register 00182 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_DSCSR); 00183 00184 //Check current state 00185 switch(value & DSCSR_ANMB_MASK) 00186 { 00187 //Auto-negotiation is still in progress? 00188 case DSCSR_ANMB_ABILITY_MATCH: 00189 case DSCSR_ANMB_ACK_MATCH: 00190 case DSCSR_ANMB_CONSIST_MATCH: 00191 case DSCSR_ANMB_SIGNAL_LINK_READY: 00192 end = FALSE; 00193 break; 00194 //Auto-negotiation is complete? 00195 default: 00196 end = TRUE; 00197 break; 00198 } 00199 00200 //Check loop condition variable 00201 } while(!end); 00202 00203 //Read DSCSR register 00204 value = dm9161ReadPhyReg(interface, DM9161_PHY_REG_DSCSR); 00205 00206 //Check current operation mode 00207 if(value & DSCSR_10HDX) 00208 { 00209 //10BASE-T half-duplex 00210 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00211 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00212 } 00213 else if(value & DSCSR_10FDX) 00214 { 00215 //10BASE-T full-duplex 00216 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00217 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00218 } 00219 else if(value & DSCSR_100HDX) 00220 { 00221 //100BASE-TX half-duplex 00222 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00223 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00224 } 00225 else if(value & DSCSR_100FDX) 00226 { 00227 //100BASE-TX full-duplex 00228 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00229 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00230 } 00231 else 00232 { 00233 //Debug message 00234 TRACE_WARNING("Invalid Duplex mode\r\n"); 00235 } 00236 00237 //Update link state 00238 interface->linkState = TRUE; 00239 00240 //Adjust MAC configuration parameters for proper operation 00241 interface->nicDriver->updateMacConfig(interface); 00242 } 00243 else 00244 { 00245 //Update link state 00246 interface->linkState = FALSE; 00247 } 00248 00249 //Process link state change event 00250 nicNotifyLinkChange(interface); 00251 } 00252 } 00253 00254 00255 /** 00256 * @brief Write PHY register 00257 * @param[in] interface Underlying network interface 00258 * @param[in] address PHY register address 00259 * @param[in] data Register value 00260 **/ 00261 00262 void dm9161WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00263 { 00264 uint8_t phyAddr; 00265 00266 //Get the address of the PHY transceiver 00267 if(interface->phyAddr < 32) 00268 phyAddr = interface->phyAddr; 00269 else 00270 phyAddr = DM9161_PHY_ADDR; 00271 00272 //Write the specified PHY register 00273 interface->nicDriver->writePhyReg(phyAddr, address, data); 00274 } 00275 00276 00277 /** 00278 * @brief Read PHY register 00279 * @param[in] interface Underlying network interface 00280 * @param[in] address PHY register address 00281 * @return Register value 00282 **/ 00283 00284 uint16_t dm9161ReadPhyReg(NetInterface *interface, uint8_t address) 00285 { 00286 uint8_t phyAddr; 00287 00288 //Get the address of the PHY transceiver 00289 if(interface->phyAddr < 32) 00290 phyAddr = interface->phyAddr; 00291 else 00292 phyAddr = DM9161_PHY_ADDR; 00293 00294 //Read the specified PHY register 00295 return interface->nicDriver->readPhyReg(phyAddr, address); 00296 } 00297 00298 00299 /** 00300 * @brief Dump PHY registers for debugging purpose 00301 * @param[in] interface Underlying network interface 00302 **/ 00303 00304 void dm9161DumpPhyReg(NetInterface *interface) 00305 { 00306 uint8_t i; 00307 00308 //Loop through PHY registers 00309 for(i = 0; i < 32; i++) 00310 { 00311 //Display current PHY register 00312 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, dm9161ReadPhyReg(interface, i)); 00313 } 00314 00315 //Terminate with a line feed 00316 TRACE_DEBUG("\r\n"); 00317 } 00318
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2