507 lines
12 KiB
Forth
507 lines
12 KiB
Forth
( 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
|
|
;
|