Hi all,

E100BEX is a miniport driver given as a sample with PB 5.0. It handles
Intel's 825xx Ethernet PCI chips and illustrates a few useful techniques for
writing NDIS 5.1 miniport drivers. Unfortunately, there is a problem in the
way E100BEX handles the interrupts.

This can be seen when E100BEX is used with GIISR.DLL on a shared interrupt
level.
For instance, a typical Registry entry for this driver is:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\E100BEX]
;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:F000

When the 825xx interrupt fires, it is handled by PeRPISR that calls
NKCallIntChain for the active level.
NKCallIntChain then calls GIISR's ISRHandle, that tests active bits of the
ScbStatus register of the controller against PortMask.
As the result of the test is positive, ISRHandle returns a valid SysIntr for
the interrupt and the matching IST in NDIS is eventually called.
The IST in NDIS calls MPIsr in E100BEX, that read 2 controller registers:
ScbCommandHigh to check that the interrupt is not masked at the controller
level and ScbStatus, indicating what interrupt sources (Rx, Tx, etc.) are
currently active. When both the interrupts are unmasked and active sources
can be seen, MPIsr writes ScbCommandHigh to mask the controller interrupts
and return TRUE to NDIS.
NDIS then calls InterruptDone: new interrupts can occur on the same level.
When E100BEX is the only possible interrupt source on this level, after
having called InterruptDone, NDIS posts a DPC that ends in E100BEX
MPHandleInterrupt routine.
MPHandleInterrupt reads ScbStatus again and writes it back to clear the bits
of the active sources. Then it processes the controller interrupts and
finally writes to ScbCommandHigh to enable the controller interrupts again.

When another device shares the same interrupt level and is located in the
interrupt chain *after* the ISRHandler instance of E100BEX, things usually
go bad. As an illustration, imagine this scenario:

1) A 825xx interrupt is processed up to the point where NDIS calls
InterruptDone, after MPIsr. The controller interrupt is disabled in
ScbCommandHigh but the active interrupt sources are still set in ScbStatus.
2) Right after InterruptDone, an interrupt pending on the other device
is processed. NKCallIntChain is called starting with GIISR's ISRHandle for
E100BEX. Unfortunately, the ScbStatus bits are still set and the SysIntr for
NDIS/E100BEX is improperly returned.
3) MPIsr is called but as the controller interrupt is masked, it returns
FALSE.
4) InterruptDone is called and as the interrupt of the other device is
still active, we restart to 2): the system is hanged.

The problem can easily be fixed by resetting ScbStatus bits in MPIsr instead
of MPHandleInterrupt.

Remi

RE: GIISR, NDIS and E100BEX bad interrupt handling by davidka

davidka
Mon Nov 27 18:50:25 CST 2006

Thanks for the analysis. I have forwarded your report to the appropriate
group.
I agree. The interrupt status bits should be remembered in the miniport
adapter structure and acknowledged on the NIC so that subsequent interrupts
aren't incorrectly routed.

David Kanz [MSFT]
This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
| From: "Remi de Gravelaine" <gravelaine at aton dash sys dot fr>
| Subject: GIISR, NDIS and E100BEX bad interrupt handling
| Date: Mon, 27 Nov 2006 17:53:17 +0100
| Lines: 71
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2900.2869
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2962
| X-RFC2646: Format=Flowed; Original
| Message-ID: <##ZePSkEHHA.4992@TK2MSFTNGP03.phx.gbl>
| Newsgroups: microsoft.public.windowsce.platbuilder
| NNTP-Posting-Host: lns-bzn-45-82-65-162-50.adsl.proxad.net 82.65.162.50
| Path: TK2MSFTNGXA01.phx.gbl!TK2MSFTNGP01.phx.gbl!TK2MSFTNGP03.phx.gbl
| Xref: TK2MSFTNGXA01.phx.gbl microsoft.public.windowsce.platbuilder:90627
| X-Tomcat-NG: microsoft.public.windowsce.platbuilder
|
| Hi all,
|
| E100BEX is a miniport driver given as a sample with PB 5.0. It handles
| Intel's 825xx Ethernet PCI chips and illustrates a few useful techniques
for
| writing NDIS 5.1 miniport drivers. Unfortunately, there is a problem in
the
| way E100BEX handles the interrupts.
|
| This can be seen when E100BEX is used with GIISR.DLL on a shared
interrupt
| level.
| For instance, a typical Registry entry for this driver is:
|
| [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCI\Template\E100BEX]
| ;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:F000
|
| When the 825xx interrupt fires, it is handled by PeRPISR that calls
| NKCallIntChain for the active level.
| NKCallIntChain then calls GIISR's ISRHandle, that tests active bits of
the
| ScbStatus register of the controller against PortMask.
| As the result of the test is positive, ISRHandle returns a valid SysIntr
for
| the interrupt and the matching IST in NDIS is eventually called.
| The IST in NDIS calls MPIsr in E100BEX, that read 2 controller registers:
| ScbCommandHigh to check that the interrupt is not masked at the
controller
| level and ScbStatus, indicating what interrupt sources (Rx, Tx, etc.) are
| currently active. When both the interrupts are unmasked and active
sources
| can be seen, MPIsr writes ScbCommandHigh to mask the controller
interrupts
| and return TRUE to NDIS.
| NDIS then calls InterruptDone: new interrupts can occur on the same level.
| When E100BEX is the only possible interrupt source on this level, after
| having called InterruptDone, NDIS posts a DPC that ends in E100BEX
| MPHandleInterrupt routine.
| MPHandleInterrupt reads ScbStatus again and writes it back to clear the
bits
| of the active sources. Then it processes the controller interrupts and
| finally writes to ScbCommandHigh to enable the controller interrupts
again.
|
| When another device shares the same interrupt level and is located in the
| interrupt chain *after* the ISRHandler instance of E100BEX, things
usually
| go bad. As an illustration, imagine this scenario:
|
| 1) A 825xx interrupt is processed up to the point where NDIS calls
| InterruptDone, after MPIsr. The controller interrupt is disabled in
| ScbCommandHigh but the active interrupt sources are still set in
ScbStatus.
| 2) Right after InterruptDone, an interrupt pending on the other
device
| is processed. NKCallIntChain is called starting with GIISR's ISRHandle
for
| E100BEX. Unfortunately, the ScbStatus bits are still set and the SysIntr
for
| NDIS/E100BEX is improperly returned.
| 3) MPIsr is called but as the controller interrupt is masked, it
returns
| FALSE.
| 4) InterruptDone is called and as the interrupt of the other device
is
| still active, we restart to 2): the system is hanged.
|
| The problem can easily be fixed by resetting ScbStatus bits in MPIsr
instead
| of MPHandleInterrupt.
|
| Remi
|
|
|


Re: GIISR, NDIS and E100BEX bad interrupt handling by Remi

Remi
Tue Nov 28 03:03:22 CST 2006

Thanks for the feedback.

Also note that in the current state of the driver, saving the status bits is
useless: MPHandleInterrupt just ignores the contents of ScbStatus and
systematically check and processes all the possible interrupt sources. Not
very subtle but efficient!

Remi