📄 wdc_mem_io.c
字号:
/*****************************************************************************
* File: wdc_mem_io.c - Implementation of WDC functions for reading/writing *
* a device's memory and I/O addresses *
* *
* Copyright (c) 2005 Jungo Ltd. http://www.jungo.com *
******************************************************************************/
#include "wdc_lib.h"
#include "wdc_defs.h"
#include "wdc_err.h"
/*************************************************************
General definitions
*************************************************************/
/* Data types definitions (based on WDC address access mode definitions) */
typedef BYTE U8;
typedef WORD U16;
typedef UINT32 U32;
typedef UINT64 U64;
/* Get data type from address access mode */
#define MODE_TO_DATA_TYPE(mode) mode##_DT
/* WD_TRANSFER data types defintions (based on WDC address access mode defintions) */
#define WDC_MODE_8_TRANS_DT Byte
#define WDC_MODE_16_TRANS_DT Word
#define WDC_MODE_32_TRANS_DT Dword
#define WDC_MODE_64_TRANS_DT Qword
/* Get WD_TRANSFER data type from address access mode */
#define MODE_TO_WD_TRANS_DATA_TYPE(mode) mode##_TRANS_DT
/* Transfer commands definitions (based on address access mode definitions) */
/* I/O commands */
#define WDC_MODE_8_TC_RP RP_BYTE
#define WDC_MODE_16_TC_RP RP_WORD
#define WDC_MODE_32_TC_RP RP_DWORD
#define WDC_MODE_64_TC_RP RP_QWORD
#define WDC_MODE_8_TC_WP WP_BYTE
#define WDC_MODE_16_TC_WP WP_WORD
#define WDC_MODE_32_TC_WP WP_DWORD
#define WDC_MODE_64_TC_WP WP_QWORD
#define WDC_MODE_8_TC_RPS RP_SBYTE
#define WDC_MODE_16_TC_RPS RP_SWORD
#define WDC_MODE_32_TC_RPS RP_SDWORD
#define WDC_MODE_64_TC_RPS RP_SQWORD
#define WDC_MODE_8_TC_WPS WP_SBYTE
#define WDC_MODE_16_TC_WPS WP_SWORD
#define WDC_MODE_32_TC_WPS WP_SDWORD
#define WDC_MODE_64_TC_WPS WP_SQWORD
/* Memory commands */
#define WDC_MODE_8_TC_RM RM_BYTE
#define WDC_MODE_16_TC_RM RM_WORD
#define WDC_MODE_32_TC_RM RM_DWORD
#define WDC_MODE_64_TC_RM RM_QWORD
#define WDC_MODE_8_TC_WM WM_BYTE
#define WDC_MODE_16_TC_WM WM_WORD
#define WDC_MODE_32_TC_WM WM_DWORD
#define WDC_MODE_64_TC_WM WM_QWORD
#define WDC_MODE_8_TC_RMS RM_SBYTE
#define WDC_MODE_16_TC_RMS RM_SWORD
#define WDC_MODE_32_TC_RMS RM_SDWORD
#define WDC_MODE_64_TC_RMS RM_SQWORD
#define WDC_MODE_8_TC_WMS WM_SBYTE
#define WDC_MODE_16_TC_WMS WM_SWORD
#define WDC_MODE_32_TC_WMS WM_SDWORD
#define WDC_MODE_64_TC_WMS WM_SQWORD
/* Get transfer command from address access mode */
#define MODE_TO_TRANS_CMD(mode, direction, fBlock, fMem) \
fBlock ? \
(WDC_READ == direction ? (fMem ? mode##_TC_RMS : mode##_TC_RPS) : \
(fMem ? mode##_TC_WMS : mode##_TC_WPS)) : \
(WDC_READ == direction ? (fMem ? mode##_TC_RM : mode##_TC_RP) : \
(fMem ? mode##_TC_WM : mode##_TC_WP)) \
static inline DWORD get_trans_cmd(WDC_ADDR_MODE mode, WDC_DIRECTION direction, BOOL fBlock, BOOL fMem)
{
switch (mode)
{
case WDC_MODE_8:
return MODE_TO_TRANS_CMD(WDC_MODE_8, direction, fBlock, fMem);
case WDC_MODE_16:
return MODE_TO_TRANS_CMD(WDC_MODE_16, direction, fBlock, fMem);
case WDC_MODE_32:
return MODE_TO_TRANS_CMD(WDC_MODE_32, direction, fBlock, fMem);
case WDC_MODE_64:
return MODE_TO_TRANS_CMD(WDC_MODE_64, direction, fBlock, fMem);
default:
return 0;
}
}
/* -----------------------------------------------
Is memory/IO address space active
----------------------------------------------- */
BOOL DLLCALLCONV WDC_AddrSpaceIsActive(WDC_DEVICE_HANDLE hDev, DWORD dwAddrSpace)
{
WDC_ADDR_DESC *pAddrDesc;
#if defined(DEBUG)
if (!WdcIsValidDevHandle(hDev))
{
WDC_Err("WDC_AddrSpaceIsActive: %s", WdcGetLastErrStr());
return FALSE;
}
#endif
pAddrDesc = WDC_GET_ADDR_DESC(hDev, dwAddrSpace);
return (BOOL)pAddrDesc->dwBytes;
}
/* -----------------------------------------------
Read/Write memory and I/O addresses
----------------------------------------------- */
#define COPY_MEM_BLOCK(dst, src, dwBytes, bits) \
{ \
DWORD step = bits/8; \
for (; dwBytes; dwBytes-=step, src+=step, dst+=step) \
*(U##bits *)dst = *(U##bits *)src; \
}
static inline void CopyMemBlock(DWORD dst, DWORD src, DWORD dwBytes, WDC_ADDR_MODE mode)
{
switch (mode)
{
case WDC_MODE_8:
COPY_MEM_BLOCK(dst, src, dwBytes, 8);
break;
case WDC_MODE_16:
COPY_MEM_BLOCK(dst, src, dwBytes, 16);
break;
case WDC_MODE_32:
COPY_MEM_BLOCK(dst, src, dwBytes, 32);
break;
case WDC_MODE_64:
COPY_MEM_BLOCK(dst, src, dwBytes, 64);
break;
}
}
#define READ_WRITE_ADDR_TRANS(pAddrDesc, dwOffset, pData, bytes, mode, \
direction, options, dwStatus) \
{ \
BOOL fMem = WDC_ADDR_IS_MEM(pAddrDesc); \
WD_TRANSFER trans; \
\
BZERO(trans); \
trans.dwPort = (pAddrDesc)->kptAddr + dwOffset; \
trans.dwBytes = bytes; \
trans.cmdTrans = get_trans_cmd(mode, direction, TRUE, fMem); \
trans.Data.pBuffer = (PVOID)pData; \
trans.fAutoinc = !(options & WDC_ADDR_RW_NO_AUTOINC); \
\
dwStatus = WD_Transfer(WDC_GetWDHandle(), &trans); \
}
#define DECLARE_READ_ADDR(bits) \
DWORD DLLCALLCONV WDC_ReadAddr##bits(WDC_DEVICE_HANDLE hDev, DWORD dwAddrSpace, DWORD dwOffset, U##bits *val) \
{ \
DWORD dwStatus = WD_STATUS_SUCCESS; \
WDC_ADDR_DESC *pAddrDesc = WDC_GET_ADDR_DESC(hDev, dwAddrSpace); \
\
if (WDC_ADDR_IS_MEM(pAddrDesc)) \
*val = WDC_ReadMem##bits(WDC_MEM_DIRECT_ADDR(pAddrDesc), dwOffset); \
else \
{ \
READ_WRITE_ADDR_TRANS(pAddrDesc, dwOffset, val, WDC_MODE_##bits, \
WDC_MODE_##bits, WDC_READ, WDC_ADDR_RW_DEFAULT, dwStatus); \
} \
return dwStatus; \
}
#define DECLARE_WRITE_ADDR(bits) \
DWORD DLLCALLCONV WDC_WriteAddr##bits(WDC_DEVICE_HANDLE hDev, DWORD dwAddrSpace, DWORD dwOffset, U##bits val) \
{ \
DWORD dwStatus = WD_STATUS_SUCCESS; \
WDC_ADDR_DESC *pAddrDesc = WDC_GET_ADDR_DESC(hDev, dwAddrSpace); \
\
if (WDC_ADDR_IS_MEM(pAddrDesc)) \
WDC_WriteMem##bits(WDC_MEM_DIRECT_ADDR(pAddrDesc), dwOffset, val); \
else \
{ \
READ_WRITE_ADDR_TRANS(pAddrDesc, dwOffset, (PVOID)&val, WDC_MODE_##bits, \
WDC_MODE_##bits, WDC_WRITE, WDC_ADDR_RW_DEFAULT, dwStatus); \
} \
return dwStatus; \
}
DECLARE_READ_ADDR(8)
DECLARE_READ_ADDR(16)
DECLARE_READ_ADDR(32)
DECLARE_READ_ADDR(64)
DECLARE_WRITE_ADDR(8)
DECLARE_WRITE_ADDR(16)
DECLARE_WRITE_ADDR(32)
DECLARE_WRITE_ADDR(64)
DWORD DLLCALLCONV WDC_ReadAddrBlock(WDC_DEVICE_HANDLE hDev, DWORD dwAddrSpace,
DWORD dwOffset, DWORD dwBytes, PVOID pData, WDC_ADDR_MODE mode,
WDC_ADDR_RW_OPTIONS options)
{
DWORD dwStatus = WD_STATUS_SUCCESS;
WDC_ADDR_DESC *pAddrDesc = WDC_GET_ADDR_DESC(hDev, dwAddrSpace);
PVOID pAddr = (PVOID)(WDC_MEM_DIRECT_ADDR(pAddrDesc) + dwOffset);
if (!(options & WDC_ADDR_RW_NO_AUTOINC) && WDC_ADDR_IS_MEM(pAddrDesc))
CopyMemBlock((DWORD)pData, (DWORD)pAddr, dwBytes, mode);
else
READ_WRITE_ADDR_TRANS(pAddrDesc, dwOffset, pData, dwBytes, mode, WDC_READ, options, dwStatus);
return dwStatus;
}
DWORD DLLCALLCONV WDC_WriteAddrBlock(WDC_DEVICE_HANDLE hDev, DWORD dwAddrSpace,
DWORD dwOffset, DWORD dwBytes, PVOID pData, WDC_ADDR_MODE mode,
WDC_ADDR_RW_OPTIONS options)
{
DWORD dwStatus = WD_STATUS_SUCCESS;
WDC_ADDR_DESC *pAddrDesc = WDC_GET_ADDR_DESC(hDev, dwAddrSpace);
PVOID pAddr = (PVOID)(WDC_MEM_DIRECT_ADDR(pAddrDesc) + dwOffset);
if (!(options & WDC_ADDR_RW_NO_AUTOINC) && WDC_ADDR_IS_MEM(pAddrDesc))
CopyMemBlock((DWORD)pAddr, (DWORD)pData, dwBytes, mode);
else
READ_WRITE_ADDR_TRANS(pAddrDesc, dwOffset, pData, dwBytes, mode, WDC_WRITE, options, dwStatus);
return dwStatus;
}
/* Read/Write multiple addresses */
DWORD DLLCALLCONV WDC_MultiTransfer(WD_TRANSFER *pTrans, DWORD dwNumTrans)
{
#if defined (DEBUG)
if (!pTrans || !dwNumTrans)
{
WDC_Err("WDC_MultiTransfer: Error - %s\n",
!pTrans ? "NULL WD_TRANSFER pointer" : "no transfer commands (dwNumTrans == 0)");
return WD_INVALID_PARAMETER;
}
#endif
return WD_MultiTransfer(WDC_GetWDHandle(), pTrans, dwNumTrans);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -