Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / network / ophir / phy.fth
\ ========== Copyright Header Begin ==========================================
\
\ Hypervisor Software File: phy.fth
\
\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
\
\ - Do no alter or remove copyright notices
\
\ - Redistribution and use of this software in source and binary forms, with
\ or without modification, are permitted provided that the following
\ conditions are met:
\
\ - Redistribution of source code must retain the above copyright notice,
\ this list of conditions and the following disclaimer.
\
\ - Redistribution in binary form must reproduce the above copyright notice,
\ this list of conditions and the following disclaimer in the
\ documentation and/or other materials provided with the distribution.
\
\ Neither the name of Sun Microsystems, Inc. or the names of contributors
\ may be used to endorse or promote products derived from this software
\ without specific prior written permission.
\
\ This software is provided "AS IS," without a warranty of any kind.
\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
\
\ You acknowledge that this software is not designed, licensed or
\ intended for use in the design, construction, operation or maintenance of
\ any nuclear facility.
\
\ ========== Copyright Header End ============================================
id: @(#)phy.fth 1.2 06/07/14
purpose: Intel Ophir/82571 transceiver routines
copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
copyright: Use is subject to license terms.
headerless
0 value an-debug?
\ Put PHY in loopback mode temporarily to bring the link down
: force-link-down ( -- )
phy-cr@ phycr.loopback or phy-cr!
d# 1000 ms
phy-cr@ phycr.loopback invert and phy-cr!
;
: phy-reset-complete? ( -- flag ) phy-cr@ phycr.reset and 0= ;
: wait-phy-reset ( -- flag )
d# 700 ['] phy-reset-complete? wait-status
;
: (reset-transceiver) ( -- ok? )
phy-cr@ phycr.reset or phy-cr!
wait-phy-reset
;
: reset-transceiver ( -- ok? )
d# 15000 get-msecs + false
begin
over timed-out? 0= over 0= and
while
(reset-transceiver) if drop true then
repeat nip
dup 0= if ." Failed to reset transceiver!" cr exit then
phy-cr@ phycr.speed-100 invert and phycr.duplex invert and phy-cr!
;
: disable-auto-nego ( -- )
an-debug? if ." Disabling Autonegotiation" cr then
phy-cr@ phycr.an-enable invert and phy-cr!
;
: enable-auto-nego ( -- )
an-debug? if ." Enabling Autonegotiation" cr then
phy-cr@ phycr.an-enable phycr.an-restart or or phy-cr!
;
: an-link-speed&mode ( -- speed duplex-mode )
phy-sr@ physr.ext-status and if
phy-1000-sr@ h# c00 and d# 10 rshift
phy-1000-cr@ h# 300 and d# 8 rshift and ( 1000bt-common-cap )
d# 10 lshift
dup gsr.lp-1000fdx and if drop 1000Mbps full-duplex exit then
gsr.lp-1000hdx and if 1000Mbps half-duplex exit then
then
phy-anlpar@ phy-anar@ and ( an-common )
dup anlpar.100fdx and if drop 100Mbps full-duplex exit then
dup anlpar.100hdx and if drop 100Mbps half-duplex exit then
dup anlpar.10fdx and if drop 10Mbps full-duplex exit then
dup anlpar.10hdx and if drop 10Mbps half-duplex exit then
;
\ Interpret and apply the "supported-network-types" property if it exists
: supported-speed&mode ( speed mode$ -- bit-mask )
rot case
10Mbps of
" half" $= if h# 1 else h# 2 then
endof
100Mbps of
" half" $= if h# 4 else h# 8 then
endof
1000Mbps of
" half" $= if h# 10 else h# 20 then
endof
( default ) 2drop 0 swap
endcase
;
: parse-supported-abilities ( str$ -- abilities )
base @ >r decimal
ascii , left-parse-string 2drop
ascii , left-parse-string $number drop -rot ( speed str$ )
ascii , left-parse-string 2drop ( speed mode$ )
supported-speed&mode ( bit-mask )
r> base !
;
: get-supported-abilities ( phy-abilty -- phy-abilty | abilty )
" supported-network-types" get-my-property 0= if
begin
decode-string ?dup
while ( phy-abilty str1$ str2$ )
parse-supported-abilities ( phy-abilty str1$ mask )
3 roll swap xor -rot ( phy-abilty' str1$ )
repeat 3drop ( phy-abilty' )
invert h# 3f and ( abilty )
then
;
: phy-abilities ( -- abilities )
phy-sr@ d# 11 rshift h# f and
gmii-phy? if phy-esr@ d# 12 rshift h# 3 and else 0 then d# 4 lshift or
( phy-abilty ) get-supported-abilities ( abilities )
;
\ Construct bit-mask abilities based on speed, duplex mode settings
\ 0000.0001 10Mbps, Half Duplex
\ 0000.0010 10Mbps, Full Duplex
\ 0000.0100 100Mbps, Half Duplex
\ 0000.1000 100Mbps, Full Duplex
\ 0001.0000 1000Mbps, Half Duplex
\ 0010.0000 1000Mbps, Full Duplex
: construct-abilities ( speed duplex-mode -- abilities )
phy-abilities
swap case
half-duplex of h# 15 endof \ Mask FDX abilities
full-duplex of h# 2a endof \ Mask HDX abilities
auto-duplex of h# 3f endof
endcase and
swap case
10Mbps of h# 3 endof
100Mbps of h# c endof
1000Mbps of h# 30 endof
auto-speed of h# 3f endof
endcase and
;
: publish-capabilities ( -- )
user-speed user-duplex construct-abilities ( abilities )
dup h# f and d# 5 lshift anar.selector-field or phy-anar! ( abilities )
gmii-phy? if ( abilities )
h# 30 and d# 4 lshift ( 1000-cap )
user-link-clock auto-link-clock <> if
gcr.ms-cfg-enable or
user-link-clock master-link-clock = if
gcr.ms-cfg-value or
then
then
phy-1000-cr!
else ( abilities )
drop ( )
then ( )
;
: match-capabilities ( -- ok? )
phy-sr@ physr.ext-status and if
phy-1000-sr@ h# c00 and d# 10 rshift
phy-1000-cr@ h# 300 and d# 8 rshift
and 0<>
else
0
then
phy-anlpar@ phy-anar@ and 0<> or
;
\ Autonegotiation may take as much as 5 seconds with 10/100 BaseT PHYs
: wait-autoneg-complete ( -- complete? )
d# 5000 get-msecs + false
begin
over timed-out? 0=
over 0= and
while
d# 20 ms
phy-sr@ physr.an-complete and if
drop true
then
repeat nip
;
: phy-link-up? ( -- up? )
phy-sr@ drop
phy-sr@ physr.link-up and
;
: link-up? ( -- flag ) phy-link-up? ;
: wait-link-up? ( -- up? )
wait-phy-reset drop
d# 2000 ['] phy-link-up? wait-status
;
: (autonegotiate) ( -- link-up? )
\ Advertise my capabilities & start auto negotiation
publish-capabilities
enable-auto-nego
\ Wait for auto negotiation to complete
wait-autoneg-complete
0= if
." Timed out waiting for Autonegotation to complete" cr
false exit
then
\ Check if autonegotation completed by parallel detection,
\ and if so, whether there are any parallel detect (multiple
\ link fault) errors
phy-aner@ dup aner.lp-an-able and 0= swap aner.mlf and and if
." Multiple link faults seen during Autonegotiation" cr
false exit
then
\ Check for common capabilities
match-capabilities 0= if
." System and network incompatible for communicating" cr
false exit
then
\ Valid Link established?
phy-link-up?
;
: do-autonegotiation ( -- link-up? )
(autonegotiate) if
an-link-speed&mode set-chosen-speed&duplex
true
else
." Check cable and try again" cr
false
then
;
: check-phy-capability ( -- )
user-speed user-duplex 2dup construct-abilities 0= if
." Not capable of " .link-speed,duplex
-1 throw
else
2drop
then
;
\ Set/Force link speed and mode, and check link status
\ For 1Gbps, we manually configure local PHY as SLAVE
: speed&mode-possible? ( speed duplex-mode -- link-up? )
over 1000Mbps = if
gcr.ms-cfg-enable
user-link-clock master-link-clock = if
gcr.ms-cfg-value or
then
phy-1000-cr!
then
phy-cr@ b# 0010.0001.0100.0000 invert and \ Mask speed & duplex bits
swap full-duplex = if phycr.duplex or then
swap case
10Mbps of phycr.speed-10 endof
100Mbps of phycr.speed-100 endof
1000Mbps of phycr.speed-1000 endof
endcase or
phy-cr!
wait-link-up?
;
: set-speed&mode ( -- link-up? )
disable-auto-nego
force-link-down
user-speed user-duplex
2dup speed&mode-possible? if set-chosen-speed&duplex true exit then
over 1000Mbps = if
." Cannot bringup link using non-autonegotation." cr
." Force link partner to " .link-speed,duplex ." as link-clock "
user-link-clock master-link-clock = if
." slave"
else
." master"
then
cr -1 throw
then
2drop false
;
: use-autonegotiation? ( -- flag )
user-speed auto-speed = user-duplex auto-duplex = or if
true exit
then
user-speed 1000Mbps = if
user-link-clock auto-link-clock =
else
false
then
;
: show-link-status ( -- )
phy-link-up? if
chosen-speed chosen-duplex .link-speed,duplex ." Link up"
else
." Link Down"
then cr
;
: setup-transceiver ( -- ok? )
reset-transceiver drop
\ disable-link-events \ Should be turned off by reset but...
check-phy-capability
use-autonegotiation? if do-autonegotiation else set-speed&mode then
show-link-status
;