1/******************************************************************************/ 2/* */ 3/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom */ 4/* Corporation. */ 5/* All rights reserved. */ 6/* */ 7/* This program is free software; you can redistribute it and/or modify */ 8/* it under the terms of the GNU General Public License as published by */ 9/* the Free Software Foundation, located in the file LICENSE. */ 10/* */ 11/* History: */ 12/******************************************************************************/ 13 14#include <bcm57xx_cfg.h> 15#ifdef INCLUDE_TBI_SUPPORT 16#include "mm.h" 17 18 19 20/******************************************************************************/ 21/* Description: */ 22/* */ 23/* Return: */ 24/******************************************************************************/ 25void 26MM_AnTxConfig( 27 PAN_STATE_INFO pAnInfo) 28{ 29 PLM_DEVICE_BLOCK pDevice; 30 31 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; 32 33 REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT); 34 35 pDevice->MacMode |= MAC_MODE_SEND_CONFIGS; 36 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); 37} 38 39 40 41/******************************************************************************/ 42/* Description: */ 43/* */ 44/* Return: */ 45/******************************************************************************/ 46void 47MM_AnTxIdle( 48 PAN_STATE_INFO pAnInfo) 49{ 50 PLM_DEVICE_BLOCK pDevice; 51 52 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; 53 54 pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS; 55 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); 56} 57 58 59 60/******************************************************************************/ 61/* Description: */ 62/* */ 63/* Return: */ 64/******************************************************************************/ 65char 66MM_AnRxConfig( 67 PAN_STATE_INFO pAnInfo, 68 unsigned short *pRxConfig) 69{ 70 PLM_DEVICE_BLOCK pDevice; 71 LM_UINT32 Value32; 72 char Retcode; 73 74 Retcode = AN_FALSE; 75 76 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; 77 78 Value32 = REG_RD(pDevice, MacCtrl.Status); 79 if(Value32 & MAC_STATUS_RECEIVING_CFG) 80 { 81 Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg); 82 *pRxConfig = (unsigned short) Value32; 83 84 Retcode = AN_TRUE; 85 } 86 87 return Retcode; 88} 89 90 91 92/******************************************************************************/ 93/* Description: */ 94/* */ 95/* Return: */ 96/******************************************************************************/ 97void 98AutonegInit( 99 PAN_STATE_INFO pAnInfo) 100{ 101 unsigned long j; 102 103 for(j = 0; j < sizeof(AN_STATE_INFO); j++) 104 { 105 ((unsigned char *) pAnInfo)[j] = 0; 106 } 107 108 /* Initialize the default advertisement register. */ 109 pAnInfo->mr_adv_full_duplex = 1; 110 pAnInfo->mr_adv_sym_pause = 1; 111 pAnInfo->mr_adv_asym_pause = 1; 112 pAnInfo->mr_an_enable = 1; 113} 114 115 116 117/******************************************************************************/ 118/* Description: */ 119/* */ 120/* Return: */ 121/******************************************************************************/ 122AUTONEG_STATUS 123Autoneg8023z( 124 PAN_STATE_INFO pAnInfo) 125{ 126 unsigned short RxConfig; 127 unsigned long Delta_us; 128 AUTONEG_STATUS AnRet; 129 130 /* Get the current time. */ 131 if(pAnInfo->State == AN_STATE_UNKNOWN) 132 { 133 pAnInfo->RxConfig.AsUSHORT = 0; 134 pAnInfo->CurrentTime_us = 0; 135 pAnInfo->LinkTime_us = 0; 136 pAnInfo->AbilityMatchCfg = 0; 137 pAnInfo->AbilityMatchCnt = 0; 138 pAnInfo->AbilityMatch = AN_FALSE; 139 pAnInfo->IdleMatch = AN_FALSE; 140 pAnInfo->AckMatch = AN_FALSE; 141 } 142 143 /* Increment the timer tick. This function is called every microsecon. */ 144// pAnInfo->CurrentTime_us++; 145 146 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */ 147 /* corresponding conditions are satisfied. */ 148 if(MM_AnRxConfig(pAnInfo, &RxConfig)) 149 { 150 if(RxConfig != pAnInfo->AbilityMatchCfg) 151 { 152 pAnInfo->AbilityMatchCfg = RxConfig; 153 pAnInfo->AbilityMatch = AN_FALSE; 154 pAnInfo->AbilityMatchCnt = 0; 155 } 156 else 157 { 158 pAnInfo->AbilityMatchCnt++; 159 if(pAnInfo->AbilityMatchCnt > 1) 160 { 161 pAnInfo->AbilityMatch = AN_TRUE; 162 pAnInfo->AbilityMatchCfg = RxConfig; 163 } 164 } 165 166 if(RxConfig & AN_CONFIG_ACK) 167 { 168 pAnInfo->AckMatch = AN_TRUE; 169 } 170 else 171 { 172 pAnInfo->AckMatch = AN_FALSE; 173 } 174 175 pAnInfo->IdleMatch = AN_FALSE; 176 } 177 else 178 { 179 pAnInfo->IdleMatch = AN_TRUE; 180 181 pAnInfo->AbilityMatchCfg = 0; 182 pAnInfo->AbilityMatchCnt = 0; 183 pAnInfo->AbilityMatch = AN_FALSE; 184 pAnInfo->AckMatch = AN_FALSE; 185 186 RxConfig = 0; 187 } 188 189 /* Save the last Config. */ 190 pAnInfo->RxConfig.AsUSHORT = RxConfig; 191 192 /* Default return code. */ 193 AnRet = AUTONEG_STATUS_OK; 194 195 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */ 196 switch(pAnInfo->State) 197 { 198 case AN_STATE_UNKNOWN: 199 if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an) 200 { 201 pAnInfo->CurrentTime_us = 0; 202 pAnInfo->State = AN_STATE_AN_ENABLE; 203 } 204 205 /* Fall through.*/ 206 207 case AN_STATE_AN_ENABLE: 208 pAnInfo->mr_an_complete = AN_FALSE; 209 pAnInfo->mr_page_rx = AN_FALSE; 210 211 if(pAnInfo->mr_an_enable) 212 { 213 pAnInfo->LinkTime_us = 0; 214 pAnInfo->AbilityMatchCfg = 0; 215 pAnInfo->AbilityMatchCnt = 0; 216 pAnInfo->AbilityMatch = AN_FALSE; 217 pAnInfo->IdleMatch = AN_FALSE; 218 pAnInfo->AckMatch = AN_FALSE; 219 220 pAnInfo->State = AN_STATE_AN_RESTART_INIT; 221 } 222 else 223 { 224 pAnInfo->State = AN_STATE_DISABLE_LINK_OK; 225 } 226 break; 227 228 case AN_STATE_AN_RESTART_INIT: 229 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; 230 pAnInfo->mr_np_loaded = AN_FALSE; 231 232 pAnInfo->TxConfig.AsUSHORT = 0; 233 MM_AnTxConfig(pAnInfo); 234 235 AnRet = AUTONEG_STATUS_TIMER_ENABLED; 236 237 pAnInfo->State = AN_STATE_AN_RESTART; 238 239 /* Fall through.*/ 240 241 case AN_STATE_AN_RESTART: 242 /* Get the current time and compute the delta with the saved */ 243 /* link timer. */ 244 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; 245 if(Delta_us > AN_LINK_TIMER_INTERVAL_US) 246 { 247 pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT; 248 } 249 else 250 { 251 AnRet = AUTONEG_STATUS_TIMER_ENABLED; 252 } 253 break; 254 255 case AN_STATE_DISABLE_LINK_OK: 256 AnRet = AUTONEG_STATUS_DONE; 257 break; 258 259 case AN_STATE_ABILITY_DETECT_INIT: 260 /* Note: in the state diagram, this variable is set to */ 261 /* mr_adv_ability<12>. Is this right?. */ 262 pAnInfo->mr_toggle_tx = AN_FALSE; 263 264 /* Send the config as advertised in the advertisement register. */ 265 pAnInfo->TxConfig.AsUSHORT = 0; 266 pAnInfo->TxConfig.D5_FD = pAnInfo->mr_adv_full_duplex; 267 pAnInfo->TxConfig.D6_HD = pAnInfo->mr_adv_half_duplex; 268 pAnInfo->TxConfig.D7_PS1 = pAnInfo->mr_adv_sym_pause; 269 pAnInfo->TxConfig.D8_PS2 = pAnInfo->mr_adv_asym_pause; 270 pAnInfo->TxConfig.D12_RF1 = pAnInfo->mr_adv_remote_fault1; 271 pAnInfo->TxConfig.D13_RF2 = pAnInfo->mr_adv_remote_fault2; 272 pAnInfo->TxConfig.D15_NP = pAnInfo->mr_adv_next_page; 273 274 MM_AnTxConfig(pAnInfo); 275 276 pAnInfo->State = AN_STATE_ABILITY_DETECT; 277 278 break; 279 280 case AN_STATE_ABILITY_DETECT: 281 if(pAnInfo->AbilityMatch == AN_TRUE && 282 pAnInfo->RxConfig.AsUSHORT != 0) 283 { 284 pAnInfo->State = AN_STATE_ACK_DETECT_INIT; 285 } 286 287 break; 288 289 case AN_STATE_ACK_DETECT_INIT: 290 pAnInfo->TxConfig.D14_ACK = 1; 291 MM_AnTxConfig(pAnInfo); 292 293 pAnInfo->State = AN_STATE_ACK_DETECT; 294 295 /* Fall through. */ 296 297 case AN_STATE_ACK_DETECT: 298 if(pAnInfo->AckMatch == AN_TRUE) 299 { 300 if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) == 301 (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK)) 302 { 303 pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT; 304 } 305 else 306 { 307 pAnInfo->State = AN_STATE_AN_ENABLE; 308 } 309 } 310 else if(pAnInfo->AbilityMatch == AN_TRUE && 311 pAnInfo->RxConfig.AsUSHORT == 0) 312 { 313 pAnInfo->State = AN_STATE_AN_ENABLE; 314 } 315 316 break; 317 318 case AN_STATE_COMPLETE_ACK_INIT: 319 /* Make sure invalid bits are not set. */ 320 if(pAnInfo->RxConfig.bits.D0 || pAnInfo->RxConfig.bits.D1 || 321 pAnInfo->RxConfig.bits.D2 || pAnInfo->RxConfig.bits.D3 || 322 pAnInfo->RxConfig.bits.D4 || pAnInfo->RxConfig.bits.D9 || 323 pAnInfo->RxConfig.bits.D10 || pAnInfo->RxConfig.bits.D11) 324 { 325 AnRet = AUTONEG_STATUS_FAILED; 326 break; 327 } 328 329 /* Set up the link partner advertisement register. */ 330 pAnInfo->mr_lp_adv_full_duplex = pAnInfo->RxConfig.D5_FD; 331 pAnInfo->mr_lp_adv_half_duplex = pAnInfo->RxConfig.D6_HD; 332 pAnInfo->mr_lp_adv_sym_pause = pAnInfo->RxConfig.D7_PS1; 333 pAnInfo->mr_lp_adv_asym_pause = pAnInfo->RxConfig.D8_PS2; 334 pAnInfo->mr_lp_adv_remote_fault1 = pAnInfo->RxConfig.D12_RF1; 335 pAnInfo->mr_lp_adv_remote_fault2 = pAnInfo->RxConfig.D13_RF2; 336 pAnInfo->mr_lp_adv_next_page = pAnInfo->RxConfig.D15_NP; 337 338 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; 339 340 pAnInfo->mr_toggle_tx = !pAnInfo->mr_toggle_tx; 341 pAnInfo->mr_toggle_rx = pAnInfo->RxConfig.bits.D11; 342 pAnInfo->mr_np_rx = pAnInfo->RxConfig.D15_NP; 343 pAnInfo->mr_page_rx = AN_TRUE; 344 345 pAnInfo->State = AN_STATE_COMPLETE_ACK; 346 AnRet = AUTONEG_STATUS_TIMER_ENABLED; 347 348 break; 349 350 case AN_STATE_COMPLETE_ACK: 351 if(pAnInfo->AbilityMatch == AN_TRUE && 352 pAnInfo->RxConfig.AsUSHORT == 0) 353 { 354 pAnInfo->State = AN_STATE_AN_ENABLE; 355 break; 356 } 357 358 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; 359 360 if(Delta_us > AN_LINK_TIMER_INTERVAL_US) 361 { 362 if(pAnInfo->mr_adv_next_page == 0 || 363 pAnInfo->mr_lp_adv_next_page == 0) 364 { 365 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; 366 } 367 else 368 { 369 if(pAnInfo->TxConfig.bits.D15 == 0 && 370 pAnInfo->mr_np_rx == 0) 371 { 372 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; 373 } 374 else 375 { 376 AnRet = AUTONEG_STATUS_FAILED; 377 } 378 } 379 } 380 381 break; 382 383 case AN_STATE_IDLE_DETECT_INIT: 384 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; 385 386 MM_AnTxIdle(pAnInfo); 387 388 pAnInfo->State = AN_STATE_IDLE_DETECT; 389 390 AnRet = AUTONEG_STATUS_TIMER_ENABLED; 391 392 break; 393 394 case AN_STATE_IDLE_DETECT: 395 if(pAnInfo->AbilityMatch == AN_TRUE && 396 pAnInfo->RxConfig.AsUSHORT == 0) 397 { 398 pAnInfo->State = AN_STATE_AN_ENABLE; 399 break; 400 } 401 402 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; 403 if(Delta_us > AN_LINK_TIMER_INTERVAL_US) 404 { 405// if(pAnInfo->IdleMatch == AN_TRUE) 406// { 407 pAnInfo->State = AN_STATE_LINK_OK; 408// } 409// else 410// { 411// AnRet = AUTONEG_STATUS_FAILED; 412// break; 413// } 414 } 415 416 break; 417 418 case AN_STATE_LINK_OK: 419 pAnInfo->mr_an_complete = AN_TRUE; 420 pAnInfo->mr_link_ok = AN_TRUE; 421 AnRet = AUTONEG_STATUS_DONE; 422 423 break; 424 425 case AN_STATE_NEXT_PAGE_WAIT_INIT: 426 break; 427 428 case AN_STATE_NEXT_PAGE_WAIT: 429 break; 430 431 default: 432 AnRet = AUTONEG_STATUS_FAILED; 433 break; 434 } 435 436 return AnRet; 437} 438#endif /* INCLUDE_TBI_SUPPORT */ 439