mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-01-11 13:29:44 +00:00
Uthernet IP/ICMP/UDP/DHCP drivers
This commit is contained in:
parent
90c1a459d7
commit
e261d14467
17
src/makefile
17
src/makefile
@ -11,6 +11,9 @@ ROD = ROD\#FE1000
|
||||
SIEVE = SIEVE\#FE1000
|
||||
UTHERNET= UTHERNET\#FE1000
|
||||
ETHERIP = ETHERIP\#FE1000
|
||||
ICMP = ICMP\#FE1000
|
||||
DHCP = DHCP\#FE1000
|
||||
STATICIP= STATICIP\#FE1000
|
||||
ROGUE = ROGUE\#FE1000
|
||||
ROGUEIO = ROGUEIO\#FE1000
|
||||
ROGUEMAP= ROGUEMAP\#FE1000
|
||||
@ -43,7 +46,7 @@ TXTTYPE = .TXT
|
||||
#SYSTYPE = \#FF2000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ICMP) $(DHCP) $(STATICIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
|
||||
clean:
|
||||
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
||||
@ -128,6 +131,18 @@ $(ETHERIP): samplesrc/etherip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/etherip.pla > samplesrc/etherip.a
|
||||
acme --setpc 4094 -o $(ETHERIP) samplesrc/etherip.a
|
||||
|
||||
$(ICMP): samplesrc/icmp.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/icmp.pla > samplesrc/icmp.a
|
||||
acme --setpc 4094 -o $(ICMP) samplesrc/icmp.a
|
||||
|
||||
$(DHCP): samplesrc/dhcp.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/dhcp.pla > samplesrc/dhcp.a
|
||||
acme --setpc 4094 -o $(DHCP) samplesrc/dhcp.a
|
||||
|
||||
$(STATICIP): samplesrc/staticip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/staticip.pla > samplesrc/staticip.a
|
||||
acme --setpc 4094 -o $(STATICIP) samplesrc/staticip.a
|
||||
|
||||
$(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a
|
||||
acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a
|
||||
|
210
src/samplesrc/dhcp.pla
Normal file
210
src/samplesrc/dhcp.pla
Normal file
@ -0,0 +1,210 @@
|
||||
//
|
||||
// DHCP
|
||||
//
|
||||
import stdlib
|
||||
predef syscall, call, memset, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip, subnet_mask, gateway
|
||||
predef swab, sendUDP, recvUDP, shutUDP, serviceIP
|
||||
end
|
||||
import icmp
|
||||
end
|
||||
//
|
||||
// Needed to init subnet_mask
|
||||
//
|
||||
const IP_BROADCAST = $FFFF
|
||||
//
|
||||
// DHCP message
|
||||
//
|
||||
struc t_dhcp
|
||||
byte dhcp_op
|
||||
byte dhcp_htype
|
||||
byte dhcp_hlen
|
||||
byte dhcp_hops
|
||||
byte[4] dhcp_xid
|
||||
word dhcp_secs
|
||||
word dhcp_flags
|
||||
byte[4] dhcp_clientip
|
||||
byte[4] dhcp_yourip
|
||||
byte[4] dhcp_serverip
|
||||
byte[4] dhcp_gatewayip
|
||||
byte[16] dhcp_clientha
|
||||
byte[192] dhcp_bootp
|
||||
byte[4] dhcp_magic
|
||||
byte[60] dhcp_opts
|
||||
end
|
||||
//
|
||||
// DHCP messages
|
||||
//
|
||||
const DHCP_DISCOVER = $01
|
||||
const DHCP_OFFER = $02
|
||||
const DHCP_REQUEST = $03
|
||||
const DHCP_DECLINE = $04
|
||||
const DHCP_ACK = $05
|
||||
const DHCP_NACK = $06
|
||||
const DHCP_RELEASE = $07
|
||||
//
|
||||
// DHCP ports
|
||||
//
|
||||
const DHCP_CLIENT_PORT = 68
|
||||
const DHCP_SERVER_PORT = 67
|
||||
//
|
||||
// Pre-configured DHCP packet
|
||||
//
|
||||
byte DHCP = $01 // OP = DISCOVER
|
||||
byte = $01 // HTYPE = ETHERNET
|
||||
byte = $06 // HLEN = 6
|
||||
byte = $00 // HOPS
|
||||
byte[4] = $01,$02,$03,$04 // TRANSACTION ID
|
||||
word = $0000 // SECONDS
|
||||
word = 0 // FLAGS
|
||||
byte[4] = 0 // CLIENT IP
|
||||
byte[4] = 0 // YOUR IP
|
||||
byte[4] = 0 // SERVER IP
|
||||
byte[4] = 0 // GATEWAY IP
|
||||
byte[16] = 0 // CLIENT HA
|
||||
byte[64] = 0 // SERVER HOST NAME
|
||||
byte[128] = 0 // BOOT FILE NAME
|
||||
byte[4] = $63,$82,$53,$63 // MAGIC
|
||||
byte optsDHCP = 53,1,1 // DISCOVER
|
||||
byte = 12, "AppleII"
|
||||
byte = 55,4 ,1,28,3,42
|
||||
byte = 255
|
||||
byte optsREQ = 53,1,3 // REQUEST
|
||||
byte = 50,4,0,0,0,0 // IP requested
|
||||
byte = 54,4,0,0,0,0 // DHCP server
|
||||
byte = 255
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
byte offerstr = "DHCP server offering IP address "
|
||||
byte ackstr = "DHCP acknowledge\n"
|
||||
byte boundstr = "Apple II bound to:\n"
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
def dumpbytes(buf, len)
|
||||
word i
|
||||
|
||||
for i = 0 to len - 1
|
||||
putb(buf->[i])
|
||||
if i & 15 == 15
|
||||
putln
|
||||
else
|
||||
putc(' ')
|
||||
fin
|
||||
next
|
||||
end
|
||||
def dumpdhcp(pkt)
|
||||
putb(pkt->dhcp_op);putln
|
||||
putb(pkt->dhcp_htype);putln
|
||||
putb(pkt->dhcp_hlen);putln
|
||||
putb(pkt->dhcp_hops);putln
|
||||
dumpbytes(@pkt->dhcp_xid, 4);putln
|
||||
putip(@pkt->dhcp_clientip);putln
|
||||
putip(@pkt->dhcp_yourip);putln
|
||||
putip(@pkt->dhcp_serverip);putln
|
||||
putip(@pkt->dhcp_gatewayip);putln
|
||||
dumpbytes(@pkt->dhcp_opts, 32);putln
|
||||
end
|
||||
def parseopts(opts, match)
|
||||
byte i
|
||||
|
||||
i = 0
|
||||
while opts->[i] <> $FF and i < 64
|
||||
while !opts->[i] and i < 64
|
||||
i = i + 1
|
||||
loop
|
||||
if opts->[i] == match
|
||||
return i
|
||||
fin
|
||||
i = i + opts->[i + 1] + 2
|
||||
loop
|
||||
return -1
|
||||
end
|
||||
def servdhcp(remip, remport, lclport, pkt, len, param)
|
||||
word optofst
|
||||
|
||||
//putip(remip);putc(':');puti(remport);putln
|
||||
if pkt=>dhcp_xid:0 == $0201 and pkt=>dhcp_xid:2 = $0403
|
||||
when pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 53) + 2]
|
||||
is DHCP_OFFER
|
||||
//puts(@offerstr); putip(@pkt->dhcp_yourip); putln
|
||||
//
|
||||
// Copy offer parameters to request
|
||||
//
|
||||
memcpy(@optsDHCP, @optsREQ, 16)
|
||||
memcpy(@optsDHCP.5, @pkt->dhcp_yourip, 4)
|
||||
memcpy(@optsDHCP.11, @pkt->dhcp_serverip, 4)
|
||||
memcpy(@DHCP.dhcp_serverip, @pkt->dhcp_serverip, 4)
|
||||
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
|
||||
break
|
||||
is DHCP_ACK
|
||||
//puts(@ackstr)
|
||||
//
|
||||
// Copy parameters to working copy
|
||||
//
|
||||
memcpy(@localip, @pkt->dhcp_yourip, 4)
|
||||
memcpy(@subnet_mask, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4)
|
||||
puts(@boundstr);putip(@localip);putc('/');putip(@subnet_mask);putln
|
||||
break
|
||||
otherwise
|
||||
dumpdhcp(pkt)
|
||||
wend
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Get the local hardware address into the DHCP packet
|
||||
//
|
||||
memcpy(@DHCP.dhcp_clientha, @localha, 6)
|
||||
//
|
||||
// Clear our local IP address
|
||||
//
|
||||
memset(@localip, 4, 0)
|
||||
//
|
||||
// Set subnet mask to all 1's
|
||||
//
|
||||
memset(@subnet_mask, 4, IP_BROADCAST)
|
||||
//
|
||||
// Prepare to receive DHCP packets from a server
|
||||
//
|
||||
recvUDP(DHCP_CLIENT_PORT, @servdhcp, 0)
|
||||
//
|
||||
// Broadcast DHCP DISCOVER message
|
||||
//
|
||||
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
|
||||
//
|
||||
// Service IP
|
||||
//
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
done
|
@ -5,29 +5,36 @@ import stdlib
|
||||
byte MACHID
|
||||
end
|
||||
import uthernet
|
||||
predef MAC, writeEther, writevEther, readEther, readvEther, recvEther
|
||||
predef copyMAC, writeEther, writevEther, readEther, recvEther
|
||||
end
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// Max Ethernet frame size
|
||||
//
|
||||
const MAX_FRAME_SIZE = 1518
|
||||
const BROADCAST_MAC = $FFFF
|
||||
const MAC_BROADCAST = $FFFF
|
||||
const MAC_SIZE = 6
|
||||
//
|
||||
// Ethernet header
|
||||
//
|
||||
struc t_ehdr
|
||||
byte[MAC_SIZE] ehdr_dstaddr
|
||||
byte[MAC_SIZE] ehdr_srcaddr
|
||||
word ehdr_payload
|
||||
struc t_ethrhdr
|
||||
byte[MAC_SIZE] ethr_dst
|
||||
byte[MAC_SIZE] ethr_src
|
||||
word ethr_payload
|
||||
end
|
||||
const PAYLOAD_IP = $0008 // BE format
|
||||
const PAYLOAD_ARP = $0608 // BE format
|
||||
//
|
||||
// IP datagram header
|
||||
//
|
||||
const IP_SIZE = 4
|
||||
struc t_ip
|
||||
const IPADR_SIZE = 4
|
||||
struc t_iphdr
|
||||
byte ip_vers_hlen
|
||||
byte ip_service
|
||||
word ip_length
|
||||
@ -35,22 +42,15 @@ struc t_ip
|
||||
word ip_flags_fragofst
|
||||
byte ip_ttl
|
||||
byte ip_proto
|
||||
word ip_checksum
|
||||
byte[IP_SIZE] ip_src
|
||||
byte[IP_SIZE] ip_dst
|
||||
byte[] ip_options
|
||||
end
|
||||
const IP_PROTO_ICMP = 1
|
||||
const IP_PROTO_UDP = 2
|
||||
const IP_PROTO_TCP = 3
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_checksum
|
||||
word ip_chksm
|
||||
byte[IPADR_SIZE] ip_src
|
||||
byte[IPADR_SIZE] ip_dst
|
||||
byte[] ip_options
|
||||
end
|
||||
const IP_BROADCAST = $FFFF
|
||||
const IP_PROTO_ICMP = $01
|
||||
const IP_PROTO_UDP = $11
|
||||
const IP_PROTO_TCP = $06
|
||||
//
|
||||
// ARP packet
|
||||
//
|
||||
@ -65,11 +65,11 @@ struc t_arp
|
||||
byte arp_plen
|
||||
word arp_op
|
||||
byte[MAC_SIZE] arp_senderha
|
||||
byte[IP_SIZE] arp_senderip
|
||||
byte[IPADR_SIZE] arp_senderip
|
||||
byte[MAC_SIZE] arp_targha
|
||||
byte[IP_SIZE] arp_targip
|
||||
byte[IPADR_SIZE] arp_targip
|
||||
end
|
||||
const t_earp = t_ehdr+t_arp
|
||||
const t_earp = t_ethrhdr+t_arp
|
||||
//
|
||||
// Pre-configured ARP packet
|
||||
//
|
||||
@ -77,15 +77,64 @@ byte[] ARP
|
||||
byte[MAC_SIZE] dstMAC
|
||||
byte[MAC_SIZE] srcMAC
|
||||
word = PAYLOAD_ARP
|
||||
word = HW_ETHER // HW TYPE
|
||||
word = ARP_PROTO // PROTO TYPE
|
||||
byte = MAC_SIZE // HLEN
|
||||
byte = IP_SIZE // PLEN
|
||||
word opARP // OP
|
||||
byte[MAC_SIZE] localha
|
||||
byte[IP_SIZE ] localip = 192,168,123,10
|
||||
byte[MAC_SIZE] remoteha
|
||||
byte[IP_SIZE] remoteip = 192,168,123,1
|
||||
word = HW_ETHER // HW TYPE
|
||||
word = ARP_PROTO // PROTO TYPE
|
||||
byte = MAC_SIZE // HLEN
|
||||
byte = IPADR_SIZE // PLEN
|
||||
word opARP // OP
|
||||
export byte[MAC_SIZE] localha
|
||||
export byte[IPADR_SIZE] localip
|
||||
byte[MAC_SIZE] remoteha
|
||||
byte[IPADR_SIZE] remoteip
|
||||
//
|
||||
// Local network parameters
|
||||
//
|
||||
export byte[IPADR_SIZE] subnet_mask
|
||||
export byte[IPADR_SIZE] gateway
|
||||
//
|
||||
// UDP IPv4 psuedo header
|
||||
//
|
||||
struc t_piphdr
|
||||
byte[IPADR_SIZE] pip_src
|
||||
byte[IPADR_SIZE] pip_dst
|
||||
byte pip_zero
|
||||
byte pip_proto
|
||||
word pip_len
|
||||
end
|
||||
//
|
||||
// UDP header
|
||||
//
|
||||
struc t_udphdr
|
||||
word udp_src
|
||||
word udp_dst
|
||||
word udp_len
|
||||
word udp_chksm
|
||||
end
|
||||
//
|
||||
// TCP header
|
||||
//
|
||||
struc t_tcphdr
|
||||
word tcp_src
|
||||
word tcp_dst
|
||||
word tcp_len
|
||||
word tcp_chksm
|
||||
end
|
||||
//
|
||||
// Notify callbacks
|
||||
//
|
||||
struc t_notify
|
||||
word notify_port
|
||||
word notify_func
|
||||
word notify_parm
|
||||
end
|
||||
const MAX_UDP_NOTIFIES = 16
|
||||
const MAX_TCP_NOTIFIES = 8
|
||||
word portsUDP
|
||||
word portsTCP
|
||||
//
|
||||
// Service ICMP externally
|
||||
//
|
||||
export word serviceICMP
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
@ -97,7 +146,7 @@ end
|
||||
//
|
||||
// Swap bytes in word
|
||||
//
|
||||
asm swab
|
||||
export asm swab
|
||||
LDA ESTKL,X
|
||||
LDY ESTKH,X
|
||||
STA ESTKH,X
|
||||
@ -105,47 +154,54 @@ asm swab
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// SUM BE format
|
||||
// sum(BUF, LEN)
|
||||
// 1'S COMPLIMENT SUM BE format
|
||||
// sum1(PREVSUM, BUF, LEN)
|
||||
//
|
||||
export asm sum
|
||||
export asm sum1
|
||||
LDY #$00
|
||||
LDA ESTKL+1,X
|
||||
STY ESTKL+1,X
|
||||
STA SRCL
|
||||
LDA ESTKH+1,X
|
||||
STY ESTKH+1,X
|
||||
STA SRCH
|
||||
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
|
||||
LDA ESTKL,X
|
||||
STA SRCL
|
||||
LDA ESTKH+1,X
|
||||
STA SRCH
|
||||
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
|
||||
LDA ESTKL,X
|
||||
ROR
|
||||
ADC #$00
|
||||
STA ESTKL,X
|
||||
BEQ CHKLP
|
||||
INC ESTKH,X
|
||||
CHKLP LDA (SRC),Y
|
||||
ADC #$00
|
||||
STA ESTKL,X
|
||||
BEQ +
|
||||
INC ESTKH,X
|
||||
BCC CHKLP
|
||||
INC ESTKH,X
|
||||
CLC
|
||||
CHKLP LDA (SRC),Y
|
||||
PHA
|
||||
INY
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ LDA (SRC),Y
|
||||
CLC
|
||||
ADC ESTKH+1,X
|
||||
STA ESTKH+1,X
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ LDA (SRC),Y
|
||||
ADC ESTKH+2,X
|
||||
STA ESTKH+2,X
|
||||
PLA
|
||||
ADC ESTKL+1,X
|
||||
STA ESTKL+1,X
|
||||
ADC ESTKL+2,X
|
||||
STA ESTKL+2,X
|
||||
INY
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ DEC ESTKL,X
|
||||
BNE CHKLP
|
||||
DEC ESTKH,X
|
||||
BNE CHKLP
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ DEC ESTKL,X
|
||||
BNE CHKLP
|
||||
DEC ESTKH,X
|
||||
BNE CHKLP
|
||||
- LDA #$00
|
||||
ADC ESTKH+2,X
|
||||
STA ESTKH+2,X
|
||||
LDA #$00
|
||||
ADC ESTKL+2,X
|
||||
STA ESTKL+2,X
|
||||
BCS -
|
||||
INX
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
//
|
||||
end//
|
||||
// DEBUG
|
||||
//
|
||||
def putln
|
||||
@ -182,25 +238,35 @@ def putip(ipptr)
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
def dumpehdr(packet)
|
||||
putha(packet + ethr_dst); putc(' ')
|
||||
putha(packet + ethr_src); putc(' ')
|
||||
putc('$');puth(packet=>ethr_payload); putln
|
||||
end
|
||||
def dumparp(packet)
|
||||
puth(packet=>arp_hw); putln
|
||||
puth(packet=>arp_proto); putln
|
||||
putb(packet->arp_hlen); putln
|
||||
putb(packet->arp_plen); putln
|
||||
puth(packet=>arp_op); putln
|
||||
putc('$');puth(packet=>arp_hw); putln
|
||||
putc('$');puth(packet=>arp_proto); putln
|
||||
putc('$');putb(packet->arp_hlen); putln
|
||||
putc('$');putb(packet->arp_plen); putln
|
||||
putc('$');puth(packet=>arp_op); putln
|
||||
putha(packet + arp_senderha)
|
||||
putc('=')
|
||||
putip(packet + arp_senderip)
|
||||
putln
|
||||
putip(packet + arp_senderip); putln
|
||||
putha(packet + arp_targha)
|
||||
putc('=')
|
||||
putip(packet + arp_targip)
|
||||
putln
|
||||
putip(packet + arp_targip); putln
|
||||
end
|
||||
def dumpehdr(packet)
|
||||
putha(packet + ehdr_dstaddr); putc(' ')
|
||||
putha(packet + ehdr_srcaddr); putc(' ')
|
||||
puth(packet=>ehdr_payload); putln
|
||||
def dumpip(packet)
|
||||
putc('$');putb(packet->ip_vers_hlen); putln
|
||||
puti(swab(packet=>ip_length)); putln
|
||||
puti(packet->ip_proto); putln
|
||||
putip(packet + ip_src); putln
|
||||
putip(packet + ip_dst); putln
|
||||
end
|
||||
def dumpudp(packet)
|
||||
puti(swab(packet=>udp_src));putln
|
||||
puti(swab(packet=>udp_dst));putln
|
||||
puti(swab(packet=>udp_len));putln
|
||||
end
|
||||
def dumpfrm(packet, len)
|
||||
word i
|
||||
@ -220,93 +286,270 @@ def dumpfrm(packet, len)
|
||||
putln
|
||||
end
|
||||
//
|
||||
// Write IP datagram
|
||||
//
|
||||
export def writeIP(dstip, proto, packet, len)
|
||||
byte[t_ip] iphdr
|
||||
|
||||
iphdr.ip_vers_hlen = 0
|
||||
iphdr.ip_service = 0
|
||||
iphdr:ip_length = len
|
||||
iphdr:ip_id = 0
|
||||
iphdr:ip_flags_fragofst = 0
|
||||
iphdr.ip_ttl = 1
|
||||
iphdr.ip_proto = proto
|
||||
iphdr:ip_checksum = 0
|
||||
memcpy(@iphdr.ip_src, @localip, IP_SIZE)
|
||||
memcpy(@ip_dst, @dstip, IP_SIZE)
|
||||
end
|
||||
//
|
||||
// Read IP datagram
|
||||
//
|
||||
export def readIP(dst, proto, packet)
|
||||
end
|
||||
//
|
||||
// Service incoming packets
|
||||
//
|
||||
def serviceIP
|
||||
word pkt, iphdr, ipopt, len
|
||||
export def serviceIP
|
||||
word pkt, iphdr, hdr, opt, len, optlen, port, lclport, remport
|
||||
byte i
|
||||
|
||||
len = recvEther
|
||||
if len
|
||||
len = len - t_ehdr
|
||||
when readEther(t_ehdr)=>ehdr_payload
|
||||
len = len - t_ethrhdr
|
||||
when readEther(t_ethrhdr)=>ethr_payload
|
||||
is PAYLOAD_ARP
|
||||
pkt = readEther(len)
|
||||
len = 0
|
||||
when pkt=>arp_op
|
||||
is ARP_REPLY
|
||||
//
|
||||
// Fill in ARP cache
|
||||
//
|
||||
memcpy(@remoteha, @pkt=>arp_senderha, 10) // copy ha and ip
|
||||
putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
//putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
break
|
||||
is ARP_REQST
|
||||
//
|
||||
// Is this a request for me?
|
||||
//
|
||||
if pkt=>arp_targip:0 == localip:0 and pkt=>arp_targip:2 == localip:2
|
||||
memcpy(@dstMAC, pkt=>arp_senderha, MAC_SIZE)
|
||||
memcpy(@dstMAC, @pkt=>arp_senderha, MAC_SIZE)
|
||||
memcpy(@remoteha, @pkt=>arp_senderha, 10) // copy ha and ip
|
||||
opARP = ARP_REPLY
|
||||
writeEther(@ARP, t_earp)
|
||||
putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
//putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
fin
|
||||
break
|
||||
otherwise
|
||||
dumparp(pkt)
|
||||
//dumparp(pkt)
|
||||
wend
|
||||
break
|
||||
is PAYLOAD_IP
|
||||
len = len - t_ip
|
||||
iphdr = readEther(t_ip)
|
||||
if iphdr=>ip_length > t_ip
|
||||
len = len - (iphdr=>ip_length - t_ip)
|
||||
ipopt = readEther(iphdr=>ip_length - t_ip)
|
||||
len = len - t_iphdr
|
||||
iphdr = readEther(t_iphdr)
|
||||
if iphdr->ip_vers_hlen <> $45
|
||||
optlen = iphdr=>ip_vers_hlen
|
||||
if optlen & $F0 <> $40
|
||||
//
|
||||
// Not IPv4, ignore
|
||||
//
|
||||
break
|
||||
fin
|
||||
optlen = (optlen & $0F) << 2
|
||||
if optlen > t_iphdr
|
||||
//
|
||||
// Read the options and throw them on the ground!
|
||||
//
|
||||
opt = readEther(optlen - t_iphdr)
|
||||
len = len - (optlen - t_iphdr)
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Filter valid destination address
|
||||
//
|
||||
if iphdr=>ip_dst:2 <> localip:2 // Yes, this is a little lazy
|
||||
if (iphdr=>ip_dst:0|subnet_mask:0) & (iphdr=>ip_dst:2|subnet_mask:2) <> IP_BROADCAST
|
||||
break
|
||||
fin
|
||||
fin
|
||||
when iphdr->ip_proto
|
||||
is IP_PROTO_UDP
|
||||
port = portsUDP
|
||||
if port
|
||||
len = len - t_udphdr
|
||||
hdr = readEther(t_udphdr)
|
||||
lclport = swab(hdr=>udp_dst)
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if port=>notify_port == lclport)
|
||||
//dumpip(iphdr)
|
||||
//dumpudp(hdr)
|
||||
port=>notify_func(@iphdr=>ip_src,swab(hdr=>udp_src),lclport,readEther(len),swab(hdr=>udp_len),port=>notify_parm)
|
||||
len = 0
|
||||
break
|
||||
fin
|
||||
port = port + t_notify
|
||||
next
|
||||
fin
|
||||
break
|
||||
is IP_PROTO_TCP
|
||||
port = portsTCP
|
||||
if port
|
||||
len = len - t_tcphdr
|
||||
hdr = readEther(t_tcphdr)
|
||||
lclport = swab(hdr=>tcp_dst)
|
||||
remport = swab(hdr=>tcp_src)
|
||||
for i = 1 to MAX_TCP_NOTIFIES
|
||||
if port=>notify_port == lclport)
|
||||
//dumpip(iphdr)
|
||||
//dumptcp(tcphdr)
|
||||
port=>notify_func(@iphdr=>ip_src,swab(hdr=>tcp_src),lclport,readEther(len),swab(hdr=>tcp_len),port=>notify_parm)
|
||||
len = 0
|
||||
break
|
||||
fin
|
||||
port = port + t_notify
|
||||
next
|
||||
fin
|
||||
break
|
||||
is IP_PROTO_ICMP
|
||||
if serviceICMP
|
||||
serviceICMP(@iphdr=>ip_src, readEther(len), len)
|
||||
len = 0
|
||||
fin
|
||||
wend
|
||||
break
|
||||
otherwise
|
||||
pkt = readEther(len)
|
||||
dumpehdr(pkt - t_ehdr)
|
||||
//dumpfrm(pkt, len)
|
||||
//dumpehdr(readEther(len) - t_ethrhdr)
|
||||
//len = 0
|
||||
wend
|
||||
if len; readEther(len); fin // Drop it
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Send IP datagram
|
||||
//
|
||||
export def sendIP(ipdst, proto, seglist, size)
|
||||
byte[t_iphdr] hdr
|
||||
byte[MAC_SIZE] dstha
|
||||
byte retry
|
||||
word timeout
|
||||
|
||||
hdr.ip_vers_hlen = $45
|
||||
hdr.ip_service = 0
|
||||
hdr:ip_length = swab(t_iphdr + size)
|
||||
hdr:ip_id = 0
|
||||
hdr:ip_flags_fragofst = 0 //$40 // Don't fragment
|
||||
hdr.ip_ttl = 10 // Is this reasonable?
|
||||
hdr.ip_proto = proto
|
||||
hdr:ip_chksm = 0
|
||||
memcpy(@hdr.ip_src, @localip, IPADR_SIZE)
|
||||
if !ipdst // IP_BROADCAST
|
||||
memset(@hdr.ip_dst, IPADR_SIZE, IP_BROADCAST)
|
||||
memset(@dstha, MAC_SIZE, MAC_BROADCAST)
|
||||
else
|
||||
retry = 0
|
||||
while ipdst=>0 <> remoteip:0 and ipdst=>2 <> remoteip:2
|
||||
if retry >= 3
|
||||
return -1 // ARP failed
|
||||
fin
|
||||
retry = retry + 1
|
||||
memset(@dstMAC, MAC_SIZE, MAC_BROADCAST)
|
||||
memset(@remoteha, MAC_SIZE, 0)
|
||||
memcpy(@remoteip, ipdst, IPADR_SIZE)
|
||||
opARP = ARP_REQST
|
||||
writeEther(@ARP, t_earp)
|
||||
for timeout = 1000 downto 0
|
||||
serviceIP
|
||||
if remoteha:0 | remoteha:2 | remoteha:4
|
||||
break
|
||||
fin
|
||||
next
|
||||
loop
|
||||
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
|
||||
memcpy(@dstha, @remoteha, MAC_SIZE)
|
||||
fin
|
||||
//
|
||||
// Calculate checksum
|
||||
//
|
||||
hdr:ip_chksm = sum1(0, @hdr, t_iphdr) ^ $FFFF
|
||||
//
|
||||
// Fill in remaining segment list for IP header and write it out
|
||||
//
|
||||
seglist=>seg_buf = @hdr
|
||||
seglist=>seg_len = t_iphdr
|
||||
return writevEther(@dstha, PAYLOAD_IP, seglist, t_iphdr + size)
|
||||
end
|
||||
//
|
||||
// Send UDP datagram
|
||||
//
|
||||
export def sendUDP(ipdst, portdst, portsrc, data, len)
|
||||
word[12] seglist // list of data and header segments
|
||||
//word segsum
|
||||
//byte[t_piphdr] phdr
|
||||
byte[t_udphdr] hdr
|
||||
|
||||
//memcpy(@phdr.pip_src, @localip, IPADR_SIZE)
|
||||
//memcpy(@phdr.pip_dst, ipdst, IPADR_SIZE)
|
||||
//phdr.pip_zero = 0
|
||||
//phdr.pip_proto = IP_PROTO_UDP
|
||||
//phdr.pip_len = swab(t_udphdr + len)
|
||||
hdr:udp_src = swab(portsrc)
|
||||
hdr:udp_dst = swab(portdst)
|
||||
hdr:udp_len = swab(t_udphdr + len)
|
||||
hdr:udp_chksm = 0
|
||||
//segsum = sum1(0, @phdr, t_piphdr + t_udphdr)
|
||||
//segsum = sum1(segsum, data, len)
|
||||
//hdr:udp_chksm = segsum ^ $FFFF
|
||||
//seglist:0:seg_buf reserved for IP header
|
||||
//seglist:0:seg_len reserved for IP header
|
||||
seglist:4:seg_buf = @hdr
|
||||
seglist:4:seg_len = t_udphdr
|
||||
seglist:8:seg_buf = data
|
||||
seglist:8:seg_len = len
|
||||
return sendIP(ipdst, IP_PROTO_UDP, @seglist, t_udphdr + len)
|
||||
end
|
||||
//
|
||||
// Notify on UDP datagram received
|
||||
//
|
||||
export def recvUDP(localport, callback, param)
|
||||
word port
|
||||
byte i
|
||||
|
||||
if !localport; return -1; fin // invalid port
|
||||
//
|
||||
// Allocate the port notify array if needed
|
||||
//
|
||||
if !portsUDP
|
||||
portsUDP = heapalloc(MAX_UDP_NOTIFIES * t_notify)
|
||||
if !portsUDP; return -1; fin
|
||||
memset(portsUDP, MAX_UDP_NOTIFIES * t_notify, 0)
|
||||
fin
|
||||
//
|
||||
// Look for an existing notification on localport
|
||||
//
|
||||
port = portsUDP
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if port=>notify_port == localport
|
||||
port=>notify_func = callback
|
||||
port=>notify_parm = param
|
||||
return 0
|
||||
fin
|
||||
next
|
||||
//
|
||||
// Add notification on localport if room
|
||||
//
|
||||
port = portsUDP
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if !port=>notify_port
|
||||
port=>notify_port = localport
|
||||
port=>notify_func = callback
|
||||
port=>notify_parm = param
|
||||
return 0
|
||||
fin
|
||||
next
|
||||
return -1
|
||||
end
|
||||
//
|
||||
// Clear notify on UDP port
|
||||
//
|
||||
export def shutUDP(localport)
|
||||
word port
|
||||
byte i
|
||||
|
||||
if !localport; return -1; fin // invalid port
|
||||
//
|
||||
// Look for an existing notification on localport
|
||||
//
|
||||
port = portsUDP
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if port=>notify_port == localport
|
||||
port=>notify_port = 0
|
||||
return 0
|
||||
fin
|
||||
next
|
||||
return -1
|
||||
end
|
||||
//
|
||||
// Fill in MAC
|
||||
//
|
||||
memcpy(@srcMAC, @MAC, MAC_SIZE)
|
||||
memcpy(@localha, @MAC, MAC_SIZE)
|
||||
//
|
||||
// Start things off with an ARP request
|
||||
//
|
||||
memset(@dstMAC, MAC_SIZE, BROADCAST_MAC)
|
||||
memset(@remoteha, MAC_SIZE, 0)
|
||||
opARP = ARP_REQST
|
||||
writeEther(@ARP, t_earp)
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
copyMAC(@srcMAC)
|
||||
copyMAC(@localha)
|
||||
done
|
96
src/samplesrc/icmp.pla
Normal file
96
src/samplesrc/icmp.pla
Normal file
@ -0,0 +1,96 @@
|
||||
//
|
||||
// ICMP service
|
||||
//
|
||||
import stdlib
|
||||
predef syscall, call, memset, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip
|
||||
word serviceICMP
|
||||
predef sendIP
|
||||
end
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// ICMP type/codes
|
||||
//
|
||||
const IP_PROTO_ICMP = 1
|
||||
const ICMP_ECHO_REQST = 8
|
||||
const ICMP_ECHO_REPLY = 0
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_chksm
|
||||
word[2] icmp_header
|
||||
end
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
byte icmpstr = "ICMP "
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
//
|
||||
// Service ICMP packets
|
||||
//
|
||||
def icmp(srcip, pkt, len)
|
||||
byte[4] echoip
|
||||
word[8] seglist
|
||||
byte[128] echo_reply
|
||||
|
||||
//puts(@icmpstr);putip(srcip);putc(' ')
|
||||
//puti(pkt->icmp_type);putc(' ');puti(pkt->icmp_code);putln
|
||||
|
||||
if pkt->icmp_type == ICMP_ECHO_REQST
|
||||
if len > 128
|
||||
len = 128
|
||||
fin
|
||||
memcpy(@echo_reply, pkt, len)
|
||||
echo_reply.icmp_type = ICMP_ECHO_REPLY
|
||||
echo_reply:icmp_chksm = 0
|
||||
//echo_reply:icmp_chksm = sum1(0, @echo_reply, len) ^ $FFFF
|
||||
memcpy(@echoip, srcip, 4)
|
||||
seglist:4:seg_buf = @echo_reply
|
||||
seglist:4:seg_len = len
|
||||
sendIP(@echoip, IP_PROTO_ICMP, @seglist, len)
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Set to notify on ICMP packets
|
||||
//
|
||||
serviceICMP = @icmp
|
||||
done
|
98
src/samplesrc/staticip.pla
Normal file
98
src/samplesrc/staticip.pla
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Static IP
|
||||
//
|
||||
import stdlib
|
||||
predef syscall, call, memset, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip
|
||||
predef sendUDP, recvUDP, shutUDP, sendIP, serviceIP, sum1
|
||||
end
|
||||
import icmp
|
||||
end
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// ICMP type/codes
|
||||
//
|
||||
const ICMP_ECHO_REQST = 8
|
||||
const ICMP_ECHO_REPLY = 0
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_chksm
|
||||
word[2] icmp_header
|
||||
end
|
||||
//
|
||||
// ICMP echo packet
|
||||
//
|
||||
const IP_PROTO_ICMP = $01
|
||||
byte ECHO = 8 // ECHO request
|
||||
byte = 0 // code
|
||||
word = 0 // checksum
|
||||
byte = 0, 69, 0, 1 // rest of header
|
||||
word segecho = 0, 0, @ECHO, 8
|
||||
byte serverip = 192,168,123,129
|
||||
byte staticip = 192,168,123,10
|
||||
byte staticmask = 255,255,255,0
|
||||
word echo_reply
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
//
|
||||
// Set our local IP address
|
||||
//
|
||||
memcpy(@localip, @staticip, 4)
|
||||
//
|
||||
// Calculate checksum
|
||||
//
|
||||
ECHO:icmp_chksm = sum1(0, @ECHO, t_icmp) ^ $FFFF
|
||||
//
|
||||
// Send an echo to the server
|
||||
//
|
||||
sendIP(@serverip, IP_PROTO_ICMP, @segecho, 0)
|
||||
//
|
||||
// Service IP
|
||||
//
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
done
|
@ -10,12 +10,23 @@ end
|
||||
const modkeep = $2000
|
||||
const modinitkeep = $4000
|
||||
//
|
||||
// Ethernet header definition
|
||||
// Segment list element
|
||||
//
|
||||
struc t_ehdr
|
||||
byte[6] ehdr_dstaddr
|
||||
byte[6] ehdr_srcaddr
|
||||
word ehdr_type
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// MAC size
|
||||
//
|
||||
const MAC_SIZE = 6
|
||||
//
|
||||
// Ethernet header
|
||||
//
|
||||
struc t_ethrhdr
|
||||
byte[MAC_SIZE] ethr_dst
|
||||
byte[MAC_SIZE] ethr_src
|
||||
word ethr_payload
|
||||
end
|
||||
//
|
||||
// Max Ethernet frame size
|
||||
@ -24,7 +35,7 @@ const MAX_FRAME_SIZE = 1518
|
||||
//
|
||||
// MAC address
|
||||
//
|
||||
export byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
//
|
||||
// Uthernet register offsets
|
||||
//
|
||||
@ -39,17 +50,17 @@ const AUTO_INC = $8000
|
||||
//
|
||||
// Uthernet register addresses
|
||||
//
|
||||
byte[] slot // Init time only
|
||||
byte rxdata_lo, rxdata_hi
|
||||
byte txcmd
|
||||
byte txlen
|
||||
byte isq
|
||||
byte pregidx
|
||||
byte pregdata
|
||||
byte[] slot // Init time only
|
||||
//
|
||||
// Current receive status and packet size
|
||||
//
|
||||
word rxstatus, rxsize // MUST be in this order!
|
||||
word rxpacket, rxptr
|
||||
word rxsize, rxpacket, rxptr
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
@ -59,6 +70,16 @@ end
|
||||
//
|
||||
// I/O access
|
||||
//
|
||||
// POKE BYTE INTO I/O SPACE
|
||||
// _pokeio(DATA)
|
||||
//
|
||||
//asm _pokeio
|
||||
// LDA ESTKL,X
|
||||
//end
|
||||
//asm _pokeiol
|
||||
// STA $C000
|
||||
// RTS
|
||||
//end
|
||||
//
|
||||
// POKE WORD INTO I/O SPACE
|
||||
// _pokeiow(DATA)
|
||||
@ -75,6 +96,20 @@ asm _pokeiowh
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// PEEK BYTE FROM I/O SPACE
|
||||
// _peekio()
|
||||
//
|
||||
asm _peekio
|
||||
DEX
|
||||
end
|
||||
asm _peekiol
|
||||
LDA $C000
|
||||
STA ESTKL,X
|
||||
LDA #$00
|
||||
STA ESTKH,X
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// PEEK WORD FROM I/O SPACE
|
||||
// _peekiow()
|
||||
//
|
||||
@ -105,16 +140,16 @@ asm pokefrm
|
||||
ROR
|
||||
ADC #$00
|
||||
STA ESTKL,X
|
||||
BEQ POKELP
|
||||
BEQ +
|
||||
INC ESTKH,X
|
||||
+ BCC POKELP
|
||||
INC ESTKH,X
|
||||
POKELP LDA (SRC),Y
|
||||
end
|
||||
asm _pokefrml
|
||||
STA $C000
|
||||
INY
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ LDA (SRC),Y
|
||||
LDA (SRC),Y
|
||||
end
|
||||
asm _pokefrmh
|
||||
STA $C000
|
||||
@ -133,31 +168,29 @@ end
|
||||
// peekfrm(BUF, LEN)
|
||||
//
|
||||
asm peekfrm
|
||||
LDY #$00
|
||||
LDA ESTKL+1,X
|
||||
STA DSTL
|
||||
LDA ESTKH+1,X
|
||||
STA DSTH
|
||||
LDY ESTKL,X
|
||||
BEQ PEEKLP
|
||||
LDY #$00
|
||||
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
|
||||
LDA ESTKL,X
|
||||
ROR
|
||||
ADC #$00
|
||||
STA ESTKL,X
|
||||
BEQ +
|
||||
INC ESTKH,X
|
||||
+ BCC PEEKLP
|
||||
INC ESTKH,X
|
||||
end
|
||||
asm _peekfrmh
|
||||
PEEKLP LDA $C000
|
||||
PHA
|
||||
end
|
||||
asm _peekfrml
|
||||
LDA $C000
|
||||
PEEKLP LDA $C000
|
||||
STA (DST),Y
|
||||
PLA
|
||||
INY
|
||||
BNE +
|
||||
INC DSTH
|
||||
+ DEC ESTKL,X
|
||||
BNE +
|
||||
DEC ESTKH,X
|
||||
BEQ EXPSW
|
||||
+ STA (DST),Y
|
||||
end
|
||||
asm _peekfrmh
|
||||
+ LDA $C000
|
||||
STA (DST),Y
|
||||
INY
|
||||
BNE +
|
||||
INC DSTH
|
||||
@ -168,11 +201,19 @@ asm _peekfrml
|
||||
EXPSW INX
|
||||
RTS
|
||||
end
|
||||
//def pokeio(io, data)
|
||||
// _pokeiowl.1 = io
|
||||
// return _pokeio(data)
|
||||
//end
|
||||
def pokeiow(io, data)
|
||||
_pokeiowl.1 = io
|
||||
_pokeiowh.1 = io+1
|
||||
return _pokeiow(data)
|
||||
end
|
||||
def peekio(io)
|
||||
_peekiol.1 = io
|
||||
return _peekio()
|
||||
end
|
||||
def peekiow(io)
|
||||
_peekiowl.1 = io
|
||||
_peekiowh.1 = io+1
|
||||
@ -189,6 +230,11 @@ end
|
||||
//
|
||||
// Uthernet interface
|
||||
//
|
||||
export def copyMAC(ptr)
|
||||
if !rxpacket; rxpacket = heapalloc(MAX_FRAME_SIZE); fin
|
||||
memcpy(ptr, @MAC, MAC_SIZE)
|
||||
return MAC_SIZE
|
||||
end
|
||||
export def writeEther(packet, size)
|
||||
pokeiow(txcmd, $C0)
|
||||
pokeiow(txlen, size)
|
||||
@ -196,22 +242,16 @@ export def writeEther(packet, size)
|
||||
return pokefrm(packet, size)
|
||||
end
|
||||
export def writevEther(destha, payload, seglist, size)
|
||||
word segsize
|
||||
|
||||
pokeiow(txcmd, $C0)
|
||||
pokeiow(txlen, size + t_ehdr)
|
||||
pokeiow(txlen, size + t_ethrhdr)
|
||||
repeat; until peekpreg($0138) & $0100
|
||||
pokefrm(destha, 6)
|
||||
pokefrm(@MAC, 6)
|
||||
pokefrm(destha, MAC_SIZE)
|
||||
pokefrm(@MAC, MAC_SIZE)
|
||||
pokefrm(@payload, 2)
|
||||
while size > 0
|
||||
segsize = seglist=>2
|
||||
if segsize > size
|
||||
segsize = size
|
||||
fin
|
||||
pokefrm(seglist=>0, segsize)
|
||||
size = size - segsize
|
||||
seglist = seglist + 4
|
||||
pokefrm(seglist=>seg_buf, seglist=>seg_len)
|
||||
size = size - seglist=>seg_len
|
||||
seglist = seglist + t_segment
|
||||
loop
|
||||
end
|
||||
export def readEther(size)
|
||||
@ -229,34 +269,18 @@ export def readEther(size)
|
||||
fin
|
||||
return segptr
|
||||
end
|
||||
export def readvEther(seglist, size)
|
||||
word segsize
|
||||
|
||||
while size > 0
|
||||
segsize = seglist=>2
|
||||
size = size - segsize
|
||||
if segsize > rxsize
|
||||
segsize = rxsize
|
||||
fin
|
||||
memcpy(seglist=>0, rxptr, segsize)
|
||||
rxptr = rxptr + segsize
|
||||
rxsize = rxsize - segsize
|
||||
seglist = seglist + 4
|
||||
loop
|
||||
return rxsize
|
||||
end
|
||||
export def recvEther
|
||||
if rxsize == 0
|
||||
if peekiow(isq) & $3F == $04
|
||||
peekfrm(@rxstatus, 4)
|
||||
if rxstatus & $0100
|
||||
if !rxpacket; rxpacket = heapalloc(MAX_FRAME_SIZE); fin
|
||||
if peekio(rxdata_hi) & $01
|
||||
peekio(rxdata_lo)
|
||||
rxsize.1 = peekio(rxdata_hi)
|
||||
rxsize.0 = peekio(rxdata_lo)
|
||||
peekfrm(rxpacket, rxsize)
|
||||
rxptr = rxpacket
|
||||
else
|
||||
peekio(rxdata_lo)
|
||||
pokepreg($0102, $0140) // Skip pkt
|
||||
rxstatus = 0
|
||||
rxsize = 0
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
@ -270,6 +294,7 @@ for slot = $F0 downto $90 step $10
|
||||
pokeiow(slot+PREG_INDEX, 0)
|
||||
if peekiow(slot+PREG_DATA) == $630E
|
||||
pokepreg($0114, $40) // RESET
|
||||
rxdata_hi = slot + 1
|
||||
txcmd = slot + TXCMD
|
||||
txlen = slot + TXLEN
|
||||
isq = slot + INT_STATUS
|
||||
|
Loading…
x
Reference in New Issue
Block a user