feat(arnitech): network entries NET_INIT, NET_MAC, NET_SEND, NET_RECV at $FF0C-$FF15
Version 2 of the Arnitech jump table, with 6 entries: whole Ethernet frames through the CS8900A at the RR-Net socket (arnitech's ADR 0027), found by its Product ID and polled, from the CS8900A datasheet's PacketPage registers and its 8-bit mode. NET_INIT resets the chip and turns on receiving its own and broadcast frames and sending; NET_MAC copies the Individual Address; NET_SEND bids and writes a frame; NET_RECV copies the oldest frame received, or drops one longer than the buffer with Skip_1. Carry is the result, with an error code in A, and the pointer and count go in SAL and EAL.
This commit is contained in:
1 parent
aa39286d9d
commit
1aaed55bc7
3 files changed
+347
-4
No files matched your search
@@ -23,4 +23,13 @@
|
||||
!addr ARNITECH_CLOCK_HRS = $DE94 ; hours, BCD 1-12, bit 7 PM
|
||||
|
||||
!addr ARNITECH_CARD_WINDOW = $DEA0 ; slot n's Card window at $DEA0 + 16 * n
|
||||
|
||||
; The RR-Net socket: the CS8900A of the Network Card in the lowest slot, in RR-Net order
|
||||
; (arnitech's ADR 0027; Cirrus Logic DS271F5 Table 18, each port's even byte the low one)
|
||||
|
||||
!addr RRNET_PP_POINTER = $DE02 ; PacketPage pointer
|
||||
!addr RRNET_PP_DATA = $DE04 ; PacketPage data port 0
|
||||
!addr RRNET_RX_TX_DATA = $DE08 ; receive and transmit data port 0
|
||||
!addr RRNET_TX_CMD = $DE0C ; write-only
|
||||
!addr RRNET_TX_LENGTH = $DE0E ; write-only
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
;; #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
|
||||
sta RRNET_RX_TX_DATA, x
|
||||
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
|
||||
}
|
||||
@@ -9,11 +9,12 @@
|
||||
; stay clear, for the stock IRQ entry, CINT, and the KERNAL revision byte.
|
||||
;
|
||||
; $FF00-$FF03 "ARNI"
|
||||
; $FF04 version of the table, $01
|
||||
; $FF04 version of the table, $02
|
||||
; $FF05 number of entries
|
||||
;
|
||||
; $FF06 ARNI_FINDCARD - finds the first Card slot holding a Card of a given type
|
||||
; In: A = the Card's type ($01 Redstone Card, $02 Internet Card; $00 finds an empty slot)
|
||||
; In: A = the Card's type ($01 Redstone Card, $02 Internet Card, $03 Network Card;
|
||||
; $00 finds an empty slot)
|
||||
; Out: carry clear if found: A = the slot (0-5), X = the low byte of its Card window
|
||||
; ($DEA0 + 16 * slot, so LDA $DE00,X reads the window's first byte);
|
||||
; carry set if no slot holds one, or no controller answers (a Cartridge switched it off)
|
||||
@@ -26,15 +27,50 @@
|
||||
; untouched but on 50 Hz all the same
|
||||
; A and X are not kept, Y is
|
||||
;
|
||||
; Version 2 adds the network: whole Ethernet frames, from the Destination Address to the end of
|
||||
; the data without the CRC, through the CS8900A at the RR-Net socket (arnitech's ADR 0027),
|
||||
; found by its Product ID. Software polls; ARP and IP are its own.
|
||||
;
|
||||
; $FF0C NET_INIT - resets the chip and sets it to receive frames for its own address and
|
||||
; broadcasts, and to send
|
||||
; In: nothing
|
||||
; Out: carry clear if done; carry set if there is no Network Card
|
||||
; A and X are not kept, Y is
|
||||
;
|
||||
; $FF0F NET_MAC - copies the MAC address: the chip's Individual Address, which a reset sets to
|
||||
; the Network Card's
|
||||
; In: X/Y = the address of 6 bytes for it, low byte in X
|
||||
; Out: carry clear if copied; carry set if there is no Network Card
|
||||
; A, X, and Y are not kept
|
||||
;
|
||||
; $FF12 NET_SEND - sends a frame
|
||||
; In: A = a zero page address holding a pointer to the frame,
|
||||
; X/Y = its length, 14-1514, low byte in X; the chip pads one under 60 bytes
|
||||
; Out: carry clear if sent; carry set if not, with A = 1 no Network Card, 2 no room in
|
||||
; the chip while it holds frames received, 3 the chip refuses the length
|
||||
; A, X, and Y are not kept
|
||||
;
|
||||
; $FF15 NET_RECV - takes the oldest frame received
|
||||
; In: A = a zero page address holding a pointer to a buffer,
|
||||
; X/Y = its length, low byte in X
|
||||
; Out: carry clear if a frame was copied into the buffer, with X/Y = its length, low byte
|
||||
; in X; carry set if not, with A = 0 none waiting, 1 no Network Card, 4 the frame is
|
||||
; longer than the buffer, and is dropped
|
||||
; A is not kept when a frame is copied
|
||||
;
|
||||
|
||||
!ifdef CONFIG_ARNITECH_CONTROLLER {
|
||||
|
||||
arnitech_jumptable:
|
||||
|
||||
!byte $41, $52, $4E, $49 ; "ARNI"
|
||||
!byte $01 ; version
|
||||
!byte $02 ; entries
|
||||
!byte $02 ; version
|
||||
!byte $06 ; entries
|
||||
|
||||
jmp arnitech_find_card ; $FF06
|
||||
jmp arnitech_set_tod ; $FF09
|
||||
jmp arnitech_net_init ; $FF0C
|
||||
jmp arnitech_net_mac ; $FF0F
|
||||
jmp arnitech_net_send ; $FF12
|
||||
jmp arnitech_net_recv ; $FF15
|
||||
}
|
||||
Reference in new issue
Block a user