diff --git a/HTTPD.PO b/HTTPD.PO new file mode 100644 index 0000000..315e107 Binary files /dev/null and b/HTTPD.PO differ diff --git a/src/libsrc/inet.pla b/src/libsrc/inet.pla index 73aa6b2..b9ca313 100644 --- a/src/libsrc/inet.pla +++ b/src/libsrc/inet.pla @@ -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 diff --git a/src/libsrc/uthernet2.pla b/src/libsrc/uthernet2.pla new file mode 100644 index 0000000..2400f04 --- /dev/null +++ b/src/libsrc/uthernet2.pla @@ -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 diff --git a/src/libsrc/wiznet.pla b/src/libsrc/wiznet.pla index c24b611..8ef71ad 100644 --- a/src/libsrc/wiznet.pla +++ b/src/libsrc/wiznet.pla @@ -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) diff --git a/src/makefile b/src/makefile index 9b71f6c..2be09e3 100644 --- a/src/makefile +++ b/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