mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-17 15:30:28 +00:00
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
This commit is contained in:
parent
5ddb2357aa
commit
964a5d5198
@ -243,7 +243,7 @@ Cn_BLK php
|
||||
ldy #0
|
||||
|
||||
- lda BLK_Cmd,y
|
||||
sta IO_BlkCmdFifo,x ; BLK_Cmd's are $0x
|
||||
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)
|
||||
@ -276,7 +276,9 @@ Cn_BLK_Done lsr ; Post: C=0 or 1
|
||||
Cn_SP lda (Ptr1),y ; CMD byte
|
||||
|
||||
cmp #SP_Cmd_format
|
||||
bcs Cn_SP_E_BADCALL ; only STATUS, READBLOCK & WRITEBLOCK supported
|
||||
beq +
|
||||
bcs Cn_SP_E_BADCALL ; only STATUS, READBLOCK, WRITEBLOCK & FORMAT supported
|
||||
+ ; C=1 if FORMAT cmd [*1]
|
||||
|
||||
ldx Slot_n0
|
||||
|
||||
@ -293,15 +295,25 @@ Cn_SP lda (Ptr1),y ; CMD byte
|
||||
pla
|
||||
sta Ptr1 ; Now Ptr1 = Param list
|
||||
|
||||
ldy #0 ; Param Cnt
|
||||
ldy #0 ; Param Idx (in bytes)
|
||||
|
||||
lda (Ptr1),y
|
||||
cmp #3 ; STATUS, READBLOCK & WRITEBLOCK = all 3 parameters
|
||||
sec
|
||||
!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
|
||||
+
|
||||
}
|
||||
|
||||
- iny ; UnitNum (B), MemPtr (L/H), DiskBlock (L/M/H) -> IO (R,W)
|
||||
lda (Ptr1),y ; UnitNum (B), MemPtr (L/H), StatusCode (B) -> IO (S)
|
||||
; 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 -
|
||||
@ -364,7 +376,8 @@ Cn_SP_E_BADCNT ldx #E_BADCNT
|
||||
; $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
|
||||
; $BF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status (KEGS / IIGS)
|
||||
; $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
|
||||
;--------------------------------------
|
||||
@ -372,8 +385,8 @@ Cn_SP_E_BADCNT ldx #E_BADCNT
|
||||
*= $00FB ; org $00FB
|
||||
!warn "CsFB padding = ", * - @checkCsFB
|
||||
;--------------------------------------
|
||||
!byte $00 ; Smart port ID Type byte
|
||||
!byte $00 ; SmartPort ID Type byte
|
||||
!word $0000 ; how many blocks are on the device. Zero means use status call
|
||||
!byte $F7 ; specifics about the device (number of drives, read/write/format capability, etc)
|
||||
!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)
|
||||
;--------------------------------------
|
||||
|
Binary file not shown.
Binary file not shown.
@ -73,6 +73,10 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
||||
*ppImageInfo = NULL;
|
||||
Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
|
||||
}
|
||||
|
||||
if (Err == eIMAGE_ERROR_NONE)
|
||||
*pWriteProtected = pImageInfo->bWriteProtected;
|
||||
|
||||
return Err;
|
||||
}
|
||||
|
||||
|
@ -82,16 +82,16 @@ Memory map SmartPort device (IO addr + s*$10):
|
||||
; C088 (r) NEXT BYTE (legacy read-only port - still supported)
|
||||
C089 (r) LOW BYTE OF DISK IMAGE SIZE IN BLOCKS
|
||||
C08A (r) HIGH BYTE OF DISK IMAGE SIZE IN BLOCKS
|
||||
C089 (w) a 6-deep FIFO to write: command, unitNum, memPtr(2), blockNum(2)
|
||||
C08A (w) a 7-deep FIFO to write: command, unitNum, memPtr(2), blockNum(3); first byte gets OR'd with $80 (ie. to indicate it's an SP command)
|
||||
C089 (w) a 6-deep FIFO to write: command, unitNum, memPtr(2), blockNum(2); for BLK driver
|
||||
C08A (w) a 7-deep FIFO to write: command, unitNum, memPtr(2), blockNum(3); for SP: first byte gets OR'd with $80 (ie. to indicate it's an SP command)
|
||||
*/
|
||||
|
||||
/*
|
||||
Hard drive emulation in AppleWin - for the HDDRVR v1 & v2 firmware
|
||||
|
||||
Concept
|
||||
To emulate a 32mb hard drive connected to an Apple IIe via AppleWin.
|
||||
Designed to work with Autoboot Rom and Prodos.
|
||||
To emulate a 32MiB hard drive connected to an Apple IIe via AppleWin.
|
||||
Designed to work with Autoboot ROM and ProDOS.
|
||||
|
||||
Overview
|
||||
1. Hard drive image file
|
||||
@ -130,8 +130,8 @@ Overview
|
||||
patching prodos (to detect DELETE FILE calls).
|
||||
|
||||
4. FORMAT
|
||||
Ignored. This would be used for low level formatting of the device
|
||||
(as in the case of a tape or SCSI drive, perhaps).
|
||||
This is used for low level formatting of the device. (GH#88)
|
||||
(Also in the case of a tape or SCSI drive, perhaps.)
|
||||
|
||||
3. Bugs
|
||||
The only thing I've noticed is that Copy II+ 7.1 seems to crash or stall
|
||||
@ -409,6 +409,12 @@ bool HarddiskInterfaceCard::Insert(const int iDrive, const std::string& pathname
|
||||
if (m_hardDiskDrive[iDrive].m_imageloaded)
|
||||
Unplug(iDrive);
|
||||
|
||||
const DWORD dwAttributes = GetFileAttributes(pathname.c_str());
|
||||
if (dwAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
m_hardDiskDrive[iDrive].m_bWriteProtected = false; // File doesn't exist - so ImageOpen() below will fail
|
||||
else
|
||||
m_hardDiskDrive[iDrive].m_bWriteProtected = (dwAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
|
||||
|
||||
// Check if image is being used by the other HDD, and unplug it in order to be swapped
|
||||
{
|
||||
const std::string & pszOtherPathname = HarddiskGetFullPathName(!iDrive);
|
||||
@ -517,11 +523,12 @@ void HarddiskInterfaceCard::Unplug(const int iDrive)
|
||||
|
||||
#if 0 // Enable HDD command logging
|
||||
#define LOG_DISK(format, ...) LOG(format, __VA_ARGS__)
|
||||
#define DEBUG_SKIP_BUSY_STATUS 1
|
||||
#else
|
||||
#define LOG_DISK(...)
|
||||
#define DEBUG_SKIP_BUSY_STATUS 0
|
||||
#endif
|
||||
|
||||
#define DEBUG_SKIP_BUSY_STATUS 0
|
||||
|
||||
// ProDOS BLK & SmartPort commands
|
||||
//
|
||||
@ -553,6 +560,7 @@ const UINT SP_Cmd_busyStatus = SP_Cmd_base + 0x3F; // AppleWin vendor-specific c
|
||||
#define BADCTL 0x21
|
||||
#define DEVICE_IO_ERROR 0x27
|
||||
#define DEVICE_NOT_CONNECTED 0x28 // No device detected/connected
|
||||
#define NOWRITE 0x2B // Disk write protected
|
||||
#define ERRORCODE_MASK 0x3F // limit to just 6 bits (as 'error' byte uses b0 & b7 for other status)
|
||||
|
||||
#define STATUS_OK 0x00
|
||||
@ -655,6 +663,7 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD)
|
||||
}
|
||||
|
||||
const UINT CYCLES_FOR_DMA_RW_BLOCK = HD_BLOCK_SIZE;
|
||||
const UINT CYCLES_FOR_FORMATTING_1_BLOCK = 100; // Arbitrary
|
||||
const UINT PAGE_SIZE = 256;
|
||||
|
||||
pHDD->m_error = DEVICE_OK;
|
||||
@ -671,7 +680,7 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD)
|
||||
break;
|
||||
case SP_Cmd_status:
|
||||
pHDD->m_error = SmartPortCmdStatus(pHDD);
|
||||
LOG_DISK("ST: %02X\n", pHDD->m_error);
|
||||
LOG_DISK("ST: %02X (statusCode: %02X)\n", pHDD->m_error, m_statusCode);
|
||||
break;
|
||||
case BLK_Cmd_Read:
|
||||
case SP_Cmd_readblock:
|
||||
@ -744,8 +753,15 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD)
|
||||
case BLK_Cmd_Write:
|
||||
case SP_Cmd_writeblock:
|
||||
{
|
||||
LOG_DISK("WR: %08X (from addr: %04X)\n", pHDD->m_diskblock, pHDD->m_memblock);
|
||||
pHDD->m_status_next = DISK_STATUS_WRITE; // or DISK_STATUS_PROT if we ever enable write-protect on HDD
|
||||
LOG_DISK("WR: %08X (from addr: %04X) %s\n", pHDD->m_diskblock, pHDD->m_memblock, pHDD->m_bWriteProtected ? "write-protected" : "");
|
||||
if (pHDD->m_bWriteProtected)
|
||||
{
|
||||
pHDD->m_status_next = DISK_STATUS_PROT;
|
||||
pHDD->m_error = NOWRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHDD->m_status_next = DISK_STATUS_WRITE;
|
||||
bool bRes = true;
|
||||
const bool bAppendBlocks = (pHDD->m_diskblock * HD_BLOCK_SIZE) >= ImageGetImageSize(pHDD->m_imagehandle);
|
||||
bool breakpointHit = false;
|
||||
@ -817,10 +833,39 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD)
|
||||
{
|
||||
pHDD->m_error = DEVICE_IO_ERROR;
|
||||
}
|
||||
} // if (pHDD->m_bWriteProtected)
|
||||
}
|
||||
break;
|
||||
case BLK_Cmd_Format:
|
||||
pHDD->m_error = DEVICE_IO_ERROR; // Not supported
|
||||
case SP_Cmd_format:
|
||||
LOG_DISK("FORMAT: write-protected=%d\n", pHDD->m_bWriteProtected);
|
||||
if (pHDD->m_bWriteProtected)
|
||||
{
|
||||
pHDD->m_error = NOWRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT numBlocks = GetImageSizeInBlocks(pHDD->m_imagehandle);
|
||||
memset(pHDD->m_buf, 0, HD_BLOCK_SIZE);
|
||||
bool res = false;
|
||||
m_notBusyCycle = g_nCumulativeCycles;
|
||||
|
||||
for (UINT block = 0; block < numBlocks; block++)
|
||||
{
|
||||
// Inefficient (especially for gzip/zip files!)
|
||||
res = ImageWriteBlock(pHDD->m_imagehandle, block, pHDD->m_buf);
|
||||
_ASSERT(res);
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
m_notBusyCycle += (UINT64)CYCLES_FOR_FORMATTING_1_BLOCK;
|
||||
#if DEBUG_SKIP_BUSY_STATUS
|
||||
m_notBusyCycle = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
pHDD->m_error = res ? DEVICE_OK : DEVICE_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_ASSERT(0);
|
||||
@ -1070,7 +1115,8 @@ BYTE HarddiskInterfaceCard::SmartPortCmdStatus(HardDiskDrive* pHDD)
|
||||
// general status:
|
||||
// . b7=block device, b6=write allowed, b5=read allowed, b4=device online or disk in drive,
|
||||
// . b3=format allowed, b2=media write protected (block devices only), b1=device currently interrupting (//c only), b0=device currently open (char device only)
|
||||
const BYTE generalStatus = isImageLoaded ? 0xF0 : 0xE0; // Loaded: b#11110000: bwrl---- / Not loaded: b#11100000: bwr-----
|
||||
BYTE generalStatus = isImageLoaded ? 0xF8 : 0xE8; // Loaded: b#11111000: bwrlf--- / Not loaded: b#11101000: bwr-f---
|
||||
if (pHDD->m_bWriteProtected) generalStatus |= (1 << 2);
|
||||
mem[statusListAddr++] = generalStatus;
|
||||
|
||||
const UINT imageSizeInBlocks = isImageLoaded ? GetImageSizeInBlocks(pHDD->m_imagehandle) : 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user