AppleWin/firmware/HDD-SmartPort/HDC-SmartPort.a65
TomCh 964a5d5198
Oz-DOS and Format command support (#88, PR #1337)
Support FORMAT cmd:
. HDC firmware: byte $FE, b3=1 (format supported)
. HDC firmware: allow both SmartPort and BLK FORMAT cmd (and check that SP FORMAT only has 1 parameter)

SmartPort Controller:
. Format will just zero all blocks (if not write-protected)
. Write cmd: if write-protected return NOWRITE
. SP Status cmd: 'General Status': set format-allowed & write-protected flags

If HDD image is read-only then support as write-protected.
. On Insert() setup m_bWriteProtected flag correctly
2024-11-02 11:39:49 +00:00

393 lines
11 KiB
Plaintext

;--------------------------------------
;AppleWin : An Apple //e emulator for Windows
;
;Copyright (C) 1994-1996, Michael O'Brien
;Copyright (C) 1999-2001, Oliver Schmidt
;Copyright (C) 2002-2005, Tom Charlesworth
;Copyright (C) 2006-2024, Tom Charlesworth, Michael Pohoreski
;
;AppleWin is free software; you can redistribute it and/or modify
;it under the terms of the GNU General Public License as published by
;the Free Software Foundation; either version 2 of the License, or
;(at your option) any later version.
;
;AppleWin is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with AppleWin; if not, write to the Free Software
;Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;
; Description: SmartPort firmware for Hard Disk Controller card
;
; Author: Copyright (c) 2024, Rémy Gibert
; . derived from works: Copyright (c) 2005, Robert Hoem
;
;--------------------------------------
!cpu 6502 ; Compatible with all Apple2's
!to "HDC-SmartPort.bin", plain
!sl "HDC-SmartPort.labels"
;--------------------------------------
!src "IO_Apple.inc"
!src "IO_Applewin.inc"
!src "MON.inc"
!src "ProDOS.inc"
;--------------------------------------
; SP commands
;--------------------------------------
SP_Cmd_status = $00
SP_Cmd_status_STATUS = $00
SP_Cmd_status_GETDCB = $01
SP_Cmd_status_GETNL = $02
SP_Cmd_status_GETDIB = $03
SP_Cmd_readblock = $01
SP_Cmd_writeblock = $02
SP_Cmd_format = $03
SP_Cmd_control = $04
SP_Cmd_init = $05
SP_Cmd_open = $06
SP_Cmd_close = $07
SP_Cmd_read = $08
SP_Cmd_write = $09
SP_Cmd_extended = $40
;--------------------------------------
; ZP locations
;--------------------------------------
Ptr1 = $3C
BLK_Cmd = $42
BLK_Cmd_Status = $0
BLK_Cmd_Read = $1
BLK_Cmd_Write = $2
BLK_Cmd_Format = $3
BLK_UnitNum = $43
BLK_MemPtr = $44
BLK_BlockNum = $46
;--------------------------------------
; Screen holes (scratch space)
;--------------------------------------
Slot_n0 = $478
; = $4F8
; = $578
; = $5F8
; = $678
; = $6F8
; = $778
;Slot_C8 = $7F8 ; IRQ protocol for handling $C800 space properly
; Screen holes,Cn indexed
; = $478-$C0
; = $4F8-$C0
; = $578-$C0
; = $5F8-$C0
; = $678-$C0
; = $6F8-$C0
; = $778-$C0
; = $7F8-$C0
;--------------------------------------
BootBlocklA3 = $800
BootBlocklA2 = $801
;--------------------------------------
; The Autoboot rom will call this.
; This is also the entry point for such things as IN#7 and PR#7
; Autoboot and ProDOS look at the following few opcodes to detect block devices
; NB. $Cn07 should be $00 for a SmartPort Interface, but changing this means that it won't autoboot on ][, ][+ and unenhanced IIe.
; . ref: http://www.1000bit.it/support/manuali/apple/technotes/udsk/tn.udsk.2.html
;--------------------------------------
!zone code
* = $0000 ; org $0000 - position-independent code, so doesn't matter (but the other fixed org positions need to be on the same page)
Cn_start lda #$20
lda #$00
cmp #$03 ; will set C=0
lda #$00 ; SP mode
; lda #$3C ; BLK mode
bcc Cn_Bootstrap
Cn_Entry_BLK sec ; $Cn0A - BLK entrypoint
bcs Cn_Entry
Cn_Entry_SP clc ; $Cn0D - SmartPort entrypoint
Cn_Entry php
sei ; disable ints, in case an int handler races our $0000/RTS and stack accesses!
;--------------------------------------
; NB. need RAM that's guaranteed to be both read & writeable:
; . can't use $0200-$BFFF, due to eg. RAMRD=0/RAMWRT=1 combination
; . can't use LC as ROM might be enabled.
; So use ZP (specifically $0000) as whatever the state of ALTZP, both read & write will be to the same physical memory location.
;--------------------------------------
lda $00 ; save $00
ldx #$60 ; opcode RTS
stx $00
jsr $0000 ; RTS immediately (NB. can't use $FF58, since LC RAM may be switched in)
sta $00 ; restore $00
tsx
lda $0100,x ; $Cn
asl
asl
asl
asl
sta Slot_n0
plp ; + restore int status
bcs Cn_BLK ; C=1: ProDOS mode .....
;--------------------------------------
; C=0: fall through to SmartPort...
;--------------------------------------
lda Ptr1 ; X = Stack Ptr from TSX above
pha
lda Ptr1+1
pha
lda $102,x ; jsr LO byte
sta Ptr1
; clc ; from bcs above
adc #3
sta $102,x ; jsr LO byte
lda $103,x ; jsr HI byte
sta Ptr1+1
adc #0
sta $103,x ; jsr HI byte
ldy #1 ; CMD byte
bne Cn_SP ; Always
;--------------------------------------
Cn_Sloop jmp MON_SLOOP
;--------------------------------------
Cn_Bootstrap bit IO_IIE_OPENAPPLE
bmi Cn_Sloop
jsr MON_RTS ; ROM supposed to be enabled at BOOT time or PR#7
tsx
lda $0100,x ; $Cn
asl
asl
asl
asl
sta Slot_n0
; Lets check to see if there's an image ready
; Slot n, disk 1
tax ; A=%0SSS0000
sta IO_Unitnum,x ; b7=0 (and b6:4=SSS) => disk 1
lda #BLK_Cmd_Status
sta IO_Command,x
lda IO_Execute,x ; Post: A=STATUS (BLK_Cmd_Status completes immediately, no need to check STATUS.b7 busy bit)
; on error A = 0eeeeee1, where eeeeee = Standard ProDOS error codes (see ProDOS.inc)
lsr ; Post: C=0 or 1
bcs Cn_Sloop ; no image ready, boot Slot n-1 image instead
;--------------------------------------
; image ready. Lets boot from it.
; we want to load block 1 from disk 1 to $800 then jump there
; Pre: X = Slot# << 4
;--------------------------------------
lda #$1
sta BLK_Cmd
stx BLK_UnitNum ; DSSS0000, where D=0 (ie. disk 1)
lda #$0
sta BLK_MemPtr
sta BLK_BlockNum
sta BLK_BlockNum+1
lda #$8
sta BLK_MemPtr+1
; clc ; C = 0 from bcs Cn_Sloop
;--------------------------------------
; entry point for BLK driver
; simple really. Copy the command from BLK_Cmd..BLK_BlockNum+1
; to our I/O ports then execute command
; Pre:
; X = Slot# << 4
; C = 0 from Cn_Bootstrap
; C = 1 from Cn_Entry_BLK
; Post:
; C = IO_Status b0
; A = result of IO_Execute
; Read or write command
; X = Slot# << 4
; Y = command
; Status command
; X = low byte of disk size
; Y = high byte of disk size
;--------------------------------------
Cn_BLK php
ldx Slot_n0
ldy #0
- lda BLK_Cmd,y
sta IO_BlkCmdFifo,x ; BLK_Cmd's are $0x (NB. not range-checked unlike SP cmds)
iny ; BLK_UnitNum's are DSSS0000 : if SSS does NOT match physical slot...
; ...hardware should handle the remap by adding +2 to the REAL dev_ID
cpy #6 ; that way, a BLK controller can support 4 devices (see $CnFE byte below)
bcc -
- lda IO_Execute,x ; A = result of IO_Execute (NB. instantaneous 512 byte r/w!)
bmi - ; b7=busy doing DMA?
plp ; restore C
bcs Cn_BLK_Done ; from Cn_Entry_BLK
lsr ; Post: C=0 or 1
bcs Cn_Sloop ; Boot Failed....
jmp BootBlocklA2 ; Success, run $801 BOOT code for Apple ][ (not /// at $800)
Cn_BLK_Done lsr ; Post: C=0 or 1
ldy BLK_Cmd ; Was it status ?
bne + ; no, go home
pha ; Save result
ldy IO_Imgsizehi,x ; Get high byte of size
lda IO_Imgsizelo,x ; Get low byte of size
tax ; Transfer into X
pla ; Get back status call result
+ rts
;--------------------------------------
Cn_SP lda (Ptr1),y ; CMD byte
cmp #SP_Cmd_format
beq +
bcs Cn_SP_E_BADCALL ; only STATUS, READBLOCK, WRITEBLOCK & FORMAT supported
+ ; C=1 if FORMAT cmd [*1]
ldx Slot_n0
sta IO_SPCmdFifo,x ; Smartport calls = $8x (OR'd with $80 by h/w), Statuscode written at IO_StatusCode
iny ; param LO
lda (Ptr1),y
pha
iny ; param HI
lda (Ptr1),y
sta Ptr1+1
pla
sta Ptr1 ; Now Ptr1 = Param list
ldy #0 ; Param Idx (in bytes)
lda (Ptr1),y
!if 1 { ; (This parameter-checking code could be removed to free up some space)
bcs @format ; NB. C-flag untouched from above [*1]
cmp #3 ; STATUS, READBLOCK & WRITEBLOCK: all have 3 parameters
beq +
bne Cn_SP_E_BADCNT
@format cmp #1 ; FORMAT: has 1 parameter
bne Cn_SP_E_BADCNT
+
}
; Parameter-1: Parameter-2: Parameter-3:
; UnitNum (B), MemPtr (L/H), StatusCode (B) -> IO (STATUS)
; UnitNum (B), MemPtr (L/H), DiskBlock (L/M/H) -> IO (READ,WRITE)
; UnitNum (B) -> IO (FORMAT)
- iny ; Always copy 6 more bytes to the FIFO regardless of the command
lda (Ptr1),y
sta IO_SPCmdFifo,x ; UnitNum Range is 0 (smartport controller itself), 1,2,3.....
cpy #6 ; blockNums are 24-bit for SP calls
bcc -
- lda IO_Execute,x ; A = result of IO_Execute (NB. instantaneous 512 byte r/w!)
bmi - ; b7=busy doing DMA?
lsr ; get C=1 & A = ERROR CODE ... or C=0 & A = 0
tax ; Save Error Code
!byte $2C ; BIT ABS
Cn_SP_E_BADCALL ldx #E_BADCALL
!byte $2C ; BIT ABS
Cn_SP_E_BADCNT ldx #E_BADCNT
pla
sta Ptr1+1
pla
sta Ptr1
txa ; Restore Error Code
ldx #0
ldy #2 ; exit returning YX = $0200 bytes transferred if success
rts ; or C=1 & A=ERROR CODE
;--------------------------------------
!zone data
;--------------------------------------
; datablock. This starts near the end of the firmware (at offset $CnFB)
;
; $CnFB :
; 7 : 1 = Support Extended commands
; 6 : [Reserved]
; 5 : [Reserved]
; 4 : [Reserved]
; 3 : [Reserved]
; 2 : [Reserved]
; 1 : 1 = Supports SCSI devices (Helps ProDOS build SP device list)
; 0 : 1 = Supports RAMDisk Card
;
; $CnFC/D : size in blocks (BLK) if $0000 Software must issue a BLK Status Call to get size in blocks
;
; $CnFE = status bits (BAP p7-14)
; 7 = medium is removable
; 6 = device is interruptable
; 5-4 = number of volumes (0..3 means 1..4)
; 3 = device supports Format call
; 2 = device can be written to
; 1 = device can be read from (must be 1)
; 0 = device status can be read (must be 1)
;
; $C7 = Removable, Interruptable, #Volumes=1, Supports write/read/status
; $D7 = Removable, Interruptable, #Volumes=2, Supports write/read/status
; $F7 = Removable, Interruptable, #Volumes=4, Supports write/read/status
; $FF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status
; $BF = Removable, , #Volumes=4, Supports format/write/read/status (KEGS / IIGS)
;
; $CnFF = offset to BLK entry point
;--------------------------------------
@checkCsFB
*= $00FB ; org $00FB
!warn "CsFB padding = ", * - @checkCsFB
;--------------------------------------
!byte $00 ; SmartPort ID Type byte
!word $0000 ; how many blocks are on the device. Zero means use status call
!byte $FF ; specifics about the device (number of drives, read/write/format capability, etc)
!byte <Cn_Entry_BLK ; entry point offset for ProDOS (must be $0a)
;--------------------------------------