📄 wdc_diag_lib.c
字号:
/********************************************************************************
* File: wdc_diag_lib.c - Implementation PCI devices' user-mode diagnostics API.*
* *
* *
*********************************************************************************/
#if !defined(__KERNEL__)
#include <stdio.h>
#include "status_strings.h"
#include "pci_regs.h"
#include "pccard_cis.h"
#include "diag_lib.h"
#include "wdc_diag_lib.h"
/*************************************************************
General definitions
*************************************************************/
/* Error messages display */
#define WDC_DIAG_ERR printf
/*************************************************************
Global variables
*************************************************************/
/* User's input command */
static CHAR gsInput[256];
/* -----------------------------------------------
All buses (PCI/PCMCIA/ISA)
----------------------------------------------- */
/* Print device's resources information to file.
For a registered device (hCard != 0), print also kernel and user-mode
mappings of memory address items */
static void WDC_DIAG_DeviceResourcesPrint(const WD_CARD *pCard, DWORD hCard,
FILE *fp)
{
int resources;
DWORD i;
const WD_ITEMS *pItem;
if (!pCard)
{
WDC_DIAG_ERR("WDC_DIAG_DeviceResourcesPrint: Error - NULL card "
"pointer\n");
return;
}
for (i = 0, resources = 0; i < pCard->dwItems; i++)
{
pItem = &pCard->Item[i];
switch (pItem->item)
{
case ITEM_MEMORY:
resources ++;
fprintf(fp," Memory range [BAR %ld]: base 0x%lX, size 0x%lX\n",
pItem->I.Mem.dwBar, pItem->I.Mem.dwPhysicalAddr,
pItem->I.Mem.dwBytes);
if (hCard) /* Registered device */
{
fprintf(fp," Kernel-mode address mapping: 0x%"KPRI"X\n",
pItem->I.Mem.dwTransAddr);
fprintf(fp," User-mode address mapping: 0x%lX\n",
pItem->I.Mem.dwUserDirectAddr);
}
break;
case ITEM_IO:
resources ++;
fprintf(fp, " I/O range [BAR %ld]: base 0x%"KPRI"X, size "
"0x%lX\n", pItem->I.IO.dwBar, pItem->I.IO.dwAddr,
pItem->I.IO.dwBytes);
break;
case ITEM_INTERRUPT:
resources ++;
fprintf(fp, " Interrupt: IRQ %ld\n", pItem->I.Int.dwInterrupt);
break;
case ITEM_BUS:
break;
default:
fprintf(fp, " Invalid item type (0x%lx)\n", pItem->item);
break;
}
}
if (!resources)
fprintf(fp, " Device has no resources\n");
}
/* Print run-time registers and PCI configuration registers information */
void WDC_DIAG_RegsInfoPrint(const WDC_REG *pRegs, DWORD dwNumRegs,
WDC_DIAG_REG_PRINT_OPTIONS options)
{
const WDC_REG *pReg;
BOOL fName, fDesc, fAddrSpace, fOffset, fSize, fDir;
DWORD i;
if (!dwNumRegs)
{
printf("There are currently no pre-defined registers to display\n");
return;
}
if (!pRegs)
{
WDC_DIAG_ERR("WDC_DIAG_RegsInfoPrint: Error - NULL registers "
"information pointer\n");
return;
}
if (!options)
options = WDC_DIAG_REG_PRINT_DEFAULT;
fName = options & WDC_DIAG_REG_PRINT_NAME,
fDesc = options & WDC_DIAG_REG_PRINT_DESC,
fAddrSpace = options & WDC_DIAG_REG_PRINT_ADDR_SPACE,
fOffset = options & WDC_DIAG_REG_PRINT_OFFSET,
fSize = options & WDC_DIAG_REG_PRINT_SIZE;
fDir = options & WDC_DIAG_REG_PRINT_DIRECTION;
printf("%3s %-*s %-*s %-*s %-*s %-*s %s\n",
"",
MAX_NAME_DISPLAY, fName ? "Name" : "",
4, fAddrSpace ? "BAR" : "",
(int)WDC_SIZE_32 * 2 + 2, fOffset ? "Offset" : "",
5, fSize ? "Size" : "",
4, fDir ? "R/W" : "",
fDesc ? "Description" : "");
printf("%3s %-*s %-*s %-*s %-*s %-*s %s\n",
"",
MAX_NAME_DISPLAY, fName ? "----" : "",
4, fAddrSpace ? "---" : "",
(int)WDC_SIZE_32 * 2 + 2, fOffset ? "------" : "",
5, fSize ? "----" : "",
4, fDir ? "---" : "",
fDesc ? "-----------" : "");
for (i = 1, pReg = pRegs; i <= dwNumRegs; i++, pReg++)
{
printf("%2ld. ", i);
if (fName)
printf("%-*.*s ", MAX_NAME_DISPLAY, MAX_NAME_DISPLAY, pReg->sName);
else
printf("%*s ", MAX_NAME_DISPLAY, "");
if (fAddrSpace && (WDC_AD_CFG_SPACE != pReg->dwAddrSpace))
printf("%2ld %*s", pReg->dwAddrSpace, 2, "");
else
printf("%4s ", "");
if (fOffset)
printf("0x%-*lX ", (int)WDC_SIZE_32 * 2, pReg->dwOffset);
else
printf("%*s ", (int)WDC_SIZE_32 * 2 + 2, "");
if (fSize)
printf("%*ld %*s", 2, pReg->dwSize, 3, "");
else
printf("%*s ", 5, "");
if (fDir)
{
printf("%-*s ", 4,
(WDC_READ_WRITE == pReg->direction) ? "RW" :
(WDC_READ == pReg->direction) ? "R" : "W");
}
else
printf("%*s ", 4, "");
if (fDesc)
printf("%.*s", 36, pReg->sDesc);
printf("\n");
}
}
/* Set address access mode */
BOOL WDC_DIAG_SetMode(WDC_ADDR_MODE *pMode)
{
int option = 0;
if (!pMode)
{
WDC_DIAG_ERR("WDC_DIAG_SetMode: Error - NULL mode pointer\n");
return FALSE;
}
printf("\n");
printf("Select read/write mode:\n");
printf("-----------------------\n");
printf("1. 8 bits (%ld bytes)\n", WDC_SIZE_8);
printf("2. 16 bits (%ld bytes)\n", WDC_SIZE_16);
printf("3. 32 bits (%ld bytes)\n", WDC_SIZE_32);
printf("4. 64 bits (%ld bytes)\n", WDC_SIZE_64);
printf("\n");
printf("Enter option or 0 to cancel: ");
fgets(gsInput, sizeof(gsInput), stdin);
if (sscanf(gsInput, "%d", &option) < 1)
{
printf("Invalid input\n");
return FALSE;
}
if (!option)
return FALSE;
switch (option)
{
case 1:
*pMode = WDC_MODE_8;
break;
case 2:
*pMode = WDC_MODE_16;
break;
case 3:
*pMode = WDC_MODE_32;
break;
case 4:
*pMode = WDC_MODE_64;
break;
default:
printf("Invalid selection\n");
return FALSE;
}
return TRUE;
}
/* Get data for address write operation from user */
/* Data size (dwSize) should be WDC_SIZE_8, WDC_SIZE_16, WDC_SIZE_32 or WDC_SIZE_64 */
BOOL WDC_DIAG_InputWriteData(PVOID pData, WDC_ADDR_SIZE dwSize)
{
UINT64 u64Data, u64MaxVal;
if (!pData)
{
WDC_DIAG_ERR("WDC_DIAG_InputWriteData: Error - NULL data pointer\n");
return FALSE;
}
u64MaxVal = (dwSize >= WDC_SIZE_64) ? ~((UINT64)0) :
((UINT64)1 << (dwSize * 8)) - 1;
printf("Enter data to write (max value: 0x%"PRI64"X) or '%c' to cancel: 0x",
u64MaxVal, DIAG_CANCEL);
fgets(gsInput, sizeof(gsInput), stdin);
if (DIAG_CANCEL == tolower(gsInput[0]))
return FALSE;
BZERO(u64Data);
if (sscanf(gsInput, "%"PRI64"x", &u64Data) < 1)
{
printf("Invalid input\n");
return FALSE;
}
if (u64Data > u64MaxVal)
{
printf("Error: Value is too big (max legal value is 0x%"PRI64"X)\n",
u64MaxVal);
return FALSE;
}
switch (dwSize)
{
case WDC_SIZE_8:
*((BYTE*)pData) = (BYTE)u64Data;
return TRUE;
case WDC_SIZE_16:
*((WORD*)pData) = (WORD)u64Data;
return TRUE;
case WDC_SIZE_32:
*((UINT32*)pData) = (UINT32)u64Data;
return TRUE;
case WDC_SIZE_64:
*((UINT64*)pData) = (UINT64)u64Data;
return TRUE;
default:
WDC_DIAG_ERR("WDC_DIAG_InputWriteData: Error - Invalid size (%ld bytes)\n", dwSize);
}
return FALSE;
}
/* Read/write a memory or I/O address */
void WDC_DIAG_ReadWriteAddr(WDC_DEVICE_HANDLE hDev, WDC_DIRECTION direction,
DWORD dwAddrSpace, WDC_ADDR_MODE mode)
{
DWORD dwStatus;
DWORD dwOffset;
BYTE bData = 0;
WORD wData = 0;
UINT32 u32Data = 0;
UINT64 u64Data = 0;
if (!hDev)
{
WDC_DIAG_ERR("WDC_DIAG_ReadWriteAddr: Error - NULL WDC device handle\n");
return;
}
if (!DIAG_InputDWORD(&dwOffset, (WDC_READ == direction) ?
"Enter offset to read from" : "Enter offset to write to", TRUE, 0, 0))
return;
if ((WDC_WRITE == direction) &&
!WDC_DIAG_InputWriteData((WDC_MODE_8 == mode) ? (PVOID)&bData :
(WDC_MODE_16 == mode) ? (PVOID)&wData :
(WDC_MODE_32 == mode) ? (PVOID)&u32Data : (PVOID)&u64Data,
WDC_ADDR_MODE_TO_SIZE(mode)))
{
return;
}
switch (mode)
{
case WDC_MODE_8:
dwStatus = (WDC_READ == direction) ?
WDC_ReadAddr8(hDev, dwAddrSpace, dwOffset, &bData) :
WDC_WriteAddr8(hDev, dwAddrSpace, dwOffset, bData);
if (WD_STATUS_SUCCESS == dwStatus)
{
printf("%s 0x%X %s offset 0x%lX in BAR %ld\n",
(WDC_READ == direction) ? "Read" : "Wrote", (UINT32)bData,
(WDC_READ == direction) ? "from" : "to", dwOffset, dwAddrSpace);
}
break;
case WDC_MODE_16:
dwStatus = (WDC_READ == direction) ?
WDC_ReadAddr16(hDev, dwAddrSpace, dwOffset, &wData) :
WDC_WriteAddr16(hDev, dwAddrSpace, dwOffset, wData);
if (WD_STATUS_SUCCESS == dwStatus)
{
printf("%s 0x%hX %s offset 0x%lX in BAR %ld\n",
(WDC_READ == direction) ? "Read" : "Wrote", wData,
(WDC_READ == direction) ? "from" : "to", dwOffset, dwAddrSpace);
}
break;
case WDC_MODE_32:
dwStatus = (WDC_READ == direction) ?
WDC_ReadAddr32(hDev, dwAddrSpace, dwOffset, &u32Data) :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -