We are developing an IOUserSCSIParallelInterfaceController driver for a legacy controller.
After completing init() successfully, no other methods are called before a DriverKit assert failure - .driver.dext) Assertion failed: (notsync || !remote || (msgid == IOService_Start_ID) || queue->OnQueue()), function Invoke, file uioserver.cpp, line 1654. - that leads immediately to "IOPCIDevice::ClientCrashed_Impl() for client " .
This appears to be because the framework is attempting a SetPowerState()' during DEXT load, which is delivered off-queue and panics in OSMetaClassBase::Invoke (uioserver.cpp`) before any other dext method runs.
Apple Silicon Mac, macOS 26 (DriverKit 25.1 SDK), Xcode 26.x.
Expected:
The SetPowerState() power-up is delivered on the driver object's dispatch queue (or otherwise handled by the framework), allowing the dext's SetPowerState override to run, ACK via super::SetPowerState(powerFlags, SUPERDISPATCH), and proceed to UserInitializeController.
Actual behavior:
init() completes (our trace logs init then completed init)
Neither Start_Impl nor SetPowerState_Impl ever executes
Instead the process fails with the assertion above , IOPCIDevice::ClientCrashed_Impl() reports "client … does not have open session … skipping recovery".
- The dext crash-loops ("Driver … has crashed N time(s)").
Any suggestions?
First off, as a disclaimer, this is a crazy week for me so you may get a lot more "quick guess" than well thought out answers. If you're still stuck, then next week I can look at things more deeply.
Getting into things:
This appears to be because the framework is attempting a SetPowerState()' during DEXT load, which is delivered off-queue and panics in OSMetaClassBase::Invoke (uioserver.cpp`) before any other dext method runs.
A few suggestions off the top of my head:
-
Start by using IOService as your provider, NOT the SCSI stack. In my experience, it's MUCH easier to try to figure out why a DEXT that worked broke than it is to figure out "why it just doesn't work".
-
Similar, particularly in the early stage, take VERY small steps. You can end up wasting SO much time because you did just a LITTLE to much work at once.
-
This sounds a bit like this panic.
In terms of the specific :
Expected: The SetPowerState() power-up is delivered on the driver object's dispatch queue (or otherwise handled by the framework), allowing the dext's SetPowerState override to run, ACK via super::SetPowerState(powerFlags, SUPERDISPATCH), and proceed to UserInitializeController.
...SCSIControllerDriverKit has VERY specific expectations and rules about which DispatchQueue's you'll use and how you'll use them. Watch "Modernize PCI and SCSI drivers with DriverKit" and make sure you create exactly the same queues in exactly the same places.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware