******************************** * * Initialize SD card * ******************************** XC 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 :INY INC $45 ; inc msb on page boundary :INY 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 :INY INC $45 ; inc msb on page boundary :INY INY BNE :LOOPY DEX BNE :LOOPX LDY #2 ; send 2 dummy crc bytes :CRC STA DATA :WAIT5 BIT CTRL BPL :WAIT5 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 HEX 400000000095 CMD1 HEX 4100000000F9 CMD8 HEX 48000001AA87 CMD16 HEX 5000000200FF CMD55 HEX 770000000065 ACMD41_40 HEX 694000000077 ACMD41_0 HEX 6900000000FF DRIVEND = *