mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-03 11:30:22 +00:00
964a5d5198
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
393 lines
11 KiB
Plaintext
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)
|
|
;--------------------------------------
|