emailler/drivers/w5100.s
Oliver Schmidt e06c02e4a3 1. Replaced IP65 Ethernet drivers with Contiki drivers.
* CS8900A
The Contiki driver allows to adjust the chip base addr at runtime (which  allows to support different slots in the Apple II) and removes received frames from the chip if there's no room to send frames.

* LAN91C96
The Contiki driver was used by IP65 more or less unchanged in the first place.

* W5100
The Contiki driver allows to adjust the chip base addr at runtime (which  allows to support different slots in the Apple II) and stays clear from the W5100 hybrid mode. It presumes a fully functional W5100 register auto-increment and pre-calculates necessary W5100 frame buffer wrap-arounds and thus achieves the maximal 6502 <-> W5100 transfer speed.
2014-06-13 00:00:53 +02:00

512 lines
10 KiB
ArmAsm

;
; 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 <ol.sc@web.de>
;
;---------------------------------------------------------------------
.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
;---------------------------------------------------------------------