From 40b3f8194c2cf2d566801c671c187ae3723db6f6 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Mon, 2 Nov 2015 11:58:26 -0800 Subject: [PATCH] Working Uthernet2 driver --- HTTPD.PO | Bin 0 -> 143360 bytes src/libsrc/inet.pla | 2 +- src/libsrc/uthernet2.pla | 962 +++++++++++++++++++++++++++++++++++++++ src/libsrc/wiznet.pla | 18 +- src/makefile | 11 +- 5 files changed, 978 insertions(+), 15 deletions(-) create mode 100644 HTTPD.PO create mode 100644 src/libsrc/uthernet2.pla diff --git a/HTTPD.PO b/HTTPD.PO new file mode 100644 index 0000000000000000000000000000000000000000..315e107146cb33dbd59c137aec58e768afc301d0 GIT binary patch literal 143360 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%0AEZ-wCs5EFgXd$j+!5j$jVdAxbuM#vu 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 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