📄 pci_lib.c
字号:
/************************************************************************
* File: pci_lib.c
*
* Library for accessing PCI devices.
* The code accesses hardware using WinDriver's WDC library.
* Code was generated by DriverWizard v7.01.
*
* Copyright (c) 2003 - 2005 Jungo Ltd. http://www.jungo.com
*************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include "wdc_defs.h"
#include "utils.h"
#include "status_strings.h"
#include "samples/shared/pci_regs.h"
#include "pci_lib.h"
/*************************************************************
Internal definitions
*************************************************************/
/* WinDriver license registration string */
/* TODO: When using a registered WinDriver version, replace the license string
below with your specific WinDriver license registration string */
#define PCI_DEFAULT_LICENSE_STRING "12345abcde1234.license"
/* PCI device information struct */
typedef struct {
WD_TRANSFER *pIntTransCmds;
PCI_INT_HANDLER funcDiagIntHandler;
PCI_EVENT_HANDLER funcDiagEventHandler;
} PCI_DEV_CTX, *PPCI_DEV_CTX;
/* TODO: You can add fields to store additional device-specific information */
static CHAR gsPCI_LastErr[256];
/*************************************************************
Static functions prototypes and inline implementation
*************************************************************/
static BOOL DeviceValidate(const PWDC_DEVICE pDev);
static void DLLCALLCONV PCI_IntHandler(PVOID pData);
static void PCI_EventHandler(WD_EVENT *pEvent, PVOID pData);
static void ErrLog(const CHAR *sFormat, ...);
static void TraceLog(const CHAR *sFormat, ...);
static inline BOOL IsValidDevice(PWDC_DEVICE pDev, const CHAR *sFunc)
{
if (!pDev || !WDC_GetDevContext(pDev))
{
snprintf(gsPCI_LastErr, sizeof(gsPCI_LastErr) - 1, "%s: NULL device %s\n",
sFunc, !pDev ? "handle" : "context");
ErrLog(gsPCI_LastErr);
return FALSE;
}
return TRUE;
}
/*************************************************************
Functions implementation
*************************************************************/
/* -----------------------------------------------
PCI and WDC library initialize/uninit
----------------------------------------------- */
DWORD PCI_LibInit(void)
{
DWORD dwStatus;
/* Set WDC library's debug options (default: level TRACE, output to Debug Monitor) */
dwStatus = WDC_SetDebugOptions(WDC_DBG_DEFAULT, NULL);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed to initialize debug options for WDC library.\n"
"Error 0x%lx - %s\n", dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
/* Open a handle to the driver and initialize the WDC library */
dwStatus = WDC_DriverOpen(WDC_DRV_OPEN_DEFAULT, PCI_DEFAULT_LICENSE_STRING);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed to initialize the WDC library. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
return WD_STATUS_SUCCESS;
}
DWORD PCI_LibUninit(void)
{
DWORD dwStatus;
/* Uninit the WDC library and close the handle to WinDriver */
dwStatus = WDC_DriverClose();
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed to uninit the WDC library. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
}
return dwStatus;
}
/* -----------------------------------------------
Device open/close
----------------------------------------------- */
WDC_DEVICE_HANDLE PCI_DeviceOpen(const WD_PCI_CARD_INFO *pDeviceInfo)
{
DWORD dwStatus;
PPCI_DEV_CTX pDevCtx = NULL;
WDC_DEVICE_HANDLE hDev = NULL;
/* Validate arguments */
if (!pDeviceInfo)
{
ErrLog("PCI_DeviceOpen: Error - NULL device information struct pointer\n");
return NULL;
}
/* Allocate memory for the PCI device context */
pDevCtx = (PPCI_DEV_CTX)malloc(sizeof (PCI_DEV_CTX));
if (!pDevCtx)
{
ErrLog("Failed allocating memory for PCI device context\n");
return NULL;
}
BZERO(*pDevCtx);
/* Open a WDC device handle */
dwStatus = WDC_PciDeviceOpen(&hDev, pDeviceInfo, pDevCtx, NULL, NULL, NULL);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed opening a WDC device handle. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
goto Error;
}
/* Validate device information */
if (!DeviceValidate((PWDC_DEVICE)hDev))
goto Error;
/* Return handle to the new device */
TraceLog("PCI_DeviceOpen: Opened a PCI device (handle 0x%p)\n", hDev);
return hDev;
Error:
if (hDev)
PCI_DeviceClose(hDev);
else
free(pDevCtx);
return NULL;
}
BOOL PCI_DeviceClose(WDC_DEVICE_HANDLE hDev)
{
DWORD dwStatus;
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
PPCI_DEV_CTX pDevCtx;
TraceLog("PCI_DeviceClose entered. Device handle: 0x%p\n", hDev);
if (!hDev)
{
ErrLog("PCI_DeviceClose: Error - NULL device handle\n");
return FALSE;
}
pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
/* Disable interrupts */
if (WDC_IntIsEnabled(hDev))
{
dwStatus = PCI_IntDisable(hDev);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed disabling interrupts. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
}
}
/* Close the device */
dwStatus = WDC_PciDeviceClose(hDev);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed closing a WDC device handle (0x%p). Error 0x%lx - %s\n",
hDev, dwStatus, Stat2Str(dwStatus));
}
/* Free PCI device context memory */
if (pDevCtx)
free (pDevCtx);
return (WD_STATUS_SUCCESS == dwStatus);
}
static BOOL DeviceValidate(const PWDC_DEVICE pDev)
{
DWORD i, dwNumAddrSpaces = pDev->dwNumAddrSpaces;
/* TODO: You can modify the implementation of this function in order to
verify that the device has all expected resources. */
/* Verify that the device has at least one active address space */
for (i = 0; i < dwNumAddrSpaces; i++)
{
if (WDC_AddrSpaceIsActive(pDev, i))
return TRUE;
}
ErrLog("Device does not have any active memory or I/O address spaces\n");
return FALSE;
}
/* -----------------------------------------------
Interrupts
----------------------------------------------- */
static void DLLCALLCONV PCI_IntHandler(PVOID pData)
{
PWDC_DEVICE pDev = (PWDC_DEVICE)pData;
PPCI_DEV_CTX pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
PCI_INT_RESULT intResult;
BZERO(intResult);
intResult.dwCounter = pDev->Int.dwCounter;
intResult.dwLost = pDev->Int.dwLost;
intResult.waitResult = (WD_INTERRUPT_WAIT_RESULT)pDev->Int.fStopped;
/* Execute the diagnostics application's interrupt handler routine */
pDevCtx->funcDiagIntHandler((WDC_DEVICE_HANDLE)pDev, &intResult);
}
DWORD PCI_IntEnable(WDC_DEVICE_HANDLE hDev, PCI_INT_HANDLER funcIntHandler)
{
DWORD dwStatus;
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
PPCI_DEV_CTX pDevCtx;
TraceLog("PCI_IntEnable entered. Device handle: 0x%p\n", hDev);
if (!IsValidDevice(pDev, "PCI_IntEnable"))
return WD_INVALID_PARAMETER;
pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
/* Check if interrupts are already enabled */
if (WDC_IntIsEnabled(hDev))
{
ErrLog("Interrupts are already enabled ...\n");
return WD_OPERATION_ALREADY_DONE;
}
/* Define the number of interrupt transfer commands to use */
#define NUM_TRANS_CMDS 0
/*
TODO: Your hardware has level sensitive interrupts, which must be
acknowledged in the kernel immediately when they are received.
Since the information for acknowledging the interrupts is
hardware-specific, YOU MUST ADD CODE to read/write the relevant
register(s) in order to correctly acknowledge the interrupts
on your device, as dictated by your hardware's specifications.
When adding transfer commands, be sure to also modify the
definition of NUM_TRANS_CMDS (above) accordingly.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -