Problem with passing the MSI resources to the child devices using mf.sys

I am working on a PCIe device which has four 16550 UART ports. All four UART’s functional registers are mapped to a single BAR(BAR0). This device supports MSI interrupts along with pin based interrupt. In case of MSI interrupt, each port has a separate vector associated to it.

I am using multifunction driver to create a child node for each UART port. Since the functional registers are part of a single BAR, I used varyingresourcemap to pass the memory resource. Interrupt resources for each port is different as each port has an individual MSI vector.

HKR,Interrupt Management,0x00000010
HKR,Interrupt Management\MessageSignaledInterruptProperties,0x00000010
HKR,Interrupt Management\MessageSignaledInterruptProperties,MSISupported,0x00010001,4
HKR,Interrupt Management\MessageSignaledInterruptProperties,MessageNumberLimit,0x00010001,4

;INST-0
HKR,Child0000,HardwareID,PCI\VEN_1055&DEV_A042&SUBSYS_00101055
HKR,Child0000,VaryingResourceMap,1,00, 00,00,00,00, 08,00,00,00
HKR,Child0000,ResourceMap,1,06

;INST-1
HKR,Child0001,HardwareID,PCI\VEN_1055&DEV_A042&SUBSYS_00111055
HKR,Child0001,VaryingResourceMap,1,00, 00,01,00,00, 08,00,00,00
HKR,Child0001,ResourceMap,1,07

;INST-2
HKR,Child0002,HardwareID,PCI\VEN_1055&DEV_A042&SUBSYS_00121055
HKR,Child0002,VaryingResourceMap,1,00, 00,02,00,00, 08,00,00,00
HKR,Child0002,ResourceMap,1,08

;INST-3
HKR,Child0003,HardwareID,PCI\VEN_1055&DEV_A042&SUBSYS_00131055
HKR,Child0003,VaryingResourceMap,1,00, 00,03,00,00, 08,00,00,00
HKR,Child0003,ResourceMap,1,09

After loading the mf.sys four child nodes are created and When I tried to load the serial inbox driver for the child devices, it reported an error :

**This device cannot start. (Code 10)
An invalid parameter was passed to a service or function.
**

When I disable the MSI interrupt (removing the Interrupt Management entries which are mentioned above and pass the same interrupt resource-6 to all the child devices), everything works fine. Serial.sys loads successfully for all the child devices and all four ports are functional.

I looked into the resources of the parent device and to make sure the correct resources are passed to child devices. I copied the resource list of parent device below.

CmResourceList at 0xffff860a29088820 Version 1.1 Interface 0x5 Bus #0x9
Entry 0 - Memory (0x3) Device Exclusive (0x1)
Flags (
Range starts at 0x00000000f7ce0000 for 0x8000 bytes
Entry 1 - DevicePrivate (0x81) Device Exclusive (0x1)
Flags (
Data - {0x00000001, 0000000000, 0000000000}
Entry 2 - Memory (0x3) Device Exclusive (0x1)
Flags (
Range starts at 0x00000000f7cefb00 for 0x100 bytes
Entry 3 - DevicePrivate (0x81) Device Exclusive (0x1)
Flags (
Data - {0x00000001, 0x00000002, 0000000000}
Entry 4 - Memory (0x3) Device Exclusive (0x1)
Flags (
Range starts at 0x00000000f7cefa00 for 0x100 bytes
Entry 5 - DevicePrivate (0x81) Device Exclusive (0x1)
Flags (
Data - {0x00000001, 0x00000004, 0000000000}
Entry 6 - Interrupt (0x2) Device Exclusive (0x1)
Flags (LATCHED MESSAGE
Message Count 1, Vector 0xfffffff3, Group 0, Affinity 0
Entry 7 - Interrupt (0x2) Device Exclusive (0x1)
Flags (LATCHED MESSAGE
Message Count 1, Vector 0xfffffff2, Group 0, Affinity 0
Entry 8 - Interrupt (0x2) Device Exclusive (0x1)
Flags (LATCHED MESSAGE
Message Count 1, Vector 0xfffffff1, Group 0, Affinity 0
Entry 9 - Interrupt (0x2) Device Exclusive (0x1)
Flags (LATCHED MESSAGE
Message Count 1, Vector 0xfffffff0, Group 0, Affinity 0

From the above, I think I am passing the correct resources to the child devices.

I looked into the statehistory of the child device after loading the serial inbox driver and could understand much. I copied it below.

State = DeviceNodeRemoved (0x312)
Previous State = DeviceNodeStartCompletion (0x306)
StateHistory[09] = DeviceNodeStartCompletion (0x306)
StateHistory[08] = DeviceNodeAwaitingQueuedRemoval (0x30f)
StateHistory[07] = DeviceNodeStartCompletion (0x306)
StateHistory[06] = DeviceNodeStartPending (0x305)
StateHistory[05] = DeviceNodeResourcesAssigned (0x304)
StateHistory[04] = DeviceNodeDriversAdded (0x303)
StateHistory[03] = DeviceNodeInitialized (0x302)
StateHistory[02] = DeviceNodeUninitialized (0x301)
StateHistory[01] = DeviceNodeInitialized (0x302)
StateHistory[00] = DeviceNodeUninitialized (0x301)
StateHistory[19] = Unknown State (0x0)
StateHistory[18] = Unknown State (0x0)
StateHistory[17] = Unknown State (0x0)
StateHistory[16] = Unknown State (0x0)
StateHistory[15] = Unknown State (0x0)
StateHistory[14] = Unknown State (0x0)
StateHistory[13] = Unknown State (0x0)
StateHistory[12] = Unknown State (0x0)
StateHistory[11] = Unknown State (0x0)
StateHistory[10] = Unknown State (0x0)
Flags (0x6c002030) DNF_ENUMERATED, DNF_IDS_QUERIED,
DNF_HAS_PROBLEM, DNF_NO_LOWER_DEVICE_FILTERS,
DNF_NO_LOWER_CLASS_FILTERS, DNF_NO_UPPER_DEVICE_FILTERS,
DNF_NO_UPPER_CLASS_FILTERS
CapabilityFlags (0x00002400) WakeFromD0, WakeFromD3
Problem = CM_PROB_FAILED_START
Problem Status = 0xc000000d
Failure Status 0000000000

I am new to windows driver development and would like to get your help in understanding the issue and also possible fix. Thanks in advance.

This is probably because serial.sys does not support MSI.
(how can you know? It imports IoConnectInterrupt rather than IoConnectInterruptEx)
So, use a legacy PCI shared interrupt as you’ve already found, or write a custom driver.

Not a solution, but when debugging issues like this in the past, I’ve found it helpful to build and install the serial driver from the Windows Driver Samples Github repo. Alter your INF file HKR,Child* entries to bind to *PNP0501, and you’ll be off to the races.

Thanks for the response.

I have taken the serial sample code from github repo and modified to the device needs. It is working with legacy interrupts but still I am not able to make it to work with MSI interrupts.

I have looked into the setupapi.dev.log and it says,

Class installer: Enter 14:16:15.899
inf: {Install from INF Section - Serial_Inst.NT} 14:16:15.899
inf: Flags - 0x00000004
inf: {Install from INF Section - exit(0x00000000)} 14:16:15.914
dvi: {Install DEVICE}
inf: {Install from INF Section - Serial_Inst.NT} 14:16:15.914
inf: Flags - 0x001005ee
inf: {Install from INF Section - exit(0x00000000)} 14:16:15.914
inf: {Install from INF Section - Serial_Inst.NT.Hw} 14:16:15.914
inf: Flags - 0x00100004
inf: {Install from INF Section - exit(0x00000000)} 14:16:15.914
dvi: {Writing Device Properties}
dvi: Strong Name=oem15.inf:50ab71fe6ed9c6ba:Serial_Inst:14.15.14.895:pci\ven_1055&dev_a042&subsys_00101055
dvi: {Writing Device Properties - Complete}
inf: AddService=Serial,0x00000002,Serial_Service (pci1xxxxserial.inf line 75)
dvi: Add Service: Modified existing service ‘Serial’.
inf: {Install from INF Section - Serial_Service} 14:16:15.930
inf: Flags - 0x00100004
inf: {Install from INF Section - exit(0x00000000)} 14:16:15.930
dvi: {Install DEVICE exit (0x00000000)}
dvi: Install Device: Configuring device class. 14:16:15.930
dvi: Install Device: Configuring device class completed. 14:16:15.930
dvi: Device Status: 0x01802400 [0x1c - 0xc0000490]
dvi: {Restarting Devices} 14:16:15.930
dvi: Start: MF\PCI#VEN_1055&DEV_A042&SUBSYS_A0421055&REV_A0\7&31E534DD&18&002000E5#CHILD0000
! dvi: Device ‘MF\PCI#VEN_1055&DEV_A042&SUBSYS_A0421055&REV_A0\7&31E534DD&18&002000E5#CHILD0000’ not started: Device has problem: 0x0a (CM_PROB_FAILED_START), problem status: 0xc000000d.
dvi: {Restarting Devices exit} 14:16:15.961
dvi: Class installer: Exit

From the above log and from kdprint messages, I understood that DriverEntry, DeviceAdd routines are executing as expected and the issue seems to be during the IRP - IRP_MN_START_DEVICE. I am struck here since I am not sure why the error happens when MSI is enabled.(Enabled by adding the MSI entries in the INF of MF.sys)

I have tried installing the serial driver without the MF (only one port can be used) and found that the driver is functional with MSI interrupts. Hence I am suspecting the MF.sys.

Please let me know If my understanding is correct also suggest any further steps to debug and find the solution.

Also, serial sample code uses the WDF framework APIs (WDF_INTERRUPT_CONFIG_INIT, WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE)for interrupt mapping which seems to be agnostic of the interrupt type.(Legacy,MSI). Is the implementation for Interrupt support is same for both Legacy and MSI interrupts with KMDF framework?

Please suggest. Thanks in advance.

We’ll, the way you would debug this is by putting a breakpoint in your AddDevice entry point, and stepping through your code to find where the error is.

Have you done that?

Peter

0xc000000d is STATUS_INVALID_PARAMETER. Your code must be returning that error. I assume it’s coming from WdfInterruptCreate, but you need to know that.

Unfortunately I don’t have debugger connected. But I have put debug print messages in the AddDevice to check the return status of the framework APIS such as WdfInterruptCreate, and all of them returns “SUCEESS”. AddDevice returns SUCCESS.

Since the error status is “CM_PROB_FAILED_START”, doesn’t it mean the driver’s AddDevice is passed through correctly?

Also, as mentioned above, I am assuming the error is during the execution of IRP - IRP_MN_START_DEVICE. If so, is it possible that MF.sys is responsible for this error as this is part of the driver stack?

Unfortunately I don’t have debugger connected.

So, “unfortunately” I stopped reading at this sentence.

Connect a debugger and debug the problem properly,please. Otherwise you’re just groping around in the dark making assumptions and guessing, when you’d have the answer in two minutes with the debugger.

Peter

1 Like