From bb6fa803359aec0828a09b75db03bf06949b07e0 Mon Sep 17 00:00:00 2001 From: tomcw Date: Thu, 9 Dec 2021 21:22:13 +0000 Subject: [PATCH] HDD r/w: error if r/w overlaps with I/O memory . break to debugger if single-stepping HDD write: support memory accesses across 64KiB boundary --- source/Debugger/Debug.cpp | 22 +++++++++++++++++++++- source/Debugger/Debug.h | 3 +++ source/Harddisk.cpp | 38 +++++++++++++++++++++++++++++++++++--- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 6acb242b..b8794c94 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -68,6 +68,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA int g_nDebugBreakOnInvalid = 0; // Bit Flags of Invalid Opcode to break on: // iOpcodeType = AM_IMPLIED (BRK), AM_1, AM_2, AM_3 int g_iDebugBreakOnOpcode = 0; bool g_bDebugBreakOnInterrupt = false; + static int g_iDebugBreakOnDmaToOrFromIoMemory = 0; + static WORD g_uDebugBreakOnDmaIoMemoryAddr = 0; static int g_bDebugBreakpointHit = 0; // See: BreakpointHit_t @@ -1251,6 +1253,20 @@ void ClearTempBreakpoints () } } +//=========================================================================== +static int CheckBreakpointsDmaToOrFromIoMemory(void) +{ + int res = g_iDebugBreakOnDmaToOrFromIoMemory; + g_iDebugBreakOnDmaToOrFromIoMemory = 0; + return res; +} + +void DebuggerBreakOnDmaToOrFromIoMemory(WORD addr, bool isDmaToMemory) +{ + g_iDebugBreakOnDmaToOrFromIoMemory = isDmaToMemory ? BP_DMA_TO_IO_MEM : BP_DMA_FROM_IO_MEM; + g_uDebugBreakOnDmaIoMemoryAddr = addr; +} + //=========================================================================== Update_t CmdBreakpoint (int nArgs) { @@ -8307,7 +8323,7 @@ void DebugContinueStepping(const bool bCallerWillUpdateDisplay/*=false*/) g_bDebugBreakpointHit |= BP_HIT_INTERRUPT; } - g_bDebugBreakpointHit |= CheckBreakpointsIO() | CheckBreakpointsReg(); + g_bDebugBreakpointHit |= CheckBreakpointsIO() | CheckBreakpointsReg() | CheckBreakpointsDmaToOrFromIoMemory(); } if (regs.pc == g_nDebugStepUntil || g_bDebugBreakpointHit) @@ -8334,6 +8350,10 @@ void DebugContinueStepping(const bool bCallerWillUpdateDisplay/*=false*/) pszStopReason = TEXT("PC reads from floating bus or I/O memory"); else if (g_bDebugBreakpointHit & BP_HIT_INTERRUPT) sprintf_s(szStopMessage, sizeof(szStopMessage), "Interrupt occurred at $%04X", g_LBR); + else if (g_bDebugBreakpointHit & BP_DMA_TO_IO_MEM) + sprintf_s(szStopMessage, sizeof(szStopMessage), "HDD DMA to I/O memory $%04X", g_uDebugBreakOnDmaIoMemoryAddr); + else if (g_bDebugBreakpointHit & BP_DMA_FROM_IO_MEM) + sprintf_s(szStopMessage, sizeof(szStopMessage), "HDD DMA from I/O memory $%04X", g_uDebugBreakOnDmaIoMemoryAddr); else pszStopReason = TEXT("Unknown!"); diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h index 5ff94c1f..fa292e4a 100644 --- a/source/Debugger/Debug.h +++ b/source/Debugger/Debug.h @@ -39,6 +39,8 @@ , BP_HIT_MEMW = (1 << 5) , BP_HIT_PC_READ_FLOATING_BUS_OR_IO_MEM = (1 << 6) , BP_HIT_INTERRUPT = (1 << 7) + , BP_DMA_TO_IO_MEM = (1 << 8) + , BP_DMA_FROM_IO_MEM = (1 << 9) }; extern int g_nBreakpoints; @@ -181,3 +183,4 @@ void DebuggerMouseClick( int x, int y ); bool IsDebugSteppingAtFullSpeed(void); + void DebuggerBreakOnDmaToOrFromIoMemory(WORD addr, bool isDmaToMemory); diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp index 01651dbb..dda122e6 100644 --- a/source/Harddisk.cpp +++ b/source/Harddisk.cpp @@ -39,6 +39,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SaveState.h" #include "YamlHelper.h" +#include "Debugger/Debug.h" #include "../resource/resource.h" /* @@ -520,7 +521,12 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY LPBYTE page = memwrite[dstAddr >> 8]; if (!page) { - _ASSERT(0); + if (g_nAppMode == MODE_STEPPING) + DebuggerBreakOnDmaToOrFromIoMemory(dstAddr, true); + //else // Show MessageBox? + + pCard->m_notBusyCycle = 0; // DMA complete + bRes = false; break; } @@ -535,7 +541,8 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY remaining -= size; } } - else + + if (!bRes) { pHDD->m_error = 1; r = DEVICE_IO_ERROR; @@ -568,7 +575,32 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY } } - memcpy(pHDD->m_buf, mem + pHDD->m_memblock, HD_BLOCK_SIZE); + // Trap and error on any accesses that overlap with I/O memory + if ((pHDD->m_memblock < 0xC000 && ((pHDD->m_memblock + HD_BLOCK_SIZE - 1) >= 0xC000)) // 1) Starts before I/O, but ends in I/O memory + || ((pHDD->m_memblock >> 12) == 0xC)) // 2) Starts in I/O memory + { + WORD dstAddr = ((pHDD->m_memblock >> 12) == 0xC) ? pHDD->m_memblock : 0xC000; + + if (g_nAppMode == MODE_STEPPING) + DebuggerBreakOnDmaToOrFromIoMemory(dstAddr, false); + //else // Show MessageBox? + + pCard->m_notBusyCycle = 0; // DMA complete + bRes = false; + } + else + { + if (pHDD->m_memblock <= 0xFE00) + { + memcpy(pHDD->m_buf, mem + pHDD->m_memblock, HD_BLOCK_SIZE); + } + else // wraps on 64KiB boundary + { + const UINT size = 0x10000 - pHDD->m_memblock; + memcpy(pHDD->m_buf, mem + pHDD->m_memblock, size); + memcpy(pHDD->m_buf + size, mem, HD_BLOCK_SIZE - size); + } + } if (bRes) bRes = ImageWriteBlock(pHDD->m_imagehandle, pHDD->m_diskblock, pHDD->m_buf);