We have a PCIe card which is updateable via programming the flash witihin a user application. Works everything. But it is a little bit uncomfortable that, after the update, the machine has to be power-cycled to let the FPGA load again from its flash.
There is a different solution though: Deactivate the device in device manager after flashing, let the FPGA reloading itself by a timer which is set before by register access. And then activate the device again. A little puzzling (and maybe risky) but works quite good.
I was able to script that with the help of pnputil and stuff. But needs admin-privileges to work, though.
Is there any way to implement that in driver code itself? Actually doesnt make sense, because the driver would need to unload itself (and go through DriverEntry after some time again...). But maybe I oversee something. Would be sufficient to trigger an AddDevice, CreateDevice (and to deregister before) or sth.?
Why can't you just set the timer and let the FPGA reload itself while the driver remains alive? If you need to redo some of the initialization, you can do that based on a timer in the driver. As long as the PCIe config space survives, that should work fine.
My machine does not crash in this case, but the following register read accesses only return 0xFFFF... So something bad happened on PCIe that the FPGA doesnt like. But works fine when deactivation/activating the driver.
That strongly suggests that your device has forgotten the BAR assignments it was given at boot time. That is a common problem when resetting FPGAs -- the config space resets to zeros.
You said you have a user-mode application that updates the flash. Why not have that same application manage the reset? Anything that can be done in Device Manager can be done with the SetupDi APIs. They are a bit wordy, but highly capable. You can look at the "devcon" source code to see examples of how to disable and enable a device.
I had a coworker playing with this in Linux for the exact same purpose. He managed to put together a script which did a hot-reset of the card and triggered a rescan of the PCIe bus. It worked well on some PCs and not at all on others so he ultimately abandoned it.
I've found following SetDeviceState(..) code which is working, but needs admin rights to run unfortunately. But I dont want to bother the user with the UAC-dialog.
But the hint with BAR assignments is really helpful, so next I would to figure out if and how I can trigger the driver to run through
So write a service that calls the setupdi APIs and have your driver trigger the service to do that (through a pended ioctl for example.)
Have you experimented through device manager or devcon to confirm this actually fixes your problem?
From a policy standpoint, I would think you WANT your firmware updater to require admin privileges. You don't want the average Joe to run something like that, and I'm SURE your client's corporate IT department doesn't want that.
Device Manager and the SetupDi APIs are all strictly user-mode components. RUNNING drivers is done in kernel mode, but MANAGING drivers is all user mode.