0001 ;;; 0002 ;;; MCFS2 Compact Flash formatter 0003 ;;; By: Daniel Tufvesson 2017 0004 ;;; 0005 0006 ;;; 0007 ;;; Monitor routines 0008 ;;; 0009 c000 mon_return: equ $C000 ; return to monitor 0010 c003 mon_outchar: equ $C003 ; outpur char in a on console 0011 c009 mon_pdata: equ $C009 ; print text string at x ended by $04 0012 c015 mon_out4hs: equ $C015 ; print 4 hex chars at x 0013 c021 mon_pcrlf: equ $C021 ; print crlf 0014 0015 0002 page_register: equ $0002 ; I/O page select register 0016 0017 ;;; 0018 ;;; CF registers 0019 ;;; 0020 9fd0 cf_base: equ $9fd0 0021 9fd0 cf_reg_0: equ cf_base+0 ; data port 0022 9fd1 cf_reg_1: equ cf_base+1 ; read: error code, write: feature 0023 9fd2 cf_reg_2: equ cf_base+2 ; number of sectors to transfer 0024 9fd3 cf_reg_3: equ cf_base+3 ; sector address LBA 0 [0:7] 0025 9fd4 cf_reg_4: equ cf_base+4 ; sector address LBA 1 [8:15] 0026 9fd5 cf_reg_5: equ cf_base+5 ; sector address LBA 2 [16:23] 0027 9fd6 cf_reg_6: equ cf_base+6 ; sector address LBA 3 [24:27 (LSB of reg)] 0028 9fd7 cf_reg_7: equ cf_base+7 ; read: status, write: command 0029 0030 ;;; 0031 ;;; CF commands 0032 ;;; 0033 0004 cf_cmd_reset: equ $04 0034 0020 cf_cmd_read: equ $20 0035 0030 cf_cmd_write: equ $30 0036 0037 0038 ;;; 0039 ;;; Program begin here 0040 ;;; 0041 0100 org $0100 0042 0100 7e 01 2c jmp format 0043 txt_hdr: 0044 0103 48 65 61 64 65 72 fcc "Header = " 20 3d 20 0045 010c 04 fcb $04 0046 txt_alloc: 0047 010d 20 41 6c 6c 6f 63 fcc " Alloc = " 20 3d 20 0048 0116 04 fcb $04 0049 txt_root: 0050 0117 20 20 52 6f 6f 74 fcc " Root = " 20 3d 20 0051 0120 04 fcb $04 0052 0053 txt_error: 0054 0121 45 72 72 6f 72 20 fcc "Error " 0055 0127 04 fcb $04 0056 0057 ;;; 0058 ;;; Program variables 0059 ;;; 0060 0128 media_addr_3: rmb 1 0061 0129 media_addr_2: rmb 1 0062 012a media_addr_1: rmb 1 0063 012b media_addr_0: rmb 1 0064 0065 0066 ;;; 0067 ;;; MCFS2 format routine 0068 ;;; 0069 format: 0070 012c bd c0 21 jsr mon_pcrlf 0071 012f 86 f0 ldaa #$f0 0072 0131 97 02 staa page_register 0073 0074 0133 bd 02 a4 jsr cf_init 0075 0136 bd 02 c9 jsr cf_check_error 0076 0139 27 03 beq *+5 0077 013b 7e 02 5c jmp general_error 0078 0079 ;;; Start of partition 0080 013e 7f 01 28 clr media_addr_3 0081 0141 7f 01 29 clr media_addr_2 0082 0144 7f 01 2a clr media_addr_1 0083 0147 7f 01 2b clr media_addr_0 0084 0085 ;;; MCFS partition header sector 0086 014a ce 01 03 ldx #txt_hdr 0087 014d bd c0 09 jsr mon_pdata 0088 0150 ce 01 2a ldx #media_addr_1 0089 0153 bd c0 15 jsr mon_out4hs 0090 0156 bd c0 21 jsr mon_pcrlf 0091 0092 0159 bd 02 68 jsr clr_secbuf 0093 015c ce 10 00 ldx #sector_buffer 0094 015f 86 4d ldaa #'M ; "MCFS" 0095 0161 b7 10 00 staa vol_hdr+0 0096 0164 86 43 ldaa #'C 0097 0166 b7 10 01 staa vol_hdr+1 0098 0169 86 46 ldaa #'F 0099 016b b7 10 02 staa vol_hdr+2 0100 016e 86 53 ldaa #'S 0101 0170 b7 10 03 staa vol_hdr+3 0102 0173 86 02 ldaa #$02 ; MCFS version $02 0103 0175 b7 10 04 staa vol_ver 0104 0178 ce 00 00 ldx #$0000 ; Partition begin (this sector) 0105 017b ff 10 05 stx vol_beg 0106 017e ce ff ff ldx #$ffff ; Partition end (last sector) 0107 0181 ff 10 07 stx vol_end 0108 0184 ce 55 55 ldx #$5555 ; Volume ID 0109 0187 ff 10 09 stx vol_id 0110 018a ce 00 01 ldx #$0001 ; Sector allocation table begin 0111 018d ff 10 2b stx vol_alloc_beg 0112 0190 ce 00 80 ldx #$0080 ; Sector allocation table end 0113 0193 ff 10 2d stx vol_alloc_end 0114 0196 ce 00 81 ldx #$0081 ; Root directory begin 0115 0199 ff 10 2f stx vol_root_beg 0116 019c ce 00 88 ldx #$0088 ; Root directory end 0117 019f ff 10 31 stx vol_root_end 0118 0119 01a2 bd 02 8d jsr write_sector ; Write sector 0120 01a5 bd 02 c9 jsr cf_check_error 0121 01a8 27 03 beq *+5 0122 01aa 7e 02 5c jmp general_error 0123 0124 ;;; Allocation sectors 0125 01ad ce 01 0d ldx #txt_alloc 0126 01b0 bd c0 09 jsr mon_pdata 0127 01b3 7c 01 2b inc media_addr_0 0128 01b6 ce 01 2a ldx #media_addr_1 0129 01b9 bd c0 15 jsr mon_out4hs 0130 ;;; Allocation sector 1 (with 50 allocated sectors) 0131 01bc bd 02 68 jsr clr_secbuf 0132 01bf 5f clrb 0133 01c0 ce 10 00 ldx #sector_buffer 0134 alloc_loop1: 0135 01c3 c1 8a cmpb #138 0136 01c5 22 06 bhi alloc_loop1_end 0137 01c7 6c 00 inc ,x 0138 01c9 08 inx 0139 01ca 5c incb 0140 01cb 20 f6 bra alloc_loop1 0141 alloc_loop1_end: 0142 01cd bd 02 8d jsr write_sector 0143 ;;; Remaining 127 allocation sectors 0144 01d0 bd 02 68 jsr clr_secbuf 0145 01d3 7c 01 2b inc media_addr_0 0146 01d6 5f clrb 0147 alloc_loop2: 0148 01d7 c1 7d cmpb #125 0149 01d9 22 09 bhi alloc_loop2_end 0150 01db bd 02 8d jsr write_sector 0151 01de 7c 01 2b inc media_addr_0 0152 01e1 5c incb 0153 01e2 20 f3 bra alloc_loop2 0154 alloc_loop2_end: 0155 0156 01e4 86 2d ldaa #'- 0157 01e6 bd c0 03 jsr mon_outchar 0158 01e9 86 20 ldaa #$20 0159 01eb bd c0 03 jsr mon_outchar 0160 01ee ce 01 2a ldx #media_addr_1 0161 01f1 bd c0 15 jsr mon_out4hs 0162 01f4 bd c0 21 jsr mon_pcrlf 0163 0164 01f7 bd 02 c9 jsr cf_check_error 0165 01fa 27 03 beq *+5 0166 01fc 7e 02 5c jmp general_error 0167 0168 ;;; Root directory 0169 01ff ce 01 17 ldx #txt_root 0170 0202 bd c0 09 jsr mon_pdata 0171 0205 7c 01 2b inc media_addr_0 0172 0208 ce 01 2a ldx #media_addr_1 0173 020b bd c0 15 jsr mon_out4hs 0174 0175 020e bd 02 68 jsr clr_secbuf ; Write root directory sector 1 0176 0211 bd 02 8d jsr write_sector 0177 0214 7c 01 2b inc media_addr_0 ; Write root directory sector 2 0178 0217 bd 02 8d jsr write_sector 0179 021a 7c 01 2b inc media_addr_0 ; Write root directory sector 3 0180 021d bd 02 8d jsr write_sector 0181 0220 7c 01 2b inc media_addr_0 ; Write root directory sector 4 0182 0223 bd 02 8d jsr write_sector 0183 0226 7c 01 2b inc media_addr_0 ; Write root directory sector 5 0184 0229 bd 02 8d jsr write_sector 0185 022c 7c 01 2b inc media_addr_0 ; Write root directory sector 6 0186 022f bd 02 8d jsr write_sector 0187 0232 7c 01 2b inc media_addr_0 ; Write root directory sector 7 0188 0235 bd 02 8d jsr write_sector 0189 0238 7c 01 2b inc media_addr_0 ; Write root directory sector 8 0190 023b bd 02 8d jsr write_sector 0191 0192 023e 86 2d ldaa #'- 0193 0240 bd c0 03 jsr mon_outchar 0194 0243 86 20 ldaa #$20 0195 0245 bd c0 03 jsr mon_outchar 0196 0248 ce 01 2a ldx #media_addr_1 0197 024b bd c0 15 jsr mon_out4hs 0198 024e bd c0 21 jsr mon_pcrlf 0199 0200 0251 bd 02 c9 jsr cf_check_error 0201 0254 27 03 beq *+5 0202 0256 7e 02 5c jmp general_error 0203 0204 0259 7e c0 00 jmp mon_return 0205 general_error: 0206 025c ce 01 21 ldx #txt_error 0207 025f bd c0 09 jsr mon_pdata 0208 0262 bd c0 21 jsr mon_pcrlf 0209 0265 7e c0 00 jmp mon_return 0210 0211 0212 ;;; 0213 ;;; Clear RAM sector buffer 0214 ;;; 0215 clr_secbuf: 0216 0268 ce 10 00 ldx #sector_buffer 0217 clr_secbuf_loop: 0218 026b 8c 12 00 cpx #sector_buffer+512 0219 026e 22 05 bhi clr_secbuf_end 0220 0270 6f 00 clr ,x 0221 0272 08 inx 0222 0273 20 f6 bra clr_secbuf_loop 0223 clr_secbuf_end: 0224 0275 39 rts 0225 0226 0227 ;;; 0228 ;;; Read sector at media_addr_[3:0] store at X 0229 ;;; Z set on OK read. Error code in A 0230 ;;; 0231 read_sector: 0232 0276 ce 10 00 ldx #sector_buffer 0233 0279 bd 02 bf jsr cf_wait 0234 027c bd 02 d8 jsr cf_set_lba 0235 027f 86 01 ldaa #1 0236 0281 b7 9f d2 staa cf_reg_2 ; number of sectors to read 0237 0284 86 20 ldaa #cf_cmd_read 0238 0286 b7 9f d7 staa cf_reg_7 ; issue read command 0239 0289 7e 02 f5 jmp cf_read_data ; read data routine 0240 028c 39 rts 0241 0242 ;;; 0243 ;;; Write sector at media_addr_[3:0] store at X 0244 ;;; Z set on OK write. Error code in A 0245 ;;; 0246 write_sector: 0247 028d ce 10 00 ldx #sector_buffer 0248 0290 bd 02 bf jsr cf_wait 0249 0293 bd 02 d8 jsr cf_set_lba 0250 0296 86 01 ldaa #1 0251 0298 b7 9f d2 staa cf_reg_2 ; number of sectors to write 0252 029b 86 30 ldaa #cf_cmd_write 0253 029d b7 9f d7 staa cf_reg_7 ; issue write command 0254 02a0 7e 03 0f jmp cf_write_data ; write data routine 0255 02a3 39 rts 0256 0257 ;;; 0258 ;;; Initialize CF 0259 ;;; 0260 cf_init: 0261 02a4 86 04 ldaa #$04 ; reset command 0262 02a6 b7 9f d7 staa cf_reg_7 0263 02a9 bd 02 bf jsr cf_wait 0264 02ac 86 e0 ldaa #$E0 ; LBA3=0, MASTER, MODE=LBA 0265 02ae b7 9f d6 staa cf_reg_6 0266 02b1 86 01 ldaa #$01 ; 8-bit transfers 0267 02b3 b7 9f d1 staa cf_reg_1 0268 02b6 86 ef ldaa #$EF ; set-feature command 0269 02b8 b7 9f d7 staa cf_reg_7 0270 02bb bd 02 bf jsr cf_wait 0271 02be 39 rts 0272 0273 ;;; 0274 ;;; Wait for CF ready 0275 ;;; 0276 cf_wait: 0277 02bf b6 9f d7 ldaa cf_reg_7 0278 02c2 84 80 anda #$80 ; mask out BUSY bit 0279 02c4 81 00 cmpa #$00 0280 02c6 26 f7 bne cf_wait 0281 02c8 39 rts 0282 0283 ;;; 0284 ;;; Check for CF error 0285 ;;; Z set on OK 0286 ;;; Error code in A 0287 ;;; bit 7 - Bad block detected 0288 ;;; bit 6 - Uncorrectable data error 0289 ;;; bit 5 - Media changed 0290 ;;; bit 4 - ID not found 0291 ;;; bit 3 - Aborted command 0292 ;;; bit 2 - Media change requested 0293 ;;; bit 1 - Track 0 not found 0294 ;;; bit 0 - Addressmask not found 0295 ;;; 0296 cf_check_error: 0297 02c9 b6 9f d7 ldaa cf_reg_7 0298 02cc 84 01 anda #$01 ; mask out ERROR bit 0299 02ce 81 00 cmpa #0 0300 02d0 27 04 beq cf_no_error 0301 02d2 b6 9f d1 ldaa cf_reg_1 0302 02d5 39 rts 0303 cf_no_error: 0304 02d6 4f clra 0305 02d7 39 rts 0306 0307 ;;; 0308 ;;; CF set LBA 0309 ;;; 0310 cf_set_lba: 0311 02d8 b6 01 2b ldaa media_addr_0 ; LBA byte 0 0312 02db b7 9f d3 staa cf_reg_3 0313 02de b6 01 2a ldaa media_addr_1 ; LBA byte 1 0314 02e1 b7 9f d4 staa cf_reg_4 0315 02e4 b6 01 29 ldaa media_addr_2 ; LBA byte 2 0316 02e7 b7 9f d5 staa cf_reg_5 0317 02ea b6 01 28 ldaa media_addr_3 ; LBA byte 3 0318 02ed 84 0f anda #%00001111 ; mask out LBA bits 0319 02ef 8a e0 oraa #%11100000 ; set mode LBA and master device 0320 02f1 b7 9f d6 staa cf_reg_6 0321 02f4 39 rts 0322 0323 ;;; 0324 ;;; Read data from CF 0325 ;;; Z set on OK 0326 ;;; error code in A 0327 ;;; 0328 cf_read_data: 0329 02f5 bd 02 bf jsr cf_wait 0330 02f8 b6 9f d7 ldaa cf_reg_7 0331 02fb 84 08 anda #$08 ; mask out DRQ bit 0332 02fd 81 08 cmpa #$08 0333 02ff 26 0c bne cf_read_data_e 0334 0301 b6 9f d0 ldaa cf_reg_0 ; read data byte 0335 0304 a7 00 staa ,X 0336 0306 08 inx 0337 0307 bd 02 c9 jsr cf_check_error 0338 030a 27 e9 beq cf_read_data 0339 030c 39 rts 0340 cf_read_data_e: 0341 030d 4f clra 0342 030e 39 rts 0343 0344 ;;; 0345 ;;; Write data to CF 0346 ;;; Z set on OK 0347 ;;; error code in A 0348 ;;; 0349 cf_write_data: 0350 030f bd 02 bf jsr cf_wait 0351 0312 b6 9f d7 ldaa cf_reg_7 0352 0315 84 08 anda #$08 ; mask out DRQ bit 0353 0317 81 08 cmpa #$08 0354 0319 26 0c bne cf_write_data_e 0355 031b a6 00 ldaa ,X 0356 031d b7 9f d0 staa cf_reg_0 ; write data byte 0357 0320 08 inx 0358 0321 bd 02 c9 jsr cf_check_error 0359 0324 27 e9 beq cf_write_data 0360 0326 39 rts 0361 cf_write_data_e: 0362 0327 4f clra 0363 0328 39 rts 0364 0365 ;;; 0366 ;;; Sector buffer 0367 ;;; 0368 1000 org $1000 0369 sector_buffer: 0370 1000 rmb 512 0371 0372 ;;; 0373 ;;; Volume header 0374 ;;; 512 bytes 0375 ;;; 0376 1000 org sector_buffer 0377 1000 vol_hdr: rmb 4 ; file system ID = "MCFS" 0378 1004 vol_ver: rmb 1 ; file system version = $02 0379 1005 vol_beg: rmb 2 ; first sector of partition 0380 1007 vol_end: rmb 2 ; last sector of partition 0381 1009 vol_id: rmb 2 ; volume ID 0382 100b vol_name: rmb 32 ; volume label (zero terminated) 0383 102b vol_alloc_beg: rmb 2 ; first sector of allocation table 0384 102d vol_alloc_end: rmb 2 ; last sector of allocation table (up to 16 sectors) 0385 102f vol_root_beg: rmb 2 ; first sector of root dir 0386 1031 vol_root_end: rmb 2 ; last sector of root dir 0387 ;;; 0388 ;;; rest of sector is set to zero 0389 ;;; Number of errors 0