SSID: Respect ASCII character Label.
[tomato.git] / release / src-rt / bcm57xx / sys / autoneg.c
blobf9145cb296d420fa65c67762550dd5014dc3ccca
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 /******************************************************************************/
14 #ifdef INCLUDE_TBI_SUPPORT
15 #include "mm.h"
19 /******************************************************************************/
20 /* Description: */
21 /* */
22 /* Return: */
23 /******************************************************************************/
24 void
25 MM_AnTxConfig(
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 /******************************************************************************/
41 /* Description: */
42 /* */
43 /* Return: */
44 /******************************************************************************/
45 void
46 MM_AnTxIdle(
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 /******************************************************************************/
60 /* Description: */
61 /* */
62 /* Return: */
63 /******************************************************************************/
64 char
65 MM_AnRxConfig(
66 PAN_STATE_INFO pAnInfo,
67 unsigned short *pRxConfig)
69 PLM_DEVICE_BLOCK pDevice;
70 LM_UINT32 Value32;
71 char Retcode;
73 Retcode = AN_FALSE;
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;
83 Retcode = AN_TRUE;
86 return Retcode;
91 /******************************************************************************/
92 /* Description: */
93 /* */
94 /* Return: */
95 /******************************************************************************/
96 void
97 AutonegInit(
98 PAN_STATE_INFO pAnInfo)
100 unsigned long j;
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 /******************************************************************************/
117 /* Description: */
118 /* */
119 /* Return: */
120 /******************************************************************************/
121 AUTONEG_STATUS
122 Autoneg8023z(
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;
155 else
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;
169 else
171 pAnInfo->AckMatch = AN_FALSE;
174 pAnInfo->IdleMatch = AN_FALSE;
176 else
178 pAnInfo->IdleMatch = AN_TRUE;
180 pAnInfo->AbilityMatchCfg = 0;
181 pAnInfo->AbilityMatchCnt = 0;
182 pAnInfo->AbilityMatch = AN_FALSE;
183 pAnInfo->AckMatch = AN_FALSE;
185 RxConfig = 0;
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;
204 /* Fall through.*/
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;
221 else
223 pAnInfo->State = AN_STATE_DISABLE_LINK_OK;
225 break;
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;
238 /* Fall through.*/
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)
246 pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT;
248 else
250 AnRet = AUTONEG_STATUS_TIMER_ENABLED;
252 break;
254 case AN_STATE_DISABLE_LINK_OK:
255 AnRet = AUTONEG_STATUS_DONE;
256 break;
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;
277 break;
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;
286 break;
288 case AN_STATE_ACK_DETECT_INIT:
289 pAnInfo->TxConfig.D14_ACK = 1;
290 MM_AnTxConfig(pAnInfo);
292 pAnInfo->State = AN_STATE_ACK_DETECT;
294 /* Fall through. */
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;
304 else
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;
315 break;
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;
325 break;
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;
347 break;
349 case AN_STATE_COMPLETE_ACK:
350 if(pAnInfo->AbilityMatch == AN_TRUE &&
351 pAnInfo->RxConfig.AsUSHORT == 0)
353 pAnInfo->State = AN_STATE_AN_ENABLE;
354 break;
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;
366 else
368 if(pAnInfo->TxConfig.bits.D15 == 0 &&
369 pAnInfo->mr_np_rx == 0)
371 pAnInfo->State = AN_STATE_IDLE_DETECT_INIT;
373 else
375 AnRet = AUTONEG_STATUS_FAILED;
380 break;
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;
391 break;
393 case AN_STATE_IDLE_DETECT:
394 if(pAnInfo->AbilityMatch == AN_TRUE &&
395 pAnInfo->RxConfig.AsUSHORT == 0)
397 pAnInfo->State = AN_STATE_AN_ENABLE;
398 break;
401 Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us;
402 if(Delta_us > AN_LINK_TIMER_INTERVAL_US)
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 // }
415 break;
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;
422 break;
424 case AN_STATE_NEXT_PAGE_WAIT_INIT:
425 break;
427 case AN_STATE_NEXT_PAGE_WAIT:
428 break;
430 default:
431 AnRet = AUTONEG_STATUS_FAILED;
432 break;
435 return AnRet;
437 #endif /* INCLUDE_TBI_SUPPORT */