1 /******************************************************************************/
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 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 /******************************************************************************/
13 #if !defined(CONFIG_NET_MULTI)
14 #if INCLUDE_TBI_SUPPORT
15 #include "bcm570x_autoneg.h"
16 #include "bcm570x_mm.h"
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
);
39 /******************************************************************************/
43 /******************************************************************************/
46 PAN_STATE_INFO pAnInfo
)
48 PLM_DEVICE_BLOCK pDevice
;
50 pDevice
= (PLM_DEVICE_BLOCK
) pAnInfo
->pContext
;
52 pDevice
->MacMode
&= ~MAC_MODE_SEND_CONFIGS
;
53 REG_WR(pDevice
, MacCtrl
.Mode
, pDevice
->MacMode
);
57 /******************************************************************************/
61 /******************************************************************************/
64 PAN_STATE_INFO pAnInfo
,
65 unsigned short *pRxConfig
)
67 PLM_DEVICE_BLOCK pDevice
;
73 pDevice
= (PLM_DEVICE_BLOCK
) pAnInfo
->pContext
;
75 Value32
= REG_RD(pDevice
, MacCtrl
.Status
);
76 if(Value32
& MAC_STATUS_RECEIVING_CFG
)
78 Value32
= REG_RD(pDevice
, MacCtrl
.RxAutoNeg
);
79 *pRxConfig
= (unsigned short) Value32
;
88 /******************************************************************************/
92 /******************************************************************************/
95 PAN_STATE_INFO pAnInfo
)
99 for(j
= 0; j
< sizeof(AN_STATE_INFO
); j
++)
101 ((unsigned char *) pAnInfo
)[j
] = 0;
104 /* Initialize the default advertisement register. */
105 pAnInfo
->mr_adv_full_duplex
= 1;
106 pAnInfo
->mr_adv_sym_pause
= 1;
107 pAnInfo
->mr_adv_asym_pause
= 1;
108 pAnInfo
->mr_an_enable
= 1;
112 /******************************************************************************/
116 /******************************************************************************/
119 PAN_STATE_INFO pAnInfo
)
121 unsigned short RxConfig
;
122 unsigned long Delta_us
;
123 AUTONEG_STATUS AnRet
;
125 /* Get the current time. */
126 if(pAnInfo
->State
== AN_STATE_UNKNOWN
)
128 pAnInfo
->RxConfig
.AsUSHORT
= 0;
129 pAnInfo
->CurrentTime_us
= 0;
130 pAnInfo
->LinkTime_us
= 0;
131 pAnInfo
->AbilityMatchCfg
= 0;
132 pAnInfo
->AbilityMatchCnt
= 0;
133 pAnInfo
->AbilityMatch
= AN_FALSE
;
134 pAnInfo
->IdleMatch
= AN_FALSE
;
135 pAnInfo
->AckMatch
= AN_FALSE
;
138 /* Increment the timer tick. This function is called every microsecon. */
139 /* pAnInfo->CurrentTime_us++; */
141 /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */
142 /* corresponding conditions are satisfied. */
143 if(MM_AnRxConfig(pAnInfo
, &RxConfig
))
145 if(RxConfig
!= pAnInfo
->AbilityMatchCfg
)
147 pAnInfo
->AbilityMatchCfg
= RxConfig
;
148 pAnInfo
->AbilityMatch
= AN_FALSE
;
149 pAnInfo
->AbilityMatchCnt
= 0;
153 pAnInfo
->AbilityMatchCnt
++;
154 if(pAnInfo
->AbilityMatchCnt
> 1)
156 pAnInfo
->AbilityMatch
= AN_TRUE
;
157 pAnInfo
->AbilityMatchCfg
= RxConfig
;
161 if(RxConfig
& AN_CONFIG_ACK
)
163 pAnInfo
->AckMatch
= AN_TRUE
;
167 pAnInfo
->AckMatch
= AN_FALSE
;
170 pAnInfo
->IdleMatch
= AN_FALSE
;
174 pAnInfo
->IdleMatch
= AN_TRUE
;
176 pAnInfo
->AbilityMatchCfg
= 0;
177 pAnInfo
->AbilityMatchCnt
= 0;
178 pAnInfo
->AbilityMatch
= AN_FALSE
;
179 pAnInfo
->AckMatch
= AN_FALSE
;
184 /* Save the last Config. */
185 pAnInfo
->RxConfig
.AsUSHORT
= RxConfig
;
187 /* Default return code. */
188 AnRet
= AUTONEG_STATUS_OK
;
190 /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */
191 switch(pAnInfo
->State
)
193 case AN_STATE_UNKNOWN
:
194 if(pAnInfo
->mr_an_enable
|| pAnInfo
->mr_restart_an
)
196 pAnInfo
->CurrentTime_us
= 0;
197 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
202 case AN_STATE_AN_ENABLE
:
203 pAnInfo
->mr_an_complete
= AN_FALSE
;
204 pAnInfo
->mr_page_rx
= AN_FALSE
;
206 if(pAnInfo
->mr_an_enable
)
208 pAnInfo
->LinkTime_us
= 0;
209 pAnInfo
->AbilityMatchCfg
= 0;
210 pAnInfo
->AbilityMatchCnt
= 0;
211 pAnInfo
->AbilityMatch
= AN_FALSE
;
212 pAnInfo
->IdleMatch
= AN_FALSE
;
213 pAnInfo
->AckMatch
= AN_FALSE
;
215 pAnInfo
->State
= AN_STATE_AN_RESTART_INIT
;
219 pAnInfo
->State
= AN_STATE_DISABLE_LINK_OK
;
223 case AN_STATE_AN_RESTART_INIT
:
224 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
225 pAnInfo
->mr_np_loaded
= AN_FALSE
;
227 pAnInfo
->TxConfig
.AsUSHORT
= 0;
228 MM_AnTxConfig(pAnInfo
);
230 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
232 pAnInfo
->State
= AN_STATE_AN_RESTART
;
236 case AN_STATE_AN_RESTART
:
237 /* Get the current time and compute the delta with the saved */
239 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
240 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
242 pAnInfo
->State
= AN_STATE_ABILITY_DETECT_INIT
;
246 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
250 case AN_STATE_DISABLE_LINK_OK
:
251 AnRet
= AUTONEG_STATUS_DONE
;
254 case AN_STATE_ABILITY_DETECT_INIT
:
255 /* Note: in the state diagram, this variable is set to */
256 /* mr_adv_ability<12>. Is this right?. */
257 pAnInfo
->mr_toggle_tx
= AN_FALSE
;
259 /* Send the config as advertised in the advertisement register. */
260 pAnInfo
->TxConfig
.AsUSHORT
= 0;
261 pAnInfo
->TxConfig
.D5_FD
= pAnInfo
->mr_adv_full_duplex
;
262 pAnInfo
->TxConfig
.D6_HD
= pAnInfo
->mr_adv_half_duplex
;
263 pAnInfo
->TxConfig
.D7_PS1
= pAnInfo
->mr_adv_sym_pause
;
264 pAnInfo
->TxConfig
.D8_PS2
= pAnInfo
->mr_adv_asym_pause
;
265 pAnInfo
->TxConfig
.D12_RF1
= pAnInfo
->mr_adv_remote_fault1
;
266 pAnInfo
->TxConfig
.D13_RF2
= pAnInfo
->mr_adv_remote_fault2
;
267 pAnInfo
->TxConfig
.D15_NP
= pAnInfo
->mr_adv_next_page
;
269 MM_AnTxConfig(pAnInfo
);
271 pAnInfo
->State
= AN_STATE_ABILITY_DETECT
;
275 case AN_STATE_ABILITY_DETECT
:
276 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
277 pAnInfo
->RxConfig
.AsUSHORT
!= 0)
279 pAnInfo
->State
= AN_STATE_ACK_DETECT_INIT
;
284 case AN_STATE_ACK_DETECT_INIT
:
285 pAnInfo
->TxConfig
.D14_ACK
= 1;
286 MM_AnTxConfig(pAnInfo
);
288 pAnInfo
->State
= AN_STATE_ACK_DETECT
;
292 case AN_STATE_ACK_DETECT
:
293 if(pAnInfo
->AckMatch
== AN_TRUE
)
295 if((pAnInfo
->RxConfig
.AsUSHORT
& ~AN_CONFIG_ACK
) ==
296 (pAnInfo
->AbilityMatchCfg
& ~AN_CONFIG_ACK
))
298 pAnInfo
->State
= AN_STATE_COMPLETE_ACK_INIT
;
302 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
305 else if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
306 pAnInfo
->RxConfig
.AsUSHORT
== 0)
308 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
313 case AN_STATE_COMPLETE_ACK_INIT
:
314 /* Make sure invalid bits are not set. */
315 if(pAnInfo
->RxConfig
.bits
.D0
|| pAnInfo
->RxConfig
.bits
.D1
||
316 pAnInfo
->RxConfig
.bits
.D2
|| pAnInfo
->RxConfig
.bits
.D3
||
317 pAnInfo
->RxConfig
.bits
.D4
|| pAnInfo
->RxConfig
.bits
.D9
||
318 pAnInfo
->RxConfig
.bits
.D10
|| pAnInfo
->RxConfig
.bits
.D11
)
320 AnRet
= AUTONEG_STATUS_FAILED
;
324 /* Set up the link partner advertisement register. */
325 pAnInfo
->mr_lp_adv_full_duplex
= pAnInfo
->RxConfig
.D5_FD
;
326 pAnInfo
->mr_lp_adv_half_duplex
= pAnInfo
->RxConfig
.D6_HD
;
327 pAnInfo
->mr_lp_adv_sym_pause
= pAnInfo
->RxConfig
.D7_PS1
;
328 pAnInfo
->mr_lp_adv_asym_pause
= pAnInfo
->RxConfig
.D8_PS2
;
329 pAnInfo
->mr_lp_adv_remote_fault1
= pAnInfo
->RxConfig
.D12_RF1
;
330 pAnInfo
->mr_lp_adv_remote_fault2
= pAnInfo
->RxConfig
.D13_RF2
;
331 pAnInfo
->mr_lp_adv_next_page
= pAnInfo
->RxConfig
.D15_NP
;
333 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
335 pAnInfo
->mr_toggle_tx
= !pAnInfo
->mr_toggle_tx
;
336 pAnInfo
->mr_toggle_rx
= pAnInfo
->RxConfig
.bits
.D11
;
337 pAnInfo
->mr_np_rx
= pAnInfo
->RxConfig
.D15_NP
;
338 pAnInfo
->mr_page_rx
= AN_TRUE
;
340 pAnInfo
->State
= AN_STATE_COMPLETE_ACK
;
341 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
345 case AN_STATE_COMPLETE_ACK
:
346 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
347 pAnInfo
->RxConfig
.AsUSHORT
== 0)
349 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
353 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
355 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
357 if(pAnInfo
->mr_adv_next_page
== 0 ||
358 pAnInfo
->mr_lp_adv_next_page
== 0)
360 pAnInfo
->State
= AN_STATE_IDLE_DETECT_INIT
;
364 if(pAnInfo
->TxConfig
.bits
.D15
== 0 &&
365 pAnInfo
->mr_np_rx
== 0)
367 pAnInfo
->State
= AN_STATE_IDLE_DETECT_INIT
;
371 AnRet
= AUTONEG_STATUS_FAILED
;
378 case AN_STATE_IDLE_DETECT_INIT
:
379 pAnInfo
->LinkTime_us
= pAnInfo
->CurrentTime_us
;
381 MM_AnTxIdle(pAnInfo
);
383 pAnInfo
->State
= AN_STATE_IDLE_DETECT
;
385 AnRet
= AUTONEG_STATUS_TIMER_ENABLED
;
389 case AN_STATE_IDLE_DETECT
:
390 if(pAnInfo
->AbilityMatch
== AN_TRUE
&&
391 pAnInfo
->RxConfig
.AsUSHORT
== 0)
393 pAnInfo
->State
= AN_STATE_AN_ENABLE
;
397 Delta_us
= pAnInfo
->CurrentTime_us
- pAnInfo
->LinkTime_us
;
398 if(Delta_us
> AN_LINK_TIMER_INTERVAL_US
)
401 /* if(pAnInfo->IdleMatch == AN_TRUE) */
404 pAnInfo
->State
= AN_STATE_LINK_OK
;
409 /* 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 */
439 #endif /* !defined(CONFIG_NET_MULTI) */