Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
994 lines (985 sloc) 23.6 KB
//
// Wiznet 5100 based ethernet card
//
// TCP/IP is built into hardware, so no dependencies on the software
// layers, like the Uthernet
//
include "inc/cmdsys.plh"
//
// 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
word setCallback
word setParam
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 regidx, regdata
word slot, 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)
word i
len = len - 1
for i = 0 to len
_pokeiow(reg + i)
_pokeio(buf->[i])
next
end
def peekregs(reg, buf, len)
// _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)
buf->[i] = _peekio()
next
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 putb(hexb)
return call($FDDA, hexb, 0, 0, 0)
end
def puth(hex)
return call($F941, hex >> 8, hex, 0, 0)
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
//
// Update notify callback
//
def wizSetCallback(wiz, callback)
if wiz->channel_proto == WIZ_PROTO_UDP or wiz->channel_proto == WIZ_PROTO_TCP
//
// Update callback on this port
//
wiz=>channel_recv_func = callback
return 0
fin
//
// Invalid port
//
return -1
end
//
// Update notify param
//
def wizSetParam(wiz, param)
if wiz->channel_proto == WIZ_PROTO_UDP or wiz->channel_proto == WIZ_PROTO_TCP
//
// Update param on this port
//
wiz=>channel_recv_parm = param
return 0
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 Wiznet card and initialize
//
for slot = $90 to $F0 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
iNet:setCallback = @wizSetCallback
iNet:setParam = @wizSetParam
return modkeep
fin
fin
pokeio(slot, regdata) // Restore register
fin
next
//
// Not found
//
return -1
done