]>
Commit | Line | Data |
---|---|---|
fe8c2806 WD |
1 | /******************************************************************************/ |
2 | /* */ | |
3 | /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 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 | /******************************************************************************/ | |
13 | #if !defined(CONFIG_NET_MULTI) | |
14 | #if INCLUDE_TBI_SUPPORT | |
15 | #include "bcm570x_autoneg.h" | |
16 | #include "bcm570x_mm.h" | |
17 | ||
18 | ||
fe8c2806 WD |
19 | /******************************************************************************/ |
20 | /* Description: */ | |
21 | /* */ | |
22 | /* Return: */ | |
23 | /******************************************************************************/ | |
24 | void | |
25 | MM_AnTxConfig( | |
26 | PAN_STATE_INFO pAnInfo) | |
27 | { | |
28 | PLM_DEVICE_BLOCK pDevice; | |
29 | ||
30 | pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; | |
31 | ||
32 | REG_WR(pDevice, MacCtrl.TxAutoNeg, (LM_UINT32) pAnInfo->TxConfig.AsUSHORT); | |
33 | ||
34 | pDevice->MacMode |= MAC_MODE_SEND_CONFIGS; | |
35 | REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); | |
36 | } | |
37 | ||
38 | ||
fe8c2806 WD |
39 | /******************************************************************************/ |
40 | /* Description: */ | |
41 | /* */ | |
42 | /* Return: */ | |
43 | /******************************************************************************/ | |
44 | void | |
45 | MM_AnTxIdle( | |
46 | PAN_STATE_INFO pAnInfo) | |
47 | { | |
48 | PLM_DEVICE_BLOCK pDevice; | |
49 | ||
50 | pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; | |
51 | ||
52 | pDevice->MacMode &= ~MAC_MODE_SEND_CONFIGS; | |
53 | REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); | |
54 | } | |
55 | ||
56 | ||
fe8c2806 WD |
57 | /******************************************************************************/ |
58 | /* Description: */ | |
59 | /* */ | |
60 | /* Return: */ | |
61 | /******************************************************************************/ | |
62 | char | |
63 | MM_AnRxConfig( | |
64 | PAN_STATE_INFO pAnInfo, | |
65 | unsigned short *pRxConfig) | |
66 | { | |
67 | PLM_DEVICE_BLOCK pDevice; | |
68 | LM_UINT32 Value32; | |
69 | char Retcode; | |
70 | ||
71 | Retcode = AN_FALSE; | |
72 | ||
73 | pDevice = (PLM_DEVICE_BLOCK) pAnInfo->pContext; | |
74 | ||
75 | Value32 = REG_RD(pDevice, MacCtrl.Status); | |
76 | if(Value32 & MAC_STATUS_RECEIVING_CFG) | |
77 | { | |
8bde7f77 WD |
78 | Value32 = REG_RD(pDevice, MacCtrl.RxAutoNeg); |
79 | *pRxConfig = (unsigned short) Value32; | |
fe8c2806 | 80 | |
8bde7f77 | 81 | Retcode = AN_TRUE; |
fe8c2806 WD |
82 | } |
83 | ||
84 | return Retcode; | |
85 | } | |
86 | ||
87 | ||
fe8c2806 WD |
88 | /******************************************************************************/ |
89 | /* Description: */ | |
90 | /* */ | |
91 | /* Return: */ | |
92 | /******************************************************************************/ | |
93 | void | |
94 | AutonegInit( | |
95 | PAN_STATE_INFO pAnInfo) | |
96 | { | |
97 | unsigned long j; | |
98 | ||
99 | for(j = 0; j < sizeof(AN_STATE_INFO); j++) | |
100 | { | |
8bde7f77 | 101 | ((unsigned char *) pAnInfo)[j] = 0; |
fe8c2806 WD |
102 | } |
103 | ||
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; | |
109 | } | |
110 | ||
111 | ||
fe8c2806 WD |
112 | /******************************************************************************/ |
113 | /* Description: */ | |
114 | /* */ | |
115 | /* Return: */ | |
116 | /******************************************************************************/ | |
117 | AUTONEG_STATUS | |
118 | Autoneg8023z( | |
119 | PAN_STATE_INFO pAnInfo) | |
120 | { | |
121 | unsigned short RxConfig; | |
122 | unsigned long Delta_us; | |
123 | AUTONEG_STATUS AnRet; | |
124 | ||
125 | /* Get the current time. */ | |
126 | if(pAnInfo->State == AN_STATE_UNKNOWN) | |
127 | { | |
8bde7f77 WD |
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; | |
fe8c2806 WD |
136 | } |
137 | ||
138 | /* Increment the timer tick. This function is called every microsecon. */ | |
139 | /* pAnInfo->CurrentTime_us++; */ | |
140 | ||
141 | /* Set the AbilityMatch, IdleMatch, and AckMatch flags if their */ | |
142 | /* corresponding conditions are satisfied. */ | |
143 | if(MM_AnRxConfig(pAnInfo, &RxConfig)) | |
144 | { | |
8bde7f77 WD |
145 | if(RxConfig != pAnInfo->AbilityMatchCfg) |
146 | { | |
147 | pAnInfo->AbilityMatchCfg = RxConfig; | |
148 | pAnInfo->AbilityMatch = AN_FALSE; | |
149 | pAnInfo->AbilityMatchCnt = 0; | |
150 | } | |
151 | else | |
152 | { | |
153 | pAnInfo->AbilityMatchCnt++; | |
154 | if(pAnInfo->AbilityMatchCnt > 1) | |
155 | { | |
156 | pAnInfo->AbilityMatch = AN_TRUE; | |
157 | pAnInfo->AbilityMatchCfg = RxConfig; | |
158 | } | |
159 | } | |
160 | ||
161 | if(RxConfig & AN_CONFIG_ACK) | |
162 | { | |
163 | pAnInfo->AckMatch = AN_TRUE; | |
164 | } | |
165 | else | |
166 | { | |
167 | pAnInfo->AckMatch = AN_FALSE; | |
168 | } | |
169 | ||
170 | pAnInfo->IdleMatch = AN_FALSE; | |
fe8c2806 WD |
171 | } |
172 | else | |
173 | { | |
8bde7f77 | 174 | pAnInfo->IdleMatch = AN_TRUE; |
fe8c2806 | 175 | |
8bde7f77 WD |
176 | pAnInfo->AbilityMatchCfg = 0; |
177 | pAnInfo->AbilityMatchCnt = 0; | |
178 | pAnInfo->AbilityMatch = AN_FALSE; | |
179 | pAnInfo->AckMatch = AN_FALSE; | |
fe8c2806 | 180 | |
8bde7f77 | 181 | RxConfig = 0; |
fe8c2806 WD |
182 | } |
183 | ||
184 | /* Save the last Config. */ | |
185 | pAnInfo->RxConfig.AsUSHORT = RxConfig; | |
186 | ||
187 | /* Default return code. */ | |
188 | AnRet = AUTONEG_STATUS_OK; | |
189 | ||
190 | /* Autoneg state machine as defined in 802.3z section 37.3.1.5. */ | |
191 | switch(pAnInfo->State) | |
192 | { | |
8bde7f77 WD |
193 | case AN_STATE_UNKNOWN: |
194 | if(pAnInfo->mr_an_enable || pAnInfo->mr_restart_an) | |
195 | { | |
196 | pAnInfo->CurrentTime_us = 0; | |
197 | pAnInfo->State = AN_STATE_AN_ENABLE; | |
198 | } | |
199 | ||
200 | /* Fall through.*/ | |
201 | ||
202 | case AN_STATE_AN_ENABLE: | |
203 | pAnInfo->mr_an_complete = AN_FALSE; | |
204 | pAnInfo->mr_page_rx = AN_FALSE; | |
205 | ||
206 | if(pAnInfo->mr_an_enable) | |
207 | { | |
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; | |
214 | ||
215 | pAnInfo->State = AN_STATE_AN_RESTART_INIT; | |
216 | } | |
217 | else | |
218 | { | |
219 | pAnInfo->State = AN_STATE_DISABLE_LINK_OK; | |
220 | } | |
221 | break; | |
222 | ||
223 | case AN_STATE_AN_RESTART_INIT: | |
224 | pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; | |
225 | pAnInfo->mr_np_loaded = AN_FALSE; | |
226 | ||
227 | pAnInfo->TxConfig.AsUSHORT = 0; | |
228 | MM_AnTxConfig(pAnInfo); | |
229 | ||
230 | AnRet = AUTONEG_STATUS_TIMER_ENABLED; | |
231 | ||
232 | pAnInfo->State = AN_STATE_AN_RESTART; | |
233 | ||
234 | /* Fall through.*/ | |
235 | ||
236 | case AN_STATE_AN_RESTART: | |
237 | /* Get the current time and compute the delta with the saved */ | |
238 | /* link timer. */ | |
239 | Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; | |
240 | if(Delta_us > AN_LINK_TIMER_INTERVAL_US) | |
241 | { | |
242 | pAnInfo->State = AN_STATE_ABILITY_DETECT_INIT; | |
243 | } | |
244 | else | |
245 | { | |
246 | AnRet = AUTONEG_STATUS_TIMER_ENABLED; | |
247 | } | |
248 | break; | |
249 | ||
250 | case AN_STATE_DISABLE_LINK_OK: | |
251 | AnRet = AUTONEG_STATUS_DONE; | |
252 | break; | |
253 | ||
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; | |
258 | ||
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; | |
268 | ||
269 | MM_AnTxConfig(pAnInfo); | |
270 | ||
271 | pAnInfo->State = AN_STATE_ABILITY_DETECT; | |
272 | ||
273 | break; | |
274 | ||
275 | case AN_STATE_ABILITY_DETECT: | |
276 | if(pAnInfo->AbilityMatch == AN_TRUE && | |
277 | pAnInfo->RxConfig.AsUSHORT != 0) | |
278 | { | |
279 | pAnInfo->State = AN_STATE_ACK_DETECT_INIT; | |
280 | } | |
281 | ||
282 | break; | |
283 | ||
284 | case AN_STATE_ACK_DETECT_INIT: | |
285 | pAnInfo->TxConfig.D14_ACK = 1; | |
286 | MM_AnTxConfig(pAnInfo); | |
287 | ||
288 | pAnInfo->State = AN_STATE_ACK_DETECT; | |
289 | ||
290 | /* Fall through. */ | |
291 | ||
292 | case AN_STATE_ACK_DETECT: | |
293 | if(pAnInfo->AckMatch == AN_TRUE) | |
294 | { | |
295 | if((pAnInfo->RxConfig.AsUSHORT & ~AN_CONFIG_ACK) == | |
296 | (pAnInfo->AbilityMatchCfg & ~AN_CONFIG_ACK)) | |
297 | { | |
298 | pAnInfo->State = AN_STATE_COMPLETE_ACK_INIT; | |
299 | } | |
300 | else | |
301 | { | |
302 | pAnInfo->State = AN_STATE_AN_ENABLE; | |
303 | } | |
304 | } | |
305 | else if(pAnInfo->AbilityMatch == AN_TRUE && | |
306 | pAnInfo->RxConfig.AsUSHORT == 0) | |
307 | { | |
308 | pAnInfo->State = AN_STATE_AN_ENABLE; | |
309 | } | |
310 | ||
311 | break; | |
312 | ||
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) | |
319 | { | |
320 | AnRet = AUTONEG_STATUS_FAILED; | |
321 | break; | |
322 | } | |
323 | ||
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; | |
332 | ||
333 | pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; | |
334 | ||
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; | |
339 | ||
340 | pAnInfo->State = AN_STATE_COMPLETE_ACK; | |
341 | AnRet = AUTONEG_STATUS_TIMER_ENABLED; | |
342 | ||
343 | break; | |
344 | ||
345 | case AN_STATE_COMPLETE_ACK: | |
346 | if(pAnInfo->AbilityMatch == AN_TRUE && | |
347 | pAnInfo->RxConfig.AsUSHORT == 0) | |
348 | { | |
349 | pAnInfo->State = AN_STATE_AN_ENABLE; | |
350 | break; | |
351 | } | |
352 | ||
353 | Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; | |
354 | ||
355 | if(Delta_us > AN_LINK_TIMER_INTERVAL_US) | |
356 | { | |
357 | if(pAnInfo->mr_adv_next_page == 0 || | |
358 | pAnInfo->mr_lp_adv_next_page == 0) | |
359 | { | |
360 | pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; | |
361 | } | |
362 | else | |
363 | { | |
364 | if(pAnInfo->TxConfig.bits.D15 == 0 && | |
365 | pAnInfo->mr_np_rx == 0) | |
366 | { | |
367 | pAnInfo->State = AN_STATE_IDLE_DETECT_INIT; | |
368 | } | |
369 | else | |
370 | { | |
371 | AnRet = AUTONEG_STATUS_FAILED; | |
372 | } | |
373 | } | |
374 | } | |
375 | ||
376 | break; | |
377 | ||
378 | case AN_STATE_IDLE_DETECT_INIT: | |
379 | pAnInfo->LinkTime_us = pAnInfo->CurrentTime_us; | |
380 | ||
381 | MM_AnTxIdle(pAnInfo); | |
382 | ||
383 | pAnInfo->State = AN_STATE_IDLE_DETECT; | |
384 | ||
385 | AnRet = AUTONEG_STATUS_TIMER_ENABLED; | |
386 | ||
387 | break; | |
388 | ||
389 | case AN_STATE_IDLE_DETECT: | |
390 | if(pAnInfo->AbilityMatch == AN_TRUE && | |
391 | pAnInfo->RxConfig.AsUSHORT == 0) | |
392 | { | |
393 | pAnInfo->State = AN_STATE_AN_ENABLE; | |
394 | break; | |
395 | } | |
396 | ||
397 | Delta_us = pAnInfo->CurrentTime_us - pAnInfo->LinkTime_us; | |
398 | if(Delta_us > AN_LINK_TIMER_INTERVAL_US) | |
399 | { | |
fe8c2806 WD |
400 | #if 0 |
401 | /* if(pAnInfo->IdleMatch == AN_TRUE) */ | |
402 | /* { */ | |
403 | #endif | |
8bde7f77 | 404 | pAnInfo->State = AN_STATE_LINK_OK; |
fe8c2806 WD |
405 | #if 0 |
406 | /* } */ | |
407 | /* else */ | |
408 | /* { */ | |
409 | /* AnRet = AUTONEG_STATUS_FAILED; */ | |
410 | /* break; */ | |
411 | /* } */ | |
412 | #endif | |
8bde7f77 | 413 | } |
fe8c2806 | 414 | |
8bde7f77 | 415 | break; |
fe8c2806 | 416 | |
8bde7f77 WD |
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; | |
fe8c2806 | 421 | |
8bde7f77 | 422 | break; |
fe8c2806 | 423 | |
8bde7f77 WD |
424 | case AN_STATE_NEXT_PAGE_WAIT_INIT: |
425 | break; | |
fe8c2806 | 426 | |
8bde7f77 WD |
427 | case AN_STATE_NEXT_PAGE_WAIT: |
428 | break; | |
fe8c2806 | 429 | |
8bde7f77 WD |
430 | default: |
431 | AnRet = AUTONEG_STATUS_FAILED; | |
432 | break; | |
fe8c2806 WD |
433 | } |
434 | ||
435 | return AnRet; | |
436 | } | |
437 | #endif /* INCLUDE_TBI_SUPPORT */ | |
438 | ||
439 | #endif /* !defined(CONFIG_NET_MULTI) */ |