The purpose of this sample is to illustrate functionality of an NDIS-WDF miniport driver. An NDIS-WDF driver exposes NDIS miniport interface at its upper edge and uses Windows Driver Framework interfaces to interact with other WDM drivers such as USB, IEEE 1394, and serial at its lower edge.
This sample can either use NDISPROT sample driver from the DDK to read/write packets to any network device installed on the system or it can use PCIDRV sample to talk to Intel 10/100 network device.
1) The diagram below shows how this sample uses NDISPROT (NDIS protocol sample available in the Windows Server 2003 DDK) as its lower WDM edge driver to read and write packets to the physical network interface card (NIC). In order to test this sample, you should at least have one physical NIC on the test machine.
--------------------- | | | TCP/IP | | | --------------------- ^ | <-------------- NDIS Interface V --------------------- | | | Sample NDISWDM | | Miniport | | | --------------------- ^ | <--------------- IRPs V --------------------- | | | NDISPROT | | | --------------------- ^ | <--------------- NDIS Interface V --------------------- | | | NDIS Miniport | | for physical NIC | | | --------------------- ^ | <-------------- Talk to the hardware using I/O resources V --------------- | H/w NIC | --------------- ||||||| -------2) The following diagram shows how this driver as an upper device filter of PCIDRV sample work as a miniport driver for Intel 10/100 Ethernet adapter. 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 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.
-------------------- | | | 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 | --------------- ||||||| -------
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.
The driver can be installed on Windows 2000 and later operating systems.
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\kmdf\NDISEDGE.
Run build -ceZ, or use the macro BLD. Using these tools 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, IA64, or AMD64).
If the build succeeds, the driver, ndisedge.sys, will be placed in a platform specific subdirectory of your %TargetPath% directory specified in the 'Sources' file.
Depending on the build environment, the 50 subdirectory produces either NDIS5.0 or NDIS 5.1 compatible driver. If built in the Windows 2000 build environment, it will produce NDIS 5.0 compatible driver. If it's built in the Windows XP or Window Server 2003 build environment, it will produce NDIS 5.1 compatible driver.
The 60 subdirectory can be built only in the Windows Vista build environment. The sample built in this subdirectory will be NDIS 6.0 compatible and will work on Windows Vista and later operating systems.
This sample can installed in either as virtual miniport driver interfacing with NDISPROT or as an upper device filter interfacing with PCIDRV. Steps on how to install this driver in each of these modes is given below.
After installing the NDISEDGE driver, you have to one of the followings to use it as your primary miniport driver:
To install the driver on a Windows 2000 machine
To install the driver on a Windows XP or Server 2003 machine
Alternatively, you can use the DEVCON.EXE from the DDK to install the driver programmatically.
c:\>DEVCON.EXE INSTALL ndisedge.inf "root\ndisedge"
The system copies the NDISEDGE.sys file to %systemroot%\system32\drivers directory and loads the driver. Instead of root-enumerating the driver as described above, you can use the toaster bus driver to bus enumerate the driver.
If you like to get this configuration to work across reboots, you should configure the NDISEDGE driver to set the target NIC filter to promiscuous mode. You can do that by using Advanced Property of the miniport in the device manager or by changing the value in the INF file before installing the miniport.
To install on Windows 2000 System:
On Windows XP, Server 2003 or Vista system:
Install NDIS Tester from the WHQL Web site and run all the client and server tests.
Initialization
NDISEDGE and NDISPROT driver are two unrelated drivers. NDISEDGE is a Plug and Play driver and NDISPROT is an Windows®NT®4.0 compatible non-Plug and Play driver. As a result, it's not possible to use a Plug and Play notification mechanism to resolve load order dependency between the drivers. If the NDISEDGE is installed as a root-enumerated driver, then it will get loaded much earlier in the boot sequence than the NDISPROT driver. When the NDISEDGE tries to open the NDISPROT in MiniportInitialize handler, it will fail with a STATUS_OBJECT_NAME_NOT_FOUND error because the NDISPROT device is not present.
Instead of using timer DPCs and work items to periodically retry opening NDISPROT, this driver uses a new executive callback mechanism to resolve the load order issue. Both NDISEDGE and NDISPROT create a Callback object (ExCreateCallback) called \Callback\NdisProtCallbackObject and register their callback handlers (ExRegisterCallback). The driver that loads first creates the object and the drivers loaded afterwards open the same object, register, and then send notification to the other drivers. Based on the notification ID received in the callback, both NDISEDGE and NDISPROT identify the source of notification and take appropriate action. For example, when the NDISEDGE driver receives a notification, it checks to see if the source driver of this notification is NDISPROT and if so, it tries to complete its initialization and indicate the final media status of its miniport to NDIS.
Request HandlerMost of the requests are handled directly by the NDISEDGE and completed synchronously. The driver also has the ability to forward any requests to the target driver. For forwarding requests, such as link speed, it queues a work item to get to PASSIVE_LEVEL of execution, and from the workitem it sends an IOCTL request to NDISPROT and waits for the IRP to complete. When the IRP returns, it indicates to NDIS about the completion of the request.
Send Packet HandlerIn the SendPacket handler, the driver copies the packet into a free TCB block (because NDISPROT cannot handle chained MDLs), initializes a preallocated IRP (IRP_MJ_WRITE) and MDL to describe the TCB data buffer and sends the IRP to the NDISPROT driver asynchronously. When the write completes, the original send packet that was saved in the TCB control block is completed and the TCB and IRP is freed for reuse.
Receive Packet handler:The driver pre-allocates a certain number (NIC_MAX_BUSY_SENDS) of RCB (Receive Control Blocks) buffers, IRPs (IRP_MJ_READ) and MDLs (to describe the RCB data buffer) during Miniport Initialize for receiving packets from the target driver (NDISPROT). It then queues a workitmem (NICPostReadsWorkItemCallBack) to post all the read IRPs to the target driver. When a read request completes, the completion routine (NICReadRequestCompletion) is called. This routine checks to see whether the received packet is acceptable based on the current packet filter set by the protocol, and decides to either indicate the packet to NDIS or discard the packet. When the indicated packet returns from NDIS through MPReturnPacket handler, the driver reclaims the associated RCB block and the read IRP for reuse, and checks to see if the number of outstanding Read IRPs to the NDISPROT has gone below a certain thershold (NIC_SEND_LOW_WATERMARK). If so, it queues a workitem to post more read IRPs and keeps the read path going.
For the latest release of the Windows device Driver Development Kit, see http://www.microsoft.com/ddk/.
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 Descriptionndiswdm.htm Sample Tour documentation for this sample (this file). Sources Generic file for building the code sample. ndisedge.inf INF file for installing the driver. ndiswdm.RC Resource file to specify driver version, etc. ndiswdm.h Include file for defining structures, constants and function prototypes. ndiswdm.c Main file that contains driver entry and other miniport functions. init.c Source file for allocating and initializing resources. send.c Source file for handling Send requests from NDIS. receive.c Source file for handling IRPs received by the lower WDM driver indicating to NDIS. request.c Source file for handling set & query information requests from NDIS. excallbk.c Source file for handling ex callback notification to resolve driver load order.
© 2003 Microsoft Corporation. All rights reserved.