more work on SD card support

This commit is contained in:
FeralChild64 committed 2020-09-27 16:36:17 +02:00
1 parent 37c193788c
commit 5704a8d4cd
13 files changed
+429 -389

No files matched your search

+2
View File
@@ -35,6 +35,8 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \
SRCDIR_DOS_M65 = $(SRCDIR_COMMON) \
src/dos_m65 \
# src/dos_m65/cmdrdos \
src/dos_m65/sdcard
SRCDIR_KERNAL = $(SRCDIR_COMMON) \
src/kernal \
+2
View File
@@ -94,6 +94,8 @@
; --- Built-in DOS configuration
;; #CONFIG# CMDRDOS NO ; do not change, DOS is not implemented yet
;; #CONFIG# UNIT_SDCARD 0 ; do not change, DOS is not implemented yet
;; #CONFIG# UNIT_FLOPPY 0 ; do not change, DOS is not implemented yet
;; #CONFIG# UNIT_RAMDISK 0 ; do not change, DOS is not implemented yet
+13
View File
@@ -241,6 +241,13 @@
; Check that internal DOS configuration is correct
!ifdef CONFIG_CMDRDOS { !ifndef CONFIG_MB_M65 {
!error "CONFIG_CMDRDOS requires CONFIG_MB_M65"
} }
; Check that startup banner configuration is correct
!set counter = 0
@@ -415,6 +422,12 @@
; Handle non-LGPL3 code
!ifdef CONFIG_CMDRDOS { !set HAS_NOLGPL3_WARN = 1 }
; Determine if we need space-savings in BASIC code
!ifndef CONFIG_MB_M65 {
+22
View File
@@ -59,9 +59,18 @@ INITMSG_end:
jsr initmsg_bytes_free
!ifdef HAS_NOLGPL3_WARN {
lda #<str_nonlgpl3_warn
ldy #>str_nonlgpl3_warn
jmp STROUT
} else {
ldx #$09
ldy #$00
jmp plot_set
}
INITMSG_main_banner:
@@ -99,3 +108,16 @@ INITMSG_revision:
lda #<rom_revision_basic_string
ldy #>rom_revision_basic_string
jmp STROUT
!ifdef HAS_NOLGPL3_WARN {
str_nonlgpl3_warn:
!byte $0D, $0D, $0D, $0D
!pet "build contains non-lgpl3 code"
!byte $0D
!pet " *** do not distribute ***"
!byte $0D, $0D, $00
}
+2
View File
@@ -106,3 +106,5 @@ initmsg_real:
}
}
!ifdef HAS_NOLGPL3_WARN { !error "HAS_NOLGPL3_WARN not implemented"
+32 -8
View File
@@ -2,17 +2,41 @@
; Memory locations for the DOS
;
; NOTES:
; - DOS zeropage is mirrored at $8000
; - starting from $8000, 16KB RAM is available (starting from $10000 in C65 address space)
; - additional 16KB RAM is reserved for DOS too ($14000-$17FFF), and can be banked-in if needed
;
; Page 0
;
!addr MAGICSTR = $00 ; magic string; if not matching, DOS considered non-functional
!addr MAGICSTR = $00 ; magic string; if not matching, DOS considered non-functional
!addr UNIT_SDCARD = $05
!addr UNIT_FLOPPY = $06
!addr UNIT_RAMDISK = $07
; General DOS configuration
; NOTES:
; - DOS zeropage is mirrored at $8000
; - starting from $8000, 16KB RAM is available (starting from $10000 in C65 address space)
; - additional 16KB RAM is reserved for DOS too ($14000-$17FFF), and can be banked-in if needed
!addr UNIT_SDCARD = $05
!addr UNIT_FLOPPY = $06
!addr UNIT_RAMDISK = $07
; SD/SDHC card variables
!addr CARD_INIT_DONE = $08 ; $80 - init done, $00 - init not done
!addr CARD_IS_SDHC = $09 ; $00 = SD, $80 = SDHC
!addr CARD_SIZE = $0A ; 4 bytes
!addr CARD_SECNUM = $0E ; 4 bytes - sector number
!addr CARD_TMP_STEP = $12 ; 4 bytes
!addr CARD_TMP_RETRIES = $16 ; 1 byte
!addr CARD_BUFPNT = $FC ; 4 bytes - pointer to hardware sector buffer XXX replace copy routines with DMAgic
;
; High memory
;
!addr CARD_BUF = $8100 ; 512 bytes, up to $82FF - buffer for reading/writing data
+4
View File
@@ -0,0 +1,4 @@
!ifndef HAS_NOLGPL3_WARN {
!error "No LGPL3 incompatible warning issued"
}
+4 -1
View File
@@ -26,6 +26,9 @@ dos_INIT:
lda #CONFIG_UNIT_RAMDISK
sta UNIT_RAMDISK
; XXX initialize drivers, etc.
; Mark SD card as not initialized
lda #$00
sta CARD_INIT_DONE
rts
-380
View File
@@ -1,380 +0,0 @@
;
; MEGA65 SD/SDHC card support
;
; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
; Permanent values XXX addresses are temporary
!addr CARD_IS_SDHC = $80 ; $00 = SD, $80 = SDHC
!addr CARD_SIZE = $81 ; 4 bytes
!addr CARD_SECNUM = $85 ; 4 bytes - sector number
!addr CARD_BUFPNT = $89 ; 4 bytes - pointer to hardware sector buffer
; Temporary data XXX addresses are temporary
!addr TMP_STEP = $8D ; 4 bytes
!addr TMP_RETRIES = $8E ; 1 byte
!addr CARD_BUF = $8100 ; 512 bytes, up to $82FF
; External entry points:
; - m65_sdcard_init
; - m65_sdcard_readsector
m65_sdcard_init:
; Initialize most important variables
lda #$00
sta CARD_IS_SDHC
lda #SD_SECBUF_0
sta CARD_BUFPNT+0
lda #SD_SECBUF_1
sta CARD_BUFPNT+1
lda #SD_SECBUF_2
sta CARD_BUFPNT+2
lda #SD_SECBUF_3
sta CARD_BUFPNT+3
; Reset the card
jsr m65_sdcard_reset
; Try to read first sector to see if card is operable
lda #$00
sta SD_ADDR+0
sta SD_ADDR+1
sta SD_ADDR+2
sta SD_ADDR+3
jsr m65_sdcard_read
bcc m65_sdcard_init_operable
; XXX if we are here, mark card as not operable and quit
m65_sdcard_init_operable:
; Work out if this is SD or SDHC card - SD cards can't read at non-sector aligned addresses
lda #$02
sta SD_ADDR+0
lda #$00
sta SD_ADDR+1
sta SD_ADDR+2
sta SD_ADDR+3
jsr m65_sdcard_read
lda SD_CTL
beq m65_sdcard_init_sdsc
; FALLTROUGH
m65_sdcard_init_sdhc:
lda #$80
sta CARD_IS_SDHC
bra m65_sdcard_init_getsize
m65_sdcard_init_sdsc:
lda #$00
sta CARD_IS_SDHC
lda #$40 ; use byte addressing
sta SD_CTL
; FALLTROUGH
m65_sdcard_init_getsize:
; Work out size of SD card in a safe way
; (binary search of sector numbers is NOT safe for some reason.
; It frequently reports bigger than the size of the card)
lda #$00
sta CARD_SECNUM+0
sta CARD_SECNUM+1
sta CARD_SECNUM+2
sta CARD_SECNUM+3
; step = 16*2048
sta TMP_STEP+0
sta TMP_STEP+2
sta TMP_STEP+3
lda #$08
sta TMP_STEP+1
; XXX finish the implementation
; -------------------------------------
m65_sdcard_readsector: ; XXX reads sector CARD_SECNUM
; Set read address, depending on card type
bit CARD_IS_SDHC
bpl m65_sdcard_readsector_sdsc
m65_sdcard_readsector_sdhc:
lda CARD_SECNUM+0
sta SD_ADDR+0
lda CARD_SECNUM+1
sta SD_ADDR+1
lda CARD_SECNUM+2
sta SD_ADDR+2
lda CARD_SECNUM+3
sta SD_ADDR+3
bra m65_sdcard_readsector_read
m65_sdcard_readsector_sdsc: ; multiply sector number by 512
lda #$00
sta SD_ADDR+0
clc
lda CARD_SECNUM+0
rol
sta SD_ADDR+1
lda CARD_SECNUM+1
rol
sta SD_ADDR+2
lda CARD_SECNUM+2
rol
sta SD_ADDR+3
bcs m65_sdcard_readsector_fail ; branch if sector number too large for SD card
lda CARD_SECNUM+3
bne m65_sdcard_readsector_fail ; branch if sector number too large for SD card
; FALLTROUGH
m65_sdcard_readsector_read:
; Set number of retries
lda #$0A
sta TMP_RETRIES
; FALLTROUGH
m65_sdcard_readsector_try_loop:
; Wait till card is ready
jsr m65_sdcard_readsector_wait
bcs m65_sdcard_readsector_fail
; Read command
lda #$02
sta SD_CTL
; Wait for command completion
jsr m65_sdcard_readsector_wait
bcs m65_sdcard_readsector_fail
lda SD_CTL
and #$67
bne m65_sdcard_readsector_copy_data
jsr m65_sdcard_reset
dec TMP_RETRIES
bne m65_sdcard_readsector_try_loop
; FALLTROUGH
m65_sdcard_readsector_fail:
sec
rts
m65_sdcard_readsector_copy_data:
; XXX this should be a separate routine
; XXX use DMAgic for this
phz
phx
ldx #$00
ldz #$00
@RL1:
lda [CARD_BUFPNT],z
sta CARD_BUF,x
inc CARD_BUFPNT+1
lda [CARD_BUFPNT],z
sta CARD_BUF+$100,x
dec CARD_BUFPNT+1
inz
inx
bne @RL1
; Restore registers and quit
plx
plz
clc
rts
; -------------------------------------
m65_sdcard_readsector_wait:
; Wait till card is ready
lda SD_CTL
; Sometimes we see this result, i.e., sdcard.vhdl thinks it is done,
; but sdcardio.vhdl thinks not. This means a read error.
cmp #$01
beq m65_sdcard_readsector_wait_fail
tax
and #$40
bne m65_sdcard_readsector_wait_fail
txa
and #$03
bne m65_sdcard_readsector_wait
clc
rts
m65_sdcard_readsector_wait_fail:
sec
rts
; -------------------------------------
m65_sdcard_read:
; Trigger read
lda #$02
sta SD_CTL
; Wait for result
ldx #90
@1:
jsr m65_sdcard_wait_16000_usec
lda SD_CTL
and #$03
beq @2
dex
bne @1
; Read failed
sec
rts
@2:
;; Success
clc
rts
; -------------------------------------
m65_sdcard_reset:
ldx #$40
stx SD_CTL
ldy #$00
sty SD_CTL
iny ; $01
sty SD_CTL
; Wait till SD card resets
@3:
lda SD_CTL
and #$03
bne @3
; For SDHC card set appropriate mode
bit CARD_IS_SDHC
bpl @4
inx ; $41
stx SD_CTL
@4:
rts
; -------------------------------------
m65_sdcard_wait_16000_usec:
; Uses VIC-II raster register; wait time is not exactly precise, but should be
; a good approximation
phx
pha
ldx #$FF
; XXX wait below is same as in KKERNAL, wait_x_lines - consider importing and reusing
lda VIC_RASTER
@w1:
cmp VIC_RASTER
beq @w1
lda VIC_RASTER
dex
bne @w1
pla
plx
rts
+136
View File
@@ -0,0 +1,136 @@
;
; Initialize memory card, determine it's type and size
;
; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
; XXX finish the routine
sdcard_init:
; Initialize most important variables
lda #$00
sta CARD_IS_SDHC
lda #SD_SECBUF_0
sta CARD_BUFPNT+0
lda #SD_SECBUF_1
sta CARD_BUFPNT+1
lda #SD_SECBUF_2
sta CARD_BUFPNT+2
lda #SD_SECBUF_3
sta CARD_BUFPNT+3
; Reset the card
jsr sdcard_reset
; Try to read first sector to see if card is operable
lda #$00
sta SD_ADDR+0
sta SD_ADDR+1
sta SD_ADDR+2
sta SD_ADDR+3
jsr sdcard_init_read
bcc sdcard_init_operable
; XXX if we are here, mark card as not operable and quit
sdcard_init_operable:
; Work out if this is SD or SDHC card - SD cards can't read at non-sector aligned addresses
lda #$02
sta SD_ADDR+0
lda #$00
sta SD_ADDR+1
sta SD_ADDR+2
sta SD_ADDR+3
jsr sdcard_init_read
lda SD_CTL
beq sdcard_init_sdsc
; FALLTROUGH
sdcard_init_sdhc:
lda #$80
sta CARD_IS_SDHC
bra sdcard_init_getsize
sdcard_init_sdsc:
lda #$00
sta CARD_IS_SDHC
lda #$40 ; use byte addressing
sta SD_CTL
; FALLTROUGH
sdcard_init_getsize:
; Work out size of SD card in a safe way
; (binary search of sector numbers is NOT safe for some reason.
; It frequently reports bigger than the size of the card)
lda #$00
sta CARD_SECNUM+0
sta CARD_SECNUM+1
sta CARD_SECNUM+2
sta CARD_SECNUM+3
; step = 16*2048
sta CARD_TMP_STEP+0
sta CARD_TMP_STEP+2
sta CARD_TMP_STEP+3
lda #$08
sta CARD_TMP_STEP+1
; XXX finish the implementation
;
; Helper routines
;
sdcard_init_read:
; Trigger read
lda #$02
sta SD_CTL
; Wait for result
ldx #90
@1:
jsr sdcard_wait_16000_usec
lda SD_CTL
and #$03
beq @2
dex
bne @1
; Read failed
sec
rts
@2:
;; Success
clc
rts
+154
View File
@@ -0,0 +1,154 @@
;
; Reads the sector from the SD card
;
; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
; XXX provide documentation
sdcard_readsector:
; XXX check if card initialized and operable
; Set read address, depending on card type
bit CARD_IS_SDHC
bpl sdcard_readsector_sdsc
sdcard_readsector_sdhc:
lda CARD_SECNUM+0
sta SD_ADDR+0
lda CARD_SECNUM+1
sta SD_ADDR+1
lda CARD_SECNUM+2
sta SD_ADDR+2
lda CARD_SECNUM+3
sta SD_ADDR+3
bra sdcard_readsector_read
sdcard_readsector_sdsc: ; multiply sector number by 512
lda #$00
sta SD_ADDR+0
clc
lda CARD_SECNUM+0
rol
sta SD_ADDR+1
lda CARD_SECNUM+1
rol
sta SD_ADDR+2
lda CARD_SECNUM+2
rol
sta SD_ADDR+3
bcs sdcard_readsector_fail ; branch if sector number too large for SD card
lda CARD_SECNUM+3
bne sdcard_readsector_fail ; branch if sector number too large for SD card
; FALLTROUGH
sdcard_readsector_read:
; Set number of retries
lda #$0A
sta CARD_TMP_RETRIES
; FALLTROUGH
sdcard_readsector_try_loop:
; Wait till card is ready
jsr sdcard_readsector_wait
bcs sdcard_readsector_fail
; Read command
lda #$02
sta SD_CTL
; Wait for command completion
jsr sdcard_readsector_wait
bcs sdcard_readsector_fail
lda SD_CTL
and #$67
bne sdcard_readsector_copy_data
jsr sdcard_reset
dec CARD_TMP_RETRIES
bne sdcard_readsector_try_loop
; FALLTROUGH
sdcard_readsector_fail:
sec
rts
;
; Helper routines
;
sdcard_readsector_copy_data:
; XXX this should be a separate routine
; XXX use DMAgic for this
phz
phx
ldx #$00
ldz #$00
@1:
lda [CARD_BUFPNT],z
sta CARD_BUF,x
inc CARD_BUFPNT+1
lda [CARD_BUFPNT],z
sta CARD_BUF+$100,x
dec CARD_BUFPNT+1
inz
inx
bne @1
; Restore registers and quit
plx
plz
clc
rts
sdcard_readsector_wait:
; Wait till card is ready
lda SD_CTL
; Sometimes we see this result, i.e., sdcard.vhdl thinks it is done,
; but sdcardio.vhdl thinks not. This means a read error.
cmp #$01
beq sdcard_readsector_wait_fail
tax
and #$40
bne sdcard_readsector_wait_fail
txa
and #$03
bne sdcard_readsector_wait
clc
rts
sdcard_readsector_wait_fail:
sec
rts
+32
View File
@@ -0,0 +1,32 @@
;
; Resets the SD card
;
; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
sdcard_reset:
ldx #$40
stx SD_CTL
ldy #$00
sty SD_CTL
iny ; $01
sty SD_CTL
; Wait till SD card resets
@1:
lda SD_CTL
and #$03
bne @1
; For SDHC card set appropriate mode
bit CARD_IS_SDHC
bpl @2
inx ; $41
stx SD_CTL
@2:
rts
+26
View File
@@ -0,0 +1,26 @@
sdcard_wait_16000_usec:
; Uses VIC-II raster register; wait time is not exactly precise, but should be
; a good approximation
phx
pha
ldx #$FF
; XXX wait below is same as in KKERNAL, wait_x_lines - consider importing and reusing
lda VIC_RASTER
@1:
cmp VIC_RASTER
beq @1
lda VIC_RASTER
dex
bne @1
pla
plx
rts