( 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 ;