我有一个关于如何基于WinIo v3.0中的SetPhysLong()为1Byte/2Byte访问构建例程的问题。
SetPhysLong()用于以 DWORD(32bit) 为单位访问内存,我的目标是构建自己的例程:
- SetPhysBYTE()以 BYTE(8bit unsigned) 为单位访问内存,和
- SetPhysWORD()以 WORD(16bit unsigned) 为单位访问内存
有人告诉我下面的方法可以解决这个问题:
- 使用GetPhysLong检索当前 DWORD 内容
- 将新的 BYTE / WORD 放入DWORD的正确部分
- 然后使用SetPhysLong将其写回
但如果发生以下情况,我认为上述方法失败:
- 假设4字节寄存器映射到内存0x12345678(因为是内存映射IO)
- 假设该寄存器的第二个字节是状态寄存器,属性是“写 1 清除”,第二个字节现在是 0x40
假设我们要将 0xA5 写入内存 0x12345678。按照你的方式,我们得到:
- 使用 GetPhysLong 然后返回 0x00004000
- 把 0xA5 放到 LSB,我们得到 0x000040A5
- 使用 SetPhysLong 将 0x000040A5 设置为内存地址 0x12345678
这是不正确的,因为值 0x40 将被写入第二个字节并将其清除为 0x00 !!!
因此,我的目标是使用 SetPhysBYTE(0x12345678, 0xA5) 来实现我的目标,并且不影响基于以下 SetPhysLong()... 的其他字节。
bool _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 4;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*pdwLinAddr = dwPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}
[编辑] 我已经解决了这个问题,如果需要,请参考下面的代码......
bool _stdcall SetPhysBYTE(PBYTE pbPhysAddr, BYTE bPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 1;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*(((PBYTE)((DWORD)pdwLinAddr))) = bPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}
bool _stdcall SetPhysWORD(PBYTE pbPhysAddr, WORD wPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 2;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*(((PWORD)((DWORD)pdwLinAddr))) = wPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}