1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-07-05 04:28:57 +00:00

REady for use Uthernet IP modules

This commit is contained in:
dschmenk 2015-01-30 20:49:01 -08:00
parent f2c9526c79
commit 235d6f5363
7 changed files with 371 additions and 624 deletions

View File

@ -7,14 +7,12 @@ import cmdsys
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
import inet
byte localha, localip, subnet, gateway
predef swab, sendUDP, listenUDP, hangupUDP, serviceIP
end
//
// Needed to init subnet_mask
// Needed to init subnet
//
const IP_BROADCAST = $FFFF
//
@ -48,6 +46,10 @@ const DHCP_ACK = $05
const DHCP_NACK = $06
const DHCP_RELEASE = $07
//
// Track DHCP progress
//
byte stateDHCP, retry, timeout
//
// DHCP ports
//
const DHCP_CLIENT_PORT = 68
@ -156,6 +158,7 @@ def servdhcp(remip, remport, lclport, pkt, len, param)
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
stateDHCP = DHCP_OFFER
//puts(@offerstr); putip(@pkt->dhcp_yourip); putln
//
// Copy offer parameters to request
@ -167,13 +170,18 @@ def servdhcp(remip, remport, lclport, pkt, len, param)
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
break
is DHCP_ACK
stateDHCP = DHCP_ACK
//
// Stop listening to UDP port
//
hangupUDP(DHCP_CLIENT_PORT)
//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
memcpy(@subnet, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4)
puts(@boundstr);putip(@localip);putc('/');putip(@subnet);putln
break
otherwise
dumpdhcp(pkt)
@ -191,20 +199,30 @@ memset(@localip, 0, 4)
//
// Set subnet mask to all 1's
//
memset(@subnet_mask, IP_BROADCAST, 4)
memset(@subnet, IP_BROADCAST, 4)
//
// 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)
listenUDP(DHCP_CLIENT_PORT, @servdhcp, 0)
//
// Service IP
//
repeat
serviceIP
until ^$C000 > 127
^$C010
while retry < 3
//
// Broadcast DHCP DISCOVER message
//
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
for timeout = 1 to 1000
serviceIP
if stateDHCP == DHCP_ACK
return 0
fin
next
retry = retry + 1
loop
//
// Nobody answered
//
return -1
done

View File

@ -1,12 +1,18 @@
import cmdsys
predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID
end
import uthernet
predef copyMAC, writeEther, writevEther, readEther, recvEther
end
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
//
// Predefine service routine
//
predef serviceIP
//
// Segment list element
//
@ -47,50 +53,26 @@ struc t_iphdr
byte[IPADR_SIZE] ip_dst
byte[] ip_options
end
const t_ethriphdr = t_ethrhdr + t_iphdr
const IP_BROADCAST = $FFFF
const IP_PROTO_ICMP = $01
const IP_PROTO_UDP = $11
const IP_PROTO_TCP = $06
//
// ARP packet
// ICMP type/codes
//
const HW_ETHER = $0100 // BE format
const ARP_PROTO = $0008 // BE format
const ARP_REQST = $0100 // BE format
const ARP_REPLY = $0200 // BE format
struc t_arp
word arp_hw
word arp_proto
byte arp_hlen
byte arp_plen
word arp_op
byte[MAC_SIZE] arp_senderha
byte[IPADR_SIZE] arp_senderip
byte[MAC_SIZE] arp_targha
byte[IPADR_SIZE] arp_targip
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
const t_earp = t_ethrhdr+t_arp
//
// Pre-configured ARP packet
//
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 = 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
//
@ -120,6 +102,60 @@ struc t_tcphdr
word tcp_chksm
end
//
// ARP packet
//
const HW_ETHER = $0100 // BE format
const ARP_PROTO = $0008 // BE format
const ARP_REQST = $0100 // BE format
const ARP_REPLY = $0200 // BE format
struc t_arp
word arp_hw
word arp_proto
byte arp_hlen
byte arp_plen
word arp_op
byte[MAC_SIZE] arp_senderha
byte[IPADR_SIZE] arp_senderip
byte[MAC_SIZE] arp_targha
byte[IPADR_SIZE] arp_targip
end
const t_earp = t_ethrhdr+t_arp
//
// Pre-configured Ethernet header
//
byte[] eFrame
//
// Destination MAC address
//
byte[MAC_SIZE] dstMAC
//
// My MAC address
//
byte[MAC_SIZE] myMAC
//
// Ethernet payload
//
word ePayload = PAYLOAD_ARP
//
// Pre-configured ARP packet - MUST follow ethernet header!
//
word ARP = 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
export byte[IPADR_SIZE] gateway
const MAX_UDP_NOTIFIES = 16
const MAX_TCP_NOTIFIES = 8
//
// Notify callbacks
//
struc t_notify
@ -127,14 +163,16 @@ struc t_notify
word notify_func
word notify_parm
end
const MAX_UDP_NOTIFIES = 16
const MAX_TCP_NOTIFIES = 8
word portsUDP
word portsTCP
//
// Service ICMP externally
// Service ICMP hook
//
export word serviceICMP
export word hookICMP
//
// Ethernet driver entrypoints
//
word setFrameLen, writeFrame, getFrameLen, readFrame
//
// Defines for ASM routines
//
@ -142,8 +180,6 @@ asm equates
!SOURCE "vmsrc/plvmzp.inc"
end
//
// ASM utility functions
//
// Swap bytes in word
//
export asm swab
@ -201,214 +237,12 @@ CHKLP LDA (SRC),Y
INX
INX
RTS
end//
// 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 putha(haptr)
byte i
for i = 0 to 4
putb(haptr->[i]); putc(':')
next
return putb(haptr->[i])
end
def putip(ipptr)
byte i
for i = 0 to 2
puti(ipptr->[i]); putc('.')
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)
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
putha(packet + arp_targha)
putc('=')
putip(packet + arp_targip); putln
end
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
if len > 64
len = 64
fin
len = len - 1
for i = 0 to len
if (i & 7) == 0
putln
else
putc(' ')
fin
putb(^(packet+i))
next
putln
end
//
// Service incoming packets
//
export def serviceIP
word pkt, iphdr, hdr, opt, len, optlen, port, lclport, remport
byte i
len = recvEther
if len
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
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(@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
fin
break
otherwise
//dumparp(pkt)
wend
break
is PAYLOAD_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
//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[t_iphdr] hdr
byte retry
word timeout
@ -423,19 +257,22 @@ export def sendIP(ipdst, proto, seglist, size)
memcpy(@hdr.ip_src, @localip, IPADR_SIZE)
if !ipdst // IP_BROADCAST
memset(@hdr.ip_dst, IP_BROADCAST, IPADR_SIZE)
memset(@dstha, MAC_BROADCAST, MAC_SIZE)
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
else
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
retry = 0
while ipdst=>0 <> remoteip:0 and ipdst=>2 <> remoteip:2
while hdr:ip_dst:0 <> remoteip:0 and hdr:ip_dst:2 <> remoteip:2
if retry >= 3
return -1 // ARP failed
fin
retry = retry + 1
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
memset(@remoteha, 0, MAC_SIZE)
memcpy(@remoteip, ipdst, IPADR_SIZE)
opARP = ARP_REQST
writeEther(@ARP, t_earp)
memcpy(@remoteip, @hdr.ip_dst, IPADR_SIZE)
ePayload = PAYLOAD_ARP
opARP = ARP_REQST
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0
serviceIP
if remoteha:0 | remoteha:2 | remoteha:4
@ -443,53 +280,55 @@ export def sendIP(ipdst, proto, seglist, size)
fin
next
loop
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
memcpy(@dstha, @remoteha, MAC_SIZE)
memcpy(@dstMAC, @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
// set the ethernet payload and frame length
//
seglist=>seg_buf = @hdr
seglist=>seg_len = t_iphdr
return writevEther(@dstha, PAYLOAD_IP, seglist, t_iphdr + size)
ePayload = PAYLOAD_IP
setFrameLen(t_ethriphdr + size)
//
// Write the ethernet header
//
writeFrame(@eFrame, t_ethrhdr)
//
// Write the IP header
//
writeFrame(@hdr, t_iphdr)
//
// Write the remaining segments
//
while size > 0
writeFrame(seglist=>seg_buf, seglist=>seg_len)
size = size - seglist=>seg_len
seglist = seglist + t_segment
loop
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
word[8] seglist // list of data and header segments
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
seglist:0:seg_buf = @hdr
seglist:0:seg_len = t_udphdr
seglist:4:seg_buf = data
seglist:4: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)
export def listenUDP(localport, callback, param)
word port
byte i
@ -530,7 +369,7 @@ end
//
// Clear notify on UDP port
//
export def shutUDP(localport)
export def hangupUDP(localport)
word port
byte i
@ -548,8 +387,136 @@ export def shutUDP(localport)
return -1
end
//
// Fill in MAC
// Service incoming packets
//
copyMAC(@srcMAC)
copyMAC(@localha)
done
export def serviceIP
word rxsize, rxpacket, rxptr
word iphdr, opt, optlen, port, lclport, remport
byte i, echolen
word[4] seglist
byte[128] echo_reply
//
// Check for received packet
//
rxsize = getFrameLen()
if rxsize
//
// Read the entire packet into memory
//
rxpacket = heapalloc(rxsize)
readFrame(rxpacket, rxsize)
rxptr = rxpacket + t_ethrhdr
rxsize = rxsize - t_ethrhdr
//
// What kind of packet is it?
//
when rxpacket=>ethr_payload
is PAYLOAD_IP
iphdr = rxptr
rxptr = rxptr + t_iphdr
rxsize = rxsize - 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!
//
rxptr = rxptr + (optlen - t_iphdr)
rxsize = rxsize - (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:0) & (iphdr=>ip_dst:2|subnet:2) <> IP_BROADCAST
break
fin
fin
//
// What kind of IP protocol is it?
//
when iphdr->ip_proto
is IP_PROTO_UDP
port = portsUDP
if port
lclport = swab(rxptr=>udp_dst)
for i = 1 to MAX_UDP_NOTIFIES
if port=>notify_port == lclport)
port=>notify_func(@iphdr=>ip_src,swab(rxptr=>udp_src),lclport,rxptr+t_udphdr,swab(rxptr=>udp_len),port=>notify_parm)
break
fin
port = port + t_notify
next
fin
break
is IP_PROTO_TCP
break
is IP_PROTO_ICMP
//
// Service ICMP packets
//
if rxptr->icmp_type == ICMP_ECHO_REQST
if rxsize > 128
echolen = 128
else
echolen = rxsize
fin
memcpy(@echo_reply, rxptr, echolen)
echo_reply.icmp_type = ICMP_ECHO_REPLY
echo_reply:icmp_chksm = 0
seglist:seg_buf = @echo_reply
seglist:seg_len = echolen
sendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
fin
if hookICMP
hookICMP(@iphdr=>ip_src, rxptr, rxsize)
fin
wend
break
is PAYLOAD_ARP
when rxptr=>arp_op
is ARP_REPLY
//
// Fill in ARP cache
//
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
break
is ARP_REQST
//
// Is this a request for me?
//
if rxptr=>arp_targip:0 == localip:0 and rxptr=>arp_targip:2 == localip:2
memcpy(@dstMAC, @rxptr=>arp_senderha, MAC_SIZE)
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
ePayload = PAYLOAD_ARP
opARP = ARP_REPLY
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
fin
wend
wend
heaprelease(rxpacket)
fin
end
//
// Initialize the driver interface
//
export def setEtherDriver(MAC, getlen, readframe, setlen, writeframe)
memcpy(@myMAC, MAC, MAC_SIZE)
memcpy(@localha, MAC, MAC_SIZE)
getFrameLen = getlen
readFrame = readframe
setFrameLen = setlen
writeFrame = writeframe
end
done

35
src/libsrc/inet.pla Normal file
View File

@ -0,0 +1,35 @@
import cmdsys
predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID
end
import uthernet
byte localip, subnet, gateway
predef serviceIP
end
byte dhcp = "DHCP"
byte serverip = 192,168,123,1
byte staticip = 192,168,123,10
byte staticmask = 255,255,255,0
if modexec(@dhcp) < 0
//
// Set our local IP address
//
memcpy(@localip, @staticip, 4)
memcpy(@subnet, @staticmask, 4)
memcpy(@gateway, @serverip, 4)
fin
//
// Service IP
//
repeat
serviceIP
until ^$C000 > 127
^$C010
done

View File

@ -1,8 +1,8 @@
import cmdsys
predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID
//
// Include dependency on S/W IP stack
//
import etherip
predef setEtherDriver
end
//
// Module don't free memory
@ -10,33 +10,6 @@ end
const modkeep = $2000
const modinitkeep = $4000
//
// Segment list element
//
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
//
const MAX_FRAME_SIZE = 1518
//
// MAC address
//
byte MAC = $00,$0A,$99,$1E,$02,$00
//
// Uthernet register offsets
//
const TXDATA = $00
@ -58,9 +31,9 @@ byte isq
byte pregidx
byte pregdata
//
// Current receive status and packet size
// Uthernet MAC address
//
word rxsize, rxpacket, rxptr
byte[6] utherMAC = $00,$0A,$99,$1E,$02,$00
//
// Defines for ASM routines
//
@ -68,21 +41,7 @@ asm equates
!SOURCE "vmsrc/plvmzp.inc"
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)
// Uthernet I/O functions
//
asm _pokeiow
LDA ESTKL,X
@ -126,7 +85,7 @@ asm _peekiowh
RTS
end
//
// WRITE PACKET FRAME INTO I/O SPACE
// WRITE FRAME DATA INTO I/O SPACE
// pokefrm(BUF, LEN)
//
asm pokefrm
@ -164,7 +123,7 @@ asm _pokefrmh
RTS
end
//
// READ PACKET FRAME FROM I/O SPACE
// READ FRAME DATA FROM I/O SPACE
// peekfrm(BUF, LEN)
//
asm peekfrm
@ -201,10 +160,6 @@ asm _peekfrmh
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
@ -228,63 +183,30 @@ def peekpreg(reg)
return peekiow(pregdata)
end
//
// Uthernet interface
// Set the length of the next packet to send and wait for data space availability
//
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)
def pokefrmlen(len)
pokeiow(txcmd, $C0)
pokeiow(txlen, size)
pokeiow(txlen, len)
repeat; until peekpreg($0138) & $0100
return pokefrm(packet, size)
end
export def writevEther(destha, payload, seglist, size)
pokeiow(txcmd, $C0)
pokeiow(txlen, size + t_ethrhdr)
repeat; until peekpreg($0138) & $0100
pokefrm(destha, MAC_SIZE)
pokefrm(@MAC, MAC_SIZE)
pokefrm(@payload, 2)
while size > 0
pokefrm(seglist=>seg_buf, seglist=>seg_len)
size = size - seglist=>seg_len
seglist = seglist + t_segment
loop
end
export def readEther(size)
word segptr
if rxsize > 0
if size > rxsize
size = rxsize
fin
segptr = rxptr
rxptr = rxptr + size
rxsize = rxsize - size
else
segptr = 0
fin
return segptr
end
export def recvEther
if rxsize == 0
if peekiow(isq) & $3F == $04
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
fin
//
// Return the length of awaiting packet, 0 otherwise
//
def peekfrmlen
word len
len = 0
if peekiow(isq) & $3F == $04
if peekio(rxdata_hi) & $01
peekio(rxdata_lo)
len.1 = peekio(rxdata_hi)
len.0 = peekio(rxdata_lo)
else
peekio(rxdata_lo)
pokepreg($0102, $0140) // Skip pkt
fin
fin
return rxsize
return len
end
//
// Identify Uthernet card and initialize
@ -304,13 +226,17 @@ for slot = $F0 downto $90 step $10
_pokefrmh.1 = slot+1
_peekfrml.1 = slot
_peekfrmh.1 = slot+1
pokepreg($0158, MAC:0) // MAC addr
pokepreg($015A, MAC:2) // MAC addr
pokepreg($015C, MAC:4) // MAC addr
pokepreg($0158, utherMAC:0) // MAC addr
pokepreg($015A, utherMAC:2) // MAC addr
pokepreg($015C, utherMAC:4) // MAC addr
pokepreg($0102, $0100) // Recv cfg
pokepreg($0104, $0D00) // Recv ctrl
pokepreg($0106, $8200) // Xmit cfg
pokepreg($0112, $00C0) // Line ctrl
//
// Install etherip driver
//
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
return modkeep
fin
fin

View File

@ -11,9 +11,8 @@ ROD = ROD\#FE1000
SIEVE = SIEVE\#FE1000
UTHERNET= UTHERNET\#FE1000
ETHERIP = ETHERIP\#FE1000
ICMP = ICMP\#FE1000
INET = INET\#FE1000
DHCP = DHCP\#FE1000
STATICIP= STATICIP\#FE1000
ROGUE = ROGUE\#FE1000
ROGUEIO = ROGUEIO\#FE1000
ROGUEMAP= ROGUEMAP\#FE1000
@ -46,7 +45,7 @@ TXTTYPE = .TXT
#SYSTYPE = \#FF2000
#TXTTYPE = \#040000
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ICMP) $(DHCP) $(STATICIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
clean:
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
@ -123,25 +122,21 @@ $(SIEVE): samplesrc/sieve.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/sieve.pla > samplesrc/sieve.a
acme --setpc 4094 -o $(SIEVE) samplesrc/sieve.a
$(UTHERNET): samplesrc/uthernet.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/uthernet.pla > samplesrc/uthernet.a
acme --setpc 4094 -o $(UTHERNET) samplesrc/uthernet.a
$(UTHERNET): libsrc/uthernet.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < libsrc/uthernet.pla > libsrc/uthernet.a
acme --setpc 4094 -o $(UTHERNET) libsrc/uthernet.a
$(ETHERIP): samplesrc/etherip.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/etherip.pla > samplesrc/etherip.a
acme --setpc 4094 -o $(ETHERIP) samplesrc/etherip.a
$(ETHERIP): libsrc/etherip.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < libsrc/etherip.pla > libsrc/etherip.a
acme --setpc 4094 -o $(ETHERIP) libsrc/etherip.a
$(ICMP): samplesrc/icmp.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/icmp.pla > samplesrc/icmp.a
acme --setpc 4094 -o $(ICMP) samplesrc/icmp.a
$(INET): libsrc/inet.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < libsrc/inet.pla > libsrc/inet.a
acme --setpc 4094 -o $(INET) libsrc/inet.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
$(DHCP): libsrc/dhcp.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < libsrc/dhcp.pla > libsrc/dhcp.a
acme --setpc 4094 -o $(DHCP) libsrc/dhcp.a
$(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a

View File

@ -1,96 +0,0 @@
//
// ICMP service
//
import cmdsys
predef syscall, call, 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

View File

@ -1,98 +0,0 @@
//
// Static IP
//
import cmdsys
predef syscall, call, 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