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 #include <bcm57xx_cfg.h>
15 #ifdef INCLUDE_TBI_SUPPORT
20 /******************************************************************************/
24 /******************************************************************************/
27 PAN_STATE_INFO pAnInfo
)
29 PLM_DEVICE_BLOCK pDevice
;
31 pDevice
= (PLM_DEVICE_BLOCK
) pAnInfo
->pContext
;
33 REG_WR(pDevice
, MacCtrl
.TxAutoNeg
, (LM_UINT32
) pAnInfo
->TxConfig
.AsUSHORT
);
35 pDevice
->MacMode
|= MAC_MODE_SEND_CONFIGS
;
36 REG_WR(pDevice
, MacCtrl
.Mode
, pDevice
->MacMode
);
41 /******************************************************************************/
45 /******************************************************************************/
48 PAN_STATE_INFO pAnInfo
)
50 PLM_DEVICE_BLOCK pDevice
;
52 pDevice
= (PLM_DEVICE_BLOCK
) pAnInfo
->pContext
;
54 pDevice
->MacMode
&= ~MAC_MODE_SEND_CONFIGS
;
55 REG_WR(pDevice
, MacCtrl
.Mode
, pDevice
->MacMode
);
60 /******************************************************************************/
64 /******************************************************************************/
67 PAN_STATE_INFO pAnInfo
,
68 unsigned short *pRxConfig
)
70 PLM_DEVICE_BLOCK pDevice
;
76 pDevice
= (PLM_DEVICE_BLOCK
) pAnInfo
->pContext
;
78 Value32
= REG_RD(pDevice
, MacCtrl
.Status
);
79 if(Value32
& MAC_STATUS_RECEIVING_CFG
)
81 Value32
= REG_RD(pDevice
, MacCtrl
.RxAutoNeg
);
82 *pRxConfig
= (unsigned short) Value32
;
92 /******************************************************************************/
96 /******************************************************************************/
99 PAN_STATE_INFO pAnInfo
)
103 for(j
= 0; j
< sizeof(AN_STATE_INFO
); j
++)
105 ((unsigned char *) pAnInfo
)[j
] = 0;
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;
117 /******************************************************************************/
121 /******************************************************************************/
124 PAN_STATE_INFO pAnInfo
)
126 unsigned short RxConfig
;
127 unsigned long Delta_us
;
128 AUTONEG_STATUS AnRet
;
130 /* Get the current time. */
131 if(pAnInfo
->State
== AN_STATE_UNKNOWN
)
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
;
143 /* Increment the timer tick. This function is called every microsecon. */
144 // pAnInfo->CurrentTime_us++;
146 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
147 /* corresponding conditions are satisfied. */
148 if(MM_AnRxConfig(pAnInfo
, &RxConfig
))
150 if(RxConfig
!= pAnInfo
->AbilityMatchCfg
)
152 pAnInfo
->AbilityMatchCfg
= RxConfig
;
153 pAnInfo
->AbilityMatch
= AN_FALSE
;
154 pAnInfo
->AbilityMatchCnt
= 0;
158 pAnInfo
->AbilityMatchCnt
++;
159 if(pAnInfo
->AbilityMatchCnt
> 1)
161 pAnInfo
->AbilityMatch
= AN_TRUE
;
162 pAnInfo
->AbilityMatchCfg
= RxConfig
;
166 if(RxConfig
& AN_CONFIG_ACK
)
168 pAnInfo
->AckMatch
= AN_TRUE
;
172 pAnInfo
->AckMatch
= AN_FALSE
;
175 pAnInfo
->IdleMatch
= AN_FALSE
;
179 pAnInfo
->IdleMatch
= AN_TRUE
;
181 pAnInfo
->AbilityMatchCfg
= 0;
182 pAnInfo
->AbilityMatchCnt
= 0;
183 pAnInfo
->AbilityMatch
= AN_FALSE
;
184 pAnInfo
->AckMatch
= AN_FALSE
;
189 /* Save the last Config. */
190 pAnInfo
->RxConfig
.AsUSHORT
= RxConfig
;
192 /* Default return code. */
193 AnRet
= AUTONEG_STATUS_OK
;
195 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
196 switch(pAnInfo
->State
)
198 case AN_STATE_UNKNOWN
:
199 if(pAnInfo
->mr_an_enable
|| pAnInfo
->mr_restart_an
)
201 pAnInfo
->CurrentTime_us
= 0;
202 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
207 case AN_STATE_AN_ENABLE
:
208 pAnInfo
->mr_an_complete
= AN_FALSE
;
209 pAnInfo
->mr_page_rx
= AN_FALSE
;
211 if(pAnInfo
->mr_an_enable
)
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
;
220 pAnInfo
->State
= AN_STATE_AN_RESTART_INIT
;
224 pAnInfo
->State
= AN_STATE_DISABLE_LINK_OK
;
228 case AN_STATE_AN_RESTART_INIT
:
229 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
230 pAnInfo
->mr_np_loaded
= AN_FALSE
;
232 pAnInfo
->TxConfig
.AsUSHORT
= 0;
233 MM_AnTxConfig(pAnInfo
);
235 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
237 pAnInfo
->State
= AN_STATE_AN_RESTART
;
241 case AN_STATE_AN_RESTART
:
242 /* Get the current time and compute the delta with the saved */
244 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
245 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
247 pAnInfo
->State
= AN_STATE_ABILITY_DETECT_INIT
;
251 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
255 case AN_STATE_DISABLE_LINK_OK
:
256 AnRet
= AUTONEG_STATUS_DONE
;
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
;
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
;
274 MM_AnTxConfig(pAnInfo
);
276 pAnInfo
->State
= AN_STATE_ABILITY_DETECT
;
280 case AN_STATE_ABILITY_DETECT
:
281 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
282 pAnInfo
->RxConfig
.AsUSHORT
!= 0)
284 pAnInfo
->State
= AN_STATE_ACK_DETECT_INIT
;
289 case AN_STATE_ACK_DETECT_INIT
:
290 pAnInfo
->TxConfig
.D14_ACK
= 1;
291 MM_AnTxConfig(pAnInfo
);
293 pAnInfo
->State
= AN_STATE_ACK_DETECT
;
297 case AN_STATE_ACK_DETECT
:
298 if(pAnInfo
->AckMatch
== AN_TRUE
)
300 if((pAnInfo
->RxConfig
.AsUSHORT
& ~AN_CONFIG_ACK
) ==
301 (pAnInfo
->AbilityMatchCfg
& ~AN_CONFIG_ACK
))
303 pAnInfo
->State
= AN_STATE_COMPLETE_ACK_INIT
;
307 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
310 else if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
311 pAnInfo
->RxConfig
.AsUSHORT
== 0)
313 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
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
)
325 AnRet
= AUTONEG_STATUS_FAILED
;
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
;
338 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
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
;
345 pAnInfo
->State
= AN_STATE_COMPLETE_ACK
;
346 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
350 case AN_STATE_COMPLETE_ACK
:
351 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
352 pAnInfo
->RxConfig
.AsUSHORT
== 0)
354 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
358 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
360 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
362 if(pAnInfo
->mr_adv_next_page
== 0 ||
363 pAnInfo
->mr_lp_adv_next_page
== 0)
365 pAnInfo
->State
= AN_STATE_IDLE_DETECT_INIT
;
369 if(pAnInfo
->TxConfig
.bits
.D15
== 0 &&
370 pAnInfo
->mr_np_rx
== 0)
372 pAnInfo
->State
= AN_STATE_IDLE_DETECT_INIT
;
376 AnRet
= AUTONEG_STATUS_FAILED
;
383 case AN_STATE_IDLE_DETECT_INIT
:
384 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
386 MM_AnTxIdle(pAnInfo
);
388 pAnInfo
->State
= AN_STATE_IDLE_DETECT
;
390 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
394 case AN_STATE_IDLE_DETECT
:
395 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
396 pAnInfo
->RxConfig
.AsUSHORT
== 0)
398 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
402 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
403 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
405 // if(pAnInfo->IdleMatch == AN_TRUE)
407 pAnInfo
->State
= AN_STATE_LINK_OK
;
411 // AnRet = AUTONEG_STATUS_FAILED;
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
;
425 case AN_STATE_NEXT_PAGE_WAIT_INIT
:
428 case AN_STATE_NEXT_PAGE_WAIT
:
432 AnRet
= AUTONEG_STATUS_FAILED
;
438 #endif /* INCLUDE_TBI_SUPPORT */