SUMMARY
Windows CE .NET supports a peripheral component interconnect (PCI) bus enumerator that can do the following:
- Discover devices that are present on the PCI bus or buses.
- Assign resources to the devices.
- Inform the appropriate driver about the presence of the device.
You can use this feature to simplify the work that you have to do to develop and configure a network driver interface specification (NDIS) miniport driver on Windows CE .NET.
This step-by-step article describes how to enable a PCI network interface card (NIC). All examples will use a network driver interface specification (NDIS) miniport named MYNIC, with the driver in the MyNic.dll file.
back to the topStep 1 - Create a PCI Bus Enumerator Template
You must add registry settings so that the PCI bus enumerator can detect your device. Put the parameters to match your device in a registry key at the following location:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\<template-name>]
Using MYNIC, for example:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\MYNIC]
"Class"=dword:02
"SubClass"=dword:00
"ProgIF"=dword:0
"VendorID"=multi_sz:"1234","5678"
"DeviceID"=multi_sz:"1111","2222"
"Dll"="NDIS.dll"
"Entry"="NdisPCIBusDeviceInit"
Of these registry settings, the PCI bus enumerator uses the following settings to determine whether a PCI card matches this template:
The
"VendorID" and
"DeviceID" values work in pairs. In this example, a PCI card matches if
VendorID=1234 and
DeviceID=1111, or if it has both a
VendorID=5678 value
and a
DeviceID=2222 value. You have to configure all 5 of these parameters as appropriate to match your device.
The
"Dll" and
"Entry" points are used to tell the PCI bus enumerator which driver to inform when it finds a match and creates a device instance. For a PCI NIC that uses NDIS,
"Dll" has to be set to
"ndis.dll" and
"Entry" has to be set to
"NdisPCIBusDeviceInit". Basically, setting
"Dll" to
"ndis.dll" invokes an indirect way of allowing NDIS to load the miniport driver, instead of
PCIEnum loading it directly. NDIS is what looks at the
"Entry" value.
By default, the template name (in our example, MYNIC) is used by NDIS as the miniport name. That is, NDIS looks in
[HKEY_LOCAL_MACHINE\Comm\<miniport name>] for the
"ImagePath" value that specifies the location of the miniport driver. If you want to use a miniport name that is different from the template name, you can set the value
"Miniport"="<miniport-name>" in the template.
For example, if you want NDIS to look for miniport driver information in
[HKEY_LOCAL_MACHINE\Comm\Test] instead of in
[HKEY_LOCAL_MACHINE\Comm\MYNIC], use the following:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\MYNIC]
"Miniport"="Test"
Additional registry settings can be part of the template and are not used by the PCI bus enumerator. The additional registry settings are copied to the instance settings for use by the miniport driver (by means of a call to
NdisReadConfiguration).
back to the topAdditional Details About the Template
When the PCI bus enumerator finds a match, it creates an instance entry in the registry. This instance information includes instance-specific resources that are assigned to the adapter, such as its bus type (PCI is always 5), bus number, IRQ, the SysIntr that the IRQ maps to, I/O addresses, and memory addresses.
The name of the instance entry is
HKLM\Comm\<template-name><n>, where
<n> starts at 1 (one) and increments by 1 (one) for each device that matches the template. The PCI bus enumerator then informs NDIS about the device instance, and proceeds to load the driver (if this is the first device instance to use it) and to initialize the device by calling the miniport's
MiniportInitialize handler.
These entries are examined only by
NDIS!NDS_Init. NDIS names the device
"PCI\<instance-name>", for example
"PCI\MYNIC1". Currently, only PCI devices can use the bus type
"PCI" as a component of the NDIS device instance name, therefore, PCMCIA NICs are not named, for example,
"PCMCIA\xxx".
back to the topStep 2 - Create Installable ISR Registry Settings
Windows CE drivers, including NDIS miniport and protocol drivers, run in the context of the Device.exe process, instead of in the kernel context. As a result, a miniport's
MiniportIsr function will run as an interrupt service thread (IST), not as an interrupt service routine (ISR). One limitation of this is that
MiniportIsr cannot decide whether an interrupt was for the device being managed by the miniport (because that decision must be made by the real ISR that runs in the kernel context).
An installable ISR is a function that runs in the kernel context that determines whether your device is generating an interrupt. The function is part of a DLL that is loaded into the kernel context.
A generic installable ISR function called
"ISRHandler" is provided as part of the OS in the module Giisr.dll. This function supports several configurable parameters that allow it to meet the needs of most devices.
For example, for the MYNIC driver to use this installable ISR, add the following settings to the registry:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\MYNIC]
"IsrDll"="giisr.dll"
"IsrHandler"="ISRHandler"
"PortIsIO"=dword:1
"PortOffset"=dword:2C
"PortSize"=dword:2
"PortMask"=dword:F000
About these registry settings:
- These "IsrDll" and "IsrHandler" settings tell the OS to use the generic ISR handler function. The remaining four port parameters configure the generic ISR to determine whether your device has generated an interrupt by reading the device's interrupt status register, or by reading the device's interrupt mask register.
- "PortIsIO"=dword:1 configures the generic ISR handler to read the device's interrupt status register from I/O space. Setting this to dword:0 causes it to be read from memory space.
- "PortOffset"=dword:3C specifies the offset to the interrupt status register from the beginning of the device's IOBase (or MemBase if PortIsIO=dword:0).
If the device has more than one I/O space (or memory space) region, and the interrupt status register is not in the first region, set "PortIndex"=dword:N to the zero-based index of the region to use. For example, if the interrupt status register is in the second region, set "PortIndex"=dword:1. - "PortSize"=dword:2 specifies that the interrupt status register has to be read as a 16-bit value. A setting of dword:1 causes an 8-bit read; a setting of dword:4 causes a 32-bit read.
- "PortMask"=dword:F000 specifies the value to logically "and" with the interrupt status register to determine whether the device is generating an interrupt (a non-zero result indicates that the device is generating an interrupt).
If you also have to read a device's interrupt mask register, set "UseMaskReg"=dword:1 and "MaskOffset"=dword:xx (where xx is the offset from the device's IOBase or MemBase to the mask register).
The mask register will be read using the same width that is specified in "PortSize". The final determination of whether an interrupt is being generated is:
Interrupt_Generated = (Interrupt_Status_Register & PortMask & Interrupt_Mask_Register) != 0;
back to the topStep 3 - Create a Miniport Driver Registry Entry
This registry entry tells NDIS the name of the miniport driver .dll.
For example, using MYNIC:
[HKEY_LOCAL_MACHINE\Comm\MYNIC]
"DisplayName"="My NIC Miniport Driver"
"Group"="NDIS"
"ImagePath"="mynic.dll"
Delete any existing Linkage\Route setting. This setting, which is used to tell NDIS to create a device instance at boot time, must not be present because the PCI bus enumerator now tells NDIS about your PCI device. For example, delete the obsolete Linkage\Route entry if you had created a
MYNIC1 adapter instance by using the following setting:
[HKEY_LOCAL_MACHINE\Comm\MYNIC\Linkage]
"Route"=multi_sz:"MYNIC1"
back to the topStep 4 - Create Other Instance-Specific Settings That You Want
You can assign instance-specific settings for a particular adapter by setting them in:
[HKEY_LOCAL_MACHINE\Comm\<instance-name>\Parms]
For example, to assign a static IP address for the adapter PCI\MYNIC1, add the following registry settings:
[HKEY_LOCAL_MACHINE\Comm\PCI\MYNIC1\Parms\TcpIp]
"EnableDHCP"=dword:0
"DefaultGateway"=multi_sz:"192.168.1.1"
"IpAddress"=multi_sz:"192.168.1.2"
"Subnetmask"=multi_sz:"255.255.255.0"
"UseZeroBroadcast"=dword:0
These registry settings cause the first MYNIC PCI adapter that is enumerated to be assigned the IP address
"192.168.1.2".
back to the topStep 5 - Retrieve or Use Resource Information in the Miniport Driver
The miniport driver can determine the resources that are allocated to an adapter by calling one of the following:
- NdisMQueryAdapterResources.
-or- - NdisReadConfiguration in the miniport driver's MiniportInitialize function.
back to the topA Note About Backward Compatibility
NdisMPciAssignResources in Windows CE .NET relies on the PCI bus enumerator to provide resource information. If your miniport driver calls this API, you must configure the registry to use the PCI bus enumerator for your device.
NOTE: Microsoft recommends that you use
NdisMQueryAdapterResources (instead of
NdisMPciAssignResources, which is discouraged).
back to the top