次の方法で共有


PCIDRV - WDF Driver for PCI Device

SUMMARY

This sample contains two functionally equivalent drivers for Intel 82557/82558 based PCI Ethernet Adapter (10/100) and Intel compatibles. The purpose of these samples is to teach how to write a WDM and KMDF driver for a PCI device. Microsoft recommendation is to use KMDF to write drivers instead of WDM. Both WDM and KMDF versions are included to show the difference in complexity, and how KMDF simplifies WDM, and also serve as a reference sample for porting WDM driver to KMDF.

The choice of Intel Ethernet Adapter is made because the hardware is relatively inexpensive, easily available, supports advanced hardware features such as scatter-gather DMA, full fledge power management - ability to wake the machine on external event (Wait-Wake), ability to power down the device when not in use (Idle detection) - hardware specification is publicly available, and the source code to interface with the hardware is also available in the DDK.

Following is the list of key features demonstrated in the WDM sample.

  • How to map hardware resources in a platform independent manner. This sample shows how to determine whether the I/O BAR of a PCI device has been mapped into memory space or I/O space by just using the Translated resource list provided by the PNP manager, and use the appropriate accessor functions to read/write to the device.

  • How to do SCATTER GATHER DMA operation using the new DMA interfaces provided on Windows 2000. Depending on the build environment, it chooses to use the Win2K compliant, Version 0, DMA functions or Windows XP and later OS compliant, Version2 functions. GetScatterGatherList versus BuildScatterGatherList.

  • How to do software tracing that works on Windows 2000 and beyond. You can control the tracing spew using Flags and Level values and also dump variable length buffers using HEXDUMP macros. The sample can be built to do boot-time tracing. Read Boot-Time tracing section in this document for more information on how to enable that.

  • This sample demonstrates all aspect of power management. It shows how to be a power policy owner of a device and do S-D state mappings, generate D-IRPs, generate Wait-wake IRPs, perform idle detection, and fast resume. Since there are inherent race conditions in the system provided power management APIs (PoRegisterDeviceForIdleDetection) for doing IDLE detection, this sample uses it own idle detection logic.

Following is the list of key KMDF interfaces demonstrated in KMDF version of this sample:

  • Handling PnP & Power Events

  • Registering Device Interface

  • Hardware resource mapping: Port, Memory & Interrupt

  • DMA Interfaces

  • Parallel default queue for write requests. If the write cannot be satisfied immediately, the request is put into a manual parallel queue.

  • Parallel manual queue for Read requests

  • Parallelc default queue for IOCTL requests. If the ioctl cannot be satisfied immediately, the request is put into a manual parallel queue.

  • Request cancelation

  • Handling Interrupt & DPC

  • Watchdog Timer DPC to monitor the device state.

  • Event Tracing & HEXDUMP

  • Reading & Writing to the registry

On Windows platform, drivers for network devices have to be an NDIS miniport driver. Only then protocols can bind and perform network transfer. So the question comes to mind is, how can a generic KMDF (or WDM) driver be used for a network controller?

Well, for illustration purposes, this sample driver has been written in this manner. Real driver for network devices should be written using NDIS. However, this sample driver can be made to work as an NDIS miniport by using another NDIS-WDM sample driver from the DDK as an upper filter. Detail about two different configurations in which these samples can be used is given below.

The WDM interface in this sample is based on the Toaster function driver, and all the code to access the hardware is taken from the E100BEX NDIS miniport sample from the DDK and converted to use WDM interfaces instead of NDIS functions. The sample has been written in such a way, separating all the hardware specific code in separate modules and isolating them in a subdirectory, it can be easily adapted to work for any PCI and PCMCIA device.

Note: This sample provides an example of a minimal driver intended for educational purposes. Neither the driver nor its sample test programs are intended for use in a production environment.

As stated earlier, this sample is meant to demonstrate how to write a KMDF (or WDM) driver for a generic PCI device. This sample doesn't espouse that you write a KMDF (or WDM) driver with an NDIS edge for PCI network controllers. For network controllers, you should write a monolithic NDIS miniport driver based on the samples given under the src\network\ndis directory.

Note that it is still possible to use a subset of KMDF APIs when writing a NDIS miniport (see src\network\ndis\usbnwifi directory for a sample on how to use KMDF interfaces to talk to USB device in an NDIS miniport).

The sample driver has been tested on the following Intel Ethernet controllers:

Device Desc Hardware ID

IBM Netfinity 10/100 Ethernet Adapter

PCI\VEN_8086&DEV_1229&SUBSYS_005C1014&REV_05

Intel(R) PRO/100+ Management Adapter with Alert On LAN

PCI\VEN_8086&DEV_1229&SUBSYS_000E8086&REV_08

Intel 8255x-based PCI Ethernet Adapter (10/100)

PCI\VEN_8086&DEV_1229&SUBSYS_00000000&REV_01

Intel Pro/100 S Server Adapter

PCI\VEN_8086&DEV_1229&SUBSYS_00508086&REV_0D

Intel 8255x-based PCI Ethernet Adapter (10/100)

PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08

Intel(R) PRO/100 VE Network Connection

PCI\VEN_8086&DEV_103D&SUBSYS_00011179&REV_83

Intel(R) PRO/100 VM Network Connection

PCI\VEN_8086&DEV_1031&REV_42

Intel(R) PRO/100 VE Network Connection

PCI\VEN_8086&DEV_1038&REV_41

Intel(R) PRO/100 SR Mobile Adapter

PCI\VEN_8086&DEV_1229

 

Click here to get a complete list of Intel Network adapters.

The driver can be installed in the Windows 2000 and later operating systems.

Using this sample as a Miniport

---------------------

| |

| TCP/IP |

| |

---------------------

^

| <-------------- NDIS Interface (I/Os done using NDIS Packets)

V

---------------------

| |

| NDISWDM Miniport |

| (NDISEDGE.SYS) | <-- Installed as an Upper Device Filter

| |

---------------------

^

| <--------------- IRPs (I/Os done using IRPs)

V

---------------------

| |

| PCIDRV.SYS | <-- Installed as a function driver

| |

---------------------

^

| <-------------- Talk to the hardware using I/O resources

V

---------------

| H/w NIC |

---------------

|||||||

-------

You can install the driver as a Net class driver using NETDRV.INF, and use the device as a fully functional network device. The picture above shows the stack layout in this configuration. The driver stack consists of NDIS-WDM driver as an upper device filter and PCIDRV as the function driver for the device. The NDIS-WDM driver registers with NDIS as a miniport so that the stack can be bound to all the protocol drivers and receive NDIS requests. The PCIDRV maps all the hardware resources (received in IRP_MN_START_DEVICE) and performs the job of reading and writing to the hardware. All the NDIS requests received by the NDIS-WDM driver is converted into IRPs and forwarded to the PCIDRV driver.

In this configuration, the NDIS acts as the power policy owner of the device and performs the job of converting S-IRPs to D-IRPs and sending Wait-Wake IRPs. The PCIDRV remains passive and mostly forwards the Power and WMI requests.

Using this sample as a standalone driver

---------------------

| |

| MYPING | <-- Usermode test application

| |

---------------------

^

| UserMode

-------------------------------------------------------------------------

| KernelMode

V

---------------------

| |

| PCIDRV | <-- Installed as a function driver

| |

---------------------

^

| <-------------- Talk to the hardware using I/O resources

V

---------------

| H/w NIC |

---------------

|||||||

-------

You can install the driver as a standalone driver of a custom setup class, called Sample Class using GENPCI.INF. The PCI device is not seen as a network controller and as a result no protocol driver is bound to the device. In order to test the read & write path of the driver, you can use the specially developed ping application, called MYPING. This test application crafts the entire Ethernet frame in usermode and sends it to the driver to be transferred on the wire. In this configuration, you can only ping another machine on the same subnet. The application does all the ARP and AARP resolution in the usermode to get the MAC address of the target machine and sends ICMP ECHO requests.

The PCIDRV sample acts as a power policy owner of the device and implements all the wait-wake and idle detection logic.

BUILDING THE SAMPLE

To build NDISEDGE.SYS (Upper device filter)

  • Click the Free Build Environment or Checked Build Environment icon under your Development Kit's program group to set basic environment variables needed by the build utility.

  • Change to the directory containing the device source code, such as CD Src\network\ndis\NDISWDM.

  • Update the 'sources' file to change the TARGETNAME from NDISWDM to NDISEDGE, and comment or remove "-DINTERFACE_WITH_NDISPROT=1" from C_DEFINES statement.

  • Build the driver by typing BLD.

To build PCIDRV.SYS (Function driver)

  • Click the Free Build Environment or Checked Build Environment icon under your Development Kit's program group to set basic environment variables needed by the build utility.

  • Change to the directory containing the device source code, such as CD Src\general\PCIDRV\.

  • Build the driver by typing BLD.

Build -ceZ, or the macro BLD invokes the Microsoft make routines that produce log files called Buildxxx_yyy_zzz.log, and also Buildxx_yyy_zzz.wrn and Buildxx_yyy_zzz.err if there are any warnings or errors. Where xxx stands for fre or chk depending on the environment chosen, yyy stands for the OS version (W2K, WXP, or Wnet), and zzz stands for platform version (x86, x64, or AMD64).

If the build succeeds, the driver will be placed in the binary output directory specified for the build environment. You can get the output path from the buildxxx.log file.

INSTALLATION

The driver can be installed as a Net class driver or as a standalone driver (user defined class). Depending on whether you are using the WDM or KMDF version, please pick up the correct INF files from the respective folder. The KMDF versions of the INF files are dynamically generated from .INX file. In addition to the driver files, you have to include the WDF coinstaller DLL from the src\redist\wdf folder of the WDK.

As a Net Class driver on Windows XP and later system:

  1. Build NDISEDGE.SYS as described above in a XP and later build environment to get the NDIS version 5.1 driver.

  2. Build PCIDRV.SYS in XP or Server 2003 build environment.

  3. Copy the drivers and the NETDRV.INF file to a floppy disk or to a directory on the target test machine. Driver should be copied under appropriate subdirectory (i386, x64, amd64).

  4. Launch the Device Manager (by clicking on Windows Start, Run option and type Devmgmt.msc).

  5. Select the Intel network controller in the device manager, right click to get the Properties menu and select Updater Driver....

  6. Select Driver Tab.

  7. Click Update Driver... button. This will take you to Hardware Update Wizard.

  8. Select Install from a list of specific location (Advanced), and then click Next.

  9. Select Don't search. I will choose the driver to install, and then click Next.

  10. Click Have Disk, and point to the directory that contains NETDRV.INF file.

  11. Select Sample WDM PCI Driver For Ethernet Adapter With NDIS Upper Edge, and then click Next.

  12. If you get a Warning dialog about installing driver that's not compatible with the hardware. Click No and exit the Wizard.

  13. Otherwise, you will get a warning dialog about installing unsigned driver. Click Continue Anyway and complete the driver upgrade.

To install as a standalone driver Windows XP and later operating systems:

  1. Build PCIDRV.SYS in XP or Server 2003 build environment.

  2. Copy the driver, test application and the GENPCI.INF file to a floppy disk or to a directory on the target test machine. Driver should be copied under appropriate subdirectory (i386, x64, amd64).

  3. Launch the Device Manager (by clicking on Windows Start, Run option and type Devmgmt.msc).

  4. Select the Intel network controller in the device manager, right click to get the Properties menu and select Updater Driver....

  5. Select Driver Tab.

  6. Click Update Driver... button. This will take you to Hardware Update Wizard.

  7. Select Install from a list of specific location (Advanced), and then click Next.

  8. Select Don't search. I will choose the driver to install, and then click Next.

  9. Click Have Disk, and point to the directory that contains GENPCI.INF file.

  10. Select Sample WDM PCI For Intel 8255x Ethernet Controller, and then click Next.

  11. If you get a Warning dialog about installing driver that's not compatible with the hardware. Click No and exit the Wizard.

  12. Otherwise, you will get a warning dialog about installing unsigned driver. Click Continue Anyway and complete the driver upgrade.

TESTING

To test the miniport configuration: Install NDIS Tester from the WHQL Web site and run all the client and server tests.

To test standalone driver configuration: You should use the specially developed ping application, called MYPING that comes with the sample. The Ping.exe provided in the system will not work because in this configuration, the test card is not bound to any network protocol - it's not seen as Net device by the system. Currently the test application doesn't have ability to get an IP address from a network DHCP server. As a result, it is better to connect the network device to a private hub and ping another machine connected to that hub. For example, let us say you have a test machine A and another machine B (development box).

  • Connect machine A and Machine B to a local hub.

  • Assign a static IP address, say 128.0.0.1 to the NIC on machine B.

  • Clear the ARP table on machine B by running Arp -d on the command line

  • Now run Myping.exe. This application enumerates GUID_DEVINTERFACE_PCIDRV and displays the name of the devices with an index number. This number will be used in identifying the interface when you invoke ping dialog.

  • In the ping dialog specify the following and click okay:

  • Device Index: 1 <- number displayed in the list window

  • Source Ip Address: 128.0.0.4 <- You can make up any valid IP address for test Machine A

  • Destination IP Address: 128.0.0.1 <- IP address of machine B

  • Packet Size: 1428 <- Default max size of ping payload. Minimum value is 32 bytes.

If the machine B has more than one adapter and if the second adapter is connected to the internet (Corporate Network), instead of assigning static IP address to the adapter that's connected to the test machine, you can install Internet Connection Sharing (ICS) on it and get an IP address for ICS. This would let you use the test machine to browse the internet when the sample is installed in the miniport configuration and also in the standalone mode without making up or stealing somebody's IP address. For example, let us say the machine B has two adapters NIC1 and NIC2. NIC1 is connected to the CorpNet and NIC2 is connected to the private hub. Install ICS on NIC2 as described below:

  • Select the NIC2 in the Network Connections Applet.

  • Click the Properties button.

  • Go to the Advanced Tab and Check the box "Allow Other network users to connect through this computers internet connection" in the Internet Connection Sharing choice.

  • This will assign 192.168.0.1 IP address to NIC2.

  • Now on machine B, you can assume 192.168.0.2 as the local IP address and run Myping.exe . Or, you can install the sample in the miniport configuration and browse the internet.

Other menu options of myping applications are:

  • Reenumerate All Device: This command lets you terminate active ping threads and close handle to all the device and reenumerate the devices again and display their names with index numbers. This might cause the devices to have new index numbers.

  • Cleanup: This command terminates ping threads and closes handles to all the devices.

  • Clear Display: Clears the window.

  • Verbose: Let you get more debug messages.

  • Exit: Terminate the application.

Note You can use this application only on a device installed in the standalone configuration. If you run it on a device that's installed as a miniport, you will get an error message. For such devices, you can use the system provided ping.exe.

CODE TOUR (WDM only)

This section describes some of the implementation details of the driver:

  • IsUpperEdgeNDIS: When you install the driver in the miniport configuration, the INF file creates a registry entry under the hardware key, HKLM\SYSTEM\CurrentControlSet\Enum\PCI\PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08\4&3b1caf2b&0&50F0\Device Parameters\IsUpperEdgeNDIS. This registry value enables the PCIDRV to determine whether it's running in a miniport configuration or not (Another approach without creating a special registry entry would be to read the class name using IoGetDeviceProperty(DevicePropertyClassName), just like the myping app does). In the miniport configuration, the driver doesn't do any power management because the upper filter, NDISEDGE.SYS, in conjunction with NDIS acts as power policy owner for the device and performs S-D mappings and generates WAIT_WAKE Irps.

  • Idle Detection: The Power manager interfaces provided on Windows 2000 through Server 2003 for registering Idle detection has synchronization issues. When the system is going into lower power state, it doesn't disable idle detection as a result you could get D-IRP to go to a lower power state while your driver is in the middle of generating another D-IRP to go to standby. Let us say, a device has registered for idle detection, and wants to be sent a D1 irp when idle. Later on the system's going into standby at S3, which corresponds to D3 for this device. The S3 Irp goes down the stack, and right then we detect that this device is "idle" and send it the D1 irp. The device could see (S3, D3, D1) or (S3, D1, D3). The first case can be particularly disastrous, especially if it thinks it's now at D1, but it's bus is at some lesser D state.

  • Fast Resume: To enable system to resume from suspend really quick, a driver should complete S0 IRP immediately, then request a D0 IRP. This allows the system to complete resuming while the driver performs device-specific re-initialization in the background. Since there is no synchronization between PnP and Power manager while generating a D-IRP, drivers have to make sure that their device doesn't get stopped or removed while they are handling a D-IRP. One technique would be to keep the S-IRP hostage until the corresponding D-IRP is completed. But then this approach delays the system boot because the devices are powered up serially, waiting for the S0 IRP sent on a device to be completed before moving on to another device. Keeping the fast resume goal and the system limitation in mind, this sample completes the SO IRP before requesting a D0-IRP and at the same time uses a remlock scheme to hold the PNP IRPs while the driver is in the middle of receiving a previously requested DO-IRP.

RESOURCES

For the latest release of the Windows device Driver Development Kit, see https://www.microsoft.com/whdc/.

If you have questions on using or adapting this sample for your project, you can either contact Microsoft Technical Support or post your questions in the Microsoft driver development newsgroup.

FILE MANIFEST

File Description

WDM

Contains WDM version of the driver.

WDM\HW

Contains hardware specific code.

KMDF

Contains KMDF version of the driver.

KMDF\HW

Contains hardware specific code.

TEST

Contains source of test application (MYPING).