diff --git a/drivers/Makefile b/drivers/Makefile index 60152c1..0daab44 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,46 +1,68 @@ -AS = ca65 -LD = ld65 -AFLAGS = - -%.o: %.c - $(CC) -c $(CFLAGS) $< - -%.o: %.s - $(AS) $(AFLAGS) $< - -# c64rrnet.lib : C64 with RR-NET or clone at $de0x -# c64wiznet.lib : C64 with Wiznet W5100 addressed at $df2x -# a2uther.lib : Apple ][ with Uthernet in slot #3 -# a2lancegs.lib : Apple ][ with LANceGS -# vic20rrnet.lib : VIC20 with RR-NET or clone at $980x +# c64rrnet.lib : C64 with RR-Net or clone (default base addr: $de0x) +# c64eth64.lib : C64 with ETH64 (default base addr: $de0x) +# a2uther.lib : Apple ][ with Uthernet (default slot: #3) +# a2lancegs.lib : Apple ][ with LANceGS (default slot: #3) +# a2uther2.lib : Apple ][ with Uthernet II (default slot: #3) +# vic20rrnet.lib : VIC20 with RR-Net or clone (default base addr: $980x) DRIVERS=\ c64rrnet.lib \ - c64wiznet.lib \ + c64eth64.lib \ a2uther.lib \ a2lancegs.lib \ + a2uther2.lib \ vic20rrnet.lib all: $(DRIVERS) -c64rrnet.lib: rr-net.o cs8900a.o c64zeropage.o c64print.o c64timer.o c64kernal.o c64input.o cbmcharconv.o +%.o: %.s + ca65 -D DYN_DRV=0 $< + +C64OBJS=\ + contiki.o \ + c64zeropage.o \ + c64print.o \ + c64timer.o \ + c64kernal.o \ + c64input.o \ + cbmcharconv.o + +A2OBJS=\ + contiki.o \ + a2zeropage.o \ + a2print.o \ + a2timer.o \ + a2kernal.o \ + a2input.o \ + a2charconv.o + +VIC20OBJS=\ + contiki.o \ + vic20zeropage.o \ + vic20print.o \ + vic20timer.o \ + vic20kernal.o \ + vic20input.o \ + cbmcharconv.o + +c64rrnet.lib: rr-net.o cs8900a.o $(C64OBJS) ar65 a $@ $^ -c64wiznet.lib: w5100.o c64zeropage.o c64print.o c64timer.o c64kernal.o c64input.o cbmcharconv.o +c64eth64.lib: eth64.o lan91c96.o $(C64OBJS) ar65 a $@ $^ -a2lancegs.lib: lan91c96.o a2zeropage.o a2print.o a2timer.o a2kernal.o a2input.o a2charconv.o +a2uther.lib: uthernet.o cs8900a.o $(A2OBJS) ar65 a $@ $^ -a2uther.lib: uthernet.o cs8900a.o a2zeropage.o a2print.o a2timer.o a2kernal.o a2input.o a2charconv.o +a2lancegs.lib: lancegs.o lan91c96.o $(A2OBJS) ar65 a $@ $^ -vic20rrnet.lib: vic20-rr-net.o cs8900a.o vic20zeropage.o vic20print.o vic20timer.o vic20kernal.o vic20input.o cbmcharconv.o +a2uther2.lib: uthernet2.o w5100.o $(A2OBJS) + ar65 a $@ $^ + +vic20rrnet.lib: vic20-rr-net.o cs8900a.o $(VIC20OBJS) ar65 a $@ $^ clean: -rm -f *.o -rm -f *.lib - -distclean: clean - -rm -f *~ diff --git a/drivers/contiki.s b/drivers/contiki.s new file mode 100644 index 0000000..227325a --- /dev/null +++ b/drivers/contiki.s @@ -0,0 +1,96 @@ +; Contiki driver wrapper + +.include "../inc/common.i" + +.export eth_init +.export eth_rx +.export eth_tx + +.import eth_inp +.import eth_inp_len +.import eth_outp +.import eth_outp_len + +.import eth_driver_io_base + +.import cfg_mac + +.import eth + +.struct driver + drvtype .byte 3 + apiver .byte + mac .byte 6 + bufaddr .addr + bufsize .word + init .byte 3 + poll .byte 3 + send .byte 3 + exit .byte 3 +.endstruct + + +.code + +; initialize the ethernet adaptor +; inputs: none +; outputs: carry flag is set if there was an error, clear otherwise +eth_init: + ldax #1518 + stax eth+driver::bufsize + ldax eth_driver_io_base + jsr eth+driver::init + ldx #5 +: lda eth+driver::mac,x + sta cfg_mac,x + dex + bpl :- + rts + +; receive a packet +; inputs: none +; outputs: +; if there was an error receiving the packet (or no packet was ready) then carry flag is set +; if packet was received correctly then carry flag is clear, +; eth_inp contains the received packet, +; and eth_inp_len contains the length of the packet +eth_rx: + ldax #eth_inp + stax eth+driver::bufaddr + jsr eth+driver::poll + stax eth_inp_len + rts + +; send a packet +; inputs: +; eth_outp: packet to send +; eth_outp_len: length of packet to send +; outputs: +; if there was an error sending the packet then carry flag is set +; otherwise carry flag is cleared +eth_tx: + ldax #eth_outp + stax eth+driver::bufaddr + ldax eth_outp_len + jmp eth+driver::send + + + +; -- LICENSE FOR contiki.s -- +; The contents of this file are subject to the Mozilla Public License +; Version 1.1 (the "License"); you may not use this file except in +; compliance with the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" +; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +; License for the specific language governing rights and limitations +; under the License. +; +; The Original Code is ip65. +; +; The Initial Developer of the Original Code is Jonno Downes, +; jonno@jamtronix.com. +; Portions created by the Initial Developer are Copyright (C) 2009 +; Jonno Downes. All Rights Reserved. +; -- LICENSE END -- diff --git a/drivers/cs8900a.s b/drivers/cs8900a.s index 9535fd2..9bc6487 100644 --- a/drivers/cs8900a.s +++ b/drivers/cs8900a.s @@ -1,282 +1,391 @@ -; Ethernet driver for CS8900A chip (as used in RR-NET and Uthernet adapters) ; -; Based on Doc Bacardi's tftp source - -.ifndef KPR_API_VERSION_NUMBER - .define EQU = - .include "../inc/kipper_constants.i" -.endif - -.include "../inc/common.i" -.include "cs8900a.i" - -.export eth_init -.export eth_rx -.export eth_tx - -.import eth_inp -.import eth_inp_len -.import eth_outp -.import eth_outp_len - -.importzp eth_dest -.importzp eth_src -.importzp eth_type -.importzp eth_data - -.import cs_init -.import cs_packet_page -.import cs_packet_data -.import cs_rxtx_data -.import cs_tx_cmd -.import cs_tx_len - -.import cfg_mac -.importzp eth_packet - -.import ip65_error - -.macro write_page page, value - lda #page/2 - ldx #value - jsr cs_write_page -.endmacro - - -.code - -; initialize the ethernet adaptor -; inputs: none -; outputs: carry flag is set if there was an error, clear otherwise -eth_init: - jsr cs_init - - lda #0 ; check magic signature - jsr cs_read_page - cpx #$0e - bne @notfound - cpy #$63 - bne @notfound - - lda #1 - jsr cs_read_page - cpx #0 - bne @notfound - ; y contains chip rev - - write_page pp_self_ctl, $0055 ; $0114, reset chip - - write_page pp_rx_ctl, $0d05 ; $0104, accept individual and broadcast packets - - lda #pp_ia/2 ; $0158, write mac address - ldx cfg_mac - ldy cfg_mac + 1 - jsr cs_write_page - - lda #pp_ia/2 + 1 - ldx cfg_mac + 2 - ldy cfg_mac + 3 - jsr cs_write_page - - lda #pp_ia/2 + 2 - ldx cfg_mac + 4 - ldy cfg_mac + 5 - jsr cs_write_page - - write_page pp_line_ctl, $00d3 ; $0112, enable rx and tx - clc - rts - -@notfound: - sec - rts - -; receive a packet -; inputs: none -; outputs: -; if there was an error receiving the packet (or no packet was ready) then carry flag is set -; if packet was received correctly then carry flag is clear, -; eth_inp contains the received packet, -; and eth_inp_len contains the length of the packet -eth_rx: - lda #$24 ; check rx status - sta cs_packet_page - lda #$01 - sta cs_packet_page + 1 - - lda cs_packet_data + 1 - and #$0d - bne :+ - sec ; no packet ready - rts - -: lda cs_rxtx_data + 1 ; ignore status - lda cs_rxtx_data - - lda cs_rxtx_data + 1 ; read packet length - sta eth_inp_len + 1 - tax ; save - lda cs_rxtx_data - sta eth_inp_len - - lda #eth_inp - sta eth_packet + 1 - - ldy #0 - cpx #0 ; < 256 bytes left? - beq @tail - -@get256: - lda cs_rxtx_data - sta (eth_packet),y - iny - lda cs_rxtx_data + 1 - sta (eth_packet),y - iny - bne @get256 - inc eth_packet + 1 - dex - bne @get256 - -@tail: - lda eth_inp_len ; bytes left / 2, round up - lsr - adc #0 - beq @done - tax - -@get: - lda cs_rxtx_data - sta (eth_packet),y - iny - lda cs_rxtx_data + 1 - sta (eth_packet),y - iny - dex - bne @get - -@done: - clc - rts - -; send a packet -; inputs: -; eth_outp: packet to send -; eth_outp_len: length of packet to send -; outputs: -; if there was an error sending the packet then carry flag is set -; otherwise carry flag is cleared -eth_tx: - lda #$c9 ; ask for buffer space - sta cs_tx_cmd - lda #0 - sta cs_tx_cmd + 1 - - lda eth_outp_len ; set length - sta cs_tx_len - lda eth_outp_len + 1 - sta cs_tx_len + 1 - cmp #6 - bmi :+ - lda #KPR_ERROR_INPUT_TOO_LARGE - sta ip65_error - sec ; oversized packet - rts - -: lda #pp_bus_status - sta cs_packet_page + 1 - -@waitspace: - lda cs_packet_data + 1 ; wait for space - ldx cs_packet_data - lsr - bcs @gotspace - jsr @done ; polling too fast doesn't work, delay added by David Schmidt - jmp @waitspace -@gotspace: - ldax #eth_outp ; send packet - stax eth_packet - - ldy #0 - ldx eth_outp_len + 1 - beq @tail - -@send256: - lda (eth_packet),y - sta cs_rxtx_data - iny - lda (eth_packet),y - sta cs_rxtx_data + 1 - iny - bne @send256 - inc eth_packet + 1 - dex - bne @send256 - -@tail: - ldx eth_outp_len - beq @done - -@send: - lda (eth_packet),y - sta cs_rxtx_data - dex - beq @done - iny - lda (eth_packet),y - sta cs_rxtx_data + 1 - iny - dex - bne @send - -@done: ; also used by timeout code above - clc - rts - -; read X/Y from page A * 2 -cs_read_page: - asl - sta cs_packet_page - lda #0 - rol - sta cs_packet_page + 1 - ldx cs_packet_data - ldy cs_packet_data + 1 - rts - -; write X/Y to page A * 2 -cs_write_page: - asl - sta cs_packet_page - lda #0 - rol - sta cs_packet_page + 1 - stx cs_packet_data - sty cs_packet_data + 1 - rts - - - -; -- LICENSE FOR cs8900a.s -- -; The contents of this file are subject to the Mozilla Public License -; Version 1.1 (the "License"); you may not use this file except in -; compliance with the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ +; Copyright (c) 2007, Adam Dunkels and Oliver Schmidt +; All rights reserved. ; -; Software distributed under the License is distributed on an "AS IS" -; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -; License for the specific language governing rights and limitations -; under the License. +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the Institute nor the names of its contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. ; -; The Original Code is ip65. +; THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. ; -; The Initial Developer of the Original Code is Per Olofsson, -; MagerValp@gmail.com. -; Portions created by the Initial Developer are Copyright (C) 2009 -; Per Olofsson. All Rights Reserved. -; -- LICENSE END -- +; This file is part of the Contiki operating system. +; +; Author: Adam Dunkels , Oliver Schmidt +; +;--------------------------------------------------------------------- + + .macpack module + module_header _cs8900a + + ; Driver signature + .byte $65, $74, $68 ; "eth" + .byte $01 ; Ethernet driver API version number + + ; Ethernet address +mac: .byte $00, $0E, $3A ; OUI of Cirrus Logic + .byte $11, $11, $11 + + ; Buffer attributes +bufaddr:.res 2 ; Address +bufsize:.res 2 ; Size + + ; Jump table. + jmp init + jmp poll + jmp send + jmp exit + +;--------------------------------------------------------------------- + + .if DYN_DRV + + .zeropage +sp: .res 2 ; Stack pointer (Do not trash !) +reg: .res 2 ; Address of rxtxreg +ptr: .res 2 ; Indirect addressing pointer +len: .res 2 ; Frame length +cnt: .res 2 ; Frame length counter + + .else + + .include "zeropage.inc" +reg := ptr1 ; Address of rxtxreg +ptr := ptr2 ; Indirect addressing pointer +len := ptr3 ; Frame length +cnt := ptr4 ; Frame length counter + + .endif + +;--------------------------------------------------------------------- + + .rodata + +fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03 + .byte fixup05-fixup04, fixup06-fixup05, fixup07-fixup06 + .byte fixup08-fixup07, fixup09-fixup08, fixup10-fixup09 + .byte fixup11-fixup10, fixup12-fixup11, fixup13-fixup12 + .byte fixup14-fixup13, fixup15-fixup14, fixup16-fixup15 + .byte fixup17-fixup16, fixup18-fixup17, fixup19-fixup18 + .byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21 + .byte fixup23-fixup22, fixup24-fixup23, fixup25-fixup24 + .byte fixup26-fixup25 + +fixups = * - fixup + +;--------------------------------------------------------------------- + +rxtxreg := $FF00 ; High byte patched at runtime +txcmd := $FF04 ; High byte patched at runtime +txlen := $FF06 ; High byte patched at runtime +isq := $FF08 ; High byte patched at runtime +packetpp := $FF0A ; High byte patched at runtime +ppdata := $FF0C ; High byte patched at runtime + + .data + +;--------------------------------------------------------------------- + +init: + ; Save address of rxtxreg + sta reg + stx reg+1 + + ; Start with first fixup location + lda #<(fixup01+1) + ldx #>(fixup01+1) + sta ptr + stx ptr+1 + ldx #$FF + ldy #$00 + + ; Fixup address at location +: lda reg + eor (ptr),y ; Use XOR to support C64 RR-Net + sta (ptr),y + iny + lda reg+1 + sta (ptr),y + dey + + ; Advance to next fixup location + inx + cpx #fixups + bcs :+ + lda ptr + clc + adc fixup,x + sta ptr + bcc :- + inc ptr+1 + bcs :- ; Always + + ; Activate C64 RR clockport in order to operate RR-Net + ; - RR config register overlays CS8900A ISQ register + ; - No need to distinguish as ISQ access doesn't hurt +: +fixup01:lda isq+1 + ora #$01 ; Set clockport bit +fixup02:sta isq+1 + + ; Check EISA registration number of Crystal Semiconductor + ; PACKETPP = $0000, PPDATA == $630E ? + lda #$00 + tax + jsr packetpp_ax + lda #$63^$0E +fixup03:eor ppdata +fixup04:eor ppdata+1 + beq :+ + sec + rts + + ; Initiate a chip-wide reset + ; PACKETPP = $0114, PPDATA = $0040 +: lda #$14 + jsr packetpp_a1 + ldy #$40 +fixup05:sty ppdata +: jsr packetpp_a1 +fixup06:ldy ppdata + and #$40 + bne :- + + ; Accept valid unicast + broadcast frames + ; PACKETPP = $0104, PPDATA = $0D05 + lda #$04 + jsr packetpp_a1 + lda #$05 + ldx #$0D + jsr ppdata_ax + + ; Set MAC address + ; PACKETPP = $0158, PPDATA = MAC[0], MAC[1] + ; PACKETPP = $015A, PPDATA = MAC[2], MAC[3] + ; PACKETPP = $015C, PPDATA = MAC[4], MAC[5] + ldy #$58 +: tya + jsr packetpp_a1 + lda mac-$58,y + ldx mac-$58+1,y + jsr ppdata_ax + iny + iny + cpy #$58+6 + bcc :- + + ; Turn on transmission and reception of frames + ; PACKETPP = $0112, PPDATA = $00D3 + lda #$12 + jsr packetpp_a1 + lda #$D3 + ldx #$00 + jsr ppdata_ax + txa + clc + rts + +;--------------------------------------------------------------------- + +poll: + ; Check receiver event register to see if there + ; are any valid unicast frames avaliable + ; PACKETPP = $0124, PPDATA & $0D00 ? + lda #$24 + jsr packetpp_a1 +fixup07:lda ppdata+1 + and #$0D + beq :+ + + ; Process the incoming frame + ; -------------------------- + + ; Read receiver event and discard it + ; RXTXREG +fixup08:ldx rxtxreg+1 +fixup09:lda rxtxreg + + ; Read frame length + ; cnt = len = RXTXREG +fixup10:ldx rxtxreg+1 +fixup11:lda rxtxreg + sta len + stx len+1 + sta cnt + stx cnt+1 + + ; Adjust odd frame length + jsr adjustcnt + + ; Is bufsize < cnt ? + lda bufsize + cmp cnt + lda bufsize+1 + sbc cnt+1 + bcs :++ + + ; Yes, skip frame + jsr skipframe + + ; No frame ready + lda #$00 +: tax + sec + rts + + ; Read bytes into buffer +: jsr adjustptr +: +fixup12:lda rxtxreg + sta (ptr),y + iny +fixup13:lda rxtxreg+1 + sta (ptr),y + iny + bne :- + inc ptr+1 + dex + bpl :- + + ; Return frame length + lda len + ldx len+1 + clc + rts + +;--------------------------------------------------------------------- + +send: + ; Save frame length + sta cnt + stx cnt+1 + + ; Transmit command + lda #$C9 + ldx #$00 +fixup14:sta txcmd +fixup15:stx txcmd+1 + lda cnt + ldx cnt+1 +fixup16:sta txlen +fixup17:stx txlen+1 + + ; Adjust odd frame length + jsr adjustcnt + + ; 8 retries + ldy #$08 + + ; Check for avaliable buffer space + ; PACKETPP = $0138, PPDATA & $0100 ? +: lda #$38 + jsr packetpp_a1 +fixup18:lda ppdata+1 + and #$01 + bne :+ + + ; No space avaliable, skip a received frame + jsr skipframe + + ; And try again + dey + bne :- + sec + rts + + ; Send the frame + ; -------------- + + ; Write bytes from buffer +: jsr adjustptr +: lda (ptr),y +fixup19:sta rxtxreg + iny + lda (ptr),y +fixup20:sta rxtxreg+1 + iny + bne :- + inc ptr+1 + dex + bpl :- + clc + rts + +;--------------------------------------------------------------------- + +exit: + rts + +;--------------------------------------------------------------------- + +packetpp_a1: + ldx #$01 +packetpp_ax: +fixup21:sta packetpp +fixup22:stx packetpp+1 + rts + +;--------------------------------------------------------------------- + +ppdata_ax: +fixup23:sta ppdata +fixup24:stx ppdata+1 + rts + +;--------------------------------------------------------------------- + +skipframe: + ; PACKETPP = $0102, PPDATA = PPDATA | $0040 + lda #$02 + jsr packetpp_a1 +fixup25:lda ppdata + ora #$40 +fixup26:sta ppdata + rts + +;--------------------------------------------------------------------- + +adjustcnt: + lsr + bcc :+ + inc cnt + bne :+ + inc cnt+1 +: rts + +;--------------------------------------------------------------------- + +adjustptr: + lda cnt + ldx cnt+1 + eor #$FF ; Two's complement part 1 + tay + iny ; Two's complement part 2 + sty reg + sec + lda bufaddr + sbc reg + sta ptr + lda bufaddr+1 + sbc #$00 + sta ptr+1 + rts + +;--------------------------------------------------------------------- diff --git a/drivers/cs8900a.i b/drivers/eth64.s similarity index 76% rename from drivers/cs8900a.i rename to drivers/eth64.s index 507884c..e4f5f36 100644 --- a/drivers/cs8900a.i +++ b/drivers/eth64.s @@ -1,14 +1,26 @@ -; originally from Per Olofsson's IP65 library - http://www.paradroid.net/ip65 +; ETH64 driver -pp_rx_ctl = $0104 -pp_line_ctl = $0112 -pp_self_ctl = $0114 -pp_bus_status = $0138 -pp_ia = $0158 +.import _lan91c96 + +.export eth = _lan91c96 +.export eth_driver_name +.export eth_driver_io_base + + +.rodata + +eth_driver_name: + .byte "ETH64",0 + + +.data + +eth_driver_io_base: + .word $de00 -; -- LICENSE FOR cs8900a.i -- +; -- LICENSE FOR eth64.s -- ; The contents of this file are subject to the Mozilla Public License ; Version 1.1 (the "License"); you may not use this file except in ; compliance with the License. You may obtain a copy of the License at diff --git a/drivers/lan91c96.s b/drivers/lan91c96.s index 34e6ca2..52a43f9 100644 --- a/drivers/lan91c96.s +++ b/drivers/lan91c96.s @@ -1,458 +1,427 @@ -; Ethernet driver for SMC LAN91C96 chip ; +; Copyright (c) 2003-2007, Adam Dunkels, Josef Soucek and Oliver Schmidt +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the Institute nor the names of its contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Adam Dunkels , Josef Soucek , +; Oliver Schmidt +; +;--------------------------------------------------------------------- -.ifndef KPR_API_VERSION_NUMBER - .define EQU = - .include "../inc/kipper_constants.i" -.endif + .macpack module + module_header _lan91c96 -.include "../inc/common.i" + ; Driver signature + .byte $65, $74, $68 ; "eth" + .byte $01 ; Ethernet driver API version number -.export eth_init -.export eth_rx -.export eth_tx -.export eth_driver_name -.export eth_driver_io_base -.import eth_inp -.import eth_inp_len -.import eth_outp -.import eth_outp_len + ; Ethernet address +mac: .byte $00, $80, $0F ; OUI of Standard Microsystems + .byte $11, $11, $11 -.import cfg_mac -.importzp eth_packet + ; Buffer attributes +bufaddr:.res 2 ; Address +bufsize:.res 2 ; Size -; LANceGS hardware addresses -ethbsr := $c00E ; Bank select register R/W (2B) + ; Jump table. + jmp init + jmp poll + jmp send + jmp exit + +;--------------------------------------------------------------------- + + .if DYN_DRV + + .zeropage +sp: .res 2 ; Stack pointer (Do not trash !) +reg: .res 2 ; Address of register base +ptr: .res 2 ; Indirect addressing pointer +len: .res 2 ; Frame length + + .else + + .include "zeropage.inc" +reg := ptr1 ; Address of register base +ptr := ptr2 ; Indirect addressing pointer +len := ptr3 ; Frame length + + .endif + +;--------------------------------------------------------------------- + + .rodata + +fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03 + .byte fixup05-fixup04, fixup06-fixup05, fixup07-fixup06 + .byte fixup08-fixup07, fixup09-fixup08, fixup10-fixup09 + .byte fixup11-fixup10, fixup12-fixup11, fixup13-fixup12 + .byte fixup14-fixup13, fixup15-fixup14, fixup16-fixup15 + .byte fixup17-fixup16, fixup18-fixup17, fixup19-fixup18 + .byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21 + .byte fixup23-fixup22, fixup24-fixup23, fixup25-fixup24 + .byte fixup26-fixup25, fixup27-fixup26, fixup28-fixup27 + .byte fixup29-fixup28, fixup30-fixup29, fixup31-fixup30 + .byte fixup32-fixup31, fixup33-fixup32, fixup34-fixup33 + .byte fixup35-fixup34, fixup36-fixup35, fixup37-fixup36 + .byte fixup38-fixup37, fixup39-fixup38, fixup40-fixup39 + +fixups = * - fixup + +;--------------------------------------------------------------------- + +ethbsr := $FF0E ; Bank select register R/W (2B) ; Register bank 0 -ethtcr := $c000 ; Transmission control register R/W (2B) -ethephsr := $c002 ; EPH status register R/O (2B) -ethrcr := $c004 ; Receive control register R/W (2B) -ethecr := $c006 ; Counter register R/O (2B) -ethmir := $c008 ; Memory information register R/O (2B) -ethmcr := $c00A ; Memory Config. reg. +0 R/W +1 R/O (2B) +ethtcr := $FF00 ; Transmition control register R/W (2B) +ethephsr := $FF02 ; EPH status register R/O (2B) +ethrcr := $FF04 ; Receive control register R/W (2B) +ethecr := $FF06 ; Counter register R/O (2B) +ethmir := $FF08 ; Memory information register R/O (2B) +ethmcr := $FF0A ; Memory Config. reg. +0 R/W +1 R/O (2B) ; Register bank 1 -ethcr := $c000 ; Configuration register R/W (2B) -ethbar := $c002 ; Base address register R/W (2B) -ethiar := $c004 ; Individual address register R/W (6B) -ethgpr := $c00A ; General address register R/W (2B) -ethctr := $c00C ; Control register R/W (2B) +ethcr := $FF00 ; Configuration register R/W (2B) +ethbar := $FF02 ; Base address register R/W (2B) +ethiar := $FF04 ; Individual address register R/W (6B) +ethgpr := $FF0A ; General address register R/W (2B) +ethctr := $FF0C ; Control register R/W (2B) ; Register bank 2 -ethmmucr := $c000 ; MMU command register W/O (1B) -ethautotx := $c001 ; AUTO TX start register R/W (1B) -ethpnr := $c002 ; Packet number register R/W (1B) -etharr := $c003 ; Allocation result register R/O (1B) -ethfifo := $c004 ; FIFO ports register R/O (2B) -ethptr := $c006 ; Pointer register R/W (2B) -ethdata := $c008 ; Data register R/W (4B) -ethist := $c00C ; Interrupt status register R/O (1B) -ethack := $c00C ; Interrupt acknowledge register W/O (1B) -ethmsk := $c00D ; Interrupt mask register R/W (1B) +ethmmucr := $FF00 ; MMU command register W/O (1B) +ethautotx := $FF01 ; AUTO TX start register R/W (1B) +ethpnr := $FF02 ; Packet number register R/W (1B) +etharr := $FF03 ; Allocation result register R/O (1B) +ethfifo := $FF04 ; FIFO ports register R/O (2B) +ethptr := $FF06 ; Pointer register R/W (2B) +ethdata := $FF08 ; Data register R/W (4B) +ethist := $FF0C ; Interrupt status register R/O (1B) +ethack := $FF0C ; Interrupt acknowledge register W/O (1B) +ethmsk := $FF0D ; Interrupt mask register R/W (1B) ; Register bank 3 -ethmt := $c000 ; Multicast table R/W (8B) -ethmgmt := $c008 ; Management interface R/W (2B) -ethrev := $c00A ; Revision register R/W (2B) -ethercv := $c00C ; Early RCV register R/W (2B) +ethmt := $FF00 ; Multicast table R/W (8B) +ethmgmt := $FF08 ; Management interface R/W (2B) +ethrev := $FF0A ; Revision register R/W (2B) +ethercv := $FF0C ; Early RCV register R/W (2B) + .data -.data +;--------------------------------------------------------------------- -; initialize the ethernet adaptor -; inputs: none -; outputs: carry flag is set if there was an error, clear otherwise -eth_init: - jsr lan_self_modify - lda #$01 -fixlan00: - sta ethbsr ; Select register bank 1 -fixlan01: - lda ethcr ; Read first four bytes - $31, $20, $67, $18 - cmp #$31 - bne lanerror -fixlan03: - lda ethbar - cmp #$67 - bne lanerror -fixlan04: - lda ethbar+1 - cmp #$18 - bne lanerror - ; we have the magic signature +init: + ; Save address of register base + sta reg + stx reg+1 - ; Reset ETH card - lda #$00 ; Bank 0 -fixlan05: - sta ethbsr - lda #%10000000 ; Software reset -fixlan06: - sta ethrcr+1 + ; Start with first fixup location + lda #<(fixup01+1) + ldx #>(fixup01+1) + sta ptr + stx ptr+1 + ldx #$FF + ldy #$00 - ldy #$00 -fixlan07: - sty ethrcr -fixlan08: - sty ethrcr+1 + ; Fixup address at location +: lda reg + ora (ptr),y + sta (ptr),y + iny + lda reg+1 + sta (ptr),y + dey - ; Delay -: cmp ($FF,x) ; 6 cycles - cmp ($FF,x) ; 6 cycles - iny ; 2 cycles - bne :- ; 3 cycles - ; 17 * 256 = 4352 -> 4,4 ms + ; Advance to next fixup location + inx + cpx #fixups + bcs :+ + lda ptr + clc + adc fixup,x + sta ptr + bcc :- + inc ptr+1 + bcs :- ; Always - ; Enable transmit and receive - lda #%10000001 ; Enable transmit TXENA, PAD_EN - ldx #%00000011 ; Enable receive, strip CRC ??? -fixlan09: - sta ethtcr -fixlan10: - stx ethrcr+1 + ; Reset ETH card +: lda #$00 ; Bank 0 +fixup01:sta ethbsr - lda #$01 ; Bank 1 -fixlan11: - sta ethbsr + lda #%10000000 ; Software reset +fixup02:sta ethrcr+1 -fixlan12: - lda ethcr+1 - ora #%00010000 ; No wait (IOCHRDY) -fixlan13: - sta ethcr+1 + ldy #$00 +fixup03:sty ethrcr +fixup04:sty ethrcr+1 - lda #%00001001 ; Auto release -fixlan14: - sta ethctr+1 + ; Delay +: cmp ($FF,x) ; 6 cycles + cmp ($FF,x) ; 6 cycles + iny ; 2 cycles + bne :- ; 3 cycles + ; 17 * 256 = 4352 -> 4,4 ms - ; Set MAC address - lda cfg_mac - ldx cfg_mac + 1 -fixlan15: - sta ethiar -fixlan16: - stx ethiar + 1 - lda cfg_mac + 2 - ldx cfg_mac + 3 -fixlan17: - sta ethiar + 2 -fixlan18: - stx ethiar + 3 - lda cfg_mac + 4 - ldx cfg_mac + 5 -fixlan19: - sta ethiar + 4 -fixlan20: - stx ethiar + 5 + ; Enable transmit and receive + lda #%10000001 ; Enable transmit TXENA, PAD_EN + ldx #%00000011 ; Enable receive, strip CRC ??? +fixup05:sta ethtcr +fixup06:stx ethrcr+1 - ; Set interrupt mask - lda #$02 ; Bank 2 -fixlan21: - sta ethbsr + lda #$01 ; Bank 1 +fixup07:sta ethbsr - lda #%00000000 ; No interrupts -fixlan22: - sta ethmsk - clc - rts + ; Check ISA mode base address register for reset values + lda #$18^67 ; I/O base $300 + ROM $CC000 +fixup08:eor ethbar +fixup09:eor ethbar+1 + beq :+ + sec + rts -lanerror: - sec - rts +: +fixup10:lda ethcr+1 + ora #%00010000 ; No wait (IOCHRDY) +fixup11:sta ethcr+1 -; receive a packet -; inputs: none -; outputs: -; if there was an error receiving the packet (or no packet was ready) then carry flag is set -; if packet was received correctly then carry flag is clear, -; eth_inp contains the received packet, -; and eth_inp_len contains the length of the packet -eth_rx: -fixlan38: - lda ethist - and #%00000001 ; Check receive interrupt - bne :+ - sec ; No packet available - rts + lda #%00001001 ; Auto release +fixup12:sta ethctr+1 -: lda #$00 - ldx #%11100000 ; Receive, Auto Increment, Read -fixlan39: - sta ethptr -fixlan40: - stx ethptr + 1 + ; Set MAC address + ldy #$00 +: lda mac,y +fixup13:sta ethiar,y + iny + cpy #$06 + bcc :- - ; Last word contains 'last data byte' and $60 or 'fill byte' and $40 -fixlan41: - lda ethdata ; Status word -fixlan42: - lda ethdata ; Only need high byte + ; Set interrupt mask + lda #$02 ; Bank 2 +fixup14:sta ethbsr - ; Move ODDFRM bit into carry: - ; - Even packet length -> carry clear -> subtract 6 bytes - ; - Odd packet length -> carry set -> subtract 5 bytes - lsr - lsr - lsr - lsr - lsr + lda #%00000000 ; No interrupts +fixup15:sta ethmsk + tax + clc + rts - ; The packet contains 3 extra words -fixlan43: - lda ethdata ; Total number of bytes - sbc #$05 ; Actually 5 or 6 depending on carry - sta eth_inp_len -fixlan44: - lda ethdata - sbc #$00 - sta eth_inp_len+1 +;--------------------------------------------------------------------- - ; Read bytes into buffer - lda #eth_inp - sta eth_packet - stx eth_packet+1 - ldx eth_inp_len+1 - ldy #$00 -lanread: -fixlan46: - lda ethdata - sta (eth_packet),y - iny - bne :+ - inc eth_packet+1 -: cpy eth_inp_len - bne lanread - dex - bpl lanread +poll: +fixup16:lda ethist + and #%00000001 ; RCV INT + beq :+ - ; Remove and release RX packet from the FIFO - lda #%10000000 -fixlan47: - sta ethmmucr + ; Process the incoming packet + ; --------------------------- + + lda #$00 + ldx #%11100000 ; RCV, AUTO INCR., READ +fixup17:sta ethptr +fixup18:stx ethptr+1 - clc - rts + ; Last word contains 'last data byte' and $60 or 'fill byte' and $40 +fixup19:lda ethdata ; Status word +fixup20:lda ethdata ; Need high byte only -; send a packet -; inputs: -; eth_outp: packet to send -; eth_outp_len: length of packet to send -; outputs: -; if there was an error sending the packet then carry flag is set -; otherwise carry flag is cleared -eth_tx: - lda eth_outp_len + 1 - ora #%00100000 -fixlan23: - sta ethmmucr ; Allocate memory for transmission -fixlan24: - lda ethist - and #%00001000 ; Allocation interrupt - bne :+ - sec - rts ; Not able to allocate; bail + ; Move ODDFRM bit into carry: + ; - Even packet length -> carry clear -> subtract 6 bytes + ; - Odd packet length -> carry set -> subtract 5 bytes + lsr + lsr + lsr + lsr + lsr -: lda #%00001000 -fixlan25: - sta ethack ; Acknowledge interrupt + ; The packet contains 3 extra words +fixup21:lda ethdata ; Total number of bytes + sbc #$05 ; Actually 5 or 6 depending on carry + sta len +fixup22:lda ethdata + sbc #$00 + sta len+1 -fixlan26: - lda etharr -fixlan27: - sta ethpnr ; Set packet number + ; Is bufsize < len ? + lda bufsize + cmp len + lda bufsize+1 + sbc len+1 + bcs :++ - lda #$00 - ldx #%01000000 ; Auto increment -fixlan28: - sta ethptr -fixlan29: - stx ethptr + 1 + ; Yes, skip packet + ; Remove and release RX packet from the FIFO + lda #%10000000 +fixup23:sta ethmmucr - lda #$00 ; Status written by CSMA -fixlan30: - sta ethdata -fixlan31: - sta ethdata + ; No packet available + lda #$00 +: tax + sec + rts - lda eth_outp_len - eor #$01 - lsr - lda eth_outp_len - adc #$05 ; Actually will be 5 or 6 depending on carry -fixlan32: - sta ethdata - lda eth_outp_len + 1 - adc #$00 -fixlan33: - sta ethdata + ; Read bytes into buffer +: jsr adjustptr +: +fixup24:lda ethdata + sta (ptr),y + iny + bne :- + inc ptr+1 + dex + bpl :- - lda #eth_outp - sta eth_packet - stx eth_packet + 1 - ldx eth_outp_len + 1 - ldy #$00 -lanwrite: - lda (eth_packet),y -fixlan34: - sta ethdata - iny - bne :+ - inc eth_packet + 1 -: cpy eth_outp_len - bne lanwrite - dex - bpl lanwrite + ; Remove and release RX packet from the FIFO + lda #%10000000 +fixup25:sta ethmmucr - lda eth_outp_len ; Odd packet length? - lsr - bcc :+ + ; Return packet length + lda len + ldx len+1 + clc + rts - lda #%001000000 ; Yes, Odd - bne fixlan36 ; Always +;--------------------------------------------------------------------- -: lda #$00 ; No -fixlan35: - sta ethdata ; Fill byte -fixlan36: - sta ethdata ; Control byte - lda #%11000000 ; Enqueue packet - transmit -fixlan37: - sta ethmmucr +send: + ; Save packet length + sta len + stx len+1 - clc - rts + ; Allocate memory for TX + txa + ora #%00100000 +fixup26:sta ethmmucr -; -; lan_self_modify - make all entry points variable so we can move the -; LANceGS card around in the Apple -; -lan_self_modify: - lda #$C0 ; FIXME - hardcoded to slot 4 - clc ; We'll be adding later, so clear carry - ; Make the accumulator contain slot number plus $80 - ; i.e. Slot 1 = $90 - ; i.e. Slot 2 = $A0 - ; i.e. Slot 3 = $B0 - ; i.e. Slot 4 = $C0 - ; i.e. Slot 5 = $D0 - ; i.e. Slot 6 = $E0 - ; i.e. Slot 7 = $F0 -; $C0s0: Save off all ethtcr, ethcr, ethmmucr, and ethmt mods - sta fixlan01 + 1 - sta fixlan09 + 1 - sta fixlan23 + 1 - sta fixlan37 + 1 -; sta fixlan45 + 1 ; Removed - sta fixlan47 + 1 + ; 8 retries + ldy #$08 -; $C0s1: Save off all ethtcr+1, ethcr+1, ethmmucr+1, and ethmt+1 mods - adc #$01 -; sta fixlan02 + 1 ; Removed - sta fixlan12 + 1 - sta fixlan13 + 1 + ; Wait for allocation ready +: +fixup27:lda ethist + and #%00001000 ; ALLOC INT + bne :+ -; $C0s2: Save off all ethephsr, ethbar, and ethpnr mods - adc #$01 - sta fixlan03 + 1 - sta fixlan27 + 1 + ; Shouldn't we do something here to actively free memory, + ; maybe removing and releasing an RX packet from the FIFO ??? -; $C0s3: Save off all ethephsr+1, ethbar+1, ethpnr+1, and etharr mods - adc #$01 - sta fixlan04 + 1 - sta fixlan26 + 1 + ; And try again + dey + bne :- + sec + rts -; $C0s4: Save off all ethrcr, ethiar, and ethfifo mods - adc #$01 - sta fixlan07 + 1 - sta fixlan15 + 1 + ; Acknowledge interrupt, is it necessary ??? +: lda #%00001000 +fixup28:sta ethack -; $C0s5: Save off all ethrcr+1, ethiar+1, and ethfifo+1 mods - adc #$01 - sta fixlan06 + 1 - sta fixlan08 + 1 - sta fixlan10 + 1 - sta fixlan16 + 1 + ; Set packet address +fixup29:lda etharr +fixup30:sta ethpnr -; $C0s6: Save off all ethecr, ethptr, and ethiar+2 mods - adc #$01 - sta fixlan17 + 1 - sta fixlan28 + 1 - sta fixlan39 + 1 + lda #$00 + ldx #%01000000 ; AUTO INCR. +fixup31:sta ethptr +fixup32:stx ethptr+1 -; $C0s7: Save off all ethecr+1, ethptr+1, and ethiar+3 mods - adc #$01 - sta fixlan18 + 1 - sta fixlan29 + 1 - sta fixlan40 + 1 + ; Status written by CSMA + lda #$00 +fixup33:sta ethdata +fixup34:sta ethdata -; $C0s8: Save off all ethmir, ethdata, ethmgmt, and ethiar+4 mods - adc #$01 - sta fixlan19 + 1 - sta fixlan30 + 1 - sta fixlan31 + 1 - sta fixlan32 + 1 - sta fixlan33 + 1 - sta fixlan34 + 1 - sta fixlan35 + 1 - sta fixlan36 + 1 - sta fixlan41 + 1 - sta fixlan42 + 1 - sta fixlan43 + 1 - sta fixlan44 + 1 - sta fixlan46 + 1 + ; Check packet length parity: + ; - Even packet length -> carry set -> add 6 bytes + ; - Odd packet length -> carry clear -> add 5 bytes + lda len + eor #$01 + lsr + + ; The packet contains 3 extra words + lda len + adc #$05 ; Actually 5 or 6 depending on carry +fixup35:sta ethdata + lda len+1 + adc #$00 +fixup36:sta ethdata -; $C0s9: Save off all ethmir+1, ethdata+1, ethmgmt+1, and ethiar+5 mods - adc #$01 - sta fixlan20 + 1 + ; Send the packet + ; --------------- -; $C0sA: Save off all ethmcr, ethgpr, and ethrev mods -; $C0sB: Save off all ethmcr+1, ethgpr+1, and ethrev+1 mods - ; None + ; Write bytes from buffer + jsr adjustptr +: lda (ptr),y +fixup37:sta ethdata + iny + bne :- + inc ptr+1 + dex + bpl :- -; $C0sC: Save off all ethctr, ethist, ethack, and ethercv mods - adc #$03 ; Because there were no a or b mods - sta fixlan24 + 1 - sta fixlan25 + 1 - sta fixlan38 + 1 + ; Odd packet length ? + lda len + lsr + bcc :+ -; $C0sD: Save off all ethmsk, ethctr+1 mods - adc #$01 - sta fixlan14 + 1 - sta fixlan22 + 1 + ; Yes + lda #%00100000 ; ODD + bne :++ ; Always -; $C0sE: Save off all ethbsr mods - adc #$01 - sta fixlan00 + 1 - sta fixlan05 + 1 - sta fixlan11 + 1 - sta fixlan21 + 1 - rts + ; No +: lda #$00 +fixup38:sta ethdata ; Fill byte +: +fixup39:sta ethdata ; Control byte + ; Add packet to FIFO + lda #%11000000 ; ENQUEUE PACKET - transmit packet +fixup40:sta ethmmucr + clc + rts -.rodata +;--------------------------------------------------------------------- -eth_driver_name: - .asciiz "LANceGS (91C96)" +exit: + rts -eth_driver_io_base = fixlan01+1 +;--------------------------------------------------------------------- +adjustptr: + lda len + ldx len+1 + eor #$FF ; Two's complement part 1 + tay + iny ; Two's complement part 2 + sty reg + sec + lda bufaddr + sbc reg + sta ptr + lda bufaddr+1 + sbc #$00 + sta ptr+1 + rts - -; The contents of this file are subject to the Mozilla Public License -; Version 1.1 (the "License"); you may not use this file except in -; compliance with the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ -; -; Software distributed under the License is distributed on an "AS IS" -; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -; License for the specific language governing rights and limitations -; under the License. -; -; The Original Code is ip65. -; -; The Initial Developer of the Original Code is David Schmidt -; Portions created by the Initial Developer is Copyright (C) 2011 -; All Rights Reserved. -; -- LICENSE END -- +;--------------------------------------------------------------------- diff --git a/drivers/lancegs.s b/drivers/lancegs.s new file mode 100644 index 0000000..05cf36b --- /dev/null +++ b/drivers/lancegs.s @@ -0,0 +1,40 @@ +; LANceGS driver + +.import _lan91c96 + +.export eth = _lan91c96 +.export eth_driver_name +.export eth_driver_io_base + + +.rodata + +eth_driver_name: + .byte "LANceGS",0 + + +.data + +eth_driver_io_base: + .word $c0b0 + + + +; -- LICENSE FOR lancegs.s -- +; The contents of this file are subject to the Mozilla Public License +; Version 1.1 (the "License"); you may not use this file except in +; compliance with the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" +; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +; License for the specific language governing rights and limitations +; under the License. +; +; The Original Code is ip65. +; +; The Initial Developer of the Original Code is Jonno Downes, +; jonno@jamtronix.com. +; Portions created by the Initial Developer are Copyright (C) 2009 +; Jonno Downes. All Rights Reserved. +; -- LICENSE END -- diff --git a/drivers/rr-net.s b/drivers/rr-net.s index a54f0b3..3a927c4 100644 --- a/drivers/rr-net.s +++ b/drivers/rr-net.s @@ -1,47 +1,22 @@ ; RR-Net driver -.export cs_init +.import _cs8900a -.export cs_packet_page -.export cs_packet_data -.export cs_rxtx_data -.export cs_tx_cmd -.export cs_tx_len +.export eth = _cs8900a .export eth_driver_name .export eth_driver_io_base -IO_BASE = $de00 -rr_ctl = IO_BASE+$01 ; address of 'control' port on Retro-Replay -cs_packet_page = IO_BASE+$02 ; address of 'packet page' port on RR-Net -cs_packet_data = IO_BASE+$04 ; address of 'packet data' port on RR-Net -cs_rxtx_data = IO_BASE+$08 ; address of 'recieve/transmit data' port on RR-Net -cs_tx_cmd = IO_BASE+$0c ; address of 'transmit command' port on RR-Net -cs_tx_len = IO_BASE+$0e ; address of 'transmission length' port on RR-Net - - -.code - -; initialise Retro Replay so we can access the network adapter -; inputs: none -; outputs: none -cs_init: - lda rr_ctl - ora #1 - sta rr_ctl - rts - .rodata eth_driver_name: -.if IO_BASE=$de00 - .byte "RR-NET",0 -.else - .byte "64NIC+",0 -.endif + .byte "RR-Net",0 + + +.data eth_driver_io_base: - .word IO_BASE + .word $de08 diff --git a/drivers/uthernet.s b/drivers/uthernet.s index a43ba49..da11be0 100644 --- a/drivers/uthernet.s +++ b/drivers/uthernet.s @@ -1,35 +1,22 @@ -; uthernet driver -; currently hardcoded to use slot 3 addresses only +; Uthernet driver -.export cs_init +.import _cs8900a -.export cs_packet_page -.export cs_packet_data -.export cs_rxtx_data -.export cs_tx_cmd -.export cs_tx_len +.export eth = _cs8900a .export eth_driver_name .export eth_driver_io_base -cs_rxtx_data = $c0b0 ; address of 'recieve/transmit data' port on Uthernet -cs_tx_cmd = $c0b4 ; address of 'transmit command' port on Uthernet -cs_tx_len = $c0b6 ; address of 'transmission length' port on Uthernet -cs_packet_page = $c0ba ; address of 'packet page' port on Uthernet -cs_packet_data = $c0bc ; address of 'packet data' port on Uthernet - - -.code - -cs_init: - rts - .rodata eth_driver_name: - .byte "UTHERNET",0 + .byte "Uthernet",0 + + +.data + eth_driver_io_base: - .word cs_rxtx_data + .word $c0b0 diff --git a/drivers/uthernet2.s b/drivers/uthernet2.s new file mode 100644 index 0000000..21cac91 --- /dev/null +++ b/drivers/uthernet2.s @@ -0,0 +1,40 @@ +; Uthernet II driver + +.import _w5100 + +.export eth = _w5100 +.export eth_driver_name +.export eth_driver_io_base + + +.rodata + +eth_driver_name: + .byte "Uthernet II",0 + + +.data + +eth_driver_io_base: + .word $c0b4 + + + +; -- LICENSE FOR uthernet2.s -- +; The contents of this file are subject to the Mozilla Public License +; Version 1.1 (the "License"); you may not use this file except in +; compliance with the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" +; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +; License for the specific language governing rights and limitations +; under the License. +; +; The Original Code is ip65. +; +; The Initial Developer of the Original Code is Jonno Downes, +; jonno@jamtronix.com. +; Portions created by the Initial Developer are Copyright (C) 2009 +; Jonno Downes. All Rights Reserved. +; -- LICENSE END -- diff --git a/drivers/vic20-rr-net.s b/drivers/vic20-rr-net.s index 7ecea83..149ef58 100644 --- a/drivers/vic20-rr-net.s +++ b/drivers/vic20-rr-net.s @@ -1,41 +1,22 @@ ; RR-Net driver, as seen on a VIC-20 (i.e. using a Masquerade adapter) -.export cs_init +.import _cs8900a -.export cs_packet_page -.export cs_packet_data -.export cs_rxtx_data -.export cs_tx_cmd -.export cs_tx_len +.export eth = _cs8900a .export eth_driver_name .export eth_driver_io_base -rr_ctl = $9801 ; address of 'control' port on Retro-Replay -cs_packet_page = $9802 ; address of 'packet page' port on RR-Net -cs_packet_data = $9804 ; address of 'packet data' port on RR-Net -cs_rxtx_data = $9808 ; address of 'recieve/transmit data' port on RR-Net -cs_tx_cmd = $980c ; address of 'transmit command' port on RR-Net -cs_tx_len = $980e ; address of 'transmission length' port on RR-Net - - -.code - -; initialise Retro Replay so we can access the network adapter -; inputs: none -; outputs: none -cs_init: - lda rr_ctl - ora #1 - sta rr_ctl - rts - .rodata eth_driver_name: - .asciiz "VIC20 RR-NET" + .asciiz "VIC20 RR-Net" + + +.data + eth_driver_io_base: - .word rr_ctl-1 + .word $9808 diff --git a/drivers/w5100.i b/drivers/w5100.i deleted file mode 100644 index 61d03a6..0000000 --- a/drivers/w5100.i +++ /dev/null @@ -1,226 +0,0 @@ -; Common Registers -W5100_MR = $0000 ; Mode Register - -W5100_GAR0 = $0001 ; Gateway Address Byte 0 -W5100_GAR1 = $0002 ; Gateway Address Byte 1 -W5100_GAR2 = $0003 ; Gateway Address Byte 2 -W5100_GAR3 = $0004 ; Gateway Address Byte 3 - -W5100_SUBR0 = $0005 ; Subnet Mask Address 0 -W5100_SUBR1 = $0006 ; Subnet Mask Address 1 -W5100_SUBR2 = $0007 ; Subnet Mask Address 2 -W5100_SUBR3 = $0008 ; Subnet Mask Address 3 - -W5100_SHAR0 = $0009 ; Local MAC Address 0 -W5100_SHAR1 = $000A ; Local MAC Address 1 -W5100_SHAR2 = $000B ; Local MAC Address 2 -W5100_SHAR3 = $000C ; Local MAC Address 3 -W5100_SHAR4 = $000D ; Local MAC Address 4 -W5100_SHAR5 = $000E ; Local MAC Address 5 - -W5100_SIPR0 = $000F ; Source IP Address 0 -W5100_SIPR1 = $0010 ; Source IP Address 0 -W5100_SIPR2 = $0011 ; Source IP Address 0 -W5100_SIPR3 = $0012 ; Source IP Address 0 - -W5100_IR = $0015 ; Interrupt -W5100_IMR = $0016 ; Interrupt Mask - -W5100_RTR0 = $0017 ; Retry Time High Byte -W5100_RTR1 = $0018 ; Retry Time Low Byte - -W5100_RCR = $0019 ; Retry Count - -W5100_RMSR = $001A ; RX Memory Size (per socket) -W5100_TMSR = $001B ; TX Memory Size (per socket) - -W5100_PATR0 = $001C ; PPPoE Auth Type High -W5100_PART1 = $001D ; PPPoE Auth Type Low - -W5100_PTIMER = $0028 ; PPP LCP Request Timer -W5100_PMAGIC = $0029 ; PPP LCP Magic Number - -W5100_UIPR0 = $002A ; Unreachable IP Address 0 -W5100_UIPR1 = $002B ; Unreachable IP Address 1 -W5100_UIPR2 = $002C ; Unreachable IP Address 2 -W5100_UIPR3 = $002D ; Unreachable IP Address 3 - -W5100_UPORT0 = $002E ; Unreachable Port High -W5100_UPORT1 = $002F ; Unreachable Port Low - -; Socket Registers -W5100_S0_BASE = $0400 ; Base for socket 0 -W5100_S0_MR = $0400 ; Socket 0 Mode -W5100_S0_CR = $0401 ; Socket 0 Command -W5100_S0_IR = $0402 ; Socket 0 Interrupt -W5100_S0_SR = $0403 ; Socket 0 Status -W5100_S0_PORT0 = $0404 ; Socket 0 Source Port High -W5100_S0_PORT1 = $0405 ; Socket 0 Source Port Low -W5100_S0_DHAR0 = $0406 ; Socket 0 Dest Mac 0 -W5100_S0_DHAR1 = $0407 ; Socket 0 Dest Mac 1 -W5100_S0_DHAR2 = $0408 ; Socket 0 Dest Mac 2 -W5100_S0_DHAR3 = $0409 ; Socket 0 Dest Mac 3 -W5100_S0_DHAR4 = $040A ; Socket 0 Dest Mac 4 -W5100_S0_DHAR5 = $040B ; Socket 0 Dest Mac 5 -W5100_S0_DIPR0 = $040C ; Socket 0 Dest IP 0 -W5100_S0_DIPR1 = $040D ; Socket 0 Dest IP 1 -W5100_S0_DIPR2 = $040E ; Socket 0 Dest IP 2 -W5100_S0_DIPR3 = $040F ; Socket 0 Dest IP 3 -W5100_S0_DPORT0 = $0410 ; Socket 0 Dest Port High -W5100_S0_DPORT1 = $0411 ; Socket 0 Dest Port Low -W5100_S0_MSSR0 = $0412 ; Socket 0 Max Segment High -W5100_S0_MSSR1 = $0413 ; Socket 0 Max Segment Low -W5100_S0_PROTO = $0414 ; Socket 0 Protocol (Raw Mode) -W5100_S0_TOS = $0415 ; Socket 0 IP TOS -W5100_S0_TTL = $0416 ; Socket 0 IP TTL -W5100_S0_TX_FSR0 = $0420 ; Socket 0 TX Free Size High -W5100_S0_TX_FSR1 = $0421 ; Socket 0 TX Free Size Low -W5100_S0_TX_RD0 = $0422 ; Socket 0 TX Read Pointer High -W5100_S0_TX_RD1 = $0423 ; Socket 0 TX Read Pointer Low -W5100_S0_TX_WR0 = $0424 ; Socket 0 TX Write Pointer High -W5100_S0_TX_WR1 = $0425 ; Socket 0 TX Write Pointer Low -W5100_S0_RX_RSR0 = $0426 ; Socket 0 RX Received Size High -W5100_S0_RX_RSR1 = $0427 ; Socket 0 RX Received Size Low -W5100_S0_RX_RD0 = $0428 ; Socket 0 RX Read Pointer High -W5100_S0_RX_RD1 = $0429 ; Socket 0 RX Read Pointer Low - -W5100_S1_BASE = $0500 ; Base for socket 1 -W5100_S1_MR = $0500 ; Socket 1 Mode -W5100_S1_CR = $0501 ; Socket 1 Command -W5100_S1_IR = $0502 ; Socket 1 Interrupt -W5100_S1_SR = $0503 ; Socket 1 Status -W5100_S1_PORT0 = $0504 ; Socket 1 Source Port High -W5100_S1_PORT1 = $0505 ; Socket 1 Source Port Low -W5100_S1_DHAR0 = $0506 ; Socket 1 Dest Mac 0 -W5100_S1_DHAR1 = $0507 ; Socket 1 Dest Mac 1 -W5100_S1_DHAR2 = $0508 ; Socket 1 Dest Mac 2 -W5100_S1_DHAR3 = $0509 ; Socket 1 Dest Mac 3 -W5100_S1_DHAR4 = $050A ; Socket 1 Dest Mac 4 -W5100_S1_DHAR5 = $050B ; Socket 1 Dest Mac 5 -W5100_S1_DIPR0 = $050C ; Socket 1 Dest IP 0 -W5100_S1_DIPR1 = $050D ; Socket 1 Dest IP 1 -W5100_S1_DIPR2 = $050E ; Socket 1 Dest IP 2 -W5100_S1_DIPR3 = $050F ; Socket 1 Dest IP 3 -W5100_S1_DPORT0 = $0510 ; Socket 1 Dest Port High -W5100_S1_DPORT1 = $0511 ; Socket 1 Dest Port Low -W5100_S1_MSSR0 = $0512 ; Socket 1 Max Segment High -W5100_S1_MSSR1 = $0513 ; Socket 1 Max Segment Low -W5100_S1_PROTO = $0514 ; Socket 1 Protocol (Raw Mode) -W5100_S1_TOS = $0515 ; Socket 1 IP TOS -W5100_S1_TTL = $0516 ; Socket 1 IP TTL -W5100_S1_TX_FSR0 = $0520 ; Socket 1 TX Free Size High -W5100_S1_TX_FSR1 = $0521 ; Socket 1 TX Free Size Low -W5100_S1_TX_RD0 = $0522 ; Socket 1 TX Read Pointer High -W5100_S1_TX_RD1 = $0523 ; Socket 1 TX Read Pointer Low -W5100_S1_TX_WR0 = $0524 ; Socket 1 TX Write Pointer High -W5100_S1_TX_WR1 = $0525 ; Socket 1 TX Write Pointer Low -W5100_S1_RX_RSR0 = $0526 ; Socket 1 RX Received Size High -W5100_S1_RX_RSR1 = $0527 ; Socket 1 RX Received Size Low -W5100_S1_RX_RD0 = $0528 ; Socket 1 RX Read Pointer High -W5100_S1_RX_RD1 = $0529 ; Socket 1 RX Read Pointer Low - -W5100_S2_BASE = $0600 ; Base for socket 2 -W5100_S2_MR = $0600 ; Socket 2 Mode -W5100_S2_CR = $0601 ; Socket 2 Command -W5100_S2_IR = $0602 ; Socket 2 Interrupt -W5100_S2_SR = $0603 ; Socket 2 Status -W5100_S2_PORT0 = $0604 ; Socket 2 Source Port High -W5100_S2_PORT1 = $0605 ; Socket 2 Source Port Low -W5100_S2_DHAR0 = $0606 ; Socket 2 Dest Mac 0 -W5100_S2_DHAR1 = $0607 ; Socket 2 Dest Mac 1 -W5100_S2_DHAR2 = $0608 ; Socket 2 Dest Mac 2 -W5100_S2_DHAR3 = $0609 ; Socket 2 Dest Mac 3 -W5100_S2_DHAR4 = $060A ; Socket 2 Dest Mac 4 -W5100_S2_DHAR5 = $060B ; Socket 2 Dest Mac 5 -W5100_S2_DIPR0 = $060C ; Socket 2 Dest IP 0 -W5100_S2_DIPR1 = $060D ; Socket 2 Dest IP 1 -W5100_S2_DIPR2 = $060E ; Socket 2 Dest IP 2 -W5100_S2_DIPR3 = $060F ; Socket 2 Dest IP 3 -W5100_S2_DPORT0 = $0610 ; Socket 2 Dest Port High -W5100_S2_DPORT1 = $0611 ; Socket 2 Dest Port Low -W5100_S2_MSSR0 = $0612 ; Socket 2 Max Segment High -W5100_S2_MSSR1 = $0613 ; Socket 2 Max Segment Low -W5100_S2_PROTO = $0614 ; Socket 2 Protocol (Raw Mode) -W5100_S2_TOS = $0615 ; Socket 2 IP TOS -W5100_S2_TTL = $0616 ; Socket 2 IP TTL -W5100_S2_TX_FSR0 = $0620 ; Socket 2 TX Free Size High -W5100_S2_TX_FSR1 = $0621 ; Socket 2 TX Free Size Low -W5100_S2_TX_RD0 = $0622 ; Socket 2 TX Read Pointer High -W5100_S2_TX_RD1 = $0623 ; Socket 2 TX Read Pointer Low -W5100_S2_TX_WR0 = $0624 ; Socket 2 TX Write Pointer High -W5100_S2_TX_WR1 = $0625 ; Socket 2 TX Write Pointer Low -W5100_S2_RX_RSR0 = $0626 ; Socket 2 RX Received Size High -W5100_S2_RX_RSR1 = $0627 ; Socket 2 RX Received Size Low -W5100_S2_RX_RD0 = $0628 ; Socket 2 RX Read Pointer High -W5100_S2_RX_RD1 = $0629 ; Socket 2 RX Read Pointer Low - -W5100_S3_BASE = $0700 ; Base for socket 3 -W5100_S3_MR = $0700 ; Socket 3 Mode -W5100_S3_CR = $0701 ; Socket 3 Command -W5100_S3_IR = $0702 ; Socket 3 Interrupt -W5100_S3_SR = $0703 ; Socket 3 Status -W5100_S3_PORT0 = $0704 ; Socket 3 Source Port High -W5100_S3_PORT1 = $0705 ; Socket 3 Source Port Low -W5100_S3_DHAR0 = $0706 ; Socket 3 Dest Mac 0 -W5100_S3_DHAR1 = $0707 ; Socket 3 Dest Mac 1 -W5100_S3_DHAR2 = $0708 ; Socket 3 Dest Mac 2 -W5100_S3_DHAR3 = $0709 ; Socket 3 Dest Mac 3 -W5100_S3_DHAR4 = $070A ; Socket 3 Dest Mac 4 -W5100_S3_DHAR5 = $070B ; Socket 3 Dest Mac 5 -W5100_S3_DIPR0 = $070C ; Socket 3 Dest IP 0 -W5100_S3_DIPR1 = $070D ; Socket 3 Dest IP 1 -W5100_S3_DIPR2 = $070E ; Socket 3 Dest IP 2 -W5100_S3_DIPR3 = $070F ; Socket 3 Dest IP 3 -W5100_S3_DPORT0 = $0710 ; Socket 3 Dest Port High -W5100_S3_DPORT1 = $0711 ; Socket 3 Dest Port Low -W5100_S3_MSSR0 = $0712 ; Socket 3 Max Segment High -W5100_S3_MSSR1 = $0713 ; Socket 3 Max Segment Low -W5100_S3_PROTO = $0714 ; Socket 3 Protocol (Raw Mode) -W5100_S3_TOS = $0715 ; Socket 3 IP TOS -W5100_S3_TTL = $0716 ; Socket 3 IP TTL -W5100_S3_TX_FSR0 = $0720 ; Socket 3 TX Free Size High -W5100_S3_TX_FSR1 = $0721 ; Socket 3 TX Free Size Low -W5100_S3_TX_RD0 = $0722 ; Socket 3 TX Read Pointer High -W5100_S3_TX_RD1 = $0723 ; Socket 3 TX Read Pointer Low -W5100_S3_TX_WR0 = $0724 ; Socket 3 TX Write Pointer High -W5100_S3_TX_WR1 = $0725 ; Socket 3 TX Write Pointer Low -W5100_S3_RX_RSR0 = $0726 ; Socket 3 RX Received Size High -W5100_S3_RX_RSR1 = $0727 ; Socket 3 RX Received Size Low -W5100_S3_RX_RD0 = $0728 ; Socket 3 RX Read Pointer High -W5100_S3_RX_RD1 = $0729 ; Socket 3 RX Read Pointer Low - -; Commands -W5100_CMD_OPEN = $01 -W5100_CMD_LISTEN = $02 -W5100_CMD_CONNECT = $04 -W5100_CMD_DISCONNECT = $08 -W5100_CMD_CLOSE = $10 -W5100_CMD_SEND = $20 -W5100_CMD_SEND_MAC = $21 -W5100_CMD_SEND_KEEP = $22 -W5100_CMD_RECV = $40 - -; Modes -W5100_MODE_CLOSED = $00 -W5100_MODE_TCP = $01 -W5100_MODE_UDP = $02 -W5100_MODE_IP_RAW = $03 -W5100_MODE_MAC_RAW = $04 -W5100_MODE_PPPOE = $05 - -; Status -W5100_STATUS_SOCK_CLOSED = $00 -W5100_STATUS_SOCK_INIT = $13 -W5100_STATUS_SOCK_LISTEN = $14 -W5100_STATUS_SOCK_SYNSENT = $15 -W5100_STATUS_SOCK_SYNRECV = $16 -W5100_STATUS_SOCK_ESTABLISHED = $17 -W5100_STATUS_SOCK_FIN_WAIT = $18 -W5100_STATUS_SOCK_CLOSING = $1A -W5100_STATUS_SOCK_TIME_WAIT = $1B -W5100_STATUS_SOCK_CLOSE_WAIT = $1C -W5100_STATUS_SOCK_LAST_ACK = $1D -W5100_STATUS_SOCK_UDP = $22 -W5100_STATUS_SOCK_IPRAW = $32 -W5100_STATUS_SOCK_MACRAW = $42 -W5100_STATUS_SOCK_PPPOE = $5F diff --git a/drivers/w5100.s b/drivers/w5100.s index 4db0782..f200a31 100644 --- a/drivers/w5100.s +++ b/drivers/w5100.s @@ -1,987 +1,511 @@ -; Ethernet driver for W5100 W5100 chip - -.ifndef KPR_API_VERSION_NUMBER - .define EQU = - .include "../inc/kipper_constants.i" -.endif - -.include "../inc/common.i" - -.include "w5100.i" - -WIZNET_BASE = $DE04 - -WIZNET_MODE_REG = WIZNET_BASE -WIZNET_ADDR_HI = WIZNET_BASE+1 -WIZNET_ADDR_LO = WIZNET_BASE+2 -WIZNET_DATA_REG = WIZNET_BASE+3 - -; DEBUG = 1 -.export eth_init -.export eth_rx -.export eth_tx -.export eth_driver_name -.export eth_driver_io_base -.import eth_inp -.import eth_inp_len -.import eth_outp -.import eth_outp_len - -.import timer_init -.import timer_read - -.import arp_init -.import ip_init - -.importzp eth_dest -.importzp eth_src -.importzp eth_type -.importzp eth_data -.importzp copy_src -.importzp copy_dest - -.export w5100_ip65_init -.export w5100_read_register -.export w5100_select_register - -.export w5100_write_register -.export w5100_set_ip_config -.export tcp_connect -.export tcp_connect_ip -.export tcp_callback -.export tcp_send_data_len -.export tcp_send_string -.export tcp_send -.export tcp_send_keep_alive -.export tcp_close -.export tcp_state - -.export tcp_connect_remote_port -.export tcp_remote_ip -.export tcp_listen - -.export tcp_inbound_data_ptr -.export tcp_inbound_data_length - -.import cfg_mac -.import cfg_ip -.import cfg_netmask -.import cfg_gateway - -.import ip65_error -.import ip65_process -.import check_for_abort_key - - -.code - -; initialize the ethernet adaptor -; inputs: none -; outputs: carry flag is set if there was an error, clear otherwise -; this implementation uses a default address for the w5100, and can be -; called as a 'generic' eth driver init function -eth_init: - lda $de01 - ora #1 ; turn on clockport - sta $de01 - - lda #$80 ; reset - sta WIZNET_MODE_REG - lda WIZNET_MODE_REG - bne @error ; writing a byte to the MODE register with bit 7 set should reset. - ; after a reset, mode register is zero - ; therefore, if there is a real W5100 at the specified address, - ; we should be able to write a $80 and read back a $00 - lda #$13 ; set indirect mode, with autoinc, no auto PING - sta WIZNET_MODE_REG - lda WIZNET_MODE_REG - cmp #$13 - bne @error ; make sure if we write to mode register without bit 7 set, - ; the value persists. - lda #$00 - sta WIZNET_ADDR_HI - lda #$16 - sta WIZNET_ADDR_LO - - ldx #$00 ; start writing to reg $0016 - Interrupt Mask Register -@loop: - lda w5100_config_data,x - sta WIZNET_DATA_REG - inx - cpx #$06 - bne @loop - - lda #$09 - sta WIZNET_ADDR_LO - ldx #$00 ; start writing to reg $0009 - MAC address - -@mac_loop: - lda cfg_mac,x - sta WIZNET_DATA_REG - inx - cpx #$06 - bne @mac_loop - - ; set up socket 0 for MAC RAW mode - - ldax #W5100_RMSR ; rx memory size (each socket) - stx WIZNET_ADDR_HI - sta WIZNET_ADDR_LO - - lda #$0A ; sockets 0 & 1 4KB each, other sockets 0KB - ; if this is changed, change the mask in eth_rx as well! - sta WIZNET_DATA_REG - - ldax #W5100_TMSR ; rx memory size (each socket) - stx WIZNET_ADDR_HI - sta WIZNET_ADDR_LO - - lda #$0A ; sockets 0 & 1 4KB each, other sockets 0KB - ; if this is changed, change the mask in eth_tx as well! - sta WIZNET_DATA_REG - - ldax #W5100_S0_MR - stx WIZNET_ADDR_HI - sta WIZNET_ADDR_LO - lda #W5100_MODE_MAC_RAW - sta WIZNET_DATA_REG - - ; open socket 0 - jsr w5100_write_register - ldax #W5100_S0_CR - stx WIZNET_ADDR_HI - sta WIZNET_ADDR_LO - lda #W5100_CMD_OPEN - sta WIZNET_DATA_REG - - lda #tcp_cxn_state_closed - sta tcp_state - clc - rts - -@error: - sec - rts - -; initialize the ip65 stack for the w5100 ethernet adaptor -; inputs: none -; outputs: carry flag is set if there was an error, clear otherwise -w5100_ip65_init: - jsr eth_init - - bcc @ok - lda #KPR_ERROR_DEVICE_FAILURE - sta ip65_error - rts -@ok: - jsr timer_init ; initialize timer - jsr arp_init ; initialize arp - jsr ip_init ; initialize ip, icmp, udp, and tcp - clc - rts - -; receive a packet -; inputs: none -; outputs: -; if there was an error receiving the packet (or no packet was ready) then carry flag is set -; if packet was received correctly then carry flag is clear, -; eth_inp contains the received packet, -; and eth_inp_len contains the length of the packet -eth_rx: - ; eth_rx will get called in the main polling loop - ; we shoe horn a check for data on the TCP socket here - ; if we do get TCP data, we will call the TCP callback routine - ; but we hide all of this from the ip65 stack proper. - lda tcp_state - beq @no_tcp - - jsr tcp_rx - bcc @no_tcp ; if we didn't get any TCP traffic, go check for a raw ethernet packet - ; eth_inp and eth_inp_len are not valid, so leave carry flag set to indicate no ethernet frame data - rts - -@no_tcp: - ldax #W5100_S0_RX_RSR0 - jsr w5100_read_register - sta eth_inp_len+1 - ldax #W5100_S0_RX_RSR1 - jsr w5100_read_register - sta eth_inp_len - bne @got_data - lda eth_inp_len+1 - bne @got_data - sec - rts -@got_data: - lda #$8D ; opcode for STA - sta next_eth_packet_byte - ldax #eth_inp - stax copy_dest - - lda #2 - sta byte_ctr_lo - lda #0 - sta byte_ctr_hi - - ; read the 2 byte frame length - jsr @get_current_rx_rd - jsr @mask_and_adjust_rx_read - - ldax rx_rd_ptr - jsr w5100_read_register - sta eth_inp_len+1 ; high byte of frame length - jsr @inc_rx_rd_ptr - ldax rx_rd_ptr - jsr w5100_read_register - sta eth_inp_len ; lo byte of frame length - - ; now copy the rest of the frame to the eth_inp buffer - ; we keep our own copy of RX_RD_PTR in sync, rather than read WIZNET_ADDR registers - ; because of issue where reads to WIZNET_ADDR can cause the autoinc ptr to advance erroneously - ; when WizNet cart used in a cartridge expander - ldy #0 -@get_next_byte: - inc rx_rd_ptr - bne :+ - inc rx_rd_ptr+1 - lda rx_rd_ptr+1 - and #$0F - clc - adc #$60 - sta rx_rd_ptr+1 - sta WIZNET_ADDR_HI -: lda WIZNET_DATA_REG - sta (copy_dest),y - iny - bne :+ - inc copy_dest+1 -: inc byte_ctr_lo - bne :+ - inc byte_ctr_hi -: lda byte_ctr_lo - cmp eth_inp_len - bne @get_next_byte - lda byte_ctr_hi - cmp eth_inp_len+1 - bne @get_next_byte - - ; update the RX RD pointer past the frame we just read - jsr @get_current_rx_rd - clc - lda rx_rd_ptr - adc eth_inp_len - sta rx_rd_ptr - lda rx_rd_ptr+1 - adc eth_inp_len+1 - tay - ldax #W5100_S0_RX_RD0 - jsr w5100_write_register - ldy rx_rd_ptr - - ldax #W5100_S0_RX_RD1 - jsr w5100_write_register - ldax #W5100_S0_CR - ldy #W5100_CMD_RECV - jsr w5100_write_register - - ; now adjust the input length to remove the 2 byte header length - sec - lda eth_inp_len - sbc #2 - sta eth_inp_len - bcs :+ - dec eth_inp_len -: clc - rts - -@inc_rx_rd_ptr: - inc rx_rd_ptr - bne :+ - inc rx_rd_ptr+1 -@mask_and_adjust_rx_read: - lda rx_rd_ptr+1 - and #$0F - clc - adc #$60 - sta rx_rd_ptr+1 -: rts - -@get_current_rx_rd: - ldax #W5100_S0_RX_RD0 - jsr w5100_read_register - sta rx_rd_ptr+1 - ldax #W5100_S0_RX_RD1 - jsr w5100_read_register - sta rx_rd_ptr - rts - -; send a packet -; inputs: -; eth_outp: packet to send -; eth_outp_len: length of packet to send -; outputs: -; if there was an error sending the packet then carry flag is set -; otherwise carry flag is cleared -eth_tx: - lda #$AD ; opcode for LDA - sta next_eth_packet_byte - ldax #eth_outp - sta eth_ptr_lo - stx eth_ptr_hi - lda #0 - sta byte_ctr_lo - sta byte_ctr_hi - - jsr @get_current_tx_wr - jmp @calculate_tx_wr_ptr -@send_next_byte: - jsr next_eth_packet_byte - tay - ldax tx_wr_ptr - jsr w5100_write_register - - inc byte_ctr_lo - bne :+ - inc byte_ctr_hi -: inc tx_wr_ptr - bne :+ - inc tx_wr_ptr+1 -@calculate_tx_wr_ptr: - lda tx_wr_ptr+1 - and #$0F - clc - adc #$40 - sta tx_wr_ptr+1 -: lda byte_ctr_lo - cmp eth_outp_len - bne @send_next_byte - lda byte_ctr_hi - cmp eth_outp_len+1 - bne @send_next_byte - - ; all bytes copied, now adjust the tx write ptr and SEND - jsr @get_current_tx_wr - clc - lda tx_wr_ptr - adc eth_outp_len - sta tx_wr_ptr - lda tx_wr_ptr+1 - adc eth_outp_len+1 - tay - ldax #W5100_S0_TX_WR0 - jsr w5100_write_register - ldy tx_wr_ptr - ldax #W5100_S0_TX_WR1 - jsr w5100_write_register - ldax #W5100_S0_CR - ldy #W5100_CMD_SEND - jsr w5100_write_register - clc - rts - -@get_current_tx_wr: - ldax #W5100_S0_TX_WR0 - jsr w5100_read_register - sta tx_wr_ptr+1 - ldax #W5100_S0_TX_WR1 - jsr w5100_read_register - sta tx_wr_ptr - rts - -advance_eth_ptr: - inc eth_ptr_lo - bne :+ - inc eth_ptr_hi -: rts - -; read one of the W5100 registers -; inputs: AX = register number to read -; outputs: A = value of nominated register -; y is overwritten -w5100_read_register: - jsr w5100_select_register - lda WIZNET_DATA_REG - rts - -; write to one of the W5100 registers -; inputs: AX = register number to write -; Y = value to write to register -; outputs: none -w5100_write_register: - jsr w5100_select_register - tya - sta WIZNET_DATA_REG - rts - -; listen for an inbound tcp connection -; this is a 'blocking' call, i.e. it will not return until a connection has been made -; inputs: -; AX: destination port (2 bytes) -; tcp_callback: vector to call when data arrives on this connection -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_listen: - stax tcp_local_port - jsr setup_tcp_socket - ldax #W5100_S1_CR - ldy #W5100_CMD_LISTEN - jsr w5100_write_register - - ; now wait for the status to change to 'established' -@listen_loop: - ; inc $d020 - jsr ip65_process - jsr check_for_abort_key - bcc @no_abort - lda #KPR_ERROR_ABORTED_BY_USER - sta ip65_error - sec - rts -@no_abort: - ldax #W5100_S1_SR - jsr w5100_read_register - cmp #W5100_STATUS_SOCK_ESTABLISHED - bne @listen_loop - - lda #tcp_cxn_state_established - sta tcp_state - - ; copy the remote IP address & port number - ldax #W5100_S1_DIPR0 - jsr w5100_select_register - ldx #0 -@ip_loop: - lda WIZNET_DATA_REG - sta tcp_remote_ip,x - inx - cpx #$04 - bne @ip_loop - - ldax #W5100_S1_DPORT0 - jsr w5100_select_register - lda WIZNET_DATA_REG - sta tcp_connect_remote_port+1 - lda WIZNET_DATA_REG - sta tcp_connect_remote_port - clc - rts - -; make outbound tcp connection -; inputs: -; tcp_connect_ip: destination ip address (4 bytes) -; AX: destination port (2 bytes) -; tcp_callback: vector to call when data arrives on this connection -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_connect: - stax tcp_remote_port - jsr timer_read ; get a pseudo random value - sta tcp_local_port+1 - inc tcp_local_port - - jsr setup_tcp_socket - - ; set the destination IP address - ldax #W5100_S1_DIPR0 - jsr w5100_select_register - ldx #0 -@remote_ip_loop: - lda tcp_connect_ip,x - sta WIZNET_DATA_REG - inx - cpx #$04 - bne @remote_ip_loop - ldx #0 - - ; W5100 register address is now W5100_S1_DPORT0, so set the destination port - lda tcp_remote_port+1 - sta WIZNET_DATA_REG - lda tcp_remote_port - sta WIZNET_DATA_REG - - ldax #W5100_S1_CR - ldy #W5100_CMD_CONNECT - jsr w5100_write_register - - ; now wait for the status to change to 'established' -@connect_loop: - ldax #W5100_S1_SR - jsr w5100_read_register - cmp #W5100_STATUS_SOCK_CLOSED - beq @error - cmp #W5100_STATUS_SOCK_ESTABLISHED - beq @ok - - jsr check_for_abort_key - bcc @connect_loop - lda #KPR_ERROR_ABORTED_BY_USER - jmp @set_error_and_exit - -@ok: - lda #tcp_cxn_state_established - sta tcp_state - clc - rts - -@error: - lda #KPR_ERROR_CONNECTION_CLOSED -@set_error_and_exit: - sta ip65_error - sec - rts - -; send a string over the current tcp connection -; inputs: -; tcp connection should already be opened -; AX: pointer to buffer - data up to (but not including) -; the first nul byte will be sent. max of 255 bytes will be sent. -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_send_string: - stax tcp_send_data_ptr - stax copy_src - lda #0 - tay - sta tcp_send_data_len - sta tcp_send_data_len+1 - lda (copy_src),y - bne @find_end_of_string - rts ; if the string is empty, don't send anything! -@find_end_of_string: - lda (copy_src),y - beq @done - inc tcp_send_data_len - iny - bne @find_end_of_string -@done: - ldax tcp_send_data_ptr - ; now we can fall through into tcp_send - -; send tcp data -; inputs: -; tcp connection should already be opened -; tcp_send_data_len: length of data to send (exclusive of any headers) -; AX: pointer to buffer containing data to be sent -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_send: - stax tcp_send_data_ptr - - ; are we connected? - ldax #W5100_S1_SR - jsr w5100_read_register - cmp #W5100_STATUS_SOCK_ESTABLISHED - beq @ok - - lda #KPR_ERROR_CONNECTION_CLOSED - sta ip65_error - sec - rts -@ok: - lda #$AD ; opcode for LDA - sta next_eth_packet_byte - - lda #0 - sta byte_ctr_lo - sta byte_ctr_hi - - jsr @get_current_tx_wr - jmp @calculate_tx_wr_ptr -@send_next_byte: - jsr next_eth_packet_byte - tay - ldax tx_wr_ptr - jsr w5100_write_register - - inc byte_ctr_lo - bne :+ - inc byte_ctr_hi -: inc tx_wr_ptr - bne :+ - inc tx_wr_ptr+1 -@calculate_tx_wr_ptr: - lda tx_wr_ptr+1 - and #$0F - clc - adc #$50 - sta tx_wr_ptr+1 -: lda byte_ctr_lo - cmp tcp_send_data_len - bne @send_next_byte - lda byte_ctr_hi - cmp tcp_send_data_len+1 - bne @send_next_byte - - ; all bytes copied, now adjust the tx write ptr and SEND - jsr @get_current_tx_wr - clc - lda tx_wr_ptr - adc tcp_send_data_len - sta tx_wr_ptr - lda tx_wr_ptr+1 - adc tcp_send_data_len+1 - tay - ldax #W5100_S1_TX_WR0 - jsr w5100_write_register - ldy tx_wr_ptr - ldax #W5100_S1_TX_WR1 - jsr w5100_write_register - ldax #W5100_S1_CR - ldy #W5100_CMD_SEND - jsr w5100_write_register - clc - rts - -@get_current_tx_wr: - ldax #W5100_S1_TX_WR0 - jsr w5100_read_register - sta tx_wr_ptr+1 - ldax #W5100_S1_TX_WR1 - jsr w5100_read_register - sta tx_wr_ptr - rts - -; send an empty ACK packet on the current connection -; inputs: -; none -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_send_keep_alive: - ; are we connected? - ldax #W5100_S1_SR - jsr w5100_read_register - cmp #W5100_STATUS_SOCK_ESTABLISHED - beq @ok - - lda #KPR_ERROR_CONNECTION_CLOSED - sta ip65_error - sec - rts -@ok: - ldax #W5100_S1_CR - ldy #W5100_CMD_SEND_KEEP - jsr w5100_write_register - clc - rts - -; close the current connection -; inputs: -; none -; outputs: -; carry flag is set if an error occured, clear otherwise -tcp_close: - ldax #W5100_S1_CR - ldy #W5100_CMD_DISCONNECT - jsr w5100_write_register - clc - rts - -; poll the TCP socket -; if there is data available, call the user supplied TCP callback -; inputs: -; none -; outputs: -; carry flag is set if there was data, clear otherwise -tcp_rx: - ; is there data? - ldax #W5100_S1_RX_RSR0 - jsr w5100_read_register - sta tcp_inbound_data_length+1 - ldax #W5100_S1_RX_RSR1 - jsr w5100_read_register - sta tcp_inbound_data_length - bne @got_data - lda tcp_inbound_data_length+1 - bne @got_data - - ; are we connected? - ldax #W5100_S1_SR - jsr w5100_read_register - cmp #W5100_STATUS_SOCK_ESTABLISHED - beq @connected_but_no_data - ; no longer connected - lda #tcp_cxn_state_closed - sta tcp_state - - lda #$ff - sta tcp_inbound_data_length - sta tcp_inbound_data_length+1 - jsr @make_fake_eth_header - jsr jmp_to_callback ; let the caller see the connection has closed - sec ; don't poll the MAC RAW socket, else it may clobber the output buffer - rts -@connected_but_no_data: - clc ; no data - go check the MAC RAW socket - rts -@got_data: - lda #$8D ; opcode for STA - sta next_eth_packet_byte - - ldax #eth_inp+$36 ; we will write to the location that TCP data would appear if this was a raw eth frame, - ; 14 bytes of ethernet header - ; 20 bytes of IP header - ; 20 bytes of TCP header - stax tcp_inbound_data_ptr - - sta eth_ptr_lo - stx eth_ptr_hi - - lda #0 - sta byte_ctr_lo - sta byte_ctr_hi - - lda tcp_inbound_data_length+1 - cmp #4 ; don't allow more than $4FF bytes at once ($1279) since we are writing to a 1500 byte - bmi :+ - lda #4 - sta tcp_inbound_data_length+1 -: ; now copy the data just arrived to the eth_inp buffer - jsr @get_current_rx_rd - jsr @mask_and_adjust_rx_read -@get_next_byte: - ldax rx_rd_ptr - jsr w5100_read_register - jsr next_eth_packet_byte - - jsr @inc_rx_rd_ptr - - inc byte_ctr_lo - bne :+ - inc byte_ctr_hi -: lda byte_ctr_lo - cmp tcp_inbound_data_length - bne @get_next_byte - lda byte_ctr_hi - cmp tcp_inbound_data_length+1 - bne @get_next_byte - - ; update the RX RD pointer past the frame we just read - jsr @get_current_rx_rd - clc - lda rx_rd_ptr - adc tcp_inbound_data_length - sta rx_rd_ptr - lda rx_rd_ptr+1 - adc tcp_inbound_data_length+1 - tay - ldax #W5100_S1_RX_RD0 - jsr w5100_write_register - ldy rx_rd_ptr - - ldax #W5100_S1_RX_RD1 - jsr w5100_write_register - ldax #W5100_S1_CR - ldy #W5100_CMD_RECV - jsr w5100_write_register - - jsr @make_fake_eth_header - jsr jmp_to_callback ; let the caller see the connection has closed - sec ; don't poll the MAC RAW socket, else it may clobber the output buffer - rts - -@inc_rx_rd_ptr: - inc rx_rd_ptr - bne :+ - inc rx_rd_ptr+1 -@mask_and_adjust_rx_read: - lda rx_rd_ptr+1 - and #$0F - clc - adc #$70 - sta rx_rd_ptr+1 -: rts - -@get_current_rx_rd: - ldax #W5100_S1_RX_RD0 - jsr w5100_read_register - sta rx_rd_ptr+1 - ldax #W5100_S1_RX_RD1 - jsr w5100_read_register - sta rx_rd_ptr - rts - -.import ip_inp -.import udp_inp - -; the function dispatcher (and possibly other parts of the ip65 stack) expect to find valid values in the eth_inp frame -; when processing tcp data -@make_fake_eth_header: - ; first set the TCP protocol value - lda #6 ; TCP protocol number - sta ip_inp+9 ; proto number - - ; now copy the remote IP address - ldx #0 -@ip_loop: - lda tcp_remote_ip,x - sta ip_inp+12,x ; src IP - inx - cpx #$04 - bne @ip_loop - - ; now the local & remote ports - lda tcp_connect_remote_port - sta udp_inp+1 ; remote port (lo byte) - lda tcp_connect_remote_port+1 - sta udp_inp+0 ; remote port (high byte) - lda tcp_local_port - sta udp_inp+3 ; local port (lo byte) - lda tcp_local_port+1 - sta udp_inp+2 ; local port (high byte) - rts - -jmp_to_callback: - jmp (tcp_callback) - -; copy the IP65 configuration to the the w5100 onchip configuration -; we assume MAC has been configured already via eth_init, but IP -; address etc may not be known when the w5100 was initialised (e.g. -; if using DHCP). -w5100_set_ip_config: - ldax #W5100_GAR0 - jsr w5100_select_register - ldx #0 -@gateway_loop: - lda cfg_gateway,x - sta WIZNET_DATA_REG - inx - cpx #$04 - bne @gateway_loop - ldx #0 -@netmask_loop: - lda cfg_netmask,x - sta WIZNET_DATA_REG - inx - cpx #$04 - bne @netmask_loop - - ldax #W5100_SIPR0 - jsr w5100_select_register - ldx #0 -@ip_loop: - lda cfg_ip,x - sta WIZNET_DATA_REG - inx - cpx #$04 - bne @ip_loop - rts - -setup_tcp_socket: - jsr w5100_set_ip_config - ldax #W5100_S1_PORT0 - jsr w5100_select_register - lda tcp_local_port+1 - sta WIZNET_DATA_REG - lda tcp_local_port - sta WIZNET_DATA_REG - - lda #0 - sta tcp_state - - ldax #W5100_S1_MR - ldy #W5100_MODE_TCP - jsr w5100_write_register - - ; open socket 1 - ldax #W5100_S1_CR - ldy #W5100_CMD_OPEN - jsr w5100_write_register - rts - - -.rodata - -eth_driver_name: - .asciiz "RR-NET MK3 (WIZNET 5100)" - -eth_driver_io_base: - .word WIZNET_BASE - -w5100_config_data: - .byte $00 ; no interrupts - .byte $0f ; 400ms retry (default) - .byte $a0 - .byte $08 ; # of timeouts - .byte $55 ; 4 sockets @2K each, tx/rx - .byte $55 - -; select one of the W5100 registers for subsequent read or write -; inputs: AX = register number to select -; outputs: none -w5100_select_register: -set_hi: - stx WIZNET_ADDR_HI -set_lo: - sta WIZNET_ADDR_LO - rts - -; return which W5100 register the next read or write will access -; inputs: none -; outputs: AX = selected register number -w5100_get_current_register: -get_hi: - ldx WIZNET_ADDR_HI -get_lo: - lda WIZNET_ADDR_LO - rts - - -.data - -next_eth_packet_byte: - lda $FFFF ; eth_packet - jmp advance_eth_ptr - -eth_ptr_lo = next_eth_packet_byte+1 -eth_ptr_hi = next_eth_packet_byte+2 - - -; .bss - -w5100_addr: .res 2 -byte_ctr_lo: .res 1 -byte_ctr_hi: .res 1 - -tx_wr_ptr: .res 2 -rx_rd_ptr: .res 2 -tcp_local_port: .res 2 - -tcp_state: .res 1 - -tcp_connect_ip: .res 4 ; ip address of remote server to connect to -tcp_callback: .res 2 ; vector to routine to be called when data is received over tcp connection - -tcp_remote_port: .res 2 ; temp space for holding port to listen on or connect to -tcp_send_data_len: .res 2 -tcp_send_data_ptr = eth_ptr_lo - -tcp_inbound_data_length: .res 2 -tcp_inbound_data_ptr: .res 2 - -tcp_connect_remote_port: .res 2 -tcp_remote_ip = tcp_connect_ip - -tcp_cxn_state_closed = 0 -tcp_cxn_state_listening = 1 ; (waiting for an inbound SYN) -tcp_cxn_state_syn_sent = 2 ; (waiting for an inbound SYN/ACK) -tcp_cxn_state_established = 3 - - - -; -- LICENSE FOR w5100a.s -- -; The contents of this file are subject to the Mozilla Public License -; Version 1.1 (the "License"); you may not use this file except in -; compliance with the License. You may obtain a copy of the License at -; http://www.mozilla.org/MPL/ ; -; Software distributed under the License is distributed on an "AS IS" -; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -; License for the specific language governing rights and limitations -; under the License. +; Copyright (c) 2013, Oliver Schmidt +; All rights reserved. ; -; The Original Code is ip65. +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. Neither the name of the Institute nor the names of its contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. ; -; The Initial Developer of the Original Code is Jonno Downes (jonno@jamtronix.com) -; Portions created by the Initial Developer is Copyright (C) 2010 -; Jonno Downes. All Rights Reserved. -; -- LICENSE END -- +; THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +; ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. +; +; This file is part of the Contiki operating system. +; +; Author: Oliver Schmidt +; +;--------------------------------------------------------------------- + + .macpack module + module_header _w5100 + + ; Driver signature + .byte $65, $74, $68 ; "eth" + .byte $01 ; Ethernet driver API version number + + ; Ethernet address +mac: .byte $00, $08, $DC ; OUI of WIZnet + .byte $11, $11, $11 + + ; Buffer attributes +bufaddr:.res 2 ; Address +bufsize:.res 2 ; Size + + ; Jump table. + jmp init + jmp poll + jmp send + jmp exit + +;--------------------------------------------------------------------- + + .if DYN_DRV + + .zeropage +sp: .res 2 ; Stack pointer (Do not trash !) +reg: .res 2 ; Pointer Register content +ptr: .res 2 ; Indirect addressing pointer +len: .res 2 ; Data length +cnt: .res 2 ; Data length counter +adv: .res 2 ; Data pointer advancement +dir: .res 1 ; Transfer direction +bas: .res 1 ; Socket 0 Base Address (hibyte) +lim: .res 1 ; Socket 0 memory limit (hibyte) +tmp: .res 1 ; Temporary value + + .else + + .include "zeropage.inc" +reg := ptr1 ; Pointer Register content +ptr := ptr2 ; Indirect addressing pointer +len := ptr3 ; Data length +cnt := ptr4 ; Data length counter +adv := sreg ; Data pointer advancement +dir := tmp1 ; Transfer direction +bas := tmp2 ; Socket 0 Base Address (hibyte) +lim := tmp3 ; Socket 0 memory limit (hibyte) +tmp := tmp4 ; Temporary value + + .endif + +;--------------------------------------------------------------------- + + .rodata + +fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03 + .byte fixup05-fixup04, fixup06-fixup05, fixup07-fixup06 + .byte fixup08-fixup07, fixup09-fixup08, fixup10-fixup09 + .byte fixup11-fixup10, fixup12-fixup11, fixup13-fixup12 + .byte fixup14-fixup13, fixup15-fixup14, fixup16-fixup15 + .byte fixup17-fixup16, fixup18-fixup17, fixup19-fixup18 + .byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21 + .byte fixup23-fixup22, fixup24-fixup23, fixup25-fixup24 + .byte fixup26-fixup25, fixup27-fixup26, fixup28-fixup27 + .byte fixup29-fixup28, fixup30-fixup29 + +fixups = * - fixup + +;--------------------------------------------------------------------- + +mode := $FF00 ; High byte patched at runtime +addr := $FF01 ; High byte patched at runtime +data := $FF03 ; High byte patched at runtime + + .data + +;--------------------------------------------------------------------- + +init: + ; Save address of register base + sta reg + stx reg+1 + + ; Start with first fixup location + lda #<(fixup01+1) + ldx #>(fixup01+1) + sta ptr + stx ptr+1 + ldx #$FF + ldy #$00 + + ; Fixup address at location +: lda reg + ora (ptr),y + sta (ptr),y + iny + lda reg+1 + sta (ptr),y + dey + + ; Advance to next fixup location + inx + cpx #fixups + bcs :+ + lda ptr + clc + adc fixup,x + sta ptr + bcc :- + inc ptr+1 + bcs :- ; Always + + ; Indirect Bus I/F mode, Address Auto-Increment +: +fixup01:lda mode + ora #$03 +fixup02:sta mode + + ; Retry Time-value Register: = 2000 ? + ldx #$00 ; Hibyte + ldy #$17 ; Lobyte + jsr set_addr + lda #$07^$D0 +fixup03:eor data +fixup04:eor data + beq :+ + sec + rts + + ; S/W Reset +: lda #$80 +fixup05:sta mode +: +fixup06:lda mode + bmi :- + + ; Indirect Bus I/F mode, Address Auto-Increment, Ping Block + lda #$13 +fixup07:sta mode + + ; Source Hardware Address Register: MAC Address + ldx #$00 ; Hibyte + ldy #$09 ; Lobyte + jsr set_addr +: lda mac,x +fixup08:sta data + inx + cpx #$06 + bcc :- + + ; RX Memory Size Register: Assign 8KB to socket 0 + ; TX Memory Size Register: Assign 8KB to socket 0 + ldx #$00 ; Hibyte + ldy #$1A ; Lobyte + jsr set_addr + lda #$03 +fixup09:sta data +fixup10:sta data + + ; Socket 0 Mode Register: MACRAW, MAC Filter + ; Socket 0 Command Register: OPEN + ldy #$00 + jsr set_addrsocket0 + lda #$44 +fixup11:sta data + lda #$01 +fixup12:sta data + tya + tax + clc + rts + +;--------------------------------------------------------------------- + +poll: + ; Check for completion of previous command + ; Socket 0 Command Register: = 0 ? + jsr set_addrcmdreg0 +fixup13:lda data + beq :++ + + ; No data available + lda #$00 +: tax + sec + rts + + ; Socket 0 RX Received Size Register: != 0 ? +: ldy #$26 ; Socket RX Received Size Register + jsr set_addrsocket0 +fixup14:lda data ; Hibyte +fixup15:ora data ; Lobyte + beq :-- + + ; Process the incoming data + ; ------------------------- + + ; Set parameters for receiving data + lda #>$6000 ; Socket 0 RX Base Address + ldx #$00 ; Read + jsr set_parameters + + ; ldy #$28 ; Socket RX Read Pointer Register + ; jsr set_addrsocket0 + + ; Calculate and set physical address + jsr set_addrphysical + + ; Move physical address shadow to $E000-$FFFF + ora #>$8000 + tax + + ; Read MAC raw 2byte packet size header + jsr get_datacheckaddr ; Hibyte + sta adv+1 + jsr get_datacheckaddr ; Lobyte + sta adv + + ; Subtract 2byte header and set length + sec + sbc #<$0002 + sta len + sta cnt + lda adv+1 + sbc #>$0002 + sta len+1 + sta cnt+1 + + ; Is bufsize < length ? + lda bufsize + cmp len + lda bufsize+1 + sbc len+1 + bcs :+ + + ; Set data length = 0 and skip read + lda #$00 + sta len + sta len+1 + beq :++ ; Always + + ; Read data +: jsr mov_data + + ; Set parameters for common code +: lda #$40 ; RECV + ldy #$28 ; Socket 0 RX Read Pointer Register + + ; Advance pointer register +common: jsr set_addrsocket0 + tay ; Save command + clc + lda reg + adc adv + tax + lda reg+1 + adc adv+1 +fixup16:sta data ; Hibyte +fixup17:stx data ; Lobyte + + ; Set command register + tya ; Restore command + jsr set_addrcmdreg0 +fixup18:sta data + + ; Return data length (will be ignored for send) + lda len + ldx len+1 + clc + rts + +;--------------------------------------------------------------------- + +send: + ; Save data length + sta len + stx len+1 + sta cnt + stx cnt+1 + sta adv + stx adv+1 + + ; Set parameters for transmitting data + lda #>$4000 ; Socket 0 TX Base Address + ldx #$01 ; Write + jsr set_parameters + + ; Wait for completion of previous command + ; Socket 0 Command Register: = 0 ? +: jsr set_addrcmdreg0 +fixup19:lda data + bne :- + + ; Socket 0 TX Free Size Register: < length ? +: ldy #$20 ; Socket TX Free Size Register + jsr set_addrsocket0 +fixup20:lda data ; Hibyte +fixup21:ldx data ; Lobyte + cpx len + sbc len+1 + bcc :- + + ; Send the data + ; ------------- + + ldy #$24 ; Socket TX Write Pointer Register + jsr set_addrsocket0 + + ; Calculate and set pyhsical address + jsr set_addrphysical + + ; Write data + jsr mov_data + + ; Set parameters for common code + lda #$20 ; SEND + ldy #$24 ; Socket TX Write Pointer Register + bne common ; Always + +;--------------------------------------------------------------------- + +exit: + rts + +;--------------------------------------------------------------------- + +set_addrphysical: +fixup22:lda data ; Hibyte +fixup23:ldy data ; Lobyte + sty reg + sta reg+1 + and #>$1FFF ; Socket Mask Address (hibyte) + ora bas ; Socket Base Address (hibyte) + tax +set_addr: +fixup24:stx addr ; Hibyte +fixup25:sty addr+1 ; Lobyte + rts + +set_addrcmdreg0: + ldy #$01 ; Socket Command Register +set_addrsocket0: + ldx #>$0400 ; Socket 0 register base address + bne set_addr ; Always + +set_addrbase: + ldx bas ; Socket Base Address (hibyte) + ldy #<$0000 ; Socket Base Address (lobyte) + beq set_addr ; Always + +get_datacheckaddr: +fixup26:lda data + iny ; Physical address shadow (lobyte) + bne :+ + inx ; Physical address shadow (hibyte) + beq set_addrbase +: rts + +;--------------------------------------------------------------------- + +set_parameters: + ; Setup variables in zero page + sta bas ; Socket Base Address + clc + adc #>$2000 ; Socket memory size + sta lim ; Socket memory limit + stx dir ; Transfer direction + + ; Set indirect addressing pointer + lda bufaddr + ldx bufaddr+1 + sta ptr + stx ptr+1 + rts + +;--------------------------------------------------------------------- + +mov_data: + ; Calculate highest R/W address allowing + ; to R/W without address wraparound + sec + lda #<$0000 ; Socket memory limit (lobyte) + sbc len + tay + lda lim ; Socket memory limit (hibyte) + sbc len+1 + tax + tya + + ; R/W without address wraparound possible because + ; highest R/W address > actual R/W address ? + ; sec +fixup27:sbc addr+1 ; Lobyte + tay + txa +fixup28:sbc addr ; Hibyte + tax + tya + bcs :+ + + ; Calculate length of first chunk + ; clc + adc len + sta cnt + tay + txa + adc len+1 + sta cnt+1 + tax + tya + + ; R/W first chunk + jsr rw_data + + ; Wraparound R/W address + jsr set_addrbase + + ; Set buffer pointer for second chunk + clc + lda bufaddr + adc cnt + sta ptr + lda bufaddr+1 + adc cnt+1 + sta ptr+1 + + ; Calculate length of second chunk + sec + lda len + sbc cnt + sta cnt + lda len+1 + sbc cnt+1 + sta cnt+1 + + ; Get length of (second) chunk +: lda cnt + ldx cnt+1 + + ; R/W (second) chunk +rw_data:eor #$FF ; Two's complement part 1 + tay + iny ; Two's complement part 2 + sty tmp + sec + lda ptr + sbc tmp + sta ptr + lda ptr+1 + sbc #$00 + sta ptr+1 + lda dir ; Transfer direction + bne :++ + + ; Read data +: +fixup29:lda data + sta (ptr),y + iny + bne :- + inc ptr+1 + dex + bpl :- + rts + + ; Write data +: lda (ptr),y +fixup30:sta data + iny + bne :- + inc ptr+1 + dex + bpl :- + rts + +;--------------------------------------------------------------------- diff --git a/ip65/Makefile b/ip65/Makefile index 05cf314..058ef1c 100644 --- a/ip65/Makefile +++ b/ip65/Makefile @@ -1,66 +1,45 @@ -AS=ca65 -LD=ld65 -AFLAGS= - # ip65.lib : minimal IP stack (UDP only) # ip65_tcp.lib : full featured TCP/IP stack -# ip65_wiznet.lib : hybrid stack for use with the w5100 chip : UDP,ICMP & ARP is done on host, TCP is on w5100 -%.o: %.c - $(CC) -c $(CFLAGS) $< +all: ip65.lib ip65_tcp.lib %.o: %.s - $(AS) $(AFLAGS) $< + ca65 $< -ETHOBJS=\ - copymem.o \ - config.o \ - timer.o \ - eth.o \ +%_tcp.o: %.s + ca65 -DTCP -o $@ $< + +IP65OBJS=\ + arithmetic.o\ arp.o \ - ip65.o \ - printf.o \ + cifs.o \ + config.o \ + copymem.o \ debug.o \ - http.o \ - httpd.o \ dhcp.o \ dns.o \ dottedquad.o \ - output_buffer.o\ + eth.o \ + http.o \ + httpd.o \ + ip65.o \ tftp.o \ + timer.o \ + output_buffer.o\ parser.o \ + printf.o \ + sntp.o \ string_utils.o \ telnet.o \ - url.o \ - arithmetic.o\ - ip.o \ - sntp.o \ - icmp.o \ - cifs.o \ - udp.o + udp.o \ + url.o -all: ip65.lib ip65_tcp.lib ip65_wiznet.lib +ip65.lib: $(IP65OBJS) ip.o icmp.o + ar65 a $@ $^ -ip65.lib: $(ETHOBJS) - $(AS) $(AFLAGS) ip.s - $(AS) $(AFLAGS) icmp.s - ar65 a ip65.lib $(ETHOBJS) - -ip65_tcp.lib: tcp.o $(ETHOBJS) tcp.s - $(AS) $(AFLAGS) ip.s -DTCP - $(AS) $(AFLAGS) icmp.s -DTCP - ar65 a ip65_tcp.lib $(ETHOBJS) tcp.o - -ip65_wiznet.lib: $(ETHOBJS) - $(AS) $(AFLAGS) ip.s - $(AS) $(AFLAGS) icmp.s -DTCP - ar65 a ip65_wiznet.lib $(ETHOBJS) +ip65_tcp.lib: $(IP65OBJS) ip_tcp.o icmp_tcp.o tcp.o + ar65 a $@ $^ clean: -rm -f *.o - -rm -f ip65.lib - -rm -f ip65_tcp.lib - -rm -f ip65_wiznet.lib - -distclean: clean - -rm -f *~ + -rm -f *.lib diff --git a/ip65/config.s b/ip65/config.s index 8e989bc..c53077e 100644 --- a/ip65/config.s +++ b/ip65/config.s @@ -8,13 +8,10 @@ .export cfg_netmask .export cfg_gateway .export cfg_dns -.export cfg_tftp_server -.export cfg_get_configuration_ptr - .export dhcp_server -.import copymem -.importzp copy_src -.importzp copy_dest +.export cfg_tftp_server + +.export cfg_get_configuration_ptr .data diff --git a/test/Makefile b/test/Makefile index 87a8be8..53ed030 100644 --- a/test/Makefile +++ b/test/Makefile @@ -7,106 +7,78 @@ # Build for WIZnet W5100 based devices: # make eth=wn -CC = cl65 -AS = ca65 -LD = ld65 -CFLAGS = -Oirs -t $(TARGET) -AFLAGS = - ifeq ($(eth),sm) + C64DRIVERLIB = ../drivers/c64eth64.lib A2DRIVERLIB = ../drivers/a2lancegs.lib else ifeq ($(eth),wn) + A2DRIVERLIB = ../drivers/a2uther2.lib else C64DRIVERLIB = ../drivers/c64rrnet.lib A2DRIVERLIB = ../drivers/a2uther.lib VICDRIVERLIB = ../drivers/vic20rrnet.lib endif -IP65LIB = ../ip65/ip65.lib -IP65TCPLIB = ../ip65/ip65_tcp.lib +UDP =\ + dns \ + dottedquad \ + parsequerystring \ + sntp \ + tftp -INCFILES = \ - ../inc/common.i\ - ../inc/commonprint.i\ - ../inc/net.i\ +TCP =\ + cifs \ + geturl \ + httpd \ + parser \ + ping \ + tcp -all: prg bin +all: $(UDP) $(TCP) +.PHONY: $(UDP) $(TCP) -prg: \ - ip65 \ - drivers \ - cifs_tcp.prg \ - dns.prg \ - dottedquad.prg \ - geturl_tcp.prg \ - httpd_tcp.prg \ - parsequerystring.prg \ - parser_tcp.prg \ - ping_tcp.prg \ - sntp.prg \ - tcp_tcp.prg \ - tftp.prg +$(addsuffix .prg,$(UDP)): IP65LIB = ../ip65/ip65.lib +$(addsuffix .prg,$(TCP)): IP65LIB = ../ip65/ip65_tcp.lib -bin: \ - ip65 \ - drivers \ - cifs_tcp.bin \ - dns.bin \ - dottedquad.bin \ - geturl_tcp.bin \ - httpd_tcp.bin \ - parsequerystring.bin \ - parser_tcp.bin \ - ping_tcp.bin \ - sntp.bin \ - tcp_tcp.bin \ - tftp.bin +$(addsuffix .bin,$(UDP)): IP65LIB = ../ip65/ip65.lib +$(addsuffix .bin,$(TCP)): IP65LIB = ../ip65/ip65_tcp.lib -vicprg: \ - ip65 \ - drivers \ - cifs_tcp.vicprg \ - dns.vicprg \ - dottedquad.vicprg \ - geturl_tcp.vicprg \ - httpd_tcp.vicprg \ - parsequerystring.vicprg \ - parser_tcp.vicprg \ - ping_tcp.vicprg \ - sntp.vicprg \ - tcp_tcp.vicprg \ - tftp.vicprg +$(addsuffix .vicprg,$(UDP)): IP65LIB = ../ip65/ip65.lib +$(addsuffix .vicprg,$(TCP)): IP65LIB = ../ip65/ip65_tcp.lib -ip65: - make -C ../ip65 all +$(foreach pgm,$(UDP) $(TCP),$(eval $(pgm): $(pgm).prg $(pgm).bin $(pgm).vicprg)) -drivers: - make -C ../drivers all +INCFILES =\ + ../inc/common.i \ + ../inc/commonprint.i \ + ../inc/net.i + +prg: $(addsuffix .prg,$(UDP) $(TCP)) + +bin: $(addsuffix .bin,$(UDP) $(TCP)) + +vicprg: $(addsuffix .vicprg,$(UDP) $(TCP)) d64: ip65.d64 dsk: ip65.dsk +ip65: + make -C ../ip65 + +drivers: + make -C ../drivers + %.o: %.s - $(AS) $(AFLAGS) $< + ca65 $< -%.prg: %.o $(IP65LIB) $(C64DRIVERLIB) $(INCFILES) - $(LD) -o $*.prg -t c64 -m $*.c64.map -vm $< $(IP65LIB) $(C64DRIVERLIB) c64.lib +%.prg: %.o ip65 drivers $(INCFILES) + ld65 -o $*.prg -C c64.cfg -m $*.c64.map -vm $< $(IP65LIB) $(C64DRIVERLIB) c64.lib -%_tcp.prg: %.o $(IP65TCPLIB) $(C64DRIVERLIB) $(INCFILES) - $(LD) -o $(subst _tcp,,$*).prg -t c64 -m $(subst _tcp,,$*).c64.map -vm $< $(IP65TCPLIB) $(C64DRIVERLIB) c64.lib +%.bin: %.o ip65 drivers $(INCFILES) + ld65 -o $*.bin -C apple2.cfg -m $*.a2.map -vm $< $(IP65LIB) $(A2DRIVERLIB) apple2.lib -%.bin: %.o $(IP65LIB) $(A2DRIVERLIB) $(INCFILES) - $(LD) -o $*.bin -t apple2 -m $*.a2.map -vm $< $(IP65LIB) $(A2DRIVERLIB) apple2.lib - -%_tcp.bin: %.o $(IP65TCPLIB) $(A2DRIVERLIB) $(INCFILES) - $(LD) -o $(subst _tcp,,$*).bin -t apple2 -m $(subst _tcp,,$*).a2.map -vm $< $(IP65TCPLIB) $(A2DRIVERLIB) apple2.lib - -%.vicprg: %.o $(IP65LIB) $(VICDRIVERLIB) $(INCFILES) - $(LD) -o $*.vicprg -C vic20-32k.cfg -m $*.vic.map -vm $< $(IP65LIB) $(VICDRIVERLIB) vic20.lib - -%_tcp.vicprg: %.o $(IP65TCPLIB) $(VICDRIVERLIB) $(INCFILES) - $(LD) -o $(subst _tcp,,$*).vicprg -C vic20-32k.cfg -m $(subst _tcp,,$*).vic.map -vm $< $(IP65TCPLIB) $(VICDRIVERLIB) vic20.lib +%.vicprg: %.o ip65 drivers $(INCFILES) + ld65 -o $*.vicprg -C vic20-32k.cfg -m $*.vic.map -vm $< $(IP65LIB) $(VICDRIVERLIB) vic20.lib ip65.d64: prg $(C1541) -format ip65,00 d64 $@ @@ -133,8 +105,7 @@ ip65.dsk: bin java -jar $(AC) -cc65 $@ tftp bin 0 < tftp.bin clean: - -rm -f *.o *.prg *.bin *.vicprg *.map + make -C ../ip65 clean + make -C ../drivers clean + -rm -f *.prg *.bin *.vicprg *.map -rm -f ip65.d64 ip65.dsk - -distclean: clean - -rm -f *~