\ ========== Copyright Header Begin ==========================================
\ Hypervisor Software File: core.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
\ - 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
\ ========== Copyright Header End ============================================
id: @(#)core.fth 1.2 06/05/11
purpose: Intel Ophir/82571 Core routines
copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
copyright: Use is subject to license terms.
0 instance value restart?
defer restart-net ['] true to restart-net
\ ============================================================================
\ ----------------------------------------------------------------------------
/x field >rx-buf \ Pointer to data buffer
/w field >rx-length \ Length of data buffer
/w field >rx-csum \ Checksum
/w field >rx-special \ Special - unused (needed for VLAN)
h# 01 constant rxstat.dd \ Descriptor done
h# 02 constant rxstat.eop \ End of packet
h# 04 constant rxstat.ixsm \ Ignore checksum indication
h# 01 constant rxerr.ce \ CRC or alignment error
h# 02 constant rxerr.se \ Symbol error (TBI)
h# 04 constant rxerr.seq \ Sequence error (TBI)
\ Ignore other errors - applicable to
\ Miscellaneous rx constants and pointers
h# 40 constant #rxds \ Number of rx descriptors
#rxds /rxd * constant /rxd-ring \ Size of rx descriptor table
0 value rxd-base \ Base of descriptor table
0 value rxd-end \ End of descriptor table in bytes.
0 value rxd-tail \ Shadow of hardware tail pointer.
0 value rxd-dma-base \ Hardware address of descriptor array.
d# 2048 constant /rx-buf \ Size of one rx buffer
constant /rx-buf-array \ Total amount of memory allocated for
0 value rx-buf-base \ Base of rx buffer array
/x field >tx-buf \ Pointer to data buffer
/w field >tx-length \ Length of data buffer
/c field >tx-cso \ Checksum offset (optional)
/c field >tx-cmd \ Command
/c field >tx-css \ Checksum Start field (optional)
/w field >tx-special \ Special - unused (needed for VLAN)
h# 01 constant txcmd.eop \ End of packet
h# 02 constant txcmd.ifcs \ Insert Frame checksum
h# 08 constant txcmd.rs \ Report status
h# 01 constant txstat.dd \ Descriptor done.
h# 02 constant txstat.ec \ Excess collisions
h# 04 constant txstat.lc \ Late collision
\ TX constants and pointers
h# 8 constant #txds \ Number of tx descriptors
\ (8 is the smallest possible)
#txds /txd * constant /tx-ring \ Size of tx descriptor table
0 value txd-base \ Base of descriptor table
0 value txd-end \ End of descriptor table in bytes
0 value txd-current \ Currently being transmitted buffer
0 value txd-tail \ Shadow of hardware tail pointer
0 value txd-dma-base \ Hardware address of descriptor array
d# 2048 constant /tx-buf \ Size of one tx buffer
constant /tx-buf-array \ Total amount of memory
\ allocated for tx buffers.
0 value tx-buf-base \ Base of tx buffer array
\ Memory layout: starting from cpu-dma-blk (which is therefore the same
\ ========== ===== ========
\ rxd-base /rxd-ring rx descriptors
\ rx-buf-base /rx-buf-array rx data buffers
\ txd-base /tx-ring tx descriptors
\ tx-buf-base /tx-buf-array tx buffers
\ Set value of /dma-blk for "map-buffers"
/rxd-ring /rx-buf-array + ( /rx-data )
/tx-ring /tx-buf-array + ( /rx-data /tx-data )
+ /rxd + is /dma-blk \ Add /rxd to allow for alignment rounding.
: rxd>d# ( desc -- index )
\ Write a value to the rx tail register
: txd>d# ( desc -- index )
\ Write a value to the tx tail register
txd-base - /txd / h# 3818 reg!
\ Initialize the rx and tx descriptor rings and buffers.
\ We aren't telling the hardware about these yet.
." Head: " h# 2810 reg@ .x
." Tail: " h# 2818 reg@ .x cr
dup i /rxd * + ( adr desc )
dup local-x@ .x /x + local-x@ .x cr
." Head: " h# 3810 reg@ .x
." Tail: " h# 3818 reg@ .x cr
dup local-x@ .x /x + local-x@ .x cr
dup >r ( base ) ( r: base )
/rxd round-up ( desc-base ) \ Align descriptor base
\ Tail starts off as first descriptor (head will be second)
\ That is, all buffers start off belonging to the chip,
\ except the tail itself.
cpu>io-adr is rxd-dma-base ( )
rxd-base /rxd-ring + dup is rx-buf-base is rxd-end
i /rx-buf * rx-buf-base + cpu>io-adr ( dma-adr )
i /rxd * rxd-base + tuck ( desc-adr dma-adr desc-adr )
\ Write the buffer address to the descriptor
>rx-buf local-x! ( desc-adr )
\ Clear the flags (buffer belongs to hw)
0 swap >rx-length local-x! ( )
rx-buf-base /rx-buf-array + is txd-base
txd-base /tx-ring + dup is tx-buf-base is txd-end
txd-base cpu>io-adr is txd-dma-base
i /tx-buf * tx-buf-base + cpu>io-adr ( dma-adr )
i /txd * txd-base + tuck ( desc dma-adr desc )
\ Write the buffer address to the descriptor
>tx-buf local-x! ( desc )
\ Clear the rest of the descriptor
0 over >tx-length local-x! ( desc )
\ Initialize command register.
txcmd.rs txcmd.eop or txcmd.ifcs or swap >tx-cmd local-c!
\ Sync it all back to mem.
r> dup cpu>io-adr /dma-blk dma-sync ( ) ( r: )
\ ============================================================================
\ ----------------------------------------------------------------------------
\ Move to the next rx descriptor in the ring (ie
: next-rxd ( desc -- next-desc )
: sync-rxd ( desc -- ) dup cpu>io-adr /rxd dma-sync ;
: sync-rx-buf ( desc -- ) >rx-buf local@ dup io>cpu-adr swap /rx-buf dma-sync ;
: return-buffer ( handle -- )
0 over >rx-status local-c! ( desc )
0 over >rx-length local-w!
: receive-ready? ( -- pkt-waiting? )
>rx-status local-c@ ( status )
rxstat.dd and 0<> ( pkt-waiting? )
: receive ( -- pkt-handle pkt pktlen )
rxd-tail next-rxd ( desc )
dup >rx-buf local-x@ io>cpu-adr ( desc pkt )
over >rx-length local-w@ ( desc pkt len desc )
\ ============================================================================
\ ----------------------------------------------------------------------------
\ Move to the next tx descriptor in the ring (ie
: next-txd ( desc -- next-desc )
: sync-tx-buf ( desc -- )
\ Might as well sync the descriptor here also.
dup dup cpu>io-adr /txd dma-sync
>tx-buf local-x@ dup io>cpu-adr swap /tx-buf dma-sync
: transmit-complete? ( desc -- complete? )
>tx-status local-c@ txstat.dd and 0<>
\ Wait for up to 4 seconds for the transmit to complete.
: send-wait ( desc -- ok? )
d# 4000 get-msecs + ( desc tout )
dup get-msecs >= while ( desc tout )
over transmit-complete? if
" Timeout waiting for transmit completion" diag-type-cr
: transmit ( buf len -- ok? )
txd-tail >r ( buf len ) ( r: desc )
dup r@ >tx-length local-w! \ Set length
r@ >tx-buf local-x@ io>cpu-adr swap cmove ( ) \ Copy data
\ Increment shadow tail pointer.
r> dup next-txd dup to txd-tail ( desc desc' ) ( r: )
\ Write updated tail pointer to hardware (starts transmit)
\ Wait for the transmit to complete.
\ At this point, errors we can see are:
\ Timeout waiting for send to complete - maybe need to restart net
: get-tx-buffer ( -- adr )
txd-tail >tx-buf local@ io>cpu-adr
\ ============================================================================
\ Initialization routines
\ ----------------------------------------------------------------------------
\ Control register: address 0x0000
: ctrl@ ( -- value ) 0 reg@ ;
: ctrl! ( value -- ) 0 reg! ;
1 d# 26 << constant ctrl.rst
1 d# 05 << constant ctrl.asde
1 d# 06 << constant ctrl.slu
\ Receive address registers:
\ Set receive address low register[i]
\ Set the i'th receive address hi register[i]
\ Assume reset has completed.
: clear-multicast-table ( -- )
\ Set the mac address in the receive address 0 registers.
\ Clear the remaining registers and the multicast table array.
mac-address drop ( mac-adr-ptr )
over 2 + w@ wbflip wljoin 0 ral! ( mac-adr-ptr )
4 + w@ wbflip h# 8000.0000 or 0 rah!
\ Clear remaining receive address registers.
h# 18 h# 0100 reg-bset \ Set upe and mpe
promiscuous of set-promis-mode endof
0 h# 2820 reg! \ Clear receive delay timer
0 h# 282c reg! \ Clear receive absolute timer reg
/rxd-ring h# 2808 reg! \ Set receive descriptor length reg
\ Set the rx descriptor base address
rxd-base cpu>io-adr xlsplit h# 2804 reg! ( base.lo ) \ hi
rxd-tail rx-tail! \ Set tail (precalculated in init-rings)
\ Give all the buffers to the chip: the tail pointer has already
\ been initialized by init-rings - set the head to be the next descriptor.
h# 0001.0101 h# 2828 reg! \ rx descriptor control
\ Store bad packets: 0000.0004 Off.
\ Promiscuous bits: 0000.0018 Off.
\ Long packet enable: 0000.0020 Off.
\ Loopback mode: 0000.00c0 No loopback
\ RDMTS 0000.0300 Don't care. 0 is ok.
\ Multicast offset: 0000.3000 Don't care. 0 is ok.
\ Accept broadcast: 0000.8000 On.
\ Receive buf size: 0003.0000 0 == 2048 byte buffers.
\ Vlan Filter: 0004.0000 Off
\ CFI bits: 0018.0000 Off.
\ Discard pause frames: 0040.0000 On.
\ Pass mac control: 0080.0000 Off.
\ BSEX: 0200.0000 Off. None of that thank you!
\ Strip crc: 0400.0000 Off.
h# 0040.8002 h# 0100 reg-bset \ Now receiving!
\ Set transmit descriptor base address
txd-base cpu>io-adr xlsplit h# 3804 reg! ( base.lo ) \ hi
/tx-ring h# 3808 reg! \ Transmit descriptor ring length
\ Start the head and tail pointers pointing to the same value
\ (doesn't matter which it is).
txd-tail tx-tail! \ Transmit descriptor tail
txd-tail txd>d# h# 3810 reg! \ Transmit descriptor head
h# 60200a h# 0410 reg! \ Inter-packet gap register.
\ Pad short packets: 0000.0004 On (per manual)
\ Collision threshold: 0000.00f0 Value = 0xf (recommended)
\ Collision distance: 0020.0000 0x40 bytes (half-duplex)
\ Software xoff 0040.0000 Off
\ Retransmit on late col: 0100.0000 Off
ctrl.slu ctrl.asde or ctrl! \ Set control register - enable PHY
0 h# 00c8 reg! \ Clear all interrupt cause set bits
h# ffff.ffff h# 00d8 reg! \ Mask all interrupts.
0 h# 0178 reg! \ Clear txcw
cpu-dma-base init-rings \ Initialize the memory structures
2 h# 100 reg-bclear \ Disable rx
2 h# 400 reg-bclear \ Disable tx