; ; Copyright (c) 2013, 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: 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 $A2, $A2, $A2 ; 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, fixup31-fixup30 .byte fixup32-fixup31 fixups = * - fixup ;--------------------------------------------------------------------- ; The addresses are fixed up at runtime mode := $C084 addr := $C085 data := $C087 ;--------------------------------------------------------------------- .data init: ; Convert slot number to slot I/O offset asl asl asl asl sta reg ; 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 (ptr),y and #%10001111 ; Allow for re-init ora reg sta (ptr),y ; 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 ; Check for W5100 shared access ; RX Memory Size Register: Assign 4+2+1+1KB to socket 0 to 3 ? : ; ldx #$00 ; Hibyte ldy #$1A ; Lobyte jsr set_addr fixup05:lda data cmp #$06 beq :+++ ; S/W Reset lda #$80 fixup06:sta mode : fixup07:lda mode bmi :- ; Indirect Bus I/F mode, Address Auto-Increment, Ping Block lda #$13 fixup08:sta mode ; Source Hardware Address Register: MAC Address ldx #$00 ; Hibyte ldy #$09 ; Lobyte jsr set_addr : lda mac,x fixup09:sta data inx cpx #$06 bcc :- ; RX Memory Size Register: Assign 4KB each to socket 0 and 1 ; TX Memory Size Register: Assign 4KB each to socket 0 and 1 ldx #$00 ; Hibyte ldy #$1A ; Lobyte jsr set_addr lda #$0A fixup10:sta data fixup11:sta data ; MAC Address: Source Hardware Address Register : ; ldx #$00 ; Hibyte ldy #$09 ; Lobyte jsr set_addr : fixup12:lda data sta mac,x inx cpx #$06 bcc :- ; Socket 0 Mode Register: MACRAW, MAC Filter ; Socket 0 Command Register: OPEN ldy #$00 jsr set_addrsocket0 lda #$44 fixup13:sta data lda #$01 fixup14:sta data tya tax clc rts ;--------------------------------------------------------------------- poll: ; Check for completion of previous command ; Socket 0 Command Register: = 0 ? jsr set_addrcmdreg0 fixup15: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 fixup16:lda data ; Hibyte fixup17: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 $F000-$FFFF ora #>$F000 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 fixup18:sta data ; Hibyte fixup19:stx data ; Lobyte ; Set command register tya ; Restore command jsr set_addrcmdreg0 fixup20: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 fixup21:lda data bne :- ; Socket 0 TX Free Size Register: < length ? : ldy #$20 ; Socket TX Free Size Register jsr set_addrsocket0 fixup22:lda data ; Hibyte fixup23: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: fixup24:lda data ; Hibyte fixup25:ldy data ; Lobyte sty reg sta reg+1 and #>$0FFF ; Socket Mask Address (hibyte) ora bas ; Socket Base Address (hibyte) tax set_addr: fixup26:stx addr ; Hibyte fixup27: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: fixup28: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 #>$1000 ; 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 fixup29:sbc addr+1 ; Lobyte tay txa fixup30: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 : fixup31:lda data sta (ptr),y iny bne :- inc ptr+1 dex bpl :- rts ; Write data : lda (ptr),y fixup32:sta data iny bne :- inc ptr+1 dex bpl :- rts ;---------------------------------------------------------------------