The copy loop wrote each byte with STA RRNET_RX_TX_DATA,X, and an indexed store reads its address first. Reads of RxTxData take the bytes of a received frame (AN181), so on a real CS8900A each byte sent took one of a frame the program had started reading. The loop now stores to the port's low or high byte by address, as ip65's and Contiki's drivers do; reads stay indexed, which read once.
304 lines
5.9 KiB
ArmAsm
304 lines
5.9 KiB
ArmAsm
;; #LAYOUT# STD * #TAKE
|
|
;; #LAYOUT# * * #IGNORE
|
|
|
|
;
|
|
; The network entries of the Arnitech jump table (mc64 only, arnitech's ADR 0027): whole
|
|
; Ethernet frames through the CS8900A at the RR-Net socket, polled, from the Destination
|
|
; Address to the end of the data, without the CRC. The chip is found by its Product ID, so
|
|
; the routines find an RR-Net on any C64 that has one. Register semantics are the CS8900A
|
|
; datasheet's (Cirrus Logic DS271F5) and its 8-bit mode's (AN181).
|
|
;
|
|
; SAL holds the pointer to the frame or buffer, EAL the bytes left, as LOAD and SAVE use them.
|
|
;
|
|
|
|
!ifdef CONFIG_ARNITECH_CONTROLLER {
|
|
|
|
; PacketPage addresses, all but the Product ID's in page $01
|
|
CS_PRODUCT_ID = $630E ; at $0000, low byte first
|
|
CS_RX_CFG = $02 ; bit 6 Skip_1
|
|
CS_RX_CTL = $04
|
|
CS_LINE_CTL = $12
|
|
CS_SELF_CTL = $14 ; bit 6 RESET
|
|
CS_RX_EVENT = $24 ; bit 8 RxOK
|
|
CS_SELF_ST = $36 ; bit 7 INITD
|
|
CS_BUS_ST = $38 ; bit 7 TxBidErr, bit 8 Rdy4TxNOW
|
|
CS_IA = $58 ; Individual Address, $0158-$015D
|
|
|
|
CS_RX_CTL_VALUE = $0D05 ; RxOKA, IndividualA, BroadcastA
|
|
CS_LINE_VALUE = $00D3 ; SerRxON, SerTxON
|
|
CS_TX_AFTER_ALL = $C0 ; TxCMD: start once the whole frame is in the chip
|
|
|
|
NET_NONE_WAITING = $00
|
|
NET_NO_CARD = $01
|
|
NET_NO_ROOM = $02
|
|
NET_LENGTH_REFUSED = $03
|
|
NET_TOO_LONG = $04
|
|
|
|
;
|
|
; NET_INIT, $FF0C: see ff00.arnitech_jumptable.s
|
|
;
|
|
|
|
arnitech_net_init:
|
|
|
|
jsr arnitech_net_probe
|
|
bcs @2
|
|
|
|
lda #CS_SELF_CTL
|
|
jsr arnitech_net_point
|
|
lda #$40 ; RESET, which points the PacketPage pointer at $0000
|
|
sta RRNET_PP_DATA
|
|
|
|
lda #CS_SELF_ST
|
|
jsr arnitech_net_point
|
|
@1:
|
|
lda RRNET_PP_DATA
|
|
bpl @1 ; until INITD
|
|
|
|
+phy_trash_a
|
|
lda #CS_RX_CTL
|
|
ldx #<CS_RX_CTL_VALUE
|
|
ldy #>CS_RX_CTL_VALUE
|
|
jsr arnitech_net_write
|
|
lda #CS_LINE_CTL
|
|
ldx #<CS_LINE_VALUE
|
|
ldy #>CS_LINE_VALUE
|
|
jsr arnitech_net_write
|
|
+ply_trash_a
|
|
|
|
clc
|
|
@2:
|
|
rts
|
|
|
|
;
|
|
; NET_MAC, $FF0F: see ff00.arnitech_jumptable.s
|
|
;
|
|
|
|
arnitech_net_mac:
|
|
|
|
stx SAL+0
|
|
sty SAL+1
|
|
jsr arnitech_net_probe
|
|
bcs @2
|
|
|
|
ldy #$00
|
|
@1:
|
|
tya
|
|
ora #CS_IA ; $58, $5A, $5C
|
|
jsr arnitech_net_point
|
|
lda RRNET_PP_DATA+0
|
|
sta (SAL), y
|
|
iny
|
|
lda RRNET_PP_DATA+1
|
|
sta (SAL), y
|
|
iny
|
|
cpy #$06
|
|
bne @1
|
|
|
|
clc
|
|
@2:
|
|
rts
|
|
|
|
;
|
|
; NET_SEND, $FF12: see ff00.arnitech_jumptable.s
|
|
;
|
|
|
|
arnitech_net_send:
|
|
|
|
jsr arnitech_net_args
|
|
lda #NET_NO_CARD
|
|
bcs arnitech_net_done
|
|
|
|
lda #CS_TX_AFTER_ALL ; TxCMD, which the high byte's write gives the chip
|
|
sta RRNET_TX_CMD+0
|
|
lda #$00
|
|
sta RRNET_TX_CMD+1
|
|
lda EAL+0 ; TxLength: the bid, at the high byte's write
|
|
sta RRNET_TX_LENGTH+0
|
|
lda EAL+1
|
|
sta RRNET_TX_LENGTH+1
|
|
|
|
lda #CS_BUS_ST
|
|
jsr arnitech_net_point
|
|
lda RRNET_PP_DATA+0
|
|
bmi @1 ; TxBidErr
|
|
lda RRNET_PP_DATA+1
|
|
lsr ; Rdy4TxNOW into carry
|
|
lda #NET_NO_ROOM
|
|
bcc arnitech_net_fail
|
|
|
|
clv ; memory to chip
|
|
jmp arnitech_net_copy ; carry clear
|
|
@1:
|
|
lda #NET_LENGTH_REFUSED
|
|
|
|
; FALLTROUGH
|
|
|
|
arnitech_net_fail:
|
|
|
|
sec
|
|
|
|
; FALLTROUGH
|
|
|
|
arnitech_net_done:
|
|
|
|
rts
|
|
|
|
;
|
|
; NET_RECV, $FF15: see ff00.arnitech_jumptable.s
|
|
;
|
|
|
|
arnitech_net_recv:
|
|
|
|
jsr arnitech_net_args
|
|
lda #NET_NO_CARD
|
|
bcs arnitech_net_done
|
|
|
|
lda #CS_RX_EVENT
|
|
jsr arnitech_net_point
|
|
lda RRNET_PP_DATA+1 ; reading the event clears it
|
|
lsr ; RxOK into carry
|
|
lda #NET_NONE_WAITING
|
|
bcc arnitech_net_fail
|
|
|
|
lda RRNET_RX_TX_DATA+1 ; RxStatus, high byte first, not needed
|
|
lda RRNET_RX_TX_DATA+0
|
|
ldx RRNET_RX_TX_DATA+1 ; RxLength, high byte first
|
|
lda RRNET_RX_TX_DATA+0
|
|
|
|
cpx EAL+1
|
|
bne @1
|
|
cmp EAL+0
|
|
beq @2
|
|
@1:
|
|
bcs @3 ; longer than the buffer
|
|
@2:
|
|
sta EAL+0
|
|
stx EAL+1
|
|
pha
|
|
txa
|
|
pha
|
|
bit arnitech_net_copy_end ; an RTS, $60: sets V, chip to memory
|
|
jsr arnitech_net_copy
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
clc
|
|
rts
|
|
@3:
|
|
lda #CS_RX_CFG
|
|
jsr arnitech_net_point
|
|
lda RRNET_PP_DATA+0
|
|
ora #$40 ; Skip_1: the frame is dropped
|
|
sta RRNET_PP_DATA+0
|
|
lda #NET_TOO_LONG
|
|
bne arnitech_net_fail ; branch always
|
|
|
|
;
|
|
; The pointer from the zero page address in A into SAL, the length in X/Y into EAL, and the
|
|
; chip probed. Out: carry clear if it answers.
|
|
;
|
|
|
|
arnitech_net_args:
|
|
|
|
stx EAL+0
|
|
sty EAL+1
|
|
tax
|
|
lda $00, x
|
|
sta SAL+0
|
|
lda $01, x
|
|
sta SAL+1
|
|
|
|
; FALLTROUGH
|
|
|
|
;
|
|
; Whether the chip answers: its Product ID at PacketPage $0000. Out: carry clear if it does.
|
|
; X and Y are kept.
|
|
;
|
|
|
|
arnitech_net_probe:
|
|
|
|
lda #$00
|
|
sta RRNET_PP_POINTER+0
|
|
sta RRNET_PP_POINTER+1
|
|
lda RRNET_PP_DATA+0
|
|
cmp #<CS_PRODUCT_ID
|
|
bne @1
|
|
lda RRNET_PP_DATA+1
|
|
cmp #>CS_PRODUCT_ID
|
|
bne @1
|
|
clc
|
|
rts
|
|
@1:
|
|
sec
|
|
rts
|
|
|
|
;
|
|
; PacketPage register $01xx, xx in A, written with X (low byte) and Y (high byte)
|
|
;
|
|
|
|
arnitech_net_write:
|
|
|
|
jsr arnitech_net_point
|
|
stx RRNET_PP_DATA+0
|
|
sty RRNET_PP_DATA+1
|
|
rts
|
|
|
|
;
|
|
; The PacketPage pointer at $01xx, xx in A. X and Y are kept.
|
|
;
|
|
|
|
arnitech_net_point:
|
|
|
|
sta RRNET_PP_POINTER+0
|
|
lda #$01
|
|
sta RRNET_PP_POINTER+1
|
|
rts
|
|
|
|
;
|
|
; EAL bytes between the chip's receive and transmit data port and SAL: from the chip with V
|
|
; set, to it with V clear. Even bytes go through the port's low byte, odd ones through its
|
|
; high byte. Out: carry clear.
|
|
;
|
|
|
|
arnitech_net_copy:
|
|
|
|
ldy #$00
|
|
@1:
|
|
lda EAL+0
|
|
ora EAL+1
|
|
beq @4
|
|
tya
|
|
and #$01
|
|
tax
|
|
bvs @2
|
|
lda (SAL), y
|
|
cpx #$01 ; plain stores: an indexed one reads the port
|
|
beq @7 ; first, which takes a byte of a received frame
|
|
sta RRNET_RX_TX_DATA+0
|
|
bvc @3 ; branch always
|
|
@7:
|
|
sta RRNET_RX_TX_DATA+1
|
|
bvc @3 ; branch always
|
|
@2:
|
|
lda RRNET_RX_TX_DATA, x
|
|
sta (SAL), y
|
|
@3:
|
|
iny
|
|
bne @5
|
|
inc SAL+1
|
|
@5:
|
|
lda EAL+0
|
|
bne @6
|
|
dec EAL+1
|
|
@6:
|
|
dec EAL+0
|
|
jmp @1
|
|
@4:
|
|
clc
|
|
|
|
arnitech_net_copy_end:
|
|
|
|
rts
|
|
}
|