| |
udpsend.asm
;+
; **-udp_send-send a UDP datagram.
;
; inputs:
; SRAM:
; MEM_UDP_LEN = native byte order length of data to send
; MEM_ETH_DEST = destination ethernet address
; MEM_IP_DSTADDR = destination IP address
;
; transmit buffer:
; UDP_DATA = user data to be sent (MEM_UDP_LEN bytes of it)
;
; checksum algorithm:
;
; ip_chksum = 0 ;
; ip_chksum = ~checksum(IPH,IPHLEN)
; udp_chksum = 0
; ph.src = ip.src
; ph.dst = ip.dst
; ph.mbzprot = 0|(ip.prot<<8)
; ph.len = udp_len (UDP data only, not header)
; ph_chksum = checksum(UDP_HDR,UDP_LEN+UDP_HEADER_LEN)
; udp_chksum = ~checksum(PH_HDR,PH_HEADER_LEN)
;-
#include "udpsend.h"
#define PH_HEADER rcv_hdr+en_rbuf_nhdr
#define PH_SRCADDR PH_HEADER+0
#define PH_DSTADDR PH_HEADER+4
#define PH_MBZPROT PH_HEADER+8
#define PH_LEN PH_HEADER+10
#define PH_CHKSUM PH_HEADER+12
#define PH_HEADER_LEN 14
#define MOVW(x,y) pmovwi x,[y]
udp_send:
;
; compute UDP length and store in UDP_LEN field and PH_LEN field.
;
MOVW(buf+2,MEM_UDP_LEN) ; get length (native order)
MOVW(buf,buf+2) ; copy it
paddwi buf,UDP_HEADER_LEN ; total length
MOVW(MEM_UDP_LEN,swap buf) ; set UDP length
;
; checksum UDP header, data, and store checksum (uncomplemented) in
; pseudoheader.
;
pclrw MEM_UDP_CHKSUM ; zero UDP checksum in header
pclrw chkacc ; reset checksum accumulator
pmovwi chkaddr,MEM_UDP_HEADER ; -> data
pmovwi chklen,UDP_HEADER_LEN ; length
sram_checksum ; compute checksum
pmovb chkaddr+1,xmit_page ; address transmit page
pmovbi chkaddr,UDP_DATA ; UDP data
pmovwi chklen,[buf+2] ; its length
in_checksum ; accumulate into chkacc
MOVW(PH_CHKSUM,chkacc) ; store checksum in pseudoheader
paddwi buf,IP_HEADER_LEN
MOVW(MEM_IP_LEN,swap buf) ; set IP length
;
; the IP header should be ready, zero its checksum, checksum it, and
; store complemented checksum back in header.
;
pclrw MEM_IP_CHKSUM ; zero IP header checksum
pclrw chkacc
pmovwi chkaddr,MEM_IPH ; -> IP header
pmovwi chklen,IP_HEADER_LEN ; length
sram_checksum ; compute checksum
pcomw chkacc
MOVW(MEM_IP_CHKSUM,chkacc) ; store in IP header
;
; finally, checksum the pseudoheader and store complemented checksum
; in UDP header.
;
pmemcpy PH_SRCADDR,MEM_IP_SRCADDR,8 ; source/dest IP addrs
pmovwi PH_MBZPROT,0x1100 ; UDP proto in PH
MOVW(PH_LEN,MEM_UDP_LEN) ; store net order length in ph
pclrw chkacc
pmovwi chkaddr,PH_HEADER ; -> PH
pmovwi chklen,PH_HEADER_LEN ; length of PH
sram_checksum
pcomw chkacc
MOVW(MEM_UDP_CHKSUM,chkacc) ; store in UDP header checksum
;
; compute total packet size and send.
;
MOVW(buf,swap MEM_IP_LEN) ; ip length total
paddwi buf,IPH ; compute length with ether header
ps2x 0,MEM_ETH_DEST,UDP_DATA ; slap on ether, ip, udp headers
xmit_frame [buf] ; out she goes
pret
Back
|
|
|