AppleIISd/AppleIISd.s

881 lines
21 KiB
ArmAsm
Raw Normal View History

2017-08-13 11:34:15 +00:00
********************************
*
* Apple][Sd Firmware
* Version 0.8
2017-08-13 11:34:15 +00:00
*
* (c) Florian Reitz, 2017
*
* X register usually contains SLOT16
* Y register is used for counting or SLOT
*
********************************
2017-08-26 11:07:42 +00:00
DAT
2017-08-13 11:34:15 +00:00
2017-08-26 11:07:42 +00:00
XC ; enable 65C02 code
DEBUG = 0
DO DEBUG
ORG $8000
ELSE
ORG $C700 ; Expansion ROM
2017-08-26 11:07:42 +00:00
FIN
2017-08-13 11:34:15 +00:00
* Memory defines
2017-08-26 11:07:42 +00:00
SLOT16 = $2B ; $s0 -> slot * 16
SLOT = $3D ; $0s
CMDLO = $40
CMDHI = $41
2017-10-15 14:48:13 +00:00
DCMD = $42 ; Command code
BUFFER = $44 ; Buffer address
BLOCK = $46 ; Block number
2017-08-26 11:07:42 +00:00
CURSLOT = $07F8 ; $Cs
DATA = $C080
CTRL = DATA+1
DIV = DATA+2
SS = DATA+3
R30 = $0478
R31 = $04F8
R32 = $0578
R33 = $05F8
2017-08-13 11:34:15 +00:00
* Constants
2017-08-26 11:07:42 +00:00
DUMMY = $FF
2017-08-27 13:02:58 +00:00
FRX = $10 ; CTRL register
ECE = $04
SS0 = $01 ; SS register
WP = $20
CD = $40
2017-08-27 13:02:58 +00:00
INITED = $80
2017-08-13 11:34:15 +00:00
* signature bytes
LDX #$20
LDY #$00
LDX #$03
2017-11-20 18:13:16 +00:00
LDY #$3C
* find slot nr
DO DEBUG
LDA #$04
STA SLOT
LDA #$C4
STA CURSLOT
LDA #$40
ELSE
JSR $FF58
TSX
LDA $0100,X
STA CURSLOT ; $Cs
AND #$0F
STA SLOT ; $0s
ASL A
ASL A
ASL A
ASL A
FIN
STA SLOT16 ; $s0
TAX ; X holds now SLOT16
BIT $CFFF
JSR CARDDET
BCC :INIT
LDA #$2F ; no card inserted
BRK
:INIT JSR INIT
********************************
*
* Install SD card driver
*
********************************
DO DEBUG
* see if slot has a driver already
LDX $BF31 ; get devcnt
INSTALL LDA $BF32,X ; get a devnum
AND #$70 ; isolate slot
CMP SLOT16 ; slot?
BEQ :INSOUT ; yes, skip it
DEX
BPL INSTALL ; keep up the search
* restore the devnum to the list
LDX $BF31 ; get devcnt again
CPX #$0D ; device table full?
BNE :INST2
JSR $FF3A ; bell
JMP :INSOUT ; do something!
:INST2 LDA $BF32-1,X ; move all entries down
STA $BF32,X ; to make room at front
DEX ; for a new entry
BNE :INST2
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
LDA #>DRIVER
STA $BF11,X
:INSOUT RTS
********************************
*
* Boot from SD card
*
********************************
ELSE
2017-11-20 18:13:16 +00:00
BOOT BEQ :DRAW ; check for error
BRK
2017-11-20 18:13:16 +00:00
:DRAW LDY #0 ; display copyright message
:DRAW1 LDA TEXT,Y
BEQ :BOOT1 ; check for NULL
STA $07D0,Y ; put on last line
INY
BPL :DRAW1
:BOOT1 LDA #$01
STA DCMD ; load command
LDX SLOT16
2017-11-20 18:13:16 +00:00
STX $43 ; slot number
LDA #$08
STA BUFFER+1 ; buffer hi
STZ BUFFER ; buffer lo
STZ BLOCK+1 ; block hi
STZ BLOCK ; block lo
BIT $CFFF
JSR READ ; call driver
2017-11-20 18:13:16 +00:00
LDA #$01
STA DCMD ; load command
LDX SLOT16
STX $43 ; slot number
LDA #$0A
STA BUFFER+1 ; buffer hi
STZ BUFFER ; buffer lo
STZ BLOCK+1 ; block hi
LDA #$01
STA BLOCK ; block lo
BIT $CFFF
JSR READ ; call driver
LDX SLOT16
JMP $801 ; goto bootloader
FIN
********************************
*
* Jump table
*
********************************
DRIVER CLD
:SAVEZP PHA ; make room for retval
LDA SLOT16 ; save all ZP locations
PHA
LDA SLOT
PHA
LDA CMDLO
PHA
LDA CMDHI
PHA
DO DEBUG
LDA #$04
STA SLOT
LDA #$C4
STA CURSLOT
LDA #$40
ELSE
JSR $FF58 ; find slot nr
TSX
LDA $0100,X
STA CURSLOT ; $Cs
AND #$0F
STA SLOT ; $0s
ASL A
ASL A
ASL A
ASL A
FIN
STA SLOT16 ; $s0
TAX ; X holds now SLOT16
BIT $CFFF
JSR CARDDET
BCC :INITED
LDA #$2F ; no card inserted
SEC
BRA :RESTZP
:INITED LDA #INITED ; check for init
BIT SS,X
BEQ :INIT
:CMD LDA DCMD ; get command
CMP #0
BEQ :STATUS
CMP #1
BEQ :READ
CMP #2
BEQ :WRITE
CMP #3
BEQ :FORMAT
CMP #$FF
BEQ :TEST
LDA #1 ; unknown command
SEC
BRA :RESTZP
:STATUS JSR STATUS
BRA :RESTZP
:READ JSR READ
BRA :RESTZP
:WRITE JSR WRITE
BRA :RESTZP
:FORMAT JSR FORMAT
BRA :RESTZP
:TEST JSR TEST ; do device test
BRA :RESTZP
:INIT JSR INIT
BCC :CMD ; init ok
:RESTZP TSX
STA $105,X ; save retval on stack
PLA ; restore all ZP locations
STA CMDHI
PLA
STA CMDLO
PLA
STA SLOT
PLA
STA SLOT16
PLA ; get retval
RTS
* Signature bytes
DS \ ; fill with zeroes
DS -4 ; locate to $xxFC
2017-11-20 18:13:16 +00:00
DW $0 ; use status call
DB $07 ; Status bits
DB #<DRIVER ; LSB of driver
2017-08-13 11:34:15 +00:00
********************************
*
* Initialize SD card
*
* C Clear - No error
* Set - Error
* A $00 - No error
* $27 - I/O error - Init failed
2017-10-03 15:46:50 +00:00
* $2F - No card inserted
2017-08-13 11:34:15 +00:00
*
********************************
2017-08-26 11:07:42 +00:00
INIT CLD
LDA #$03 ; set SPI mode 3
STA CTRL,X
2017-08-27 13:02:58 +00:00
LDA SS,X
ORA #SS0 ; set CS high
2017-08-26 11:07:42 +00:00
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
2017-08-27 13:02:58 +00:00
LDA SS,X
AND #$FF!SS0 ; set CS low
2017-08-26 11:07:42 +00:00
STA SS,X
LDA #<CMD0 ; send CMD0
STA CMDLO
LDA #>CMD0
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1 ; get response
CMP #$01
BNE :ERROR1 ; error!
LDA #<CMD8 ; send CMD8
STA CMDLO
LDA #>CMD8
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR3
CMP #$01
BNE :SDV1 ; may be SD Ver. 1
2017-08-13 11:34:15 +00:00
* check for $01aa match!
2017-08-26 11:07:42 +00:00
:SDV2 LDA #<CMD55
STA CMDLO
LDA #>CMD55
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1
LDA #<ACMD4140
STA CMDLO
LDA #>ACMD4140
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1
CMP #$01
BEQ :SDV2 ; wait for ready
CMP #0
2017-08-26 11:07:42 +00:00
BNE :ERROR1 ; error!
2017-08-13 11:34:15 +00:00
* send CMD58
* SD Ver. 2 initialized!
2017-08-26 11:07:42 +00:00
JMP :BLOCKSZ
:ERROR1 JMP :IOERROR ; needed for far jump
:SDV1 LDA #<CMD55
STA CMDLO
LDA #>CMD55
STA CMDHI
JSR SDCMD ; ignore response
2017-08-26 11:07:42 +00:00
LDA #<ACMD410
STA CMDLO
LDA #>ACMD410
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1
CMP #$01
BEQ :SDV1 ; wait for ready
CMP #0
2017-08-26 11:07:42 +00:00
BNE :MMC ; may be MMC card
2017-08-13 11:34:15 +00:00
* SD Ver. 1 initialized!
2017-08-26 11:07:42 +00:00
JMP :BLOCKSZ
:MMC LDA #<CMD1
STA CMDLO
LDA #>CMD1
STA CMDHI
:LOOP1 JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1
CMP #$01
BEQ :LOOP1 ; wait for ready
CMP #0
2017-08-26 11:07:42 +00:00
BNE :IOERROR ; error!
2017-08-13 11:34:15 +00:00
* MMC Ver. 3 initialized!
2017-08-26 11:07:42 +00:00
:BLOCKSZ LDA #<CMD16
STA CMDLO
LDA #>CMD16
STA CMDHI
JSR SDCMD
2017-08-26 11:07:42 +00:00
JSR GETR1
CMP #0
2017-08-26 11:07:42 +00:00
BNE :IOERROR ; error!
2017-10-03 15:46:50 +00:00
:END LDA SS,X
2017-08-27 13:02:58 +00:00
ORA #INITED ; initialized
STA SS,X
LDA CTRL,X
ORA #ECE ; enable 7MHz
STA CTRL,X
CLC ; all ok
2017-08-26 11:07:42 +00:00
LDY #0
BCC :END1
:IOERROR SEC
LDY #$27 ; init error
2017-08-27 13:02:58 +00:00
:END1 LDA SS,X ; set CS high
ORA #SS0
2017-08-26 11:07:42 +00:00
STA SS,X
LDA #0 ; set div to 2
STA DIV,X
TYA ; retval in A
RTS
2017-08-13 11:34:15 +00:00
********************************
*
* Send SD command
* Call with command in CMDHI and CMDLO
*
********************************
SDCMD PHY
2017-08-26 11:07:42 +00:00
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
2017-08-13 11:34:15 +00:00
********************************
*
* Get R1
* R1 is in A
*
********************************
2017-08-26 11:07:42 +00:00
GETR1 LDA #DUMMY
STA DATA,X
:WAIT BIT CTRL,X
BPL :WAIT
LDA DATA,X ; get response
BIT #$80
2017-08-26 11:07:42 +00:00
BNE GETR1 ; wait for MSB=0
PHA
2017-08-26 11:07:42 +00:00
LDA #DUMMY
STA DATA,X ; send another dummy
PLA ; restore R1
2017-08-26 11:07:42 +00:00
RTS
2017-08-13 11:34:15 +00:00
********************************
*
* Get R3
* R1 is in A
* R3 is in scratchpad ram
*
********************************
2017-08-26 11:07:42 +00:00
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
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
2017-08-13 11:34:15 +00:00
********************************
*
* Calculate block address
* Unit number is in $43 DSSS0000
2017-08-13 11:34:15 +00:00
* Block no is in $46-47
* Address is in R30-R33
*
********************************
2017-10-15 14:48:13 +00:00
GETBLOCK PHX ; save X
2017-08-26 11:07:42 +00:00
PHY ; save Y
LDX SLOT
2017-10-15 14:48:13 +00:00
LDA BLOCK ; store block num
2017-08-26 11:07:42 +00:00
STA R33,X ; in R30-R33
2017-10-15 14:48:13 +00:00
LDA BLOCK+1
2017-08-26 11:07:42 +00:00
STA R32,X
LDA #0
STA R31,X
STA R30,X
LDA #$80 ; drive number
BIT $43
BEQ :SHIFT ; D1
LDA #1 ; D2
STA R31,X
:SHIFT LDY #9 ; ASL can't be used with Y
2017-08-26 11:07:42 +00:00
: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
2017-08-13 11:34:15 +00:00
********************************
*
* Send SD command
* Cmd is in A
2017-08-26 11:07:42 +00:00
*
2017-08-13 11:34:15 +00:00
********************************
2017-08-26 11:07:42 +00:00
COMMAND PHY ; save Y
LDY SLOT
STA DATA,X ; send command
LDA R30,Y ; get arg from R30 on
2017-08-26 11:07:42 +00:00
STA DATA,X
LDA R31,Y
STA DATA,X
LDA R32,Y
STA DATA,X
LDA R33,Y
STA DATA,X
LDA #DUMMY
STA DATA,X ; dummy crc
JSR GETR1
PLY ; restore Y
RTS
2017-08-13 11:34:15 +00:00
********************************
*
* Check for card detect
*
* C Clear - card in slot
* Set - no card in slot
*
********************************
CARDDET PHA
LDA #CD ; 0: card in
BIT SS,X ; 1: card out
CLC
BEQ :DONE ; card is in
SEC ; card is out
:DONE PLA
RTS
********************************
*
* Check for write protect
*
* C Clear - card not protected
* Set - card write protected
*
********************************
WRPROT PHA
LDA #WP ; 0: write enabled
BIT SS,X ; 1: write disabled
CLC
BEQ :DONE
SEC
:DONE PLA
RTS
2017-08-13 11:34:15 +00:00
********************************
*
* Status request
* $43 Unit number DSSS000
* $44-45 Unused
* $46-47 Unused
*
* C Clear - No error
* Set - Error
* A $00 - No error
* $2B - Card write protected
2017-10-03 15:46:50 +00:00
* $2F - No card inserted
* X - Blocks avail (low byte)
* Y - Blocks avail (high byte)
2017-08-13 11:34:15 +00:00
*
********************************
STATUS LDA #0 ; no error
2017-08-26 11:07:42 +00:00
LDX #$FF ; 32 MB partition
LDY #$FF
2017-08-13 11:34:15 +00:00
JSR WRPROT
BCC :DONE
LDA #$2B ; card write protected
:DONE RTS
2017-08-13 11:34:15 +00:00
********************************
*
* 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
*
********************************
READ JSR GETBLOCK ; calc block address
2017-08-13 11:34:15 +00:00
2017-08-27 13:02:58 +00:00
LDA SS,X ; enable /CS
AND #$FF!SS0
2017-08-26 11:07:42 +00:00
STA SS,X
LDA #$51 ; send CMD17
JSR COMMAND ; send command
BNE :ERROR ; check for error
2017-08-26 11:07:42 +00:00
:GETTOK LDA #DUMMY ; get data token
STA DATA,X
LDA DATA,X ; get response
CMP #$FE
BNE :GETTOK ; wait for $FE
2017-08-27 13:02:58 +00:00
LDA CTRL,X ; enable FRX
ORA #FRX
STA CTRL,X
LDA #DUMMY
2017-08-26 11:07:42 +00:00
STA DATA,X
LDY #0
:LOOP1 LDA DATA,X ; read data from card
STA (BUFFER),Y
INY
BNE :LOOP1
2017-10-15 14:48:13 +00:00
INC BUFFER+1 ; inc msb on page boundary
:LOOP2 LDA DATA,X
STA (BUFFER),Y
INY
BNE :LOOP2
DEC BUFFER+1
2017-08-26 11:07:42 +00:00
:CRC LDA DATA,X ; read two bytes crc
LDA DATA,X ; and ignore
LDA DATA,X ; read a dummy byte
2017-08-27 13:02:58 +00:00
LDA CTRL,X ; disable FRX
AND #$FF!FRX
STA CTRL,X
CLC ; no error
LDA #0
:DONE PHP
PHA
2017-08-27 13:02:58 +00:00
LDA SS,X
ORA #SS0
2017-08-26 11:07:42 +00:00
STA SS,X ; disable /CS
PLA
PLP
2017-08-26 11:07:42 +00:00
RTS
2017-08-13 11:34:15 +00:00
:ERROR SEC ; an error occured
LDA #$27
BRA :DONE
2017-08-13 11:34:15 +00:00
********************************
*
* Write 512 byte block
* $43 Unit number DSSS0000
2017-08-13 11:34:15 +00:00
* $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
* $2B - Card write protected
*
********************************
WRITE JSR WRPROT
BCS :WPERROR ; card write protected
2017-10-15 14:48:13 +00:00
JSR GETBLOCK ; calc block address
2017-08-26 11:07:42 +00:00
2017-08-27 13:02:58 +00:00
LDA SS,X ; enable /CS
AND #$FF!SS0
2017-08-26 11:07:42 +00:00
STA SS,X
LDA #$58 ; send CMD24
JSR COMMAND ; send command
BNE :IOERROR ; check for error
2017-08-26 11:07:42 +00:00
LDA #DUMMY
STA DATA,X ; send dummy
LDA #$FE
STA DATA,X ; send data token
LDY #0
:LOOP1 LDA (BUFFER),Y
STA DATA,X :
INY
BNE :LOOP1
INC BUFFER+1 :
:LOOP2 LDA (BUFFER),Y
2017-08-26 11:07:42 +00:00
STA DATA,X
INY
BNE :LOOP2
DEC BUFFER+1
2017-08-26 11:07:42 +00:00
:CRC LDA #DUMMY
STA DATA,X ; send 2 dummy crc bytes
2017-08-26 11:07:42 +00:00
STA DATA,X
STA DATA,X ; get data response
2017-08-26 11:07:42 +00:00
LDA DATA,X
AND #$1F
CMP #$05
BNE :IOERROR ; check for write error
CLC ; no error
LDA #0
2017-08-26 11:07:42 +00:00
:DONE PHP
PHA
:WAIT LDA #DUMMY
STA DATA,X ; wait for write cycle
LDA DATA,X ; to complete
BEQ :WAIT
2017-08-26 11:07:42 +00:00
2017-08-27 13:02:58 +00:00
LDA SS,X ; disable /CS
ORA #SS0
2017-08-26 11:07:42 +00:00
STA SS,X
PLA
PLP
2017-08-26 11:07:42 +00:00
RTS
2017-08-13 11:34:15 +00:00
:IOERROR SEC ; an error occured
2017-08-26 11:07:42 +00:00
LDA #$27
BRA :DONE
:WPERROR SEC
LDA #$2B
BRA :DONE
2017-08-13 11:34:15 +00:00
********************************
*
* Format
* not supported!
*
********************************
2017-08-26 11:07:42 +00:00
FORMAT SEC
LDA #$01 ; invalid command
RTS
2017-10-15 14:48:13 +00:00
********************************
*
* Test routine
*
********************************
TEST LDA SLOT16
PHA
LDA SLOT
PHA
2017-10-15 14:48:13 +00:00
* get buffer
LDA #2 ; get 512 byte buffer
JSR $BEF5 ; call GETBUFR
BCS :ERROR
STA BUFFER+1
STZ BUFFER
PLA
STA SLOT
PLA
STA SLOT16
2017-10-15 14:48:13 +00:00
* fill buffer
LDY #0
:LOOP TYA
STA (BUFFER),Y
INY
BNE :LOOP
INC BUFFER+1
:LOOP1 TYA
STA (BUFFER),Y
INY
BNE :LOOP1
DEC BUFFER+1
2017-10-15 14:48:13 +00:00
STZ BLOCK ; block number
STZ BLOCK+1
LDX SLOT16
* write to card
JSR WRITE
2017-10-15 14:48:13 +00:00
BCS :ERROR
* read from card
JSR READ
2017-10-15 14:48:13 +00:00
BCS :ERROR
* check for errors
LDY #0
:LOOP2 TYA
CMP (BUFFER),Y
BNE :ERRCMP ; error in buffer
INY
BNE :LOOP2
INC BUFFER+1
:LOOP3 TYA
CMP (BUFFER),Y
BNE :ERRCMP
INY
BNE :LOOP3
DEC BUFFER+1
2017-10-15 14:48:13 +00:00
* free buffer
JSR $BEF8 ; call FREEBUFR
CLC
LDA #0
RTS
:ERROR BRK
:ERRCMP BRK
2017-11-20 18:13:16 +00:00
TEXT ASC "Apple][Sd (c)2017 Florian Reitz",00
2017-08-26 11:07:42 +00:00
CMD0 HEX 400000
HEX 000095
CMD1 HEX 410000
HEX 0000F9
CMD8 HEX 480000
HEX 01AA87
CMD16 HEX 500000
HEX 0200FF
CMD55 HEX 770000
HEX 000065
ACMD4140 HEX 694000
HEX 000077
ACMD410 HEX 690000
HEX 0000FF