📄 pci_lib.c
字号:
*************************************************************************
* NOTE: If you attempt to use this code without first modifying it in *
* order to correctly acknowledge your device's interrupts, as *
* explained above, the OS will HANG when an interrupt occurs! *
*************************************************************************
*/
/* Store the diag interrupt handler routine, which will be executed by
PCI_IntHandler() when an interrupt is received */
pDevCtx->funcDiagIntHandler = funcIntHandler;
/* Enable the interrupts */
dwStatus = WDC_IntEnable(hDev, NULL, NUM_TRANS_CMDS, 0,
PCI_IntHandler, (PVOID)pDev, WDC_IS_KP(hDev));
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed enabling interrupts. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
/* TODO: You can add code here to write to the device in order
to physically enable the hardware interrupts */
TraceLog("PCI_IntEnable: Interrupts enabled\n");
return WD_STATUS_SUCCESS;
}
DWORD PCI_IntDisable(WDC_DEVICE_HANDLE hDev)
{
DWORD dwStatus;
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
PPCI_DEV_CTX pDevCtx;
TraceLog("PCI_IntDisable entered. Device handle: 0x%p\n", hDev);
if (!IsValidDevice(pDev, "PCI_IntDisable"))
return WD_INVALID_PARAMETER;
pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
if (!WDC_IntIsEnabled(hDev))
{
ErrLog("Interrupts are already disabled ...\n");
return WD_OPERATION_ALREADY_DONE;
}
/* TODO: You can add code here to write to the device in order
to physically disable the hardware interrupts */
/* Disable the interrupts */
dwStatus = WDC_IntDisable(hDev);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed disabling interrupts. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
}
/* Free the memory allocated for the interrupt transfer commands */
if (pDevCtx->pIntTransCmds)
{
free(pDevCtx->pIntTransCmds);
pDevCtx->pIntTransCmds = NULL;
}
return dwStatus;
}
BOOL PCI_IntIsEnabled(WDC_DEVICE_HANDLE hDev)
{
if (!IsValidDevice((PWDC_DEVICE)hDev, "PCI_IntIsEnabled"))
return FALSE;
return WDC_IntIsEnabled(hDev);
}
/* -----------------------------------------------
Plug-and-play and power management events
----------------------------------------------- */
static void PCI_EventHandler(WD_EVENT *pEvent, PVOID pData)
{
PWDC_DEVICE pDev = (PWDC_DEVICE)pData;
PPCI_DEV_CTX pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
TraceLog("PCI_EventHandler entered, pData: 0x%p, dwAction 0x%lx\n",
pData, pEvent->dwAction);
/* Execute the diagnostics application's event handler function */
pDevCtx->funcDiagEventHandler((WDC_DEVICE_HANDLE)pDev, pEvent->dwAction);
}
DWORD PCI_EventRegister(WDC_DEVICE_HANDLE hDev, PCI_EVENT_HANDLER funcEventHandler)
{
DWORD dwStatus;
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
PPCI_DEV_CTX pDevCtx;
DWORD dwActions = WD_ACTIONS_ALL;
/* TODO: Modify the above to set up the plug-and-play/power management
events for which you wish to receive notifications.
dwActions can be set to any combination of the WD_EVENT_ACTION
flags defined in windrvr.h */
TraceLog("PCI_EventRegister entered. Device handle: 0x%p\n", hDev);
if (!IsValidDevice(pDev, "PCI_EventRegister"))
return WD_INVALID_PARAMETER;
pDevCtx = (PPCI_DEV_CTX)WDC_GetDevContext(pDev);
/* Check if event is already registered */
if (WDC_EventIsRegistered(hDev))
{
ErrLog("Events are already registered ...\n");
return WD_OPERATION_ALREADY_DONE;
}
/* Store the diag event handler routine to be executed from PCI_EventHandler() upon an event */
pDevCtx->funcDiagEventHandler = funcEventHandler;
/* Register event */
dwStatus = WDC_EventRegister(hDev, dwActions, PCI_EventHandler, hDev, FALSE);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed to register events. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
TraceLog("Events registered\n");
return WD_STATUS_SUCCESS;
}
DWORD PCI_EventUnregister(WDC_DEVICE_HANDLE hDev)
{
DWORD dwStatus;
TraceLog("PCI_EventUnregister entered. Device handle: 0x%p\n", hDev);
if (!IsValidDevice((PWDC_DEVICE)hDev, "PCI_EventUnregister"))
return WD_INVALID_PARAMETER;
if (!WDC_EventIsRegistered(hDev))
{
ErrLog("Cannot unregister events - no events currently registered ...\n");
return WD_OPERATION_ALREADY_DONE;
}
dwStatus = WDC_EventUnregister(hDev);
if (WD_STATUS_SUCCESS != dwStatus)
{
ErrLog("Failed to unregister events. Error 0x%lx - %s\n",
dwStatus, Stat2Str(dwStatus));
}
return dwStatus;
}
BOOL PCI_EventIsRegistered(WDC_DEVICE_HANDLE hDev)
{
if (!IsValidDevice((PWDC_DEVICE)hDev, "PCI_EventIsRegistered"))
return FALSE;
return WDC_EventIsRegistered(hDev);
}
/* -----------------------------------------------
Address spaces information
----------------------------------------------- */
DWORD PCI_GetNumAddrSpaces(WDC_DEVICE_HANDLE hDev)
{
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
if (!IsValidDevice(pDev, "PCI_GetNumAddrSpaces"))
return 0;
return pDev->dwNumAddrSpaces;
}
BOOL PCI_GetAddrSpaceInfo(WDC_DEVICE_HANDLE hDev, PCI_ADDR_SPACE_INFO *pAddrSpaceInfo)
{
PWDC_DEVICE pDev = (PWDC_DEVICE)hDev;
WDC_ADDR_DESC *pAddrDesc;
DWORD dwAddrSpace, dwMaxAddrSpace;
BOOL fIsMemory;
if (!IsValidDevice(pDev, "PCI_GetAddrSpaceInfo"))
return FALSE;
#if defined(DEBUG)
if (!pAddrSpaceInfo)
{
ErrLog("PCI_GetAddrSpaceInfo: Error - NULL address space information pointer\n");
return FALSE;
}
#endif
dwAddrSpace = pAddrSpaceInfo->dwAddrSpace;
dwMaxAddrSpace = pDev->dwNumAddrSpaces - 1;
if (dwAddrSpace > dwMaxAddrSpace)
{
ErrLog("PCI_GetAddrSpaceInfo: Error - Address space %ld is out of range (0 - %ld)\n",
dwAddrSpace, dwMaxAddrSpace);
return FALSE;
}
pAddrDesc = &pDev->pAddrDesc[dwAddrSpace];
fIsMemory = WDC_ADDR_IS_MEM(pAddrDesc);
snprintf(pAddrSpaceInfo->sName, MAX_NAME - 1, "BAR %ld", dwAddrSpace);
snprintf(pAddrSpaceInfo->sType, MAX_TYPE - 1, fIsMemory ? "Memory" : "I/O");
if (WDC_AddrSpaceIsActive(pDev, dwAddrSpace))
{
WD_ITEMS *pItem = &pDev->cardReg.Card.Item[pAddrDesc->dwItemIndex];
DWORD dwAddr = fIsMemory ? pItem->I.Mem.dwPhysicalAddr : (DWORD)pItem->I.IO.dwAddr;
snprintf(pAddrSpaceInfo->sDesc, MAX_DESC - 1, "0x%0*lX - 0x%0*lX (0x%lx bytes)",
(int)WDC_SIZE_32 * 2, dwAddr,
(int)WDC_SIZE_32 * 2, dwAddr + pAddrDesc->dwBytes - 1,
pAddrDesc->dwBytes);
}
else
snprintf(pAddrSpaceInfo->sDesc, MAX_DESC - 1, "Inactive address space");
/* TODO: You can modify the code above to set a different address space name/description */
return TRUE;
}
/* -----------------------------------------------
Debugging and error handling
----------------------------------------------- */
static void ErrLog(const CHAR *sFormat, ...)
{
va_list argp;
va_start(argp, sFormat);
vsnprintf(gsPCI_LastErr, sizeof(gsPCI_LastErr) - 1, sFormat, argp);
#if defined(DEBUG)
WDC_Err("PCI lib: %s", PCI_GetLastErr());
#endif
va_end(argp);
}
static void TraceLog(const CHAR *sFormat, ...)
{
#if defined(DEBUG)
CHAR sMsg[256];
va_list argp;
va_start(argp, sFormat);
vsnprintf(sMsg, sizeof(sMsg) - 1, sFormat, argp);
WDC_Trace("PCI lib: %s", sMsg);
va_end(argp);
#endif
}
const char *PCI_GetLastErr(void)
{
return gsPCI_LastErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -