1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-01-12 04:30:42 +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 predef heapmark, heapallocalign, heapalloc, heaprelease
byte MACHID byte MACHID
end end
import etherip import inet
byte localha, localip, subnet_mask, gateway byte localha, localip, subnet, gateway
predef swab, sendUDP, recvUDP, shutUDP, serviceIP predef swab, sendUDP, listenUDP, hangupUDP, serviceIP
end
import icmp
end end
// //
// Needed to init subnet_mask // Needed to init subnet
// //
const IP_BROADCAST = $FFFF const IP_BROADCAST = $FFFF
// //
@ -48,6 +46,10 @@ const DHCP_ACK = $05
const DHCP_NACK = $06 const DHCP_NACK = $06
const DHCP_RELEASE = $07 const DHCP_RELEASE = $07
// //
// Track DHCP progress
//
byte stateDHCP, retry, timeout
//
// DHCP ports // DHCP ports
// //
const DHCP_CLIENT_PORT = 68 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 if pkt=>dhcp_xid:0 == $0201 and pkt=>dhcp_xid:2 = $0403
when pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 53) + 2] when pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 53) + 2]
is DHCP_OFFER is DHCP_OFFER
stateDHCP = DHCP_OFFER
//puts(@offerstr); putip(@pkt->dhcp_yourip); putln //puts(@offerstr); putip(@pkt->dhcp_yourip); putln
// //
// Copy offer parameters to request // 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) sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
break break
is DHCP_ACK is DHCP_ACK
stateDHCP = DHCP_ACK
//
// Stop listening to UDP port
//
hangupUDP(DHCP_CLIENT_PORT)
//puts(@ackstr) //puts(@ackstr)
// //
// Copy parameters to working copy // Copy parameters to working copy
// //
memcpy(@localip, @pkt->dhcp_yourip, 4) memcpy(@localip, @pkt->dhcp_yourip, 4)
memcpy(@subnet_mask, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4) memcpy(@subnet, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4)
puts(@boundstr);putip(@localip);putc('/');putip(@subnet_mask);putln puts(@boundstr);putip(@localip);putc('/');putip(@subnet);putln
break break
otherwise otherwise
dumpdhcp(pkt) dumpdhcp(pkt)
@ -191,20 +199,30 @@ memset(@localip, 0, 4)
// //
// Set subnet mask to all 1's // 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 // Prepare to receive DHCP packets from a server
// //
recvUDP(DHCP_CLIENT_PORT, @servdhcp, 0) listenUDP(DHCP_CLIENT_PORT, @servdhcp, 0)
//
// Broadcast DHCP DISCOVER message
//
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
// //
// Service IP // Service IP
// //
repeat while retry < 3
serviceIP //
until ^$C000 > 127 // Broadcast DHCP DISCOVER message
^$C010 //
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 done

View File

@ -1,12 +1,18 @@
import cmdsys import cmdsys
predef syscall, call, getc, gets, putc, puts, putln predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID byte MACHID
end end
import uthernet //
predef copyMAC, writeEther, writevEther, readEther, recvEther // Module don't free memory
end //
const modkeep = $2000
const modinitkeep = $4000
//
// Predefine service routine
//
predef serviceIP
// //
// Segment list element // Segment list element
// //
@ -47,50 +53,26 @@ struc t_iphdr
byte[IPADR_SIZE] ip_dst byte[IPADR_SIZE] ip_dst
byte[] ip_options byte[] ip_options
end end
const t_ethriphdr = t_ethrhdr + t_iphdr
const IP_BROADCAST = $FFFF const IP_BROADCAST = $FFFF
const IP_PROTO_ICMP = $01 const IP_PROTO_ICMP = $01
const IP_PROTO_UDP = $11 const IP_PROTO_UDP = $11
const IP_PROTO_TCP = $06 const IP_PROTO_TCP = $06
// //
// ARP packet // ICMP type/codes
// //
const HW_ETHER = $0100 // BE format const IP_PROTO_ICMP = 1
const ARP_PROTO = $0008 // BE format const ICMP_ECHO_REQST = 8
const ARP_REQST = $0100 // BE format const ICMP_ECHO_REPLY = 0
const ARP_REPLY = $0200 // BE format //
struc t_arp // ICMP message format
word arp_hw //
word arp_proto struc t_icmp
byte arp_hlen byte icmp_type
byte arp_plen byte icmp_code
word arp_op word icmp_chksm
byte[MAC_SIZE] arp_senderha word[2] icmp_header
byte[IPADR_SIZE] arp_senderip
byte[MAC_SIZE] arp_targha
byte[IPADR_SIZE] arp_targip
end 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 // UDP IPv4 psuedo header
// //
@ -120,6 +102,60 @@ struc t_tcphdr
word tcp_chksm word tcp_chksm
end 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 // Notify callbacks
// //
struc t_notify struc t_notify
@ -127,14 +163,16 @@ struc t_notify
word notify_func word notify_func
word notify_parm word notify_parm
end end
const MAX_UDP_NOTIFIES = 16
const MAX_TCP_NOTIFIES = 8
word portsUDP word portsUDP
word portsTCP 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 // Defines for ASM routines
// //
@ -142,8 +180,6 @@ asm equates
!SOURCE "vmsrc/plvmzp.inc" !SOURCE "vmsrc/plvmzp.inc"
end end
// //
// ASM utility functions
//
// Swap bytes in word // Swap bytes in word
// //
export asm swab export asm swab
@ -201,214 +237,12 @@ CHKLP LDA (SRC),Y
INX INX
INX INX
RTS 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 end
// //
// Send IP datagram // Send IP datagram
// //
export def sendIP(ipdst, proto, seglist, size) export def sendIP(ipdst, proto, seglist, size)
byte[t_iphdr] hdr byte[t_iphdr] hdr
byte[MAC_SIZE] dstha
byte retry byte retry
word timeout word timeout
@ -423,19 +257,22 @@ export def sendIP(ipdst, proto, seglist, size)
memcpy(@hdr.ip_src, @localip, IPADR_SIZE) memcpy(@hdr.ip_src, @localip, IPADR_SIZE)
if !ipdst // IP_BROADCAST if !ipdst // IP_BROADCAST
memset(@hdr.ip_dst, IP_BROADCAST, IPADR_SIZE) memset(@hdr.ip_dst, IP_BROADCAST, IPADR_SIZE)
memset(@dstha, MAC_BROADCAST, MAC_SIZE) memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
else else
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
retry = 0 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 if retry >= 3
return -1 // ARP failed return -1 // ARP failed
fin fin
retry = retry + 1 retry = retry + 1
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE) memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
memset(@remoteha, 0, MAC_SIZE) memset(@remoteha, 0, MAC_SIZE)
memcpy(@remoteip, ipdst, IPADR_SIZE) memcpy(@remoteip, @hdr.ip_dst, IPADR_SIZE)
opARP = ARP_REQST ePayload = PAYLOAD_ARP
writeEther(@ARP, t_earp) opARP = ARP_REQST
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0 for timeout = 1000 downto 0
serviceIP serviceIP
if remoteha:0 | remoteha:2 | remoteha:4 if remoteha:0 | remoteha:2 | remoteha:4
@ -443,53 +280,55 @@ export def sendIP(ipdst, proto, seglist, size)
fin fin
next next
loop loop
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE) memcpy(@dstMAC, @remoteha, MAC_SIZE)
memcpy(@dstha, @remoteha, MAC_SIZE)
fin fin
// //
// Calculate checksum // Calculate checksum
// //
hdr:ip_chksm = sum1(0, @hdr, t_iphdr) ^ $FFFF 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 ePayload = PAYLOAD_IP
seglist=>seg_len = t_iphdr setFrameLen(t_ethriphdr + size)
return writevEther(@dstha, PAYLOAD_IP, seglist, t_iphdr + 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 end
// //
// Send UDP datagram // Send UDP datagram
// //
export def sendUDP(ipdst, portdst, portsrc, data, len) export def sendUDP(ipdst, portdst, portsrc, data, len)
word[12] seglist // list of data and header segments word[8] seglist // list of data and header segments
//word segsum
//byte[t_piphdr] phdr
byte[t_udphdr] hdr 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_src = swab(portsrc)
hdr:udp_dst = swab(portdst) hdr:udp_dst = swab(portdst)
hdr:udp_len = swab(t_udphdr + len) hdr:udp_len = swab(t_udphdr + len)
hdr:udp_chksm = 0 hdr:udp_chksm = 0
//segsum = sum1(0, @phdr, t_piphdr + t_udphdr) seglist:0:seg_buf = @hdr
//segsum = sum1(segsum, data, len) seglist:0:seg_len = t_udphdr
//hdr:udp_chksm = segsum ^ $FFFF seglist:4:seg_buf = data
//seglist:0:seg_buf reserved for IP header seglist:4:seg_len = len
//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) return sendIP(ipdst, IP_PROTO_UDP, @seglist, t_udphdr + len)
end end
// //
// Notify on UDP datagram received // Notify on UDP datagram received
// //
export def recvUDP(localport, callback, param) export def listenUDP(localport, callback, param)
word port word port
byte i byte i
@ -530,7 +369,7 @@ end
// //
// Clear notify on UDP port // Clear notify on UDP port
// //
export def shutUDP(localport) export def hangupUDP(localport)
word port word port
byte i byte i
@ -548,8 +387,136 @@ export def shutUDP(localport)
return -1 return -1
end end
// //
// Fill in MAC // Service incoming packets
// //
copyMAC(@srcMAC) export def serviceIP
copyMAC(@localha) word rxsize, rxpacket, rxptr
done 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 // Include dependency on S/W IP stack
predef memset, memcpy, modaddr, modexec //
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail import etherip
byte MACHID predef setEtherDriver
end end
// //
// Module don't free memory // Module don't free memory
@ -10,33 +10,6 @@ end
const modkeep = $2000 const modkeep = $2000
const modinitkeep = $4000 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 // Uthernet register offsets
// //
const TXDATA = $00 const TXDATA = $00
@ -58,9 +31,9 @@ byte isq
byte pregidx byte pregidx
byte pregdata 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 // Defines for ASM routines
// //
@ -68,21 +41,7 @@ asm equates
!SOURCE "vmsrc/plvmzp.inc" !SOURCE "vmsrc/plvmzp.inc"
end end
// //
// I/O access // Uthernet I/O functions
//
// 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)
// //
asm _pokeiow asm _pokeiow
LDA ESTKL,X LDA ESTKL,X
@ -126,7 +85,7 @@ asm _peekiowh
RTS RTS
end end
// //
// WRITE PACKET FRAME INTO I/O SPACE // WRITE FRAME DATA INTO I/O SPACE
// pokefrm(BUF, LEN) // pokefrm(BUF, LEN)
// //
asm pokefrm asm pokefrm
@ -164,7 +123,7 @@ asm _pokefrmh
RTS RTS
end end
// //
// READ PACKET FRAME FROM I/O SPACE // READ FRAME DATA FROM I/O SPACE
// peekfrm(BUF, LEN) // peekfrm(BUF, LEN)
// //
asm peekfrm asm peekfrm
@ -201,10 +160,6 @@ asm _peekfrmh
EXPSW INX EXPSW INX
RTS RTS
end end
//def pokeio(io, data)
// _pokeiowl.1 = io
// return _pokeio(data)
//end
def pokeiow(io, data) def pokeiow(io, data)
_pokeiowl.1 = io _pokeiowl.1 = io
_pokeiowh.1 = io+1 _pokeiowh.1 = io+1
@ -228,63 +183,30 @@ def peekpreg(reg)
return peekiow(pregdata) return peekiow(pregdata)
end end
// //
// Uthernet interface // Set the length of the next packet to send and wait for data space availability
// //
export def copyMAC(ptr) def pokefrmlen(len)
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(txcmd, $C0)
pokeiow(txlen, size) pokeiow(txlen, len)
repeat; until peekpreg($0138) & $0100 repeat; until peekpreg($0138) & $0100
return pokefrm(packet, size)
end end
export def writevEther(destha, payload, seglist, size) //
pokeiow(txcmd, $C0) // Return the length of awaiting packet, 0 otherwise
pokeiow(txlen, size + t_ethrhdr) //
repeat; until peekpreg($0138) & $0100 def peekfrmlen
pokefrm(destha, MAC_SIZE) word len
pokefrm(@MAC, MAC_SIZE) len = 0
pokefrm(@payload, 2) if peekiow(isq) & $3F == $04
while size > 0 if peekio(rxdata_hi) & $01
pokefrm(seglist=>seg_buf, seglist=>seg_len) peekio(rxdata_lo)
size = size - seglist=>seg_len len.1 = peekio(rxdata_hi)
seglist = seglist + t_segment len.0 = peekio(rxdata_lo)
loop else
end peekio(rxdata_lo)
export def readEther(size) pokepreg($0102, $0140) // Skip pkt
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
fin fin
fin fin
return rxsize return len
end end
// //
// Identify Uthernet card and initialize // Identify Uthernet card and initialize
@ -304,13 +226,17 @@ for slot = $F0 downto $90 step $10
_pokefrmh.1 = slot+1 _pokefrmh.1 = slot+1
_peekfrml.1 = slot _peekfrml.1 = slot
_peekfrmh.1 = slot+1 _peekfrmh.1 = slot+1
pokepreg($0158, MAC:0) // MAC addr pokepreg($0158, utherMAC:0) // MAC addr
pokepreg($015A, MAC:2) // MAC addr pokepreg($015A, utherMAC:2) // MAC addr
pokepreg($015C, MAC:4) // MAC addr pokepreg($015C, utherMAC:4) // MAC addr
pokepreg($0102, $0100) // Recv cfg pokepreg($0102, $0100) // Recv cfg
pokepreg($0104, $0D00) // Recv ctrl pokepreg($0104, $0D00) // Recv ctrl
pokepreg($0106, $8200) // Xmit cfg pokepreg($0106, $8200) // Xmit cfg
pokepreg($0112, $00C0) // Line ctrl pokepreg($0112, $00C0) // Line ctrl
//
// Install etherip driver
//
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
return modkeep return modkeep
fin fin
fin fin

View File

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