mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-03-20 03:31:27 +00:00
Working Uthernet2 driver
This commit is contained in:
parent
ff1fb15531
commit
40b3f8194c
@ -45,7 +45,7 @@ export byte[t_inet] iNet
|
||||
//
|
||||
// List of loadable network device drivers
|
||||
//
|
||||
byte netDrivers = "WIZNET"
|
||||
byte netDrivers = "UTHERNET2"
|
||||
byte = "UTHERNET"
|
||||
byte = ""
|
||||
word driver = @netDrivers
|
||||
|
962
src/libsrc/uthernet2.pla
Normal file
962
src/libsrc/uthernet2.pla
Normal file
@ -0,0 +1,962 @@
|
||||
//
|
||||
// Uthernet II Wiznet 5100 based ethernet card
|
||||
//
|
||||
// TCP/IP is built into hardware, so no dependencies on the software
|
||||
// layers, like the Uthernet
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef isugt, isuge, isult, isule
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
byte MACHID
|
||||
end
|
||||
//
|
||||
// Net object
|
||||
//
|
||||
import inet
|
||||
word iNet
|
||||
end
|
||||
struc t_inet
|
||||
word initIP
|
||||
word serviceIP
|
||||
word openUDP
|
||||
word sendUDP
|
||||
word closeUDP
|
||||
word listenTCP
|
||||
word connectTCP
|
||||
word sendTCP
|
||||
word closeTCP
|
||||
word setInterfaceIP
|
||||
word getInterfaceHA
|
||||
end
|
||||
//
|
||||
// Module don't free memory
|
||||
//
|
||||
const modkeep = $2000
|
||||
const modinitkeep = $4000
|
||||
//
|
||||
// Wiznet registers
|
||||
//
|
||||
const WIZ_MR = $00
|
||||
const WIZ_GWR = $01
|
||||
const WIZ_SUBR = $05
|
||||
const WIZ_SHAR = $09
|
||||
const WIZ_SIPR = $0F
|
||||
const WIZ_IR = $15
|
||||
const WIZ_IMR = $16
|
||||
const WIZ_RTR = $17
|
||||
const WIZ_RCR = $19
|
||||
const WIZ_RMSR = $1A
|
||||
const WIZ_TMSR = $1B
|
||||
const WIZ_PATR = $1C
|
||||
const WIZ_PTMR = $28
|
||||
const WIZ_PMGC = $29
|
||||
const WIZ_UIPR = $2A
|
||||
const WIZ_UPRT = $2E
|
||||
//
|
||||
// Wiznet socket registers
|
||||
//
|
||||
const WIZ_SREGS = $0400
|
||||
const WIZ_SSIZE = $0100
|
||||
const WIZ_SOCK0 = $0400
|
||||
const WIZ_SOCK1 = $0500
|
||||
const WIZ_SOCK2 = $0600
|
||||
const WIZ_SOCK3 = $0700
|
||||
const WIZ_SnMR = $00
|
||||
const WIZ_SnCR = $01
|
||||
const WIZ_SnIR = $02
|
||||
const WIZ_SnSR = $03
|
||||
const WIZ_SnPORT = $04
|
||||
const WIZ_SnDHAR = $06
|
||||
const WIZ_SnDIPR = $0C
|
||||
const WIZ_SnDPORT = $10
|
||||
const WIZ_SnMSSR = $12
|
||||
const WIZ_SnPROTO = $14
|
||||
const WIZ_SnTOS = $15
|
||||
const WIZ_SnTTL = $16
|
||||
const WIZ_SnFSR = $20
|
||||
const WIZ_SnTXRD = $22
|
||||
const WIZ_SnTXWR = $24
|
||||
const WIZ_SnRSR = $26
|
||||
const WIZ_SnRXRD = $28
|
||||
//
|
||||
// Wiznet socket data
|
||||
//
|
||||
const WIZ_TXMEM = $4000
|
||||
const WIZ_TXSIZE = $0800
|
||||
const WIZ_TXMASK = WIZ_TXSIZE-1
|
||||
const WIZ_TXMEM0 = $4000
|
||||
const WIZ_TXMEM1 = $4800
|
||||
const WIZ_TXMEM2 = $5000
|
||||
const WIZ_TXMEM3 = $5800
|
||||
const WIZ_RXMEM = $6000
|
||||
const WIZ_RXSIZE = $0800
|
||||
const WIZ_RXMASK = WIZ_RXSIZE-1
|
||||
const WIZ_RXMEM0 = $6000
|
||||
const WIZ_RXMEM1 = $6800
|
||||
const WIZ_RXMEM2 = $7000
|
||||
const WIZ_RXMEM3 = $7800
|
||||
//
|
||||
// Wiznet indirect registers
|
||||
//
|
||||
byte slot, regidx, regdata
|
||||
word saveidx
|
||||
//
|
||||
// Wiznet MAC address
|
||||
//
|
||||
byte[6] wizMAC = $00,$0A,$99,$1E,$02,$B0
|
||||
//
|
||||
// Wiznet IP addresses
|
||||
//
|
||||
byte[4] localip
|
||||
byte[4] subnet
|
||||
byte[4] gateway
|
||||
//
|
||||
// Predefine service routine
|
||||
//
|
||||
predef wizServiceIP
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// Max Ethernet frame size
|
||||
//
|
||||
const MAX_FRAME_SIZE = 1518
|
||||
const MAC_BROADCAST = $FFFF
|
||||
const MAC_SIZE = 6
|
||||
//
|
||||
// Ethernet header
|
||||
//
|
||||
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 IP4ADR_SIZE = 4
|
||||
struc t_iphdr
|
||||
byte ip_vers_hlen
|
||||
byte ip_service
|
||||
word ip_length
|
||||
word ip_id
|
||||
word ip_flags_fragofst
|
||||
byte ip_ttl
|
||||
byte ip_proto
|
||||
word ip_chksm
|
||||
byte[IP4ADR_SIZE] ip_src
|
||||
byte[IP4ADR_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
|
||||
word bcast = IP_BROADCAST, IP_BROADCAST
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// UDP IPv4 psuedo header
|
||||
//
|
||||
struc t_piphdr
|
||||
byte[IP4ADR_SIZE] pip_src
|
||||
byte[IP4ADR_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
|
||||
//
|
||||
// Local network parameters
|
||||
//
|
||||
const MAX_WIZ_CHANNELS = 4
|
||||
//
|
||||
// Channel protocols
|
||||
//
|
||||
const WIZ_PROTO_CLOSED = 0
|
||||
const WIZ_PROTO_TCP = 1
|
||||
const WIZ_PROTO_UDP = 2
|
||||
const WIZ_PROTO_IP = 3
|
||||
const WIZ_PROTO_RAW = 4
|
||||
//
|
||||
// State transistions
|
||||
//
|
||||
const TCP_STATE_CLOSED = 0
|
||||
const TCP_STATE_CLOSING = 1
|
||||
const TCP_STATE_LISTEN = 2
|
||||
const TCP_STATE_CONNECT = 3
|
||||
const TCP_STATE_OPEN = 4
|
||||
//
|
||||
// HW channels
|
||||
//
|
||||
struc t_channel
|
||||
byte channel_proto
|
||||
byte channel_state
|
||||
word channel_regs
|
||||
word channel_txmem
|
||||
word channel_rxmem
|
||||
word channel_lclport
|
||||
word channel_remport
|
||||
byte[4] channel_remip
|
||||
word channel_recv_func
|
||||
word channel_recv_parm
|
||||
end
|
||||
byte[t_channel * MAX_WIZ_CHANNELS] wizChannel
|
||||
//
|
||||
// Service ICMP hook
|
||||
//
|
||||
export word hookICMP
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
asm equates
|
||||
!SOURCE "vmsrc/plvmzp.inc"
|
||||
end
|
||||
//
|
||||
// Swap bytes in word
|
||||
//
|
||||
asm swab
|
||||
LDA ESTKL,X
|
||||
LDY ESTKH,X
|
||||
STA ESTKH,X
|
||||
STY ESTKL,X
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// Wiznet I/O functions
|
||||
//
|
||||
// POKE WORD TO I/O SPACE
|
||||
// Note: Big Endian format
|
||||
//
|
||||
asm _pokeiow
|
||||
LDA ESTKH,X
|
||||
end
|
||||
asm _pokeiowl
|
||||
STA $C000
|
||||
LDA ESTKL,X
|
||||
end
|
||||
asm _pokeiowh
|
||||
STA $C000
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// POKE BYTE TO I/O SPACE
|
||||
//
|
||||
asm _pokeio
|
||||
LDA ESTKL,X
|
||||
end
|
||||
asm _pokeiol
|
||||
STA $C000
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// PEEK BYTE FROM I/O SPACE
|
||||
//
|
||||
asm _peekio
|
||||
DEX
|
||||
end
|
||||
asm _peekiol
|
||||
LDA $C000
|
||||
STA ESTKL,X
|
||||
LDA #$00
|
||||
STA ESTKH,X
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// PEEK WORD FROM I/O SPACE
|
||||
// Note: Big Endian format
|
||||
//
|
||||
asm _peekiow
|
||||
DEX
|
||||
end
|
||||
asm _peekiowl
|
||||
LDA $C000
|
||||
STA ESTKH,X
|
||||
end
|
||||
asm _peekiowh
|
||||
LDA $C000
|
||||
STA ESTKL,X
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// WRITE DATA INTO I/O SPACE
|
||||
// pokedata(BUF, LEN)
|
||||
//
|
||||
asm pokedata
|
||||
LDA ESTKL+1,X
|
||||
STA SRCL
|
||||
LDA ESTKH+1,X
|
||||
STA SRCH
|
||||
LDY ESTKL,X
|
||||
BEQ POKELP
|
||||
LDY #$00
|
||||
INC ESTKH,X
|
||||
POKELP LDA (SRC),Y
|
||||
end
|
||||
asm _pokedata
|
||||
STA $C000
|
||||
INY
|
||||
BNE +
|
||||
INC SRCH
|
||||
+ DEC ESTKL,X
|
||||
BNE POKELP
|
||||
DEC ESTKH,X
|
||||
BNE POKELP
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// READ DATA FROM I/O SPACE
|
||||
// peekdata(BUF, LEN)
|
||||
//
|
||||
asm peekdata
|
||||
LDA ESTKL+1,X
|
||||
STA DSTL
|
||||
LDA ESTKH+1,X
|
||||
STA DSTH
|
||||
LDY ESTKL,X
|
||||
BEQ PEEKLP
|
||||
LDY #$00
|
||||
INC ESTKH,X
|
||||
end
|
||||
asm _peekdata
|
||||
PEEKLP LDA $C000
|
||||
STA (DST),Y
|
||||
INY
|
||||
BNE +
|
||||
INC DSTH
|
||||
+ DEC ESTKL,X
|
||||
BNE PEEKLP
|
||||
DEC ESTKH,X
|
||||
BNE PEEKLP
|
||||
INX
|
||||
RTS
|
||||
end
|
||||
def pokeiow(io, data)
|
||||
_pokeiowl.1 = io
|
||||
_pokeiowh.1 = io+1
|
||||
return _pokeiow(data)
|
||||
end
|
||||
def pokeio(io, data)
|
||||
_pokeiol.1 = io
|
||||
return _pokeio(data)
|
||||
end
|
||||
def peekio(io)
|
||||
_peekiol.1 = io
|
||||
return _peekio()
|
||||
end
|
||||
def peekiow(io)
|
||||
_peekiowl.1 = io
|
||||
_peekiowh.1 = io+1
|
||||
return _peekiow()
|
||||
end
|
||||
def pokereg(reg, data)
|
||||
_pokeiow(reg)
|
||||
return _pokeio(data)
|
||||
end
|
||||
def peekreg(reg)
|
||||
_pokeiow(reg)
|
||||
return _peekio()
|
||||
end
|
||||
def pokeregs(reg, buf, len)
|
||||
_pokeiow(reg)
|
||||
return pokedata(buf, len)
|
||||
end
|
||||
def peekregs(reg, buf, len)
|
||||
_pokeiow(reg)
|
||||
return peekdata(buf, len)
|
||||
end
|
||||
def pokeregw(reg, dataw)
|
||||
_pokeiow(reg)
|
||||
_pokeio(dataw.1)
|
||||
return _pokeio(dataw.0)
|
||||
end
|
||||
def peekregw(reg)
|
||||
word dataw
|
||||
|
||||
_pokeiow(reg)
|
||||
dataw.1 = _peekio()
|
||||
_pokeiow(reg + 1)
|
||||
dataw.0 = _peekio()
|
||||
return dataw
|
||||
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 putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
//
|
||||
// Send UDP datagram
|
||||
//
|
||||
def wizSendUDP(wiz, ipdst, portdst, data, len)
|
||||
word wizregs, wizdata, txrr, txwr, splitlen
|
||||
|
||||
wizregs = wiz=>channel_regs
|
||||
wizdata = wiz=>channel_txmem
|
||||
if !ipdst
|
||||
ipdst = @bcast
|
||||
fin
|
||||
//
|
||||
// Wait for Tx room
|
||||
//
|
||||
repeat; until peekregw(wizregs + WIZ_SnFSR) >= len
|
||||
//
|
||||
// Calc new write ptr, check for split
|
||||
//
|
||||
txwr = peekregw(wizregs + WIZ_SnTXWR)
|
||||
txrr = txwr & WIZ_TXMASK
|
||||
if txrr + len > WIZ_TXSIZE
|
||||
splitlen = WIZ_TXSIZE - txrr
|
||||
pokeregs(wizdata + txrr, data, splitlen)
|
||||
pokeregs(wizdata, data + splitlen, len - splitlen)
|
||||
else
|
||||
pokeregs(wizdata + txrr, data, len)
|
||||
fin
|
||||
//
|
||||
// Set destination address/port
|
||||
//
|
||||
pokeregs(wizregs + WIZ_SnDIPR, ipdst, IP4ADR_SIZE)
|
||||
pokeregw(wizregs + WIZ_SnDPORT, portdst)
|
||||
//
|
||||
// Update write pointer and send
|
||||
//
|
||||
pokeregw(wizregs + WIZ_SnTXWR, txwr + len)
|
||||
pokereg(wizregs + WIZ_SnCR, $20) // SEND
|
||||
end
|
||||
//
|
||||
// Open UDP channel and set datagram received callback
|
||||
//
|
||||
def wizOpenUDP(localport, callback, param)
|
||||
word wiz
|
||||
byte i
|
||||
|
||||
if !localport; return -1; fin // invalid port
|
||||
//
|
||||
// Look for an existing notification on localport
|
||||
//
|
||||
//putc('O')
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if wiz->channel_proto == IP_PROTO_UDP and wiz=>channel_lclport == localport
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
//
|
||||
// Add notification on localport if room
|
||||
//
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if !wiz->channel_proto
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
return 0
|
||||
fin
|
||||
fin
|
||||
//putc('0' + i);putln
|
||||
//
|
||||
// Fill in this channel and open it
|
||||
//
|
||||
wiz->channel_proto = WIZ_PROTO_UDP
|
||||
wiz=>channel_lclport = localport
|
||||
wiz=>channel_recv_func = callback
|
||||
wiz=>channel_recv_parm = param
|
||||
pokeregw(wiz=>channel_regs + WIZ_SnPORT, localport)
|
||||
pokereg(wiz=>channel_regs + WIZ_SnMR, $02) // UDP protocol
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN
|
||||
return wiz
|
||||
end
|
||||
//
|
||||
// Close UDP port
|
||||
//
|
||||
def wizCloseUDP(wiz)
|
||||
//putc('S')
|
||||
if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel)
|
||||
//
|
||||
// Clear notiications on this port
|
||||
//
|
||||
if wiz->channel_proto == WIZ_PROTO_UDP
|
||||
//putc('1' + ((wiz=>channel_regs - WIZ_SREGS) >> 8));putln
|
||||
wiz->channel_proto = WIZ_PROTO_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
return 0
|
||||
fin
|
||||
fin
|
||||
//putc('!');putln
|
||||
//
|
||||
// Invalid port
|
||||
//
|
||||
return -1
|
||||
end
|
||||
//
|
||||
// Open TCP socket in SERVER mode
|
||||
//
|
||||
def wizListenTCP(lclport, callback, param)
|
||||
word wiz
|
||||
byte i
|
||||
|
||||
//
|
||||
// Look for an existing notification on localport
|
||||
//
|
||||
//putc('L')
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_LISTEN and wiz=>channel_lclport == lclport
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
//
|
||||
// Add notification on localport if room
|
||||
//
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if !wiz->channel_proto
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
return 0
|
||||
fin
|
||||
fin
|
||||
//putc('0' + i);putln
|
||||
//
|
||||
// Fill in this channel and open it
|
||||
//
|
||||
wiz->channel_proto = WIZ_PROTO_TCP
|
||||
wiz->channel_state = TCP_STATE_LISTEN
|
||||
wiz=>channel_remip:0 = 0
|
||||
wiz=>channel_remip:2 = 0
|
||||
wiz=>channel_remport = 0
|
||||
wiz=>channel_lclport = lclport
|
||||
wiz=>channel_recv_func = callback
|
||||
wiz=>channel_recv_parm = param
|
||||
pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol
|
||||
pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport)
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN
|
||||
while peekreg(wiz=>channel_regs + WIZ_SnSR) <> $13; loop // Wait for init
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $02) // LISTEN
|
||||
return wiz
|
||||
end
|
||||
//
|
||||
// Open TCP socket in CLIENT mode
|
||||
//
|
||||
def wizConnectTCP(remip, remport, lclport, callback, param)
|
||||
word wiz
|
||||
byte i
|
||||
|
||||
//
|
||||
// Look for an existing notification on localport
|
||||
//
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_CONNECT and wiz=>channel_lclport == lclport
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
//
|
||||
// Add notification on localport if room
|
||||
//
|
||||
wiz = @wizChannel
|
||||
for i = 1 to MAX_WIZ_CHANNELS
|
||||
if !wiz->channel_proto
|
||||
break
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if i > MAX_WIZ_CHANNELS
|
||||
return 0
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Fill in this channel and open it
|
||||
//
|
||||
wiz->channel_proto = WIZ_PROTO_TCP
|
||||
wiz->channel_state = TCP_STATE_CONNECT
|
||||
wiz=>channel_remip:0 = remip=>0
|
||||
wiz=>channel_remip:2 = remip=>2
|
||||
wiz=>channel_remport = remport
|
||||
wiz=>channel_lclport = lclport
|
||||
wiz=>channel_recv_func = callback
|
||||
wiz=>channel_recv_parm = param
|
||||
pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol
|
||||
pokeregs(wiz=>channel_regs + WIZ_SnDIPR, remip, IP4ADR_SIZE)
|
||||
pokeregw(wiz=>channel_regs + WIZ_SnDPORT, remport)
|
||||
pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport)
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $01) // OPEN
|
||||
while peekreg(wiz=>channel_regs + WIZ_SnSR) <> $13; loop // Wait for init
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $04) // CONNECT
|
||||
return wiz
|
||||
end
|
||||
//
|
||||
// Write to TCP socket
|
||||
//
|
||||
def wizSendTCP(wiz, data, len)
|
||||
word wizregs, wizdata, txrr, txwr, splitlen
|
||||
|
||||
if wiz->channel_state <> TCP_STATE_OPEN; return -1; fin
|
||||
//putc('W');puti(len);putc(':')
|
||||
wizregs = wiz=>channel_regs
|
||||
wizdata = wiz=>channel_txmem
|
||||
//
|
||||
// Wait for Tx room
|
||||
//
|
||||
repeat; until peekregw(wizregs + WIZ_SnFSR) >= len
|
||||
//
|
||||
// Calc new write ptr, check for split
|
||||
//
|
||||
txwr = peekregw(wizregs + WIZ_SnTXWR)
|
||||
txrr = txwr & WIZ_TXMASK
|
||||
if txrr + len > WIZ_TXSIZE
|
||||
splitlen = WIZ_TXSIZE - txrr
|
||||
pokeregs(wizdata + txrr, data, splitlen)
|
||||
pokeregs(wizdata, data + splitlen, len - splitlen)
|
||||
//putc('(');puti(splitlen);putc(',');puti(len-splitlen);putc(')')
|
||||
else
|
||||
pokeregs(wizdata + txrr, data, len)
|
||||
fin
|
||||
//puth(txrr);putc('-');putc('>');puth(txwr+len);putln
|
||||
//
|
||||
// Update write pointer and send
|
||||
//
|
||||
pokeregw(wizregs + WIZ_SnTXWR, txwr + len)
|
||||
pokereg(wizregs + WIZ_SnCR, $20) // SEND
|
||||
end
|
||||
//
|
||||
// Close TCP socket
|
||||
//
|
||||
def wizCloseTCP(wiz)
|
||||
if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel)
|
||||
//
|
||||
// Clear notiications on this port
|
||||
//
|
||||
if wiz->channel_proto == WIZ_PROTO_TCP and (wiz->channel_state == TCP_STATE_OPEN or wiz->channel_state == TCP_STATE_CLOSING)
|
||||
wiz->channel_state = TCP_STATE_CLOSING
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $08) // DISCON
|
||||
repeat
|
||||
wizServiceIP()
|
||||
until wiz->channel_state == TCP_STATE_CLOSED
|
||||
wiz->channel_proto = WIZ_PROTO_CLOSED
|
||||
return 0
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Invalid port
|
||||
//
|
||||
return -1
|
||||
end
|
||||
//
|
||||
// Service incoming packets
|
||||
//
|
||||
def wizServiceIP
|
||||
word wiz, wizregs, wizdata, rxlen, rxrr, rxwr, rxpkt, splitlen
|
||||
byte ir, i, sir
|
||||
|
||||
ir = peekreg(WIZ_IR)
|
||||
if ir and ir <> $FF // Ignore spurious read of IR
|
||||
//putc('I');putb(ir)
|
||||
wiz = @wizChannel
|
||||
for i = 0 to 3
|
||||
when ir & (1 << i)
|
||||
is 1
|
||||
is 2
|
||||
is 4
|
||||
is 8
|
||||
wizregs = wiz=>channel_regs
|
||||
wizdata = wiz=>channel_rxmem
|
||||
sir = peekreg(wizregs + WIZ_SnIR)
|
||||
when wiz->channel_proto
|
||||
is WIZ_PROTO_TCP
|
||||
if sir & $01
|
||||
//putc('C')
|
||||
//
|
||||
// Connect TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_LISTEN
|
||||
peekregs(wiz=>channel_regs + WIZ_SnDIPR, @wiz=>channel_remip, IP4ADR_SIZE)
|
||||
wiz=>channel_remport = peekregw(wiz=>channel_regs + WIZ_SnDPORT)
|
||||
is TCP_STATE_CONNECT
|
||||
wiz->channel_state = TCP_STATE_OPEN
|
||||
break
|
||||
otherwise
|
||||
//putc('?')
|
||||
wend
|
||||
fin
|
||||
if sir & $04
|
||||
//putc('R')
|
||||
//
|
||||
// Receive TCP packet
|
||||
//
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
//puti(rxlen);putc(':')
|
||||
if rxwr + rxlen > WIZ_RXSIZE
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
//putc('(');puti(splitlen);putc(',');puti(rxlen-splitlen);putc(')')
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
//puth(rxwr);putc('-');putc('>');puth(rxwr+rxlen);putln
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,rxpkt,rxlen,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
fin
|
||||
if sir & $02
|
||||
//putc('S')
|
||||
//
|
||||
// Close TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_OPEN
|
||||
wiz->channel_state = TCP_STATE_CLOSING
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,0,wiz=>channel_lclport,0,wiz=>channel_recv_parm)
|
||||
break
|
||||
is TCP_STATE_CLOSING
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
break
|
||||
otherwise
|
||||
//putc('?')
|
||||
wend
|
||||
fin
|
||||
if sir & $08
|
||||
//putc('T')
|
||||
//
|
||||
// Timeout on TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_OPEN
|
||||
wiz->channel_state = TCP_STATE_CLOSING
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
break
|
||||
is TCP_STATE_CONNECT
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
is TCP_STATE_CLOSING
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
break
|
||||
otherwise
|
||||
//putc('?')
|
||||
wend
|
||||
fin
|
||||
//if sir & $10
|
||||
//putc('W');putc('O');putc('K');puth(peekregw(wiz=>channel_regs+WIZ_SnTXWR));putln
|
||||
//
|
||||
// Write TCP socket OK
|
||||
//
|
||||
//fin
|
||||
break
|
||||
is WIZ_PROTO_UDP
|
||||
//putc('U');putb(sir)
|
||||
if sir & $04
|
||||
//putc('R')
|
||||
//
|
||||
// Receive UDP packet
|
||||
//
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
if rxwr + rxlen >= WIZ_RXSIZE
|
||||
//putc('!')
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
//putc('=');putip(rxpkt);putc(' ');puti(rxlen)
|
||||
//putc('/');puti(swab(rxpkt=>6))
|
||||
//putc(' ');puth(rxrr);putc(' ');puth(rxwr);putln
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(rxpkt,swab(rxpkt=>4),rxpkt+8,rxlen-8,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
fin
|
||||
break
|
||||
otherwise
|
||||
wend
|
||||
pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR
|
||||
ir = ir ^ (1 << i)
|
||||
break
|
||||
wend
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
if ir
|
||||
//
|
||||
// Clear IR for now
|
||||
//
|
||||
pokereg(WIZ_IR, ir)
|
||||
fin
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Set the local IP addresses
|
||||
//
|
||||
def setWizIP(newIP, newSubnet, newGateway)
|
||||
if newIP
|
||||
localip:0 = newIP=>0; localip:2 = newIP=>2
|
||||
pokeregs(WIZ_SIPR, newIP, IP4ADR_SIZE)
|
||||
fin
|
||||
if newSubnet
|
||||
subnet:0 = newSubnet=>0; subnet:2 = newSubnet=>2
|
||||
pokeregs(WIZ_SUBR, newSubnet, IP4ADR_SIZE)
|
||||
fin
|
||||
if newGateway
|
||||
gateway:0 = newGateway=>0; gateway:2 = newGateway=>2
|
||||
pokeregs(WIZ_GWR, newGateway, IP4ADR_SIZE)
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Get the interface hardware address
|
||||
//
|
||||
def getWizHA(ha)
|
||||
if ha
|
||||
ha=>0 = wizMAC:0; ha=>2 = wizMAC:2; ha=>4 = wizMAC:4
|
||||
fin
|
||||
return MAC_SIZE
|
||||
end
|
||||
//
|
||||
// Identify Uthernet II card and initialize
|
||||
//
|
||||
for slot = $F0 downto $90 step $10
|
||||
regdata = peekio(slot)
|
||||
if (regdata & $E4) == $00
|
||||
pokeio(slot, $03) // Try setting auto-increment indirect I/F
|
||||
if peekio(slot) == $03
|
||||
saveidx = peekiow(slot + 1)
|
||||
peekio(slot + 3) // Dummy read to data register should increment index
|
||||
if peekiow(slot + 1) == saveidx + 1
|
||||
//
|
||||
// Good chance this is it
|
||||
//
|
||||
pokeio(slot, $80) // RESET
|
||||
regidx = slot + 1
|
||||
regdata = slot + 3
|
||||
_pokedata.1 = regdata
|
||||
_peekdata.1 = regdata
|
||||
pokeio(slot, $03) // Auto-increment indirect I/F + enable ping
|
||||
//
|
||||
// The following looks redundant, but it sets up the peek/poke locations
|
||||
// for peekreg(s)/pokereg(s)
|
||||
//
|
||||
pokeiow(regidx, WIZ_MR)
|
||||
pokeio(regdata, $03) // Auto-increment indirect I/F + enable ping
|
||||
peekio(regdata)
|
||||
//
|
||||
// Initialize common registers
|
||||
//
|
||||
pokeregs(WIZ_SHAR, @wizMAC, 6) // MAC addr
|
||||
pokeregw(WIZ_RTR, 5000) // Timeout period to 500ms
|
||||
pokereg(WIZ_RMSR, $55) // 2K Rx memory/channel
|
||||
pokereg(WIZ_TMSR, $55) // 2K Tx memory/channel
|
||||
//
|
||||
// Fill channel structure
|
||||
//
|
||||
saveidx = @wizChannel
|
||||
for slot = 0 to 3
|
||||
saveidx=>channel_regs = WIZ_SREGS + (WIZ_SSIZE * slot)
|
||||
saveidx=>channel_txmem = WIZ_TXMEM + (WIZ_TXSIZE * slot)
|
||||
saveidx=>channel_rxmem = WIZ_RXMEM + (WIZ_RXSIZE * slot)
|
||||
saveidx = saveidx + t_channel
|
||||
next
|
||||
//
|
||||
// Fill in Net class
|
||||
//
|
||||
iNet:serviceIP = @wizServiceIP
|
||||
iNet:openUDP = @wizOpenUDP
|
||||
iNet:sendUDP = @wizSendUDP
|
||||
iNet:closeUDP = @wizCloseUDP
|
||||
iNet:listenTCP = @wizListenTCP
|
||||
iNet:connectTCP = @wizConnectTCP
|
||||
iNet:sendTCP = @wizSendTCP
|
||||
iNet:closeTCP = @wizCloseTCP
|
||||
iNet:setInterfaceIP = @setWizIP
|
||||
iNet:getInterfaceHA = @getWizHA
|
||||
return modkeep
|
||||
fin
|
||||
fin
|
||||
pokeio(slot, regdata) // Restore register
|
||||
fin
|
||||
next
|
||||
//
|
||||
// Not found
|
||||
//
|
||||
return -1
|
||||
done
|
@ -397,20 +397,20 @@ def peekreg(reg)
|
||||
return _peekio()
|
||||
end
|
||||
def pokeregs(reg, buf, len)
|
||||
word i
|
||||
|
||||
len = len - 1
|
||||
for i = 0 to len
|
||||
_pokeiow(reg + i)
|
||||
_pokeio(buf->[i])
|
||||
next
|
||||
_pokeiow(reg)
|
||||
return pokedata(buf, len)
|
||||
// word i
|
||||
// len = len - 1
|
||||
// for i = 0 to len
|
||||
// _pokeiow(reg + i)
|
||||
// _pokeio(buf->[i])
|
||||
// next
|
||||
end
|
||||
def peekregs(reg, buf, len)
|
||||
// There is an issue missing data on back-to-back reads
|
||||
_pokeiow(reg)
|
||||
return peekdata(buf, len)
|
||||
// There is an issue missing data on back-to-back reads
|
||||
// word i
|
||||
|
||||
// len = len - 1
|
||||
// for i = 0 to len
|
||||
// _pokeiow(reg + i)
|
||||
|
11
src/makefile
11
src/makefile
@ -10,6 +10,7 @@ SB = SB\#FF2000
|
||||
ROD = ROD\#FE1000
|
||||
SIEVE = SIEVE\#FE1000
|
||||
WIZNET = WIZNET\#FE1000
|
||||
UTHERNET2= UTHERNET2\#FE1000
|
||||
UTHERNET= UTHERNET\#FE1000
|
||||
ETHERIP = ETHERIP\#FE1000
|
||||
INET = INET\#FE1000
|
||||
@ -48,7 +49,7 @@ TXTTYPE = .TXT
|
||||
#SYSTYPE = \#FF2000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(FIBER) $(SB) $(MON) $(ROD) $(SIEVE) $(WIZNET) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(FIBER) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
|
||||
clean:
|
||||
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
||||
@ -129,14 +130,14 @@ $(SIEVE): samplesrc/sieve.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/sieve.pla > samplesrc/sieve.a
|
||||
acme --setpc 4094 -o $(SIEVE) samplesrc/sieve.a
|
||||
|
||||
$(WIZNET): libsrc/wiznet.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/wiznet.pla > libsrc/wiznet.a
|
||||
acme --setpc 4094 -o $(WIZNET) libsrc/wiznet.a
|
||||
|
||||
$(UTHERNET): libsrc/uthernet.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/uthernet.pla > libsrc/uthernet.a
|
||||
acme --setpc 4094 -o $(UTHERNET) libsrc/uthernet.a
|
||||
|
||||
$(UTHERNET2): libsrc/uthernet2.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/uthernet2.pla > libsrc/uthernet2.a
|
||||
acme --setpc 4094 -o $(UTHERNET2) libsrc/uthernet2.a
|
||||
|
||||
$(ETHERIP): libsrc/etherip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/etherip.pla > libsrc/etherip.a
|
||||
acme --setpc 4094 -o $(ETHERIP) libsrc/etherip.a
|
||||
|
Loading…
x
Reference in New Issue
Block a user