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