Enhanced Ethernet drivers.

Made Ethernet drivers easier to consume by assembly programs.
* Replaced function pointers with JMP instructions.
* Provide return values additionally via Carry flag.

Reset Ethernet chips on initialization.
Both for the CS8900A and the W5100 the data sheets just say that
the RESET bit is automatically cleared after the RESET. This may
be interpreted in two ways:
1) There's no need to be afraid of reading the RESET bit as 1 and
unintentionally trigger a RESET by writing it back after ORing in
some other bit.
2) The RESET process isn't complete before the RESET bit hasn't
become 0 again.
It's impossible for me to empirically falsify the latter option
as the drivers are supposed to work on faster machines than the
ones I have access to. And if the RESET process includes things
like oscillators then the time to complete the RESET could differ
even between multiple exemplars of the same chip. Therefore I
opted to presume the latter option.
However that means a non-exsistent chip may cause an infinite
loop while waiting for the RESET bit to be cleared so I finally
added code to detect the presence of the Ethernet chips. There's
a risk of a chip being locked up in a way that makes the detection
fail - and therefore the RESET not being performed. This catch-22
needs to be solved by the user doing a hard RESET.
This commit is contained in:
Oliver Schmidt 2014-06-12 22:56:35 +02:00
parent a0961fc3c4
commit a5d7a06027
4 changed files with 177 additions and 109 deletions

View File

@ -48,10 +48,10 @@ bufaddr:.res 2 ; Address
bufsize:.res 2 ; Size
; Jump table.
.addr init
.addr poll
.addr send
.addr exit
jmp init
jmp poll
jmp send
jmp exit
;---------------------------------------------------------------------
@ -85,6 +85,8 @@ fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03
.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
@ -143,6 +145,29 @@ 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
@ -173,6 +198,8 @@ fixup02:sta isq+1
lda #$D3
ldx #$00
jsr ppdata_ax
txa
clc
rts
;---------------------------------------------------------------------
@ -183,27 +210,22 @@ poll:
; PACKETPP = $0124, PPDATA & $0D00 ?
lda #$24
jsr packetpp_a1
fixup03:lda ppdata+1
fixup07:lda ppdata+1
and #$0D
bne :+
; No frame ready
tax
rts
beq :+
; Process the incoming frame
; --------------------------
; Read receiver event and discard it
; RXTXREG
:
fixup04:ldx rxtxreg+1
fixup05:lda rxtxreg
fixup08:ldx rxtxreg+1
fixup09:lda rxtxreg
; Read frame length
; cnt = len = RXTXREG
fixup06:ldx rxtxreg+1
fixup07:lda rxtxreg
fixup10:ldx rxtxreg+1
fixup11:lda rxtxreg
sta len
stx len+1
sta cnt
@ -217,23 +239,24 @@ fixup07:lda rxtxreg
cmp cnt
lda bufsize+1
sbc cnt+1
bcs :+
bcs :++
; Yes, skip frame
jsr skipframe
; No frame ready
lda #$00
tax
: tax
sec
rts
; Read bytes into buffer
: jsr adjustptr
:
fixup08:lda rxtxreg
fixup12:lda rxtxreg
sta (ptr),y
iny
fixup09:lda rxtxreg+1
fixup13:lda rxtxreg+1
sta (ptr),y
iny
bne :-
@ -244,6 +267,7 @@ fixup09:lda rxtxreg+1
; Return frame length
lda len
ldx len+1
clc
rts
;---------------------------------------------------------------------
@ -256,12 +280,12 @@ send:
; Transmit command
lda #$C9
ldx #$00
fixup10:sta txcmd
fixup11:stx txcmd+1
fixup14:sta txcmd
fixup15:stx txcmd+1
lda cnt
ldx cnt+1
fixup12:sta txlen
fixup13:stx txlen+1
fixup16:sta txlen
fixup17:stx txlen+1
; Adjust odd frame length
jsr adjustcnt
@ -273,7 +297,7 @@ fixup13:stx txlen+1
; PACKETPP = $0138, PPDATA & $0100 ?
: lda #$38
jsr packetpp_a1
fixup14:lda ppdata+1
fixup18:lda ppdata+1
and #$01
bne :+
@ -283,6 +307,7 @@ fixup14:lda ppdata+1
; And try again
dey
bne :-
sec
rts
; Send the frame
@ -291,15 +316,16 @@ fixup14:lda ppdata+1
; Write bytes from buffer
: jsr adjustptr
: lda (ptr),y
fixup15:sta rxtxreg
fixup19:sta rxtxreg
iny
lda (ptr),y
fixup16:sta rxtxreg+1
fixup20:sta rxtxreg+1
iny
bne :-
inc ptr+1
dex
bpl :-
clc
rts
;---------------------------------------------------------------------
@ -311,15 +337,16 @@ exit:
packetpp_a1:
ldx #$01
fixup17:sta packetpp
fixup18:stx packetpp+1
packetpp_ax:
fixup21:sta packetpp
fixup22:stx packetpp+1
rts
;---------------------------------------------------------------------
ppdata_ax:
fixup19:sta ppdata
fixup20:stx ppdata+1
fixup23:sta ppdata
fixup24:stx ppdata+1
rts
;---------------------------------------------------------------------
@ -328,9 +355,9 @@ skipframe:
; PACKETPP = $0102, PPDATA = PPDATA | $0040
lda #$02
jsr packetpp_a1
fixup21:lda ppdata
fixup25:lda ppdata
ora #$40
fixup22:sta ppdata
fixup26:sta ppdata
rts
;---------------------------------------------------------------------

View File

@ -47,9 +47,13 @@ struct {
struct uip_eth_addr ethernet_address;
uint8_t *buffer;
uint16_t buffer_size;
void __fastcall__ (* init)(uint16_t reg);
char jmp_init;
char __fastcall__ (* init)(uint16_t reg);
char jmp_poll;
uint16_t (* poll)(void);
char jmp_send;
void __fastcall__ (* send)(uint16_t len);
char jmp_exit;
void (* exit)(void);
} *module;
@ -97,7 +101,10 @@ ethernet_init(struct ethernet_config *config)
module->buffer = uip_buf;
module->buffer_size = UIP_BUFSIZE;
module->init(config->addr);
if(module->init(config->addr)) {
log_message(config->name, ": No hardware");
error_exit();
}
uip_setethaddr(module->ethernet_address);
}

View File

@ -49,10 +49,10 @@ bufaddr:.res 2 ; Address
bufsize:.res 2 ; Size
; Jump table.
.addr init
.addr poll
.addr send
.addr exit
jmp init
jmp poll
jmp send
jmp exit
;---------------------------------------------------------------------
@ -89,7 +89,7 @@ fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03
.byte fixup29-fixup28, fixup30-fixup29, fixup31-fixup30
.byte fixup32-fixup31, fixup33-fixup32, fixup34-fixup33
.byte fixup35-fixup34, fixup36-fixup35, fixup37-fixup36
.byte fixup38-fixup37
.byte fixup38-fixup37, fixup39-fixup38, fixup40-fixup39
fixups = * - fixup
@ -195,51 +195,58 @@ fixup06:stx ethrcr+1
lda #$01 ; Bank 1
fixup07:sta ethbsr
fixup08:lda ethcr+1
; 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
:
fixup10:lda ethcr+1
ora #%00010000 ; No wait (IOCHRDY)
fixup09:sta ethcr+1
fixup11:sta ethcr+1
lda #%00001001 ; Auto release
fixup10:sta ethctr+1
fixup12:sta ethctr+1
; Set MAC address
ldy #$00
: lda mac,y
fixup11:sta ethiar,y
fixup13:sta ethiar,y
iny
cpy #$06
bcc :-
; Set interrupt mask
lda #$02 ; Bank 2
fixup12:sta ethbsr
fixup14:sta ethbsr
lda #%00000000 ; No interrupts
fixup13:sta ethmsk
fixup15:sta ethmsk
tax
clc
rts
;---------------------------------------------------------------------
poll:
fixup14:lda ethist
fixup16:lda ethist
and #%00000001 ; RCV INT
bne :+
; No packet available
tax
rts
beq :+
; Process the incoming packet
; ---------------------------
: lda #$00
lda #$00
ldx #%11100000 ; RCV, AUTO INCR., READ
fixup15:sta ethptr
fixup16:stx ethptr+1
fixup17:sta ethptr
fixup18:stx ethptr+1
; Last word contains 'last data byte' and $60 or 'fill byte' and $40
fixup17:lda ethdata ; Status word
fixup18:lda ethdata ; Need high byte only
fixup19:lda ethdata ; Status word
fixup20:lda ethdata ; Need high byte only
; Move ODDFRM bit into carry:
; - Even packet length -> carry clear -> subtract 6 bytes
@ -251,10 +258,10 @@ fixup18:lda ethdata ; Need high byte only
lsr
; The packet contains 3 extra words
fixup19:lda ethdata ; Total number of bytes
fixup21:lda ethdata ; Total number of bytes
sbc #$05 ; Actually 5 or 6 depending on carry
sta len
fixup20:lda ethdata
fixup22:lda ethdata
sbc #$00
sta len+1
@ -263,22 +270,23 @@ fixup20:lda ethdata
cmp len
lda bufsize+1
sbc len+1
bcs :+
bcs :++
; Yes, skip packet
; Remove and release RX packet from the FIFO
lda #%10000000
fixup21:sta ethmmucr
fixup23:sta ethmmucr
; No packet available
lda #$00
tax
: tax
sec
rts
; Read bytes into buffer
: jsr adjustptr
:
fixup22:lda ethdata
fixup24:lda ethdata
sta (ptr),y
iny
bne :-
@ -288,11 +296,12 @@ fixup22:lda ethdata
; Remove and release RX packet from the FIFO
lda #%10000000
fixup23:sta ethmmucr
fixup25:sta ethmmucr
; Return packet length
lda len
ldx len+1
clc
rts
;---------------------------------------------------------------------
@ -305,14 +314,14 @@ send:
; Allocate memory for TX
txa
ora #%00100000
fixup24:sta ethmmucr
fixup26:sta ethmmucr
; 8 retries
ldy #$08
; Wait for allocation ready
:
fixup25:lda ethist
fixup27:lda ethist
and #%00001000 ; ALLOC INT
bne :+
@ -322,25 +331,26 @@ fixup25:lda ethist
; And try again
dey
bne :-
sec
rts
; Acknowledge interrupt, is it necessary ???
: lda #%00001000
fixup26:sta ethack
fixup28:sta ethack
; Set packet address
fixup27:lda etharr
fixup28:sta ethpnr
fixup29:lda etharr
fixup30:sta ethpnr
lda #$00
ldx #%01000000 ; AUTO INCR.
fixup29:sta ethptr
fixup30:stx ethptr+1
fixup31:sta ethptr
fixup32:stx ethptr+1
; Status written by CSMA
lda #$00
fixup31:sta ethdata
fixup32:sta ethdata
fixup33:sta ethdata
fixup34:sta ethdata
; Check packet length parity:
; - Even packet length -> carry set -> add 6 bytes
@ -352,10 +362,10 @@ fixup32:sta ethdata
; The packet contains 3 extra words
lda len
adc #$05 ; Actually 5 or 6 depending on carry
fixup33:sta ethdata
fixup35:sta ethdata
lda len+1
adc #$00
fixup34:sta ethdata
fixup36:sta ethdata
; Send the packet
; ---------------
@ -363,7 +373,7 @@ fixup34:sta ethdata
; Write bytes from buffer
jsr adjustptr
: lda (ptr),y
fixup35:sta ethdata
fixup37:sta ethdata
iny
bne :-
inc ptr+1
@ -381,13 +391,14 @@ fixup35:sta ethdata
; No
: lda #$00
fixup36:sta ethdata ; Fill byte
fixup38:sta ethdata ; Fill byte
:
fixup37:sta ethdata ; Control byte
fixup39:sta ethdata ; Control byte
; Add packet to FIFO
lda #%11000000 ; ENQUEUE PACKET - transmit packet
fixup38:sta ethmmucr
fixup40:sta ethmmucr
clc
rts
;---------------------------------------------------------------------

View File

@ -48,10 +48,10 @@ bufaddr:.res 2 ; Address
bufsize:.res 2 ; Size
; Jump table.
.addr init
.addr poll
.addr send
.addr exit
jmp init
jmp poll
jmp send
jmp exit
;---------------------------------------------------------------------
@ -96,7 +96,8 @@ fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03
.byte fixup17-fixup16, fixup18-fixup17, fixup19-fixup18
.byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21
.byte fixup23-fixup22, fixup24-fixup23, fixup25-fixup24
.byte fixup26-fixup25
.byte fixup26-fixup25, fixup27-fixup26, fixup28-fixup27
.byte fixup29-fixup28, fixup30-fixup29
fixups = * - fixup
@ -144,23 +145,40 @@ init:
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
fixup01:sta mode
fixup05:sta mode
:
fixup02:lda mode
fixup06:lda mode
bmi :-
; Indirect Bus I/F mode, Address Auto-Increment, Ping Block
lda #$13
fixup03:sta mode
fixup07:sta mode
; Source Hardware Address Register: MAC Address
ldx #$00 ; Hibyte
ldy #$09 ; Lobyte
jsr set_addr
: lda mac,x
fixup04:sta data
fixup08:sta data
inx
cpx #$06
bcc :-
@ -171,17 +189,20 @@ fixup04:sta data
ldy #$1A ; Lobyte
jsr set_addr
lda #$03
fixup05:sta data
fixup06:sta data
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
fixup07:sta data
fixup11:sta data
lda #$01
fixup08:sta data
fixup12:sta data
tya
tax
clc
rts
;---------------------------------------------------------------------
@ -190,19 +211,20 @@ poll:
; Check for completion of previous command
; Socket 0 Command Register: = 0 ?
jsr set_addrcmdreg0
fixup09:lda data
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
fixup10:lda data ; Hibyte
fixup11:ora data ; Lobyte
fixup14:lda data ; Hibyte
fixup15:ora data ; Lobyte
beq :--
; Process the incoming data
@ -268,17 +290,18 @@ common: jsr set_addrsocket0
tax
lda reg+1
adc adv+1
fixup12:sta data ; Hibyte
fixup13:stx data ; Lobyte
fixup16:sta data ; Hibyte
fixup17:stx data ; Lobyte
; Set command register
tya ; Restore command
jsr set_addrcmdreg0
fixup14:sta data
fixup18:sta data
; Return data length (will be ignored for send)
lda len
ldx len+1
clc
rts
;---------------------------------------------------------------------
@ -300,14 +323,14 @@ send:
; Wait for completion of previous command
; Socket 0 Command Register: = 0 ?
: jsr set_addrcmdreg0
fixup15:lda data
fixup19:lda data
bne :-
; Socket 0 TX Free Size Register: < length ?
: ldy #$20 ; Socket TX Free Size Register
jsr set_addrsocket0
fixup16:lda data ; Hibyte
fixup17:ldx data ; Lobyte
fixup20:lda data ; Hibyte
fixup21:ldx data ; Lobyte
cpx len
sbc len+1
bcc :-
@ -337,16 +360,16 @@ exit:
;---------------------------------------------------------------------
set_addrphysical:
fixup18:lda data ; Hibyte
fixup19:ldy data ; Lobyte
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:
fixup20:stx addr ; Hibyte
fixup21:sty addr+1 ; Lobyte
fixup24:stx addr ; Hibyte
fixup25:sty addr+1 ; Lobyte
rts
set_addrcmdreg0:
@ -361,7 +384,7 @@ set_addrbase:
beq set_addr ; Always
get_datacheckaddr:
fixup22:lda data
fixup26:lda data
iny ; Physical address shadow (lobyte)
bne :+
inx ; Physical address shadow (hibyte)
@ -402,10 +425,10 @@ mov_data:
; R/W without address wraparound possible because
; highest R/W address > actual R/W address ?
; sec
fixup23:sbc addr+1 ; Lobyte
fixup27:sbc addr+1 ; Lobyte
tay
txa
fixup24:sbc addr ; Hibyte
fixup28:sbc addr ; Hibyte
tax
tya
bcs :+
@ -466,7 +489,7 @@ rw_data:eor #$FF ; Two's complement part 1
; Read data
:
fixup25:lda data
fixup29:lda data
sta (ptr),y
iny
bne :-
@ -477,7 +500,7 @@ fixup25:lda data
; Write data
: lda (ptr),y
fixup26:sta data
fixup30:sta data
iny
bne :-
inc ptr+1