1 ******************************** 2 * 3 * Initialize SD card 4 * 5 ******************************** 6 7 XC 8 ORG $8000 9 10 SLOT = $04 ; slot 4 11 DATA = $C0C0 ; slot 4 12 CTRL = DATA+1 13 DIV = DATA+2 14 SS = DATA+3 15 R30 = $0478 16 R31 = $04F8 17 R32 = $0578 18 R33 = $05F8 19 CMDLO = $FA 20 CMDHI = $FB 21 * 22 FROM = $FA ; + $fb 23 TO = $FC ; + $fd 24 SIZE = $FE ; + $ff 25 * 26 SSNONE = $0F 27 SS0 = $0E 28 TC = $80 29 DUMMY = $FF 30 31 32 ******************************** 33 * 34 * Install SD card driver 35 * 36 ******************************** 37 38 * make room for the driver 39 8000: A9 04 40 GETBUF LDA #4 ; allocate 4 pages 8002: 20 F5 BE 41 JSR $BEF5 ; call GETBUFR 8005: B0 59 42 BCS ERROR ; did an error occur? 8007: 85 FD 43 STA TO+1 ; store buffer addr msb 8009: 8D 84 80 44 STA BUFMSB 800C: 64 FC 45 STZ TO ; store buffer addr lsb 800E: 9C 85 80 46 STZ BUFLSB 8011: A9 80 47 LDA #>DRIVER1 8013: 85 FB 48 STA FROM+1 ; store from addr msb 8015: A9 8C 49 LDA #DRIVEND-DRIVER 801B: 85 FF 52 STA SIZE+1 ; store size msb 801D: A9 E4 53 LDA #CMD0 9650: 85 FB 189 STA CMDHI 9652: 20 FD 96 190 JSR CMD 9655: 20 0F 97 191 JSR GETR1 ; get response 9658: C9 01 192 CMP #$01 965A: D0 39 193 BNE ERROR1 ; error! 194 965C: A9 C6 195 LDA #CMD8 9662: 85 FB 198 STA CMDHI 9664: 20 FD 96 199 JSR CMD 9667: 20 2C 97 200 JSR GETR3 966A: C9 01 201 CMP #$01 966C: D0 2A 202 BNE SDV1 ; may be SD Ver. 1 203 204 * check for $01aa match! 966E: A9 D2 205 SDV2 LDA #CMD55 9674: 85 FB 208 STA CMDHI 9676: 20 FD 96 209 JSR CMD 9679: 20 0F 97 210 JSR GETR1 967C: A9 D8 211 LDA #ACMD41_40 9682: 85 FB 214 STA CMDHI 9684: 20 FD 96 215 JSR CMD 9687: 20 0F 97 216 JSR GETR1 968A: C9 01 217 CMP #$01 968C: F0 E0 218 BEQ SDV2 ; wait for ready 968E: C9 00 219 CMP #$00 9690: D0 03 220 BNE ERROR1 ; error! 221 * send CMD58 222 * SD Ver. 2 initialized! 9692: 4C D2 96 223 JMP BLOCKSZ 224 9695: 4C EE 96 225 ERROR1 JMP IOERROR ; needed for far jump 226 9698: A9 D2 227 SDV1 LDA #CMD55 969E: 85 FB 230 STA CMDHI ===== Page 5 ===== 96A0: 20 FD 96 231 JSR CMD ; ignore response 96A3: A9 DE 232 LDA #ACMD41_0 96A9: 85 FB 235 STA CMDHI 96AB: 20 FD 96 236 JSR CMD 96AE: 20 0F 97 237 JSR GETR1 96B1: C9 01 238 CMP #$01 96B3: F0 E3 239 BEQ SDV1 ; wait for ready 96B5: C9 00 240 CMP #$00 96B7: D0 03 241 BNE MMC ; may be MMC card 242 * SD Ver. 1 initialized! 96B9: 4C D2 96 243 JMP BLOCKSZ 244 96BC: A9 C0 245 MMC LDA #CMD1 96C2: 85 FB 248 STA CMDHI 96C4: 20 FD 96 249 :LOOP JSR CMD 96C7: 20 0F 97 250 JSR GETR1 96CA: C9 01 251 CMP #$01 96CC: F0 F6 252 BEQ :LOOP ; wait for ready 96CE: C9 00 253 CMP #$00 96D0: D0 1C 254 BNE IOERROR ; error! 255 * MMC Ver. 3 initialized! 256 96D2: A9 CC 257 BLOCKSZ LDA #CMD16 96D8: 85 FB 260 STA CMDHI 96DA: 20 FD 96 261 JSR CMD 96DD: 20 0F 97 262 JSR GETR1 96E0: C9 00 263 CMP #$00 96E2: D0 0A 264 BNE IOERROR ; error! 265 96E4: 18 266 END CLC ; all ok 96E5: A0 00 267 LDY #0 96E7: 90 08 268 BCC END1 96E9: 38 269 CDERROR SEC 96EA: A0 28 270 LDY #$28 ; no card error 96EC: B0 03 271 BCS END1 96EE: 38 272 IOERROR SEC 96EF: A0 27 273 LDY #$27 ; init error 96F1: A9 0F 274 END1 LDA #SSNONE ; deselect card 96F3: 8D C3 C0 275 STA SS 96F6: A9 00 276 LDA #0 96F8: 8D C2 C0 277 STA DIV 96FB: 98 278 TYA ; retval in A 96FC: 60 279 RTS 280 281 282 ******************************** 283 * 284 * Send SD command 285 * Call with command in CMDHI and CMDLO 286 * 287 ******************************** ===== Page 6 ===== 288 96FD: A0 00 289 CMD LDY #0 96FF: B1 FA 290 :LOOP LDA (CMDLO),Y 9701: 8D C0 C0 291 STA DATA 9704: 2C C1 C0 292 :WAIT BIT CTRL ; TC is in N 9707: 10 FB 293 BPL :WAIT 9709: C8 294 INY 970A: C0 06 295 CPY #6 970C: 90 F1 296 BCC :LOOP 970E: 60 297 RTS 298 299 300 ******************************** 301 * 302 * Get R1 303 * R1 is in A 304 * 305 ******************************** 306 970F: A9 FF 307 GETR1 LDA #DUMMY 9711: 8D C0 C0 308 STA DATA 9714: 2C C1 C0 309 :WAIT BIT CTRL 9717: 10 FB 310 BPL :WAIT 9719: AD C0 C0 311 LDA DATA ; get response 971C: 8D 7C 04 312 STA R30+SLOT ; save R1 971F: 29 80 313 AND #$80 9721: D0 EC 314 BNE GETR1 ; wait for MSB=0 9723: A9 FF 315 LDA #DUMMY 9725: 8D C0 C0 316 STA DATA ; send another dummy 9728: AD 7C 04 317 LDA R30+SLOT ; restore R1 972B: 60 318 RTS 319 320 321 ******************************** 322 * 323 * Get R3 324 * R1 is in A 325 * R3 is in scratchpad ram 326 * 327 ******************************** 328 972C: 20 0F 97 329 GETR3 JSR GETR1 ; get R1 first 972F: 48 330 PHA ; save R1 9730: 5A 331 PHY ; save Y 9731: A0 04 332 LDY #04 9733: A9 FF 333 :LOOP LDA #DUMMY ; send dummy 9735: 8D C0 C0 334 STA DATA 9738: 2C C1 C0 335 :WAIT BIT CTRL 973B: 10 FB 336 BPL :WAIT 973D: AD C0 C0 337 LDA DATA 9740: 48 338 PHA 9741: 88 339 DEY 9742: D0 EF 340 BNE :LOOP ; do 4 times 9744: 68 341 PLA 9745: 8D FC 05 342 STA R33+SLOT ; save R3 9748: 68 343 PLA 9749: 8D 7C 05 344 STA R32+SLOT ===== Page 7 ===== 974C: 68 345 PLA 974D: 8D FC 04 346 STA R31+SLOT 9750: 68 347 PLA 9751: 8D 7C 04 348 STA R30+SLOT 9754: 7A 349 PLY ; restore Y 9755: A9 FF 350 LDA #DUMMY 9757: 8D C0 C0 351 STA DATA ; send another dummy 975A: 68 352 PLA ; restore R1 975B: 60 353 RTS 354 355 356 ******************************** 357 * 358 * Status request 359 * $43 Unt number DSSS000 360 * $44-45 Unused 361 * $46-47 Unused 362 * 363 * C Clear - No error 364 * Set - Error 365 * A $00 - No error 366 * $27 - I/O error 367 * $28 - No card inserted / no init 368 * $2B - Card write protected 369 * X - Blocks avail (low byte) 370 * Y - Blocks avail (high byte) 371 * 372 ******************************** 373 975C: 18 374 STATUS CLC ; no error 975D: A9 00 375 LDA #0 975F: A2 FF 376 LDX #$FF ; 32 MB partition 9761: A0 FF 377 LDY #$FF 9763: 60 378 RTS 379 380 * TODO: check for card detect and write protect! 381 382 383 ******************************** 384 * 385 * Read 512 byte block 386 * $43 Unit number DSSS0000 387 * $44-45 Address (LO/HI) of buffer 388 * $46-47 Block number (LO/HI) 389 * 390 * C Clear - No error 391 * Set - Error 392 * A $00 - No error 393 * $27 - Bad block number 394 * $28 - No card inserted 395 * 396 ******************************** 397 398 * TODO: check for card detect! 399 9764: A9 0E 400 READ LDA #SS0 ; enable /CS 9766: 8D C3 C0 401 STA SS ===== Page 8 ===== 402 9769: A5 46 403 LDA $46 ; store block num 976B: 8D FC 05 404 STA R33+SLOT ; in R30-R33 976E: A5 47 405 LDA $47 9770: 8D 7C 05 406 STA R32+SLOT 9773: 9C FC 04 407 STZ R31+SLOT 9776: 9C 7C 04 408 STZ R30+SLOT 9779: A0 09 409 LDY #9 977B: 0E FC 05 410 :LOOP ASL R33+SLOT ; mul block num 977E: 2E 7C 05 411 ROL R32+SLOT ; by 512 to get 9781: 2E FC 04 412 ROL R31+SLOT ; real address 9784: 2E 7C 04 413 ROL R30+SLOT 9787: 88 414 DEY 9788: D0 F1 415 BNE :LOOP 416 978A: A9 51 417 LDA #$51 ; send CMD17 978C: 8D C0 C0 418 STA DATA 978F: 2C C1 C0 419 :WAIT BIT CTRL 9792: 10 FB 420 BPL :WAIT 9794: AD 7C 04 421 :ARG LDA R30+SLOT ; get arg from R30 on 9797: 8D C0 C0 422 STA DATA 979A: 2C C1 C0 423 :WAIT1 BIT CTRL 979D: 10 FB 424 BPL :WAIT1 979F: AD FC 04 425 LDA R31+SLOT 97A2: 8D C0 C0 426 STA DATA 97A5: 2C C1 C0 427 :WAIT11 BIT CTRL 97A8: 10 FB 428 BPL :WAIT11 97AA: AD 7C 05 429 LDA R32+SLOT 97AD: 8D C0 C0 430 STA DATA 97B0: 2C C1 C0 431 :WAIT12 BIT CTRL 97B3: 10 FB 432 BPL :WAIT12 97B5: AD FC 05 433 LDA R33+SLOT 97B8: 8D C0 C0 434 STA DATA 97BB: 2C C1 C0 435 :WAIT13 BIT CTRL 97BE: 10 FB 436 BPL :WAIT13 97C0: A9 FF 437 LDA #DUMMY 97C2: 8D C0 C0 438 STA DATA ; dummy crc 97C5: 2C C1 C0 439 :WAIT2 BIT CTRL 97C8: 10 FB 440 BPL :WAIT2 97CA: A9 FF 441 :GETR1 LDA #DUMMY 97CC: 8D C0 C0 442 STA DATA ; get R1 97CF: 2C C1 C0 443 :WAIT3 BIT CTRL 97D2: 10 FB 444 BPL :WAIT3 97D4: AD C0 C0 445 LDA DATA ; get response 446 * 447 * TODO: check for error! 448 * 97D7: C9 FE 449 CMP #$FE 97D9: D0 EF 450 BNE :GETR1 ; wait for $FE 451 97DB: A2 02 452 LDX #2 ; read data from card 97DD: A0 00 453 :LOOPX LDY #0 97DF: A9 FF 454 :LOOPY LDA #DUMMY 97E1: 8D C0 C0 455 STA DATA 97E4: 2C C1 C0 456 :WAIT4 BIT CTRL 97E7: 10 FB 457 BPL :WAIT4 97E9: AD C0 C0 458 LDA DATA ===== Page 9 ===== 97EC: 92 44 459 STA ($44) 97EE: E6 44 460 INC $44 97F0: D0 02 461 BNE :INY 97F2: E6 45 462 INC $45 ; inc msb on page boundary 97F4: C8 463 :INY INY 97F5: D0 E8 464 BNE :LOOPY 97F7: CA 465 DEX 97F8: D0 E3 466 BNE :LOOPX 467 97FA: 20 2C 97 468 :OK JSR GETR3 ; read 2 bytes crc 97FD: A9 0F 469 LDA #SSNONE 97FF: 8D C3 C0 470 STA SS ; disable /CS 9802: 18 471 CLC ; no error 9803: A9 00 472 LDA #$00 9805: 60 473 RTS 474 9806: A9 0F 475 :ERROR LDA #SSNONE 9808: 8D C3 C0 476 STA SS ; disable /CS 980B: 38 477 SEC ; an error occured 980C: A9 27 478 LDA #$27 980E: 60 479 RTS 480 481 482 ******************************** 483 * 484 * Write 512 byte block 485 * $43 Unit number DSSS000 486 * $44-45 Address (LO/HI) of buffer 487 * $46-47 Block number (LO/HI) 488 * 489 * C Clear - No error 490 * Set - Error 491 * A $00 - No error 492 * $27 - Bad block number 493 * $28 - No card inserted 494 * 495 ******************************** 496 497 * TODO: check for card detect and write protect! 498 980F: A9 0E 499 WRITE LDA #SS0 ; enable /CS 9811: 8D C3 C0 500 STA SS 501 9814: A5 46 502 LDA $46 ; store block num 9816: 8D FC 05 503 STA R33+SLOT 9819: A5 47 504 LDA $47 981B: 8D 7C 05 505 STA R32+SLOT 981E: 9C FC 04 506 STZ R31+SLOT 9821: 9C 7C 04 507 STZ R30+SLOT 9824: A0 09 508 LDY #9 9826: 0E FC 05 509 :LOOP ASL R33+SLOT ; mul block num 9829: 2E 7C 05 510 ROL R32+SLOT ; by 512 to get 982C: 2E FC 04 511 ROL R31+SLOT ; real address 982F: 2E 7C 04 512 ROL R30+SLOT 9832: 88 513 DEY 9833: D0 F1 514 BNE :LOOP 515 ===== Page 10 ===== 9835: A9 58 516 LDA #$58 ; send CMD24 9837: 8D C0 C0 517 STA DATA 983A: 2C C1 C0 518 :WAIT BIT CTRL 983D: 10 FB 519 BPL :WAIT 983F: AD 7C 04 520 :ARG LDA R30+SLOT ; get arg from R30 on 9842: 8D C0 C0 521 STA DATA 9845: 2C C1 C0 522 :WAIT1 BIT CTRL 9848: 10 FB 523 BPL :WAIT1 984A: AD FC 04 524 LDA R31+SLOT 984D: 8D C0 C0 525 STA DATA 9850: 2C C1 C0 526 :WAIT11 BIT CTRL 9853: 10 FB 527 BPL :WAIT11 9855: AD 7C 05 528 LDA R32+SLOT 9858: 8D C0 C0 529 STA DATA 985B: 2C C1 C0 530 :WAIT12 BIT CTRL 985E: 10 FB 531 BPL :WAIT12 9860: AD FC 05 532 LDA R33+SLOT 9863: 8D C0 C0 533 STA DATA 9866: 2C C1 C0 534 :WAIT13 BIT CTRL 9869: 10 FB 535 BPL :WAIT13 986B: A9 FF 536 LDA #DUMMY 986D: 8D C0 C0 537 STA DATA ; dummy crc 9870: 2C C1 C0 538 :WAIT2 BIT CTRL 9873: 10 FB 539 BPL :WAIT2 9875: A9 FF 540 :GETR1 LDA #DUMMY 9877: 8D C0 C0 541 STA DATA ; get R1 987A: 2C C1 C0 542 :WAIT3 BIT CTRL 987D: 10 FB 543 BPL :WAIT3 987F: AD C0 C0 544 LDA DATA : get response 545 * 546 * TODO: check for error! 547 * 9882: C9 FE 548 CMP #$FE 9884: D0 EF 549 BNE :GETR1 ; wait for $FE 9886: A2 02 550 LDX #2 ; send data to card 9888: A0 00 551 :LOOPX LDY #0 988A: B2 44 552 :LOOPY LDA ($44) 988C: 8D C0 C0 553 STA DATA 988F: 2C C1 C0 554 :WAIT4 BIT CTRL 9892: 10 FB 555 BPL :WAIT4 9894: E6 44 556 INC $44 9896: D0 02 557 BNE :INY 9898: E6 45 558 INC $45 ; inc msbon page boundary 989A: C8 559 :INY INY 989B: D0 ED 560 BNE :LOOPY 989D: CA 561 DEX 989E: D0 E8 562 BNE :LOOPX 563 98A0: A0 02 564 LDY #2 ; send 2 dummy crc bytes 98A2: 8D C0 C0 565 :CRC STA DATA 98A5: 2C C1 C0 566 :WAIT5 BIT CTRL 98A8: 10 FB 567 BPL :WAIT5 98AA: 88 568 DEY 98AB: D0 F5 569 BNE :CRC 570 98AD: A9 0F 571 :OK LDA #SSNONE ; disable /CS 98AF: 8D C3 C0 572 STA SS ===== Page 11 ===== 98B2: 18 573 CLC ; no error 98B3: A9 00 574 LDA #0 98B5: 60 575 RTS 576 577 578 ******************************** 579 * 580 * Format 581 * not supported! 582 * 583 ******************************** 584 98B6: 38 585 FORMAT SEC 98B7: A9 01 586 LDA #$01 ; invalid command 98B9: 60 587 RTS 588 589 590 98BA: 40 00 00 591 CMD0 HEX 400000000095 98BD: 00 00 95 98C0: 41 00 00 592 CMD1 HEX 4100000000F9 98C3: 00 00 F9 98C6: 48 00 00 593 CMD8 HEX 48000001AA87 98C9: 01 AA 87 98CC: 50 00 00 594 CMD16 HEX 5000000200FF 98CF: 02 00 FF 98D2: 77 00 00 595 CMD55 HEX 770000000065 98D5: 00 00 65 98D8: 69 40 00 596 ACMD41_40 HEX 694000000077 98DB: 00 00 77 98DE: 69 00 00 597 ACMD41_0 HEX 6900000000FF 98E1: 00 00 FF 598 599 DRIVEND = * --End assembly, 880 bytes, Errors: 0 Symbol table - alphabetical order: ACMD41_0=$98DE ACMD41_40=$98D8 BLOCKSZ =$96D2 BUFLSB =$8085 BUFMSB =$8084 ? CDERROR =$96E9 CMD =$96FD CMD0 =$98BA CMD1 =$98C0 CMD16 =$98CC CMD55 =$98D2 CMD8 =$98C6 CMDHI =$FB CMDLO =$FA CTRL =$C0C1 DATA =$C0C0 DIV =$C0C2 DRIVEND =$98E4 DRIVER =$9600 DRIVER1 =$808C DUMMY =$FF ? END =$96E4 END1 =$96F1 ERROR =$8060 ERROR1 =$9695 FORMAT =$98B6 FROM =$FA ? GETBUF =$8000 GETR1 =$970F GETR3 =$972C INIT =$9626 INSLP =$804D INSLP2 =$8063 INSOUT =$8083 ? INSTALL =$804A IOERROR =$96EE MMC =$96BC ? MOVEUP =$8021 MU1 =$8037 MU2 =$803E MU3 =$8042 R30 =$0478 R31 =$04F8 R32 =$0578 R33 =$05F8 READ =$9764 SDV1 =$9698 SDV2 =$966E SIZE =$FE SLOT =$04 SS =$C0C3 SS0 =$0E SSNONE =$0F STATUS =$975C ? TC =$80 TO =$FC WRITE =$980F ===== Page 12 ===== Symbol table - numerical order: SLOT =$04 SS0 =$0E SSNONE =$0F ? TC =$80 CMDLO =$FA FROM =$FA CMDHI =$FB TO =$FC SIZE =$FE DUMMY =$FF R30 =$0478 R31 =$04F8 R32 =$0578 R33 =$05F8 ? GETBUF =$8000 ? MOVEUP =$8021 MU1 =$8037 MU2 =$803E MU3 =$8042 ? INSTALL =$804A INSLP =$804D ERROR =$8060 INSLP2 =$8063 INSOUT =$8083 BUFMSB =$8084 BUFLSB =$8085 DRIVER1 =$808C DRIVER =$9600 INIT =$9626 SDV2 =$966E ERROR1 =$9695 SDV1 =$9698 MMC =$96BC BLOCKSZ =$96D2 ? END =$96E4 ? CDERROR =$96E9 IOERROR =$96EE END1 =$96F1 CMD =$96FD GETR1 =$970F GETR3 =$972C STATUS =$975C READ =$9764 WRITE =$980F FORMAT =$98B6 CMD0 =$98BA CMD1 =$98C0 CMD8 =$98C6 CMD16 =$98CC CMD55 =$98D2 ACMD41_40=$98D8 ACMD41_0=$98DE DRIVEND =$98E4 DATA =$C0C0 CTRL =$C0C1 DIV =$C0C2 SS =$C0C3