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 */