From 92f8061ea8d5f378d1730bb94d586f7a51d22d27 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 13 Aug 2017 13:34:15 +0200 Subject: [PATCH] Fix for line ending --- AppleIISd.lst | 785 +++++++++++++++++++++++++++++++++++++++++++++++++- AppleIISd.s | 720 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1503 insertions(+), 2 deletions(-) diff --git a/AppleIISd.lst b/AppleIISd.lst index 2cd8fc4..4c6e194 100644 --- a/AppleIISd.lst +++ b/AppleIISd.lst @@ -1 +1,784 @@ - 1 ******************************** 2 * 3 * Apple][Sd Firmware 4 * Version 0.5 5 * 6 * (c) Florian Reitz, 2017 7 * 8 * X register usually contains SLOT16 9 * Y register iss used for counting or SLOT 10 * 11 ******************************** 12 12-AUG-17 15::51 14 15 XC ; enable 65C02 code 16 DEBUG = 0 17 DO DEBUG 18 ORG $8000 19 ELSE 20 ORG $C800 ; Expansion ROM 21 FIN 22 23 * Memory defines 24 25 SLOT16 = $2B ; $s0 -> slot * 16 26 WORK = $3C 27 SLOT = $3D ; $0s 28 CMDLO = $40 29 CMDHI = $41 30 31 CURSLOT = $07F8 ; $Cs 32 DATA = $C080 33 CTRL = DATA+1 34 DIV = DATA+2 35 SS = DATA+3 36 R30 = $0478 37 R31 = $04F8 38 R32 = $0578 39 R33 = $05F8 40 INITED = $0678 41 42 * Constants 43 44 SSNONE = $0F 45 SS0 = $0E 46 DUMMY = $FF 47 48 49 ******************************** 50 * 51 * Install SD card driver 52 * 53 ******************************** 54 55 * signature bytes 56 C800: A2 20 57 LDX #$20 C802: A0 00 58 LDY #$00 C804: A2 03 59 LDX #$03 ===== Page 2 ===== C806: 86 3C 60 STX WORK 61 62 * find slot nr 63 64 DO DEBUG 65 LDA #$04 66 STA SLOT 67 LDA #$C4 68 STA CURSLOT 69 LDA #$40 70 STA SLOT16 71 ELSE C808: 20 58 FF 72 JSR $FF58 C80B: BA 73 TSX C80C: BD 00 01 74 LDA $0100,X C80F: 8D F8 07 75 STA CURSLOT ; $Cs C812: 29 0F 76 AND #$0F C814: 85 3D 77 STA SLOT ; $0s C816: 0A 78 ASL A C817: 0A 79 ASL A C818: 0A 80 ASL A C819: 0A 81 ASL A C81A: 85 2B 82 STA SLOT16 ; $s0 83 FIN C81C: AA 84 TAX ; X holds now SLOT16 85 C81D: 2C FF CF 86 BIT $CFFF C820: 20 00 C9 87 JSR INIT 88 89 DO 0 90 * 91 * TODO: check for init error 92 * 93 94 * see if slot has a driver already 95 96 LDX $BF31 ; get devcnt 97 INSLP LDA $BF32,X ; get a devnum 98 AND #$70 ; isolate slot 99 CMP SLOT16 ; slot? 100 BEQ INSOUT ; yes, skip it 101 DEX 102 BPL INSLP ; keep up the search 103 104 * restore the devnum to the list 105 106 LDX $BF31 ; get devcnt again 107 CPX #$0D ; device table full? 108 BNE INSLP2 109 110 JSR $FF3A ; bell 111 JMP INSOUT ; do something! 112 113 INSLP2 LDA $BF32-1,X ; move all entries down 114 STA $BF32,X ; to make room at front 115 DEX ; for a new entry 116 BNE INSLP2 ===== Page 3 ===== 117 LDA #$04 ; ProFile type device 118 ORA SLOT16 119 STA $BF32 ; slot, drive 1 at top of list 120 INC $BF31 ; update devcnt 121 122 * now insert the device driver vector 123 124 LDA SLOT 125 ASL 126 TAX 127 LDA #DRIVER 131 ELSE 132 LDA CURSLOT 133 FIN 134 STA $BF11,X 135 136 INSOUT RTS 137 FIN 138 C823: A9 01 139 BOOT LDA #$01 C825: 85 42 140 STA $42 ; load command C827: A5 2B 141 LDA SLOT16 C829: AA 142 TAX C82A: 85 43 143 STA $43 ; slot number C82C: 64 44 144 STZ $44 ; buffer lo C82E: A9 08 145 LDA #$08 C830: 85 45 146 STA $45 ; buffer hi C832: 64 46 147 STZ $46 ; block lo C834: 64 47 148 STZ $47 ; block hi C836: 2C FF CF 149 BIT $CFFF C839: 20 B7 CA 150 JSR READ ; call driver C83C: 4C 01 08 151 JMP $801 ; goto bootloader 152 153 154 ******************************** 155 * 156 * Jump table 157 * 158 ******************************** 159 C83F: D8 160 DRIVER CLD 161 DO DEBUG 162 LDA #$04 163 STA SLOT 164 LDA #$C4 165 STA CURSLOT 166 LDA #$40 167 STA SLOT16 168 ELSE C840: 20 58 FF 169 JSR $FF58 ; find slot nr C843: BA 170 TSX C844: BD 00 01 171 LDA $0100,X C847: 8D F8 07 172 STA CURSLOT ; $Cs C84A: 29 0F 173 AND #$0F ===== Page 4 ===== C84C: 85 3D 174 STA SLOT ; $0s C84E: 0A 175 ASL A C84F: 0A 176 ASL A C850: 0A 177 ASL A C851: 0A 178 ASL A C852: 85 2B 179 STA SLOT16 ; $s0 180 FIN C854: AA 181 TAX ; X holds now SLOT16 182 C855: 2C FF CF 183 BIT $CCFF C858: A4 3D 184 LDY SLOT C85A: B9 78 06 185 LDA INITED,Y ; check for init C85D: C9 01 186 CMP #$01 C85F: 90 22 187 BCC :INIT C861: A5 42 188 :CMD LDA $42 ; get command C863: C9 90 189 CMP #$00 C865: F0 10 190 BEQ :STATUS C867: C9 01 191 CMP #$01 C869: F0 0F 192 BEQ :READ C86B: C9 02 193 CMP #$02 C86D: F0 0E 194 BEQ :WRITE C86F: C9 03 195 CMP #$03 C871: F0 0D 196 BEQ :FORMAT C873: 38 197 SEC ; unknown command C874: A9 01 198 LDA #$01 C876: 60 199 RTS 200 C877: 4C AF CA 201 :STATUS JMP STATUS C87A: 4C B7 CA 202 :READ JMP READ C87D: 4C 01 CB 203 :WRITE JMP WRITE C880: 4C 91 CB 204 :FORMAT JMP FORMAT C883: 20 00 C9 205 :INIT JSR INIT C886: 80 D9 206 BRA :CMD 207 208 * Signature bytes 209 C888: 00 00 00 210 DS \ ; fill with zeroes C88B: 00 00 00 00 C88F: 00 00 00 00 C893: 00 00 00 00 C897: 00 00 00 00 C89B: 00 00 00 00 C89F: 00 00 00 00 C8A3: 00 00 00 00 C8A7: 00 00 00 00 C8AB: 00 00 00 00 C8AF: 00 00 00 00 C8B3: 00 00 00 00 C8B7: 00 00 00 00 C8BB: 00 00 00 00 C8BF: 00 00 00 00 C8C3: 00 00 00 00 C8C7: 00 00 00 00 C8CB: 00 00 00 00 C8CF: 00 00 00 00 C8D3: 00 00 00 00 C8D7: 00 00 00 00 ===== Page 5 ===== C8DB: 00 00 00 00 C8DF: 00 00 00 00 C8E3: 00 00 00 00 C8E7: 00 00 00 00 C8EB: 00 00 00 00 C8EF: 00 00 00 00 C8F3: 00 00 00 00 C8F7: 00 00 00 00 C8FB: 00 00 00 00 C8FF: 00 211 DS -4 ; locate to $C8FC C8FC: FF FF 212 DW $FFFF ; 65535 blocks C8FE: 47 213 DB $47 ; Status bits C8FF: 3F 214 DB #CMD0 C92A: 85 41 250 STA CMDHI C92C: 20 DE C9 251 JSR CMD C92F: 20 F2 C9 252 JSR GETR1 ; get response C932: C9 01 253 CMP #$01 C934: D0 39 254 BNE :ERROR1 ; error! 255 C936: A9 A1 256 LDA #CMD8 C93C: 85 41 259 STA CMDHI C93E: 20 DE C9 260 JSR CMD C941: 20 0D CA 261 JSR GETR3 C944: C9 01 262 CMP #$01 C946: D0 2A 263 BNE :SDV1 ; may be SD Ver. 1 264 265 * check for $01aa match! C948: A9 AD 266 :SDV2 LDA #CMD55 C94E: 85 41 269 STA CMDHI C950: 20 DE C9 270 JSR CMD C953: 20 F2 C9 271 JSR GETR1 C956: A9 B3 272 LDA #ACMD4140 C95C: 85 41 275 STA CMDHI C95E: 20 DE C9 276 JSR CMD C961: 20 F2 C9 277 JSR GETR1 C964: C9 01 278 CMP #$01 C966: F0 E0 279 BEQ :SDV2 ; wait for ready C968: C9 00 280 CMP #$00 C96A: D0 03 281 BNE :ERROR1 ; error! 282 * send CMD58 283 * SD Ver. 2 initialized! C96C: 4C AC C9 284 JMP :BLOCKSZ 285 C96F: 4C CF C9 286 :ERROR1 JMP :IOERROR ; needed for far jump 287 C972: A9 AD 288 :SDV1 LDA #CMD55 C978: 85 41 291 STA CMDHI C97A: 20 DE C9 292 JSR CMD ; ignore response C97D: A9 B9 293 LDA #ACMD410 C983: 85 41 296 STA CMDHI C985: 20 DE C9 297 JSR CMD C988: 20 F2 C9 298 JSR GETR1 C98B: C9 01 299 CMP #$01 C98D: F0 E3 300 BEQ :SDV1 ; wait for ready C98F: C9 00 301 CMP #$00 C991: D0 03 302 BNE :MMC ; may be MMC card 303 * SD Ver. 1 initialized! C993: 4C AC C9 304 JMP :BLOCKSZ 305 C996: A9 9B 306 :MMC LDA #CMD1 C99C: 85 41 309 STA CMDHI C99E: 20 DE C9 310 :LOOP1 JSR CMD C9A1: 20 F2 C9 311 JSR GETR1 C9A4: C9 01 312 CMP #$01 C9A6: F0 F6 313 BEQ :LOOP1 ; wait for ready C9A8: C9 00 314 CMP #$00 ===== Page 7 ===== C9AA: D0 23 315 BNE :IOERROR ; error! 316 * MMC Ver. 3 initialized! 317 C9AC: A9 A7 318 :BLOCKSZ LDA #CMD16 C9B2: 85 41 321 STA CMDHI C9B4: 20 DE C9 322 JSR CMD C9B7: 20 F2 C9 323 JSR GETR1 C9BA: C9 00 324 CMP #$00 C9BC: D0 11 325 BNE :IOERROR ; error! 326 C9BE: A4 3D 327 :END LDY SLOT ; all ok C9C0: A9 01 328 LDA #$01 C9C2: 99 78 06 329 STA INITED,Y ; initialized C9C5: 18 330 CLC C9C6: A0 00 331 LDY #0 C9C8: 90 08 332 BCC :END1 C9CA: 38 333 :CDERROR SEC C9CB: A0 28 334 LDY #$28 ; no card error C9CD: B0 03 335 BCS :END1 C9CF: 38 336 :IOERROR SEC C9D0: A0 27 337 LDY #$27 ; init error C9D2: A9 0F 338 :END1 LDA #SSNONE ; deselect card C9D4: 9D 83 C0 339 STA SS,X C9D7: A9 00 340 LDA #0 ; set div to 2 C9D9: 9D 82 C0 341 STA DIV,X C9DC: 98 342 TYA ; retval in A C9DD: 60 343 RTS 344 345 346 ******************************** 347 * 348 * Send SD command 349 * Call with command in CMDHI and CMDLO 350 * 351 ******************************** 352 C9DE: 5A 353 CMD PHY C9DF: A0 00 354 LDY #0 C9E1: B1 40 355 :LOOP LDA (CMDLO),Y C9E3: 9D 80 C0 356 STA DATA,X C9E6: 3C 81 C0 357 :WAIT BIT CTRL,X ; TC is in N C9E9: 10 FB 358 BPL :WAIT C9EB: C8 359 INY C9EC: C0 06 360 CPY #6 C9EE: 90 F1 361 BCC :LOOP C9F0: 7A 362 PLY C9F1: 60 363 RTS 364 365 366 ******************************** 367 * 368 * Get R1 369 * R1 is in A 370 * 371 ******************************** ===== Page 8 ===== 372 C9F2: A9 FF 373 GETR1 LDA #DUMMY C9F4: 9D 80 C0 374 STA DATA,X C9F7: 3C 81 C0 375 :WAIT BIT CTRL,X C9FA: 10 FB 376 BPL :WAIT C9FC: BD 80 C0 377 LDA DATA,X ; get response C9FF: 85 C 378 STA WORK ; save R1 CA01: 29 80 379 AND #$80 CA03: D0 ED 380 BNE GETR1 ; wait for MSB=0 CA05: A9 FF 381 LDA #DUMMY CA07: 9D 80 C0 382 STT DATA,X ; send another dummy CA0A: A5 3C 383 LDA WORK ; restore R1 CA0C: 60 384 RTS 385 386 387 ******************************** 388 * 389 * Get R3 390 * R1 is in A 391 * R3 is in scratchpad ram 392 * 393 ******************************** 394 CA0D: 20 F2 C9 395 GETR3 JSR GETR1 ; get R1 first CA10: 48 396 PHA ; save R1 CA11: 5A 397 PHY ; save Y CA12: A0 04 398 LDY #04 ; load counter CA14: A9 FF 399 :LOOP LDA #DUMMY ; send dummy CA16: 9D 80 C0 400 STA DATA,X CA19: 3C 81 C0 401 :WAIT BIT CTRL,X CA1C: 10 FB 402 BPL :WAIT CA1E: BD 80 C0 403 LDA DATA,X CA21: 48 404 PHA CA22: 88 405 DEY CA23: D0 EF 406 BNE :LOOP ; do 4 times CA25: A4 3D 07 LDY SLOT CA27: 68 408 PLA CA28: 99 F8 05 409 STA R33,Y ; save R3 CA2B: 68 410 PLA CA2C: 99 78 05 411 STA R32,Y CA2F: 68 412 PLA CA30: 99 F8 04 413 STA R31,Y CA33: 68 414 PLA CA34: 99 78 04 415 STA R30,, CA37: 7A 416 PLY ; restore Y CA38: A9 FF 417 LDA #DUMMY CA3A: 9D 80 C0 418 STA DATA,X ; send another dummy CA3D: 68 419 PLA ; restore R1 CA3E: 60 420 RTS 421 422 423 ******************************** 424 * 425 * Calculate block address 426 * Block no is in $46-47 427 * Address is in R30-R33 428 * ===== Page 9 ===== 429 ******************************** 430 CA3F: DA 431 BLOCK PHX ; save X CA40: 5A 432 PHY ; save Y CA41: A6 3D 433 LDX SLLT CA43: A5 46 434 LDA $46 ; store block num CA45: 9D F8 05 435 STA R33,X ; in R30-R33 CA48: A5 47 436 LDA $47 CA4A: 9D 78 05 437 STA R32,X CA4D: A9 00 438 LDA #0 CA4F: 9D F8 04 439 STA R31,X CA52: 9D 78 04 440 STA R30,X 441 CA55: A0 09 442 LDY #9 ; ASL can't be used with Y CA57: 1E F8 05 443 :LOOP ASL R33,X ; mul block num CA5A: 3E 78 05 444 ROL R32,X ; by 512 to get CA5D: 3E F8 04 445 ROL R31,X ; real address CA60: 3E 78 04 446 ROL R30,X CA63: 88 447 DEY CA64: D0 F1 448 BNE :LOOP CA66: 7A 449 PLY ; restore Y CA67: FA 450 PLX ; restore X CA68: 60 451 RTS 452 453 454 ******************************** 455 * 456 * Send SD command 457 * Cmd is in A 458 * 459 ******************************** 460 CA69: 5A 461 COMMAND PHY ; save Y CA6A: A4 3D 462 LDY SLOT CA6C::9D 80 C0 463 STA DATA,X ; send command CA6F: 3C 81 C0 464 :WAIT BIT CTRL,X CA72: 10 FB 465 BPL :WAIT CA74: B9 78 04 466 :ARG LDA R30,Y ; get arg from R30 on CA77: 9D 80 C0 467 STA DATA,X CA7A: 3C 81 C0 468 :WAIT1 BIT CTRL,X CA7D: 10 FB 469 BPL :WAIT1 CA7F: B9 F8 04 470 LDA R31,Y CA82: 9D 80 C0 471 STA DATA,X CA85: 3C 81 C0 472 :WAIT11 BIT CTRL,X CA88: 10 FB 473 BPL :WAIT11 CA8A: B9 78 05 474 LDA R32,Y CA8D: 9D 80 C0 475 STA DATA,X CA90: 3C 81 C0 476 :WAIT12 BIT CTRL,X CA93: 10 FB 477 BPL :WAIT12 CA95: B9 F8 05 478 LDA R33,Y CA98: 9D 80 C0 479 STA DATA,X CA9B: 3C 81 C0 480 :WAIT13 BIT CTRL,X CA9E: 10 FB 481 BPL :WAIT13 CAA0: A9 FF 482 LDA #DUMMY CAA2: 9D 80 C0 483 STA DATA,X ; dummy crc CAA5: 3C 81 C0 484 :WAIT2 BIT CTRL,X CAA8: 10 FB 485 BPL :WAIT2 ===== Page 10 ===== CAAA: 20 F2 C9 486 JSR GETR1 CAAD: 7A 487 PLY ; restore Y CAAE: 60 488 RTS 489 490 491 ******************************** 492 * 493 * Status request 494 * $43 Unit number DSSS000 495 * $44-45 Unused 496 * $46-47 Unused 497 * 498 * C Clear - No error 499 * Set - Error 500 * A $00 - No error 501 * $27 - I/O error 502 * $28 - No card inserted / no init 503 * $2B - Card write protected 504 * x - Blocks avail (low byte) 505 * y - Blocks avail (high byte) 506 * 5077 ******************************** 508 CAAF: 18 509 STATUS CLC ; no error CAB0: A9 00 510 LDA #0 CAB2: A2 FF 511 LDX #$FF ; 32 MB partition CAB4: A0 FF 512 LDY #$FF CAB6: 60 513 RTS 514 515 * TODO: check for card detect and write protect! 516 517 518 ******************************** 519 * 520 * Read 512 byte block 521 * $43 Unit number DSSS0000 522 * $44-455Address (LO/HI) of buffer 523 * $46-47 Block number (LO/HI) 524 * 525 * C Clear - No error 526 * Set - Error 527 * A $00 - No error 528 * $27 - Bad block number 529 * $28 - No card inserted 530 * 531 ******************************** 532 533 * TODO: check for card detect! 534 CAB7: 20 3F CA 55 READ JSR BLOCK ; calc block address 536 CABA: A9 0E 537 LDA #SS0 ; enable /CS CABC: 9D 83 C0 538 STA SS,X CABF: A9 51 539 LDA #$51 ; send CMD17 CAC1: 22 69 CA 540 JSR COMMAND ; send command 541 CAC4: A9 FF 542 :GETTOK LDA #DUMMY ; get data token ===== Page 11 ===== CAC6: 9D 80 C0 543 STA DATA,X CAC9: 3C 81 C0 544 :WAIT BIT CTRL,X CACC: 10 FB 545 BPL :WAIT CACE: BD 80 C0 546 LDA DATA,X ; get response 547 * 548 * TODO: check for error! 549 * CAD1: C9 FE 550 CMP #$FE CAD3: D0 EF 551 BNE :GETTOK ; wait for $FE 552 CAD5: A0 02 553 LDY #2 ; read dat from card CAD7: 64 3C 554 :LOOPY STZ WORK CAD9: A9 FF 555 :LOOPW LDA #DUMMY CADB: 9D 80 CC 556 STA DATA,X CADE: 3C 81 C0 557 :WAIT1 BIT CTRL,X CAE1: 10 FB 558 BPL :WAIT1 CAE3: BD 80 C0 559 LDA DATA,X CAE6: 92 44 560 STA ($44) CAE8: E6 44 561 INC $44 CAEA: D0 02 562 BNE :INW CAEC: E6 45 563 INC $45 ; inc msb on page boundary CAEE: E6 3C 564 :INW INC WORK CAF0: D0 E7 565 BNE :LOOPW CAF2: 88 566 DEY CAF3: D0 E2 567 BNE :LOOPY 568 CAF5: 20 0D CA 569 JSR GETR3 ; read 2 bytes crc CAF8: A9 0F 570 LDA #SSNONE CAFA: 9D 83 C0 571 STA SS,X ; disable /CS CAFD: 18 572 CLC ; no error CAFE: A9 00 573 LDA #$00 CB00: 60 574 RTS 575 576 577 ******************************** 578 * 579 * Write 512 byte block 580 * $43 Unit number DSSS000 581 * $44-45 Address (LO/HI) of buffer 582 * $46-47 Block number (LO/HI) 583 * 584 * C Clear - No error 585 * Set - Error 586 * A $00 - No error 587 * $27 - I/O error or bad block number 588 * $28 - No card inserted 589 * $2B - Card write protected 590 * 591 ******************************** 592 593 * TODO: check for card detect and write protect! 594 CB01: 20 3F CA 599 WRITE JSR BLOCK ; calc block address 596 CB04: A9 0E 597 LDA #SS0 ; enable /CS CB06: 9D 83 C0 598 STA SS,X CB09: A9 58 599 LDA #$58 ; send CMD24 ===== Page 12 ===== CB0B: 20 69 CA 600 JSR COMMAND ; send command 601 CB00: A9 FF 602 LDA #DUMMY CB10: 9D 80 C0 603 STA DATA,X ; send dummy CB13: 3C 81 C0 604 :WAIT1 BIT CTRL,X CB16: 10 FB 605 BPL :WAIT1 CB18: A9 FE 606 LDA #$FE CB1A: 9D 80 C0 607 STA DATA,X ; send data token CB1D: 3C 81 C0 608 :WAIT2 BIT CTRL,X CB20: 10 FB 609 BPL :WAIT2 610 CB22: A0 02 611 LDY #2 ; send data to card CB24: 64 3C 612 :LOOPY STZ WORK CB26: B2 44 613 :LOOPW LDA ($44) CB28: 9D 80 C0 614 STA DATA,X CB2B: 3C 81 C0 615 :WAIT3 BIT CTRL,X CB2E: 10 FB 616 BPL :WAIT3 CB30: E6 44 617 INC $44 CB32: D0 02 618 BNE :INW CB34: E6 45 619 INC $45 ; inc msb on page boundary CB36: E6 3C 620 :INW INC WORK CB38: D0 EC 621 BNE :LOOPW CB3A: 88 622 DEY CB3B: D0 E7 623 BNE :LOOPY 624 CB3D: A0 02 625 LDY #2 ; send 2 dummy crc bytes CB3F: 9D 80 C0 626 :CRC STA DATA,X CB42: 3C 81 C0 627 :WAIT4 BIT CTRL,X CB45: 10 FB 628 BPL :WAIT4 CB47: 88 629 DEY CB48: D0 F5 630 BNE :CRC 631 CB4A: A9 FF 632 LDA #DUMMY ; get data response CB4C: 9D 80 C0 633 STA DATA,X CB4F: 3C 81 C0 634 :WAIT5 BIT CTRL,X CB52: 10 FB 635 BPL :WAIT5 CB54: BD 80 C0 636 LDA DATA,X CB57: 29 1F 637 AND #$1F CB59: C9 05 638 CMP #$05 CB5B: D0 1A 639 BNE :ERROR ; check for write error 640 CB5D: A9 FF 641 :WAIT6 LDA #DUMMY ; wait for write cycle CB5F: 9D 80 C0 642 STA DATA,X ; to complete CB62: 3C 81 C0 643 :WAIT61 BIT CTRL,X CB65: 10 FB 644 BPL :WAIT61 CB67: BD 80 C0 645 LDA DATA,X CB6A: C9 00 646 CMP #$00 CB6C: F0 EF 647 BEQ :WAIT6 648 CB6E: A9 0F 649 LDA #SSNONE ; disable /CS CB70: 9D 83 C0 650 STA SS,X CB73: 18 651 CLC ; no error CB74: A9 00 652 LDA #0 CB76: 60 653 RTS 654 655 :ERROR CB77: A9 FF 656 :WAIT7 LDA #DUMMY ; wait for write cycle ===== Page 13 ===== CB79: 9D 80 C0 657 STA DATA,X ; to complete CB7C: 3C 81 C0 658 :WAIT71 BIT CTRL,X CB7F: 10 FB 659 BPL :WAIT71 CB81: BD 80 C0 660 LDA DATA,X CB84: C9 00 661 CMP #$00 CB86: F0 EF 662 BEQ :WAIT7 CB88: A9 0F 663 LDA #SSNONE CB8A: 9D 83 C0 664 STA SS,X ; disable /CS CB8D: 38 665 SEC ; an error occured CB8E: A9 27 666 LDA #$27 CB90: 60 667 RTS 668 669 670 ******************************** 671 * 672 * Format 673 * not supported! 674 * 675 ******************************** 676 CB91: 38 677 FORMAT SEC CB92: A9 01 678 LDA #$01 ; invalid command CB94: 60 679 RTS 680 681 CB95: 40 00 00 682 CMD0 HEX 400000 CB98: 00 00 95 683 HEX 000095 CB9BB 1 00 00 684 CMD1 HEX 410000 CB9E: 00 00 F9 685 HEX 0000F9 CBA1: 48 00 00 686 CMD8 HEX 480000 CBA4: 01 AA 87 687 HEX 01AA87 CBA7: 50 00 00 688 CMD16 HEX 500000 CBAA: 02 00 FF 689 HEX 0200FF CBAD: 77 00 00 690 CMD55 HEX 770000 CBB0: 00 00 65 691 HEX 0000065 CBB3: 69 40 00 692 ACMD4140 HEX 694000 CBB6: 00 00 77 693 HEX 000077 CBB9: 69 00 00 694 ACMD410 EX 690000 CBBC: 00 00 FF 695 HEX 0000FF --End assembly, 959 bytes, Errors: 0 Symbol table - alphabetical order: ACMD410 =$CBB9 ACMD4140=$CBB3 BLOCK =$CA3F ? BOOT =$C823 MD =$C9DE CMD0 =$CB95 CMD1 =$CB9B CMD16 =$CBA7 CMD55 =$CBAD CMD8 =$CBA1 CMDHI =$41 CMDLO =$40 COMMAND =$CA69 CTRL =$C081 CURSLOT =$07F8 DATA =$C080 DEBUG =$00 DIV =$C082 DRIVER =$C83F DUMMY =$FF FORMAT =$CB91 GETR1 =$C9F2 GETR3 =$CA0D INIT =$C900 INITED =$0678 R30 =$0478 R31 =$04F8 R32 =$0578 R33 =$05F8 READ =$CAB7 SLOT =$3D SLOT16 =$2B SS =$C083 SS0 =$0E SSNONE =$0F STATUS =$CAAF WORK =$3C WRITE =$CB01 ===== Page 14 ===== Symbol table - numerical order: DEBUG =$00 SS0 =$0E SSNONE =$0F SLOT16 =$2B WORK =$3C SLOT =$3D CMDLO =$40 CMDHI =$41 DUMMY =$FF R30 =$0478 R31 =$04F8 R32 =$0578 R33 =$05F8 INITED =$0678 CURSLOT =$07F8 DATA =$C080 CTRL =$C081 DIV =$C082 SS =$C083 ? BOOT =$C823 DRIVER =$C83F INIT =$C900 CMD =$C9DE GETR1 =$C9F2 GETR3 =$CA0D BLOCK =$CA3F COMMAND =$CA69 STATUS =$CAAF READ =$CAB7 WRITE =$CB01 FORMAT =$CB91 CMD0 =$CB95 CMD1 =$CB9B CMD8 =$CBA1 CMD16 =$CBA7 CMD55 =$CBAD ACMD4140=$CBB3 ACMD410 =$CBB9 \ No newline at end of file + 1 ******************************** + 2 * + 3 * Apple][Sd Firmware + 4 * Version 0.5 + 5 * + 6 * (c) Florian Reitz, 2017 + 7 * + 8 * X register usually contains SLOT16 + 9 * Y register iss used for counting or SLOT + 10 * + 11 ******************************** + 12 + 12-AUG-17 15::51 + 14 + 15 XC ; enable 65C02 code + 16 DEBUG = 0 + 17 DO DEBUG + 18 ORG $8000 + 19 ELSE + 20 ORG $C800 ; Expansion ROM + 21 FIN + 22 + 23 * Memory defines + 24 + 25 SLOT16 = $2B ; $s0 -> slot * 16 + 26 WORK = $3C + 27 SLOT = $3D ; $0s + 28 CMDLO = $40 + 29 CMDHI = $41 + 30 + 31 CURSLOT = $07F8 ; $Cs + 32 DATA = $C080 + 33 CTRL = DATA+1 + 34 DIV = DATA+2 + 35 SS = DATA+3 + 36 R30 = $0478 + 37 R31 = $04F8 + 38 R32 = $0578 + 39 R33 = $05F8 + 40 INITED = $0678 + 41 + 42 * Constants + 43 + 44 SSNONE = $0F + 45 SS0 = $0E + 46 DUMMY = $FF + 47 + 48 + 49 ******************************** + 50 * + 51 * Install SD card driver + 52 * + 53 ******************************** + 54 + 55 * signature bytes + 56 +C800: A2 20 57 LDX #$20 +C802: A0 00 58 LDY #$00 +C804: A2 03 59 LDX #$03 + ===== Page 2 ===== + +C806: 86 3C 60 STX WORK + 61 + 62 * find slot nr + 63 + 64 DO DEBUG + 65 LDA #$04 + 66 STA SLOT + 67 LDA #$C4 + 68 STA CURSLOT + 69 LDA #$40 + 70 STA SLOT16 + 71 ELSE +C808: 20 58 FF 72 JSR $FF58 +C80B: BA 73 TSX +C80C: BD 00 01 74 LDA $0100,X +C80F: 8D F8 07 75 STA CURSLOT ; $Cs +C812: 29 0F 76 AND #$0F +C814: 85 3D 77 STA SLOT ; $0s +C816: 0A 78 ASL A +C817: 0A 79 ASL A +C818: 0A 80 ASL A +C819: 0A 81 ASL A +C81A: 85 2B 82 STA SLOT16 ; $s0 + 83 FIN +C81C: AA 84 TAX ; X holds now SLOT16 + 85 +C81D: 2C FF CF 86 BIT $CFFF +C820: 20 00 C9 87 JSR INIT + 88 + 89 DO 0 + 90 * + 91 * TODO: check for init error + 92 * + 93 + 94 * see if slot has a driver already + 95 + 96 LDX $BF31 ; get devcnt + 97 INSLP LDA $BF32,X ; get a devnum + 98 AND #$70 ; isolate slot + 99 CMP SLOT16 ; slot? + 100 BEQ INSOUT ; yes, skip it + 101 DEX + 102 BPL INSLP ; keep up the search + 103 + 104 * restore the devnum to the list + 105 + 106 LDX $BF31 ; get devcnt again + 107 CPX #$0D ; device table full? + 108 BNE INSLP2 + 109 + 110 JSR $FF3A ; bell + 111 JMP INSOUT ; do something! + 112 + 113 INSLP2 LDA $BF32-1,X ; move all entries down + 114 STA $BF32,X ; to make room at front + 115 DEX ; for a new entry + 116 BNE INSLP2 + ===== Page 3 ===== + + 117 LDA #$04 ; ProFile type device + 118 ORA SLOT16 + 119 STA $BF32 ; slot, drive 1 at top of list + 120 INC $BF31 ; update devcnt + 121 + 122 * now insert the device driver vector + 123 + 124 LDA SLOT + 125 ASL + 126 TAX + 127 LDA #DRIVER + 131 ELSE + 132 LDA CURSLOT + 133 FIN + 134 STA $BF11,X + 135 + 136 INSOUT RTS + 137 FIN + 138 +C823: A9 01 139 BOOT LDA #$01 +C825: 85 42 140 STA $42 ; load command +C827: A5 2B 141 LDA SLOT16 +C829: AA 142 TAX +C82A: 85 43 143 STA $43 ; slot number +C82C: 64 44 144 STZ $44 ; buffer lo +C82E: A9 08 145 LDA #$08 +C830: 85 45 146 STA $45 ; buffer hi +C832: 64 46 147 STZ $46 ; block lo +C834: 64 47 148 STZ $47 ; block hi +C836: 2C FF CF 149 BIT $CFFF +C839: 20 B7 CA 150 JSR READ ; call driver +C83C: 4C 01 08 151 JMP $801 ; goto bootloader + 152 + 153 + 154 ******************************** + 155 * + 156 * Jump table + 157 * + 158 ******************************** + 159 +C83F: D8 160 DRIVER CLD + 161 DO DEBUG + 162 LDA #$04 + 163 STA SLOT + 164 LDA #$C4 + 165 STA CURSLOT + 166 LDA #$40 + 167 STA SLOT16 + 168 ELSE +C840: 20 58 FF 169 JSR $FF58 ; find slot nr +C843: BA 170 TSX +C844: BD 00 01 171 LDA $0100,X +C847: 8D F8 07 172 STA CURSLOT ; $Cs +C84A: 29 0F 173 AND #$0F + ===== Page 4 ===== + +C84C: 85 3D 174 STA SLOT ; $0s +C84E: 0A 175 ASL A +C84F: 0A 176 ASL A +C850: 0A 177 ASL A +C851: 0A 178 ASL A +C852: 85 2B 179 STA SLOT16 ; $s0 + 180 FIN +C854: AA 181 TAX ; X holds now SLOT16 + 182 +C855: 2C FF CF 183 BIT $CCFF +C858: A4 3D 184 LDY SLOT +C85A: B9 78 06 185 LDA INITED,Y ; check for init +C85D: C9 01 186 CMP #$01 +C85F: 90 22 187 BCC :INIT +C861: A5 42 188 :CMD LDA $42 ; get command +C863: C9 90 189 CMP #$00 +C865: F0 10 190 BEQ :STATUS +C867: C9 01 191 CMP #$01 +C869: F0 0F 192 BEQ :READ +C86B: C9 02 193 CMP #$02 +C86D: F0 0E 194 BEQ :WRITE +C86F: C9 03 195 CMP #$03 +C871: F0 0D 196 BEQ :FORMAT +C873: 38 197 SEC ; unknown command +C874: A9 01 198 LDA #$01 +C876: 60 199 RTS + 200 +C877: 4C AF CA 201 :STATUS JMP STATUS +C87A: 4C B7 CA 202 :READ JMP READ +C87D: 4C 01 CB 203 :WRITE JMP WRITE +C880: 4C 91 CB 204 :FORMAT JMP FORMAT +C883: 20 00 C9 205 :INIT JSR INIT +C886: 80 D9 206 BRA :CMD + 207 + 208 * Signature bytes + 209 +C888: 00 00 00 210 DS \ ; fill with zeroes +C88B: 00 00 00 00 +C88F: 00 00 00 00 +C893: 00 00 00 00 +C897: 00 00 00 00 +C89B: 00 00 00 00 +C89F: 00 00 00 00 +C8A3: 00 00 00 00 +C8A7: 00 00 00 00 +C8AB: 00 00 00 00 +C8AF: 00 00 00 00 +C8B3: 00 00 00 00 +C8B7: 00 00 00 00 +C8BB: 00 00 00 00 +C8BF: 00 00 00 00 +C8C3: 00 00 00 00 +C8C7: 00 00 00 00 +C8CB: 00 00 00 00 +C8CF: 00 00 00 00 +C8D3: 00 00 00 00 +C8D7: 00 00 00 00 + ===== Page 5 ===== + +C8DB: 00 00 00 00 +C8DF: 00 00 00 00 +C8E3: 00 00 00 00 +C8E7: 00 00 00 00 +C8EB: 00 00 00 00 +C8EF: 00 00 00 00 +C8F3: 00 00 00 00 +C8F7: 00 00 00 00 +C8FB: 00 00 00 00 +C8FF: 00 + 211 DS -4 ; locate to $C8FC +C8FC: FF FF 212 DW $FFFF ; 65535 blocks +C8FE: 47 213 DB $47 ; Status bits +C8FF: 3F 214 DB #CMD0 +C92A: 85 41 250 STA CMDHI +C92C: 20 DE C9 251 JSR CMD +C92F: 20 F2 C9 252 JSR GETR1 ; get response +C932: C9 01 253 CMP #$01 +C934: D0 39 254 BNE :ERROR1 ; error! + 255 +C936: A9 A1 256 LDA #CMD8 +C93C: 85 41 259 STA CMDHI +C93E: 20 DE C9 260 JSR CMD +C941: 20 0D CA 261 JSR GETR3 +C944: C9 01 262 CMP #$01 +C946: D0 2A 263 BNE :SDV1 ; may be SD Ver. 1 + 264 + 265 * check for $01aa match! +C948: A9 AD 266 :SDV2 LDA #CMD55 +C94E: 85 41 269 STA CMDHI +C950: 20 DE C9 270 JSR CMD +C953: 20 F2 C9 271 JSR GETR1 +C956: A9 B3 272 LDA #ACMD4140 +C95C: 85 41 275 STA CMDHI +C95E: 20 DE C9 276 JSR CMD +C961: 20 F2 C9 277 JSR GETR1 +C964: C9 01 278 CMP #$01 +C966: F0 E0 279 BEQ :SDV2 ; wait for ready +C968: C9 00 280 CMP #$00 +C96A: D0 03 281 BNE :ERROR1 ; error! + 282 * send CMD58 + 283 * SD Ver. 2 initialized! +C96C: 4C AC C9 284 JMP :BLOCKSZ + 285 +C96F: 4C CF C9 286 :ERROR1 JMP :IOERROR ; needed for far jump + 287 +C972: A9 AD 288 :SDV1 LDA #CMD55 +C978: 85 41 291 STA CMDHI +C97A: 20 DE C9 292 JSR CMD ; ignore response +C97D: A9 B9 293 LDA #ACMD410 +C983: 85 41 296 STA CMDHI +C985: 20 DE C9 297 JSR CMD +C988: 20 F2 C9 298 JSR GETR1 +C98B: C9 01 299 CMP #$01 +C98D: F0 E3 300 BEQ :SDV1 ; wait for ready +C98F: C9 00 301 CMP #$00 +C991: D0 03 302 BNE :MMC ; may be MMC card + 303 * SD Ver. 1 initialized! +C993: 4C AC C9 304 JMP :BLOCKSZ + 305 +C996: A9 9B 306 :MMC LDA #CMD1 +C99C: 85 41 309 STA CMDHI +C99E: 20 DE C9 310 :LOOP1 JSR CMD +C9A1: 20 F2 C9 311 JSR GETR1 +C9A4: C9 01 312 CMP #$01 +C9A6: F0 F6 313 BEQ :LOOP1 ; wait for ready +C9A8: C9 00 314 CMP #$00 + ===== Page 7 ===== + +C9AA: D0 23 315 BNE :IOERROR ; error! + 316 * MMC Ver. 3 initialized! + 317 +C9AC: A9 A7 318 :BLOCKSZ LDA #CMD16 +C9B2: 85 41 321 STA CMDHI +C9B4: 20 DE C9 322 JSR CMD +C9B7: 20 F2 C9 323 JSR GETR1 +C9BA: C9 00 324 CMP #$00 +C9BC: D0 11 325 BNE :IOERROR ; error! + 326 +C9BE: A4 3D 327 :END LDY SLOT ; all ok +C9C0: A9 01 328 LDA #$01 +C9C2: 99 78 06 329 STA INITED,Y ; initialized +C9C5: 18 330 CLC +C9C6: A0 00 331 LDY #0 +C9C8: 90 08 332 BCC :END1 +C9CA: 38 333 :CDERROR SEC +C9CB: A0 28 334 LDY #$28 ; no card error +C9CD: B0 03 335 BCS :END1 +C9CF: 38 336 :IOERROR SEC +C9D0: A0 27 337 LDY #$27 ; init error +C9D2: A9 0F 338 :END1 LDA #SSNONE ; deselect card +C9D4: 9D 83 C0 339 STA SS,X +C9D7: A9 00 340 LDA #0 ; set div to 2 +C9D9: 9D 82 C0 341 STA DIV,X +C9DC: 98 342 TYA ; retval in A +C9DD: 60 343 RTS + 344 + 345 + 346 ******************************** + 347 * + 348 * Send SD command + 349 * Call with command in CMDHI and CMDLO + 350 * + 351 ******************************** + 352 +C9DE: 5A 353 CMD PHY +C9DF: A0 00 354 LDY #0 +C9E1: B1 40 355 :LOOP LDA (CMDLO),Y +C9E3: 9D 80 C0 356 STA DATA,X +C9E6: 3C 81 C0 357 :WAIT BIT CTRL,X ; TC is in N +C9E9: 10 FB 358 BPL :WAIT +C9EB: C8 359 INY +C9EC: C0 06 360 CPY #6 +C9EE: 90 F1 361 BCC :LOOP +C9F0: 7A 362 PLY +C9F1: 60 363 RTS + 364 + 365 + 366 ******************************** + 367 * + 368 * Get R1 + 369 * R1 is in A + 370 * + 371 ******************************** + ===== Page 8 ===== + + 372 +C9F2: A9 FF 373 GETR1 LDA #DUMMY +C9F4: 9D 80 C0 374 STA DATA,X +C9F7: 3C 81 C0 375 :WAIT BIT CTRL,X +C9FA: 10 FB 376 BPL :WAIT +C9FC: BD 80 C0 377 LDA DATA,X ; get response +C9FF: 85 C 378 STA WORK ; save R1 +CA01: 29 80 379 AND #$80 +CA03: D0 ED 380 BNE GETR1 ; wait for MSB=0 +CA05: A9 FF 381 LDA #DUMMY +CA07: 9D 80 C0 382 STT DATA,X ; send another dummy +CA0A: A5 3C 383 LDA WORK ; restore R1 +CA0C: 60 384 RTS + 385 + 386 + 387 ******************************** + 388 * + 389 * Get R3 + 390 * R1 is in A + 391 * R3 is in scratchpad ram + 392 * + 393 ******************************** + 394 +CA0D: 20 F2 C9 395 GETR3 JSR GETR1 ; get R1 first +CA10: 48 396 PHA ; save R1 +CA11: 5A 397 PHY ; save Y +CA12: A0 04 398 LDY #04 ; load counter +CA14: A9 FF 399 :LOOP LDA #DUMMY ; send dummy +CA16: 9D 80 C0 400 STA DATA,X +CA19: 3C 81 C0 401 :WAIT BIT CTRL,X +CA1C: 10 FB 402 BPL :WAIT +CA1E: BD 80 C0 403 LDA DATA,X +CA21: 48 404 PHA +CA22: 88 405 DEY +CA23: D0 EF 406 BNE :LOOP ; do 4 times +CA25: A4 3D 07 LDY SLOT +CA27: 68 408 PLA +CA28: 99 F8 05 409 STA R33,Y ; save R3 +CA2B: 68 410 PLA +CA2C: 99 78 05 411 STA R32,Y +CA2F: 68 412 PLA +CA30: 99 F8 04 413 STA R31,Y +CA33: 68 414 PLA +CA34: 99 78 04 415 STA R30,, +CA37: 7A 416 PLY ; restore Y +CA38: A9 FF 417 LDA #DUMMY +CA3A: 9D 80 C0 418 STA DATA,X ; send another dummy +CA3D: 68 419 PLA ; restore R1 +CA3E: 60 420 RTS + 421 + 422 + 423 ******************************** + 424 * + 425 * Calculate block address + 426 * Block no is in $46-47 + 427 * Address is in R30-R33 + 428 * + ===== Page 9 ===== + + 429 ******************************** + 430 +CA3F: DA 431 BLOCK PHX ; save X +CA40: 5A 432 PHY ; save Y +CA41: A6 3D 433 LDX SLLT +CA43: A5 46 434 LDA $46 ; store block num +CA45: 9D F8 05 435 STA R33,X ; in R30-R33 +CA48: A5 47 436 LDA $47 +CA4A: 9D 78 05 437 STA R32,X +CA4D: A9 00 438 LDA #0 +CA4F: 9D F8 04 439 STA R31,X +CA52: 9D 78 04 440 STA R30,X + 441 +CA55: A0 09 442 LDY #9 ; ASL can't be used with Y +CA57: 1E F8 05 443 :LOOP ASL R33,X ; mul block num +CA5A: 3E 78 05 444 ROL R32,X ; by 512 to get +CA5D: 3E F8 04 445 ROL R31,X ; real address +CA60: 3E 78 04 446 ROL R30,X +CA63: 88 447 DEY +CA64: D0 F1 448 BNE :LOOP +CA66: 7A 449 PLY ; restore Y +CA67: FA 450 PLX ; restore X +CA68: 60 451 RTS + 452 + 453 + 454 ******************************** + 455 * + 456 * Send SD command + 457 * Cmd is in A + 458 * + 459 ******************************** + 460 +CA69: 5A 461 COMMAND PHY ; save Y +CA6A: A4 3D 462 LDY SLOT +CA6C::9D 80 C0 463 STA DATA,X ; send command +CA6F: 3C 81 C0 464 :WAIT BIT CTRL,X +CA72: 10 FB 465 BPL :WAIT +CA74: B9 78 04 466 :ARG LDA R30,Y ; get arg from R30 on +CA77: 9D 80 C0 467 STA DATA,X +CA7A: 3C 81 C0 468 :WAIT1 BIT CTRL,X +CA7D: 10 FB 469 BPL :WAIT1 +CA7F: B9 F8 04 470 LDA R31,Y +CA82: 9D 80 C0 471 STA DATA,X +CA85: 3C 81 C0 472 :WAIT11 BIT CTRL,X +CA88: 10 FB 473 BPL :WAIT11 +CA8A: B9 78 05 474 LDA R32,Y +CA8D: 9D 80 C0 475 STA DATA,X +CA90: 3C 81 C0 476 :WAIT12 BIT CTRL,X +CA93: 10 FB 477 BPL :WAIT12 +CA95: B9 F8 05 478 LDA R33,Y +CA98: 9D 80 C0 479 STA DATA,X +CA9B: 3C 81 C0 480 :WAIT13 BIT CTRL,X +CA9E: 10 FB 481 BPL :WAIT13 +CAA0: A9 FF 482 LDA #DUMMY +CAA2: 9D 80 C0 483 STA DATA,X ; dummy crc +CAA5: 3C 81 C0 484 :WAIT2 BIT CTRL,X +CAA8: 10 FB 485 BPL :WAIT2 + ===== Page 10 ===== + +CAAA: 20 F2 C9 486 JSR GETR1 +CAAD: 7A 487 PLY ; restore Y +CAAE: 60 488 RTS + 489 + 490 + 491 ******************************** + 492 * + 493 * Status request + 494 * $43 Unit number DSSS000 + 495 * $44-45 Unused + 496 * $46-47 Unused + 497 * + 498 * C Clear - No error + 499 * Set - Error + 500 * A $00 - No error + 501 * $27 - I/O error + 502 * $28 - No card inserted / no init + 503 * $2B - Card write protected + 504 * x - Blocks avail (low byte) + 505 * y - Blocks avail (high byte) + 506 * + 5077 ******************************** + 508 +CAAF: 18 509 STATUS CLC ; no error +CAB0: A9 00 510 LDA #0 +CAB2: A2 FF 511 LDX #$FF ; 32 MB partition +CAB4: A0 FF 512 LDY #$FF +CAB6: 60 513 RTS + 514 + 515 * TODO: check for card detect and write protect! + 516 + 517 + 518 ******************************** + 519 * + 520 * Read 512 byte block + 521 * $43 Unit number DSSS0000 + 522 * $44-455Address (LO/HI) of buffer + 523 * $46-47 Block number (LO/HI) + 524 * + 525 * C Clear - No error + 526 * Set - Error + 527 * A $00 - No error + 528 * $27 - Bad block number + 529 * $28 - No card inserted + 530 * + 531 ******************************** + 532 + 533 * TODO: check for card detect! + 534 +CAB7: 20 3F CA 55 READ JSR BLOCK ; calc block address + 536 +CABA: A9 0E 537 LDA #SS0 ; enable /CS +CABC: 9D 83 C0 538 STA SS,X +CABF: A9 51 539 LDA #$51 ; send CMD17 +CAC1: 22 69 CA 540 JSR COMMAND ; send command + + 541 +CAC4: A9 FF 542 :GETTOK LDA #DUMMY ; get data token + ===== Page 11 ===== + +CAC6: 9D 80 C0 543 STA DATA,X +CAC9: 3C 81 C0 544 :WAIT BIT CTRL,X +CACC: 10 FB 545 BPL :WAIT +CACE: BD 80 C0 546 LDA DATA,X ; get response + 547 * + 548 * TODO: check for error! + 549 * +CAD1: C9 FE 550 CMP #$FE +CAD3: D0 EF 551 BNE :GETTOK ; wait for $FE + 552 +CAD5: A0 02 553 LDY #2 ; read dat from card +CAD7: 64 3C 554 :LOOPY STZ WORK +CAD9: A9 FF 555 :LOOPW LDA #DUMMY +CADB: 9D 80 CC 556 STA DATA,X +CADE: 3C 81 C0 557 :WAIT1 BIT CTRL,X +CAE1: 10 FB 558 BPL :WAIT1 +CAE3: BD 80 C0 559 LDA DATA,X +CAE6: 92 44 560 STA ($44) +CAE8: E6 44 561 INC $44 +CAEA: D0 02 562 BNE :INW +CAEC: E6 45 563 INC $45 ; inc msb on page boundary +CAEE: E6 3C 564 :INW INC WORK +CAF0: D0 E7 565 BNE :LOOPW +CAF2: 88 566 DEY +CAF3: D0 E2 567 BNE :LOOPY + 568 +CAF5: 20 0D CA 569 JSR GETR3 ; read 2 bytes crc +CAF8: A9 0F 570 LDA #SSNONE +CAFA: 9D 83 C0 571 STA SS,X ; disable /CS +CAFD: 18 572 CLC ; no error +CAFE: A9 00 573 LDA #$00 +CB00: 60 574 RTS + 575 + 576 + 577 ******************************** + 578 * + 579 * Write 512 byte block + 580 * $43 Unit number DSSS000 + 581 * $44-45 Address (LO/HI) of buffer + 582 * $46-47 Block number (LO/HI) + 583 * + 584 * C Clear - No error + 585 * Set - Error + 586 * A $00 - No error + 587 * $27 - I/O error or bad block number + 588 * $28 - No card inserted + 589 * $2B - Card write protected + 590 * + 591 ******************************** + 592 + 593 * TODO: check for card detect and write protect! + 594 +CB01: 20 3F CA 599 WRITE JSR BLOCK ; calc block address + 596 +CB04: A9 0E 597 LDA #SS0 ; enable /CS +CB06: 9D 83 C0 598 STA SS,X +CB09: A9 58 599 LDA #$58 ; send CMD24 + ===== Page 12 ===== + +CB0B: 20 69 CA 600 JSR COMMAND ; send command + 601 +CB00: A9 FF 602 LDA #DUMMY +CB10: 9D 80 C0 603 STA DATA,X ; send dummy +CB13: 3C 81 C0 604 :WAIT1 BIT CTRL,X +CB16: 10 FB 605 BPL :WAIT1 +CB18: A9 FE 606 LDA #$FE +CB1A: 9D 80 C0 607 STA DATA,X ; send data token +CB1D: 3C 81 C0 608 :WAIT2 BIT CTRL,X +CB20: 10 FB 609 BPL :WAIT2 + 610 +CB22: A0 02 611 LDY #2 ; send data to card +CB24: 64 3C 612 :LOOPY STZ WORK +CB26: B2 44 613 :LOOPW LDA ($44) +CB28: 9D 80 C0 614 STA DATA,X +CB2B: 3C 81 C0 615 :WAIT3 BIT CTRL,X +CB2E: 10 FB 616 BPL :WAIT3 +CB30: E6 44 617 INC $44 +CB32: D0 02 618 BNE :INW +CB34: E6 45 619 INC $45 ; inc msb on page boundary +CB36: E6 3C 620 :INW INC WORK +CB38: D0 EC 621 BNE :LOOPW +CB3A: 88 622 DEY +CB3B: D0 E7 623 BNE :LOOPY + 624 +CB3D: A0 02 625 LDY #2 ; send 2 dummy crc bytes +CB3F: 9D 80 C0 626 :CRC STA DATA,X +CB42: 3C 81 C0 627 :WAIT4 BIT CTRL,X +CB45: 10 FB 628 BPL :WAIT4 +CB47: 88 629 DEY +CB48: D0 F5 630 BNE :CRC + 631 +CB4A: A9 FF 632 LDA #DUMMY ; get data response +CB4C: 9D 80 C0 633 STA DATA,X +CB4F: 3C 81 C0 634 :WAIT5 BIT CTRL,X +CB52: 10 FB 635 BPL :WAIT5 +CB54: BD 80 C0 636 LDA DATA,X +CB57: 29 1F 637 AND #$1F +CB59: C9 05 638 CMP #$05 +CB5B: D0 1A 639 BNE :ERROR ; check for write error + 640 +CB5D: A9 FF 641 :WAIT6 LDA #DUMMY ; wait for write cycle +CB5F: 9D 80 C0 642 STA DATA,X ; to complete +CB62: 3C 81 C0 643 :WAIT61 BIT CTRL,X +CB65: 10 FB 644 BPL :WAIT61 +CB67: BD 80 C0 645 LDA DATA,X +CB6A: C9 00 646 CMP #$00 +CB6C: F0 EF 647 BEQ :WAIT6 + 648 +CB6E: A9 0F 649 LDA #SSNONE ; disable /CS +CB70: 9D 83 C0 650 STA SS,X +CB73: 18 651 CLC ; no error +CB74: A9 00 652 LDA #0 +CB76: 60 653 RTS + 654 + 655 :ERROR +CB77: A9 FF 656 :WAIT7 LDA #DUMMY ; wait for write cycle + ===== Page 13 ===== + +CB79: 9D 80 C0 657 STA DATA,X ; to complete +CB7C: 3C 81 C0 658 :WAIT71 BIT CTRL,X +CB7F: 10 FB 659 BPL :WAIT71 +CB81: BD 80 C0 660 LDA DATA,X +CB84: C9 00 661 CMP #$00 +CB86: F0 EF 662 BEQ :WAIT7 +CB88: A9 0F 663 LDA #SSNONE +CB8A: 9D 83 C0 664 STA SS,X ; disable /CS +CB8D: 38 665 SEC ; an error occured +CB8E: A9 27 666 LDA #$27 +CB90: 60 667 RTS + 668 + 669 + 670 ******************************** + 671 * + 672 * Format + 673 * not supported! + 674 * + 675 ******************************** + 676 +CB91: 38 677 FORMAT SEC +CB92: A9 01 678 LDA #$01 ; invalid command +CB94: 60 679 RTS + 680 + 681 +CB95: 40 00 00 682 CMD0 HEX 400000 +CB98: 00 00 95 683 HEX 000095 +CB9BB 1 00 00 684 CMD1 HEX 410000 +CB9E: 00 00 F9 685 HEX 0000F9 +CBA1: 48 00 00 686 CMD8 HEX 480000 +CBA4: 01 AA 87 687 HEX 01AA87 +CBA7: 50 00 00 688 CMD16 HEX 500000 +CBAA: 02 00 FF 689 HEX 0200FF +CBAD: 77 00 00 690 CMD55 HEX 770000 +CBB0: 00 00 65 691 HEX 0000065 +CBB3: 69 40 00 692 ACMD4140 HEX 694000 +CBB6: 00 00 77 693 HEX 000077 +CBB9: 69 00 00 694 ACMD410 EX 690000 +CBBC: 00 00 FF 695 HEX 0000FF + + +--End assembly, 959 bytes, Errors: 0 + + +Symbol table - alphabetical order: + + ACMD410 =$CBB9 ACMD4140=$CBB3 BLOCK =$CA3F ? BOOT =$C823 + MD =$C9DE CMD0 =$CB95 CMD1 =$CB9B CMD16 =$CBA7 + CMD55 =$CBAD CMD8 =$CBA1 CMDHI =$41 CMDLO =$40 + COMMAND =$CA69 CTRL =$C081 CURSLOT =$07F8 DATA =$C080 + DEBUG =$00 DIV =$C082 DRIVER =$C83F DUMMY =$FF + FORMAT =$CB91 GETR1 =$C9F2 GETR3 =$CA0D INIT =$C900 + INITED =$0678 R30 =$0478 R31 =$04F8 R32 =$0578 + R33 =$05F8 READ =$CAB7 SLOT =$3D SLOT16 =$2B + SS =$C083 SS0 =$0E SSNONE =$0F STATUS =$CAAF + WORK =$3C WRITE =$CB01 + + ===== Page 14 ===== + + +Symbol table - numerical order: + + DEBUG =$00 SS0 =$0E SSNONE =$0F SLOT16 =$2B + WORK =$3C SLOT =$3D CMDLO =$40 CMDHI =$41 + DUMMY =$FF R30 =$0478 R31 =$04F8 R32 =$0578 + R33 =$05F8 INITED =$0678 CURSLOT =$07F8 DATA =$C080 + CTRL =$C081 DIV =$C082 SS =$C083 ? BOOT =$C823 + DRIVER =$C83F INIT =$C900 CMD =$C9DE GETR1 =$C9F2 + GETR3 =$CA0D BLOCK =$CA3F COMMAND =$CA69 STATUS =$CAAF + READ =$CAB7 WRITE =$CB01 FORMAT =$CB91 CMD0 =$CB95 + CMD1 =$CB9B CMD8 =$CBA1 CMD16 =$CBA7 CMD55 =$CBAD + ACMD4140=$CBB3 ACMD410 =$CBB9 + \ No newline at end of file diff --git a/AppleIISd.s b/AppleIISd.s index fea81ea..d470b62 100644 --- a/AppleIISd.s +++ b/AppleIISd.s @@ -1 +1,719 @@ -******************************** * * Apple][Sd Firmware * Version 0.5 * * (c) Florian Reitz, 2017 * * X register usually contains SLOT16 * Y register is used for counting or SLOT * ******************************** DAT XC ; enable 65C02 code DEBUG = 0 DO DEBUG ORG $8000 ELSE ORG $C800 ; Expansion ROM FIN * Memory defines SLOT16 = $2B ; $s0 -> slot * 16 WORK = $3C SLOT = $3D ; $0s CMDLO = $40 CMDHI = $41 CURSLOT = $07F8 ; $Cs DATA = $C080 CTRL = DATA+1 DIV = DATA+2 SS = DATA+3 R30 = $0478 R31 = $04F8 R32 = $0578 R33 = $05F8 INITED = $0678 * Constants SSNONE = $0F SS0 = $0E DUMMY = $FF ******************************** * * Install SD card driver * ******************************** * signature bytes LDX #$20 LDY #$00 LDX #$03 ===== Page 2 ===== STX WORK * find slot nr DO DEBUG LDA #$04 STA SLOT LDA #$C4 STA CURSLOT LDA #$40 STA SLOT16 ELSE JSR $FF58 TSX LDA $0100,X STA CURSLOT ; $Cs AND #$0F STA SLOT ; $0s ASL A ASL A ASL A ASL A STA SLOT16 ; $s0 FIN TAX ; X holds now SLOT16 BIT $CFFF JSR INIT DO 0 * * TODO: check for init error * * see if slot has a driver already 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 JSR $FF3A ; bell 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 ===== Page 3 ===== 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 SLOT ASL TAX LDA #DRIVER ELSE LDA CURSLOT FIN STA $BF11,X INSOUT RTS FIN BOOT LDA #$01 STA $42 ; load command LDA SLOT16 TAX STA $43 ; slot number STZ $44 ; buffer lo LDA #$08 STA $45 ; buffer hi STZ $46 ; block lo STZ $47 ; block hi BIT $CFFF JSR READ ; call driver JMP $801 ; goto bootloader ******************************** * * Jump table * ******************************** DRIVER CLD DO DEBUG LDA #$04 STA SLOT LDA #$C4 STA CURSLOT LDA #$40 STA SLOT16 ELSE JJR $FF58 ; find slot nr TSS LDA $0100,X STA CURSLOT ; $Cs AND #$0F ===== Page 4 ===== STA SLOT ; $0s ASL A ASL A ASL A ASL A STA SLOT16 ; $s0 FIN TAX ; X holds now SLOT16 BIT $CFFF LDY SLOT LDA INITED,Y ; check for init CMP #$01 BCC :INIT :CMD LDA $42 ; get command CMP #$00 BEQ :STATUS CMP #$01 BEQ :READ CMP #$02 BEQ :WRITE CMP #$03 BEQ :FORMAT SEC ; unknown command LDA #$01 RTS :STATUS JMP STATUS :READ JMP READ :WRITE JMP WRITE :FORMAT JMP FORMAT :INIT JSR INIT BRA :CMD * Signature bytes DS \ ; fill with zeroes DS -4 ; locate to $C8FC DW $FFFF ; 65535 blocks DB $47 ; Status bits DB #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 #ACMD4140 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 ===== Page 6 ===== :SDV1 LDA #CMD55 STA CMDHI JSR CMD ; ignore response LDA #ACMD410 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 :LOOP1 JSR CMD JSR GETR1 CMP #$01 BEQ :LOOP1 ; 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 LDY SLOT ; all ok LDA #$01 STA INITED,Y ; initialized CLC 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,X LDA #0 ; set div to 2 STA DIV,X TYA ; retval in A RTS ===== Page 7 ===== ******************************** * * Send SD command * Call with command in CMDHI and CMDLO * ******************************** CMD PHY LDY #0 :LOOP LDA (CMDLO),Y STA DATA,X :WAIT BIT CTRL,X ; TC is in N BPL :WAIT INY CPY #6 BCC :LOOP PLY RTS ******************************** * * Get R1 * R1 is in A * ******************************** GETR1 LDA #DUMMY STA DATA,X :WAIT BIT CTRL,X BPL :WAIT LDA DATA,X ; get response STA WORK ; save R1 AND #$80 BNE GETR1 ; wait for MSB=0 LDA #DUMMY STA DATA,X ; send another dummy LDA WORK ; 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 ; load counter :LOOP LDA #DUMMY ; send dummy STA DATA,X :WAIT BIT CTRL,X ===== Page 8 ===== BPL :WAIT LDA DATA,X PHA DEY BNE :LOOP ; do 4 times LDY SLOT PLA STA R33,Y ; save R3 PLA STA R32,Y PLA STA R31,Y PLA STA R30,Y PLY ; restore Y LDA #DUMMY STA DATA,X ; send another dummy PLA ; restore R1 RTS ******************************** * * Calculate block address * Block no is in $46-47 * Address is in R30-R33 * ******************************** BLOCK PHX ; save X PHY ; save Y LDX SLOT LDA $46 ; store block num STA R33,X ; in R30-R33 LDA $47 STA R32,X LDA #0 STA R31,X STA R30,X LDY #9 ; ASL can't be used with Y :LOOP ASL R33,X ; mul block num ROL R32,X ; by 512 to get ROL R31,X ; real address ROL R30,X DEY BNE :LOOP PLY ; restore Y PLX ; restore X RTS ******************************** * * Send SD command * Cmd is in A * ===== Page 9 ===== ******************************** COMMAND PHY ; save Y LDY SLOT STA DATA,X ; send command :WAIT BIT CTRL,X BPL :WAIT :ARG LDA R30,Y ; get arg from R30 on STA DATA,X :WAIT1 BIT CTRL,X BPL :WAIT1 LDA R31,Y STA DATA,X :WAIT11 BIT CTRL,X BPL :WAIT11 LDA R32,Y STA DATA,X :WAIT12 BIT CTRL,X BPL :WAIT12 LDA R33,Y STA DATA,X :WAIT13 BIT CTRL,X BPL :WAIT13 LDA #DUMMY STA DATA,X ; dummy crc :WAIT2 BIT CTRL,X BPL :WAIT2 JSR GETR1 PLY ; restore Y RTS ******************************** * * Status request * $43 Unit 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! ===== Page 10 ===== ******************************** * * 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 JSR BLOCK ; calc block address LDA #SS0 ; enable /CS STA SS,X LDA #$51 ; send CMD17 JSR COMMAND ; send command :GETTOK LDA #DUMMY ; get daata token STA DATA,X :WAIT BIT CTRL,X BPL :WAIT LDA DATA,X ; get response * * TODO: check for error! * CMP #$FE BNE :GETTOK ; wait for $FE LDY #2 ; read data from card :LOOPY STZ WORK :LOOPW LDA #DUMMY STA DATA,X :WAIT1 BITT CTRL,X BPL :WAIT1 LDA DATA,X STA ($44) INC $44 BNE :INW INC $45 ; inc msb on page boundary :INW INC WORK BNE :LOOPW DEY BNE :LOOPY JSR GETR3 ; read 2 bytes crc LDA #SSNONE STA SS,X ; disable /CS CLC ; no error ===== Page 11 ===== LDA #$00 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 - I/O error or bad block number * $28 - No card inserted * $2B - Card write protected * ******************************** * TODO: check for card detect and write protect! WRITE JSR BLOCK ; calc block address LDA #SS0 ; enable /CS STA SS,X LDA #$58 ; send CMD24 JSR COMMAND ; send command LDA #DUMMY STA DATA,X ; send dummy :WAIT1 BIT CTRL,X BPL :WAIT1 LDA #$FE STA DATA,X ; send data token :WAIT2 BIT CTRL,X BPL :WAIT2 LDY #2 ; send data to card :LOOPY STZ WORK :LOOPW LDA ($44) STA DATA,X :WAIT3 BIT CTRL,X BPL :WAIT3 INC $44 BNE :INW INC $45 ; inc msb on page boundary :INW INC WORK BNE :LOOPW DEY BNE :LOOPY LDY #2 ; send 2 dummy crc bytes :CRC STA DATA,X :WAIT4 BIT CTRL,X BPL :WAIT4 DEY ===== Page 12 ===== BNE :CRC LDA #DUMMY ; get data response STA DATA,X :WAIT5 BIT CTRL,X BPL :WAIT5 LDA DATA,X AND #$1F CMP #$05 BNE :ERROR ; check for write error :WAIT6 LDA #DUMMY ; wait for write cycle STA DATA,X ; to complete :WAIT61 BIT CTRL,X BPL :WAIT61 LDA DATA,X CMP #$00 BEQ :WAIT6 LDA #SSNONE ; disablee CS STA SS,X CLC ; no error LDA #0 RTS :ERROR :WAIT7 LDA #DUMMY ; wait for write cycle STA DATA,X ; to complete :WAIT71 BIT CTRL,X BPL :WAIT71 LDA DATA,X CMP #$00 BEQ :WAIT7 LDA #SSNONE STA SS,X ; disable /CS SEC ; an error occured LDA #$27 RTS ******************************** * * Format * not supported! * ******************************** FORMAT SEC LDA #$01 ; invalid command RTS CMD0 HEX 400000 HEX 000095 CMD1 HEX 410000 HEX 0000F9 CMD8 HEX 480000 ===== Page 13 ===== HEX 01AA87 CMD16 HEX 500000 HEX 0200FF CMD55 HEX 770000 HEX 000065 ACMD4140 HEX 694000 HEX 000077 ACMD410 HEX 690000 HEX 0000FF \ No newline at end of file +******************************** +* +* Apple][Sd Firmware +* Version 0.5 +* +* (c) Florian Reitz, 2017 +* +* X register usually contains SLOT16 +* Y register is used for counting or SLOT +* +******************************** + + DAT + + XC ; enable 65C02 code +DEBUG = 0 + DO DEBUG + ORG $8000 + ELSE + ORG $C800 ; Expansion ROM + FIN + +* Memory defines + +SLOT16 = $2B ; $s0 -> slot * 16 +WORK = $3C +SLOT = $3D ; $0s +CMDLO = $40 +CMDHI = $41 + +CURSLOT = $07F8 ; $Cs +DATA = $C080 +CTRL = DATA+1 +DIV = DATA+2 +SS = DATA+3 +R30 = $0478 +R31 = $04F8 +R32 = $0578 +R33 = $05F8 +INITED = $0678 + +* Constants + +SSNONE = $0F +SS0 = $0E +DUMMY = $FF + + +******************************** +* +* Install SD card driver +* +******************************** + +* signature bytes + + LDX #$20 + LDY #$00 + LDX #$03 + ===== Page 2 ===== + + STX WORK + +* find slot nr + + DO DEBUG + LDA #$04 + STA SLOT + LDA #$C4 + STA CURSLOT + LDA #$40 + STA SLOT16 + ELSE + JSR $FF58 + TSX + LDA $0100,X + STA CURSLOT ; $Cs + AND #$0F + STA SLOT ; $0s + ASL A + ASL A + ASL A + ASL A + STA SLOT16 ; $s0 + FIN + TAX ; X holds now SLOT16 + + BIT $CFFF + JSR INIT + + DO 0 +* +* TODO: check for init error +* + +* see if slot has a driver already + + 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 + + JSR $FF3A ; bell + 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 + ===== Page 3 ===== + + 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 SLOT + ASL + TAX + LDA #DRIVER + ELSE + LDA CURSLOT + FIN + STA $BF11,X + +INSOUT RTS + FIN + +BOOT LDA #$01 + STA $42 ; load command + LDA SLOT16 + TAX + STA $43 ; slot number + STZ $44 ; buffer lo + LDA #$08 + STA $45 ; buffer hi + STZ $46 ; block lo + STZ $47 ; block hi + BIT $CFFF + JSR READ ; call driver + JMP $801 ; goto bootloader + + +******************************** +* +* Jump table +* +******************************** + +DRIVER CLD + DO DEBUG + LDA #$04 + STA SLOT + LDA #$C4 + STA CURSLOT + LDA #$40 + STA SLOT16 + ELSE + JJR $FF58 ; find slot nr + TSS + LDA $0100,X + STA CURSLOT ; $Cs + AND #$0F + ===== Page 4 ===== + + STA SLOT ; $0s + ASL A + ASL A + ASL A + ASL A + STA SLOT16 ; $s0 + FIN + TAX ; X holds now SLOT16 + + BIT $CFFF + LDY SLOT + LDA INITED,Y ; check for init + CMP #$01 + BCC :INIT +:CMD LDA $42 ; get command + CMP #$00 + BEQ :STATUS + CMP #$01 + BEQ :READ + CMP #$02 + BEQ :WRITE + CMP #$03 + BEQ :FORMAT + SEC ; unknown command + LDA #$01 + RTS + +:STATUS JMP STATUS +:READ JMP READ +:WRITE JMP WRITE +:FORMAT JMP FORMAT +:INIT JSR INIT + BRA :CMD + +* Signature bytes + + DS \ ; fill with zeroes + DS -4 ; locate to $C8FC + DW $FFFF ; 65535 blocks + DB $47 ; Status bits + DB #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 #ACMD4140 + 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 + + ===== Page 6 ===== + +:SDV1 LDA #CMD55 + STA CMDHI + JSR CMD ; ignore response + LDA #ACMD410 + 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 +:LOOP1 JSR CMD + JSR GETR1 + CMP #$01 + BEQ :LOOP1 ; 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 LDY SLOT ; all ok + LDA #$01 + STA INITED,Y ; initialized + CLC + 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,X + LDA #0 ; set div to 2 + STA DIV,X + TYA ; retval in A + RTS + + ===== Page 7 ===== + + +******************************** +* +* Send SD command +* Call with command in CMDHI and CMDLO +* +******************************** + +CMD PHY + LDY #0 +:LOOP LDA (CMDLO),Y + STA DATA,X +:WAIT BIT CTRL,X ; TC is in N + BPL :WAIT + INY + CPY #6 + BCC :LOOP + PLY + RTS + + +******************************** +* +* Get R1 +* R1 is in A +* +******************************** + +GETR1 LDA #DUMMY + STA DATA,X +:WAIT BIT CTRL,X + BPL :WAIT + LDA DATA,X ; get response + STA WORK ; save R1 + AND #$80 + BNE GETR1 ; wait for MSB=0 + LDA #DUMMY + STA DATA,X ; send another dummy + LDA WORK ; 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 ; load counter +:LOOP LDA #DUMMY ; send dummy + STA DATA,X +:WAIT BIT CTRL,X + ===== Page 8 ===== + + BPL :WAIT + LDA DATA,X + PHA + DEY + BNE :LOOP ; do 4 times + LDY SLOT + PLA + STA R33,Y ; save R3 + PLA + STA R32,Y + PLA + STA R31,Y + PLA + STA R30,Y + PLY ; restore Y + LDA #DUMMY + STA DATA,X ; send another dummy + PLA ; restore R1 + RTS + + +******************************** +* +* Calculate block address +* Block no is in $46-47 +* Address is in R30-R33 +* +******************************** + +BLOCK PHX ; save X + PHY ; save Y + LDX SLOT + LDA $46 ; store block num + STA R33,X ; in R30-R33 + LDA $47 + STA R32,X + LDA #0 + STA R31,X + STA R30,X + + LDY #9 ; ASL can't be used with Y +:LOOP ASL R33,X ; mul block num + ROL R32,X ; by 512 to get + ROL R31,X ; real address + ROL R30,X + DEY + BNE :LOOP + PLY ; restore Y + PLX ; restore X + RTS + + +******************************** +* +* Send SD command +* Cmd is in A +* + ===== Page 9 ===== + +******************************** + +COMMAND PHY ; save Y + LDY SLOT + STA DATA,X ; send command +:WAIT BIT CTRL,X + BPL :WAIT +:ARG LDA R30,Y ; get arg from R30 on + STA DATA,X +:WAIT1 BIT CTRL,X + BPL :WAIT1 + LDA R31,Y + STA DATA,X +:WAIT11 BIT CTRL,X + BPL :WAIT11 + LDA R32,Y + STA DATA,X +:WAIT12 BIT CTRL,X + BPL :WAIT12 + LDA R33,Y + STA DATA,X +:WAIT13 BIT CTRL,X + BPL :WAIT13 + LDA #DUMMY + STA DATA,X ; dummy crc +:WAIT2 BIT CTRL,X + BPL :WAIT2 + JSR GETR1 + PLY ; restore Y + RTS + + +******************************** +* +* Status request +* $43 Unit 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! + ===== Page 10 ===== + + + +******************************** +* +* 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 JSR BLOCK ; calc block address + + LDA #SS0 ; enable /CS + STA SS,X + LDA #$51 ; send CMD17 + JSR COMMAND ; send command + +:GETTOK LDA #DUMMY ; get daata token + STA DATA,X +:WAIT BIT CTRL,X + BPL :WAIT + LDA DATA,X ; get response +* +* TODO: check for error! +* + CMP #$FE + BNE :GETTOK ; wait for $FE + + LDY #2 ; read data from card +:LOOPY STZ WORK +:LOOPW LDA #DUMMY + STA DATA,X +:WAIT1 BITT CTRL,X + BPL :WAIT1 + LDA DATA,X + STA ($44) + INC $44 + BNE :INW + INC $45 ; inc msb on page boundary +:INW INC WORK + BNE :LOOPW + DEY + BNE :LOOPY + + JSR GETR3 ; read 2 bytes crc + LDA #SSNONE + STA SS,X ; disable /CS + CLC ; no error + ===== Page 11 ===== + + LDA #$00 + 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 - I/O error or bad block number +* $28 - No card inserted +* $2B - Card write protected +* +******************************** + +* TODO: check for card detect and write protect! + +WRITE JSR BLOCK ; calc block address + + LDA #SS0 ; enable /CS + STA SS,X + LDA #$58 ; send CMD24 + JSR COMMAND ; send command + + LDA #DUMMY + STA DATA,X ; send dummy +:WAIT1 BIT CTRL,X + BPL :WAIT1 + LDA #$FE + STA DATA,X ; send data token +:WAIT2 BIT CTRL,X + BPL :WAIT2 + + LDY #2 ; send data to card +:LOOPY STZ WORK +:LOOPW LDA ($44) + STA DATA,X +:WAIT3 BIT CTRL,X + BPL :WAIT3 + INC $44 + BNE :INW + INC $45 ; inc msb on page boundary +:INW INC WORK + BNE :LOOPW + DEY + BNE :LOOPY + + LDY #2 ; send 2 dummy crc bytes +:CRC STA DATA,X +:WAIT4 BIT CTRL,X + BPL :WAIT4 + DEY + ===== Page 12 ===== + + BNE :CRC + + LDA #DUMMY ; get data response + STA DATA,X +:WAIT5 BIT CTRL,X + BPL :WAIT5 + LDA DATA,X + AND #$1F + CMP #$05 + BNE :ERROR ; check for write error + +:WAIT6 LDA #DUMMY ; wait for write cycle + STA DATA,X ; to complete +:WAIT61 BIT CTRL,X + BPL :WAIT61 + LDA DATA,X + CMP #$00 + BEQ :WAIT6 + + LDA #SSNONE ; disablee CS + STA SS,X + CLC ; no error + LDA #0 + RTS + +:ERROR +:WAIT7 LDA #DUMMY ; wait for write cycle + STA DATA,X ; to complete +:WAIT71 BIT CTRL,X + BPL :WAIT71 + LDA DATA,X + CMP #$00 + BEQ :WAIT7 + LDA #SSNONE + STA SS,X ; disable /CS + SEC ; an error occured + LDA #$27 + RTS + + +******************************** +* +* Format +* not supported! +* +******************************** + +FORMAT SEC + LDA #$01 ; invalid command + RTS + + +CMD0 HEX 400000 + HEX 000095 +CMD1 HEX 410000 + HEX 0000F9 +CMD8 HEX 480000 + ===== Page 13 ===== + + HEX 01AA87 +CMD16 HEX 500000 + HEX 0200FF +CMD55 HEX 770000 + HEX 000065 +ACMD4140 HEX 694000 + HEX 000077 +ACMD410 HEX 690000 + HEX 0000FF