Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: bge-phy.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)bge-phy.fth 1.9 06/08/23 | |
43 | purpose: | |
44 | copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | ||
48 | headers | |
49 | ||
50 | 0 value an-debug? | |
51 | ||
52 | d# 5 constant #rst-retries \ # of retries to reset phy | |
53 | create pattern | |
54 | h# 5555 w, h# 0005 w, h# 2aaa w, h# 000a w, h# 3456 w, h# 0003 w, | |
55 | h# 2aaa w, h# 000a w, h# 3333 w, h# 0003 w, h# 789a w, h# 0005 w, | |
56 | h# 5a5a w, h# 0005 w, h# 2a6a w, h# 000a w, h# 1bcd w, h# 0003 w, | |
57 | h# 2a5a w, h# 000a w, h# 33c3 w, h# 0003 w, h# 2ef1 w, h# 0005 w, | |
58 | ||
59 | : phy-macro-done? ( -- flag ) | |
60 | h# 16 phy@ h# 1000 and 0= | |
61 | ; | |
62 | ||
63 | : wait-phy-macro-done ( -- flag ) | |
64 | d# 100 ['] phy-macro-done? wait-status | |
65 | ; | |
66 | ||
67 | \ Put PHY in loopback mode temporarily to bring the link down | |
68 | : force-link-down ( -- ) | |
69 | phy-cr@ phycr.loopback or phy-cr! | |
70 | d# 1000 ms | |
71 | phy-cr@ phycr.loopback invert and phy-cr! | |
72 | ; | |
73 | ||
74 | : phy-reset-complete? ( -- flag ) phy-cr@ phycr.reset and 0= ; | |
75 | ||
76 | : wait-phy-reset ( -- flag ) | |
77 | d# 700 ['] phy-reset-complete? wait-status | |
78 | ; | |
79 | ||
80 | \ This code is taken from a recommendation by Broadcom on | |
81 | \ how to reset the PHY and check for a failed reset | |
82 | \ condition that can occur occasionally, if such a condition | |
83 | \ is detected then retry the reset for a pre-determined | |
84 | \ number of iterations | |
85 | ||
86 | : pattern@ ( index set# -- val ) | |
87 | 6 * + /w * pattern + w@ | |
88 | ; | |
89 | ||
90 | : (reset-transceiver-once) ( -- ok? ) | |
91 | \ issue a phy reset, and wait for reset to complete | |
92 | phy-cr@ phycr.reset or phy-cr! ( ) | |
93 | wait-phy-reset drop ( ) | |
94 | \ now go check the DFE TAPs to see if locked up, but | |
95 | \ first, we need to set up PHY so we can read DFE TAPs | |
96 | \ Disable Transmitter and Interrupt, while we play with | |
97 | \ the PHY registers, so the link partner won't see any | |
98 | \ strange data and the Driver won't see any interrupts. | |
99 | h# 10 phy@ h# 3000 or h# 10 phy! ( ) | |
100 | \ Setup Full-Duplex, 1000 mbps | |
101 | h# 140 phy-cr! ( ) | |
102 | \ Set to Master mode | |
103 | h# 1800 9 phy! ( ) | |
104 | ||
105 | \ ADC and Gamma fixes only apply to Ax revisions | |
106 | \ not Bx revisions, so check that relevant part | |
107 | \ of revision id is 0 | |
108 | pci-rev-id h# f00 and 0= if | |
109 | \ ADC fix | |
110 | \ Enable SM_DSP_CLOCK & 6dB | |
111 | h# c00 h# 18 phy! ( ) | |
112 | \ work-arounds | |
113 | h# 201f h# 17 phy! ( ) | |
114 | h# 2aaa h# 15 phy! ( ) | |
115 | ||
116 | \ Gamma fix | |
117 | h# a h# 17 phy! ( ) | |
118 | h# 323 h# 15 phy! ( ) | |
119 | then | |
120 | ||
121 | \ blocks the PHY control access | |
122 | h# 8005 h# 17 phy! ( ) | |
123 | h# 800 h# 15 phy! ( ) | |
124 | \ check TAPs for all 4 channels, as soon | |
125 | \ as we see a lockup we'll stop checking | |
126 | 4 0 do ( ) | |
127 | \ select channel and set TAP index to 0 | |
128 | i h# 2000 * h# 200 or h# 17 phy! ( ) | |
129 | \ freeze filter again just to be safe | |
130 | 2 h# 16 phy! ( ) | |
131 | \ write fixed pattern to the RAM, 3 TAPs for | |
132 | \ each channel, each TAP have 2 WORDs (LO/HI) | |
133 | 6 0 do ( ) | |
134 | i j pattern@ h# 15 phy! ( ) | |
135 | loop ( ) | |
136 | \ Active PHY's Macro operation to write DFE TAP from RAM, | |
137 | \ and wait for Macro to complete | |
138 | h# 202 h# 16 phy! ( ) | |
139 | wait-phy-macro-done drop ( ) | |
140 | \ --- done with write phase, now begin read phase --- | |
141 | \ select channel and set TAP index to 0 | |
142 | i h# 2000 * h# 200 or h# 17 phy! ( ) | |
143 | \ Active PHY's Macro operation to load DFE TAP to RAM, | |
144 | \ and wait for Macro to complete | |
145 | h# 82 h# 16 phy! ( ) | |
146 | wait-phy-macro-done drop ( ) | |
147 | \ enable "pre-fetch" | |
148 | h# 802 h# 16 phy! ( ) | |
149 | wait-phy-macro-done drop ( ) | |
150 | \ read back the TAP values | |
151 | \ 3 TAPs for each channel, each TAP have 2 WORDs (LO/HI) | |
152 | 6 0 do ( ) | |
153 | \ read Lo/Hi then wait for 'done' is faster | |
154 | \ For DFE TAP, the HI word contains 6 bits, | |
155 | \ LO word contains 15 bits | |
156 | h# 15 phy@ h# 7fff and ( dataLo ) | |
157 | h# 15 phy@ h# 3f and ( dataLo dataHi ) | |
158 | wait-phy-macro-done drop ( dataLo dataHi ) | |
159 | \ check if what we wrote is what we read back | |
160 | i 1+ j pattern@ = swap ( hiMatch? dataLo ) | |
161 | i j pattern@ = ( hiMatch? loMatch? ) | |
162 | and 0= if ( ) | |
163 | \ if failed, then the PHY is locked up, | |
164 | \ we need to do PHY reset again | |
165 | unloop unloop false exit ( false ) | |
166 | then ( ) | |
167 | 2 +loop ( ) | |
168 | loop ( ) | |
169 | true ( true ) | |
170 | ; | |
171 | ||
172 | : (reset-transceiver-special) ( -- ok? ) | |
173 | false | |
174 | #rst-retries 0 do | |
175 | (reset-transceiver-once) if ( false ) | |
176 | drop true leave ( true ) | |
177 | then ( false ) | |
178 | loop ( ok? ) | |
179 | \ remove block phy control | |
180 | h# 8005 h# 17 phy! ( ok? ) | |
181 | 0 h# 15 phy! ( ok? ) | |
182 | \ unfreeze DFE TAP filter for all channels | |
183 | h# 8200 h# 17 phy! ( ok? ) | |
184 | 0 h# 16 phy! ( ok? ) | |
185 | \ Restore PHY back to operating state | |
186 | h# 400 h# 18 phy! ( ok? ) | |
187 | \ enable transmitter and interrupt | |
188 | h# 10 phy@ h# cfff and h# 10 phy! ( ok? ) | |
189 | ; | |
190 | ||
191 | : (reset-transceiver-generic) ( -- ok? ) | |
192 | phy-cr@ phycr.reset or phy-cr! | |
193 | wait-phy-reset | |
194 | ; | |
195 | ||
196 | \ return true if BCM5704C rev < B0 | |
197 | : bcm5704c<revb0? ( -- flag ) | |
198 | pci-dev-id BCM-5704 = | |
199 | pci-rev-id h# f00 and 0= and | |
200 | ; | |
201 | ||
202 | : (reset-transceiver) ( -- ok? ) | |
203 | pci-dev-id BCM-5703 = | |
204 | pci-dev-id BCM-5703a = or | |
205 | bcm5704c<revb0? or if \ The 5703 and 5704 (revs less than | |
206 | \ B0) need a non-default method to | |
207 | \ reset the phy | |
208 | \ NB: 5702/5705 are not supported. | |
209 | (reset-transceiver-special) | |
210 | else | |
211 | (reset-transceiver-generic) | |
212 | then | |
213 | ; | |
214 | ||
215 | : reset-transceiver ( -- ok? ) | |
216 | d# 15000 get-msecs + false | |
217 | begin | |
218 | over timed-out? 0= over 0= and | |
219 | while | |
220 | (reset-transceiver) if drop true then | |
221 | repeat nip | |
222 | dup 0= if ." Failed to reset transceiver!" cr exit then | |
223 | phy-cr@ phycr.speed-100 invert and phycr.duplex invert and phy-cr! | |
224 | ; | |
225 | ||
226 | : disable-auto-nego ( -- ) | |
227 | an-debug? if ." Disabling Autonegotiation" cr then | |
228 | phy-cr@ phycr.an-enable invert and phy-cr! | |
229 | ; | |
230 | ||
231 | : enable-auto-nego ( -- ) | |
232 | an-debug? if ." Enabling Autonegotiation" cr then | |
233 | phy-cr@ phycr.an-enable phycr.an-restart or or phy-cr! | |
234 | ; | |
235 | ||
236 | : an-link-speed&mode ( -- speed duplex-mode ) | |
237 | ||
238 | phy-sr@ physr.ext-status and if | |
239 | phy-1000-sr@ h# c00 and d# 10 rshift | |
240 | phy-1000-cr@ h# 300 and d# 8 rshift and ( 1000bt-common-cap ) | |
241 | d# 10 lshift | |
242 | dup gsr.lp-1000fdx and if drop 1000Mbps full-duplex exit then | |
243 | gsr.lp-1000hdx and if 1000Mbps half-duplex exit then | |
244 | then | |
245 | ||
246 | phy-anlpar@ phy-anar@ and ( an-common ) | |
247 | dup anlpar.100fdx and if drop 100Mbps full-duplex exit then | |
248 | dup anlpar.100hdx and if drop 100Mbps half-duplex exit then | |
249 | dup anlpar.10fdx and if drop 10Mbps full-duplex exit then | |
250 | dup anlpar.10hdx and if drop 10Mbps half-duplex exit then | |
251 | ; | |
252 | ||
253 | : supported-speed&mode ( speed mode$ -- bit-mask ) | |
254 | rot case | |
255 | 10Mbps of | |
256 | " half" $= if h# 1 else h# 2 then | |
257 | endof | |
258 | 100Mbps of | |
259 | " half" $= if h# 4 else h# 8 then | |
260 | endof | |
261 | 1000Mbps of | |
262 | " half" $= if h# 10 else h# 20 then | |
263 | endof | |
264 | ( default ) 0 | |
265 | endcase | |
266 | ; | |
267 | ||
268 | : parse-supported-abilities ( str$ -- abilities ) | |
269 | base @ >r decimal | |
270 | ascii , left-parse-string 2drop | |
271 | ascii , left-parse-string $number drop -rot ( speed str$ ) | |
272 | ascii , left-parse-string 2drop ( speed mode$ ) | |
273 | supported-speed&mode ( bit-mask ) | |
274 | r> base ! | |
275 | ; | |
276 | ||
277 | : get-supported-abilities ( phy-abilty -- phy-abilty | abilty ) | |
278 | " supported-network-types" get-my-property 0= if | |
279 | begin | |
280 | decode-string ?dup | |
281 | while ( phy-abilty str1$ str2$ ) | |
282 | parse-supported-abilities ( phy-abilty str1$ mask ) | |
283 | 3 roll swap xor -rot ( mask' str1$ ) | |
284 | repeat 3drop ( mask' ) | |
285 | invert h# 3f and ( abilty ) | |
286 | then | |
287 | ; | |
288 | ||
289 | : phy-abilities ( -- abilities ) | |
290 | phy-sr@ d# 11 rshift h# f and | |
291 | gmii-phy? if phy-esr@ d# 12 rshift h# 3 and else 0 then d# 4 lshift or | |
292 | ( phy-abilty ) get-supported-abilities ( abilities ) | |
293 | ; | |
294 | ||
295 | \ Construct bit-mask abilities based on speed, duplex mode settings | |
296 | \ 0000.0001 10Mbps, Half Duplex | |
297 | \ 0000.0010 10Mbps, Full Duplex | |
298 | \ 0000.0100 100Mbps, Half Duplex | |
299 | \ 0000.1000 100Mbps, Full Duplex | |
300 | \ 0001.0000 1000Mbps, Half Duplex | |
301 | \ 0010.0000 1000Mbps, Full Duplex | |
302 | : construct-abilities ( speed duplex-mode -- abilities ) | |
303 | phy-abilities | |
304 | swap case | |
305 | half-duplex of h# 15 endof \ Mask FDX abilities | |
306 | full-duplex of h# 2a endof \ Mask HDX abilities | |
307 | auto-duplex of h# 3f endof | |
308 | endcase and | |
309 | swap case | |
310 | 10Mbps of h# 3 endof | |
311 | 100Mbps of h# c endof | |
312 | 1000Mbps of h# 30 endof | |
313 | auto-speed of h# 3f endof | |
314 | endcase and | |
315 | ; | |
316 | ||
317 | : publish-capabilities ( -- ) | |
318 | ||
319 | user-speed user-duplex construct-abilities ( abilities ) | |
320 | dup h# f and d# 5 lshift h# 1 or phy-anar! \ anar[8:5] | |
321 | gmii-phy? if ( abilities ) | |
322 | h# 30 and d# 4 lshift ( 1000-cap ) | |
323 | user-link-clock auto-link-clock <> if | |
324 | gcr.ms-cfg-enable or | |
325 | user-link-clock master-link-clock = if | |
326 | gcr.ms-cfg-value or | |
327 | then | |
328 | then | |
329 | phy-1000-cr! | |
330 | else ( abilities ) | |
331 | drop ( ) | |
332 | then ( ) | |
333 | ; | |
334 | ||
335 | : match-capabilities ( -- ok? ) | |
336 | phy-sr@ physr.ext-status and if | |
337 | phy-1000-sr@ h# c00 and d# 10 rshift | |
338 | phy-1000-cr@ h# 300 and d# 8 rshift | |
339 | and 0<> | |
340 | else | |
341 | 0 | |
342 | then | |
343 | phy-anlpar@ phy-anar@ and 0<> or | |
344 | ; | |
345 | ||
346 | \ Autonegotiation may take as much as 5 seconds with 10/100 BaseT PHYs | |
347 | : wait-autoneg-complete ( -- complete? ) | |
348 | d# 5000 get-msecs + false | |
349 | begin | |
350 | over timed-out? 0= | |
351 | over 0= and | |
352 | while | |
353 | d# 20 ms | |
354 | phy-sr@ physr.an-complete and if | |
355 | drop true | |
356 | then | |
357 | repeat nip | |
358 | ; | |
359 | ||
360 | : phy-link-up? ( -- up? ) | |
361 | phy-sr@ drop | |
362 | phy-sr@ physr.link-up and | |
363 | ; | |
364 | ||
365 | : link-up? ( -- flag ) phy-link-up? ; | |
366 | ||
367 | : wait-link-up? ( -- up? ) | |
368 | wait-phy-reset drop | |
369 | d# 2000 ['] phy-link-up? wait-status | |
370 | ; | |
371 | ||
372 | : (autonegotiate) ( -- link-up? ) | |
373 | ||
374 | \ Advertise my capabilities & start auto negotiation | |
375 | publish-capabilities | |
376 | enable-auto-nego | |
377 | ||
378 | \ Wait for auto negotiation to complete | |
379 | wait-autoneg-complete | |
380 | 0= if | |
381 | ." Timed out waiting for Autonegotiation to complete" cr | |
382 | false exit | |
383 | then | |
384 | ||
385 | \ Check if autonegotiation completed by parallel detection, | |
386 | \ and if so, whether there are any parallel detect (multiple | |
387 | \ link fault) errors | |
388 | phy-aner@ dup aner.lp-an-able and 0= swap aner.mlf and and if | |
389 | ." Multiple link faults seen during Autonegotiation" cr | |
390 | false exit | |
391 | then | |
392 | ||
393 | \ Check for common capabilities | |
394 | match-capabilities 0= if | |
395 | ." System and network incompatible for communicating" cr | |
396 | false exit | |
397 | then | |
398 | ||
399 | \ Valid Link established? | |
400 | phy-link-up? | |
401 | ; | |
402 | ||
403 | : do-autonegotiation ( -- link-up? ) | |
404 | (autonegotiate) if | |
405 | an-link-speed&mode set-chosen-speed&duplex | |
406 | true | |
407 | else | |
408 | ." Check cable and try again" cr | |
409 | false | |
410 | then | |
411 | ; | |
412 | ||
413 | : check-phy-capability ( -- ) | |
414 | user-speed user-duplex 2dup construct-abilities 0= if | |
415 | ." Not capable of " .link-speed,duplex | |
416 | -1 throw | |
417 | else | |
418 | 2drop | |
419 | then | |
420 | ; | |
421 | ||
422 | \ Set/Force link speed and mode, and check link status | |
423 | \ For 1Gbps, we manually configure local PHY as SLAVE | |
424 | : speed&mode-possible? ( speed duplex-mode -- link-up? ) | |
425 | over 1000Mbps = if | |
426 | phy-1000-cr@ h# 1800 invert and h# 1000 or phy-1000-cr! | |
427 | then | |
428 | phy-cr@ b# 0010.0001.0100.0000 invert and \ Mask speed & duplex bits | |
429 | swap full-duplex = if phycr.duplex or then | |
430 | swap case | |
431 | 10Mbps of phycr.speed-10 endof | |
432 | 100Mbps of phycr.speed-100 endof | |
433 | 1000Mbps of phycr.speed-1000 endof | |
434 | endcase or | |
435 | phy-cr! | |
436 | wait-link-up? | |
437 | ; | |
438 | ||
439 | ||
440 | : set-speed&mode ( -- link-up? ) | |
441 | disable-auto-nego | |
442 | force-link-down | |
443 | user-speed user-duplex | |
444 | 2dup speed&mode-possible? if set-chosen-speed&duplex true exit then | |
445 | over 1000Mbps = if | |
446 | ." Cannot bringup link using non-autonegotation." cr | |
447 | ." Force link partner to " .link-speed,duplex ." as link-clock " | |
448 | user-link-clock master-link-clock = if | |
449 | ." slave" | |
450 | else | |
451 | ." master" | |
452 | then | |
453 | cr -1 throw | |
454 | then | |
455 | 2drop false | |
456 | ; | |
457 | ||
458 | \ Use non-autonegotiation only is both speed & duplex modes are specified | |
459 | : use-autonegotiation? ( -- flag ) | |
460 | user-speed auto-speed = user-duplex auto-duplex = or if | |
461 | true exit | |
462 | then | |
463 | user-speed 1000Mbps = if | |
464 | user-link-clock auto-link-clock = | |
465 | else | |
466 | false | |
467 | then | |
468 | ; | |
469 | ||
470 | : show-link-status ( -- ) | |
471 | phy-link-up? if | |
472 | chosen-speed chosen-duplex .link-speed,duplex ." Link up" | |
473 | else | |
474 | ." Link Down" | |
475 | then cr | |
476 | ; | |
477 | ||
478 | : disable-link-events ( -- ) | |
479 | pci-dev-id BCM-5704 = \ Rev a0 of the 5704 needs non-default | |
480 | pci-rev-id 0= and if \ timing. | |
481 | h# 8d68 h# 1c phy! \ bcm5704 PHY-MAC timing reg | |
482 | h# 8d68 h# 1c phy! \ needs to be written twice to stick | |
483 | then | |
484 | 0 h# 6844 breg! \ Make sure we're in auto-access mode | |
485 | h# 18 h# 404 breg-bset \ Clear Link Attentions (Enet MAC Status Reg) | |
486 | h# c0000 h# 454 breg-bset \ Disable auto polling (MI Mode Reg) | |
487 | 1 ms \ wait 40 us | |
488 | 2 h# 18 phy! \ Disable Wake on Lan | |
489 | h# 1a phy@ drop \ Read MDI Interrupt_Status Reg twice | |
490 | h# 1a phy@ drop \ to clear sticky bits | |
491 | h# fffd h# 1b phy! \ mask all interrupts except Link Status Change | |
492 | ; | |
493 | ||
494 | ||
495 | : setup-transceiver ( -- ok? ) | |
496 | reset-transceiver drop | |
497 | disable-link-events \ Should be turned off by reset but... | |
498 | check-phy-capability | |
499 | use-autonegotiation? if do-autonegotiation else set-speed&mode then | |
500 | show-link-status | |
501 | ; |