Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
dm9161.c
Go to the documentation of this file.
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
