URL
https://opencores.org/ocsvn/rtf65002/rtf65002/trunk
Subversion Repositories rtf65002
[/] [rtf65002/] [trunk/] [software/] [asm/] [ethernet.asm] - Rev 40
Compare with Previous | Blame | View Log
; ============================================================================; __; \\__/ o\ (C) 2014 Robert Finch, Stratford; \ __ / All rights reserved.; \/_// robfinch<remove>@opencores.org; ||;;; This source file is free software: you can redistribute it and/or modify; it under the terms of the GNU Lesser General Public License as published; by the Free Software Foundation, either version 3 of the License, or; (at your option) any later version.;; This source file is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program. If not, see <http://www.gnu.org/licenses/>.;; ============================================================================;;==============================================================================; Ethernet test code;==============================================================================my_MAC1 EQU 0x00my_MAC2 EQU 0xFFmy_MAC3 EQU 0xEEmy_MAC4 EQU 0xF0my_MAC5 EQU 0xDAmy_MAC6 EQU 0x42; r1 = PHY; r2 = regnum; r3 = data;eth_mii_write:phaphxpush r4ld r4,#ETHMACasl r2,r2,#8or r1,r1,r2sta ETH_MIIADDRESS,r4sty ETH_MIITX_DATA,r4lda #ETH_WCTRLDATAsta ETH_MIICOMMAND,r4stz ETH_MIICOMMAND,r4emiw1:lda ETH_MIISTATUS,r4bit #ETH_MIISTATUS_BUSYbne emiw1pop r4plxplarts; r1 = PHY; r2 = regeth_mii_read:phxphyldy #ETHMACasl r2,r2,#8or r1,r1,r2sta ETH_MIIADDRESS,ylda #ETH_MIICOMMAND_RSTATsta ETH_MIICOMMAND,ystz ETH_MIICOMMAND,yemir1:lda ETH_MIISTATUS,ybit #ETH_MIISTATUS_BUSYbne emir1lda ETH_MIIRX_DATA,yplyplxrtspublic ethmac_setup:ld r4,#ETHMAClda #ETH_MIIMODER_RSTsta ETH_MIIMODER,r4lda ETH_MIIMODER,r4and #~ETH_MIIMODER_RSTsta ETH_MIIMODER,r4lda #$10 ; /16=1.25MHzsta ETH_MIIMODER,r4 ; Clock divider for MII Management interfacelda #ETH_MODER_RSTsta ETH_MODER,r4lda ETH_MODER,r4and #~ETH_MODER_RSTsta ETH_MODER,r4stz ETH_MIITX_DATA,r4stz ETH_MIIADDRESS,r4stz ETH_MIICOMMAND,r4lda #0xEEF0DA42sta ETH_MAC_ADDR0,r4 ; MAC0lda #0x00FFsta ETH_MAC_ADDR1,r4 ; MAC1lda #-1sta ETH_INT_SOURCE,r4; Advertise support for 10/100 FD/HDlda #ETH_PHYldx #ETH_MII_ADVERTISEjsr eth_mii_reador r3,r1,#ETH_ADVERTISE_ALLlda #ETH_PHYldx #ETH_MII_ADVERTISEjsr eth_mii_write; Do NOT advertise support for 1000BTlda #ETH_PHYldx #ETH_MII_CTRL1000jsr eth_mii_readand r3,r1,#~(ETH_ADVERTISE_1000FULL|ETH_ADVERTISE_1000HALF)lda #ETH_PHYldx #ETH_MII_CTRL1000jsr eth_mii_write; Disable 1000BTlda #ETH_PHYldx #ETH_MII_EXPANSIONjsr eth_mii_readand r3,r1,#~(ETH_ESTATUS_1000_THALF|ETH_ESTATUS_1000_TFULL)ldx #ETH_MII_EXPANSIONjsr eth_mii_write; Restart autonegotiationlda #0ldx #ETH_MII_BMCRjsr eth_mii_readand r3,r1,#~(ETH_BMCR_ANRESTART|ETH_BMCR_ANENABLE)lda #7jsr eth_mii_write; Enable BOTH the transmiter and receiverlda #$A003sta ETH_MODER,r4rts; Initialize the ethmac controller.; Supply a MAC address, set MD clock;message "eth_init"public eth_init:phaphyldy #ETHMAClda #$A003sta ETH_MODER,y; lda #0x64 ; 100; sta ETH_MIIMODER,y; lda #7 ; PHY address; sta ETH_MIIADDRESS,ylda #0xEEF0DA42sta ETH_MAC_ADDR0,y ; MAC0lda #0x00FFsta ETH_MAC_ADDR1,y ; MAC1plyplarts; Request a packet and display on screen; r1 = address where to put packet;message "eth_request_packet"public eth_request_packet:phxphypush r4push r5ldy #ETHMACldx #4 ; clear rx interruptstx ETH_INT_SOURCE,ysta 0x181,y ; storage addressldx #0xe000 ; enable interruptstx 0x180,yeth1:nopldx ETH_INT_SOURCE,ybit r2,#4 ; get bit #2beq eth1ldx 0x180,y ; get from descriptorlsr r2,r2,#16ldy #0phajsr GetScreenLocationadd r4,r1,3780 ; second last line of screenplaeth20:add r5,r1,r3lb r2,0,r5 ; get byteadd r5,r4,r3stx (r5) ; store to screeninycpy #83bne eth20pop r5pop r4plyplxrts; r1 = packet address;message "eth_interpret_packet"public eth_interpret_packet:phxphylb r2,12,r1lb r3,13,r1cpx #8 ; 0x806 ?bne eth2cpy #6bne eth2lda #2 ; return r1 = 2 for ARPeth5:plyplxrtseth2:cpx #8bne eth3 ; 0x800 ?cpy #0bne eth3lb r2,23,r1cpx #1bne eth4lda #1bra eth5 ; return 1 ICMPeth4:cpx #$11bne eth6lda #3 ; return 3 for UDPbra eth5eth6:cpx #6bne eth7lda #4 ; return 4 for TCPbra eth5eth7:eth3:eor r1,r1,r1 ; return zero for unknownplyplxrts; r1 = address of packet to send; r2 = packet length;message "eth_send_packet"public eth_send_packet:phxphypush r4ldy #ETHMAC; wait for tx buffer to be cleareth8:ld r4,0x100,ybit r4,#$8000bne eth8ld r4,#1 ; clear tx interruptst r4,ETH_INT_SOURCE,y; set addresssta 0x101,y; set the packet length field and enable interruptsasl r2,r2,#16or r2,r2,#0xF000stx 0x100,ypop r4plyplxrts; Only for IP type packets (not ARP); r1 = rx buffer address; r2 = swap flag; Returns:; r1 = data start index;message "eth_build_packet"public eth_build_packet:phypush r4push r5push r6push r7push r8push r9push r10lb r3,6,r1lb r4,7,r1lb r5,8,r1lb r6,9,r1lb r7,10,r1lb r8,11,r1; write to destination headersb r3,0,r1sb r4,1,r1sb r5,2,r1sb r6,3,r1sb r7,4,r1sb r8,5,r1; write to source headerld r3,#my_MAC1sb r3,6,r1ld r3,#my_MAC2sb r3,7,r1ld r3,#my_MAC3sb r3,8,r1ld r3,#my_MAC4sb r3,9,r1ld r3,#my_MAC5sb r3,10,r1ld r3,#my_MAC6sb r3,11,r1cmp r2,#1bne eth16 ; if (swap)lb r3,26,r1lb r4,27,r1lb r5,28,r1lb r6,29,r1; read destinationlb r7,30,r1lb r8,31,r1lb r9,32,r1lb r10,33,r1; write to sendersb r7,26,r1sb r8,27,r1sb r9,28,r1sb r10,29,r1; write destinationsb r3,30,r1sb r4,31,r1sb r5,32,r1sb r6,33,r1eth16:ldy eth_unique_idinysty eth_unique_idsb r3,19,r1lsr r3,r3,#8sb r3,18,r1lb r3,14,r1and r3,r3,#0xFasl r3,r3,#2 ; *4add r1,r3,#14 ; return datastart in r1pop r10pop r9pop r8pop r7pop r6pop r5pop r4plyrts; Compute IPv4 checksum of header; r1 = packet address; r2 = data start;message "eth_checksum"public eth_checksum:phypush r4push r5push r6; set checksum to zerostz 24,r1stz 25,r1eor r3,r3,r3 ; r3 = sum = zerold r4,#14eth15:ld r5,r2dec r5 ; r5 = datastart - 1cmp r4,r5bpl eth14add r6,r1,r4lb r5,0,r6 ; shi = [rx_addr+i]lb r6,1,r6 ; slo = [rx_addr+i+1]asl r5,r5,#8or r5,r5,r6 ; shiloadd r3,r3,r5 ; sum = sum + shiloadd r4,r4,#2 ; i = i + 2bra eth15eth14:ld r5,r3 ; r5 = sumand r3,r3,#0xfffflsr r5,r5,#16add r3,r3,r5eor r3,r3,#-1sb r3,25,r1 ; low bytelsr r3,r3,#8sb r3,24,r1 ; high bytepop r6pop r5pop r4plyrts; r1 = packet address; returns r1 = 1 if this IP;message "eth_verifyIP"public eth_verifyIP:phxphypush r4push r5lb r2,30,r1lb r3,31,r1lb r4,32,r1lb r5,33,r1; Check for general broadcastcmp r2,#$FFbne eth11cmp r3,#$FFbne eth11cmp r4,#$FFbne eth11cmp r5,#$FFbne eth11eth12:lda #1eth13:pop r5pop r4plyplxrtseth11:ld r1,r2asl r1,r1,#8or r1,r1,r3asl r1,r1,#8or r1,r1,r4asl r1,r1,#8or r1,r1,r5cmp #$C0A8012A ; 192.168.1.42beq eth12eor r1,r1,r1bra eth13msgEthTestdb CR,LF,"Ethernet test - press CTRL-C to exit.",CR,LF,0message "eth_main"public eth_main:jsr RequestIOFocusjsr ClearScreenjsr HomeCursorlda #msgEthTestjsr DisplayStringB; jsr eth_initjsr ethmac_setupeth_loop:jsr KeybdGetCharcmp #-1beq eth17cmp #CTRLCbne eth17lda #$A000 ; tunr off transmit/recievesta ETH_MODER+ETHMACjsr ReleaseIOFocusrtseth17lda #eth_rx_buffer<<2 ; memory address zerojsr eth_request_packetjsr eth_interpret_packet ; r1 = packet typecmp #1bne eth10ld r2,r1 ; save off r1, r2 = packet typelda #eth_rx_buffer<<2 ; memory address zerojsr eth_verifyIPtaytxa ; r1 = packet type againcpy #1bne eth10lda #eth_rx_buffer<<2 ; memory address zeroldx #1jsr eth_build_packettay ; y = icmpstartlda #eth_rx_buffer<<2 ; memory address zeroadd r4,r1,r3sb r0,0,r4 ; [rx_addr+icmpstart] = 0lb r2,17,r1add r2,r2,#14 ; r2 = lenld r6,r2 ; r6 = lenadd r15,r1,r3lb r4,2,r15 ; shilb r5,3,r15 ; sloasl r4,r4,#8or r4,r4,r5 ; sum = {shi,slo};eor r4,r4,#-1 ; sum = ~sumsub r4,r4,#0x800 ; sum = sum - 0x800eor r4,r4,#-1 ; sum = ~sumadd r15,r1,r3sb r4,3,r15lsr r4,r4,#8sb r4,2,r15tyxjsr eth_checksumlda #eth_rx_buffer<<2 ; memory address zerold r2,r6jsr eth_send_packetjmp eth_loopeth10:; r2 = rx_addrcmp #2bne eth_loop ; Do we have ARP ?; xor r2,r2,r2 ; memory address zeroldx #eth_rx_buffer<<2; get the opcodelb r13,21,xcmp r13,#1bne eth_loop ; ARP request; get destination IP addresslb r9,38,xlb r10,39,xlb r11,40,xlb r12,41,x; set r15 = destination IPld r15,r9asl r15,r15,#8or r15,r15,r10asl r15,r15,#8or r15,r15,r11asl r15,r15,#8or r15,r15,r12; Is it our IP ?cmp r15,#$C0A8012A ; //192.168.1.42bne eth_loop; get source IP addresslb r5,28,xlb r6,29,xlb r7,30,xlb r8,31,x; set r14 = source IPld r14,r5asl r14,r14,#8or r14,r14,r6asl r14,r14,#8or r14,r14,r7asl r14,r14,#8or r14,r14,r8; Get the source MAC addresspush r6push r7push r8push r9push r10push r11lb r6,22,xlb r7,23,xlb r8,24,xlb r9,25,xlb r10,26,xlb r11,27,x; write to destination headersb r6,0,xsb r7,1,xsb r8,2,xsb r9,3,xsb r10,4,xsb r11,5,x; and write to ARP destinationsb r6,32,xsb r7,33,xsb r8,34,xsb r9,35,xsb r10,36,xsb r11,37,xpop r11pop r10pop r9pop r8pop r7pop r6; write to source header; stbc #0x00,6[r2]; stbc #0xFF,7[r2]; stbc #0xEE,8[r2]; stbc #0xF0,9[r2]; stbc #0xDA,10[r2]; stbc #0x42,11[r2]sb r0,6,xlda #0xFFsb r1,7,xlda #0xEEsb r1,8,xlda #0xF0sb r1,9,xlda #0xDAsb r1,10,xlda #0x42sb r1,11,x; write to ARP source; stbc #0x00,22[r2]; stbc #0xFF,23[r2]; stbc #0xEE,24[r2]; stbc #0xF0,25[r2]; stbc #0xDA,26[r2]; stbc #0x42,27[r2]sb r0,22,xlda #0xFFsb r1,23,xlda #0xEEsb r1,24,xlda #0xF0sb r1,25,xlda #0xDAsb r1,26,xlda #0x42sb r1,27,x; swap sender / destination IP; write sendersb r9,28,xsb r10,29,xsb r11,30,xsb r12,31,x; write destinationsb r5,38,xsb r6,39,xsb r7,40,xsb r8,41,x; change request to reply; stbc #2,21[r2]lda #2sb r1,21,xtxa ; r1 = packet addressldx #0x2A ; r2 = packet lengthjsr eth_send_packetjmp eth_loop
