ndis miniport driver: MPPause callback is not called when the firmware is in an error state

Hello. I have a ndis 6.20 miniport driver that is based on the netvmini example. It works together with a real hardware nic. There is a firmware problem under certain conditions where no frames can be sent. The network stack continues to send frames and my SendNetBufferLists function is called. !ndiskd.pendingnbls shows that my driver has the ownership for several send frames.

Usually, when the driver is disabled in the device manager, MPPause and HaltEx is called. My MPPause function would flush the tx queue (indicate to ndis that the NBLs completed with an error status).

When the firmware is in the error state, I see a behavior that I can’t explain. When the driver is disabled, neither MPPause nor HaltEx is called. The CheckForHang and OIDRequest handlers continue to be called. The device manager window hangs, the mouse pointer is a revolving circle. This goes on forever (several hours). The CPU usage is 0%.

!ndiskd.netadapter shows following info:

Miniport           Running
Device PnP         REMOVED             Show state history
Datapath           Normal
Interface          Up
Media              Connected
Power              D0
References         0n10                Show detail
Total resets       0
Pending OID        None
Flags              BUS_MASTER, 64BIT_DMA, SG_DMA, ALLOW_BUGCHECK_CALLBACK,
                   BUGCHECK_CALLBACK_REGISTERED, DEFAULT_PORT_ACTIVATED,
                   SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK,
                   MEDIA_CONNECTED
PnP flags          PM_SUPPORTED, REMOVE_IN_PROGRESS, DEVICE_POWER_ENABLED,
                   HARDWARE_DEVICE

MINIPORT PM & PNP EVENTS

Event              Timestamp           (most recent event at bottom)        
DeviceAdded
                   4432 ms later
DeviceStart
                   218 ms later
MiniportInitialized
                   9000 us later
MiniportRestarted
                   43 minutes later
DeviceQueryRemove
DeviceRemove
                   Tue Sep  7 10:20:40.725 2021 (UTC + 2:00) Now?

Set a breakpoint on the next event

Here is the callstack, when I break with the debugger in this state:

7: kd> k

Child-SP RetAddr Call Site

00 fffff60a87c7d8f0 fffff8056b462822 kdnic!TXSendCompleteDpc+0x24f
01 fffff60a87c7d930 fffff801d23474f3 kdnic!TXSendCompleteDpc+0x142
02 fffff60a87c7d970 fffff801d234858d nt!KiProcessExpiredTimerList+0x153
03 fffff60a87c7da60 fffff801d241cc5a nt!KiRetireDpcList+0x43d
04 fffff60a87c7dc60 0000000000000000 nt!KiIdleLoop+0x5a

kdnic is not my driver.

I made a test. I disabled the driver while I was in the firmware error state. There were pending tx nbls. The device manager hung. In my CheckForHang function, I called TXFlushSendQueue which indicates to ndis that the nbls are finished with an error state. The MPPause and HaltEx callbacks were called, the device manager disabled the driver and was responsive.

Why is this happening?