AppleIISd/AppleIISd.s
2017-08-13 13:34:15 +02:00

720 lines
19 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

********************************
*
* 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
STA $BF10,X ; write to driver table
DO DEBUG
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 #<DRIVER ; LSB of driver
********************************
*
* Initialize SD card
*
* C Clear - No error
* Set - Error
* A $00 - No error
* $27 - I/O error - Init failed
* $28 - No card inserted
*
********************************
INIT CLD
LDA #$03 ; set SPI mode 3
===== Page 5 =====
STA CTRL,X
LDA #SSNONE
STA SS,X
LDA #7
STA DIV,X
LDY #10
LDA #DUMMY
:LOOP STA DATA,X
:WAIT BIT CTRL,X
BPL :WAIT
DEY
BNE :LOOP ; do 10 times
LDA #SS0 ; set CS low
STA SS,X
LDA #<CMD0 ; send CMD0
STA CMDLO
LDA #>CMD0
STA CMDHI
JSR CMD
JSR GETR1 ; get response
CMP #$01
BNE :ERROR1 ; error!
LDA #<CMD8 ; send CMD8
STA CMDLO
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 CMDLO
LDA #>CMD55
STA CMDHI
JSR CMD
JSR GETR1
LDA #<ACMD4140
STA CMDLO
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 CMDLO
LDA #>CMD55
STA CMDHI
JSR CMD ; ignore response
LDA #<ACMD410
STA CMDLO
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 CMDLO
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 CMDLO
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