1 /******************************************************************************/
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom */
5 /* All rights reserved. */
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. */
12 /******************************************************************************/
14 #ifdef INCLUDE_TBI_SUPPORT
19 /******************************************************************************/
23 /******************************************************************************/
26 PAN_STATE_INFO pAnInfo)
28 PLM_DEVICE_BLOCK pDevice;
30 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
32 REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT);
34 pDevice->MacMode |= MAC_MODE_SEND_CONFIGS;
35 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
40 /******************************************************************************/
44 /******************************************************************************/
47 PAN_STATE_INFO pAnInfo)
49 PLM_DEVICE_BLOCK pDevice;
51 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
53 pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS;
54 REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode);
59 /******************************************************************************/
63 /******************************************************************************/
66 PAN_STATE_INFO pAnInfo,
67 unsigned short *pRxConfig)
69 PLM_DEVICE_BLOCK pDevice;
75 pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext;
77 Value32 = REG_RD(pDevice, MacCtrl.Status);
78 if(Value32 & MAC_STATUS_RECEIVING_CFG)
80 Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg);
81 *pRxConfig = (unsigned short) Value32;
91 /******************************************************************************/
95 /******************************************************************************/
98 PAN_STATE_INFO pAnInfo)
102 for(j = 0; j < sizeof(AN_STATE_INFO); j++)
104 ((unsigned char *) pAnInfo)[j] = 0;
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;
116 /******************************************************************************/
120 /******************************************************************************/
123 PAN_STATE_INFO pAnInfo)
125 unsigned short RxConfig;
126 unsigned long Delta_us;
127 AUTONEG_STATUS AnRet;
129 /* Get the current time. */
130 if(pAnInfo->State == AN_STATE_UNKNOWN)
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;
142 /* Increment the timer tick. This function is called every microsecon. */
143 // pAnInfo->CurrentTime_us++;
145 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
146 /* corresponding conditions are satisfied. */
147 if(MM_AnRxConfig(pAnInfo, &RxConfig))
149 if(RxConfig != pAnInfo->AbilityMatchCfg)
151 pAnInfo->AbilityMatchCfg = RxConfig;
152 pAnInfo->AbilityMatch = AN_FALSE;
153 pAnInfo->AbilityMatchCnt = 0;
157 pAnInfo->AbilityMatchCnt++;
158 if(pAnInfo->AbilityMatchCnt > 1)
160 pAnInfo->AbilityMatch = AN_TRUE;
161 pAnInfo->AbilityMatchCfg = RxConfig;
165 if(RxConfig & AN_CONFIG_ACK)
167 pAnInfo->AckMatch = AN_TRUE;
171 pAnInfo->AckMatch = AN_FALSE;
174 pAnInfo->IdleMatch = AN_FALSE;
178 pAnInfo->IdleMatch = AN_TRUE;
180 pAnInfo->AbilityMatchCfg = 0;
181 pAnInfo->AbilityMatchCnt = 0;
182 pAnInfo->AbilityMatch = AN_FALSE;
183 pAnInfo->AckMatch = AN_FALSE;
188 /* Save the last Config. */
189 pAnInfo->RxConfig.AsUSHORT = RxConfig;
191 /* Default return code. */
192 AnRet = AUTONEG_STATUS_OK;
194 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
195 switch(pAnInfo->State)
197 case AN_STATE_UNKNOWN:
198 if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an)
200 pAnInfo->CurrentTime_us = 0;
201 pAnInfo->State = AN_STATE_AN_ENABLE;
206 case AN_STATE_AN_ENABLE:
207 pAnInfo->mr_an_complete = AN_FALSE;
208 pAnInfo->mr_page_rx = AN_FALSE;
210 if(pAnInfo->mr_an_enable)
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;
219 pAnInfo->State = AN_STATE_AN_RESTART_INIT;
223 pAnInfo->State = AN_STATE_DISABLE_LINK_OK;
227 case AN_STATE_AN_RESTART_INIT:
228 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
229 pAnInfo->mr_np_loaded = AN_FALSE;
231 pAnInfo->TxConfig.AsUSHORT = 0;
232 MM_AnTxConfig(pAnInfo);
234 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
236 pAnInfo->State = AN_STATE_AN_RESTART;
240 case AN_STATE_AN_RESTART:
241 /* Get the current time and compute the delta with the saved */
243 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
244 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
246 pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT;
250 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
254 case AN_STATE_DISABLE_LINK_OK:
255 AnRet = AUTONEG_STATUS_DONE;
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;
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;
273 MM_AnTxConfig(pAnInfo);
275 pAnInfo->State = AN_STATE_ABILITY_DETECT;
279 case AN_STATE_ABILITY_DETECT:
280 if(pAnInfo->AbilityMatch == AN_TRUE &&
281 pAnInfo->RxConfig.AsUSHORT != 0)
283 pAnInfo->State = AN_STATE_ACK_DETECT_INIT;
288 case AN_STATE_ACK_DETECT_INIT:
289 pAnInfo->TxConfig.D14_ACK = 1;
290 MM_AnTxConfig(pAnInfo);
292 pAnInfo->State = AN_STATE_ACK_DETECT;
296 case AN_STATE_ACK_DETECT:
297 if(pAnInfo->AckMatch == AN_TRUE)
299 if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) ==
300 (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK))
302 pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT;
306 pAnInfo->State = AN_STATE_AN_ENABLE;
309 else if(pAnInfo->AbilityMatch == AN_TRUE &&
310 pAnInfo->RxConfig.AsUSHORT == 0)
312 pAnInfo->State = AN_STATE_AN_ENABLE;
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)
324 AnRet = AUTONEG_STATUS_FAILED;
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;
337 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
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;
344 pAnInfo->State = AN_STATE_COMPLETE_ACK;
345 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
349 case AN_STATE_COMPLETE_ACK:
350 if(pAnInfo->AbilityMatch == AN_TRUE &&
351 pAnInfo->RxConfig.AsUSHORT == 0)
353 pAnInfo->State = AN_STATE_AN_ENABLE;
357 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
359 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
361 if(pAnInfo->mr_adv_next_page == 0 ||
362 pAnInfo->mr_lp_adv_next_page == 0)
364 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
368 if(pAnInfo->TxConfig.bits.D15 == 0 &&
369 pAnInfo->mr_np_rx == 0)
371 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
375 AnRet = AUTONEG_STATUS_FAILED;
382 case AN_STATE_IDLE_DETECT_INIT:
383 pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us;
385 MM_AnTxIdle(pAnInfo);
387 pAnInfo->State = AN_STATE_IDLE_DETECT;
389 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
393 case AN_STATE_IDLE_DETECT:
394 if(pAnInfo->AbilityMatch == AN_TRUE &&
395 pAnInfo->RxConfig.AsUSHORT == 0)
397 pAnInfo->State = AN_STATE_AN_ENABLE;
401 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
402 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
404 // if(pAnInfo->IdleMatch == AN_TRUE)
406 pAnInfo->State = AN_STATE_LINK_OK;
410 // AnRet = AUTONEG_STATUS_FAILED;
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;
424 case AN_STATE_NEXT_PAGE_WAIT_INIT:
427 case AN_STATE_NEXT_PAGE_WAIT:
431 AnRet = AUTONEG_STATUS_FAILED;
437 #endif /* INCLUDE_TBI_SUPPORT */