Common resources for bus device and child devices. Unnecessary resource rebalancing

Hello!

I have PCI-E board which adds 4 serial ports to the system. So I’m developing bus driver for this hardware.
My idea to create 4 PDOs devices, provide necessary resources and use standard serial driver from WDK examples (with minimal changes if necessary).
But I have some issue with resource rebalancing.

I do the following:

  1. The bus driver receives a memory from the Pnp manager in EvtDevicePrepareHardware.
  2. This region of memory is divided into several sub-regions and distributed between child devices in EvtDeviceResourceRequirementsQuery.
  3. The child device driver maps the provided memory in the EvtDevicePrepareHardware function.

The problem is that the Pnp manager starts rebalancing resources because the bus driver and child device driver own overlapping areas of memory.

In Device Manager, I can see that a bus device and child devices may own overlapped resources.
How to allocate overlapped resources to child devices to avoid resource rebalancing?

This is source code (from bus driver) which provides resources to child devices in regions EvtDeviceResourceRequirementsQuery:

serialNo = ... status = RtlIoEncodeMemIoResource(&descriptor, CmResourceTypeMemory, 0, PAGE_SIZE, baseAddr.LowPart + (serialNo - 1) * 0x40, baseAddr.LowPart + (serialNo - 1) * 0x40 + 0x40); ASSERT(NT_SUCCESS(status)); descriptor.ShareDisposition = CmResourceShareShared; descriptor.ShareDisposition = CM_RESOURCE_MEMORY_READ_WRITE; status = WdfIoResourceListAppendDescriptor(reslist, &descriptor); ASSERT(NT_SUCCESS(status));_

Thanks in advance!

Best Regards,
Alexey

There have been discussions about this in the past, bottom line is the design of your device is not going to allow you to use a totally unmodified serial port driver. What you will need to do is modify the serial port sample and create a bus driver. The bus driver will need to provide the resources through a device interface request from the modified serial port. Also, depending on how the interrupt is managed you are going to need to have the bus driver do the interrupt management, and call the interrupt handler of the serial port.

I did this for a number of clients years ago who followed the FPGA providers suggestions that work fine for Linux but are broken for Windows.

1 Like

Thanks for your answer Don_Burn!
Looks like I have a similar task. FPGA HW with several ports on this HW.
And there is a solution for Linux but I need to develop for Windows.

All devices use the same interrupt. So looks like this will be the next task which I will have to deal with.

I will try to find mentioned discussion… If you consider it necessary to briefly talk about the difficulties that await me along this path, it will be great.

So it is shared interrupt handling task. And I need to do interrupt management in bus driver.
So it is resource allocation to child devices. I need to solve it using “device interface request”

May be it is easier to control such serial ports using raw-mode in bus driver? Of course I will need to move all functionality from serial example to bus driver…

Thanks!

Alexius, keep the design as a bus driver and serial port. The serial port modifications are pretty simple though spread through the driver. If you keep the serial port driver close to the original, then when Microsoft issues an update to the WDK samples you can compare things and easily develop the changes.

The bus driver I did was pretty small. In my case it was about 1500 lines of code, but that included a lot of comments, and support for more than just the serial ports, since most of the clients I did this for had other devices in their FPGA. A simple KMDF bus driver for this with only the interrupt handling, and the memory segmenting would be well less than a 1000 lines of code without comments.

1 Like

Right.

Unfortunately, there are OS defined ways to do these things… but they sadly aren’t exported for drivers writers to use. Consider, for example, how GPIO interrupts are dispatched: The GPIO controller driver gets the interrupt, and then that interrupt goes through “second level dispatching” to call the ISR of the driver that’s registered to use that interrupt. This has been an architected part of the system since Windows 8.

So, for interrupts I know for sure there’s no available sub-dispatch scheme available to driver devs.

I’ve often wondered, however, if it’s possible to Have a bus driver parcel out a sub-set of its resources to a child device in some wya, and still make Windows happy. I know Mr. Burn says this isn’t possible… and I know I don’t know how to do it… But I’ve never spent the time to fully convince myself that there isn’t some very specific sequence of (query/set/filter resource requirements, for example) operations that’ll make this work.

Peter

1 Like

Peter,

I always felt this should be doable also. When I asked 9 years ago Doron and Jake kindly pointed out the error of my ways, both on the forum and in private correspondence. Why the system won’t allow splitting of a BAR, or for that matter sharing an interrupt, is something that should be asked again. Between MF.sys and the OS in general there are mechanisms, how hard would it be to provide these for the common situations?

Of course I should not complain, I sold the bus driver / serial port to a significant number of firms that had followed the FPGA vendors claims it all worked perfectly, when in fact they vendor never tried Windows.

[MODS: Edited for format… lines starting with spaces in Markdown are “code” format]

1 Like

Thanks a lot for your answers. Very valuable information!

> @Don_Burn said: > <…> > Also, depending on how the interrupt is managed you are going to need to have the bus driver do the interrupt management, and call the interrupt handler of the serial port. It seems like I have already started resolving this task. I register isr handler in bus driver and check UART_IIR register for each UART to define which SerialIsr handler shall be called. But how to transfer SerialIsr handler function pointer from Serial Driver to Bus Driver? I’ve read a lot of articles about driver to driver communication. bi-directional bus interface or may be device interface request? Thanks

I used the following device interface:

typedef BOOLEAN INTERRUPT_CALLBACK (
__in PVOID InterruptContext );

typedef INTERRUPT_CALLBACK *PINTERRUPT_CALLBACK;

typedef BOOLEAN INTERRUPT_SYNC(
__in PVOID InterruptData,
__in PINTERRUPT_CALLBACK Callback,
__in PVOID Context );

typedef INTERRUPT_SYNC *PINTERRUPT_SYNC;

typedef
VOID INTERRUPT_LOCK_ACQ(
__in PVOID InterruptData );

typedef INTERRUPT_LOCK_ACQ *PINTERRUPT_LOCK_ACQ;

typedef
VOID INTERRUPT_LOCK_REL(
__in PVOID InterruptData );

typedef INTERRUPT_LOCK_REL *PINTERRUPT_LOCK_REL;

typedef struct {
INTERFACE Interface;
PHYSICAL_ADDRESS Raw;
PHYSICAL_ADDRESS Translated;
ULONG Vector;
KIRQL Irql;
KINTERRUPT_MODE InterruptMode;
KAFFINITY Affinity;
PINTERRUPT_CALLBACK InterruptRoutine;
PVOID InterruptContext;
PINTERRUPT_SYNC InterruptSynchronize;
PINTERRUPT_LOCK_ACQ InterruptAcquireLock;
PINTERRUPT_LOCK_REL InterruptReleaseLock;
PVOID InterruptSyncContext;
} RESOURCES, *PRESOURCES;

The InterruptRoutine and InterruptContext were passed from the Serial driver down, the rest was passed back.

Just my approach to this.

1 Like

Thanks a lot! I will try to implement…