NDIS miniport installation problems...

I’m still having issues getting my NDIS driver initialized. I thought I
had the issue resolved, however my install script was doing a devcon
install, instead of an update.

Here is what I have at the moment…

My bus driver creates a PDO with:

WdfDeviceInitSetDeviceType(init, FILE_DEVICE_BUS_EXTENDER);

WdfDeviceCreate(…)
WdfDeviceSetPnpCapabilities(…)
WdfDeviceSetPowerCapabilities(…)
WdfDeviceAddQueryInterface(…)

No errors during execution.

In the NDIS driver, my DriverEntry does: (same as usbnwifi)

WDF_DRIVER_CONFIG_INIT(&dc, WDF_NO_EVENT_CALLBACK);
dc.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
nrc = WdfDriverCreate(obj, path, WDF_NO_OBJECT_ATTRIBUTES,
&dc, &fw_handle);

< fill in a NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS struct>

rc = NdisMRegisterMiniportDriver(obj, path, (PNDIS_HANDLE)
driver_context, &c, &mp_handle);

Again, no errors and DriverEntry returns with NDIS_STATUS_SUCCESS.

When I do:

devcon update netnovl.inx VBUS\test_dev_10

The NDIS driver loads and immediately unloads without calling the
Initialize routine and device manager reports “code 31”.

The inx file for the NDIS driver has:

[novell.ndi.NTx86]
Characteristics = 0x82
AddReg = venet.reg
CopyFiles = novell.CopyFiles
*IfType = 6 ; IF_TYPE_ETHERNET_CSMACD
*MediaType = 0
*PhysicalMediaType = 14

I’m not sure if this is entirely correct. From what I see in the
documentation, MediaType = 0 (NdisMedium802_3) is “not supported” in
ndis 6.0, but nothing else makes sense. I’m trying to create a standard
NIC driver here.

Is this enough information? I can’t see what I’m doing wrong here. Any
ideas? (I’ve tried a brute force method of changing MediaType and
PhysicalMedia to no avail…)

Again, the basic problem I see thus far is that my NDIS driver
Initialize function is not called, unless I do a “devcon install”, which
I think is wrong for a PnP device…

THanks,
-PWM

Like the sample, you driver build project should be processing the .INX file
*into* an .INF file.

That way those pesky $ARCH$ macros will get expanded into x86 or amd64 as
appropriate and the Version line will be stamped with something reasonable.

If you have decide to just do the substitutions yourself, well, you should
have changed the file extension to .INF to meet with convention and
expectation.

Devcon install will create a root enumerated device with the DeviceId
specified. It will call the equivalent of ‘update’ too so.

I suspect you have done a really good job of getting lots of variants of
your driver package (broken variants) installed into the driver store with
little hope of it ever working correctly until you clean-up.

So to that end, you likely need to learn about a few more devcon commands
like:

Find all of your device nodes that have been left around with variants of
the command:
devcon findall “”
devcon findall “@*\VBUS*”

Delete the device instances found above:
for %d in (“” “” …) do devcon remove %d

Find the driver packages from your activity:
devcon dp_enum

Delete all of the driver packages kicking about found above.
for %p in (oem.inf oem.inf …) do devcon dp_delete %p

or set the environment variable DEVMGR_SHOW_NONPRESENT_DEVICES=1 and start
DevMgmt.msc, select Show Hidden Devices, go find all of yours, delete them,
and check “uninstall driver software associated with this device”

After you have eradicated all of the broken information from the PnP and
DevInst systems, perhaps we can then have a look at your INF in its entirety
or AT LEAST show us the Manufacture section(s) so we can seen what the
device ID looks like.

Then you can use devcon to dump out your child device node before you
install anything like your driver on it so we can see what PnP has decided
the DeviceID is.

I have to say, I don’t know what the big issue is here other than that you
don’t at all seem to be hesitant to make changes where none are warranted.
If you start with a sample, make small incremental changes and verify them.
When you break something, find out why. If this is your first Windows
driver, well, expect to do things “just because that is the way” until you
get a black-belt in Windows device install and can make those changes
knowing the effect in advance.

The NDISEDGE sample would probably load on your device instance with nothing
but the addition of your PnP Device ID to the manufacture section of that
samples INF. You can presumably neuter that sample via deletion of all of
its functionality that tries to do stuff with the WDM lower edge to the
point where it will at least load. Your own driver should probably have
started at that point too.

Getting the install correct and ‘skeleton’ driver loading and unloading
ought to be the first step.

If you want, contact me off-list and send me the INF. You seem to be in the
weeds.

Good Luck,
Dave Cattley

Initially sent directly to David, however this will all be open sourced
eventually anyway… I’d be happy to send the driver code as well if anyone is interested.

(2nd time… Hummm no attachments to netdev, eh? :slight_smile:

On Fri, 2009-12-11 at 14:50 -0500, David R. Cattley wrote:

Like the sample, you driver build project should be processing the .INX file
*into* an .INF file.

My makefiles do create a .inf file from the inx file. That is not the
issue.

chkinf likes the inf as well. No errors nor warnings. That was not
always the case.

That way those pesky $ARCH$ macros will get expanded into x86 or amd64 as
appropriate and the Version line will be stamped with something reasonable.

If you have decide to just do the substitutions yourself, well, you should
have changed the file extension to .INF to meet with convention and
expectation.

Not completely sure I understand this. The samples mostly seem to work
with .inx files and call stampinf in the makefiles. I followed this
model in the bus driver as well as the ndis driver.

Devcon install will create a root enumerated device with the DeviceId
specified. It will call the equivalent of ‘update’ too so.

I suspect you have done a really good job of getting lots of variants of
your driver package (broken variants) installed into the driver store with
little hope of it ever working correctly until you clean-up.

So to that end, you likely need to learn about a few more devcon commands
like:

Find all of your device nodes that have been left around with variants of
the command:
devcon findall “”
> devcon findall “@*\VBUS*”
>
> Delete the device instances found above:
> for %d in (“” “” …) do devcon remove %d
>
> Find the driver packages from your activity:
> devcon dp_enum
>
> Delete all of the driver packages kicking about found above.
> for %p in (oem.inf oem.inf …) do devcon dp_delete %p
>

> or set the environment variable DEVMGR_SHOW_NONPRESENT_DEVICES=1 and start
> DevMgmt.msc, select Show Hidden Devices, go find all of yours, delete them,
> and check “uninstall driver software associated with this device”
>
> After you have eradicated all of the broken information from the PnP and
> DevInst systems, perhaps we can then have a look at your INF in its entirety
> or AT LEAST show us the Manufacture section(s) so we can seen what the
> device ID looks like.
>

I am (somewhat) familiar with devcon and its capabilities, however I do
all this in a much easier fashion. I merely delete the VM image and
copy a new one from a backup.

The backup image is a pristine win7 32bit image with all current updates
installed. (current as of yesterday)

To back up a bit, I am developing a set of drivers to take advantage of
a new bus technology for virtualization on Linux platforms. The uses a
hypervisor based on kvm.

I keep the source on a share exported from a server, and map the share
to the image so I can replace the image at will.

After installing both the bus driver and the ndis driver, device manager
shows the bus installed correctly and one of the two PDOs correctly
assigned given the name I assigned. The other PDO shows up in the
“Other” class since there is no driver associated with the hwid.

As best I can see, this all looks correct.

> Then you can use devcon to dump out your child device node before you
> install anything like your driver on it so we can see what PnP has decided
> the DeviceID is.

I have done this and the hardware ids for the PDOs show up as expected.

The bus hwids:

PCI\VEN_11DA&DEV_2000&SUBSYS_11001AF4&REV_02\3&13C0B0C5&0&18
Name: VBus Enumerator
Hardware IDs:
PCI\VEN_11DA&DEV_2000&SUBSYS_11001AF4&REV_02
PCI\VEN_11DA&DEV_2000&SUBSYS_11001AF4
PCI\VEN_11DA&DEV_2000&CC_068000
PCI\VEN_11DA&DEV_2000&CC_0680
Compatible IDs:
PCI\VEN_11DA&DEV_2000&REV_02
PCI\VEN_11DA&DEV_2000
PCI\VEN_11DA&CC_068000
PCI\VEN_11DA&CC_0680
PCI\VEN_11DA
PCI\CC_068000
PCI\CC_0680
1 matching device(s) found.

The bus driver also finds its hardware resources correctly and maps them
appropriately.

The PDOs (the bus driver creates) hwids:

VBUS\TEST_DEV_10\4&306CFD90&0&10
Name: Vbus virtual ethernet id = 10
Hardware IDs:
VBUS\test_dev_10
Compatible IDs:
VBUS\test_dev_10
VBUS\TEST_DEV_11\4&306CFD90&0&11
Name: Vbus virtual ethernet id = 11
Hardware IDs:
VBUS\test_dev_11
Compatible IDs:
VBUS\test_dev_11
2 matching device(s) found.

I install the ndis driver with:

% devcon update netnovl.inf VBUS\test_dev_10

>
> I have to say, I don’t know what the big issue is here other than that you
> don’t at all seem to be hesitant to make changes where none are warranted.
> If you start with a sample, make small incremental changes and verify them.
> When you break something, find out why. If this is your first Windows
> driver, well, expect to do things “just because that is the way” until you
> get a black-belt in Windows device install and can make those changes
> knowing the effect in advance.

This is my second. The bus driver being the first. And it is not
complete by any means. It merely loads, and starts, and creates 2
PDO’s. It too is a skeleton at this point.

The big issue is the tremendous learning curve one has to go through to
not only write a windows driver, but get the install correct. This is
huge and I am learning. I started two months ago.

Compound that with seemingly different interfaces and requirements for
creating both a bus driver (pure kmdf) as well as a NIC driver (Ndis)
and you are correct, I am floundering. Badly.

To really show you how lost I am, my background is entirely in storage
and file system kernel development. Networking is also new ground.

>
> The NDISEDGE sample would probably load on your device instance with nothing
> but the addition of your PnP Device ID to the manufacture section of that
> samples INF. You can presumably neuter that sample via deletion of all of
> its functionality that tries to do stuff with the WDM lower edge to the
> point where it will at least load. Your own driver should probably have
> started at that point too.
>

I do not have the NDISEDGE sample. It does not exist in the current WDK
as best I can tell. It certainly is not in the ndis samples directory.
I wish I had simple NIC driver sample.

Regardless, the code in the samples is copyrighted by Microsoft. I am
creating my own sources based entirely upon what is presented in the
sample. usbnwifi comes fairly close, but it is not a generic nic driver
according to what I see in the .inx files as well as from what I gleam
through the documentation.

Regardless, my skeleton is exactly that: a skeleton. It contains all
the callbacks for the miniport and all except for *Initialize do nothing
other than print a text message to COM1, which is displayed on the
hypervisor window.

I have a very simple goal at this point:

Have the ndis driver obtain the bus interface exported by the PDO’s
created by the bus driver.

This should prove install, to my mind. Once this is complete, I will
run with the rest of the implementation.

This is, in fact, all that the ndis driver *Initialize function does.
Allocate a context, attempt to get the PDO bus interface.

There is no other executable code in the ndis driver save the OID
handling which I saw as tedious busy work since I had to review each OID
in the documentation tree to find out what was supported and required.
(Oid handling also has traces and those routines are not being
executed.)

> Getting the install correct and ‘skeleton’ driver loading and unloading
> ought to be the first step.

The ndis driver does load and unload properly. The precise order is
DriverEntry, *SetOptions, and *Unload. In that order.

>
> If you want, contact me off-list and send me the INF. You seem to be in the
> weeds.

Utterly.

*inx below

Thanks,
-PWM

;
; Copyright (c) 2009 Novell Inc.
;
; INF file for installing the Novell Virtual Ethernet Adapter.
;
;

[version]
Signature = “$Windows NT$”
Class = Net
ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}
Provider = %Novl%
CatalogFile = venet.cat
DriverVer = 12/09/2009,1.0.0000.00000

[Manufacturer]
%Novl% = Novl, NTamd64, NTx86

[ControlFlags]
ExcludeFromSelect = *

[Novl.NTx86]
; DisplayName Section DeviceID
; ----------- ------- --------
%Novl.Device_desc% = novell.ndi, VBUS\test_dev_10

[Novl.NTamd64]
; DisplayName Section DeviceID
; ----------- ------- --------
%Novl.Device_desc% = novell.ndi, VBUS\test_dev_10

[novell.ndi.NTx86]
Characteristics = 0x82
AddReg = venet.reg
CopyFiles = novell.CopyFiles
*IfType = 6 ; IF_TYPE_ETHERNET_CSMACD
*MediaType = 0
*PhysicalMediaType = 14

;*MediaType = 0 ; NdisMedium802_11
;*PhysicalMediaType = 0 ; NdisPhysicalMediumUnspecified
;*PhysicalMediaType = 14 ; NdisPhysicalMedium802_3

[novell.ndi.NTAMD64]
Characteristics = 0x82
AddReg = venet.reg
CopyFiles = novell.CopyFiles
*IfType = 6 ; IF_TYPE_ETHERNET_CSMACD
*MediaType = 0
*PhysicalMediaType = 14

[novell.ndi.NTx86.Services]
AddService = venet, 2, novell.Service

[novell.ndi.NTAMD64.Services]
AddService = venet, 2, novell.Service

[novell.Service]
DisplayName = %Novell.Service.DispName%
ServiceType = 1 ;SERVICE_KERNEL_DRIVER
StartType = 3 ;SERVICE_DEMAND_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary = %12%\venet.sys
;LoadOrderGroup = NDIS

[venet.reg]
HKR, Ndi, Service, 0, “venet”

HKR, Ndi\Interfaces, UpperRange, 0, “ndis5”
HKR, Ndi\Interfaces, LowerRange, 0, “ethernet”

HKR, Ndi\params*ReceiveBuffers, ParamDesc, 0, “%ReceiveBuffers%”
HKR, Ndi\params*ReceiveBuffers, default, 0, “64”
HKR, Ndi\params*ReceiveBuffers, min, 0, “1”
HKR, Ndi\params*ReceiveBuffers, max, 0, “00000128”
HKR, Ndi\params*ReceiveBuffers, step, 0, “1”
HKR, Ndi\params*ReceiveBuffers, Base, 0, “10”
HKR, Ndi\params*ReceiveBuffers, type, 0, “int”

HKR, Ndi\params*TransmitBuffers, ParamDesc, 0, “%TransmitBuffers%”
HKR, Ndi\params*TransmitBuffers, default, 0, “20”
HKR, Ndi\params*TransmitBuffers, min, 0, “1”
HKR, Ndi\params*TransmitBuffers, max, 0, “00000020”
HKR, Ndi\params*TransmitBuffers, step, 0, “1”
HKR, Ndi\params*TransmitBuffers, Base, 0, “10”
HKR, Ndi\params*TransmitBuffers, type, 0, “int”

[novell.CopyFiles]
venet.sys,2

[SourceDisksNames]
1 = %DiskDescription%,venet.sys,

[SourceDisksNames]
1 = %DiskDescription%,venet.sys,

[SourceDisksFiles]
venet.sys = 1,

[DestinationDirs]
novell.CopyFiles = 12

;-------------- WDF Coinstaller installation

[DestinationDirs]
CoInstaller_CopyFiles = 11

[novell.ndi.NTx86.CoInstallers]
AddReg=CoInstaller_AddReg
CopyFiles=CoInstaller_CopyFiles

[novell.ndi.NTAMD64.CoInstallers]
AddReg=CoInstaller_AddReg
CopyFiles=CoInstaller_CopyFiles

[CoInstaller_CopyFiles]
wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll

[SourceDisksFiles]
wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with
SourceDisksNames

[CoInstaller_AddReg]
HKR,CoInstallers32,0x00010000, “wdfcoinstaller$KMDFCOINSTALLERVERSION$.dll,WdfC
oInstaller”

[novell.ndi.NTx86.Wdf]
KmdfService = venet, novell_wdfsect

[novell.ndi.NTAMD64.Wdf]
KmdfService = venet, novell_wdfsect

[novell_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$

;---------------------------------------------------------------;

[Strings]
Novl = “Novell”
Novell = “Novell Inc”
Novl.Device_desc = “AlacrityVM Virtual Ethernet Adapter”
Novell.Service.DispName = “AlacrityVM Virtual Ethernet (venet) driver”
DiskDescription = “Novell Sample Driver Disk 1”
TransmitBuffers = “Transmit Buffers”
ReceiveBuffers = “Receive Buffers”

Peter,

One thing I noted in this INF is that the NDI Characteristics for the NIC
device are being set to 0x82 which is NCF_HAS_UI | NCF_SOFTWARE_ENUMERATED
(or NCF_WRAPPER as it was once known).

I believe it should be NCF_HAS_UI | NCF_VIRTUAL (your NIC device is a
‘virtual’ NIC ) or 0x81.

NCF_SOFTWARE_ENUMERATED sounds like just what you have but in this case, it
is most definately not. This NCF_ flag indicates to NDIS that the device
has been enumerated by the SWENUM virtual bus. This is used (exclusively?)
by system components like NDISWAN to enumerate ‘software NICs’ that have
some special mojo (undocumented of course and inaccessible to the rest of us
that would like to do the same thing!).

Your NIC is ‘virtual’ not ‘software enumerated’.

Start with that change and then see what happens.

Good Luck,
Dave Cattley