WinDriver™ PCI/ISA User's Manual

Jungo Connectivity Ltd.

Version 12.9.0

Information in this document is subject to change without notice. The software described in this document is furnished under a license agreement. The software may be used, copied or distributed only in accordance with that agreement. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or any means, electronically or mechanically, including photocopying and recording for any purpose without the written permission of Jungo Connectivity Ltd.

Brand and product names mentioned in this document are trademarks of their respective owners and are used here only for identification purposes.


Table of Contents

1. WinDriver Overview
1.1. Introduction to WinDriver
1.2. Background
1.2.1. The Challenge
1.2.2. The WinDriver Solution
1.3. How Fast Can WinDriver Go?
1.4. Conclusion
1.5. WinDriver Benefits
1.6. WinDriver Architecture
1.7. What Platforms Does WinDriver Support?
1.8. Limitations of the Different Evaluation Versions
1.9. How Do I Develop My Driver with WinDriver?
1.9.1. On Windows and Linux
1.10. What Does the WinDriver Toolkit Include?
1.10.1. WinDriver Modules
1.10.2. Utilities
1.10.3. Samples and Enhanced-Support Chipset APIs
1.10.3.1. Enhanced Chipset Support
1.11. Can I Distribute the Driver Created with WinDriver?
2. Understanding Device Drivers
2.1. Device Driver Overview
2.2. Classification of Drivers According to Functionality
2.2.1. Monolithic Drivers
2.2.2. Layered Drivers
2.2.3. Miniport Drivers
2.3. Classification of Drivers According to Operating Systems
2.3.1. WDM Drivers
2.3.2. Unix Device Drivers
2.3.3. Linux Device Drivers
2.4. The Entry Point of the Driver
2.5. Associating the Hardware with the Driver
2.6. Communicating with Drivers
3. Installing WinDriver
3.1. System Requirements
3.1.1. Windows System Requirements
3.1.2. Windows 10 IoT Core System Requirements
3.1.3. Linux System Requirements
3.2. WinDriver Installation Process
3.2.1. Windows WinDriver Installation Instructions
3.2.2. Linux WinDriver Installation Instructions
3.2.2.1. Preparing the System for Installation
3.2.2.2. Installation
3.2.2.3. Restricting Hardware Access on Linux
3.3. Upgrading Your Installation
3.4. Checking Your Installation
3.4.1. Windows and Linux Installation Check
3.5. Uninstalling WinDriver
3.5.1. Windows WinDriver Uninstall Instructions
3.5.2. Linux WinDriver Uninstall Instructions
4. Using DriverWizard
4.1. An Overview
4.2. DriverWizard Walkthrough
4.2.1. Automatic Code Generation
4.2.1.1. Generating the Code
4.2.1.2. The Generated PCI/ISA C Code
4.2.1.3. The Generated PCI/ISA Python Code
4.2.1.4. The Generated PCI/ISA C#.NET Code
4.2.2. Compiling the Generated Code
4.2.2.1. Windows Compilation
4.2.2.1.1. Running compiled code under Windows 10 IoT Core
4.2.2.2. Linux Compilation
5. Developing a Driver
5.1. Using DriverWizard to Build a Device Driver
5.2. Writing the Device Driver Without DriverWizard
5.2.1. Include the Required WinDriver Files
5.2.2. Write Your Code
5.2.3. Configure and Build Your Code
6. Debugging Drivers
6.1. User-Mode Debugging
6.2. Debug Monitor
6.2.1. The wddebug_gui Utility
6.2.1.1. Search in wddebug_gui
6.2.1.2. Opening Windows kernel crash dump with wddebug_gui
6.2.1.3. Running wddebug_gui for a Renamed Driver
6.2.2. The wddebug Utility
6.2.2.1. Console-Mode wddebug Execution
6.2.2.2. Debugging in Windows 10 IoT Core
7. Enhanced Support for Specific Chipsets
7.1. Overview
7.2. Developing a Driver Using the Enhanced Chipset Support
8. PCI Express
8.1. PCI Express Overview
8.2. WinDriver for PCI Express
9. Advanced Issues
9.1. Performing Direct Memory Access (DMA)
9.1.1. Implementing Scatter/Gather DMA
9.1.2. Implementing Contiguous-Buffer DMA
9.1.2.1. Preallocating Contiguous DMA Buffers on Windows
9.2. Handling Interrupts
9.2.1. Interrupt Handling — Overview
9.2.2. WinDriver Interrupt Handling Sequence
9.2.3. Registering IRQs for Non-Plug-and-Play Hardware on Windows 7 and Higher
9.2.4. Determining the Interrupt Types Supported by the Hardware
9.2.5. Determining the Interrupt Type Enabled for a PCI Card
9.2.6. Setting Up Kernel-Mode Interrupt Transfer Commands
9.2.6.1. Interrupt Mask Commands
9.2.6.2. Sample WinDriver Transfer Commands Code
9.2.7. WinDriver MSI/MSI-X Interrupt Handling
9.2.7.1. Windows MSI/MSI-X Device INF Files
9.2.8. Sample User-Mode WinDriver Interrupt Handling Code
9.2.9. Shared Interrupts via IPC
9.2.9.1. Enabling Shared Interrupts:
9.2.9.2. Disabling Shared Interrupts:
9.3. Buffer sharing between multiple processes
9.4. Single Root I/O Virtualization (SR-IOV)
10. Improving Performance
10.1. Overview
10.1.1. Performance Improvement Checklist
10.2. Improving the Performance of a User-Mode Driver
10.2.1. Using Direct Access to Memory-Mapped Regions
10.2.2. Block Transfers and Grouping Multiple Transfers
10.2.3. Performing 64-Bit Data Transfers
11. Understanding the Kernel PlugIn
11.1. Background
11.2. Do I Need to Write a Kernel PlugIn Driver?
11.3. What Kind of Performance Can I Expect?
11.4. Overview of the Development Process
11.5. The Kernel PlugIn Architecture
11.5.1. Architecture Overview
11.5.2. WinDriver's Kernel and Kernel PlugIn Interaction
11.5.3. Kernel PlugIn Components
11.5.4. Kernel PlugIn Event Sequence
11.5.4.1. Opening a Handle from the User Mode to a Kernel PlugIn Driver
11.5.4.2. Handling User-Mode Requests from the Kernel PlugIn
11.5.4.3. Interrupt Handling — Enable/Disable and High Interrupt Request Level Processing
11.5.4.4. Interrupt Handling — Deferred Procedure Calls
11.5.4.5. Plug-and-Play and Power Management Events
11.6. How Does Kernel PlugIn Work?
11.6.1. Minimal Requirements for Creating a Kernel PlugIn Driver
11.6.2. Kernel PlugIn Implementation
11.6.2.1. Before You Begin
11.6.2.2. Write Your KP_Init Function
11.6.2.3. Write Your KP_Open Function(s)
11.6.2.4. Write the Remaining PlugIn Callbacks
11.6.3. Sample/Generated Kernel PlugIn Driver Code Overview
11.6.4. Kernel PlugIn Sample/Generated Code Directory Structure
11.6.4.1. pci_diag and kp_pci Sample Directories
11.6.4.2. The Generated DriverWizard Kernel PlugIn Directory
11.6.5. Handling Interrupts in the Kernel PlugIn
11.6.5.1. Interrupt Handling in the User Mode (Without the Kernel PlugIn)
11.6.5.2. Interrupt Handling in the Kernel (Using the Kernel PlugIn)
11.6.6. Message Passing
12. Creating a Kernel PlugIn Driver
12.1. Determine Whether a Kernel PlugIn is Needed
12.2. What programming languages can be used with a Kernel PlugIn?
12.3. Prepare the User-Mode Source Code
12.4. Create a New Kernel PlugIn Project
12.5. Open a Handle to the Kernel PlugIn
12.6. Set Interrupt Handling in the Kernel PlugIn
12.7. Set I/O Handling in the Kernel PlugIn
12.8. Compile Your Kernel PlugIn Driver
12.8.1. Windows Kernel PlugIn Driver Compilation
12.8.2. Linux Kernel PlugIn Driver Compilation
12.9. Install Your Kernel PlugIn Driver
12.9.1. Windows Kernel PlugIn Driver Installation
12.9.2. Linux Kernel PlugIn Driver Installation
13. Dynamically Loading Your Driver
13.1. Why Do You Need a Dynamically Loadable Driver?
13.2. Windows Dynamic Driver Loading
13.2.1. The wdreg Utility
13.2.1.1. WDM Drivers
13.2.1.2. Non-WDM Drivers
13.2.2. Dynamically Loading/Unloading windrvr1290.sys INF Files
13.2.3. Dynamically Loading/Unloading Your Kernel PlugIn Driver
13.3. The wdreg_frontend utility
13.4. Windows 10 IoT Core Dynamic Driver Loading
13.5. Linux Dynamic Driver Loading
13.5.1. Dynamically Loading/Unloading Your Kernel PlugIn Driver
14. Distributing Your Driver
14.1. Getting a Valid WinDriver License
14.2. Windows Driver Distribution
14.2.1. Preparing the Distribution Package
14.2.2. Installing Your Driver on the Target Computer
14.2.3. Installing Your Kernel PlugIn on the Target Computer
14.3. Linux Driver Distribution
14.3.1. Preparing the Distribution Package
14.3.1.1. Kernel Module Components
14.3.1.2. User-Mode Hardware-Control Application or Shared Object
14.3.2. Building and Installing the WinDriver Driver Module on the Target
14.3.3. Building and Installing Your Kernel PlugIn Driver on the Target
14.3.4. Installing the User-Mode Hardware-Control Application or Shared Object
15. Driver Installation — Advanced Issues
15.1. Windows INF Files
15.1.1. Why Should I Create an INF File?
15.1.2. How Do I Install an INF File When No Driver Exists?
15.1.3. How Do I Replace an Existing Driver Using the INF File?
15.2. Renaming the WinDriver Kernel Driver
15.2.1. Windows Driver Renaming
15.2.2. Linux Driver Renaming
15.3. Windows Digital Driver Signing and Certification
15.3.1. Overview
15.3.1.1. Authenticode Driver Signature
15.3.1.2. Windows Certification Program
15.3.2. Driver Signing and Certification of WinDriver-Based Drivers
15.3.2.1. HCK Test Notes
A. 64-Bit Operating Systems Support
A.1. Supported 64-Bit Architectures
A.2. Support for 32-Bit Applications on 64-Bit Windows and Linux Platforms
A.3. 64-Bit and 32-Bit Data Types
B. API Reference
B.1. WD_DriverName
B.2. WDC Library Overview
B.3. WDC High-Level API
B.3.1. Structures, Types and General Definitions
B.3.1.1. WDC_DEVICE_HANDLE
B.3.1.2. WDC_DRV_OPEN_OPTIONS Definitions
B.3.1.3. WDC_DIRECTION Enumeration
B.3.1.4. WDC_ADDR_MODE Enumeration
B.3.1.5. WDC_ADDR_RW_OPTIONS Enumeration
B.3.1.6. WDC_ADDR_SIZE Definitions
B.3.1.7. WDC_SLEEP_OPTIONS Definitions
B.3.1.8. WDC_DBG_OPTIONS Definitions
B.3.1.9. WDC_PCI_SCAN_RESULT Structure
B.3.1.10. WDC_PCI_SCAN_CAPS_RESULT Structure
B.3.2. WDC_DriverOpen()
B.3.3. WDC_DriverClose()
B.3.4. WDC_PciScanDevices()
B.3.5. WDC_PciScanDevicesByTopology()
B.3.6. WDC_PciScanRegisteredDevices()
B.3.7. WDC_PciScanCaps()
B.3.8. WDC_PciScanCapsBySlot()
B.3.9. WDC_PciScanExtCaps()
B.3.10. WDC_PciGetExpressGen()
B.3.11. WDC_PciGetExpressGenBySlot()
B.3.12. WDC_PciGetExpressOffset()
B.3.13. WDC_PciGetHeaderType()
B.3.14. PciConfRegData2Str()
B.3.15. PciExpressConfRegData2Str()
B.3.16. WDC_PciGetDeviceInfo()
B.3.17. WDC_PciDeviceOpen()
B.3.18. WDC_IsaDeviceOpen()
B.3.19. WDC_PciDeviceClose()
B.3.20. WDC_IsaDeviceClose()
B.3.21. WDC_CardCleanupSetup()
B.3.22. WDC_KernelPlugInOpen()
B.3.23. WDC_CallKerPlug()
B.3.24. WDC_ReadMemXXX()
B.3.25. WDC_WriteMemXXX()
B.3.26. WDC_ReadAddrXXX()
B.3.27. WDC_WriteAddrXXX()
B.3.28. WDC_ReadAddrBlock()
B.3.29. WDC_WriteAddrBlock()
B.3.30. WDC_MultiTransfer()
B.3.31. WDC_AddrSpaceIsActive()
B.3.32. WDC_PciReadCfgBySlot()
B.3.33. WDC_PciWriteCfgBySlot()
B.3.34. WDC_PciReadCfg()
B.3.35. WDC_PciWriteCfg()
B.3.36. WDC_PciReadCfgBySlotXXX()
B.3.37. WDC_PciWriteCfgBySlotXXX()
B.3.38. WDC_PciReadCfgXXX()
B.3.39. WDC_PciWriteCfgXXX()
B.3.40. WDC_DMAContigBufLock()
B.3.41. WDC_DMASGBufLock()
B.3.42. WDC_DMAReservedBufLock()
B.3.43. WDC_DMABufUnlock()
B.3.44. WDC_DMABufGet()
B.3.45. WDC_DMAGetGlobalHandle Macro
B.3.46. WDC_DMASyncCpu()
B.3.47. WDC_DMASyncIo()
B.3.48. WDC_IntEnable()
B.3.49. WDC_IntDisable()
B.3.50. WDC_IntIsEnabled()
B.3.51. WDC_IntType2Str()
B.3.52. WDC_EventRegister()
B.3.53. WDC_EventUnregister()
B.3.54. WDC_EventIsRegistered()
B.3.55. WDC_PciSriovEnable()
B.3.56. WDC_PciSriovDisable
B.3.57. WDC_PciSriovGetNumVFs()
B.3.58. WDC_SetDebugOptions()
B.3.59. WDC_Err()
B.3.60. WDC_Trace()
B.3.61. WDC_GetWDHandle()
B.3.62. WDC_GetDevContext()
B.3.63. WDC_GetBusType()
B.3.64. WDC_Sleep()
B.3.65. WDC_Version()
B.4. WDC Low-Level API
B.4.1. WDC_ADDR_DESC Structure
B.4.2. WDC_DEVICE Structure
B.4.3. PWDC_DEVICE
B.4.4. WDC_MEM_DIRECT_ADDR Macro
B.4.5. WDC_ADDR_IS_MEM Macro
B.4.6. WDC_GET_ADDR_DESC Macro
B.4.7. WDC_GET_ADDR_SPACE_SIZE Macro
B.4.8. WDC_GET_ENABLED_INT_TYPE Macro
B.4.9. WDC_GET_INT_OPTIONS Macro
B.4.10. WDC_INT_IS_MSI Macro
B.4.11. WDC_GET_ENABLED_INT_LAST_MSG Macro
B.4.12. WDC_IS_KP Macro
B.5. WDS Library Overview
B.6. WDS High-Level API
B.6.1. WDS_SharedBufferAlloc()
B.6.2. WDS_SharedBufferFree()
B.6.3. WDS_SharedBufferGet()
B.6.4. WDS_SharedBufferGetGlobalHandle Macro
B.7. WD_xxx Structures, Types and General Definitions
B.7.1. WD_BUS_TYPE Enumeration
B.7.2. ITEM_TYPE Enumeration
B.7.3. WD_PCI_ID Structure
B.7.4. WD_PCI_SLOT Structure
B.7.5. WD_PCI_CAP Structure
B.7.6. WD_ITEMS Structure
B.7.7. WD_CARD Structure
B.7.8. WD_PCI_CARD_INFO Structure
B.7.9. WD_DMA Structure
B.7.10. WD_TRANSFER Structure
B.7.11. WD_KERNEL_BUFFER Structure
B.8. Kernel PlugIn Kernel-Mode Functions
B.8.1. KP_Init
B.8.2. KP_Open
B.8.3. KP_Close
B.8.4. KP_Call
B.8.5. KP_Event
B.8.6. KP_IntEnable
B.8.7. KP_IntDisable
B.8.8. KP_IntAtIrql
B.8.9. KP_IntAtDpc
B.8.10. KP_IntAtIrqlMSI
B.8.11. KP_IntAtDpcMSI
B.8.12. COPY_TO_USER_OR_KERNEL, COPY_FROM_USER_OR_KERNEL
B.8.13. Kernel PlugIn Synchronization APIs
B.8.13.1. Kernel PlugIn Synchronization Types
B.8.13.2. kp_spinlock_init()
B.8.13.3. kp_spinlock_wait()
B.8.13.4. kp_spinlock_release()
B.8.13.5. kp_spinlock_uninit()
B.8.13.6. kp_interlocked_init()
B.8.13.7. kp_interlocked_uninit()
B.8.13.8. kp_interlocked_increment()
B.8.13.9. kp_interlocked_decrement()
B.8.13.10. kp_interlocked_add()
B.8.13.11. kp_interlocked_read()
B.8.13.12. kp_interlocked_set()
B.8.13.13. kp_interlocked_exchange()
B.9. Kernel PlugIn Structure Reference
B.9.1. WD_KERNEL_PLUGIN
B.9.2. WD_INTERRUPT
B.9.3. WD_KERNEL_PLUGIN_CALL
B.9.4. KP_INIT
B.9.5. KP_OPEN_CALL
B.10. User-Mode Utility Functions
B.10.1. Stat2Str
B.10.2. get_os_type
B.10.3. check_secureBoot_enabled
B.10.4. ThreadStart
B.10.5. ThreadWait
B.10.6. OsEventCreate
B.10.7. OsEventClose
B.10.8. OsEventWait
B.10.9. OsEventSignal
B.10.10. OsEventReset
B.10.11. OsMutexCreate
B.10.12. OsMutexClose
B.10.13. OsMutexLock
B.10.14. OsMutexUnlock
B.10.15. PrintDbgMessage
B.10.16. WD_LogStart
B.10.17. WD_LogStop
B.10.18. WD_LogAdd
B.11. WinDriver Status Codes
B.11.1. Introduction
B.11.2. Status Codes Returned by WinDriver
C. WinDriver IPC
C.1. WinDriver IPC Overview
C.2. WinDriver IPC API Reference
C.2.1. IPC_MSG_RX_HANDLER()
C.2.2. WDS_IpcRegister()
C.2.3. WDS_IpcUnRegister()
C.2.4. WDS_IsIpcRegistered()
C.2.5. WDS_IpcScanProcs()
C.2.6. WDS_IpcMulticast()
C.2.7. WDS_IpcSubGroupMulticast()
C.2.8. WDS_IpcUidUnicast()
C.2.9. WDS_SharedIntEnable()
C.2.10. WDS_SharedIntDisableLocal()
C.2.11. WDS_SharedIntDisableGlobal()
D. Troubleshooting and Support
E. Evaluation Version Limitations
E.1. Windows WinDriver Evaluation Limitations
E.2. Linux WinDriver Evaluation Limitations
F. Purchasing WinDriver
G. Distributing Your Driver — Legal Issues
H. Additional Documentation

List of Figures

1.1. WinDriver Architecture
2.1. Monolithic Drivers
2.2. Layered Drivers
2.3. Miniport Drivers
4.1. Create or Open a Driver Project
4.2. Select Your Plug-and-Play Device
4.3. DriverWizard INF File Information
4.4. PCI Resources
4.5. Define Registers
4.6. Read/Write Memory and I/O
4.7. Listen to Interrupts
4.8. Define Transfer Commands for Level-Sensitive Interrupts
4.9. Code Generation Options
4.10. Additional Driver Options
6.1. Start Debug Monitor
6.2. Debug Options
6.3. Search in wddebug_gui
9.1. DriverWizard INF File Information
11.1. Kernel PlugIn Architecture
11.2. Interrupt Handling Without Kernel PlugIn
11.3. Interrupt Handling With the Kernel PlugIn
13.1. The wdreg_frontend icon
13.2. The dialog box wdreg_frontend will open if driver file is not located in the Windows system directory
13.3. wdreg_frontend after successfully loading a sys file
13.4. Error message given by Windows when trying to install an unsigned driver
13.5. wdreg_frontend upon successfully installing a sys driver