Jungo WinDriver  
Official Documentation
kp_pci.c
Go to the documentation of this file.
1/* @JUNGO_COPYRIGHT@ */
2
3/************************************************************************
4* File: kp_pci.c
5*
6* Kernel PlugIn driver for accessing PCI devices.
7* The code accesses hardware using WinDriver's WDC library.
8@CODE_GEN@
9*
10* Note: This code sample is provided AS-IS and as a guiding sample only.
11*************************************************************************/
12
13#include "kpstdlib.h"
14#include "wd_kp.h"
15#ifndef ISA
16#include "pci_regs.h"
17#endif /* ifndef ISA */
18#include "../pci_lib.h"
19
20/*************************************************************
21 Functions prototypes
22 *************************************************************/
23BOOL __cdecl KP_PCI_Open(KP_OPEN_CALL *kpOpenCall, HANDLE hWD, PVOID pOpenData,
24 PVOID *ppDrvContext);
25/* @32on64@ */
26BOOL __cdecl KP_PCI_Open_32_64(KP_OPEN_CALL *kpOpenCall, HANDLE hWD,
27 PVOID pOpenData, PVOID *ppDrvContext);
28/* @32on64@ */
29void __cdecl KP_PCI_Close(PVOID pDrvContext);
30void __cdecl KP_PCI_Call(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall);
31BOOL __cdecl KP_PCI_IntEnable(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall,
32 PVOID *ppIntContext);
33void __cdecl KP_PCI_IntDisable(PVOID pIntContext);
34BOOL __cdecl KP_PCI_IntAtIrql(PVOID pIntContext, BOOL *pfIsMyInterrupt);
35DWORD __cdecl KP_PCI_IntAtDpc(PVOID pIntContext, DWORD dwCount);
36BOOL __cdecl KP_PCI_IntAtIrqlMSI(PVOID pIntContext, ULONG dwLastMessage,
37 DWORD dwReserved);
38DWORD __cdecl KP_PCI_IntAtDpcMSI(PVOID pIntContext, DWORD dwCount,
39 ULONG dwLastMessage, DWORD dwReserved);
40#ifndef ISA
41BOOL __cdecl KP_PCI_Event(PVOID pDrvContext, WD_EVENT *wd_event);
42#endif /* ifndef ISA */
43static void KP_PCI_Err(const CHAR *sFormat, ...);
44static void KP_PCI_Trace(const CHAR *sFormat, ...);
45/* @32on64@ */
46#define PTR32 UINT32
47
48typedef struct {
49 UINT32 dwNumAddrSpaces; /* Total number of device address spaces */
50 PTR32 pAddrDesc; /* Array of device address spaces information */
51} PCI_DEV_ADDR_DESC_32B;
52/* @32on64@ */
53
54/*************************************************************
55 Functions implementation
56 *************************************************************/
57
65BOOL __cdecl KP_Init(KP_INIT *kpInit)
66{
67 /* Verify that the version of the WinDriver Kernel PlugIn library
68 is identical to that of the windrvr.h and wd_kp.h files */
69 if (WD_VER != kpInit->dwVerWD)
70 {
71 /* Rebuild your Kernel PlugIn driver project with the compatible
72 version of the WinDriver Kernel PlugIn library (kp_nt<version>.lib)
73 and windrvr.h and wd_kp.h files */
74
75 return FALSE;
76 }
77
78 kpInit->funcOpen = KP_PCI_Open;
79/* @32on64@ */
81/* @32on64@ */
82#if defined(WINNT)
83 strcpy(kpInit->cDriverName, KP_PCI_DRIVER_NAME);
84#else
85 strncpy(kpInit->cDriverName, KP_PCI_DRIVER_NAME,
86 sizeof(kpInit->cDriverName));
87#endif
88 kpInit->cDriverName[sizeof(kpInit->cDriverName) - 1] = 0;
89
90 return TRUE;
91}
92
154BOOL __cdecl KP_PCI_Open(KP_OPEN_CALL *kpOpenCall, HANDLE hWD, PVOID pOpenData,
155 PVOID *ppDrvContext)
156{
157 PCI_DEV_ADDR_DESC *pDevAddrDesc;
158 DWORD dwSize;
159 DWORD dwStatus;
160
161 /* Initialize the PCI library */
162 dwStatus = PCI_LibInit();
163 if (WD_STATUS_SUCCESS != dwStatus)
164 {
165 KP_PCI_Err("KP_PCI_Open: Failed to initialize the PCI library. "
166 "Last error [%s]\n", PCI_GetLastErr());
167 return FALSE;
168 }
169
170 KP_PCI_Trace("KP_PCI_Open: Entered. PCI library initialized\n");
171
172 kpOpenCall->funcClose = KP_PCI_Close;
173 kpOpenCall->funcCall = KP_PCI_Call;
174 kpOpenCall->funcIntEnable = KP_PCI_IntEnable;
175 kpOpenCall->funcIntDisable = KP_PCI_IntDisable;
176 kpOpenCall->funcIntAtIrql = KP_PCI_IntAtIrql;
177 kpOpenCall->funcIntAtDpc = KP_PCI_IntAtDpc;
180#ifndef ISA
181 kpOpenCall->funcEvent = KP_PCI_Event;
182#endif /* ifndef ISA */
183
184 if (ppDrvContext)
185 {
186 if (pOpenData)
187 {
188 WDC_ADDR_DESC *pAddrDesc;
189
190 /* Create a copy of device information in the driver context */
191 dwSize = sizeof(PCI_DEV_ADDR_DESC);
192 pDevAddrDesc = malloc(dwSize);
193 if (!pDevAddrDesc)
194 goto malloc_error;
195
196 COPY_FROM_USER(pDevAddrDesc, pOpenData, dwSize);
197
198 dwSize = sizeof(WDC_ADDR_DESC) * pDevAddrDesc->dwNumAddrSpaces;
199 pAddrDesc = malloc(dwSize);
200 if (!pAddrDesc)
201 goto malloc_error;
202
203 COPY_FROM_USER(pAddrDesc, pDevAddrDesc->pAddrDesc, dwSize);
204 pDevAddrDesc->pAddrDesc = pAddrDesc;
205
206 *ppDrvContext = pDevAddrDesc;
207 }
208 else
209 {
210 *ppDrvContext = NULL;
211 }
212 }
213
214 KP_PCI_Trace("KP_PCI_Open: Kernel PlugIn driver opened successfully\n");
215
216 return TRUE;
217
218malloc_error:
219 KP_PCI_Err("KP_PCI_Open: Failed allocating [%ld] bytes\n", dwSize);
220 if (pDevAddrDesc)
221 free(pDevAddrDesc);
222 PCI_LibUninit();
223 return FALSE;
224}
225
226/* @32on64@ */
227
234BOOL __cdecl KP_PCI_Open_32_64(KP_OPEN_CALL *kpOpenCall, HANDLE hWD,
235 PVOID pOpenData, PVOID *ppDrvContext)
236{
237 PCI_DEV_ADDR_DESC *pDevAddrDesc;
238 DWORD dwSize;
239 DWORD dwStatus;
240
241 /* Initialize the PCI library */
242 dwStatus = PCI_LibInit();
243 if (WD_STATUS_SUCCESS != dwStatus)
244 {
245 KP_PCI_Err("KP_PCI_Open_32_64: Failed to initialize the PCI library. "
246 "Last error [%s]\n", PCI_GetLastErr());
247 return FALSE;
248 }
249
250 KP_PCI_Trace("KP_PCI_Open_32_64: Entered. PCI library initialized\n");
251
252 kpOpenCall->funcClose = KP_PCI_Close;
253 kpOpenCall->funcCall = KP_PCI_Call;
254 kpOpenCall->funcIntEnable = KP_PCI_IntEnable;
255 kpOpenCall->funcIntDisable = KP_PCI_IntDisable;
256 kpOpenCall->funcIntAtIrql = KP_PCI_IntAtIrql;
257 kpOpenCall->funcIntAtDpc = KP_PCI_IntAtDpc;
260#ifndef ISA
261 kpOpenCall->funcEvent = KP_PCI_Event;
262#endif /* ifndef ISA */
263
264 if (ppDrvContext)
265 {
266 if (pOpenData)
267 {
268 PCI_DEV_ADDR_DESC_32B devAddrDesc_32;
269 WDC_ADDR_DESC *pAddrDesc;
270
271 /* Create a copy of the device information in the driver context */
272 dwSize = sizeof(PCI_DEV_ADDR_DESC);
273 pDevAddrDesc = malloc(dwSize);
274 if (!pDevAddrDesc)
275 goto malloc_error;
276
277 /* Copy device information sent from a 32-bit user application */
278 COPY_FROM_USER(&devAddrDesc_32, pOpenData,
279 sizeof(PCI_DEV_ADDR_DESC_32B));
280
281 /* Copy the 32-bit data to a 64-bit struct */
282 pDevAddrDesc->dwNumAddrSpaces = devAddrDesc_32.dwNumAddrSpaces;
283 dwSize = sizeof(WDC_ADDR_DESC) * pDevAddrDesc->dwNumAddrSpaces;
284 pAddrDesc = malloc(dwSize);
285 if (!pAddrDesc)
286 goto malloc_error;
287
288 COPY_FROM_USER(pAddrDesc, (PVOID)(KPTR)devAddrDesc_32.pAddrDesc,
289 dwSize);
290 pDevAddrDesc->pAddrDesc = pAddrDesc;
291
292 *ppDrvContext = pDevAddrDesc;
293 }
294 else
295 {
296 *ppDrvContext = NULL;
297 }
298 }
299
300 KP_PCI_Trace("KP_PCI_Open_32_64: Kernel PlugIn driver opened "
301 "successfully\n");
302
303 return TRUE;
304
305malloc_error:
306 KP_PCI_Err("KP_PCI_Open_32_64: Failed allocating [%ld] bytes\n", dwSize);
307 if (pDevAddrDesc)
308 free(pDevAddrDesc);
309 PCI_LibUninit();
310 return FALSE;
311}
312/* @32on64@ */
313
326void __cdecl KP_PCI_Close(PVOID pDrvContext)
327{
328 DWORD dwStatus;
329
330 KP_PCI_Trace("KP_PCI_Close: Entered\n");
331
332 /* Uninit the PCI library */
333 dwStatus = PCI_LibUninit();
334 if (WD_STATUS_SUCCESS != dwStatus)
335 {
336 KP_PCI_Err("KP_PCI_Close: Failed to uninit the PCI library. "
337 "Last error [%s]\n", PCI_GetLastErr());
338 }
339
340 /* Free the memory allocated for the driver context */
341 if (pDrvContext)
342 {
343 if (((PCI_DEV_ADDR_DESC *)pDrvContext)->pAddrDesc)
344 free(((PCI_DEV_ADDR_DESC *)pDrvContext)->pAddrDesc);
345 free(pDrvContext);
346 }
347}
348
377void __cdecl KP_PCI_Call(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall)
378{
379 KP_PCI_Trace("KP_PCI_Call: Entered. Message [0x%lx]\n", kpCall->dwMessage);
380
381 kpCall->dwResult = KP_PCI_STATUS_OK;
382
383 switch (kpCall->dwMessage)
384 {
385 case KP_PCI_MSG_VERSION: /* Get the version of the Kernel PlugIn driver */
386 {
387 KP_PCI_VERSION *pUserKPVer = (KP_PCI_VERSION *)(kpCall->pData);
388 KP_PCI_VERSION kernelKPVer;
389
390 BZERO(kernelKPVer);
391 kernelKPVer.dwVer = 100;
392#define DRIVER_VER_STR "My Driver V1.00"
393 memcpy(kernelKPVer.cVer, DRIVER_VER_STR, sizeof(DRIVER_VER_STR));
394 COPY_TO_USER(pUserKPVer, &kernelKPVer, sizeof(KP_PCI_VERSION));
395 kpCall->dwResult = KP_PCI_STATUS_OK;
396 }
397 break;
398
399 default:
400 kpCall->dwResult = KP_PCI_STATUS_MSG_NO_IMPL;
401 }
402
403 /* NOTE: You can modify the messages above and/or add your own
404 Kernel PlugIn messages.
405 When changing/adding messages, be sure to also update the
406 messages definitions in ../pci_lib.h. */
407}
428BOOL __cdecl KP_PCI_IntEnable(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall,
429 PVOID *ppIntContext)
430{
431 KP_PCI_Trace("KP_PCI_IntEnable: Entered\n");
432
433 /* You can allocate specific memory for each interrupt in *ppIntContext */
434
435 /* In this sample we will set the interrupt context to the driver context,
436 which has been set in KP_PCI_Open to hold the device information. */
437 *ppIntContext = pDrvContext;
438
439 /* TODO: You can add code here to write to the device in order
440 to physically enable the hardware interrupts */
441
442 return TRUE;
443}
444
456void __cdecl KP_PCI_IntDisable(PVOID pIntContext)
457{
458 /* Free any memory allocated in KP_PCI_IntEnable() here */
459}
495BOOL __cdecl KP_PCI_IntAtIrql(PVOID pIntContext, BOOL *pfIsMyInterrupt)
496{
497 static DWORD dwIntCount = 0; /* Interrupts count */
498 PCI_DEV_ADDR_DESC *pDevAddrDesc = (PCI_DEV_ADDR_DESC *)pIntContext;
499/* @kp_IntAtIrql@ */
500/* @sample_only_start@ */
501#ifndef ISA
502 WDC_ADDR_DESC *pAddrDesc = &pDevAddrDesc->pAddrDesc[INTCSR_ADDR_SPACE];
503
504#define USE_MULTI_TRANSFER
505#if defined USE_MULTI_TRANSFER
506 /* Define the number of interrupt transfer commands to use */
507 WD_TRANSFER trans[2];
508
509 /*
510 This sample demonstrates how to set up two transfer commands, one for
511 reading the device's INTCSR register (as defined in gPCI_Regs) and one
512 for writing to it to acknowledge the interrupt.
513
514 TODO: PCI interrupts are level sensitive interrupts and must be
515 acknowledged in the kernel immediately when they are received.
516 Since the information for acknowledging the interrupts is
517 hardware-specific, YOU MUST MODIFY THE CODE below and set up
518 transfer commands in order to correctly acknowledge the interrupts
519 on your device, as dictated by your hardware's specifications.
520
521 *************************************************************************
522 * NOTE: If you attempt to use this code without first modifying it in *
523 * order to correctly acknowledge your device's interrupts, as *
524 * explained above, the OS will HANG when an interrupt occurs! *
525 *************************************************************************
526 */
527
528 BZERO(trans);
529
530 /* Prepare the interrupt transfer commands */
531
532 /* #1: Read status from the INTCSR register */
533 trans[0].pPort = pAddrDesc->pAddr + INTCSR;
534 /* 32bit read: */
535 trans[0].cmdTrans = WDC_ADDR_IS_MEM(pAddrDesc) ? RM_DWORD : RP_DWORD;
536
537 /* #2: Write ALL_INT_MASK to the INTCSR register to acknowledge the
538 interrupt */
539 /* In this example both commands access the same address (register): */
540 trans[1].pPort = trans[0].pPort;
541 /* 32bit write: */
542 trans[1].cmdTrans = WDC_ADDR_IS_MEM(pAddrDesc) ? WM_DWORD : WP_DWORD;
543 trans[1].Data.Dword = ALL_INT_MASK;
544
545 /* Execute the transfer commands */
546 WDC_MultiTransfer(trans, 2);
547#else
548 /* NOTE: For memory registers you can replace the use of WDC_MultiTransfer()
549 (or any other WD_xxx/WDC_xxx read/write function call) with direct
550 memory access. For example, if INTCSR is a memory register, the code
551 above can be replaced with the following: */
552
553 UINT32 readData;
554 PVOID pData = (DWORD *)(pAddrDesc->pAddr + INTCSR);
555
556 /* Read status from the PCI_INTCSR register */
557 readData = WDC_ReadMem32(pData, 0);
558
559 /* Write to the PCI_INTCSR register to acknowledge the interrupt */
560 WDC_WriteMem32(pData, 0, ALL_INT_MASK);
561#endif
562#undef USE_MULTI_TRANSFER
563
564 /* If the data read from the hardware indicates that the interrupt belongs
565 to you, you must set *pfIsMyInterrupt to TRUE.
566 Otherwise, set it to FALSE (this will let ISR's of other drivers be
567 invoked). */
568 *pfIsMyInterrupt = FALSE;
569#endif /* ifndef ISA */
570/* @sample_only_end@ */
571 /* This sample schedules a DPC once in every 5 interrupts.
572 TODO: You can modify the implementation to schedule the DPC as needed. */
573 dwIntCount++;
574 if (!(dwIntCount % 5))
575 return TRUE;
576
577 return FALSE;
578}
579
602DWORD __cdecl KP_PCI_IntAtDpc(PVOID pIntContext, DWORD dwCount)
603{
604 return dwCount;
605}
643BOOL __cdecl KP_PCI_IntAtIrqlMSI(PVOID pIntContext, ULONG dwLastMessage,
644 DWORD dwReserved)
645{
646 static DWORD dwIntCount = 0; /* Interrupts count */
647
648 /* There is no need to acknowledge MSI/MSI-X. However, you can implement
649 the same functionality here as done in the KP_PCI_IntAtIrql handler
650 to read/write data from/to registers at HIGH IRQL. */
651
652 /* This sample schedules a DPC once in every 5 interrupts.
653 TODO: You can modify the implementation to schedule the DPC as needed. */
654 dwIntCount++;
655 if (!(dwIntCount % 5))
656 return TRUE;
657
658 return FALSE;
659}
660
688DWORD __cdecl KP_PCI_IntAtDpcMSI(PVOID pIntContext, DWORD dwCount,
689 ULONG dwLastMessage, DWORD dwReserved)
690{
691 return dwCount;
692}
693
694#ifndef ISA
695
712BOOL __cdecl KP_PCI_Event(PVOID pDrvContext, WD_EVENT *wd_event)
713{
714 return TRUE; /* Return TRUE to notify the user mode of the event */
715}
716#endif /* ifndef ISA */
717
718/* -----------------------------------------------
719 Debugging and error handling
720 ----------------------------------------------- */
721static void KP_PCI_Err(const CHAR *sFormat, ...)
722{
723#if defined(DEBUG)
724 CHAR sMsg[256];
725 va_list argp;
726
727 va_start(argp, sFormat);
728 vsnprintf(sMsg, sizeof(sMsg) - 1, sFormat, argp);
729 WDC_Err("%s: %s", KP_PCI_DRIVER_NAME, sMsg);
730 va_end(argp);
731#endif
732}
733
734static void KP_PCI_Trace(const CHAR *sFormat, ...)
735{
736#if defined(DEBUG)
737 CHAR sMsg[256];
738 va_list argp;
739
740 va_start(argp, sFormat);
741 vsnprintf(sMsg, sizeof(sMsg) - 1, sFormat, argp);
742 WDC_Trace("%s: %s", KP_PCI_DRIVER_NAME, sMsg);
743 va_end(argp);
744#endif
745}
746
BOOL __cdecl KP_PCI_Open(KP_OPEN_CALL *kpOpenCall, HANDLE hWD, PVOID pOpenData, PVOID *ppDrvContext)
Kernel PlugIn open function.
Definition: kp_pci.c:154
BOOL __cdecl KP_PCI_IntAtIrqlMSI(PVOID pIntContext, ULONG dwLastMessage, DWORD dwReserved)
High-priority Message-Signaled Interrupts (MSI) / Extended Message-Signaled Interrupts (MSI-X) handle...
Definition: kp_pci.c:643
DWORD __cdecl KP_PCI_IntAtDpcMSI(PVOID pIntContext, DWORD dwCount, ULONG dwLastMessage, DWORD dwReserved)
Deferred processing Message-Signaled Interrupts (MSI) / Extended Message-Signaled Interrupts (MSI-X) ...
Definition: kp_pci.c:688
DWORD __cdecl KP_PCI_IntAtDpc(PVOID pIntContext, DWORD dwCount)
Deferred processing legacy interrupt handler routine.
Definition: kp_pci.c:602
BOOL __cdecl KP_PCI_IntEnable(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall, PVOID *ppIntContext)
Called when WDC_IntEnable() / WD_IntEnable() is called from the user mode with a Kernel PlugIn handle...
Definition: kp_pci.c:428
BOOL __cdecl KP_PCI_IntAtIrql(PVOID pIntContext, BOOL *pfIsMyInterrupt)
High-priority legacy interrupt handler routine, which is run at high interrupt request level.
Definition: kp_pci.c:495
#define DRIVER_VER_STR
#define PTR32
Definition: kp_pci.c:46
void __cdecl KP_PCI_Close(PVOID pDrvContext)
Called when WD_KernelPlugInClose() (see the WinDriver PCI Low-Level API Reference) is called from use...
Definition: kp_pci.c:326
void __cdecl KP_PCI_Call(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall)
Called when the user-mode application calls WDC_CallKerPlug() (or the low-level WD_KernelPlugInCall()...
Definition: kp_pci.c:377
void __cdecl KP_PCI_IntDisable(PVOID pIntContext)
Called when WDC_IntDisable() / WD_IntDisable() is called from the user mode for interrupts that were ...
Definition: kp_pci.c:456
BOOL __cdecl KP_Init(KP_INIT *kpInit)
KP_Init is called when the Kernel PlugIn driver is loaded.
Definition: kp_pci.c:65
BOOL __cdecl KP_PCI_Event(PVOID pDrvContext, WD_EVENT *wd_event)
Called when a Plug-and-Play or power management event for the device is received, provided the user-m...
Definition: kp_pci.c:712
BOOL __cdecl KP_PCI_Open_32_64(KP_OPEN_CALL *kpOpenCall, HANDLE hWD, PVOID pOpenData, PVOID *ppDrvContext)
KP_PCI_Open_32_64 is called when WD_KernelPlugInOpen() is called from a 32-bit user mode application ...
Definition: kp_pci.c:234
#define NULL
Definition: kpstdlib.h:268
void *__cdecl malloc(unsigned long size)
#define TRUE
Definition: kpstdlib.h:264
#define FALSE
Definition: kpstdlib.h:260
void __cdecl free(void *buf)
char *__cdecl strcpy(char *s1, const char *s2)
CHAR cDriverName[WD_MAX_KP_NAME_LENGTH]
return the device driver name
Definition: wd_kp.h:69
DWORD dwVerWD
version of the WinDriver Kernel PlugIn library
Definition: wd_kp.h:68
KP_FUNC_OPEN funcOpen
returns the KP_Open function
Definition: wd_kp.h:71
KP_FUNC_OPEN funcOpen_32_64
returns the KP_Open function for 32 bit app with 64 bit KP.
Definition: wd_kp.h:72
Definition: wd_kp.h:67
KP_FUNC_EVENT funcEvent
Definition: wd_kp.h:58
KP_FUNC_CLOSE funcClose
Definition: wd_kp.h:50
KP_FUNC_INT_AT_IRQL funcIntAtIrql
Definition: wd_kp.h:54
KP_FUNC_INT_AT_DPC_MSI funcIntAtDpcMSI
Definition: wd_kp.h:57
KP_FUNC_INT_ENABLE funcIntEnable
Definition: wd_kp.h:52
KP_FUNC_INT_AT_IRQL_MSI funcIntAtIrqlMSI
Definition: wd_kp.h:56
KP_FUNC_INT_AT_DPC funcIntAtDpc
Definition: wd_kp.h:55
KP_FUNC_CALL funcCall
Definition: wd_kp.h:51
KP_FUNC_INT_DISABLE funcIntDisable
Definition: wd_kp.h:53
KPTR pAddr
I/O / Memory kernel mapped address – for WD_Transfer(), WD_MultiTransfer(), or direct kernel access.
Definition: wdc_defs.h:34
Address space information struct.
Definition: wdc_defs.h:27
DWORD cmdTrans
Transfer command WD_TRANSFER_CMD.
Definition: windrvr.h:590
UINT32 Dword
Use for 32 bit transfer.
Definition: windrvr.h:601
union WD_TRANSFER::@14 Data
KPTR pPort
I/O port for transfer or kernel memory address.
Definition: windrvr.h:589
#define vsnprintf
Definition: utils.h:25
#define WD_VER
Definition: wd_ver.h:25
#define WDC_ADDR_IS_MEM(pAddrDesc)
Check if memory or I/O address.
Definition: wdc_defs.h:87
void DLLCALLCONV WDC_Trace(const CHAR *format,...)
Displays debug trace messages according to the WDC debug options.
DWORD DLLCALLCONV WDC_MultiTransfer(_In_ WD_TRANSFER *pTransCmds, _In_ DWORD dwNumTrans)
Performs a group of memory and/or I/O read/write transfers.
void DLLCALLCONV WDC_Err(const CHAR *format,...)
Displays debug error messages according to the WDC debug options.
#define WDC_ReadMem32(addr, off)
reads 4 byte (32 bits) from a specified memory address.
Definition: wdc_lib.h:739
#define WDC_WriteMem32(addr, off, val)
writes 4 byte (32 bits) to a specified memory address.
Definition: wdc_lib.h:764
@ WD_STATUS_SUCCESS
[0] Operation completed successfully
Definition: windrvr.h:1066
@ RM_DWORD
Read memory dword.
Definition: windrvr.h:414
@ WP_DWORD
Write port dword.
Definition: windrvr.h:399
@ WM_DWORD
Write memory dword.
Definition: windrvr.h:417
@ RP_DWORD
Read port dword.
Definition: windrvr.h:396
#define BZERO(buf)
Definition: windrvr.h:1553
unsigned int UINT32
Definition: windrvr.h:337
UINT32 KPTR
Definition: windrvr.h:372