I am having trouble with an MSI device.
I am calling IoConnectToInterruptEx(…) with the message based fields of
the parameter structure filled in. The result is always a fall back to a
line based interrupt.
I can see that the adapter has MSI capability (see below).
My client told me that the test computer has MSI capability (how can I
confirm this?).
I plan to use the iointex library to allow a single source for XP through
Windows 7 but have tested without the library on Windows 7 with the same
results.
My code is based on the WDK example of using the iointex libray (
http://msdn.microsoft.com/en-us/library/ff565402(v=vs.85).aspx ) modified
with the necessary corrections (set the pointer for the return structure and
check the return for the type of interrupt returned).
Is there any way to determine why the connect fell back to a line based
interrupt?
Did I miss something else in my code (see below)?
Ed
========================================================================
PCI Configuration Space (Segment:0000 Bus:06 Device:00 Function:00)
Common Header:
00: VendorID 16d5
02: DeviceID 5808
04: Command 0107 IOSpaceEn MemSpaceEn BusInitiate SERREn
06: Status 4010 CapList SERR
08: RevisionID 00
09: ProgIF 00
0a: SubClass 80 Other Signal Processing Controller
0b: BaseClass 11 Signal Processing
0c: CacheLineSize 0010 BurstDisabled
0d: LatencyTimer 00
0e: HeaderType 00
0f: BIST 00
10: BAR0 febff004
14: BAR1 00000000
18: BAR2 fe400004
1c: BAR3 00000000
20: BAR4 fd800004
24: BAR5 00000000
28: CBCISPtr 00000000
2c: SubSysVenID 16d5
2e: SubSysID 5808
30: ROMBAR fea00000
34: CapPtr 40
3c: IntLine 0a
3d: IntPin 01
3e: MinGnt 00
3f: MaxLat 00
Device Private:
40: 00034801 00000000 00806005 00000000
50: 00000000 00000000 00000000 00000000
60: 00010010 012c8fe9 00022800 0003f441
70: 10410040 00000000 00000000 00000000
80: 00000000 00000000 00000000 00000000
90: 00000000 00000000 00000000 00000000
a0: 00000000 00000000 00000000 00000000
b0: 00000000 00000000 00000000 00000000
c0: 00000000 00000000 00000000 00000000
d0: 00000000 00000000 00000000 00000000
e0: 00000000 00000000 00000000 00000000
f0: 00000000 00000000 00000000 00000000
Capabilities:
40: CapID 01 PwrMgmt Capability
41: NextPtr 48
42: PwrMgmtCap 0003 Version=3
44: PwrMgmtCtrl 0000 DataScale:0 DataSel:0 D0
48: CapID 05 MSI Capability
49: NextPtr 60
4a: MsgCtrl 64BitCapable MultipleMsgEnable:0 (0x1)
MultipleMsgCapable:0 (0x1)
4c: MsgAddr 0
50: MsgAddrHi 0
54: MsData 0
60: CapID 10 PCI Express Capability
61: NextPtr 00
62: Express Caps 0001 Type:Endpoint
64: Device Caps 012c8fe9
68: Device Control 2800 MRR:512 NS ap pf et MP:128 ro ur fe nf ce
6a: Device Status 0002 tp ap ur fe NF ce
6c: Link Caps 0003f441
70: Link Control 0040 es CC rl ld RCB:64 ASPM:None
72: Link Status 1041 SCC lt lte NLW:x4 LS:2.5
74: Slot Caps 00000000
78: Slot Control 0000 pcc PI:?? AI:?? hpi cc pde mrls pfd ab
7a: Slot Status 0000 pds hpi cc pdc ms pfd ab
7c: Root Control 0000 pmei fs nfs cs
7e: Reserved 0000
80: Root Status 00000000 pmep pmes ID:0
Enhanced Capabilities:
100: CapID 0003 Serial Number Capability
Version 1
NextPtr 000
===========================================================================
{
IO_CONNECT_INTERRUPT_PARAMETERS params;
DevExt->MessageInterruptUsed = FALSE;
RtlZeroMemory( ¶ms,
sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
params.Version = CONNECT_MESSAGE_BASED;
// Set members of params.MessageBased here.
params.MessageBased.PhysicalDeviceObject =
DevExt->UnderlyingPDO;
params.MessageBased.MessageServiceRoutine =
InterruptMessageServiceRoutine;
params.MessageBased.ServiceContext = DevExt ;
params.MessageBased.SpinLock = NULL;
params.MessageBased.SynchronizeIrql = 0;
params.MessageBased.FloatingSave = FALSE;
params.MessageBased.FallBackServiceRoutine =
HandleInterrupt;
params.MessageBased.ConnectionContext.Generic =
(PVOID)&DevExt->ConnectionContext;
DebugPrint(LOUD, DBG_INIT, “calling IoConnectInterruptEx -
MessageBased\n” );
status = IoConnectInterruptEx(¶ms);
if ( NT_SUCCESS(status) )
{
// Operation succeeded. We are running on Windows
Vista.
SET_FLAG(DevExt->Flags, ADAPTER_INTERRUPT_IN_USE);
DebugPrint(LOUD, DBG_INIT, “IoConnectInterruptEx
succeeded. We are running on Windows Vista or later.\n” );
//
// Save the type of interrupt connected. We’ll use
this and also the returned connection
// context later when we need to disconnect from the
interrupt.
//
DevExt->IntConnectVersion = params.Version;
// Check to see… Did we connect to any Message
Signaled Interrupts, or did we
// have to fall back to using traditional line-based
interrupts? IoConnectInterruptEx
// sets the Version field to indicate the interrupt
type to which we actually were connected.
//
if(params.Version == CONNECT_MESSAGE_BASED)
{
// PIO_INTERRUPT_MESSAGE_INFO msgInfo;
DebugPrint(LOUD, DBG_INIT, " Message
Signaled Interrupt connected.\n" );
//
// Because we succeeded in connceting to one
or more Message Signaled Interrupts, the
// connection context that was returned was a
pointer to an IO_INTERRUPT_MESSAGE_INFO structure.
//
// msgInfo =
DevExt->ConnectionContext.InterruptMessageTable;
// devExt->MessageUsed = TRUE;
DevExt->MessageInterruptUsed = TRUE; // We’re
using message-based interrupts.
//
// Get count of Message Signaled Interrupts we
were granted Note: Even though our device
// requests more, we could be granted only 1
Message Signaled Interrupt in certain situations.
// Deal with that here…
//
DevExt->IntMessageCount =
(*DevExt->ConnectionContext.InterruptMessageTable)->MessageCount;
}
else
{
ASSERT(Version == CONNECT_LINE_BASED);
DebugPrint(LOUD, DBG_INIT, " Line Interrupt
connected.\n" );
DevExt->MessageInterruptUsed = FALSE; // We’re
not using message-based interrupts.
}
}
else
{
// Running an older Windows - call
IoconnectInterruptEx with CONNECT_FULLY_SPECIFIED
…
}
}