;******************************* ; ; Apple][Sd Firmware ; Version 1.2.3 ; ProDOS functions ; ; (c) Florian Reitz, 2017 - 2021 ; ; X register usually contains SLOT16 ; Y register is used for counting or SLOT ; ;******************************* .export PRODOS .export STATUS .export READ .export WRITE .import COMMAND .import SDCMD .import GETBLOCK .import CARDDET .import INITED .import INIT .import WRPROT .import GETR1 .import GETR3 .include "AppleIISd.inc" .segment "EXTROM" ;******************************* ; ; ProDOS command dispatcher ; ; $42-$47 MLI input locations ; X Slot*16 ; Y Slot ; ; C Clear - No error ; Set - Error ; A $00 - No error ; $01 - Unknown command ; ;******************************* PRODOS: LDA DCMD ; get command BEQ @STATUS ; branch if cmd is 0 CMP #1 BEQ @READ CMP #2 BEQ @WRITE LDA #ERR_BADCMD ; unknown command SEC RTS @STATUS: JMP STATUS @READ: JMP READ @WRITE: JMP WRITE ;******************************* ; ; Status request ; $43 Unit number DSSS000 ; $44-45 Unused ; $46-47 Unused ; ; C Clear - No error ; Set - Error ; A $00 - No error ; $28 - No card inserted ; $2B - Card write protected ; X - Blocks avail (low byte) ; Y - Blocks avail (high byte) ; ;******************************* STATUS: LDA #NO_ERR ; Thanks for this one, Antoine! JSR CARDDET BCC @WRPROT LDA #ERR_NODRIVE; no card inserted BNE @DONE @WRPROT: JSR WRPROT BCC @DONE LDA #ERR_NOWRITE; card write protected @DONE: LDX #$FF ; 32 MB partition LDY #$FF RTS ;******************************* ; ; 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 ; ;******************************* READ: JSR CARDDET ; check for card BCS @NDERROR ; no card JSR INITED ; check for initialization BCC @GETBLOCK JSR INIT ; initialize card BCS @NDERROR ; init failed @GETBLOCK: JSR GETBLOCK ; calc block address LDA SS,X ; enable /CS AND #<~SS0 STA SS,X LDA #$51 ; send CMD17 JSR COMMAND ; send command CMP #0 BNE @IOERROR ; check for error @GETTOK: LDA #DUMMY ; get data token STA DATA,X LDA DATA,X ; get response CMP #$FE BNE @GETTOK ; wait for $FE LDA CTRL,X ; enable FRX ORA #FRX STA CTRL,X LDA #DUMMY STA DATA,X LDY #0 @LOOP1: LDA DATA,X ; read data from card STA (BUFFER),Y INY BNE @LOOP1 INC BUFFER+1 ; inc msb on page boundary @LOOP2: LDA DATA,X STA (BUFFER),Y INY BNE @LOOP2 DEC BUFFER+1 @CRC: LDA DATA,X ; read two bytes crc LDA DATA,X ; and ignore LDA DATA,X ; read a dummy byte LDA CTRL,X ; disable FRX AND #<~FRX STA CTRL,X CLC ; no error LDA #NO_ERR @DONE: PHP PHA LDA SS,X ORA #SS0 STA SS,X ; disable /CS PLA PLP RTS @IOERROR: SEC ; an error occured LDA #ERR_IOERR BRA @DONE @NDERROR: SEC ; an error occured LDA #ERR_NODRIVE BRA @DONE ;******************************* ; ; Write 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 - I/O error or bad block number ; $2B - Card write protected ; ;******************************* WRITE: JSR WRPROT BCS @WPERROR ; card write protected JSR GETBLOCK ; calc block address LDA SS,X ; enable /CS AND #<~SS0 STA SS,X LDA #$58 ; send CMD24 JSR COMMAND ; send command CMP #0 BNE @IOERROR ; check for error 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 STA DATA,X INY BNE @LOOP2 DEC BUFFER+1 @CRC: LDA #DUMMY STA DATA,X ; send 2 dummy crc bytes STA DATA,X STA DATA,X ; get data response LDA DATA,X AND #$1F CMP #$05 BNE @IOERROR ; check for write error CLC ; no error LDA #NO_ERR @DONE: PHP PHA @WAIT: LDA #DUMMY STA DATA,X ; wait for write cycle LDA DATA,X ; to complete BEQ @WAIT LDA SS,X ; disable /CS ORA #SS0 STA SS,X PLA PLP RTS @IOERROR: SEC ; an error occured LDA #ERR_IOERR BRA @DONE @WPERROR: SEC LDA #ERR_NOWRITE BRA @DONE