( Low-level MAC actions JCB 13:23 08/24/10)
================================================================
Initialization:
mac-cold
Packet reception and reading:
mac-fullness
mac-inoffset
mac@
macc@
mac@n
mac-consume
Packet construction and transmission:
mac-pkt-begin
mac-pkt-,
mac-pkt-c,
mac-pkt-d,
mac-pkt-2,
mac-pkt-3,
mac-pkt-,0
mac-pkt-s,
mac-pkt-src
packetout-off
mac!
macc!
mac-complete
mac-checksum
mac-send
================================================================
( NE2K JCB 10:23 11/08/10)
: ne2sel
false ether_cs_n ! ;
: ne2unsel
true ether_cs_n ! ;
: ne2a ( a -- )
pb_a ! ;
: ne2rc@ ( a -- u ) \ NE2 byte reg read
true ether_bhe_n !
true ether_aen !
ne2sel
ne2a
false pb_rd_n !
\ pause144
pb_d @ h# ff and
true pb_rd_n !
\ false ether_aen !
\ ne2unsel
;
: ne2rc! ( u a -- )
\ over hex2 s" -> " type dup hex2 cr
true ether_bhe_n !
ne2sel
ne2a
pb_d !
d# 0 ddir !
false pb_wr_n !
true pb_wr_n !
\ ne2unsel
d# 1 ddir !
;
: ne2r! ( u a -- )
over d# 8 rshift over 1+ ne2rc! ne2rc! ;
: ne2r. \ dump registers
d# 16 0do
d# 1000 0do pause144 loop
i hex2 space
i ne2rc@ hex4 cr
loop
;
h# 00 constant ne2-CR
h# 01 constant ne2-PSTART
h# 01 constant ne2-PAR0
h# 03 constant ne2-PAR2
h# 05 constant ne2-PAR4
h# 01 constant ne2-CR9346
h# 02 constant ne2-PSTOP
h# 03 constant ne2-BNRY
h# 04 constant ne2-TSR
h# 04 constant ne2-TPSR
h# 05 constant ne2-TBCR0
h# 05 constant ne2-NCR
h# 06 constant ne2-CPR
h# 06 constant ne2-TBCR1
h# 07 constant ne2-ISR
h# 07 constant ne2-CURR
h# 08 constant ne2-RSAR0
h# 08 constant ne2-CRDA0
h# 09 constant ne2-RSAR1
h# 09 constant ne2-CRDA1
h# 0A constant ne2-RBCR0
h# 0B constant ne2-RBCR1
h# 0C constant ne2-RSR
h# 0C constant ne2-RCR
h# 0D constant ne2-TCR
h# 0D constant ne2-CNTR0
h# 0E constant ne2-DCR
h# 0E constant ne2-CNTR1
h# 0F constant ne2-IMR
h# 0F constant ne2-CNTR2
h# 10 constant ne2-RDMAPORT
h# 14 constant ne2-MIIEEP
h# 15 constant ne2-TR
h# 17 constant ne2-GPOC
h# 17 constant ne2-GPI
h# 1F constant ne2-RSTPORT
: ne2-page0 h# 22 ne2-CR ne2rc! ;
: ne2-page1 h# 62 ne2-CR ne2rc! ;
: ne2-clrisr \ clear the ISR
h# ff ne2-ISR ne2rc! ;
: ne2r.2
s" Page 0" type cr
ne2-page0
ne2r.
s" Page 1" type cr
ne2-page1
ne2r.
ne2-page0 ;
( The MII interface JCB 12:47 11/09/10)
h# 08 constant MII_EEP_MDO
h# 04 constant MII_EEP_MDI
h# 01 constant MII_EEP_MDC
: eep-on ( u ) ne2-MIIEEP ne2rc@ or ne2-MIIEEP ne2rc! ;
: eep-off ( u ) invert ne2-MIIEEP ne2rc@ and ne2-MIIEEP ne2rc! ;
: miix ( u c -- u ) \ Send c bit data u
tuck
d# 16 swap - lshift
swap
0do
MII_EEP_MDO over 0< if
eep-on
else
eep-off
then
MII_EEP_MDC eep-on \ clock up
2*
ne2-MIIEEP ne2rc@ MII_EEP_MDI and if 1+ then
MII_EEP_MDC eep-off \ clock down
loop
;
: phy@ ( a -- u )
h# ffff d# 16 miix drop
h# ffff d# 16 miix drop
h# 0d0 d# 9 miix drop
d# 5 miix drop
h# 0 d# 1 miix drop
h# 0 d# 16 miix
;
: phy! ( u a -- )
h# ffff d# 16 miix drop
h# ffff d# 16 miix drop
h# 0b0 d# 9 miix drop
d# 5 miix drop
h# 2 d# 2 miix drop
d# 16 miix drop
;
: phy.
d# 32 0do
i hex2 space i phy@ hex4 cr
loop
cr
;
: phy-cold
\ h# b000 d# 0 phy!
h# 0800 d# 0 phy!
s" PHY power down for 2.5s" type cr
d# 2500000. sleepus
\ h# 1200 d# 0 phy!
h# 0000 d# 0 phy!
exit
sleep1
sleep1
sleep1
sleep1
sleep1
sleep1
\ h# 6030 d# 30 phy!
phy. sleep1
cr
phy.
;
: mac-cold ( ethaddr -- )
false RESET_TRIGGER !
sleep1
true RESET_TRIGGER !
sleep1
true pb_rd_n !
true pb_wr_n !
true ether_cs_n !
false ether_aen !
true ether_bhe_n !
d# 0 pb_a !
d# 1 ddir !
\ d# 4 0do ne2-RSTPORT ne2rc@ ne2-RSTPORT ne2rc! sleep1 loop
phy-cold
\ Wait for TR RST_B to go low and GPI link up
s" TR GPI" type cr
begin
ne2-TR ne2rc@ hex2 d# 3 spaces
ne2-GPI ne2rc@ hex2 d# 3 spaces
sleep.1
cr
ne2-TR ne2rc@ d# 2 and 0=
ne2-GPI ne2rc@ d# 1 and 0<> and
until
\ Wait for TR RST_B to go low
\ begin
\ sleep1
\ ne2-TR ne2rc@ dup hex2 cr
\ d# 2 and 0=
\ until
true if
h# 21 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 0
h# 00 ne2-DCR ne2rc! \ Selects byte-wide DMA transfers
h# 00 ne2-RBCR0 ne2rc! \ Load data byte count for remote DMA
h# 00 ne2-RBCR1 ne2rc!
h# 20 ne2-RCR ne2rc! \ Temporarily set receiver to monitor mode
h# 02 ne2-TCR ne2rc! \ Transmitter set to internal loopback mode
\ Initialize Receive Buffer Ring: Boundary Pointer
\ (BNDRY), Page Start (PSTART), and Page Stop
\ (PSTOP)
h# 46 ne2-PSTART ne2rc!
h# 46 ne2-BNRY ne2rc!
h# 80 ne2-PSTOP ne2rc!
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
h# 01 ne2-IMR ne2rc! \ Initialize interrupt mask
h# 61 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 1
h# 12 d# 1 ne2rc! \ Set Physical Address
h# 34 d# 2 ne2rc!
h# 56 d# 3 ne2rc!
h# 77 d# 4 ne2rc!
h# 77 d# 5 ne2rc!
h# 77 d# 6 ne2rc!
d# 16 d# 8 do \ Set multicast address
h# 00 i ne2rc!
loop
h# 47 ne2-CURR ne2rc! \ Initialize CURRent pointer
h# 22 ne2-CR ne2rc! \ Start the NIC, Abort DMA, page 0
h# 10 ne2-GPOC ne2rc! \ Select media interface
s" GPI = " type ne2-GPI ne2rc@ hex2 cr
h# 00 ne2-TCR ne2rc! \ Transmitter full duplex
h# 04 ne2-RCR ne2rc! \ Enable receiver and set accept broadcast
else
h# 21 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 0
sleep.1
h# 00 ne2-DCR ne2rc! \ Selects word-wide DMA transfers
h# 00 ne2-RBCR0 ne2rc! \ Load data byte count for remote DMA
h# 00 ne2-RBCR1 ne2rc!
h# 20 ne2-RCR ne2rc! \ Temporarily set receiver to monitor mode
h# 02 ne2-TCR ne2rc! \ Transmitter set to internal loopback mode
h# 40 ne2-TPSR ne2rc! \ Set Tx start page
\ Initialize Receive Buffer Ring: Boundary Pointer
\ (BNDRY), Page Start (PSTART), and Page Stop
\ (PSTOP)
h# 46 ne2-PSTART ne2rc!
h# 46 ne2-BNRY ne2rc!
h# 80 ne2-PSTOP ne2rc!
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
h# 01 ne2-IMR ne2rc! \ Initialize interrupt mask
h# 61 ne2-CR ne2rc! \ Stop the NIC, abort DMA, page 1
sleep.1
h# 12 d# 1 ne2rc! \ Set Physical Address
h# 34 d# 2 ne2rc!
h# 56 d# 3 ne2rc!
h# 77 d# 4 ne2rc!
h# 77 d# 5 ne2rc!
h# 77 d# 6 ne2rc!
d# 16 d# 8 do \ Set multicast address
h# ff i ne2rc!
loop
h# 47 ne2-CURR ne2rc! \ Initialize CURRent pointer
h# 20 ne2-CR ne2rc! \ DMA abort, page 0
h# 10 ne2-GPOC ne2rc! \ Select media interface
s" GPI = " type ne2-GPI ne2rc@ hex2 cr
h# 1c ne2-RCR ne2rc! \ Enable receiver and set accept broadcast
h# 00 ne2-TCR ne2rc! \ Transmitter full duplex
h# ff ne2-ISR ne2rc! \ Clear Interrupt Status Register (ISR) by writing 0FFh to it.
h# 22 ne2-CR ne2rc! \ Start the NIC, Abort DMA, page 0
then
;
: NicCompleteDma
h# 22 ne2-CR ne2rc! \ Complete remote DMA
;
: maca ( a -- ) \ set DMA address a
dup d# 8 rshift ne2-RSAR1 ne2rc! ne2-RSAR0 ne2rc! ;
: mac1b \ set DMA transfer for 1 byte
h# 01 ne2-RBCR0 ne2rc!
h# 00 ne2-RBCR1 ne2rc! ;
: mac2b \ set DMA transfer for 2 bytes
h# 02 ne2-RBCR0 ne2rc!
h# 00 ne2-RBCR1 ne2rc! ;
: macc@ ( a -- u )
maca mac1b
h# 0a ne2-CR ne2rc! \ running, DMA read
ne2-RDMAPORT ne2rc@
NicCompleteDma ;
: macc! ( u a -- )
maca mac1b
h# 12 ne2-CR ne2rc! \ running, DMA write
ne2-RDMAPORT ne2rc! ;
: mac@ ( a -- u )
maca mac2b
h# 0a ne2-CR ne2rc! \ running, DMA read
ne2-RDMAPORT ne2rc@ d# 8 lshift ne2-RDMAPORT ne2rc@ or
NicCompleteDma ;
: mac! ( u a -- )
maca mac2b
h# 12 ne2-CR ne2rc! \ running, DMA write
dup d# 8 rshift ne2-RDMAPORT ne2rc! ne2-RDMAPORT ne2rc! ;
: mac-dump ( a u -- )
bounds
begin
2dup u>
while
dup h# f and 0= if
cr dup hex4 [char] : emit space
then
dup mac@ hex4 space
2+
repeat 2drop cr ;
variable currpkt
: mac-inoffset ( u -- u ) \ compute offset into current incoming packet
currpkt @ +
dup 0< if
h# 8000 -
h# 4600 +
then
;
: mac@n ( n addr -- d0 .. dn )
swap 0do dup mac@ swap 2+ loop drop ;
( words for constructing packet data JCB 07:01 08/20/10)
variable writer
: mac-pkt-begin h# 4000 writer ! ;
: bump ( n -- ) writer +! ;
: mac-pkt-c, ( n -- ) writer @ macc! d# 1 bump ;
: mac-pkt-, ( n -- ) writer @ mac! d# 2 bump ;
: mac-pkt-d, ( d -- ) mac-pkt-, mac-pkt-, ;
: mac-pkt-2, ( n0 n1 -- ) swap mac-pkt-, mac-pkt-, ;
: mac-pkt-3, rot mac-pkt-, mac-pkt-2, ;
: mac-pkt-,0 ( n -- ) 0do d# 0 mac-pkt-, loop ;
: mac-pkt-s, ( caddr u -- )
0do
dup c@
mac-pkt-c,
1+
loop
drop
;
: mac-pkt-src ( n offset -- ) \ copy n words from incoming+offset
swap 0do
dup mac-inoffset mac@ mac-pkt-,
2+
loop
drop
;
: mac-pkt-complete ( -- length ) \ set up size
writer @ h# 4000 -
\ h# 4000 over mac-dump
dup ne2-TBCR0 ne2r! ;
: mac-checksum ( addr nwords -- sum )
d# 0 swap
0do
over mac@ ( addr sum v )
+1c
swap 2+ swap
loop
nip
invert
;
: mac-snap
s" CR PSTART PSTOP BNRY TSR NCR CPR ISR CRDA0 CRDA1 - - RSR CNTR0 CNTR1 CNTR2" type cr
d# 16 0do
i ne2rc@ hex2 d# 5 spaces
loop
;
: mac-fullness ( -- f )
ether_irq @ if
ne2-BNRY ne2rc@ 1+ ne2-CPR ne2rc@ <> dup if
\ mac-snap
ne2-BNRY ne2rc@ 1+ d# 8 lshift d# 4 + currpkt !
\ s" currpkt=" type currpkt @ hex4 space
\ currpkt @ d# 4 - macc@ hex2
\ cr
\ currpkt @ d# 4 - d# 16 mac-dump
else
ne2-clrisr
then
else
false
then
;
: mac-consume ( -- ) \ finished with current packet, move on
ne2-BNRY ne2rc@ 1+ d# 8 lshift 1+ macc@ \ next pkt
1- ne2-BNRY ne2rc!
;
variable ne2cold
: mac-send
ne2cold @ 0= if
h# 21 ne2-CR ne2rc!
h# 22 ne2-CR ne2rc!
true ne2cold !
then
h# 40 ne2-TPSR ne2rc!
h# 26 ne2-CR ne2rc! \ START
;
: packetout-off \ compute offset in output packet
h# 4000 + ;
: nicwork
\ ISA mode
\ begin
s" TR= " type h# 15 ne2rc@ hex2 space
s" ether_irq=" type ether_irq @ hex1 space
s" ISR=" type ne2-ISR ne2rc@ hex2 space
cr
\ again
false if
h# 0000 ne2-RSAR0 ne2r!
cr
d# 16 0do
ne2-RDMAPORT ne2rc@ hex2 space
loop
cr
then
s" CR PSTART PSTOP BNRY TSR NCR CPR ISR CRDA0 CRDA1 - - RSR CNTR0 CNTR1 CNTR2" type cr
begin
d# 16 0do
i ne2rc@ hex2 d# 5 spaces
loop
ether_irq @ hex1
cr
sleep1
ne2-CPR ne2rc@ h# 47 <>
until
\ h# 4700 h# 100 mac-dump
\ cr
\ h# 0947 h# 4700 mac!
\ h# 4700 h# 100 mac-dump
;