Hello,

I am writing an NDIS driver for a PCI NIC (Intel Pro Wireless 2200) on a
CEPC, for CE.net 4.2.
The platform is equiped with another Ethernet chip on the PCI bus. The
driver for this chip comes from Intel (E100CE.DLL, for 8255X network chips.)
Both NICs are wired to the first available PCI interrupt, which is IRQ6
(INTA) in my configuration.

When I enable the E100CE driver in my project, it is initialized before my
IPWL2200 driver and NdisMRegisterInterrupt produces this output:

Loaded 'G:\WINCE420\PUBLIC\EBB615EX\RELDIR\DEBUG\E100CE.DLL', no matching
symbolic information found.
4294778928 ==>NdisInitializeWrapper
4294778929 <==NdisInitializeWrapper
4294778931 ==>NdisMRegisterMiniport: NdisWrapperHandle 0004BBA0
4294778932 ==>ndisRegisterMiniportDriver: NdisWrapperHandle 0004BBA0
4294778933 <==ndisRegisterMiniportDriver: MiniBlock 0004BC10
4294778935 NdisMRegisterMiniport: MiniBlock 0004BC10
4294778936 <==NdisMRegisterMiniport: MiniBlock 0004BC10, Status 0
4294778940
4294778942 ndisMInitializeAdapter: Miniport 0004BE28,
4294778944 ==>ndisQueueMiniportOnDriver: Miniport 0004BE28, MiniBlock
0004BC10
4294778945 <==ndisQueueMiniportOnDriver: Miniport 0004BE28, MiniBlock
0004BC10, rc 1
4294778946 ==>NdisMSetAttributesEx: Miniport 0004BE28
4294778948 ==>NdisMMapIoSpace
4294778950 ***NDIS*** (a, 514)
4294778951 ==>NdisMRegisterInterrupt: Miniport 0004BE28 Vector 6
4294778953 0x8fbadbb8: NDIS:: CeConnectInterrupt() --> IRQ[6] SYSINTR[34]
4294778954 ***NDIS*** (a, 719)
4294778956 <==NdisMRegisterInterrupt: Miniport 0004BE28, Status 0

Then my driver initializes and a DEBUGCHK is issued by
NdisMRegisterInterrupt code:

Loaded symbols for 'G:\WINCE420\PUBLIC\EBB615EX\RELDIR\DEBUG\IPWL2200.DLL'
4294783878 ==>NdisInitializeWrapper
4294783879 <==NdisInitializeWrapper
4294783881 ==>NdisMRegisterMiniport: NdisWrapperHandle 000539A0
4294783882 ==>ndisRegisterMiniportDriver: NdisWrapperHandle 000539A0
4294783883 <==ndisRegisterMiniportDriver: MiniBlock 00053A10
4294783885 NdisMRegisterMiniport: MiniBlock 00053A10
4294783886 <==NdisMRegisterMiniport: MiniBlock 00053A10, Status 0
4294783889
4294783890 ndisMInitializeAdapter: Miniport 00053C28,
4294783892 ==>ndisQueueMiniportOnDriver: Miniport 00053C28, MiniBlock
00053A10
4294783893 <==ndisQueueMiniportOnDriver: Miniport 00053C28, MiniBlock
00053A10, rc 1
4294783899 ==>NdisMSetAttributesEx: Miniport 00053C28
4294783906 ==>NdisMMapIoSpace
4294783951 ***NDIS*** (a, 514)
4294783965 ==>NdisMRegisterInterrupt: Miniport 00053C28 Vector 6
4294784133 0x8fbadbb8: NDIS:: CeConnectInterrupt() --> IRQ[6] SYSINTR[33]
4294784154 0x8fbadbb8: Unknown: DEBUGCHK failed in file
d:\mckendric\private\winceos\comm\ndis51\sys\.\timerm.c at line 688
4294784187 ***NDIS*** (a, 719)
4294784197 <==NdisMRegisterInterrupt: Miniport 00053C28, Status 0

The call to NdisMRegisterInterrupt succeeds but my system hangs when the
2200 fires its first interrupt.

Both drivers use giisr.dll for their interrupt handling:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\E100CE]
;PCI Bus Enumeration Information
"Class"=dword:02
"SubClass"=dword:00
"ProgIF"=dword:0
"VendorID"=multi_sz:"8086","8086","8086"
"DeviceID"=multi_sz:"1209","1229","2449"
"Dll"="NDIS.dll"
"Entry"="NdisPCIBusDeviceInit"
"Transceiver"=dword:3
;Installable ISR Handler Information
"IsrDll"="giisr.dll"
"IsrHandler"="ISRHandler"
"PortIsIO"=dword:0
"PortOffset"=dword:0
"PortSize"=dword:4
"PortMask"=dword:20F0

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\IPWL2200]
"Dll"="NDIS.dll"
"Class"=dword:02
"SubClass"=dword:80
"ProgIF"=dword:0
"VendorID"=multi_sz:"8086"
"DeviceID"=multi_sz:"4220"
"Entry"="NdisPCIBusDeviceInit"
;Installable ISR Handler Information
"IsrDll"="giisr.dll"
"IsrHandler"="ISRHandler"
"PortIsIO"=dword:0
"PortOffset"=dword:8
"PortSize"=dword:4
"PortMask"=dword:C5311832

As far as I could debug, after a sucessful call to CeConnectInterrupt,
NdisMRegisterInterrupt puts in a table indexed by the IRQ Vector
(InterruptVector, i.e. IRQ number) the handle of the calling miniport
(MiniportAdapterHandle).
The first time NdisMRegisterInterrupt is called, this table entry is NULL
upon entry so the first calling MiniportAdapterHandle is written at
Table[InterruptVector]; in addition a variable local to
NdisMRegisterInterrupt ([ebp-228h]) is set to TRUE.
The second time NdisMRegisterInterrupt is called, Table[InterruptVector] is
not NULL anymore so the DEBUGCHK is called, previously-mentionned local
variable is set to FALSE and the new MiniportAdapterHandle overwrites
previous Table[InterruptVector] value.
Please note that the [ebp-228h] variable is no used anymore.

I have 2 questions:

1) Is this DEBUGCHK really useful?
2) Does anybody here have an idea of what happens when the interrupt hangs
the system?

Thanks for your future answers.
--
Remi de Gravelaine
gravelaine at aton dash sys dot fr

Re: NdisMRegisterInterrupt DEBUGCHK in Wince 4.2 by Remi

Remi
Mon Aug 29 11:25:02 CDT 2005

Forget the "hanging" bug...

After some debugging, I discovered that the bug came from the E100CE driver
configuration: the 0x20F0 value for "PortMask" is not suitable, as the
interrupt signaling bits for 8255X chips are bits 12 to15! A much more
efficient value for PortMask is 0xF000.
With the stupid 0x20F0 mask, every PCI interrupt using the same number that
the 8255X chip triggers the ndisMIsr and the E100CE ISR, that will not know
what to do with it. As the interrupt remains active on the bus, the system
hangs, stucked in a useless and repetitive interrupt servicing.

The DEBUGCHK issue remains.

Remi de Gravelaine
gravelaine at aton dash sys dot fr


Re: NdisMRegisterInterrupt DEBUGCHK in Wince 4.2 by stjong

stjong
Wed Aug 31 21:16:30 CDT 2005

The ASSERT is not really useful for your case as both cards are not sharing
the same Interrupt ID.
I'll file a bug to have this ASSERT fine tuned.
Can you confirm that after you resolved the hang issue both cards now work
correctly?
Thanks,
-- Soemin ---
Windows CE CoreOS/Networking
This posting is provided "AS IS" with no warranties, and confers no rights.


Re: NdisMRegisterInterrupt DEBUGCHK in Wince 4.2 by Remi

Remi
Sun Sep 04 13:00:23 CDT 2005

Thanks for your answer, Soemin.

> Can you confirm that after you resolved the hang issue both cards now work
> correctly?

It actually depends on the driver you use for Intel 8255X chip.

For my x86 platforms, I use what I call the "old" E100CE.DLL from Intel.
This driver is dated march, 7, 2002 and has 22016 bytes. This drivers
behaves correctly and the registry fix (i.e. replacing 20F0 value in
E100CE.REG by F000) appears to be OK.
Unfortunately, the "new" version of E100CE.DLL (the one you can currently
find on Intel site) introduces a very bad feature: there is a hard-coded
sequence that immediately precedes the regular NdisMRegisterInterrupt call
and that enforces a call to KernelLibIoControl supplying to GIISR.DLL a
GIISR_INFO with the buggous 0x2F00 Mask value!!!

From "dumpbin /disasm e100ce.dll" (comments are from me):

1000198B: 8B 45 FC mov eax,dword ptr [ebp-4]
1000198E: 53 push ebx ;
lpBytesReturned = NULL;
1000198F: 53 push ebx ;
nOutBufSize = 0;
10001990: 53 push ebx ;
lpOutBuf = NULL
10001991: 8B 88 D0 03 00 00 mov ecx,dword ptr [eax+000003D0h]
10001997: 6A 20 push 20h ;
nInBufSize = sizeof(GIISR_INFO)
10001999: 89 4D BC mov dword ptr [ebp-44h],ecx ;
GiisrInfo.SysIntr
1000199C: 8B 4D 10 mov ecx,dword ptr [ebp+10h]
1000199F: 89 4D CC mov dword ptr [ebp-34h],ecx ;
GiisrInfo.PortAddress
100019A2: 8D 4D BC lea ecx,[ebp-44h]
100019A5: 51 push ecx ;
lpInBuf = &GiisrInfo
100019A6: 68 00 01 00 00 push 100h ;
dwIoControlCode = IOCTL_GIISR_INFO
100019AB: C7 45 C0 01 00 00 mov dword ptr [ebp-40h],1 ;
GiisrInfo.CheckPort = TRUE;
00
100019B2: 89 5D C4 mov dword ptr [ebp-3Ch],ebx ;
GiisrInfo.PortIsIO = FALSE;
100019B5: 89 5D C8 mov dword ptr [ebp-38h],ebx ;
GiisrInfo.UseMaskReg = FALSE;
100019B8: C7 45 D0 04 00 00 mov dword ptr [ebp-30h],4 ;
GiisrInfo.PortSize = 4;
00
100019BF: C7 45 D4 F0 20 00 mov dword ptr [ebp-2Ch],20F0h ;
GiisrInfo.Mask = 0x02F0; <<<
00
100019C6: FF B0 C4 03 00 00 push dword ptr [eax+000003C4h] ;
hModule
100019CC: E8 13 3A 00 00 call 100053E4 ;
KernelLibIoControl
100019D1: 83 C4 1C add esp,1Ch

Thus, GIISR's CreateInstance / IoControl are called twice for the same
SYSINTR: once by the above-described call to KernelLibIoControl then once by
NdisMRegisterInterrupt, which uses the Registry values. As a result, the
first instance is always checked first and always returns a valid SYSINTR
value to NKCallIntChain, because 0x20F0 & 0x0050 is always true. This is
clearly an Intel bug but they don't seem to be interrested in it.

I did not try to patch the "new" E100CE driver (for instance by replacing
the 'call KernelLibIoControl' bytes by nop codes) but I suppose this would
work.

For the driver I wrote for Intel 2200BG, I have "fatal errors" from the
firmware when doing large transfers but I am working on it... Except for
this point, the driver is almost functional.

Hope this helped.


--
Remi de Gravelaine
ATON Systèmes
gravelaine at aton dash sys dot fr