MSI-X在WDF中断

我在使用WDF / KMDF编写的Windows总线驱动程序中执行MSI-X中断时遇到了很多麻烦。 我已经阅读了MSDN文档 ,并没有很多有用的信息。 我的理解是,它应该只是“工作”。

我已经更改了我们的驱动程序的INF文件来添加相应的registry项,并确认它们在安装时正确设置。 我正确地查询PCIconfiguration空间并确定是否支持MSI-X中断。

问题是,一旦我有这个信息,我不知道如何改变我的代码,专门设置为MSI-X的中断。 我做标准调用来configuration一个WDF_INTERRUPT_CONFIG_INIT stuct并调用WdfInterruptCreate,但创build的中断不是消息信号,我不知道需要做什么才能真正做到这一点。

这里有没有WDF版本的步骤,还是应该在这里做标准的WDFINTERRUPT创build步骤?

有没有人有这样的经验? 任何人都可以提供一个示例源?

上周我一直在类似的事情上挣扎。 我的应用程序略有不同,因为我试图获得普通的MSI中断,而不是MSI-X中断工作。 但是我以几乎相同的方式使用了WDF框架。

我意识到你在2013年4月左右发布了你的原始问题,但没有更新。 你解决了你原来的问题吗? 如果是这样,我想看看你自己的解决方案。

在我的WDF驱动程序中,我正在映射传入的硬件资源列表,并使用WdfCmResourceListGetDescriptor()函数对其进行解析,以检查WDFCMRESLIST列表中的每个PCM_PARTIAL_RESOURCE_DESCRIPTOR项目。 我能够获得一个CmResourceTypeInterrupt描述符,但它始终是旧式中断,而不是MSI中断。 我的设备支持MSI。 我不明白为什么MSI描述符不在资源列表中,即使在我的.inf文件中设置了额外的注册表项后,如上所述。

事实证明,我的.inf文件中有一个错字。 我忘了在我的设备安装部分添加“.HW”后缀。 添加此后缀允许总线管理器修改设备中的pcie配置地址,并创建适当的MSI中断资源描述符,驱动程序必须挂接该描述符。

[Standard.NT$ARCH$] %tdvr.DeviceDesc%=tdvr_Device, PCI\VEN_104C&DEV_B800 [tdvr_Device.NT] CopyFiles=Drivers_Dir [tdvr_Device.NT.HW] AddReg=MSI_Interrupts [Drivers_Dir] tdvr.sys ;http://msdn.microsoft.com/en-us/library/windows/hardware/ff544246(v=vs.85).aspx ;To receive message-signaled interrupts (MSIs), a driver's INF file must enable MSIs in the ;registry during installation. Use the Interrupt Management\MessageSignaledInterruptProperties ;subkey of the device's hardware key to enable MSI support. [MSI_Interrupts] HKR,Interrupt Management,,0x00000010 HKR,Interrupt Management\MessageSignaledInterruptProperties,,0x00000010 HKR,Interrupt Management\MessageSignaledInterruptProperties,MSISupported,0x00010001,1 

当在资源列表中找到MSI中断资源描述符(例如,在evtMapHWResources回调中)时,描述符将用作WdfInterruptCreate()函数的输入。 这里的“tdvr”前缀是我自己的驱动程序命名约定。

 NTSTATUS tdvrConfigureInterrupts( _Inout_ PDEVICE_CONTEXT deviceContext, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR interruptDescRaw, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR interruptDescTranslated ) { NTSTATUS status; PAGED_CODE(); FuncEntry(); // What kind of interrupt has been provided? if (CM_RESOURCE_INTERRUPT_MESSAGE & interruptDescTranslated->Flags) { TraceInterrupt(TRACE_LEVEL_INFORMATION, "Message Interrupt level 0x%0x, Vector 0x%0x, MessageCount %u\n" ,interruptDescTranslated->u.MessageInterrupt.Translated.Level ,interruptDescTranslated->u.MessageInterrupt.Translated.Vector ,interruptDescTranslated->u.MessageInterrupt.Raw.MessageCount ); } else { TraceInterrupt(TRACE_LEVEL_INFORMATION, "Legacy Interrupt level: 0x%0x, Vector: 0x%0x\n" ,interruptDescTranslated->u.Interrupt.Level ,interruptDescTranslated->u.Interrupt.Vector ); } // // Create WDFINTERRUPT object. // WDF_INTERRUPT_CONFIG interruptConfig; WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, tdvrEvtInterruptIsr, tdvrEvtInterruptDpc ); // Each interrupt has some context data WDF_OBJECT_ATTRIBUTES interruptAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &interruptAttributes, INTERRUPT_CONTEXT ); // // These first two callbacks will be called at DIRQL. Their job is to // enable and disable interrupts. // interruptConfig.EvtInterruptEnable = tdvrEvtInterruptEnable; interruptConfig.EvtInterruptDisable = tdvrEvtInterruptDisable; // If the driver calls WdfInterruptCreate from EvtDriverDeviceAdd, the InterruptRaw and // InterruptTranslated members of the WDF_INTERRUPT_CONFIG structure must be NULL. // the driver calls WdfInterruptCreate from EvtDevicePrepareHardware, these members must both be valid. interruptConfig.InterruptTranslated = interruptDescTranslated; interruptConfig.InterruptRaw = interruptDescRaw; // Our driver must call WdfInterruptCreate once for each interrupt vector that its device requires. // If the device supports message-signaled interrupts (MSI), the driver must create an interrupt object // for each message that the device can support. status = WdfInterruptCreate( deviceContext->WdfDevice, &interruptConfig, &interruptAttributes, &deviceContext->WdfInterrupt ); if (!NT_SUCCESS(status)) { TraceInterrupt(TRACE_LEVEL_ERROR, "WdfInterruptCreate FAILED: %!STATUS!\n", status); } else { PINTERRUPT_CONTEXT interruptContext = InterruptGetContext(deviceContext->WdfInterrupt); // do whatever with context info } FuncExit(); return status; } 

就像我现在所希望的那样,你已经明白了这一点,但是我想我会发表一些东西来贡献。