WinIo v3.0でSetPhysLong()に基づいて1Byte/2Byteアクセスのルーチンを構築する方法について 1 つ質問があります。
SetPhysLong()は、DWORD(32bit) 単位でメモリにアクセスするために使用され、私の目的は、独自のルーチンを構築することです。
- SetPhysBYTE()でBYTE(8bit unsigned)単位でメモリアクセスし、
- SetPhysWORD()でWORD(16bit unsigned)単位でメモリアクセス
誰かがこの問題を解決できる方法を以下に教えてくれました:
- GetPhysLongを使用して、現在の DWORD コンテンツを取得します
- 新しいBYTE / WORDをDWORDの正しい部分に入れます
- 次にSetPhysLongを使用してそれを書き戻します
しかし、以下の状況が発生した場合、上記の方法は失敗したと思います:
- 4 バイトのレジスタがメモリ 0x12345678 にマップされていると仮定します (これはメモリにマップされた IO であるため)。
- そのレジスタの 2 番目のバイトがステータス レジスタであり、属性が「Write 1 to clear」であり、2 番目のバイトが 0x40であると仮定します。
0xA5 をメモリ 0x12345678 に書き込みたいとします。あなたのやり方に従ってください、私たちは得ました:
- GetPhysLong を使用し、0x00004000 を返します
- LSBに0xA5を入れると、0x000040A5が得られました
- SetPhysLong を使用して、0x000040A5 をメモリ アドレス 0x12345678 に設定します。
値 0x40 が 2 番目のバイトに書き込まれ、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;
}