;;; ;;; MCFS2 flash card storage driver ;;; By: Daniel Tufvesson 2017-2022 ;;; ;;; Provides three external functions: ;;; fc_init - initializes storage ;;; fc_read_sector - read one sector from storage ;;; fc_write_sector - write one sector to storage ;;; ;;; ;;; CF registers ;;; cf_base: equ $9fd0 cf_reg_0: equ cf_base+0 ; data port cf_reg_1: equ cf_base+1 ; read: error code, write: feature cf_reg_2: equ cf_base+2 ; number of sectors to transfer cf_reg_3: equ cf_base+3 ; sector address LBA 0 [0:7] cf_reg_4: equ cf_base+4 ; sector address LBA 1 [8:15] cf_reg_5: equ cf_base+5 ; sector address LBA 2 [16:23] cf_reg_6: equ cf_base+6 ; sector address LBA 3 [24:27 (LSB of reg)] cf_reg_7: equ cf_base+7 ; read: status, write: command ;;; ;;; CF commands ;;; cf_cmd_reset: equ $04 *cf_cmd_id: equ $ec cf_cmd_read: equ $20 cf_cmd_write: equ $30 ;;; ;;; Read sector at media_addr_[3:0] store at X ;;; Z set on OK read. Error code in A ;;; fc_read_sector: jsr cf_wait_for_busy_clr jsr cf_wait_for_ready_set jsr cf_set_lba ldaa #1 staa cf_reg_2 ; number of sectors to read ldaa #cf_cmd_read staa cf_reg_7 ; issue read command jmp cf_read_data ; read data routine rts ;;; ;;; Write sector at media_addr_[3:0] stored at X ;;; Z set on OK write. Error code in A ;;; fc_write_sector: jsr cf_wait_for_busy_clr jsr cf_wait_for_ready_set jsr cf_set_lba ldaa #1 staa cf_reg_2 ; number of sectors to write ldaa #cf_cmd_write staa cf_reg_7 ; issue write command jmp cf_write_data ; write data routine rts ;;; ;;; Initialize storage ;;; Z set on OK init. Error code in A ;;; fc_init: jsr cf_init jsr cf_check_error rts ;;; ;;; Initialize CF ;;; cf_init: ldaa #cf_cmd_reset ; reset command staa cf_reg_7 jsr cf_wait_for_busy_clr jsr cf_wait_for_ready_set ldaa #$e0 ; LBA3=0, MASTER, MODE=LBA staa cf_reg_6 ldaa #$01 ; 8-bit transfers staa cf_reg_1 ldaa #$ef ; set-feature command staa cf_reg_7 jsr cf_wait_for_busy_clr rts ;;; ;;; Wait for CF BUSY flag clear ;;; cf_wait_for_busy_clr: ldaa cf_reg_7 bita #$80 ; check BUSY bit bne cf_wait_for_busy_clr rts ;;; ;;; Wait for CF READY flag set ;;; cf_wait_for_ready_set: ldaa cf_reg_7 bita #$40 ; check READY bit beq cf_wait_for_ready_set rts ;;; ;;; Check for CF error ;;; Z set on OK ;;; Error code in A ;;; bit 7 - Bad block detected ;;; bit 6 - Uncorrectable data error ;;; bit 5 - Media changed ;;; bit 4 - ID not found ;;; bit 3 - Aborted command ;;; bit 2 - Media change requested ;;; bit 1 - Track 0 not found ;;; bit 0 - Addressmask not found ;;; cf_check_error: ldaa cf_reg_7 bita #$01 ; mask out ERROR bit beq cf_no_error ldaa cf_reg_1 rts cf_no_error: clra rts ;;; ;;; CF set LBA ;;; cf_set_lba: ldaa media_addr_0 ; LBA byte 0 staa cf_reg_3 ldaa media_addr_1 ; LBA byte 1 staa cf_reg_4 ldaa media_addr_2 ; LBA byte 2 staa cf_reg_5 ldaa media_addr_3 ; LBA byte 3 anda #%00001111 ; mask out LBA bits oraa #%11100000 ; set mode LBA and master device staa cf_reg_6 rts ;;; ;;; Read data from CF ;;; Z set on OK ;;; error code in A ;;; cf_read_data: jsr cf_wait_for_busy_clr ldaa cf_reg_7 bita #$08 ; check DRQ flag beq cf_read_data_e ldaa cf_reg_0 ; read data byte staa ,x inx jsr cf_check_error beq cf_read_data rts cf_read_data_e: clra rts ;;; ;;; Write data to CF ;;; Z set on OK ;;; error code in A ;;; cf_write_data: jsr cf_wait_for_busy_clr ldaa cf_reg_7 bita #$08 ; check DRQ flag beq cf_write_data_e ldaa ,x staa cf_reg_0 ; write data byte inx jsr cf_check_error beq cf_write_data rts cf_write_data_e: clra rts