;******************************* ; ; Initialize SD card ; ;******************************* .PC02 ORG $C800 SLOT16 = $2B ; s0 -> slot * 16 CURSLOT = $07F8 ; Cs DATA = $C0C0 ; slot 4 CTRL = DATA+1 DIV = DATA+2 SS = DATA+3 R30 = $0478 R31 = $04F8 R32 = $0578 R33 = $05F8 CMDLO = $FA CMDHI = $FB WORK = $3C FROM = $FA ; + $fb TO = $FC ; + $fd SIZE = $FE ; + $ff SSNONE = $0F SS0 = $0E TC = $80 DUMMY = $FF ;******************************* ; ; Install SD card driver ; ;******************************* ; signature bytes ldx #$20 ldy #$00 ldx #$03 stx WORK ; find slot nr jsr $FF58 tsx lda $0100,X and #$0F ora #$C0 sta CURSLOT ; $Cs asl A asl A asl A asl A sta SLOT16 ; $s0 bit $CFFF jsr INIT: ; ; TODO: check for init error ; ; see if slot has a driver already INSTALL: ldx $BF31 ; get devcnt INSLP: lda $BF32,X ; get a devnum and #$70 ; isolate slot cmp SLOT16 ; slot? beq INSOUT: ; yes, skip it dex bpl INSLP: ; keep up the search ; restore the devnum to the list ldx $BF31 ; get devcnt again cpx #$0D ; device table full? bne INSLP2: ERROR: jmp INSOUT: ; do something! INSLP2: lda $BF32-1,X ; move all entries down sta $BF32,X ; to make room at front dex ; for a new entry bne INSLP2: lda #$04 ; ProFile type device ora SLOT16 sta $BF32 ; slot, drive 1 at top of list inc $BF31 ; update devcnt ; now insert the device driver vector lda CURSLOT and #$0F txa lda #CMD0 sta CMDHI jsr CMD jsr GETR1: ; get response cmp #$01 bne ERROR1: ; error! lda #CMD8 sta CMDHI jsr CMD jsr GETR3: cmp #$01 bne SDV1: ; may be SD Ver. 1 ; check for $01aa match! SDV2: lda #CMD55 sta CMDHI jsr CMD jsr GETR1: lda #ACMD41_40 sta CMDHI jsr CMD jsr GETR1: cmp #$01 beq SDV2: ; wait for ready cmp #$00 bne ERROR1: ; error! ; send CMD58 ; SD Ver. 2 initialized! jmp BLOCKSZ: ERROR1: jmp IOERROR: ; needed for far jump SDV1: lda #CMD55 sta CMDHI jsr CMD ; ignore response lda #ACMD41_0 sta CMDHI jsr CMD jsr GETR1: cmp #$01 beq SDV1: ; wait for ready cmp #$00 bne MMC: ; may be MMC card ; SD Ver. 1 initialized! jmp BLOCKSZ: MMC: lda #CMD1 sta CMDHI @LOOP: jsr CMD jsr GETR1: cmp #$01 beq @LOOP: ; wait for ready cmp #$00 bne IOERROR: ; error! ; MMC Ver. 3 initialized! BLOCKSZ: lda #CMD16 sta CMDHI jsr CMD jsr GETR1: cmp #$00 bne IOERROR: ; error! END: clc ; all ok ldy #0 bcc END1: CDERROR: sec ldy #$28 ; no card error bcs END1: IOERROR: sec ldy #$27 ; init error END1: lda #SSNONE ; deselect card sta SS lda #0 sta DIV tya ; retval in A rts ;******************************* ; ; Send SD command ; Call with command in CMDHI and CMDLO ; ;******************************* CMD: ldy #0 @LOOP: lda (CMDLO),Y sta DATA @WAIT: bit CTRL ; TC is in N bpl @WAIT: iny cpy #6 bcc @LOOP: rts ;******************************* ; ; Get R1 ; R1 is in A ; ;******************************* GETR1: lda #DUMMY sta DATA @WAIT: bit CTRL bpl @WAIT: lda DATA ; get response sta R30+SLOT ; save R1 and #$80 bne GETR1: ; wait for MSB=0 lda #DUMMY sta DATA ; send another dummy lda R30+SLOT ; restore R1 rts ;******************************* ; ; Get R3 ; R1 is in A ; R3 is in scratchpad ram ; ;******************************* GETR3: jsr GETR1: ; get R1 first pha ; save R1 phy ; save Y ldy #04 @LOOP: lda #DUMMY ; send dummy sta DATA @WAIT: bit CTRL bpl @WAIT: lda DATA pha dey bne @LOOP: ; do 4 times pla sta R33+SLOT ; save R3 pla sta R32+SLOT pla sta R31+SLOT pla sta R30+SLOT ply ; restore Y lda #DUMMY sta DATA ; send another dummy pla ; restore R1 rts ;******************************* ; ; Status request ; $43 Unt number DSSS000 ; $44-45 Unused ; $46-47 Unused ; ; C Clear - No error ; Set - Error ; A $00 - No error ; $27 - I/O error ; $28 - No card inserted / no init ; $2B - Card write protected ; X - Blocks avail (low byte) ; Y - Blocks avail (high byte) ; ;******************************* STATUS: clc ; no error lda #0 ldx #$FF ; 32 MB partition ldy #$FF rts ; ; TODO: check for card detect and write protect! ; ;******************************* ; ; Read 512 byte block ; $43 Unit number DSSS0000 ; $44-45 Address (LO/HI) of buffer ; $46-47 Block number (LO/HI) ; ; C Clear - No error ; Set - Error ; A $00 - No error ; $27 - Bad block number ; $28 - No card inserted ; ;******************************* ; ; TODO: check for card detect! ; READ: lda #SS0 ; enable /CS sta SS lda $46 ; store block num sta R33+SLOT ; in R30-R33 lda $47 sta R32+SLOT stz R31+SLOT stz R30+SLOT ldy #9 @LOOP: asl R33+SLOT ; mul block num rol R32+SLOT ; by 512 to get rol R31+SLOT ; real address rol R30+SLOT dey bne @LOOP: lda #$51 ; send CMD17 sta DATA @WAIT: bit CTRL bpl @WAIT: @ARG: lda R30+SLOT ; get arg from R30 on sta DATA @WAIT1: bit CTRL bpl @WAIT1: lda R31+SLOT sta DATA @WAIT11: bit CTRL bpl @WAIT11: lda R32+SLOT sta DATA @WAIT12: bit CTRL bpl @WAIT12: lda R33+SLOT sta DATA @WAIT13: bit CTRL bpl @WAIT13: lda #DUMMY sta DATA ; dummy crc @WAIT2: bit CTRL bpl @WAIT2: @GETR1: lda #DUMMY sta DATA ; get R1 @WAIT3: bit CTRL bpl @WAIT3: lda DATA ; get response ; ; TODO: check for error! ; cmp #$FE bne @GETR1: ; wait for $FE ldx #2 ; read data from card @LOOPX: ldy #0 @LOOPY: lda #DUMMY sta DATA @WAIT4: bit CTRL bpl @WAIT4: lda DATA sta ($44) inc $44 bne @INCY: inc $45 ; inc msb on page boundary @INCY: iny bne @LOOPY: dex bne @LOOPX: @OK: jsr GETR3: ; read 2 bytes crc lda #SSNONE sta SS ; disable /CS clc ; no error lda #$00 rts :ERROR: lda #SSNONE sta SS ; disable /CS sec ; an error occured lda #$27 rts ;******************************* ; ; Write 512 byte block ; $43 Unit number DSSS000 ; $44-45 Address (LO/HI) of buffer ; $46-47 Block number (LO/HI) ; ; C Clear - No error ; Set - Error ; A $00 - No error ; $27 - Bad block number ; $28 - No card inserted ; ;******************************* ; ; TODO: check for card detect and write protect! ; WRITE: lda #SS0 ; enable /CS sta SS lda $46 ; store block num sta R33+SLOT lda $47 sta R32+SLOT stz R31+SLOT stz R30+SLOT ldy #9 @LOOP: asl R33+SLOT ; mul block num rol R32+SLOT ; by 512 to get rol R31+SLOT ; real address rol R30+SLOT dey bne @LOOP: lda #$58 ; send CMD24 sta DATA @WAIT: bit CTRL bpl @WAIT: @ARG: lda R30+SLOT ; get arg from R30 on sta DATA @WAIT1: bit CTRL bpl @WAIT1: lda R31+SLOT sta DATA @WAIT11: bit CTRL bpl @WAIT11: lda R32+SLOT sta DATA @WAIT12: bit CTRL bpl @WAIT12: lda R33+SLOT sta DATA @WAIT13: bit CTRL bpl @WAIT13: lda #DUMMY sta DATA ; dummy crc @WAIT2: bit CTRL bpl @WAIT2: @GETR1: lda #DUMMY sta DATA ; get R1 @WAIT3: bit CTRL bpl @WAIT3: lda DATA ; get response ; ; TODO: check for error! ; cmp #$FE bne @GETR1: ; wait for $FE ldx #2 ; send data to card @LOOPX: ldy #0 @LOOPY: lda ($44) sta DATA @WAIT4: bit CTRL bpl @WAIT4: inc $44 bne @INCY: inc $45 ; inc msb on page boundary @INCY: iny bne @LOOPY: dex bne @LOOPX: ldy #2 ; send 2 dummy crc bytes @CRC: sta DATA @WAIT:5 bit CTRL bpl @WAIT:5 dey bne @CRC: @OK: lda #SSNONE ; disable /CS sta SS clc ; no error lda #0 rts ;******************************* ; ; Format ; not supported! ; ;******************************* FORMAT: sec lda #$01 ; invalid command rts CMD0 .byte $400000000095 CMD1 .byte $4100000000F9 CMD8 .byte $48000001AA87 CMD16 .byte $5000000200FF CMD55 .byte $770000000065 ACMD41_40 .byte $694000000077 ACMD41_0 .byte $6900000000FF DRIVEND = *