WinDriver™ PCI/ISA/CardBus User’s Manual Version 9.20 http://www.jungo.
COPYRIGHT © Jungo Ltd. 2005 – 2008 All Rights Reserved. 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.
Contents Table of Contents 2 List of Figures 1 2 13 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 . . . . . . . .
CONTENTS 2.3 2.4 2.5 2.6 3 4 Classification of Drivers According to Operating Systems 2.3.1 WDM Drivers . . . . . . . . . . . . . . . . . . 2.3.2 VxD Drivers . . . . . . . . . . . . . . . . . . . 2.3.3 Unix Device Drivers . . . . . . . . . . . . . . . 2.3.4 Linux Device Drivers . . . . . . . . . . . . . . 2.3.5 Solaris Device Drivers . . . . . . . . . . . . . . The Entry Point of the Driver . . . . . . . . . . . . . . . Associating the Hardware to the Driver . . . . . . . . . Communicating with Drivers .
CONTENTS 4.1 4.2 4.3 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 56 64 64 65 65 65 66 66 66 67 67 67 67 68 . . . . . . . . . . . . . . . . . . . . 69 69 70 70 71 72 73 73 73 73 73 . . . . 74 74 75 . . 75 . . . . 77 78 7 Enhanced Support for Specific Chipsets 7.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Developing a Driver Using the Enhanced Chipset Support . . . . . 81 81 82 8 PCI Express 8.1 PCI Express Overview . . . . . . . . . . . .
CONTENTS 8.2 9 5 WinDriver for PCI Express . . . . . . . . . . . . . . . . . . . . . . 85 Advanced Issues 9.1 Performing Direct Memory Access (DMA) . . . . . . . . . . . . . 9.1.1 Scatter/Gather DMA . . . . . . . . . . . . . . . . . . . . . 9.1.1.1 Sample Scatter/Gather DMA Implementation . . 9.1.1.2 What Should You Implement? . . . . . . . . . . 9.1.2 Contiguous Buffer DMA . . . . . . . . . . . . . . . . . . . 9.1.2.1 Sample Contiguous Buffer DMA Implementation . . . . . . . . . . . . . . . . . . 9.1.
CONTENTS 11.4 11.5 11.6 6 Overview of the Development Process . . . . . . . . . . . . . . . . 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 Handle from the User Mode to a Kernel PlugIn Driver . . . .
CONTENTS . . . . . 148 149 149 149 150 13 Dynamically Loading Your Driver 13.1 Why Do You Need a Dynamically Loadable Driver? . . . . . . . . 13.2 Windows Dynamic Driver Loading . . . . . . . . . . . . . . . . . . 13.2.1 Windows Driver Types . . . . . . . . . . . . . . . . . . . . 13.2.2 The WDREG Utility . . . . . . . . . . . . . . . . . . . . . 13.2.2.1 WDM Drivers . . . . . . . . . . . . . . . . . . 13.2.2.2 Non-WDM Drivers . . . . . . . . . . . . . . . . 13.2.3 Dynamically Loading/Unloading windrvr6.
CONTENTS 15.3 15.4 8 15.2.1.1 Rename the Windows Driver Using DriverWizard . . . . . . . . . . . . . . . . . . . 15.2.1.2 Manually Rename the Windows Driver . . . . . 15.2.2 Linux Driver Rename . . . . . . . . . . . . . . . . . . . . 15.2.2.1 Rename the Linux Driver Using DriverWizard . 15.2.2.2 Manually Rename the Linux Driver . . . . . . . 15.2.3 Solaris Driver Rename . . . . . . . . . . . . . . . . . . . . 15.2.3.1 Rename the Solaris Driver Using DriverWizard . 15.2.3.
CONTENTS B.3.6 B.3.7 B.3.8 B.3.9 B.3.10 B.3.11 B.3.12 B.3.13 B.3.14 B.3.15 B.3.16 B.3.17 B.3.18 B.3.19 B.3.20 B.3.21 B.3.22 B.3.23 B.3.24 B.3.25 B.3.26 B.3.27 B.3.28 B.3.29 B.3.30 B.3.31 B.3.32 B.3.33 B.3.34 B.3.35 B.3.36 B.3.37 B.3.38 B.3.39 B.3.40 B.3.41 B.3.42 B.3.43 B.3.44 B.3.45 B.3.46 B.3.47 9 WDC_PcmciaScanDevices() . . . WDC_PciGetDeviceInfo() . . . . WDC_PcmciaGetDeviceInfo() . . WDC_PciDeviceOpen() . . . . . WDC_PcmciaDeviceOpen() . . . WDC_IsaDeviceOpen() . . . . . WDC_PciDeviceClose() . . . . .
CONTENTS B.4 B.5 B.6 B.3.48 WDC_EventIsRegistered() . . . . . . . . . . B.3.49 WDC_SetDebugOptions() . . . . . . . . . . B.3.50 WDC_Err() . . . . . . . . . . . . . . . . . . B.3.51 WDC_Trace() . . . . . . . . . . . . . . . . . B.3.52 WDC_GetWDHandle() . . . . . . . . . . . . B.3.53 WDC_GetDevContext() . . . . . . . . . . . B.3.54 WDC_GetBusType() . . . . . . . . . . . . . B.3.55 WDC_Sleep() . . . . . . . . . . . . . . . . . B.3.56 WDC_Version() . . . . . . . . . . . . . . . WDC Low Level API . . . . . .
CONTENTS B.6.7 B.6.8 B.6.9 B.6.10 B.7 B.8 KP_IntDisable() . . . . . . . . . . . . . . . . . KP_IntAtIrql() . . . . . . . . . . . . . . . . . . KP_IntAtDpc() . . . . . . . . . . . . . . . . . . COPY_TO_USER_OR_KERNEL, COPY_FROM_USER_OR_KERNEL . . . . . B.6.11 Kernel PlugIn Synchronization APIs . . . . . . B.6.11.1 Kernel PlugIn Synchronization Types B.6.11.2 kp_spinlock_init() . . . . . . . . . . . B.6.11.3 kp_spinlock_wait() . . . . . . . . . . B.6.11.4 kp_spinlock_release() . . . . . . . . . B.6.11.
CONTENTS B.9 B.8.17 WD_LogAdd() . . . . . . . . . . . . WinDriver Status Codes . . . . . . . . . . . B.9.1 Introduction . . . . . . . . . . . . . B.9.2 Status Codes Returned by WinDriver 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C Troubleshooting and Support D Evaluation Version Limitations D.1 Windows WinDriver Evaluation Limitations . . D.2 Windows CE WinDriver Evaluation Limitations D.3 Linux WinDriver Evaluation Limitations . . . .
List of Figures 1.1 WinDriver Architecture . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.1 2.2 2.3 Monolithic Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . Layered Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Miniport Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 28 29 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 Create or Open a WinDriver Project . . . . . . . . . . . Select Your Plug and Play Device . . . . . . . . . . . .
Chapter 1 WinDriver Overview In this chapter you will explore the uses of WinDriver, and learn the basic steps of creating your driver. NOTE This manual outlines WinDriver’s support for PCI / PCMCIA / CardBus / ISA / EISA / CompactPCI / PCI Express devices. WinDriver also supports the Universal Serial Bus (USB). For detailed information regarding WinDriver USB, please refer to the WinDriver Product Line page on our web-site (http://www.jungo.com/st/ windriver.
1.2 Background 15 with the features that WinDriver offers to the advanced user. However, most developers will find that reading this chapter and glancing through the DriverWizard and function reference chapters is all they need to successfully write their driver. WinDriver supports development for all PCI / PCMCIA / CardBus / ISA / EISA / CompactPCI / PCI Express chipsets. Enhanced support is offered for PLX, Altera, AMCC and Xilinx PCI chipsets, as outlined in Chapter 7 of the manual.
1.2 Background 16 1.2.2 The WinDriver Solution Easy Development: WinDriver enables Windows, Windows CE, Linux and Solaris programmers to create PCI/PCMCIA/CardBus/ISA/EISA/CompactPCI/PCI Express based device drivers in an extremely short time. WinDriver allows you to create your driver in the familiar user-mode environment, using MSDEV/Visual C/C++, MSDEV .NET, Borland C++ Builder, Borland Delphi, Visual Basic 6.0, MS eMbedded Visual C++, MS Platform Builder C++, GCC, or any other appropriate compiler.
1.3 How Fast Can WinDriver Go? 17 1.3 How Fast Can WinDriver Go? You can expect the same throughput using the WinDriver Kernel PlugIn as when using a custom kernel driver. Throughput is constrained only by the limitations of your operating system and hardware. A rough estimate of the throughput you can obtain using the Kernel PlugIn is approximately 100,000 interrupts per second. 1.
1.5 WinDriver Benefits 18 1.5 WinDriver Benefits • Easy user-mode driver development. • Kernel PlugIn for high-performance drivers. • Friendly DriverWizard allows hardware diagnostics without writing a single line of code. • Automatically generates the driver code for the project in C, C#, Delphi (Pascal) or Visual Basic. • Supports any PCI/PCMCIA/CardBus/ISA/EISA/CompactPCI/PCI Express device, regardless of manufacturer.
1.6 WinDriver Architecture 1.6 WinDriver Architecture Figure 1.
1.7 What Platforms Does WinDriver Support? 20 For hardware access, your application calls one of the WinDriver user-mode functions. The user-mode function calls the WinDriver kernel, which accesses the hardware for you through the native calls of the operating system. WinDriver’s design minimizes performance hits on your code, even though it is running in user mode. However, some hardware drivers have high performance requirements that cannot be achieved in user mode.
1.8 Limitations of the Different Evaluation Versions 21 1.8 Limitations of the Different Evaluation Versions All the evaluation versions of WinDriver are full featured. No functions are limited or crippled in any way. The evaluation version of WinDriver varies from the registered version in the following ways: • Each time WinDriver is activated, an Un-registered message appears.
1.10 What Does the WinDriver Toolkit Include? 22 1.9.2 On Windows CE 1. Plug your hardware into a Windows host machine. 2. Diagnose your hardware using DriverWizard. 3. Let DriverWizard generate your driver’s skeletal code. 4. Modify this code using eMbedded Visual C++ to meet your specific needs. If you are using Platform Builder, activate it and insert the generated *.pbp into your workspace. 5. Test and debug your code and hardware from the CE emulation running on the host machine.
1.10 What Does the WinDriver Toolkit Include? 23 1.10.1 WinDriver Modules • WinDriver (WinDriver/include) – the general purpose hardware access toolkit. The main files here are: – windrvr.h: Declarations and definitions of WinDriver’s basic API. – wdc_lib.h and wdc_defs.h: Declarations and definitions of the WinDriver Card (WDC) library, which provides convenient wrapper APIs for accessing PCI/PCMCIA/CardBus/ISA/EISA/CompactPCI/PCI Express devices (see Chapter B.2). – windrvr_int_thread.
1.10 What Does the WinDriver Toolkit Include? 24 1.10.2 Utilities • pci_dump.exe (WinDriver/util/pci_dump.exe) – used to obtain a dump of the PCI configuration registers of the installed PCI cards. • pci_diag.exe (WinDriver/util/pci_diag.exe) – used for reading/writing PCI configuration registers, accessing PCI I/O and memory ranges and handling PCI interrupts. • pci_scan.exe (WinDriver/util/pci_scan.exe) – used to obtain a list of the PCI cards installed and the resources allocated for each card.
1.11 Can I Distribute the Driver Created with WinDriver? 25 1.10.4 Samples In addition to the samples provided for specific chipsets [1.10.3], WinDriver includes a variety of samples that demonstrate how to use WinDriver’s API to communicate with your device and perform various driver tasks. • C samples: found under the WinDriver/samples directory. These samples also include the source code for the utilities listed above [1.10.2]. • .NET C# samples (Windows): found under the WinDriver\csharp.
Chapter 2 Understanding Device Drivers This chapter provides you with a general introduction to device drivers and takes you through the structural elements of a device driver. NOTE Using WinDriver, you do not need to familiarize yourself with the internal workings of driver development.
2.2 Classification of Drivers According to Functionality 2.2 Classification of Drivers According to Functionality There are numerous driver types, differing in their functionality. This subsection briefly describes three of the most common driver types. 2.2.1 Monolithic Drivers Monolithic drivers are device drivers that embody all the functionality needed to support a hardware device. A monolithic driver is accessed by one or more user applications, and directly drives a hardware device.
2.2 Classification of Drivers According to Functionality 28 2.2.2 Layered Drivers Layered drivers are device drivers that are part of a stack of device drivers that together process an I/O request. An example of a layered driver is a driver that intercepts calls to the disk and encrypts/decrypts all data being transferred to/from the disk. In this example, a driver would be hooked on to the top of the existing driver and would only do the encryption/decryption.
2.3 Classification of Drivers According to Operating Systems 29 Figure 2.3: Miniport Drivers Windows NT/2000/XP/Server 2003/Vista provide several driver classes (called ports) that handle the common functionality of their class. It is then up to the user to add only the functionality that has to do with the inner workings of the specific hardware. The NDIS miniport driver is one example of such a driver.
2.3 Classification of Drivers According to Operating Systems 30 WDM drivers are PnP drivers that support power management protocols, and include monolithic drivers, layered drivers and miniport drivers. 2.3.2 VxD Drivers VxD drivers are Windows 95/98/Me Virtual Device Drivers, often called VxDs because the file names end with the .vxd extension. VxD drivers are typically monolithic in nature. They provide direct access to hardware and privileged operating system functions.
2.4 The Entry Point of the Driver 31 2.3.5 Solaris Device Drivers Solaris device drivers are also based on the classic Unix device driver model. Like Linux drivers, Solaris drivers may be either statically linked with the kernel or dynamically loaded and removed from the kernel. Like Unix and Linux device drivers, Solaris device drivers are either layered or monolithic drivers. 2.
2.6 Communicating with Drivers 32 2.6 Communicating with Drivers A driver can create an instance, thus enabling an application to open a handle to the driver through which the application can communicate with it. The applications communicate with the drivers using a file access API (Application Program Interface). Applications open a handle to the driver using CreateFile() call (in Windows), or open() call (in Linux) with the name of the device as the file name.
Chapter 3 Installing WinDriver This chapter takes you through the process of installing WinDriver on your development platform, and shows you how to verify that your WinDriver is properly installed. The last section discusses the uninstall procedure. To find out how to install the driver you create on target platforms, refer to Chapter 14. 3.1 System Requirements 3.1.1 Windows System Requirements 3.1.1.1 Windows 98/Me System Requirements • Any x86 32-bit processor.
3.1 System Requirements 34 3.1.2 Windows CE System Requirements • An x86 / MIPS / ARM Windows Embedded CE v6.00 or Windows CE 4.x – 5.0 (.NET) target platform or: an ARMV4I Windows Mobile 5.0/6.0 target platform. • Windows 2000/XP/Server 2003/Vista host development platform. • For Windows CE 4.x – 5.0: Microsoft eMbedded Visual C++ with a corresponding target SDK OR Microsoft Platform Builder with a corresponding BSP (Board Support Package) for the target platform. For Windows Embedded CE 6.
3.1 System Requirements 35 3.1.4 Solaris System Requirements • Solaris 8 / 9 / 10 / OpenSolaris. NOTE For Solaris 8 it is recommended to use update 3 or higher (available from Sun: http://www.sun.com). • 64-bit or 32-bit kernel on SPARC platform OR 32-bit kernel on x86 platform. • Any development environment supporting C (such as GCC). • WinDriver 5.22 is still provided for Solaris 2.6/7.0 32-bit kernel on Intel x86 platform.
3.2 WinDriver Installation Process 36 3.2 WinDriver Installation Process The WinDriver CD contains all versions of WinDriver for all the different operating systems. The CD’s root directory contains the Windows 98/Me/2000/XP/Server 2003/Vista and Windows CE version. This will automatically begin when you insert the CD into your CD drive. The other versions of WinDriver are located in sub-directories, i.e. Linux/, Wince/, etc. 3.2.
3.2 WinDriver Installation Process 37 NOTE The WinDriver installation defines a WD_BASEDIR environment variable, which is set to point to the location of your WinDriver directory, as selected during the installation. This variable is used during the DriverWizard [4] code generation – it determines the default directory for saving your generated code and is used in the include paths of the generated project/make files. This variable is also used from the sample Kernel PlugIn projects and makefiles.
3.2 WinDriver Installation Process 38 3.2.2 Windows CE WinDriver Installation Instructions 3.2.2.1 Installing WinDriver CE when Building New CE-Based Platforms NOTES • The following instructions apply to platform developers who build Windows CE kernel images using Windows CE Platform Builder or using MSDEV 2005 with the Windows CE 6.0 plugin. The instructions use the notation ”Windows CE IDE” to refer to either of these platforms.
3.2 WinDriver Installation Process 39 (a) Run the Windows CE IDE and open your platform. (b) From the File menu select Manage Catalog Items.... and then click the Import... button and select the WinDriver.cec file from the relevant WinDriver\samples\wince_install\\ directory (e.g. WinDriver\samples\wince_install\ARMV4I\). This will add a WinDriver component to the Platform Builder Catalog.
3.2 WinDriver Installation Process 40 7. Restart your target CE platform. The WinDriver CE kernel will automatically load. 8. Compile and run the sample programs to make sure that WinDriver CE is loaded and is functioning correctly (see section 3.4.2, which describes how to check your installation). 3.2.2.
3.2 WinDriver Installation Process 41 kernel module has to be reloaded after boot. To load WinDriver on the target Windows Mobile platform every time the OS is started, copy the WinDriver\redist\Windows_Mobile_5_ARMV4I\ wdreg.exe utility to the Windows\StartUp\ directory on the target. 6. Restart your target CE computer. The WinDriver CE kernel will automatically load. You will have to do a warm reset rather than just suspend/resume (use the reset or power button on your target CE computer). 7.
3.2 WinDriver Installation Process 42 3.2.3 Linux WinDriver Installation Instructions 3.2.3.1 Preparing the System for Installation In Linux, kernel modules must be compiled with the same header files that the kernel itself was compiled with. Since WinDriver installs the kernel module windrvr6.o/.ko, it must compile with the header files of the Linux kernel during the installation process. Therefore, before you install WinDriver for Linux, verify that the Linux source code and the file versions.
3.2 WinDriver Installation Process /usr/src$ ln -s / linux For example, for the Linux 2.4 kernel type: /usr/src$ ln -s linux-2.4/ linux 3.2.3.2 Installation 1. Insert the WinDriver CD into your Linux machine’s CD drive or copy the downloaded file to your preferred directory. 2. Change directory to your preferred installation directory, for example to your home directory: $ cd ~ 3. Extract the WinDriver distribution file – WD920LN.tgz: $ tar xvzf //WD920LN.
3.2 WinDriver Installation Process 44 6. Create a symbolic link so that you can easily launch the DriverWizard GUI: $ ln -s /wizard/wdwizard/ usr/bin/wdwizard 7. Change the read and execute permissions on the file wdwizard so that ordinary users can access this program. 8. Change the user and group IDs and give read/write permissions to the device file /dev/windrvr6 depending on how you wish to allow users to access hardware through the device. If you are using a Linux 2.6.
3.2 WinDriver Installation Process 45 12. Select the Register WinDriver option from the File menu and insert the license string you received from Jungo. 13. Click the Activate License button. 14. To register source code that you developed during the evaluation period, refer to the documentation of WDC_DriverOpen() [B.3.2]. When using the low-level WD_xxx API instead of the WDC_xxx API [B.2] (which is used by default), refer to the documentation of WD_License() in the WinDriver PCI Low-Level API Reference.
3.2 WinDriver Installation Process 46 3.2.4 Solaris WinDriver Installation Instructions Installation of WinDriver should be performed by the system administrator logged in as root, or with root privileges, since the WinDriver installation process includes installation of the kernel module windrvr6. 1. Insert your CD into your Solaris machine CD drive or copy the downloaded file to your preferred directory. 2.
3.2 WinDriver Installation Process 47 The following three steps are optional: 9. Create a symbolic link so that you can easily launch the DriverWizard GUI: ~/WinDriver# ln -s ~/WinDriver/wizard/wdwizard/ usr/bin/wdwizard 10. Change the read and execute permissions on the file wdwizard so that ordinary users can access this program. 11.
3.3 Upgrading Your Installation 3.3 Upgrading Your Installation To upgrade to a new version of WinDriver on Windows, follow the steps outlined in section 3.2.1, which illustrate the process of installing WinDriver for Windows 98/Me/2000/XP/Server 2003/Vista. You can either choose to overwrite the existing installation or install to a separate directory. After installation, start DriverWizard and enter the new license string, if you have received one. This completes the upgrade of WinDriver.
3.4 Checking Your Installation 49 3.4 Checking Your Installation 3.4.1 Windows, Linux and Solaris Installation Check 1. Start DriverWizard: On Windows, by choosing Programs | WinDriver | DriverWizard from the Start menu, or using the shortcut that is automatically created on your Desktop. A third option for activating the DriverWizard on Windows is by running wdwizard.exe from a command prompt under the wizard sub-directory.
3.5 Uninstalling WinDriver 50 3.5 Uninstalling WinDriver This section will help you to uninstall either the evaluation or registered version of WinDriver. 3.5.1 Windows WinDriver Uninstall Instructions NOTES • For Windows 98/Me, replace references to wdreg below with wdreg16. • For Windows 2000/XP/Server 2003/Vista, you can also use the wdreg_gui.exe utility instead of wdreg.exe. • wdreg.exe, wdreg_gui.exe and wdreg16.
3.5 Uninstalling WinDriver 51 4. Uninstall WinDriver: • On the development PC, on which you installed the WinDriver toolkit: Run Start | WinDriver | Uninstall, OR run the uninstall.exe utility from the WinDriver\ installation directory. The uninstall will stop and unload the WinDriver kernel module (windrvr6.sys); delete the copy of the windrvr6.
3.5 Uninstalling WinDriver 52 NOTES • If there are open handles to WinDriver when attempting to uninstall it (either using the uninstall utility or by running the wdreg uninstall command directly) – for example if there is an open WinDriver application or a connected Plug-and-Play device that has been registered to work with WinDriver via an INF file (on Windows 98/Me/2000/XP/Server 2003/Vista) – an appropriate warning message will be displayed.
3.5 Uninstalling WinDriver 3.5.2 Linux WinDriver Uninstall Instructions NOTE You must be logged in as root to perform the uninstall procedure. 1. Verify that the WinDriver module is not being used by another program: • View a list of modules and the programs using each of them: /# /sbin/lsmod • Close any applications that are using the WinDriver module. • Unload any modules that are using the WinDriver module: /sbin# rmmod 2. Unload the WinDriver module: /sbin# rmmod windrvr6 3.
3.5 Uninstalling WinDriver 54 3.5.3 Solaris WinDriver Uninstall Instructions NOTE You must be logged in as root to perform the uninstall procedure. 1. Make sure no programs are using WinDriver. 2. If you created a Kernel PlugIn driver, remove it by following these steps: (a) # /usr/sbin/rem_drv kpname (b) On 64-bit platforms (64-bit SPARC): # rm /kernel/drv/sparcv9/kpname On 32-bit platforms (32-bit x86/SPARC): # rm /kernel/drv/kpname (c) # rm /kernel/drv/kpname.conf 3.
Chapter 4 Using DriverWizard This chapter describes WinDriver DriverWizard’s hardware diagnostics and driver code generation capabilities. NOTE CardBus devices are handled via WinDriver’s PCI API, therefore any references to PCI in this chapter also include CardBus. 4.1 An Overview DriverWizard (included in the WinDriver toolkit) is a GUI-based diagnostics and driver generation tool that allows you to write to and read from the hardware, before writing a single line of code.
4.2 DriverWizard Walkthrough 56 have to be modified according to the specific functionality of the device in question. Preferably, use the complete source code libraries and sample applications (supplied in the package) tailored to the various PCI chipsets.
4.2 DriverWizard Walkthrough 2. Run DriverWizard and select your device: (a) Click Start | Programs | WinDriver | DriverWizard or double click the DriverWizard icon on your desktop (on Windows), or run the wdwizard utility from the WinDriver/wizard/ directory. (b) Click New host driver project to start a new project, or Open an existing project to open a saved session. Figure 4.1: Create or Open a WinDriver Project (c) Select your Plug and Play card from the list of devices detected by DriverWizard.
4.2 DriverWizard Walkthrough 58 For non-Plug and Play cards, select ISA. To generate code for a PCI device that is not currently attached to the computer, select PCI: PCI Virtual Device. 3. Generate an INF file for DriverWizard: When developing a driver for a Plug and Play Windows operating system (i.e., Windows 98/Me/2000/XP/Server 2003/Vista) you are required to install an INF file for your device. This file will register your Plug and Play device to work with the windrvr6.sys driver.
4.2 DriverWizard Walkthrough Figure 4.3: DriverWizard INF File Information (b) DriverWizard will display information detected for your device – Vendor ID, Device ID, Device Class, manufacturer name and device name – and allow you to modify the manufacturer and device names and the device class information. (c) When you are done, click Next and choose the directory in which you wish to store the generated INF file. DriverWizard will then automatically generate the INF file for you.
4.2 DriverWizard Walkthrough 60 NOTE To use Message-Signaled Interrups (MSI) or Extended Message-Signaled Interrups (MSI-X) on Windows Vista (for PCI cards that support MSI/MSI-X) you will need to modify or replace the generated DriverWizard INF file to include specific MSI information, otherwise WinDriver will attempt to use legacy level sensitive interrupt handling for your card, as explained in section 9.2.6.1 of the manual. 4.
4.2 DriverWizard Walkthrough 61 Figure 4.4: PCI Resources Figure 4.5: Define Registers NOTE When accessing memory mapped ranges, be aware that Linux PowerPC uses big-endian for handling memory storage, as opposed to the PCI bus that uses little-endian. For more information regarding little/big-endian issues, refer to section 9.3.
4.2 DriverWizard Walkthrough 62 Figure 4.6: Read/Write Memory and I/O • ’Listen’ to your hardware’s interrupts. Figure 4.
4.2 DriverWizard Walkthrough 63 Figure 4.8: Define Transfer Commands for Level Sensitive Interrupts 6. Generate the skeletal driver code: (a) Select to generate code either via the Generate Code toolbar icon or from the Project | Generate Code menu. (b) In the Select Code Generation Options dialogue box that will appear, choose the code language and development environment(s) for the generated code and select Next to generate the code.
4.3 DriverWizard Notes 64 Figure 4.9: Code Generation Options 4.3 DriverWizard Notes 4.3.1 Sharing a Resource If you want more than one driver to share a single resource, you must define that resource as shared: 1. Select the resource. 2. Right click on the resource. 3. Select Share from the menu.
4.3 DriverWizard Notes 65 Figure 4.10: Additional Driver Options NOTE New interrupts are set as Shared by default. If you wish to define an interrupt as unshared, follow Steps 1 and 2, and select Unshared in Step 3. 4.3.2 Disabling a Resource During your diagnostics, you may wish to disable a resource so that DriverWizard will ignore it and not create code for it. 1. Select the resource. 2. Right click on the resource name. 3. Choose Disable from the menu. 4.3.
4.3 DriverWizard Notes 66 input and output during the diagnostics stage, so that you may analyze your device’s physical performance at a later time. You can save the log for future reference. When saving the project, your log is saved as well. Each log is associated with one project. 4.3.5 Automatic Code Generation After you have finished diagnosing your device and have ensured that it runs according to your specifications, you are ready to write your driver. 4.3.5.
4.3 DriverWizard Notes 67 • A diagnostics program that utilizes the generated DriverWizard API (declared in xxx_lib.h) to communicate with your device(s): xxx_diag.c The source code of the generated diagnostics console application. Use this diagnostics program as your skeletal device driver. • A list of all files created can be found at xxx_files.txt.
4.3 DriverWizard Notes 68 NOTES • For Windows 98/Me/2000/XP/Server 2003/Vista, the generated IDE files are located under an x86\ directory – for 32-bit projects, or amd64\ directory – for 64-bit projects. • For Windows CE, note that the generated Windows Mobile code is targeted at the Windows Mobile 5.0/6.0 ARMV4I SDK. 4.3.6.2 Linux and Solaris Compilation Use the makefile that was created for you by DriverWizard in order to build the generated code using your favourite compiler, preferably GCC.
Chapter 5 Developing a Driver This chapter takes you through the WinDriver driver development cycle. NOTE If your device is based on one of the chipsets for which WinDriver provides enhanced support (PLX 9030, 9050, 9052, 9054, 9056, 9080 and 9656; Altera pci_dev_kit; Xilinx VirtexII and Virtex 5; AMCC S5933), read the following overview and then skip straight to Chapter 7. 5.
5.2 Writing the Device Driver Without the DriverWizard 70 • Use any C / .NET / Delphi / Visual Basic compiler (such as MSDEV/Visual C/C++, MSDEV .NET, Borland C++ Builder, Borland Delphi, Visual Basic 6.0, MS eMbedded Visual C++, MS Platform Builder C++, GCC, etc.) to compile the skeletal driver you need. • For Linux and Solaris, use any compilation environment, preferably GCC, to build your code. • That is all you need to do in order to create your user-mode driver.
5.2 Writing the Device Driver Without the DriverWizard 71 3. Link your code with the wdapi920 library/shared object: • For Windows 98/Me/2000/XP/Server 2003/Vista: WinDriver\lib\\wdapi920.lib or wdapi920_borland.lib (for Borland C++ Builder), where the directory is either x86\ (32-bit binaries for x86 platforms), am64\ (64-bit binaries for x64 platforms) or am64\x86\ (32-bit binaries for x64 platforms). • For Windows CE: WinDriver\lib\WINCE\\wdapi920.lib.
5.3 Developing Your Driver on Windows CE Platforms 72 the device, which you can later use to communicate with the device using the WDC_xxx API. 5. Communicate with the device using the WDC_xxx API (see description in Appendix B). To enable interrupts, call WDC_IntEnable() [B.3.43]. To register to receive notifications for Plug and Play and power management events, call WDC_EventRegister() [B.3.46]. 6. When you are done, call WDC_IntDisable() [B.3.
5.4 Developing in Visual Basic and Delphi 73 5.4 Developing in Visual Basic and Delphi The entire WinDriver API can be used when developing drivers in Visual Basic and Delphi. 5.4.1 Using DriverWizard DriverWizard can be used to diagnose your hardware and verify that it is working properly before you start coding. You can then proceed to automatically generate source code with the wizard in a variety of languages, including Delphi and Visual Basic. For more information, refer to Chapter 4 and Section 5.
Chapter 6 Debugging Drivers The following sections describe how to debug your hardware access application code. 6.1 User-Mode Debugging • Since WinDriver is accessed from the user mode, we recommend that you first debug your code using your standard debugging software. • The Debug Monitor utility [6.2] logs debug messages from WinDriver’s kerneland user-mode APIs. You can also use WinDriver APIs to send your own debug messages to the Debug Monitor log.
6.2 Debug Monitor 75 6.2 Debug Monitor Debug Monitor is a powerful graphical- and console-mode tool for monitoring all activities handled by the WinDriver kernel (windrvr6.sys/.dll/.o/.ko). You can use this tool to monitor how each command sent to the kernel is executed. In addition, WinDriver enables you to print your own debug messages to the Debug Monitor, using the WD_DebugAdd() function (described in the WinDriver PCI Low-Level API Reference) or the high-level PrintDbgMessage() function [B.8.14].
6.2 Debug Monitor 76 2. Set the Debug Monitor’s status, trace level and debug sections information from the Debug Options dialogue, which is activated either from the Debug Monitor’s View | Debug Options menu or the Debug Options toolbar button. Figure 6.2: Debug Options • Status – Set trace on or off. • Section – Choose what part of the WinDriver API you would like to monitor.
6.2 Debug Monitor 77 • Level – Choose the level of messages you want to see for the resources defined. Error is the lowest trace level, resulting in minimum output to the screen. Trace is the highest trace level, displaying every operation the WinDriver kernel performs. • Select the Send debug messages to the operating system kernel debugger option if you want debugging messages to be sent to an external kernel debugger as well.
6.2 Debug Monitor 78 6.2.2 Using the Debug Monitor in Console Mode – wddebug The Debug Monitor utility comes in a console-mode version – WinDriver/util/wddebug – which is available for all supported operating systems. To use the wddebug console-mode version of the Debug Monitor utility on Windows 98/Me/2000/XP/Server 2003/Vista, Windows CE, Linux and Solaris, run the WinDriver/util/wddebug utility, as explained below. i On Windows CE, start a Windows CE command window (CMD.
6.2 Debug Monitor 79 – dbg_off : Stop redirecting debug messages from the Debug Monitor to a kernel debugger. NOTE The on and dbg_on commands can be run together with the level and/or sections options described below. • dump : Continuously display (”dump”) debug information until the user presses Esc.
6.2 Debug Monitor 80 • Run wddebug with the dump command to begin dumping debug messages to the command prompt. You can turn off the display of the debug messages at any time by pressing Esc in the command prompt. • Run applications that use the driver, and view the debug messages as they are being logged to the command prompt / the kernel debugger.
Chapter 7 Enhanced Support for Specific Chipsets 7.1 Overview In addition to the standard WinDriver API and the DriverWizard code generation capabilities described in this manual, which support development of drivers for any PCI/ISA/PCMCIA/CardBus device, WinDriver offers enhanced support for specific PCI chipsets. The enhanced support includes custom API and sample diagnostics code, which are designed specifically for these chipsets.
7.2 Developing a Driver Using the Enhanced Chipset Support 82 7.2 Developing a Driver Using the Enhanced Chipset Support When developing a driver for a device based on one of the enhanced-support chipsets [7.1], you can use WinDriver’s chipset-set specific support by following these steps: 1. Locate the sample diagnostics program for your device under the WinDriver/chip_vendor/chip_name/ directory.
Chapter 8 PCI Express 8.1 PCI Express Overview The PCI Express (PCIe) bus architecture (formerly 3GIO or 3rd Generation I/O) was introduced by Intel, in partnership with other leading companies, including IBM, Dell, Compaq, HP and Microsoft, with the intention that it will become the prevailing standard for PC I/O in the years to come. PCI-Express allows for larger bandwidth and higher scalability than the standard PCI 2.2 bus. The standard PCI 2.
8.1 PCI Express Overview 84 The increased bandwidth support makes PCI Express ideal for the growing number of devices that require high bandwidth, such as hard drive controllers, video streaming devices and networking cards. The usage of a switch to control the data flow in the PCI Express bus, as explained above, provides an improvement over a shared PCI bus, because each device essentially has direct access to the bus, instead of multiple components having to share the bus.
8.2 WinDriver for PCI Express 85 8.2 WinDriver for PCI Express WinDriver fully supports backward compatibility with the standard PCI features on PCI Express boards. The wide support provided by WinDriver for the standard PCI bus – including a rich set of APIs, code samples and the graphical DriverWizard for hardware debugging and driver code generation – is also applicable to PCI Express devices, which by design are backward compatible with the legacy PCI bus.
Chapter 9 Advanced Issues This chapter covers advanced driver development issues and contains guidelines for using WinDriver to perform tasks that cannot be fully automated by the DriverWizard. Note that WinDriver’s enhanced support for specific chipsets [7] includes custom APIs for performing hardware-specific tasks like DMA and interrupt handling, thus freeing developers of drivers for these chipsets from the need to implement the code for performing these tasks themselves. 9.
9.1 Performing Direct Memory Access (DMA) 87 virtual address space, thus enabling easy access to the allocated physical memory blocks. The programming of a device’s DMA controller is hardware specific. Normally, you need to program your device with the local address (on your device), the host address (the physical memory address on your PC) and the transfer count (the size of the memory block to transfer), and then set the register that initiates the transfer.
9.1 Performing Direct Memory Access (DMA) 88 9.1.1.
9.1 Performing Direct Memory Access (DMA) 89 /* DMAOpen: Locks a Scatter/Gather DMA buffer */ BOOL DMAOpen(WDC_DEVICE_HANDLE hDev, PVOID pBuf, UINT32 u32LocalAddr, DWORD dwDMABufSize, BOOL fToDev, WD_DMA **ppDma) { DWORD dwStatus, i; DWORD dwOptions = fToDev ? DMA_TO_DEVICE : DMA_FROM_DEVICE; /* Lock a Scatter/Gather DMA buffer */ dwStatus = WDC_DMASGBufLock(hDev, pBuf, dwOptions, dwDMABufSize, ppDma); if (WD_STATUS_SUCCESS != dwStatus) { printf("Failed locking a Scatter/Gather DMA buffer.
9.1 Performing Direct Memory Access (DMA) 90 9.1.1.2 What Should You Implement? In the code sample above, it is up to you to implement the following MyDMAxxx() routines, according to your device’s specification • MyDMAProgram(): Program the device’s DMA registers. Refer the device’s datasheet for the details. • MyDMAStart(): Write to the device’s registers to start DMA transfers. • MyDMAInterruptEnable() and MyDMAInterruptDisable(): Use WDC_IntEnable() [B.3.43] and WDC_IntDisable() [B.3.
9.1 Performing Direct Memory Access (DMA) 91 9.1.2.
9.
9.1 Performing Direct Memory Access (DMA) 93 9.1.2.2 What Should You Implement? In the code sample above, it is up to you to implement the following MyDMAxxx() routines, according to your device’s specification • MyDMAProgram(): Program the device’s DMA registers. Refer the device’s datasheet for the details. • MyDMAStart(): Write to the device to initiate DMA transfers. • MyDMAInterruptEnable() and MyDMAInterruptDisable(): Use WDC_IntEnable() [B.3.43] and WDC_IntDisable() [B.3.
9.2 Handling Interrupts 94 9.2 Handling Interrupts WinDriver provides you with API, DriverWizard code generation, and samples, to simplify the task of handling interrupts from your driver. If you are developing a driver for a device based on one of the enhanced-support WinDriver chipsets [7], we recommend that you use the custom WinDriver interrupt APIs for your specific chip in order to handle the interrupts, since these routines are implemented specifically for the target hardware.
9.2 Handling Interrupts 95 • Edge-triggered interrupts: These are interrupts that are generated once, when the physical interrupt signal goes from low to high. Therefore, exactly one interrupt is generated. No special action is required in order to acknowledge this type of interrupt. ISA/EISA interrupts are edge triggered. MSI/MSI-X: Newer PCI bus technologies, available beginnig with v2.2 of the PCI bus and in PCI Express, support Message-Signaled Interrups (MSI).
9.2 Handling Interrupts 96 9.2.2 WinDriver Interrupt Handling Sequence NOTE This section describes how to use WinDriver to handle interrupts from a user-mode application. Since interrupt handling is a performance-critical task, it is very likely that you may want to handle the interrupts directly in the kernel. WinDriver’s Kernel PlugIn [11] enables you to implement kernel-mode interrupt routines. To find out how to handle interrupts from the Kernel PlugIn, please refer to section 11.6.5 of the manual.
9.2 Handling Interrupts 97 NOTES • The low-level WD_IntWait() WinDriver function (described in the WinDriver PCI Low-Level API Reference), which is used by the high-level interrupt enable functions to wait on interrupts from the device, puts the thread to sleep until an interrupt occurs. There is no CPU consumption while waiting for an interrupt. Once an interrupt occurs, it is first handled by the WinDriver kernel, then WD_IntWait() wakes up the interrupt handler thread and returns, as explained above.
9.2 Handling Interrupts 98 9.2.4 Determining the Interrupt Type Enabled for a PCI Card When attempting to enable interrupts for a PCI card on Linux or Windows Vista, WinDriver first tries to use MSI-X or MSI, if supported by the card. If this fails, WinDriver attempts to enable legacy level sensitive interrupts. WinDriver’s interrupt enable functions return information regarding the interrupt type that was enabled for the card.
9.2 Handling Interrupts 99 9.2.5.1 Interrupt Mask Commands The interrupt transfer commands array that you pass to WinDriver can also contain an interrupt mask structure, which will be used to verify the source of the interrupt. This is done by setting the transfer structure’s cmdTrans field, which defines the type of the transfer command, to CMD_MASK, and setting the relevant mask in the transfer structure’s Data field [B.5.15].
9.2 Handling Interrupts 100 9.2.5.2 Sample WinDriver Transfer Commands Code This section provides sample code for setting up interrupt transfer commands using the WinDriver Card (WDC) library API [B.2]. The sample code is provided for the following scenario: Assume you have a PCI card that generates level sensitive interrupts. When an interrupt occurs you expect the value of your card’s interrupt command-status register (INTCSR), which is mapped to an I/O port address (dwAddr), to be intrMask.
9.2 Handling Interrupts 101 The following code demonstrates how to use the WDC_IntEnable() function to enable the interrupts using the transfer commands prepared above: /* Enable the interrupts: hDev: WDC_DEVICE_HANDLE received from a previous call to WDC_PciDeviceOpen(). INTERRUPT_CMD_COPY: Used to save the read data - see WDC_IntEnable(). interrupt_handler: Your user-mode interrupt handler routine. pData: The data to pass to the interrupt handler routine.
9.2 Handling Interrupts 102 [ I n s t a l l . NT .HW] AddReg = I n s t a l l . NT .HW. AddReg [ I n s t a l l . NT .HW.
9.2 Handling Interrupts 103 NOTES • The following sample code demonstrates interrupt handling for an edge triggered ISA card. The code does not set up any kernel-mode interrupt transfer commands [9.2.5], which is accetable in the case of edge-triggered or MSI/MSI-X interrupts [9.2.1].
9.2 Handling Interrupts 104 interrupt_handler, (PVOID)hDev, FALSE); /* WDC_IntEnable() allocates and initializes the required WD_INTERRUPT structure, stores it in the WDC_DEVICE structure, then calls InterruptEnable(), which calls WD_IntEnable() and creates an interrupt handler thread */ if (WD_STATUS_SUCCESS != dwStatus) { printf ("Failed enabling interrupt.
9.2 Handling Interrupts 105 logical interrupt = SYSINTR_FIRMWARE + physical interrupt When the device is not registered with Windows CE Plug-and-Play, WinDriver will follow this mapping. 3. Specify the Mapped Interrupt Value NOTE This option can only be performed by the Platform Builder. Provide the device’s mapped logical interrupt value. If unavailable, statically map the physical IRQ to a logical interrupt.
9.2 Handling Interrupts 106 9.2.8.1 Improving Interrupt Latency on Windows CE You can reduce the interrupt latency on Windows CE for PCI devices by making slight changes in the registry and in your code: 1. When developing your driver on Windows CE platforms, you must first register your device to work with WinDriver, as explained in section 5.3.
9.3 Byte Ordering 107 9.3 Byte Ordering 9.3.1 Introduction to Endianness There are two main architectures for handling memory storage. They are called Big Endian and Little Endian and refer to the order in which the bytes are stored in memory. • Big endian means that the most significant byte of any multi-byte data field is stored at the lowest memory address. This means a Hex word like 0x1234 is stored in memory as (0x12 0x34). The big end, or upper end, is stored first.
9.3 Byte Ordering 108 9.3.3 Macros for PCI Target Access WinDriver’s macros for PCI target access are used for converting endianness while reading/writing from/to PCI cards using memory mapped ranges of PCI devices. NOTE These macro definitions apply to Linux PowerPC architecture.
9.3 Byte Ordering 109 9.3.4 Macros for PCI Master Access WinDriver’s macros for PCI master access are used for converting endianness of data in host memory that is accessed by the PCI master device, i.e. in cases of access that is initiated by the device rather than the host. NOTE These macro definitions apply to both Linux PowerPC and SPARC architectures.
Chapter 10 Improving Performance 10.1 Overview Once your user-mode driver has been written and debugged, you might find that certain modules in your code do not operate fast enough (for example: an interrupt handler or accessing I/O-mapped regions). If this is the case, try to improve performance in one of the following ways: • Improve the performance of your user-mode driver [10.2]. • Create a Kernel PlugIn driver [11] and move the performance-critical portions of your code to the Kernel PlugIn.
10.1 Overview 111 10.1.1 Performance Improvement Checklist The following checklist will help you determine how to improve the performance of your driver: Problem ISA Card – accessing an I/O-mapped range on the card PCI Card – accessing an I/O-mapped range on the card Accessing a memory-mapped range on the card Interrupt latency – missing interrupts, receiving interrupts too late PCI target access vs.
10.2 Improving the Performance of a User-Mode Driver 112 10.2 Improving the Performance of a User-Mode Driver As a general rule, transfers to memory-mapped regions are faster than transfers to I/O-mapped regions, because WinDriver enables you to access memory-mapped regions directly from the user mode, without the need for a function call, as explained in section 10.2.1.
10.2 Improving the Performance of a User-Mode Driver 113 Whatever the method you select to access the memory on your card, it is important to align the base address according to the size of the data type, especially when issuing string transfer commands. Otherwise, the transfers are split into smaller portions. The easiest way to align data is to use basic types when defining a buffer, i.e.
10.2 Improving the Performance of a User-Mode Driver 114 development tools. To date, such tools do not enable 64-bit data transfer on x86 platforms running 32-bit operating systems. Jungo’s benchmark performance testing results for 64-bit data transfer indicate a significant improvement of data transfer rates compared to 32-bit data transfer, guaranteeing that drivers developed with WinDriver will achieve far better performance than 32-bit data transfer normally allows.
Chapter 11 Understanding the Kernel PlugIn This chapter provides a description of WinDriver’s Kernel PlugIn feature. NOTE Kernel PlugIn is not implemented under Windows CE. In this operating system there is no separation between kernel mode and user mode, therefore top performance can be achieved without using the Kernel PlugIn. To improve the interrupt handling rate on Windows CE, follow the instructions in section 9.2.8.1 of the manual. 11.
11.2 Do I Need to Write a Kernel PlugIn Driver? 116 • The parts of the code that will run in the kernel through the Kernel PlugIn are platform independent and therefore will run on every platform supported by WinDriver and the Kernel PlugIn. A standard kernel-mode driver will run only on the platform it was written for. Using WinDriver’s Kernel PlugIn feature, your driver will operate without any performance degradation. 11.
11.5 The Kernel PlugIn Architecture 117 11.5 The Kernel PlugIn Architecture 11.5.1 Architecture Overview A driver written in user mode uses WinDriver’s API (WDC_xxx and/or WD_xxx [B.2]) to access devices. If a certain function that was implemented in the user mode requires kernel performance (the interrupt handler, for example), that function is moved to the WinDriver Kernel PlugIn.
11.5 The Kernel PlugIn Architecture 118 11.5.2 WinDriver’s Kernel and Kernel PlugIn Interaction There are two types of interaction between the WinDriver kernel and the WinDriver Kernel PlugIn: Interrupt handling: When WinDriver receives an interrupt, by default it will activate the caller’s user-mode interrupt handler. However, if the interrupt was set to be handled by a Kernel PlugIn driver, then once WinDriver receives the interrupt, it activates the Kernel PlugIn driver’s kernel-mode interrupt handler.
11.5 The Kernel PlugIn Architecture 119 11.5.4 Kernel PlugIn Event Sequence The following is a typical event sequence that covers all the functions that you can implement in your Kernel PlugIn: 11.5.4.1 Opening Handle from the User Mode to a Kernel PlugIn Driver Event/Callback Event: Windows loads your Kernel PlugIn driver. Callback: Your KP_Init() Kernel PlugIn routine [B.6.2] is called Event: Your user-mode driver application calls WDC_xxxDeviceOpen() (PCI: [B.3.9], PCMCIA: [B.3.10], ISA: [B.3.
11.5 The Kernel PlugIn Architecture 120 11.5.4.2 Handling User-Mode Requests from the Kernel PlugIn Event/Callback Event: Your application calls WDC_CallKerPlug() [B.3.17], or the low-level WD_KernelPlugInCall() function (see the WinDriver PCI Low-Level API Reference). Callback: Your KP_Call() Kernel PlugIn routine [B.6.4] is called. Notes Your application calls WDC_CallKerPlug() / WD_KernelPlugInCall() to execute code in the kernel mode (in the Kernel PlugIn driver).
11.5 The Kernel PlugIn Architecture Event/Callback Event: Your application calls WDC_IntDisable() [B.3.44], or the low-level InterruptDisable() or WD_IntDisable() functions (see the WinDriver PCI Low-Level API Reference), when the interrupts were previously enabled in the Kernel PlugIn (see the description of the interrupt enable event above.) Callback: Your KP_IntDisable() Kernel PlugIn routine [B.6.7] is called. 121 Notes This function should free any memory that was allocated by the KP_IntEnable() [B.
11.6 How Does Kernel PlugIn Work? Event/Callback Event: A Plug and Play or power management event (to which the application registered to listen) occurs. Callback: Your KP_Event() Kernel PlugIn routine [B.6.5] is called. Event: KP_Event() [B.6.5] returns TRUE. Callback: WD_IntWait() (see the WinDriver PCI Low-Level API Reference) returns. 122 Notes KP_Event() receives information about the event that occurred and can proceed to handle it as needed.
11.6 How Does Kernel PlugIn Work? 123 NOTE While this is not a minimal requirement, when developing a Kernel PlugIn driver it is highly recommended that you use two computers: set up one computer as your host platform and the other as your target platform. The host computer is the computer on which you develop your driver and the target computer is the computer on which you run and test the driver you develop 11.6.2 Kernel PlugIn Implementation 11.6.2.
11.6 How Does Kernel PlugIn Work? 124 This function is called once, when the driver is loaded. The KP_INIT structure should be filled with the name of your Kernel PlugIn and the address of your KP_Open() function [B.6.2] (see example in WinDriver/samples/pci_diag/kp_pci/kp_pci.c). NOTES • The name that you select for your Kernel PlugIn driver – by setting it in the cDriverName field of the KP_INIT structure in KP_Init() [B.6.1] – should be the name of the driver that you wish to create – i.e.
11.6 How Does Kernel PlugIn Work? 125 Note that the driver name was set using a preprocessor definition. This definition is found in the WinDriver/samples/pci_diag/pci_lib.h header file, which is shared by the pci_diag user-mode application and the KP_PCI Kernel PlugIn driver: /* Kernel PlugIn driver name (should be no more than 8 characters) */ #define KP_PCI_DRIVER_NAME "KP_PCI" 11.6.2.3 Write Your KP_Open() Function Your KP_Open() function [B.6.
11.6 How Does Kernel PlugIn Work? Callback KP_IntEnable() [B.6.6] KP_IntDisable() [B.6.7] KP_IntAtIrql() [B.6.8] KP_IntAtDpc() [B.6.
11.6 How Does Kernel PlugIn Work? Callback KP_Event() [B.6.5] 127 Functionality Called when a Plug and Play or power management event occurs, provided the user-mode application previously registered to receive notifications for this event in the Kernel PlugIn by calling WDC_EventRegister() [B.3.
11.6 How Does Kernel PlugIn Work? 128 From the KP_PCI sample (WinDriver/samples/pci_diag/kp_pci/kp_pci.c): /* KP_PCI_Open is called when WD_KernelPlugInOpen() is called from the user mode. pDrvContext will be passed to the rest of the Kernel PlugIn callback functions.
11.6 How Does Kernel PlugIn Work? 129 if (!pAddrDesc) goto malloc_error; COPY_FROM_USER(pAddrDesc, pDev->pAddrDesc, dwSize); pDev->pAddrDesc = pAddrDesc; *ppDrvContext = pDev; KP_PCI_Trace("KP_PCI_Open: Kernel PlugIn driver opened successfully\n"); return TRUE; malloc_error: KP_PCI_Err("KP_PCI_Open: Failed allocating %ld bytes\n", dwSize); PCI_LibUninit(); return FALSE; } 11.6.2.
11.6 How Does Kernel PlugIn Work? 130 The sample/generated code demonstrates how to pass data to the Kernel PlugIn’s KP_Open() function and how to use this function to allocate and store a global Kernel PlugIn driver context, which can be used by other functions in the Kernel PlugIn.
11.6 How Does Kernel PlugIn Work? 131 11.6.4 Kernel PlugIn Sample/Generated Code Directory Structure 11.6.4.1 pci_diag and kp_pci Sample Directories The Kernel PlugIn sample code – KP_PCI – is implemented in the kp_pci.c file.
11.6 How Does Kernel PlugIn Work? 132 • pci_diag.c: Implementation of a sample diagnostics user-mode console (CUI) application, which demonstrates communication with a PCI device using the pci_lib and WDC libraries. The sample also demonstrates how to communicate with a Kernel PlugIn driver from a user-mode WinDriver application. By default, the sample attempts to open the selected PCI device with a handle to the KP_PCI Kernel PlugIn driver.
11.6 How Does Kernel PlugIn Work? 133 11.6.4.2 The Generated DriverWizard Kernel PlugIn Directory The generated DriverWizard Kernel PlugIn code for your device will include a kernel-mode Kernel PlugIn project and a user-mode application that communicates with it.
11.6 How Does Kernel PlugIn Work? 134 • xxx_diag.c: Implementation of a sample diagnostics user-mode console (CUI) application, which demonstrates communication your device using the xxx_lib and WDC libraries. The application also demonstrates how to communicate with a Kernel PlugIn driver from a user-mode WinDriver application. By default, the application attempts to open your device with a handle to the KP_XXX Kernel PlugIn driver.
11.6 How Does Kernel PlugIn Work? 135 returns TRUE. The return value of KP_IntAtDpc() determines how many times (if at all) the user-mode interrupt handler routine will be executed. In the KP_PCI sample, for example, the Kernel PlugIn interrupt handler code counts five interrupts and notifies the user mode on every fifth interrupt, thus WD_IntWait() (see the WinDriver PCI Low-Level API Reference) will return on only one out of every five incoming interrupts in the user mode.
11.6 How Does Kernel PlugIn Work? 136 11.6.5.2 Interrupt Handling in the Kernel (Using a Kernel PlugIn) To have the interrupts handled by the Kernel PlugIn, the user-mode application should open a handle to the device with a Kernel PlugIn driver, by passing the name of a Kernel PlugIn driver to the WDC_xxxDeviceOpen() function (PCI: [B.3.9], PCMCIA: [B.3.10], ISA: [B.3.11]), and then call WDC_IntEnable() [B.3.43] with the fUseKP parameter set to TRUE. If your are not using the WDC_xxx API [B.
11.6 How Does Kernel PlugIn Work? 137 If the Kernel PlugIn interrupt handler is enabled, then KP_IntAtIrql() [B.6.8] for each incoming interrupt. The code in the KP_IntAtIrql() function is executed at high interrupt request level. While this code is running, the system is halted, i.e., there will be no context switches and no lower-priority interrupts will be handled. The code in the KP_IntAtIrql() function is limited in the following ways: • It may only access non-pageable memory.
11.6 How Does Kernel PlugIn Work? 138 11.6.6 Message Passing The WinDriver architecture enables a kernel-mode function to be activated from the user mode by passing a message from the user mode to the Kernel PlugIn driver using WDC_CallKerPlug() [B.3.17] or the low-level WD_KernelPlugInCall() function (see the WinDriver PCI Low-Level API Reference). The messages are defined by the developer in a header file that is common to both the user-mode and kernel-mode plugin parts of the driver.
Chapter 12 Writing a Kernel PlugIn The easiest way to write a Kernel PlugIn driver is to use DriverWizard to generate the Kernel PlugIn code for your hardware (see sections 11.6.3 and 11.6.4.2). Alternatively, you can use the sample KP_PCI PCI Kernel PlugIn driver, found under the WinDriver/samples/pci_diag/kp_pci directory, as the basis for your Kernel PlugIn driver development (see sections 11.6.3 and 11.6.4.1). You can also develop your code "from scratch", if you wish.
12.2 Prepare the User-Mode Source Code 140 12.2 Prepare the User-Mode Source Code 1. Isolate the functions you need to move into the Kernel PlugIn. 2. Remove any platform-specific code from the functions. Use only functions that can also be used from the kernel. 3. Recompile your driver in the user mode. 4. Debug your driver in user mode again to see that your code still works after changes have been made. NOTES • Keep in mind that the kernel stack is relatively limited in size.
12.4 Create a Handle to the Kernel PlugIn 141 2. Change all instances of ”KP_PCI” and ”kp_pci” in all the Kernel PlugIn files in your new directory to ”KP_MyDrv” and ”kp_mydrv” (respectively). Note: The names of the KP_PCI_xxx() functions in the kp_pci.c files do not have to be changed in order for the code to function correctly, although the code will be clearer if you use your driver’s name in the function names. 3. Change all occurrences of ”KP_PCI” in file names to ”kp_mydrv”. 4.
12.5 Set Interrupt Handling in the Kernel PlugIn 142 XXX_DeviceOpen()/PCI_DeviceOpen() library function (which is called from the generated/sample xxx_diag/pci_diag user-mode application.) If you are not using the WDC library from your code [B.2], you need to call WD_KernelPlugInOpen() at the beginning of your code in order to open a handle to your Kernel PlugIn driver, and call WD_KernelPlugInClose() before terminating the application or when you no longer wish to use the Kernel PlugIn driver.
12.6 Set I/O Handling in the Kernel PlugIn 143 3. Move the implementation of the user-mode interrupt handler, or the relevant portions of this implementation, to the Kernel PlugIn’s interrupt handler functions. High-priority code, such as the code for acknowledging (clearing) level sensitive interrupts, should be moved to the KP_IntAtIrql() function [B.6.8], which runs at high interrupt request level. Deferred processing of the interrupt can be moved to KP_IntAtDpc() [B.6.
12.7 Compile Your Kernel PlugIn Driver 144 12.7 Compile Your Kernel PlugIn Driver 12.7.
12.7 Compile Your Kernel PlugIn Driver 145 To build your Kernel PlugIn driver and respective user-mode application, follow these steps: 1. Verify that the Windows Driver Development Kit (DDK) for your target operating system is installed on your PC (see section 11.6.1). The target operating system is the operating system for which you wish to create your driver. For example, if you are creating a driver for Windows XP, install the Windows XP DDK.
12.7 Compile Your Kernel PlugIn Driver 146 NOTE The active configuration must correspond with the target OS for which you are building the driver. For example, for Windows 2000 select either Win32 win2k free (release mode) or Win32 win2k checked (debug mode). iii. Build your driver: Build the project from the Build menu or using the relevant short-cut key (e.g. F7 in MSDEV 6.0). (c) To build the user-mode application that drives the Kernel PlugIn driver (pci_diag.exe – sample / xxx_diag.
12.7 Compile Your Kernel PlugIn Driver 147 12.7.2 On Linux 1. Open a shell terminal. 2. Change directory to your Kernel PlugIn directory. For example, when compiling the sample KP_PCI driver, run: cd WinDriver/samples/pci_diag/kp_pci When compiling the Kernel PlugIn driver for your generated DriverWizard Kernel PlugIn code, run the following command, where represents the path to your generated DriverWizard project directory (e.g.
12.7 Compile Your Kernel PlugIn Driver 148 12.7.3 On Solaris NOTE WinDriver generates makefiles for GNU make utility only. If you wish to use the standard make utility, instead of the GNU make, you must modify the makefile that WinDriver generates. The GNU make package is available from http://www.sunfreeware.com. 1. Open a shell terminal. 2. Change directory to your driver’s project directory. For example, when compiling the sample KP_PCI driver, run: cd WinDriver/samples/pci_diag/ 3.
12.8 Install Your Kernel PlugIn Driver 149 12.8 Install Your Kernel PlugIn Driver 12.8.1 On Windows 1. Copy the driver file (xxx.sys) to the target platform’s drivers directory: %windir%\system32\drivers (e.g., C:\WINNT\system32\drivers – on Windows 2000, or C:\Windows\system32\drivers – on Windows XP/Server2003/Vista). NOTE If your Kernel PlugIn driver is intended for Windows 98/Me, develop the driver on a Windows 2000/XP/Server 2003/Vista host PC (see note in section 12.7). 2.
12.8 Install Your Kernel PlugIn Driver 150 represents the path to your generated DriverWizard project directory (e.g. /home/user/WinDriver/wizard/my_projects/my_kp/): cd /kermode/ 2. Run the following command to install your Kernel PlugIn driver: make install 12.8.3 On Solaris NOTE Installation of the Kernel PlugIn Driver should be performed by the system administrator logged in as root, or with root privileges (become a super user). 1. Change directory to your Kernel PlugIn directory.
12.8 Install Your Kernel PlugIn Driver 4. Copy your Kernel PlugIn driver to the target’s drivers directory. For example to copy the sample KP_PCI driver: On 64-bit platforms run: # cp kp_pci /kernel/drv/sparcv9 On 32-bit platforms run: # cp kp_pci /kernel/drv 5. Install the driver by running: # make install NOTE The following commands are also useful when installing a driver on Solaris: • modinfo – lists the loaded kernel modules. • rem_drv – removes the kernel module.
Chapter 13 Dynamically Loading Your Driver 13.1 Why Do You Need a Dynamically Loadable Driver? When adding a new driver, you may be required to reboot the system in order for it to load your new driver into the system. WinDriver is a dynamically loadable driver, which enables your customers to start your application immediately after installing it, without the need for reboot. You can dynamically load your driver whether you have created a user-mode or a kernel-mode (Kernel PlugIn [11]) driver.
13.2 Windows Dynamic Driver Loading 153 13.2 Windows Dynamic Driver Loading 13.2.1 Windows Driver Types Windows drivers can be implemented as either of the following types: • WDM (Windows Driver Model) drivers: Files with the extension .sys on Windows 98/Me/2000/XP/Server 2003/Vista (e.g. windrvr6.sys). WDM drivers are installed via the installation of an INF file (see below). • Non-WDM / Legacy drivers: These include drivers for non-Plug and Play Windows operating systems (Windows NT 4.
13.2 Windows Dynamic Driver Loading 154 NOTES 1. wdreg for Windows 2000/XP/Server 2003/Vista is dependent on the Driver Install Frameworks API (DIFxAPI) DLL – difxapi.dll, unless when run with the -compat option (described below). difxapi.dll is provided under the WinDriver\util diretory. 2. The explanations and examples below refer to wdreg, but for Windows 2000/XP/Server 2003/Vista you can replace any references to wdreg with wdreg_gui. 3.
13.2 Windows Dynamic Driver Loading 155 Usage: The wdreg utility can be used in two ways as demonstrated below: 1. wdreg -inf [-silent] [-log ] [install | uninstall | enable | disable] 2. wdreg -rescan [-silent] [-log ] • OPTIONS wdreg supports several basic OPTIONS from which you can choose one, some, or none: -inf – The path of the INF file to be dynamically installed.
13.2 Windows Dynamic Driver Loading 156 13.2.2.2 Non-WDM Drivers This section explains how to use the wdreg utility to install non-WDM drivers, namely Kernel PlugIn drivers, on Windows 98/Me/2000/XP/Server 2003/Vista. Usage: wdreg [-file ] [-name ] [-startup ] [-silent] [-log ] Action [Action ...] • OPTIONS wdreg supports several basic OPTIONS from which you can choose one, some, or none: -startup : Specifies when to start the driver.
13.2 Windows Dynamic Driver Loading 157 (%windir%\system32\drivers). Therefore, you should verify that the driver file is located in the correct directory before attempting to install the driver. Usage: wdreg -name -file install -silent – Suppresses the display of messages of any kind. -log – Logs all messages to the specified file.
13.2 Windows Dynamic Driver Loading 158 NOTE Note that in order to successfully stop a driver, there cannot be any open handles to the driver (such as open applications that use the driver). This is also true for the install and uninstall shortcuts, since both commands include stopping the driver. 13.2.3 Dynamically Loading/Unloading windrvr6.sys INF Files When using WinDriver, you develop a user-mode application that controls and accesses your hardware by using the generic windrvr6.
13.2 Windows Dynamic Driver Loading 159 13.2.4 Dynamically Loading/Unloading Your Kernel PlugIn Driver If you have used WinDriver to develop a Kernel PlugIn driver, you must load your Kernel PlugIn after loading the WinDriver generic driver windrvr6.sys. When uninstalling your driver, you should unload your Kernel PlugIn driver before unloading windrvr6.sys. NOTE Kernel PlugIn drivers for Windows 98/Me are not dynamically loaded, they require reboot after the initial loading.
13.3 Linux Dynamic Driver Loading 160 13.3 Linux Dynamic Driver Loading • To dynamically load WinDriver on Linux, execute: /sbin/modprobe windrvr6 • To dynamically unload WinDriver, execute: /sbin/rmmod windrvr6 • You can also use the wdreg script from the WinDriver/util/ directory to install (load) windrvr6.o/.ko. Usage: wdreg To install the windrvr6 module run: wdreg windrvr6 TIP To automatically load windrvr6.o/.ko on each boot, run the wdreg script from the target Linux /etc/rc.d/rc.
13.5 Windows Mobile Dynamic Driver Loading 161 13.5 Windows Mobile Dynamic Driver Loading The WinDriver\redist\Windows_Mobile_5_ARMV4I\ wdreg.exe utility can be used for loading the WinDriver kernel module (windrvr6.dll) on a Windows Mobile platform. TIP On Windows Mobile the operating system’s security scheme prevents the loading of unsigned drivers at boot time, therefore the WinDriver kernel module has to be reloaded after boot.
Chapter 14 Distributing Your Driver Read this chapter in the final stages of driver development. It will guide you in preparing your driver for distribution. 14.1 Getting a Valid License for WinDriver To purchase a WinDriver license, complete the WinDriver/docs/order.pdf order form and fax or email it to Jungo. Complete details are included on the order form. Alternatively, you can order WinDriver on-line. For more details, visit our web site: http://www.jungo.com.
14.2 Windows Driver Distribution 163 14.2 Windows Driver Distribution NOTES • For Windows 2000/XP/Server 2003/Vista, all references to wdreg in this section can be replaced with wdreg_gui, which offers the same functionality but displays GUI messages instead of console-mode messages. For Windows 98/Me, all references to wdreg should be replaced with wdreg16. For more information regarding the wdreg utility, see Chapter 13.
14.2 Windows Driver Distribution 164 Distributing the driver you created is a multi-step process. First, create a distribution package that includes all the files required for the installation of the driver on the target computer. Second, install the driver on the target machine. This involves installing windrvr6.sys and windrvr6.inf, installing the specific INF file for your device (for Plug-and-Play hardware – PCI/PCMCIA), and installing your Kernel PlugIn driver (if you have created one).
14.2 Windows Driver Distribution 165 14.2.2 Installing Your Driver on the Target Computer NOTE The user must have administrative privileges on the target computer in order to install your driver. Follow the instructions below in the order specified to properly install your driver on the target computer: • Preliminary Steps: – To avoid reboot, before attempting to install the driver make sure that there are no open handles to the windrvr6.sys service.
14.2 Windows Driver Distribution 166 • Install WinDriver’s kernel module: 1. Copy windrvr6.sys, windrvr6.inf and wd920.cat to the same directory. NOTE wd920.cat contains the driver’s Authenticode digital signature for Windows 2000/XP/Server 2003/Vista. In order to maintain the signature’s validity this file must be found in the same installation directory as the windrvr6.inf file.
14.2 Windows Driver Distribution 167 NOTE wdreg is an interactive utility. If it fails, it will display a message instructing the user how to overcome the problem. In some cases the user may be asked to reboot the computer. CAUTION! When distributing your driver, take care not to overwrite a newer version of windrvr6.sys with an older version of the file in Windows drivers directory (%windir%\system32\drivers).
14.2 Windows Driver Distribution 168 • Install wdapi920.dll: If your hardware control application/DLL uses wdapi920.dll (as is the case for the sample and generated DriverWizard WinDriver projects), copy this DLL to the target’s %windir%\system32 directory. If you are distributing a 32-bit application/DLL to a target 64-bit platform, rename wdapi920_32.dll to wdapi920.dll and copy this file to the target’s %windir%\sysWOW64 directory.
14.3 Windows CE Driver Distribution 169 usage, please refer to Chapter 13 (see specifically section 13.2.4 for Kernel PlugIn installation). 14.3 Windows CE Driver Distribution 14.3.1 Distribution to New Windows CE Platforms NOTE The following instructions apply to platform developers who build Windows CE kernel images using Windows CE Platform Builder or using MSDEV 2005 with the Windows CE 6.0 plugin. The instructions use the notation ”Windows CE IDE” to refer to either of these platforms.
14.3 Windows CE Driver Distribution 170 transfer the file to your target platform using a floppy disk. However, if you prefer to have the file windrvr6.dll loaded on demand via the CESH/PPSH services, you need to perform the manual integration method described in step 4 instead of performing the procedure described in the present step. (a) Run the Windows CE IDE and open your platform. (b) From the File menu select Manage Catalog Items.... and then click the Import... button and select the WinDriver.
14.3 Windows CE Driver Distribution 171 5. Select Make Run-Time Image from the Build menu and name the new image NK.BIN. 6. Download your new kernel to the target platform and initialize it either by selecting Download/Initialize from the Target menu or by using a floppy disk. 7. Restart your target CE platform. The WinDriver CE kernel will automatically load. 8. Install your hardware control application/DLL on the target. If your hardware control application/DLL uses wdapi920.
14.4 Linux Driver Distribution 172 3. Restart your target CE computer. The WinDriver CE kernel will automatically load. You will have to do a warm reset rather than just suspend/resume (use the reset or power button on your target CE computer). 4. Install your hardware control application/DLL on the target. If your hardware control application/DLL uses wdapi920.
14.4 Linux Driver Distribution 173 is used for kernels compiled with GCC v2.x.x, and windrvr_gcc_v3.a is used for kernels compiled with GCC v3.x.x. windrvr_gcc_v3_regparm.a is used for kernels compiled with GCC v3.x.x with the regparm flag. • linux_wrappers.c/h: wrapper library source code files that bind the WinDriver kernel module to the Linux kernel. • linux_common.h, windrvr.h, wd_ver.h and wdusb_interface.h: header files required for building the WinDriver kernel module on the target.
14.4 Linux Driver Distribution 174 wish to protect your source code from unauthorized copying) or as source code. Note that under the license agreement with Jungo you may not distribute the source code of the libwdapi920.so shared object. CAUTION! If you select to distribute your source code, make sure you do not distribute your WinDriver license string, which is used in the code. 14.4.
14.5 Solaris Driver Distribution 175 14.5 Solaris Driver Distribution NOTE If you have renamed the WinDriver kernel module (windrvr6), as explained in section 15.2, replace the relevant windrvr6 and windrvr references with the name of your driver, and replace references to the WinDriver redist/ and lib/ directories with the path to your copy of the relevant directory. For example, when using the generated DriverWizard renamed driver files for your driver project, as explained in section 15.2.3.
Chapter 15 Driver Installation – Advanced Issues 15.1 INF Files – Windows 98/Me/2000/XP/Server 2003/Vista Device information (INF) files are text files that provide information used by the Plug-and-Play mechanism in Windows 98/Me/2000/XP/Server 2003/Vista to install software that supports a given hardware device. INF files are required for hardware that identifies itself, such as USB and PCI. An INF file includes all necessary information about a device and the files to be installed.
15.1 INF Files – Windows 98/Me/2000/XP/Server 2003/Vista 177 15.1.1 Why Should I Create an INF File? • To stop the Windows Found New Hardware Wizard from popping up after each boot. • To ensure that the operating system can initialize the PCI configuration registers on Windows 98/Me/2000/XP/Server 2003/Vista. • To ensure that PCI interrupts are handled correctly. • To load the new driver created for the device.
15.1 INF Files – Windows 98/Me/2000/XP/Server 2003/Vista 178 and click the Update Driver... button. On Windows 2000/XP/Server 2003/Vista you can choose to upgrade the driver directly from the Properties list. In all the manual installation methods above you will need to point Windows to the location of the relevant INF file during the installation. We recommend using the wdreg utility to install the INF file automatically, instead of installing it manually.
15.1 INF Files – Windows 98/Me/2000/XP/Server 2003/Vista 179 15.1.3 How Do I Replace an Existing Driver Using the INF File? NOTE You must have administrative privileges in order to replace a driver on Windows 98/Me/2000/XP/Server 2003/Vista. 1.
15.1 INF Files – Windows 98/Me/2000/XP/Server 2003/Vista 180 In the manual installation methods above you will need to point Windows to the location of the relevant INF file during the installation. If the installation wizard offers to install an INF file other than the one you have generated, select Install one of the other drivers and choose your specific INF file from the list. We recommend using the wdreg utility to install the INF file automatically, instead of installing it manually.
15.2 Renaming the WinDriver Kernel Driver 181 15.2 Renaming the WinDriver Kernel Driver The WinDriver APIs are implemented within the windrvr6.sys/.dll/.o/.ko kernel driver module (depending on the OS), which provides the main driver functionality and enables you to code your specific driver logic from the user mode [1.6]. On Windows, Linux and Solaris you can change the name of the WinDriver kernel module to your preferred driver name, and then distribute the renamed driver instead of windrvr6.sys/.o/.
15.2 Renaming the WinDriver Kernel Driver 182 NOTES • References to the WinDriver\redist directory in this section can be replaced with WinDriver\redist_win98_compat. The redist\ directory contains a digitally signed, WHQL-compliant, windrvr6.sys driver and related files. The redist_win98_compat\ directory contains an unsigned non-WHQL compliant version of the driver for Windows 98/Me and higher. • Renaming the signed windrvr6.sys driver nullifies its signature.
15.2 Renaming the WinDriver Kernel Driver 183 – xxx_device.inf – A modified version of the standard generated DriverWizard INF file for your device, which registers your device with your driver (xxx.sys). You can make additional modifications to this file, if you wish, such as changing the manufacturer or driver provider strings. – wdapi920.dll – A copy of the WinDriver API DLL.
15.2 Renaming the WinDriver Kernel Driver 184 Note: The sample and generated DriverWizard WinDriver projects/makefiles already set this preprocessor flag by default. 4. Install your new driver by following the instructions in section 14.2 of the manual, using the modified files from the generated xxx_installation\ directory instead of the installation files from the original WinDriver distribution. 15.2.1.
15.2 Renaming the WinDriver Kernel Driver 185 3. Verify that your application calls the WD_DriverName() function [B.1] with your new driver name before calling any other WinDriver function. Note that the sample and generated DriverWizard WinDriver applications already include a call to this function, but with the default driver name (windrvr6), so all you need to do is replace the driver name that is passed to the function in the code with your new driver name. 4.
15.2 Renaming the WinDriver Kernel Driver 186 required modifications for building your xxx.o/.ko driver instead of windrvr6.o/.ko. • lib/ and include/ directories: Copies of the library and include directories from the original WinDriver distribution. These copies are created since the supported Linux WinDriver kernel driver build method relies on the existence of these directories directly under the same parent directory as the redist/ directory. 2.
15.2 Renaming the WinDriver Kernel Driver 187 build method relies on the existence of these directories directly under the same parent directory as the redist/ directory. 3. Verify that your application calls the WD_DriverName() function [B.1] with your new driver name before calling any other WinDriver function.
15.2 Renaming the WinDriver Kernel Driver 188 directory with the following files and directories: • redist/ directory: This directory provides modified versions of the files from the original WinDriver/redist directory – i.e. the windrvr6 kernel module and windrvr6.conf installation file – which have been modified to use your new driver name (xxx). • lib/ directory: This directory is simply a copy of the lib/ directory from the original WinDriver distribution.
15.3 Digital Driver Signing & Certification – Windows 2000/XP/Server 2003/Vista 189 Note: The copy of the lib/ directory should not be modified. This copy is created since the driver’s installation method relies on the existence of this directory directly under the same parent directory as the redist/ directory. 3. Verify that your application calls the WD_DriverName() function [B.1] with your new driver name before calling any other WinDriver function.
15.3 Digital Driver Signing & Certification – Windows 2000/XP/Server 2003/Vista 190 15.3.1.1 Authenticode Driver Signature The Microsoft Authenticode mechanism verifies the authenticity of driver’s provider. It allows driver developers to include information about themselves and their code with their programs through the use of digital signatures, and informs users of the driver that the driver’s publisher is participating in an infrastructure of trusted entities.
15.3 Digital Driver Signing & Certification – Windows 2000/XP/Server 2003/Vista 191 15.3.2 Driver Signing & Certification of WinDriver-Based Drivers As indicated above [15.3.1.1], The WinDriver\redist\windrvr6.sys driver has an Authenticode signature. Since WinDriver’s kernel module (windrvr6.sys) is a generic driver, which can be used as a driver for different types of hardware devices, it cannot be submitted as a stand-alone driver for WHQL certification.
15.3 Digital Driver Signing & Certification – Windows 2000/XP/Server 2003/Vista 192 (or your renamed driver) and any INF files used in your driver’s installation. – Assign the name of your new catalog file to the CatalogFile entry in your driver’s INF file(s). (You can either change the CatalogFile entry in the windrvr6.inf file to refer to your new catalog file, and add a similar entry in your device-specific INF file; or incorporate both windrvr6.
15.4 Windows XP Embedded WinDriver Component 193 • The tests submission requires you to provide a *.pdb debug symbol file and an ouput of the PREfast utility (defects.xml). You can find copies of these files for the windrvr6.sys driver in the WinDriver\redist directory. When selecting to rename and rebuild the windrvr6.sys driver module, as explained in section 15.2, a new debug symbols file is created for the driver. (The original defects.xml file is also applicable to the rebuilt driver).
15.4 Windows XP Embedded WinDriver Component 194 device’s hardware type and vendor and product IDs. For example, for a PCI device with vendor ID 0x1111 and product ID 0x2222: "my_dev_pci"=Install, PCI\VEN_1111&DEV_2222 OR: • Create an INF file for your device using DriverWizard [4.2 (3)] and name it dev.inf, or use an INF file from one of WinDriver’s enhanced-support chipsets [7] that suits your card and rename it to dev.inf. Then copy your dev.
Appendix A 64-bit Operating Systems Support A.1 Supported 64-bit Architectures WinDriver supports the following 64-bit platforms: • Solaris SPARC 64-bit. For a full list of Solaris platforms supported by WinDriver, refer to section 3.1.4. • Linux AMD64 or Intel EM64T (x86_64). For a full list of the Linux platforms supported by WinDriver, refer to section 3.1.3. • Windows AMD64 or Intel EM64T (x64). For a full list of the Windows platforms supported by WinDriver, refer to sections 3.1.1.1 and 3.1.1.2.
A.2 Support for 32-bit Applications on 64-bit Architectures A.2 196 Support for 32-bit Applications on 64-bit Architectures WinDriver for Solaris SPARC 64-bit, Linux AMD64 and Windows AMD64 support both 32-bit and 64-bit applications. In order to build a 32-bit application for one of these platforms, use any appropriate 32-bit compiler with the -DKERNEL_64BIT compilation flag. Note, however, that 64-bit applications are more efficient. A.
Appendix B API Reference NOTE This function reference is C oriented. The WinDriver .NET, Visual Basic and Delphi APIs have been implemented as closely as possible to the C APIs, therefore .NET, VB and Delphi programmers can also use this reference to better understand the WinDriver APIs for their selected development language. For the exact API implementation and usage examples for your selected language, refer to the WinDriver .NET/VB/Delphi source code.
B.1 WD_DriverName() 198 B.1 WD_DriverName() P URPOSE • Sets the name of the WinDriver kernel module, which will be used by the calling application. NOTE: • The default driver name, which is used if the function is not called, is windrvr6.
B.1 WD_DriverName() 199 P ROTOTYPE const char * DLLCALLCONV WD_DriverName ( c o n s t c h a r * sName ) ; PARAMETERS Name ➢ sName Type const char* Input/Output Input D ESCRIPTION Name sName Description The name of the WinDriver kernel module to be used by the application. NOTE: The driver name should be indicated without the driver file’s extension. For example, use windrvr6, not windrvr6.sys or windrvr6.o. R ETURN VALUE Returns the selected driver name on success; returns NULL on failure (e.g.
B.2 WDC Library Overview 200 B.2 WDC Library Overview The "WinDriver Card" – WDC – API provides convenient user-mode wrappers to the basic WinDriver PCI/ISA/PCMCIA/CardBus WD_xxx API, which is described in the WinDriver PCI Low-Level API Reference. The WDC wrappers are designed to simplify the usage of WinDriver for communicating with PCI/ISA/PCMCIA/CardBus devices.
B.3 WDC High Level API 201 B.3 WDC High Level API This section describes the WDC API defined in the WinDriver/include/wdc_lib.h header file. B.3.1 Structures, Types and General Definitions B.3.1.1 WDC_DEVICE_HANDLE Handle to a WDC device information structure [B.4.3] type: typedef void * WDC_DEVICE_HANDLE; B.3.1.
B.3 WDC High Level API 202 Name WDC_DRV_OPEN_KP WDC_DRV_OPEN_ALL WDC_DRV_OPEN_DEFAULT Description Convenience option when calling WDC_DriverOpen() [B.3.2] from the Kernel PlugIn. This option is equivalent to setting the WDC_DRV_OPEN_BASIC flag, which is the recommended option to set when opening a handle to the WDC library from the Kernel PlugIn. A convenience mask of all the basic WDC driver open flags – WDC_DRV_OPEN_CHECK_VER and WDC_DRV_OPEN_REG_REG_LIC.
B.3 WDC High Level API 203 B.3.1.4 WDC_ADDR_MODE Enumeration Enumeration of memory or I/O addresses/registers read/write modes. The enumeration values are used to determine whether a memory or I/O address/register is read/written in multiples of 8, 16, 32 or 64 bits (i.e. 1, 2, 4 or 8 bytes). Enum Value WDC_MODE_8 WDC_MODE_16 WDC_MODE_32 WDC_MODE_64 Description 8 bits (1 byte) mode 16 bits (2 bytes) mode 32 bits (4 bytes) mode 64 bits (8 bytes) mode B.3.1.
B.3 WDC High Level API 204 B.3.1.6 WDC_ADDR_SIZE Definitions typedef DWORD WDC_ADDR_SIZE; Preprocessor definitions that depict memory or I/O address/register sizes: Name WDC_SIZE_8 WDC_SIZE_16 WDC_SIZE_32 WDC_SIZE_64 Description 8 bits (1 byte) 16 bits (2 bytes) 32 bits (4 bytes) 64 bits (8 bytes) B.3.1.7 WDC_SLEEP_OPTIONS Definitions typedef DWORD WDC_SLEEP_OPTIONS; Preprocessor definitions depict the sleep options that can be passed to WDC_Sleep() [B.3.
B.3 WDC High Level API Name WDC_DBG_OUT_FILE 205 Description Send debug messages from the WDC library to a debug file. By default, the debug file will be stderr, unless a different file is set in the sDbgFile parameter of the WDC_SetDebugOptions() function [B.3.49]. This option is only supported from the user mode (as opposed to the Kernel PlugIn). The following flags determine the debug level – i.e.
B.3 WDC High Level API Name WDC_DBG_FULL 206 Description Full WDC debugging: • From the user mode: WDC_DBG_OUT_DBM | WDC_DBG_OUT_FILE | WDC_DBG_LEVEL_TRACE : Send WDC error and trace debug messages both to the Debug Monitor [6.2] and to a debug output file (default file: stderr) • From the Kernel PlugIn: WDC_DBG_OUT_DBM | WDC_DBG_LEVEL_TRACE : Send WDC error and trace messages to the Debug Monitor [6.
B.3 WDC High Level API 207 B.3.1.9 WDC_SLOT_U Union WDC PCI/PCMCIA device location information union type: Name ➢ pciSlot ➢ pcmciaSlot Type WD_PCI_SLOT WD_PCMCIA_SLOT Description PCI device location information structure [B.5.8] PCMCIA device location information structure [B.5.9] B.3.1.10 WDC_PCI_SCAN_RESULT Structure Structure type for holding the results of a PCI bus scan (see WDC_PciScanDevices() [B.3.
B.3 WDC High Level API 208 B.3.1.11 WDC_PCMCIA_SCAN_RESULT Structure Structure type for holding the results of a PCMCIA bus scan (see WDC_PcmciaScanDevices() [B.3.6]): Name ➢ dwNumDevices Type DWORD ➢ deviceId WD_PCMCIA_ID[WD_PCMCIA_CARDS] ➢ deviceSlot WD_PCMCIA_SLOT[WD_PCMCIA_CARDS] Description Number of devices found on the PCMCIA bus that match the search criteria (manufacturer & device IDs) Array of matching vendor and device IDs found on the PCMCIA bus [B.5.
B.3 WDC High Level API B.3.2 209 WDC_DriverOpen() P URPOSE • Opens and stores a handle to WinDriver’s kernel module and initializes the WDC library according to the open options passed to it. This function should be called once before calling any other WDC API.
B.3 WDC High Level API B.3.3 210 WDC_DriverClose() • Closes the WDC WinDriver handle (acquired and stored by a previous call to WDC_DriverOpen() [B.3.2]) and un-initializes the WDC library. Every WDC_DriverOpen() call should have a matching WDC_DriverClose() call, which should be issued when you no longer need to use the WDC library. P ROTOTYPE DWORD DLLCALLCONV WDC_DriverClose ( v o i d ) ; R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API B.3.4 211 WDC_PciScanDevices() P URPOSE • Scans the PCI bus for all devices with the specified vendor and device ID combination and returns information regarding the matching devices that were found and their location. The function performs the scan by iterating through all possible PCI buses on the host platform, then through all possible PCI slots, and then through all possible PCI functions.
B.3 WDC High Level API Name pPciScanResult 212 Description A pointer to a structure that will be updated by the function with the results of the PCI bus scan [B.3.1.10] R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9]. R EMARKS • If you set both the vendor and device IDs to zero will return, the function will return information regarding all connected PCI devices. B.3.
B.3 WDC High Level API 213 PARAMETERS Name ➢ dwVendorId ➢ dwDeviceId ➢ pPciScanResult Type DWORD DWORD WDC_PCI_SCAN_RESULT* Input/Output Input Input Output D ESCRIPTION Name dwVendorId dwDeviceId pPciScanResult Description Vendor ID to search for (hexadecimal). Zero (0) – all vendor IDs. Device ID to search for (hexadecimal). Zero (0) – all device IDs. A pointer to a structure that will be updated by the function with the results of the PCI bus scan [B.3.1.
B.3 WDC High Level API B.3.6 214 WDC_PcmciaScanDevices() P URPOSE • Scans the PCMCIA bus for all devices with the specified manufacturer and device ID combination and returns information regarding the matching devices that were found and their location.
B.3 WDC High Level API B.3.7 215 WDC_PciGetDeviceInfo() P URPOSE • Retrieves a PCI device’s resources information (memory and I/O ranges and interrupt information). P ROTOTYPE DWORD DLLCALLCONV WDC_PciGetDeviceInfo ( WD_PCI_CARD_INFO * p D e v i c e I n f o ) ; PARAMETERS Name ➢ pDeviceInfo ❏ pciSlot ❏ Card Type WD_PCI_CARD_INFO* WD_PCI_SLOT WD_CARD Input/Output Input/Output Input Output D ESCRIPTION Name pDeviceInfo Description Pointer to a PCI device information structure [B.5.
B.3 WDC High Level API B.3.8 216 WDC_PcmciaGetDeviceInfo() P URPOSE • Retrieves a PCMCIA device’s resources information (memory and I/O ranges and interrupt information).
B.3 WDC High Level API 217 R EMARKS • The resources information is obtained from the operating system’s Plug-and-Play manager, unless the information is not available, in which case it is read directly from the PCMCIA configuration registers. Note: On Windows, you must install an INF file, which registers your device with WinDriver, before calling this function (see section 15.1 regarding creation of INF files with WinDriver).
B.3 WDC High Level API B.3.9 218 WDC_PciDeviceOpen() P URPOSE • Allocates and initializes a WDC PCI device structure, registers the device with WinDriver, and returns a handle to the device. Among the operations performed by this function: • Verifies that a non-shareable memory or I/O resource on the device has not already been registered exclusively.
B.
B.3 WDC High Level API 220 D ESCRIPTION Name phDev pDeviceInfo pDevCtx reserved pcKPDriverName pKPOpenData Description Pointer to a handle to the WDC device allocated by the function Pointer to a PCI device information structure [B.5.12], which contains information regarding the device to open Pointer to device context information, which will be stored in the device structure Reserved for future use Kernel PlugIn driver name.
B.3 WDC High Level API 221 B.3.10 WDC_PcmciaDeviceOpen() P URPOSE • Allocates and initializes a WDC PCMCIA device structure, registers the device with WinDriver, and returns a handle to the device. Among the operations performed by this function: • Verifies that a non-shareable memory or I/O resource on the device has not already been registered exclusively.
B.
B.3 WDC High Level API 223 D ESCRIPTION Name phDev pDeviceInfo pDevCtx reserved pcKPDriverName pKPOpenData Description Pointer to a handle to the WDC device allocated by the function Pointer to a PCMCIA device information structure [B.5.13], which contains information regarding the device to open Pointer to device context information, which will be stored in the device structure Reserved for future use Kernel PlugIn driver name.
B.3 WDC High Level API 224 B.3.11 WDC_IsaDeviceOpen() P URPOSE • Allocates and initializes a WDC ISA device structure, registers the device with WinDriver, and returns a handle to the device. Among the operations performed by this function: • Verifies that a non-shareable memory or I/O resource on the device has not already been registered exclusively.
B.
B.3 WDC High Level API 226 D ESCRIPTION Name phDev pDeviceInfo pDevCtx reserved pcKPDriverName pKPOpenData Description Pointer to a handle to the WDC device allocated by the function Pointer to a card information structure [B.5.11], which contains information regarding the device to open Pointer to device context information, which will be stored in the device structure Reserved for future use Kernel PlugIn driver name.
B.3 WDC High Level API 227 B.3.12 WDC_PciDeviceClose() P URPOSE • Un-initializes a WDC PCI device structure and frees the memory allocated for it. P ROTOTYPE DWORD DLLCALLCONV WDC_PciDeviceClose (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a WDC PCI device structure, returned by WDC_PciDeviceOpen() [B.3.9] R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API 228 B.3.13 WDC_PcmciaDeviceClose() P URPOSE • Un-initializes a WDC PCMCIA device structure and frees the memory allocated for it. P ROTOTYPE DWORD DLLCALLCONV WDC_PcmciaDeviceClose (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a WDC PCMCIA device structure, returned by WDC_PcmciaDeviceOpen() [B.3.
B.3 WDC High Level API 229 B.3.14 WDC_IsaDeviceClose() P URPOSE • Un-initializes a WDC ISA device structure and frees the memory allocated for it. P ROTOTYPE DWORD DLLCALLCONV WDC_IsaDeviceClose (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a WDC ISA device structure, returned by WDC_IsaDeviceOpen() [B.3.11] R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API 230 B.3.15 WDC_CardCleanupSetup() P URPOSE • Sets a list of transfer cleanup commands to be performed for the specified card on any of the following occasions: • The application exists abnormally. • The application exits normally but without closing the specified card. • If the bForceCleanup parameter is set to TRUE, the cleanup commands will also be performed when the specified card is closed.
B.3 WDC High Level API 231 PARAMETERS Name ➢ hDev ➢ Cmd ➢ dwCmds ➢ bForceCleanup Type WDC_DEVICE_HANDLE WD_TRANSFER* DWORD BOOL Input/Output Input Input Input Input D ESCRIPTION Name hDev Cmd dwCmds bForceCleanup Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) Pointer to an array of cleanup transfer commands to be performed [B.5.
B.3 WDC High Level API 232 B.3.16 WDC_KernelPlugInOpen() P URPOSE • Opens a handle to a Kernel PlugIn driver. P ROTOTYPE DWORD DLLCALLCONV WDC_KernelPlugInOpen ( WDC_DEVICE_HANDLE hDev , c o n s t CHAR * pcKPDriverName , PVOID pKPOpenData ) ; PARAMETERS Name ➢ hDev ➢ pcKPDriverName ➢ pKPOpenData Type WDC_DEVICE_HANDLE const CHAR* PVOID Input/Output Input/Output Input Input D ESCRIPTION Name hDev pcKPDriverName pKPOpenData Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.
B.3 WDC High Level API 233 R EMARKS • Normally you do not need to call this function, since you can open a handle to a Kernel PlugIn driver when opening the handle to your device, as explained in the description of the WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]). This function is used for opening a handle to the Kernel PlugIn from a .NET application. The WinDriver Kernel PlugIn samples pass the address of the device handle to be allocated, i.e.
B.3 WDC High Level API 234 B.3.17 WDC_CallKerPlug() P URPOSE • Sends a message from a user-mode application to a Kernel PlugIn driver. The function passes a message ID from the application to the Kernel PlugIn’s KP_Call() [B.6.4] function, which should be implemented to handle the specified message ID, and returns the result from the Kernel PlugIn to the user-mode application.
B.3 WDC High Level API R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API 236 B.3.18 WDC_ReadMemXXX() P URPOSE • WDC_ReadMem8/16/32/64() reads 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, from a specified memory address. The address is read directly in the calling context (user mode / kernel mode).
B.3 WDC High Level API 237 B.3.19 WDC_WriteMemXXX() P URPOSE • WDC_WriteMem8/16/32/64() writes 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, to a specified memory address. The address is written to directly in the calling context (user mode / kernel mode).
B.3 WDC High Level API 238 B.3.20 WDC_ReadAddrXXX() P URPOSE • WDC_ReadAddr8/16/32/64() reads 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, from a specified memory or I/O address.
B.3 WDC High Level API 239 D ESCRIPTION Name hDev dwAddrSpace dwOffset val Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.
B.3 WDC High Level API 240 B.3.21 WDC_WriteAddrXXX() P URPOSE • WDC_WriteAddr8/16/32/64() writes 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, to a specified memory or I/O address.
B.3 WDC High Level API R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API 242 B.3.22 WDC_ReadAddrBlock() P URPOSE • Reads a block of data from the device.
B.3 WDC High Level API 243 D ESCRIPTION Name hDev dwAddrSpace dwOffset dwBytes pData mode options Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) The memory or I/O address space to read from The offset from the beginning of the specified address space (dwAddrSpace) to read from The number of bytes to read Pointer to a buffer to be filled with the data that is read from the device The read access mode – see WDC_ADDR_MODE [B.3.1.
B.3 WDC High Level API 244 B.3.23 WDC_WriteAddrBlock() P URPOSE • Writes a block of data to the device.
B.3 WDC High Level API 245 D ESCRIPTION Name hDev dwAddrSpace dwOffset dwBytes pData mode options Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) The memory or I/O address space to write to The offset from the beginning of the specified address space (dwAddrSpace) to write to The number of bytes to write Pointer to a buffer that holds the data to write to the device The write access mode – see WDC_ADDR_MODE [B.3.1.
B.3 WDC High Level API 246 B.3.24 WDC_MultiTransfer() P URPOSE • Performs a group of memory and/or I/O read/write transfers. P ROTOTYPE DWORD DLLCALLCONV WDC_MultiTransfer ( WD_TRANSFER * p T r a n s , DWORD dwNumTrans ) ; PARAMETERS Name ➢ pTrans ➢ dwNumTrans Type WD_TRANSFER* DWORD Input/Output Input D ESCRIPTION Name pTrans dwNumTrans Description Pointer to an array of transfer commands information structures [B.5.
B.3 WDC High Level API 247 B.3.25 WDC_AddrSpaceIsActive() P URPOSE • Checks if the specified memory or I/O address space is active – i.e. if its size is not zero. P ROTOTYPE BOOL DLLCALLCONV WDC_AddrSpaceIsActive ( WDC_DEVICE_HANDLE hDev , DWORD dwAddrSpace ) ; PARAMETERS Name ➢ hDev ➢ dwAddrSpace Type WDC_DEVICE_HANDLE DWORD Input/Output Input Input D ESCRIPTION Name hDev dwAddrSpace Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.
B.3 WDC High Level API 248 B.3.26 WDC_PciReadCfgBySlot() P URPOSE • Reads data from a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. The device is identified by its location on the PCI bus. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+). On such platforms, all references to ”PCI” in the description below also include PCI Express.
B.3 WDC High Level API 249 D ESCRIPTION Name pPciSlot dwOffset pData dwBytes Description Pointer to a PCI device location information structure [B.5.8], which can be acquired by calling WDC_PciScanDevices() [B.3.
B.3 WDC High Level API 250 B.3.27 WDC_PciWriteCfgBySlot() P URPOSE • Write data to a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. The device is identified by its location on the PCI bus. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+). On such platforms, all references to ”PCI” in the description below also include PCI Express.
B.3 WDC High Level API 251 D ESCRIPTION Name pPciSlot dwOffset pData dwBytes Description Pointer to a PCI device location information structure [B.5.8], which can be acquired by calling WDC_PciScanDevices() [B.3.4] The offset from the beginning of the PCI configuration space to write to Pointer to a data buffer that holds the data to write The number of bytes to write R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.3 WDC High Level API 252 B.3.28 WDC_PciReadCfg() P URPOSE • Reads data from a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+). On such platforms, all references to ”PCI” in the description below also include PCI Express.
B.3 WDC High Level API 253 B.3.29 WDC_PciWriteCfg() P URPOSE • Writes data to a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+). On such platforms, all references to ”PCI” in the description below also include PCI Express.
B.3 WDC High Level API 254 B.3.30 WDC_PciReadCfgBySlotXXX() P URPOSE • WDC_PciReadCfgBySlot8/16/32/64() reads 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, from a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. The device is identified by its location on the PCI bus. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g.
B.3 WDC High Level API 255 PARAMETERS Name ➢ pPciSlot ➢ dwOffset ➢ val Type WD_PCI_SLOT* DWORD BYTE* / WORD* / UINT32* / UINT64* Input/Output Input Input Output D ESCRIPTION Name pPciSlot dwOffset val Description Pointer to a PCI device location information structure [B.5.8], which can be acquired by calling WDC_PciScanDevices() [B.3.
B.3 WDC High Level API 256 B.3.31 WDC_PciWriteCfgBySlotXXX() P URPOSE • WDC_PciWriteCfgBySlot8/16/32/64() writes 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, to a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. The device is identified by its location on the PCI bus. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g.
B.3 WDC High Level API 257 PARAMETERS Name ➢ pPciSlot ➢ dwOffset ➢ val Type WD_PCI_SLOT* DWORD BYTE / WORD / UINT32 / UINT64 Input/Output Input Input Input D ESCRIPTION Name pPciSlot dwOffset val Description Pointer to a PCI device location information structure [B.5.8], which can be acquired by calling WDC_PciScanDevices() [B.3.
B.3 WDC High Level API 258 B.3.32 WDC_PciReadCfgXXX() P URPOSE • WDC_PciReadCfg8/16/32/64() reads 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, from a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space . Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+).
B.3 WDC High Level API 259 PARAMETERS Name ➢ hDev ➢ dwOffset ➢ val Type WDC_DEVICE_HANDLE DWORD BYTE* / WORD* / UINT32* / UINT64* Input/Output Input Input Output D ESCRIPTION Name hDev dwOffset val Description Handle to a WDC PCI device structure, returned by WDC_PciDeviceOpen() [B.3.
B.3 WDC High Level API 260 B.3.33 WDC_PciWriteCfgXXX() P URPOSE • WDC_PciWriteCfg8/16/32/64() writes 1 byte (8 bits) / 2 bytes (16 bits) / 4 bytes (32 bits) / 8 bytes (64 bits), respectively, to a specified offset in a PCI device’s configuration space or a PCI Express device’s extended configuration space. Access to the PCI Express extended configuaration space is supported on target platforms that support such access (e.g. Windows, Linux, Solaris 10+).
B.3 WDC High Level API 261 PARAMETERS Name ➢ hDev ➢ dwOffset ➢ val Type WDC_DEVICE_HANDLE DWORD BYTE / WORD / UINT32 / UINT64 Input/Output Input Input Input D ESCRIPTION Name hDev dwOffset val Description Handle to a WDC PCI device structure, returned by WDC_PciDeviceOpen() [B.3.9] The offset from the beginning of the PCI configuration space to read from The data to write to the PCI configuration space R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.
B.3 WDC High Level API 262 B.3.34 WDC_PcmciaReadAttribSpace() P URPOSE • Reads data from a specified offset in a PCMCIA device’s attribute space.
B.3 WDC High Level API 263 B.3.35 WDC_PcmciaWriteAttribSpace() P URPOSE • Writes data to a specified offset in a PCMCIA device’s attribute space.
B.3 WDC High Level API 264 B.3.36 WDC_PcmciaSetWindow() P URPOSE • Modifies the settings of the PCMCIA bus controller’s memory window.
B.3 WDC High Level API 265 B.3.37 WDC_PcmciaSetVpp() P URPOSE • Modifies the power level of the PCMCIA bus controller’s Voltage Power Pin (Vpp). P ROTOTYPE DWORD DLLCALLCONV WDC_PcmciaSetVpp ( WDC_DEVICE_HANDLE hDev , WD_PCMCIA_VPP vpp ) ; PARAMETERS Name ➢ hDev ➢ vpp Type WDC_DEVICE_HANDLE WD_PCMCIA_VPP Input/Output Input Input D ESCRIPTION Name hDev vpp Description Handle to a WDC PCMCIA device structure, returned by WDC_PcmciaDeviceOpen() [B.3.
B.3 WDC High Level API 266 B.3.38 WDC_DMAContigBufLock() P URPOSE • Allocates a DMA buffer and returns mappings of the allocated buffer to physical address space and to user-mode and kernel virtual address spaces.
B.3 WDC High Level API 267 D ESCRIPTION Name hDev ppBuf dwOptions dwDMABufSize ppDma Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]). NOTE: This field can also be set to NULL in order to lock a contiguous physical memory buffer with no relation to a specific device.
B.3 WDC High Level API 268 R EMARKS • When calling this function you do not need to set the DMA_KERNEL_BUFFER_ALLOC flag, since the function sets this flag automatically. • This function is currently only supported from the user mode. • On Solaris x86 platforms, for an allocation of a Contiguous DMA Buffer that is larger than the physical page size (4K), call WDC_DMAContigBufLock() with the DMA_KERNEL_ONLY_MAP flag (set within the dwOptions parameter).
B.3 WDC High Level API 269 B.3.39 WDC_DMASGBufLock() P URPOSE • Locks a pre-allocated user-mode memory buffer for DMA and returns the corresponding physical mappings of the locked DMA pages. On Windows 98/Me/2000/XP/Server 2003/Vista the function also returns a kernel-mode mapping of the buffer.
B.3 WDC High Level API Name dwOptions dwDMABufSize ppDma 270 Description A bit mask of any of the following flags (defined in an enumeration in windrvr.h): • DMA_FROM_DEVICE: Synchronize the DMA buffer for transfers from the device to memory. • DMA_TO_DEVICE: Synchronize the DMA buffer for transfers from memory to the device. • DMA_TO_FROM_DEVICE: Synchronize the DMA buffer for transfers in both directions – i.e.
B.3 WDC High Level API 271 B.3.40 WDC_DMABufUnlock() P URPOSE • Unlocks and frees the memory allocated for a DMA buffer by a previous call to WDC_DMAContigBufLock() [B.3.38] or WDC_DMASGBufLock() [B.3.39]. P ROTOTYPE DWORD DLLCALLCONV WDC_DMABufUnlock (WD_DMA * pDma ) ; PARAMETERS Name ➢ pDma Type WD_DMA* Input/Output Input D ESCRIPTION Name pDma Description Pointer to a DMA information structure [B.5.14], received from a previous call to WDC_DMAContigBufLock() [B.3.
B.3 WDC High Level API 272 B.3.41 WDC_DMASyncCpu() P URPOSE • Synchronizes the cache of all CPUs with the DMA buffer, by flushing the data from the CPU caches. NOTE: This function should be called before performing a DMA transfer (see Remarks below). P ROTOTYPE DWORD DLLCALLCONV WDC_DMASyncCpu(WD_DMA * pDma ) ; PARAMETERS Name ➢ pDma Type WD_DMA* Input/Output Input D ESCRIPTION Name pDma Description Pointer to a DMA information structure [B.5.
B.3 WDC High Level API 273 R EMARKS • An asynchronous DMA read or write operation accesses data in memory, not in the processor (CPU) cache, which resides between the CPU and the host’s physical memory. Unless the CPU cache has been flushed, by calling WDC_DMASyncCpu(), just before a read transfer, the data transferred into system memory by the DMA operation could be overwritten with stale data if the CPU cache is flushed later.
B.3 WDC High Level API 274 B.3.42 WDC_DMASyncIo() P URPOSE • Synchronizes the I/O caches with the DMA buffer, by flushing the data from the I/O caches and updating the CPU caches. NOTE: This function should be called after performing a DMA transfer (see Remarks below).
B.3 WDC High Level API 275 R EMARKS • After a DMA transfer has been completed, the data can still be in the I/O cache, which resides between the host’s physical memory and the bus-master DMA device, but not yet in the host’s main memory. If the CPU accesses the memory, it might read the wrong data from the CPU cache.
B.3 WDC High Level API 276 B.3.43 WDC_IntEnable() P URPOSE • Enables interrupt handling for the device. • If the caller selects to handle the interrupts in the kernel, using a Kernel PlugIn driver, the Kernel PlugIn KP_IntAtIrql() function [B.6.8], which runs at high IRQ (Interrupt Request) level, will be invoked immediately when an an interrupt is received.
B.3 WDC High Level API 277 PARAMETERS Name ➢ hDev ➢ pTransCmds ➢ dwNumCmds ➢ dwOptions ➢ funcIntHandler ➢ pData ➢ fUseKP Type WDC_DEVICE_HANDLE WD_TRANSFER* DWORD DWORD typedef void (*INT_HANDLER)( PVOID pData); PVOID BOOL Input/Output Input Input Input Input Input Input Input D ESCRIPTION Name hDev pTransCmds Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.
B.3 WDC High Level API Name funcIntHandler pData fUseKP 278 Description A user-mode interrupt handler callback function, which will be executed after an interrupt is received and processed in the kernel. (The prototype of the interrupt handler – INT_HANDLER – is defined in windrvr_int_thread.h). Data for the user-mode interrupt handler callback routine (funcIntHandler) If TRUE – The device’s Kernel PlugIn driver’s KP_IntAtIrql() function [B.6.
B.3 WDC High Level API 279 • A successful call to this function must be followed with a call to WDC_IntDisable() later on in the code, in order to disable the interrupts. The WDC_xxxDriverClose() functions (PCI: [B.3.12], PCMCIA: [B.3.13], ISA: [B.3.14]) call WDC_IntDisable() if the device’s interrupts are enabled. B.3.44 WDC_IntDisable() P URPOSE • Disables interrupt interrupt handling for the device, pursuant to a previous call to WDC_IntEnable() [B.3.43].
B.3 WDC High Level API 280 B.3.45 WDC_IntIsEnabled() P URPOSE • Checks if a device’s interrupts are currently enabled. P ROTOTYPE BOOL DLLCALLCONV WDC_IntIsEnabled (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) R ETURN VALUE Returns TRUE if the device’s interrupts are enabled; otherwise returns FALSE.
B.3 WDC High Level API 281 B.3.46 WDC_EventRegister() P URPOSE • Registers the application to receive Plug-and-Play and power management events notifications for the device.
B.3 WDC High Level API 282 D ESCRIPTION Name hDev dwActions funcEventHandler pData Description Handle to a Plug-and-Play WDC device, returned by WDC_PciDeviceOpen() [B.3.9] or WDC_PcmciaDeviceOpen() [B.3.
B.3 WDC High Level API Name fUseKP 283 Description If TRUE – When an event for which the caller registered to receive notifications (dwActions) occurs, the device’s Kernel PlugIn driver’s KP_Event() function [B.6.5] will be called. (The Kernel PlugIn driver to be used for the device is passed to WDC_xxxDeviceOpen() and stored in the WDC device structure).
B.3 WDC High Level API 284 B.3.47 WDC_EventUnregister() P URPOSE • Un-registers an application from a receiving Plug-and-Play and power management notifications for a device, pursuant to a previous call to WDC_EventRegister() [B.3.46]. P ROTOTYPE DWORD DLLCALLCONV W D C _ E v e n t U n r e g ist er (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a Plug-and-Play WDC device, returned by WDC_PciDeviceOpen() [B.3.
B.3 WDC High Level API 285 B.3.48 WDC_EventIsRegistered() P URPOSE • Checks if the application is currently registered to receive Plug-and-Play and power management notifications for the device. P ROTOTYPE BOOL DLLCALLCONV W D C _ E v e n t I s R e g i s t e r e d (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a Plug-and-Play WDC device, returned by WDC_PciDeviceOpen() [B.3.9] or WDC_PcmciaDeviceOpen() [B.3.
B.3 WDC High Level API 286 B.3.49 WDC_SetDebugOptions() P URPOSE • Sets debug options for the WDC library – see the description of WDC_DBG_OPTIONS [B.3.1.8] for details regarding the possible debug options to set. • This function is typically called at the beginning of the application, after the call to WDC_DriverOpen() [B.3.2], and can be re-called at any time while the WDC library is in use (i.e. WDC_DriverClose() [B.3.3] has not been called) in order to change the debug settings.
B.3 WDC High Level API 287 D ESCRIPTION Name dbgOptions sDbgFile Description A bit mask of flags indicating the desired debug settings – see WDC_DBG_OPTIONS [B.3.1.8]. If this parameter is set to zero, the default debug options will be used – see WDC_DBG_DEFAULT [B.3.1.8]. WDC debug output file. This parameter is relevant only if the WDC_DBG_OUT_FILE flag is set in the debug options (dbgOptions) (either directly or via one of the convenience debug options combinations – see WDC_DBG_OPTIONS [B.3.1.8]).
B.3 WDC High Level API 288 B.3.50 WDC_Err() P URPOSE • Displays debug error messages according to the WDC debug options – see WDC_DBG_OPTIONS [B.3.1.8] and WDC_SetDebugOptions() [B.3.49]. P ROTOTYPE v o i d DLLCALLCONV WDC_Err ( c o n s t CHAR * f o r m a t [ , argument ] . . . ) ; PARAMETERS Name ➢ format ➢ argument Type const CHAR* Input/Output Input Input D ESCRIPTION Name format argument R ETURN VALUE None Description Format-control string, which contains the error message to display.
B.3 WDC High Level API 289 B.3.51 WDC_Trace() P URPOSE • Displays debug trace messages according to the WDC debug options – see WDC_DBG_OPTIONS [B.3.1.8] and WDC_SetDebugOptions() [B.3.49]. P ROTOTYPE v o i d DLLCALLCONV WDC_Trace ( c o n s t CHAR * f o r m a t [ , argument ] . . . ) ; PARAMETERS Name ➢ format ➢ argument Type const CHAR* Input/Output Input Input D ESCRIPTION Name format argument R ETURN VALUE None Description Format-control string, which contains the trace message to display.
B.3 WDC High Level API 290 B.3.52 WDC_GetWDHandle() P URPOSE • Returns a handle to WinDriver’s kernel module, which is required by the basic WD_xxx WinDriver PCI/PCMCIA/ISA API, described in the WinDriver PCI Low-Level API Reference (see Remarks below).
B.3 WDC High Level API 291 B.3.53 WDC_GetDevContext() P URPOSE • Returns the device’s user context information. P ROTOTYPE PVOID DLLCALLCONV WDC_GetDevContext (WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) R ETURN VALUE Returns a pointer to the device’s user context, or NULL if not context has been set.
B.3 WDC High Level API 292 B.3.54 WDC_GetBusType() P URPOSE • Returns the device’s bus type: WD_BUS_PCI, WD_BUS_PCMCIA, WD_BUS_ISA or WD_BUS_UNKNOWN. P ROTOTYPE WD_BUS_TYPE DLLCALLCONV WDC_GetBusType(WDC_DEVICE_HANDLE hDev ) ; PARAMETERS Name ➢ hDev Type WDC_DEVICE_HANDLE Input/Output Input D ESCRIPTION Name hDev R ETURN VALUE Returns the device’s bus type [B.5.1]. Description Handle to a WDC device, returned by WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.
B.3 WDC High Level API 293 B.3.55 WDC_Sleep() P URPOSE • Delays execution for the specified duration of time (in microseconds). By default the function performs a busy sleep (consumes the CPU). P ROTOTYPE DWORD DLLCALLCONV WDC_Sleep ( DWORD dwMicroSecs , WDC_SLEEP_OPTIONS o p t i o n s ) ; PARAMETERS Name ➢ dwMicroSecs ➢ options Type DWORD WDC_SLEEP_OPTIONS D ESCRIPTION Name dwMicroSecs options Description The number of microseconds to sleep Sleep options [B.3.1.
B.3 WDC High Level API 294 B.3.56 WDC_Version() P URPOSE • Returns the version number of the WinDriver kernel module used by the WDC library. P ROTOTYPE DWORD DLLCALLCONV WDC_Version ( CHAR * s V e r s i o n , DWORD * p d w V e r s i o n ) ; PARAMETERS Name ➢ sVersion ➢ pdwVersion Type CHAR* DWORD* Input/Output Output Output D ESCRIPTION Name sVersion pdwVersion Description Pointer to a pre-allocated buffer to be filled by the function with the driver’s version information string.
B.4 WDC Low Level API 295 B.4 WDC Low Level API This section described the WDC types and preprocessor definitions defined in the WinDriver/include/wdc_defs.h header file. B.4.1 WDC_ID_U Union WDC device ID information union type (used for PCI and PCMCIA devices): Name ➢ pciId ➢ pcmciaId B.4.2 Type WD_PCI_ID WD_PCMCIA_ID Description PCI device ID information structure [B.5.6] PCMCIA device ID information structure [B.5.
B.4 WDC Low Level API 296 Name ➢ dwUserDirectMemAddr B.4.3 Type UPTR Description The user-mode mapping of a memory address space’s physical base address. This address is used for accessing memory addresses directly from the user mode WDC_DEVICE Structure PCI/PCMCIA/ISA device information structure type. The WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) allocate and return device structures of this type.
B.4 WDC Low Level API 297 Name ➢ hIntThread Type DWORD ➢ Event WD_EVENT ➢ hEvent HANDLE ➢ pCtx PVOID B.4.4 PWDC_DEVICE Pointer to a WDC_DEVICE structure [B.4.3] type: typedef WDC_DEVICE *PWDC_DEVICE Description Handle to the interrupt thread that is spawn when interrupts are enabled. This handle is passed by WDC to the low-level WinDriver interrupt APIs. When using the WDC API you do not need to access this handle directly.
B.4 WDC Low Level API B.4.5 298 WDC_MEM_DIRECT_ADDR Macro P URPOSE • Utility macro that returns a pointer that can be used for direct access to a specified memory address space from the context of the calling process. P ROTOTYPE WDC_MEM_DIRECT_ADDR ( pAddrDesc ) PARAMETERS Name ➢ pAddrDesc Type WDC_ADDR_DESC* Input/Output Input D ESCRIPTION Name pAddrDesc Description Pointer to a WDC memory address space information structure [B.4.
B.4 WDC Low Level API B.4.6 299 WDC_ADDR_IS_MEM Macro P URPOSE • Utility macro that checks if a given address space is a memory or I/O address space. P ROTOTYPE WDC_ADDR_IS_MEM( pAddrDesc ) PARAMETERS Name ➢ pAddrDesc Type WDC_ADDR_DESC* Input/Output Input D ESCRIPTION Name pAddrDesc Description Pointer to a WDC memory address space information structure [B.4.2] R ETURN VALUE Returns pAddrDesc->fIsMemory, which is set to TRUE for a memory address space and to FALSE otherwise.
B.4 WDC Low Level API B.4.7 300 WDC_GET_ADDR_DESC Macro P URPOSE • Utility macro that retrieves a WDC address space information structure (WDC_ADDR_DESC [B.4.2]), which complies to the specified address space number. P ROTOTYPE WDC_GET_ADDR_DESC( pDev , dwAddrSpace ) PARAMETERS Name ➢ pDev ➢ dwAddrSpace Type PWDC_DEVICE DWORD Input/Output Input Input D ESCRIPTION Name pDev dwAddrSpace Description Pointer to a WDC device information structure [B.4.
B.4 WDC Low Level API B.4.8 301 WDC_GET_ENABLED_INT_TYPE Macro P URPOSE • Utility macro for retrieving the value of a WDC device’s dwEnabledIntType WD_INTERRUPT field. This field is updated by WDC_IntEnable() [B.3.43] to indicate the interupt type enabled for the device, as detailed in the description of the macro’s return value below.
B.4 WDC Low Level API B.4.9 302 WDC_IS_KP Macro P URPOSE • Utility macro that checks if a WDC device uses a Kernel PlugIn driver. P ROTOTYPE WDC_IS_KP ( pDev ) PARAMETERS Name ➢ pDev Type PWDC_DEVICE Input/Output Input D ESCRIPTION Name pDev Description Pointer to a WDC device information structure [B.4.4] R ETURN VALUE Returns TRUE if the device uses a Kernel PlugIn driver; otherwise returns FALSE.
B.5 WD_xxx Structures, Types and General Definitions B.5 WD_xxx Structures, Types and General Definitions This section describes basic WD_xxx structures and types, which are used by the WDC_xxx APIs. The APIs described in this section are defined in the WinDriver/include/windrvr.h header file. B.5.1 WD_BUS_TYP Enumeration Bus types enumeration: Enum Value WD_BUS_USB WD_BUS_UNKNOWN WD_BUS_ISA WD_BUS_EISA WD_BUS_PCI WD_BUS_PCMCIA B.5.
B.5 WD_xxx Structures, Types and General Definitions B.5.3 304 WD_PCMCIA_ACC_SPEED Enumeration Enumeration of PCMCIA bus access speeds: Enum Value WD_PCMCIA_ACC_SPEED_DEFAULT WD_PCMCIA_ACC_SPEED_250NS WD_PCMCIA_ACC_SPEED_200NS WD_PCMCIA_ACC_SPEED_150NS WD_PCMCIA_ACC_SPEED_1000NS B.5.
B.5 WD_xxx Structures, Types and General Definitions B.5.6 WD_PCI_ID Structure PCI device identification information structure: Name ➢ dwVendorId ➢ dwDeviceId B.5.7 Type DWORD DWORD Description Vendor ID Device ID WD_PCMCIA_ID Structure PCMCIA device identification information structure: Name ➢ wManufacturerId ➢ wCardId B.5.
B.5 WD_xxx Structures, Types and General Definitions B.5.9 306 WD_PCMCIA_SLOT Structure PCMCIA device location information structure: Name ➢ uBus ➢ uSocket ➢ uFunction Type BYTE BYTE BYTE Description PCMCIA Bus number (0 based) Socket number (0 based) Function number (0 based) B.5.10 WD_ITEMS Structure Card resources information structure: Name ➢ item Type DWORD ➢ fNotSharable DWORD Description Item type – see the ITEM_TYPE enumeration [B.5.2].
B.5 WD_xxx Structures, Types and General Definitions Name ➢ dwOptions Type DWORD ➢ I union ❏ Mem struct 307 Description A bit-mask of item registration flags, applicable when calling one of the WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) or the low-level WD_CardRegister() function (see the WinDriver PCI Low-Level API Reference).
B.5 WD_xxx Structures, Types and General Definitions Name ✦ dwPhysicalAddr Type DWORD ✦ dwBytes DWORD ✦ dwTransAddr DWORD ✦ dwUserDirectAddr DWORD 308 Description First address of the physical memory range. This field is updated by the WDC_XXXGetDeviceInfo() functions (PCI: [B.3.7]; PCMCIA: [B.3.8]) or the low-level WD_PciGetCardInfo() and WD_PcmciaGetCardInfo() functions (see the WinDriver PCI Low-Level API Reference). Length (in bytes) of the memory range.
B.5 WD_xxx Structures, Types and General Definitions Name ✦ dwCpuPhysicalAddr Type DWORD ✦ dwBar DWORD ❏ IO ✦ dwAddr struct DWORD ✦ dwBytes DWORD 309 Description Translation of the card’s physical memory base address (dwPhysicalAddr) from bus-specific values to CPU values. This field is updated by WD_CardRegister() (see the WinDriver PCI Low-Level API Reference), which is called from the WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]). Base Address Register (BAR) number.
B.5 WD_xxx Structures, Types and General Definitions Name ✦ dwBar ❏ Int ✦ dwInterrupt Type DWORD struct DWORD 310 Description Base Address Register (BAR) number. This field is updated by the WDC_XXXGetDeviceInfo() functions (PCI: [B.3.7]; PCMCIA: [B.3.8]) or the low-level WD_PciGetCardInfo() and WD_PcmciaGetCardInfo() functions (see the WinDriver PCI Low-Level API Reference). Interrupt item data (item = ITEM_INTERRUPT) Physical interrupt request (IRQ) number.
B.5 WD_xxx Structures, Types and General Definitions Name ✦ dwOptions Type DWORD 311 Description Interrupt bit-mask, which can consist of a combination of any of the following flags: Interrupt type flags: • INTERRUPT_MESSAGE_X – Indicates that the hardware supports Extended Message-Signaled Interrups (MSI-X). This option is applicable only to PCI cards on Linux – see information in section 9.2.3. • INTERRUPT_MESSAGE – On Linux, indicates that the hardware supports Message-Signaled Interrups (MSI).
B.5 WD_xxx Structures, Types and General Definitions Name ✦ dwOptions (continued) Type DWORD 312 Description NOTES: • For Plug-and-Play hardware (PCI/PCMCIA), use WinDriver’s WDC_PciGetDeviceInfo() [B.3.7] (PCI) or WDC_PcmciaGetDeviceInfo() [B.3.8] (PCMCIA) function (or the low-level WD_PciGetCardInfo() or WD_PcmciaGetCardInfo() function) to retrieve the Plug-and-Play hardware information, including the supported interrupt types.
B.5 WD_xxx Structures, Types and General Definitions Name ✦ hInterrupt ❏ Bus ✦ dwBusType ✦ dwBusNum ✦ dwSlotFunc ➢ Val Type DWORD WD_BUS WD_BUS_TYPE DWORD DWORD struct 313 Description Handle to an internal WinDriver interrupt structure, required by the low-level WD_xxx() WinDriver interrupt APIs (see the WinDriver PCI Low-Level API Reference). This field is updated by WD_CardRegister() (see the WinDriver PCI Low-Level API Reference), which is called from the WDC_xxxDeviceOpen() functions (PCI [B.3.
B.5 WD_xxx Structures, Types and General Definitions 314 B.5.11 WD_CARD Structure Card information structure: Name ➢ dwItems ➢ Item Type DWORD WD_ITEMS [WD_CARD_ITEMS] Description Number of items (resources) on the card Array of card resources (items) information structures [B.5.10] B.5.12 WD_PCI_CARD_INFO Structure PCI card information structure: Name ➢ pciSlot Type WD_PCI_SLOT ➢ Card WD_CARD Description PCI device location information structure [B.5.
B.5 WD_xxx Structures, Types and General Definitions 315 B.5.13 WD_PCMCIA_CARD_INFO Structure PCMCIA card information structure: Name ➢ pcmciaSlot Type WD_PCMCIA_SLOT ➢ Card ➢ cVersion WD_CARD CHAR [WD_PCMCIA_VERSION_LEN] CHAR [WD_PCMCIA_ MANUFACTURER_LEN] CHAR [WD_PCMCIA_ PRODUCTNAME_LEN] WORD WORD WORD ➢ cManufacturer ➢ cProductName ➢ wManufacturerId ➢ wCardId ➢ wFuncId Description PCMCIA device location information structure [B.5.9], which can be acquired by calling WDC_PcmciaScanDevices() [B.3.
B.5 WD_xxx Structures, Types and General Definitions 316 B.5.14 WD_DMA Structure Direct Memory Access (DMA) information structure: Name ➢ hDma Type DWORD ➢ pUserAddr PVOID ➢ pKernelAddr KPTR ➢ dwBytes ➢ dwOptions DWORD DWORD Description DMA buffer handle (or 0 for a failed allocation). This handle is returned from WDC_DMAContigBufLock() [B.3.38] and WDC_DMASGBufLock() [B.3.
B.5 WD_xxx Structures, Types and General Definitions Name ➢ dwOptions (continued) Type DWORD 317 Description DMA flags: • DMA_FROM_DEVICE: Synchronize the DMA buffer for transfers from the device to memory. • DMA_TO_DEVICE: Synchronize the DMA buffer for transfers from memory to the device. • DMA_TO_FROM_DEVICE: Synchronize the DMA buffer for transfers in both directions – i.e. from the device to memory and from memory to the device (<=> DMA_FROM_DEVICE | DMA_TO_DEVICE).
B.5 WD_xxx Structures, Types and General Definitions Name ➢ dwPages Type DWORD ➢ hCard DWORD ➢ Page WD_DMA_PAGE [WD_DMA_PAGES] ❏ pPhysicalAddr ❏ dwBytes KPTR DWORD 318 Description Number of physical memory blocks used for the allocated buffer. For Contiguous Buffer DMA this field is always set to 1.
B.5 WD_xxx Structures, Types and General Definitions Name ➢ cmdTrans (continued) Type DWORD ➢ dwPort KPTR ➢ dwBytes DWORD 319 Description • CMD_MASK: This command is applicable when passing interrupt transfer commands to the interrupt enable functions (WDC_IntEnable() [B.3.43] or the low-level InterruptEnable() or WD_IntEnable() functions – see the WinDriver PCI Low-Level API Reference).
B.5 WD_xxx Structures, Types and General Definitions Name ➢ fAutoinc Type DWORD ➢ dwOptions ➢ Data DWORD union ❏ ❏ ❏ ❏ ❏ Byte Word Dword Qword pBuffer BYTE WORD UINT32 UINT64 PVOID 320 Description Relevant only for string (block) transfers: If TRUE, the I/O or memory port/address will be incremented after each block that is transferred; If FALSE, all data is transferred to/from the same port/address.
B.6 Kernel PlugIn Kernel-Mode Functions 321 B.6 Kernel PlugIn Kernel-Mode Functions The following functions are callback functions which are implemented in your Kernel PlugIn driver, and which will be called when their calling event occurs. For example: KP_Init() [B.6.1] is the callback function that is called when the driver is loaded. Any code that you want to execute upon loading should be in this function. KP_Init() sets the name of the driver and the KP_Open() function.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.1 322 KP_Init() P URPOSE • Called when the Kernel PlugIn driver is loaded. Sets the name of the Kernel PlugIn driver and the KP_Open() [B.6.2] callback function.
B.6 Kernel PlugIn Kernel-Mode Functions 323 R ETURN VALUE TRUE if successful. Otherwise FALSE. R EMARKS • You must define the KP_Init() function in your code in order to link the Kernel PlugIn driver to WinDriver. KP_Init() is called when the driver is loaded. Any code that you want to execute upon loading should be in this function. E XAMPLE BOOL __cdecl KP_Init(KP_INIT *kpInit) { /* Check if the version of the WinDriver Kernel PlugIn library is the same version as windrvr.h and wd_kp.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.2 324 KP_Open() P URPOSE • Called when WD_KernelPlugInOpen() (see the WinDriver PCI Low-Level API Reference) is called from user mode. WD_KernelPlugInOpen() is automatically called from the WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) when these functions are called with a valid Kernel PlugIn driver (set in the pcKPDriverName parameter). This function sets the rest of the Kernel PlugIn callback functions (KP_Call() [B.6.
B.6 Kernel PlugIn Kernel-Mode Functions 325 D ESCRIPTION Name kpOpenCall hWD pOpenData ppDrvContext Description Structure to fill in the addresses of the KP_xxx() callback functions [B.7.5] The WinDriver handle that WD_KernelPlugInOpen() was called with Pointer to data passed from user mode Pointer to driver context data with which the KP_Close() [B.6.3], KP_Call() [B.6.4], KP_IntEnable() [B.6.6] and KP_Event() [B.6.5] functions will be called.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.3 326 KP_Close() P URPOSE • Called when WD_KernelPlugInClose() (see the WinDriver PCI Low-Level API Reference) is called from user mode. For devices that have been opened with a Kernel PlugIn driver – i.e. WDC_xxxDeviceOpen() (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.11]) was called with a valid Kernel PlugIn driver (set in the pcKPDriverName parameter) – the WDC_xxxDeviceClose() functions (PCI [B.3.12] / PCMCIA [B.3.13] / ISA [B.3.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.4 327 KP_Call() P URPOSE • Called when the user-mode application calls WDC_CallKerPlug() [B.3.17] (or the low-level WD_KernelPlugInCall() function – see the WinDriver PCI Low-Level API Reference). This function is a message handler for your utility functions.
B.6 Kernel PlugIn Kernel-Mode Functions 328 D ESCRIPTION Name pDrvContext kpCall fIsKernelMode Description Driver context data that was set by KP_Open() [B.6.2] and will also be passed to KP_Close() [B.6.3], KP_IntEnable() [B.6.6] and KP_Event() [B.6.5] Structure with user-mode information received from the WDC_CallKerPlug() [B.3.17] (or from the low-level WD_KernelPlugInCall() function – see the WinDriver PCI Low-Level API Reference) and/or with information to return back to the user mode [B.7.
B.6 Kernel PlugIn Kernel-Mode Functions 329 E XAMPLE void __cdecl KP_Call(PVOID pDrvContext, WD_KERNEL_PLUGIN_CALL *kpCall, BOOL fIsKernelMode) { kpCall->dwResult = MY_DRV_OK; switch (kpCall->dwMessage) { /* In this sample we implement a GetVersion message */ case MY_DRV_MSG_VERSION: { DWORD dwVer = 100; MY_DRV_VERSION *ver = (MY_DRV_VERSION *)kpCall->pData; COPY_TO_USER_OR_KERNEL(&ver->dwVer, &dwVer, sizeof(DWORD), fIsKernelMode); COPY_TO_USER_OR_KERNEL(ver->cVer, "My Driver V1.00", sizeof("My Driver V1.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.5 330 KP_Event() P URPOSE • Called when a Plug-and-Play or power management event for the device is received, provided the user-mode application first called WDC_EventRegister() [B.3.46] with fUseKP = TRUE (or the low-level EventRegister() function with a Kernel PlugIn handle – see WinDriver PCI Low-Level API Reference) (see the Remarks below).
B.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.6 332 KP_IntEnable() P URPOSE • Called when WD_IntEnable() (see WinDriver PCI Low-Level API Reference) is called from the user mode with a Kernel PlugIn handle. WD_IntEnable() is called automatically from WDC_IntEnable() [B.3.43] and InterruptEnable() (see WinDriver PCI Low-Level API Reference). The interrupt context that is set by this function (*ppIntContext) will be passed to the rest of the Kernel PlugIn interrupt functions.
B.6 Kernel PlugIn Kernel-Mode Functions 333 D ESCRIPTION Name pDrvContext kpCall ppIntContext Description Driver context data that was set by KP_Open() [B.6.2] and will also be passed to KP_Close() [B.6.3], KP_Call() [B.6.4] and KP_Event() [B.6.5] Structure with information from WD_IntEnable() [B.7.3] Pointer to interrupt context data that will be passed to the KP_IntDisable() [B.6.7], KP_IntAtIrql() [B.6.8] and KP_IntAtDpc() [B.6.9] functions.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.7 334 KP_IntDisable() P URPOSE • Called when WD_IntDisable() (see WinDriver PCI Low-Level API Reference) is called from the user mode for interrupts that were enabled in the Kernel PlugIn. WD_IntDisable() is called automatically from WDC_IntDisable() [B.3.44] and InterruptDisable() (see WinDriver PCI Low-Level API Reference). • This function should free any memory that was allocated in KP_IntEnable() [B.6.6].
B.6 Kernel PlugIn Kernel-Mode Functions B.6.8 335 KP_IntAtIrql() P URPOSE • High-priority interrupt handler routine, which is run at high interrupt request level. This function is called upon the arrival of interrupts that have been enabled using a Kernel PlugIn driver – see WDC_IntEnable() [B.3.43] or the low-level InterruptEnable() and WD_IntEnable() functions (see WinDriver PCI Low-Level API Reference).
B.6 Kernel PlugIn Kernel-Mode Functions 336 R EMARKS • Code running at IRQL will only be interrupted by higher priority interrupts. • Code running at IRQL is limited by the following restrictions: – You may only access non-pageable memory. – You may only call the following functions (or wrapper functions that call these functions): * WDC_xxx read/write address or configuration space functions. * WDC_MultiTransfer() [B.3.
B.6 Kernel PlugIn Kernel-Mode Functions 337 E XAMPLE BOOL __cdecl KP_IntAtIrql(PVOID pIntContext, BOOL *pfIsMyInterrupt) { DWORD *pdwIntCount = (DWORD *) pIntContext; /* Check your hardware here to see if the interrupt belongs to you. If it does, you must set *pfIsMyInterrupt to TRUE. Otherwise, set *pfIsMyInterrupt to FALSE.
B.6 Kernel PlugIn Kernel-Mode Functions B.6.9 338 KP_IntAtDpc() P URPOSE • Deferred processing interrupt handler routine. This function is called once the high-priority interrupt handling is completed, provided that KP_IntAtIrql() [B.6.8] returned TRUE.
B.6 Kernel PlugIn Kernel-Mode Functions 339 R ETURN VALUE Returns the number of times to notify user mode (i.e., return from WD_IntWait() – see the WinDriver PCI Low-Level API Reference). R EMARKS • Most of the interrupt handling should be implemented within this function (as opposed to the high-priority KP_IntAtIrql() [B.6.8] interrupt handler).
B.6 Kernel PlugIn Kernel-Mode Functions 340 B.6.10 COPY_TO_USER_OR_KERNEL, COPY_FROM_USER_OR_KERNEL P URPOSE • Macros for copying data from the user mode to the Kernel PlugIn and vice versa. R EMARKS • The COPY_TO_USER_OR_KERNEL and COPY_FROM_USER_OR_KERNEL are macros used for copying data (when necessary) to/from user-mode memory addresses (respectively), when accessing such addresses from within the Kernel PlugIn.
B.6 Kernel PlugIn Kernel-Mode Functions 341 B.6.11 Kernel PlugIn Synchronization APIs This section describes the Kernel Plug-In synchronization APIs. These APIs support the following synchronization mechanisms: • Spinlocks [B.6.11.2 – B.6.11.5], which are used to synchronize between threads on a single or multiple CPU system. NOTE The Kernel PlugIn spinlock functions can be called from any context apart from high interrupt request level.
B.6 Kernel PlugIn Kernel-Mode Functions 342 B.6.11.2 kp_spinlock_init() P URPOSE • Initializes a new Kernel PlugIn spinlock object. P ROTOTYPE KP_SPINLOCK * k p _ s p i n l o c k _ i n i t ( v o i d ) ; R ETURN VALUE If successful, returns a pointer to the new Kernel PlugIn spinlock object [B.6.11.1], otherwise returns NULL.
B.6 Kernel PlugIn Kernel-Mode Functions 343 B.6.11.3 kp_spinlock_wait() P URPOSE • Waits on a Kernel PlugIn spinlock object. P ROTOTYPE v o i d k p _ s p i n l o c k _ w a i t ( KP_SPINLOCK * s p i n l o c k ) ; PARAMETERS Name ➢ spinlock Type KP_SPINLOCK* Input/Output Input D ESCRIPTION Name spinlock R ETURN VALUE None Description Pointer to the Kernel PlugIn spinlock object [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 344 B.6.11.4 kp_spinlock_release() P URPOSE • Releases a Kernel PlugIn spinlock object. P ROTOTYPE v o i d k p _ s p i n l o c k _ r e l e a s e ( KP_SPINLOCK * s p i n l o c k ) ; PARAMETERS Name ➢ spinlock Type KP_SPINLOCK* Input/Output Input D ESCRIPTION Name spinlock R ETURN VALUE None Description Pointer to the Kernel PlugIn spinlock object [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 345 B.6.11.5 kp_spinlock_uninit() P URPOSE • Un-initializes a Kernel PlugIn spinlock object. P ROTOTYPE v o i d k p _ s p i n l o c k _ u n i n i t ( KP_SPINLOCK * s p i n l o c k ) ; PARAMETERS Name ➢ spinlock Type KP_SPINLOCK* Input/Output Input D ESCRIPTION Name spinlock R ETURN VALUE None Description Pointer to the Kernel PlugIn spinlock object [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 346 B.6.11.6 kp_interlocked_init() P URPOSE • Initializes a Kernel PlugIn interlocked counter. P ROTOTYPE v o i d k p _ i n t e r l o c k e d _ i n i t ( KP_INTERLOCKED * t a r g e t ) ; PARAMETERS Name ➢ target Type KP_INTERLOCKED* Input/Output Input/Output D ESCRIPTION Name target R ETURN VALUE None Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 347 B.6.11.7 kp_interlocked_uninit() P URPOSE • Un-initializes a Kernel PlugIn interlocked counter. P ROTOTYPE v o i d k p _ i n t e r l o c k e d _ u n i n i t ( KP_INTERLOCKED * t a r g e t ) ; PARAMETERS Name ➢ target Type KP_INTERLOCKED* Input/Output Input/Output D ESCRIPTION Name target R ETURN VALUE None Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 348 B.6.11.8 kp_interlocked_increment() P URPOSE • Increments the value of a Kernel PlugIn interlocked counter by one. P ROTOTYPE i n t k p _ i n t e r l o c k e d _ i n c r e m e n t ( KP_INTERLOCKED * t a r g e t ) ; PARAMETERS Name ➢ target Type KP_INTERLOCKED* Input/Output Input/Output D ESCRIPTION Name target Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 349 B.6.11.9 kp_interlocked_decrement() P URPOSE • Decrements the value of a Kernel PlugIn interlocked counter by one. P ROTOTYPE i n t k p _ i n t e r l o c k e d _ d e c r e m e n t ( KP_INTERLOCKED * t a r g e t ) ; PARAMETERS Name ➢ target Type KP_INTERLOCKED* Input/Output Input/Output D ESCRIPTION Name target Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 350 B.6.11.10 kp_interlocked_add() P URPOSE • Adds a specified value to the current value of a Kernel PlugIn interlocked counter. P ROTOTYPE i nt kp_interlocked_add ( KP_INTERLOCKED * t a r g e t , i nt val ) ; PARAMETERS Name ➢ target ➢ val Type KP_INTERLOCKED* val Input/Output Input/Output Input D ESCRIPTION Name target val Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 351 B.6.11.11 kp_interlocked_read() P URPOSE • Reads to the value of a Kernel PlugIn interlocked counter. P ROTOTYPE i n t k p _ i n t e r l o c k e d _ r e a d ( KP_INTERLOCKED * t a r g e t ) ; PARAMETERS Name ➢ target Type KP_INTERLOCKED* Input/Output Input D ESCRIPTION Name target Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.1] to read R ETURN VALUE Returns the value of the interlocked counter (target).
B.6 Kernel PlugIn Kernel-Mode Functions 352 B.6.11.12 kp_interlocked_set() P URPOSE • Sets the value of a Kernel PlugIn interlocked counter to the specified value. P ROTOTYPE void k p _ i n t e r l o c k e d _ s e t ( KP_INTERLOCKED * t a r g e t , i nt val ) ; PARAMETERS Name ➢ target ➢ val Type KP_INTERLOCKED* val Input/Output Input/Output Input D ESCRIPTION Name target val R ETURN VALUE None Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.6 Kernel PlugIn Kernel-Mode Functions 353 B.6.11.13 kp_interlocked_exchange() P URPOSE • Sets the value of a Kernel PlugIn interlocked counter to the specified value and returns the previous value of the counter. P ROTOTYPE i nt kp_interlocked_exchange ( KP_INTERLOCKED * t a r g e t , i nt val ) ; PARAMETERS Name ➢ target ➢ val Type KP_INTERLOCKED* val Input/Output Input/Output Input D ESCRIPTION Name target val Description Pointer to the Kernel PlugIn interlocked counter [B.6.11.
B.7 Kernel PlugIn Structure Reference 354 B.7 Kernel PlugIn Structure Reference This section contains detailed information about the different Kernel PlugIn related structures. WD_XXX structures are used in user-mode functions and KP_XXX structures are used in kernel-mode functions. The Kernel PlugIn synchronization types are documented in section B.6.11.1. B.7.1 WD_KERNEL_PLUGIN Defines a Kernel PlugIn open command.
B.7 Kernel PlugIn Structure Reference B.7.2 355 WD_INTERRUPT Interrupt information structure. This structure is used by the low-level InterruptEnable(), InterruptDisable(), WD_IntEnable(), WD_IntDisable(), WD_IntWait() and WD_IntCount() functions. WDC_IntEnable() [B.3.43] calls InterruptEnable(), which in turn calls WD_IntEnable(), WD_IntWait() and WD_IntCount(). WDC_IntDisable() [B.3.44] calls InterruptDisable(), which calls WD_IntDisable().
B.7 Kernel PlugIn Structure Reference B.7.3 356 WD_KERNEL_PLUGIN_CALL Kernel PlugIn message information structure. This structure contains information that will be passed between a user-mode process and the Kernel PlugIn. The structure is used when passing messages to the Kernel PlugIn or when installing a Kernel PlugIn interrupt. This structure is passed as a parameter to the Kernel PlugIn KP_Call() [B.6.4] and KP_IntEnable() [B.6.
B.7 Kernel PlugIn Structure Reference B.7.4 357 KP_INIT This structure is used by the Kernel PlugIn KP_Init() function [B.6.1]. Its primary use is to notify WinDriver of the given driver’s name and of which kernel-mode function to call when WD_KernelPlugInOpen() (see WinDriver PCI Low-Level API Reference) is called from the user mode. WD_KernelPlugInOpen() is called from the high-level WDC_xxxDeviceOpen() functions (PCI [B.3.9] / PCMCIA [B.3.10] / ISA [B.3.
B.7 Kernel PlugIn Structure Reference B.7.5 358 KP_OPEN_CALL This is the structure through which the Kernel PlugIn defines the names of its callback functions (other than KP_Open()). It is used from the KP_Open() [B.6.2] Kernel PlugIn function, which sets the callbacks in the structure. A Kernel PlugIn may implement 7 different callback functions (other than KP_Open() [B.6.2]): funcClose – Called when the user-mode process is done with this instance of the driver.
B.7 Kernel PlugIn Structure Reference 359 called with a Kernel PlugIn handle – see WinDriver PCI Low-Level API Reference). This callback function should implement the desired kernel handling for Plug-and-Play and power management events.
B.8 User-Mode Utility Functions 360 B.8 User-Mode Utility Functions This section describes a number of user-mode utility functions you will find useful for implementing various tasks. These utility functions are multi-platform, implemented on all operating systems supported by WinDriver. B.8.1 Stat2Str() P URPOSE • Retrieves the status string that corresponds to a status code.
B.8 User-Mode Utility Functions B.8.2 get_os_type() P URPOSE • Retrieves the type of the operating system. P ROTOTYPE OS_TYPE g e t _ o s _ t y p e ( v o i d ) ; R ETURN VALUE Returns the type of the operating system. If the operating system type is not detected, returns OS_CAN_NOT_DETECT.
B.8 User-Mode Utility Functions B.8.3 362 ThreadStart() P URPOSE • Creates a thread. P ROTOTYPE DWORD T h r e a d S t a r t ( HANDLE * phThread , HANDLER_FUNC pFunc , void * pData ) ; PARAMETERS Name ➢ phThread ➢ pFunc ➢ pData Type HANDLE* typedef void (*HANDLER_FUNC)( void *pData); VOID* Input/Output Output Input Input D ESCRIPTION Name phThread pFunc pData Description Returns the handle to the created thread Starting address of the code that the new thread is to execute.
B.8 User-Mode Utility Functions B.8.4 363 ThreadWait() P URPOSE • Waits for a thread to exit.
B.8 User-Mode Utility Functions B.8.5 364 OsEventCreate() P URPOSE • Creates an event object. P ROTOTYPE DWORD O s E v e n t C r e a t e (HANDLE * phOsEvent ) ; PARAMETERS Name ➢ phOsEvent Type HANDLE* Input/Output Output D ESCRIPTION Name phOsEvent Description The pointer to a variable that receives a handle to the newly created event object R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions B.8.6 365 OsEventClose() P URPOSE • Closes a handle to an event object.
B.8 User-Mode Utility Functions B.8.7 366 OsEventWait() P URPOSE • Waits until a specified event object is in the signaled state or the time-out interval elapses. P ROTOTYPE DWORD O s E v e n t W a i t ( HANDLE hOsEvent , DWORD dwSecTimeout ) ; PARAMETERS Name ➢ hOsEvent ➢ dwSecTimeout Type HANDLE DWORD Input/Output Input Input D ESCRIPTION Name hOsEvent dwSecTimeout Description The handle to the event object Time-out interval of the event, in seconds.
B.8 User-Mode Utility Functions B.8.8 367 OsEventSignal() P URPOSE • Sets the specified event object to the signaled state. P ROTOTYPE DWORD O s E v e n t S i g n a l (HANDLE hOsEvent ) ; PARAMETERS Name ➢ hOsEvent Type HANDLE D ESCRIPTION Name hOsEvent Description The handle to the event object R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions B.8.9 368 OsEventReset() P URPOSE • Resets the specified event object to the non-signaled state. P ROTOTYPE DWORD O s E v e n t R e s e t (HANDLE hOsEvent ) ; PARAMETERS Name ➢ hOsEvent Type HANDLE D ESCRIPTION Name hOsEvent Description The handle to the event object R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions 369 B.8.10 OsMutexCreate() P URPOSE • Creates a mutex object. P ROTOTYPE DWORD O s M u t e x C r e a t e (HANDLE * phOsMutex ) ; PARAMETERS Name ➢ phOsMutex Type HANDLE* Input/Output Output D ESCRIPTION Name phOsMutex Description The pointer to a variable that receives a handle to the newly created mutex object R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions 370 B.8.11 OsMutexClose() P URPOSE • Closes a handle to a mutex object.
B.8 User-Mode Utility Functions 371 B.8.12 OsMutexLock() P URPOSE • Locks the specified mutex object. P ROTOTYPE DWORD OsMutexLock (HANDLE hOsMutex ) ; PARAMETERS Name ➢ hOsMutex Type HANDLE Input/Output Input D ESCRIPTION Name hOsMutex Description The handle to the mutex object to be locked R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions 372 B.8.13 OsMutexUnlock() P URPOSE • Releases (unlocks) a locked mutex object. P ROTOTYPE DWORD OsMutexUnlock (HANDLE hOsMutex ) ; PARAMETERS Name ➢ hOsMutex Type HANDLE Input/Output Input D ESCRIPTION Name hOsMutex Description The handle to the mutex object to be unlocked R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.8 User-Mode Utility Functions 373 B.8.14 PrintDbgMessage() P URPOSE • Sends debug messages to the debug monitor. P ROTOTYPE void PrintDbgMessage ( DWORD dwLevel , DWORD d w S e c t i o n , const char * format [ , argument ] . . .
B.8 User-Mode Utility Functions 374 B.8.15 WD_LogStart() P URPOSE • Opens a log file. P ROTOTYPE DWORD WD_LogStart ( c o n s t c h a r * sFileName , c o n s t c h a r * sMode ) ; PARAMETERS Name ➢ sFileName ➢ sMode Type const char* const char* Input/Output Input Input D ESCRIPTION Name sFileName sMode Description Name of log file to be opened Type of access permitted.
B.8 User-Mode Utility Functions B.8.16 WD_LogStop() P URPOSE • Closes a log file.
B.8 User-Mode Utility Functions 376 B.8.17 WD_LogAdd() P URPOSE • Adds user printouts into log file. P ROTOTYPE VOID DLLCALLCONV WD_LogAdd ( const char * sFormat [ , argument ] . . . ) ; PARAMETERS Name ➢ sFormat ➢ argument Type const char* D ESCRIPTION Name sFormat argument Description Format-control string Optional format arguments R ETURN VALUE Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.9].
B.9 WinDriver Status Codes 377 B.9 WinDriver Status Codes B.9.1 Introduction Most of the WinDriver functions return a status code, where zero (WD_STATUS_SUCCESS) means success and a non-zero value means failure. The Stat2Str() functions can be used to retrieve the status description string for a given status code. The status codes and their descriptive strings are listed below.
B.9 WinDriver Status Codes B.9.
Appendix C Troubleshooting and Support Please refer to http://www.jungo.com/st/support/support_windriver.
Appendix D Evaluation Version Limitations D.1 Windows WinDriver Evaluation Limitations • Each time WinDriver is activated, an Unregistered message appears. • When using DriverWizard, a dialogue box with a message stating that an evaluation version is being run appears on every interaction with the hardware. • DriverWizard [4]: – Each time DriverWizard is activated, an Unregistered message appears. – An evaluation message is displayed on every interaction with the hardware using DriverWizard.
D.3 Linux WinDriver Evaluation Limitations 381 • WinDriver CE emulation on Windows 2000/XP/Server 2003/Vista will stop working after 30 days. D.3 Linux WinDriver Evaluation Limitations • Each time WinDriver is activated, an Unregistered message appears. • DriverWizard [4]: – Each time DriverWizard is activated, an Unregistered message appears. – An evaluation message is displayed on every interaction with the hardware using DriverWizard.
Appendix E Purchasing WinDriver Fill in the order form found in Start | WinDriver | Order Form on your Windows start menu, and send it to Jungo via email, fax or mail (see details below). Your WinDriver package will be sent to you via Fedex or standard postal mail. The WinDriver license string will be emailed to you immediately. EMAIL WEB Support: support@jungo.com http://www.jungo.com Sales: sales@jungo.
Appendix F Distributing Your Driver – Legal Issues WinDriver is licensed per-seat. The WinDriver license allows one developer on a single computer to develop an unlimited number of device drivers, and to freely distribute the created drivers without royalties, as outlined in the license agreement in the WinDriver/docs/license.pdf file.
Appendix G Additional Documentation U PDATED M ANUALS The most updated WinDriver user manuals can be found on Jungo’s site at: http://www.jungo.com/st/support/support_windriver.html. V ERSION H ISTORY If you wish to view WinDriver version history, refer to the WinDriver Release Notes: http://www.jungo.com/st/wdver.html.The release notes include a list of the new features, enhancements and fixes that have been added in each WinDriver version.