Intermediate Drivers (Windows Embedded CE 6.0)

1/6/2010

The NDIS architecture supports intermediate drivers. An NDIS intermediate driver does not use NDIS functions to control adapter hardware. Instead, it exists on top of another driver, such as the serial driver. The layered driver model represents a special kind of intermediate driver that exists on top of an NDIS miniport driver. A layered miniport driver exposes a miniport interface to the overlying protocol driver and a protocol-driver interface to the underlying miniport. In a layered miniport driver structure, the protocol driver communicates with a miniport driver at the bottom of the layered miniport driver. A layered miniport driver exports MiniportXXX functions at its upper edge and ProtocolXXX functions at its lower edge.

The following illustration shows the layered NDIS miniport driver architecture.

Ee483408.298ca3ff-5366-4fa5-8acb-e7306e9be199(en-US,WinEmbedded.60).gif

Layered miniport drivers can be used to filter out certain packets or to perform other special functions, such as decrypting and encrypting data.

A layered miniport driver maintains two interfaces: a miniport driver interface supplied to protocol drivers and a protocol driver interface supplied to underlying miniports. Use the NDIS protocol driver guidelines when building the layered miniport's protocol driver interface. Use the NDIS miniport driver guidelines when building the layered miniport's miniport driver interface; however, the layered miniport will generally use the intermediate driver functions, NdisIMXXX, and not the standard miniport functions, NdisMXXX.

The following table shows a set of new NDIS library functions. These functions apply to intermediate drivers, as well as to layered miniport driver architectures.

Function Description

NdisIMRegisterLayeredMiniport

Registers an intermediate driver's MiniportXXX entry points and name with the NDIS library when the driver initializes.

NdisIMInitializeDeviceInstance

Calls an NDIS intermediate driver's MiniportInitialize function to set up the driver's virtual network adapter for I/O operations on an underlying network adapter driver to which the intermediate driver is bound.

NdisIMInitializeDeviceInstanceEx

Calls an NDIS intermediate driver's MiniportInitialize function to initialize the driver's virtual network adapter and, optionally, to set up state information about the driver's virtual network adapter for subsequently bound protocols.

NdisIMDeInitializeDeviceInstance

Calls an NDIS intermediate driver's MiniportHalt function to tear down the driver's virtual network adapter.

NdisIMGetDeviceContext

Allows an NDIS intermediate driver's MiniportInitialize function to access the device context area that is allocated by its ProtocolBindAdapter function.

Any NDIS intermediate or layered miniport driver that exports both MiniportXXX and ProtocolXXX functions usually sets up a characteristics structure and calls the NdisIMRegisterLayeredMiniport function from its DriverEntry function after DriverEntry calls the NdisMInitializeWrapper function. This structure is copied in the NdisIMRegisterLayeredMiniport request to the internal storage of the NDIS library. Thus, once it has registered, such a driver cannot change its handler functions. An intermediate driver can call the NdisMRegisterMiniport function, instead of the NdisIMRegisterLayeredMiniport function, if it is prepared for an immediate call to the MiniportInitialize function.

NDIS Intermediate Drivers and Power Management

Windows CE .NET 4.0 introduced support for Network Driver Interface Specification (NDIS) version 5.1. This includes the wake-on-LAN feature that implements wake-specific OIDs and power state D3. For more information, see Plug and Play and Power Management Object Identifiers and Power Manager Requests and NDIS.

In this design, the TCPIP protocol driver may decide to send an OID_PNP_ADD_WAKE_UP_PATTERN object to inform the underlying miniport when to wake-up. Therefore, NDIS registers the drivers with the Power Manager. The following example shows how the NDIS GUID is defined in %_WINCEROOT%\PUBLIC\COMMON\SDK\INC\cedrv_guid.h:

#define CE_DRIVER_POWER_MANAGEABLE_NDIS_GUID        TEXT("{98C5250D-C29A-4985-AE5F-AFE5367E5006}")

The Windows Driver Development Kit at MSDN describes how to create an NDIS intermediate filter driver. With the Windows version of this driver, you can hide the intermediate driver from the Windows user interface. This is done on the desktop by setting the NCF_HIDDEN flag in the .inf file for the intermediate driver.

Windows Embedded CE does not provide this flag. Therefore, the Power Manager (PM) detects both the intermediate driver and the underlying miniport driver. Conversely, NDISUIO only detects the intermediate driver. However, the specifications for how an intermediate driver handles power management are identical. This causes unintended consequences.

For instances of intermediate drivers, the naming convention requires that you append the underlying miniport name:

<Intermediate_Driver>\<Underlying_Miniport_Driver>

For example, an intermediate driver would be registered as follows:

{98C5250D-C29A-4985-AE5F-AFE5367E5006}\PASS\NETCARD  

Ee483408.collapse(en-US,WinEmbedded.60).gifIssues with Power Management and NDIS Intermediate Drivers

After the intermediate driver is initialized, it receives a query of OID_PNP_CAPABILITIES. The DDK documentation at MSDN indicates that the intermediate driver should not pass down the OIDs which are direct mappings from PM IRPs. These OIDs include OID_PNP_QUERY_POWER and OID_PNP_SET_POWER. Therefore, the PASSTHRU sample driver correctly blocks these queries to its underlying miniport driver. However, an intermediate driver for Windows Embedded CE should respond to these two queries in a specific way. If the intermediate driver passed down these OIDs, however, it could result in sending duplicate and even conflicting OIDs to the physical adapter.

For the OID_PNP_CAPABILITIES query, if the intermediate driver returns NDIS_STATUS_SUCCESS, it will result in two power manageable adapters that are registered to the Power Manager. However, only the underlying adapter is actually power managed. Currently, there is no mechanism to differentiate a filter driver from MUX driver. Therefore, the user might detect 1 + n instances of power manageable adapters.

This can cause confusion when the GetDevicePower or SetDevicePower functions are used, and the caller assumes that the NDIS and PM names are identical. The OID_PNP_CAPABILITIES query and the PASSTHRU example both return NDIS_STATUS_SUCCESS when both instance names are queried. However, the success return code from an intermediate driver does not change the power state of the underlying adapter. Therefore, a user might interpret that the underlying driver is powered down when it is actually still running at full power.

Ee483408.collapse(en-US,WinEmbedded.60).gifRecommendations for Power Management and NDIS Intermediate Drivers

To address the issues described in the previous paragraphs, the following list provides recommendations for enabling a NDIS intermediate driver to work correctly with Power Manager.

  • An intermediate driver should indicate set DisablePowerManagement in the registry. For more information about this registry setting, see TCP/IPv4 and TCP/IPv6 Common Registry Settings. When this is set, NDIS will not register the virtual adapter instance or the intermediate driver instances to the Power Manager.

  • An intermediate driver should accurately report the OID_PNP_CAPABILITIES of the underlying miniport driver to which it binds. This will enable wake-on LAN requirements to be passed to the underlying miniport driver.

  • After reporting capabilities of the underlying miniport driver, an intermediate driver should pass-through the Power Management OIDs that it receives: OID_PNP_ENABLE_WAKE_UP, OID_PNP_WAKE_UP_PATTERN, and so on. It should not pass-through OID_PNP_QUERY_POWER and OID_PNP_SET_POWER, according to the DDK.

  • An intermediate driver should call NdisIMNotifyPnPEvent when its protocol driver PNP handler receives a net event. By calling this function, upper layer protocol drivers can detect an adapter power change of the underlying miniport driver that the filter I/M driver proxy. Starting in Windows Embedded CE 6.0, NDIS also passes up the NetEventSetPower event.

  • Applications should use the RequestDeviceNotifications function to enumerate the power manageable NDIS drivers. Calls to the SetDevicePower function should be made to the underlying adapter, which will change the power state.

  • Starting in CE 6.0, we recommend that an intermediate driver set the FilterDriver registry entry so that the network utility application will accurately identify it. The driver should also identify its UnderlyingAdapterName in the registry. This enables the network utility application software to accurately identify the real miniport driver it controls. The following is an example of a registry entry:

        [HKLM\Comm\PASS\PCCARD\NE20001]        " FilterDriver"=dword:1         " UnderlyingAdapterName"="PCCARD\\NE20001" 
    
  • In earlier versions, a deadlock issue occurred in the PASSTHRU sample when it performed binding operations in its bind handler. This issue does not occur in CE 6.0.

See Also

Concepts

Miniports, Intermediate Drivers, and Protocol Drivers
NDIS Driver Upper-Edge Functions
NDIS Protocol Driver Lower-Edge Functions