⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wdc_diag_lib.c

📁 This a generic PCI express device driver that enable user to access the device without caring much o
💻 C
📖 第 1 页 / 共 3 页
字号:
/********************************************************************************
*  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 + -