Hello everyone,
We are migrating our KEXT for a Thunderbolt storage device to a DEXT based on IOUserSCSIParallelInterfaceController.
We've run into a fundamental issue where the driver's behavior splits based on the I/O source: high-level I/O from the file system (e.g., Finder, cp) is mostly functional (with a minor ls -al sorting issue for Traditional Chinese filenames), while low-level I/O directly to the block device (e.g., diskutil) fails or acts unreliably. Basic read/write with dd appears to be mostly functional.
We suspect that our DEXT is failing to correctly register its full device "personality" with the I/O Kit framework, unlike its KEXT counterpart. As a result, low-level I/O requests with special attributes (like cache synchronization) sent by diskutil are not being handled correctly by the IOUserSCSIParallelInterfaceController framework of our DEXT.
Actions Performed & Relevant Logs
1. Discrepancy: diskutil info Shows Different Device Identities for DEXT vs. KEXT
For the exact same hardware, the KEXT and DEXT are identified by the system as two different protocols.
KEXT Environment:
   Device Identifier:         disk5
   Protocol:                  Fibre Channel Interface
   ...
   Disk Size:                 66.0 TB
   Device Block Size:         512 Bytes
DEXT Environment:
   Device Identifier:         disk5
   Protocol:                  SCSI
   SCSI Domain ID:            2
   SCSI Target ID:            0
   ...
   Disk Size:                 66.0 TB
   Device Block Size:         512 Bytes
2. Divergent I/O Behavior: Partial Success with Finder/cp vs. Failure with diskutil
High-Level I/O (Partially Successful):
In the DEXT environment, if we operate on an existing volume (e.g., /Volumes/GammaCarry), file copy operations using Finder or cp succeed. Furthermore, the logs we've placed in our single I/O entry point, UserProcessParallelTask_Impl, are triggered.
Side Effect: However, running ls -al on such a volume shows an incorrect sorting order for files with Traditional Chinese names (they appear before . and ..).
Low-Level I/O (Contradictory Behavior):
In the DEXT environment, when we operate directly on the raw block device (/dev/disk5):
diskutil partitionDisk ... -> Fails 100% of the time with the error: Error: -69825: Wiping volume data to prevent future accidental probing failed.
dd command -> Basic read/write operations appear to work correctly (a write can be immediately followed by a read within the same DEXT session, and the data is correct).
3. Evidence of Cache Synchronization Failure (Non-deterministic Behavior)
The success of the dd command is not deterministic. Cross-environment tests prove that its write operations are unreliable:
First Test:
In the DEXT environment, write a file with random data to /dev/disk5 using dd.
Reboot into the KEXT environment.
Read the data back from /dev/disk5 using dd. The result is a file filled with all zeros.
Conclusion: The write operation only went to the hardware cache, and the data was lost upon reboot.
Second Test:
In the DEXT environment, write the same random file to /dev/disk5 using dd.
Key Variable: Immediately after, still within the DEXT environment, read the data back once for verification. The content is correct!
Reboot into the KEXT environment.
Read the data back from /dev/disk5. This time, the content is correct!
Conclusion: The additional read operation in the second test unintentionally triggered a hardware cache flush. This proves that the dd (in our DEXT) write operation by itself does not guarantee synchronization, making its behavior unreliable.
Our Problem
Based on the observations above, we have the conclusion:
High-Level Path (triggered by Finder/cp):
When an I/O request originates from the high-level file system, the framework seems to enter a fully-featured mode. In this mode, all SCSI commands, including READ/WRITE, INQUIRY, and SYNCHRONIZE CACHE, are correctly packaged and dispatched to our UserProcessParallelTask_Impl entry point. Therefore, Finder operations are mostly functional.
Low-Level Path (triggered by dd/diskutil):
When an I/O request originates from the low-level raw block device layer:
The most basic READ/WRITE commands can be dispatched (which is why dd appears to work).
However, critical management commands, such as INQUIRY and SYNCHRONIZE CACHE, are not being correctly dispatched or handled. This leads to the incorrect device identification in diskutil info and the failure of diskutil partitionDisk due to its inability to confirm cache synchronization.
We would greatly appreciate any guidance, suggestions, or insights on how to resolve this discrepancy. Specifically, what is the recommended approach within DriverKit to ensure that a DEXT based on IOUserSCSIParallelInterfaceController can properly declare its capabilities and handle both high-level and low-level I/O requests uniformly?
Thank you.
Charles
                    
                  
                PCIDriverKit
RSS for tagDevelop device drivers for Peripheral Component Interconnect accessories.
Posts under PCIDriverKit tag
            
              
                20 Posts
              
            
            
              
                
              
            
          
          
  
    
    Selecting any option will automatically load the page
  
  
  
  
    
  
  
              Post
Replies
Boosts
Views
Activity
                    
                      Hello everyone,
I am migrating a KEXT for a SCSI PCI RAID controller (LSI 3108 RoC) to DriverKit (DEXT). While the DEXT loads successfully, I'm facing a DMA issue: an INQUIRY command results in a 0-byte disk because the data buffer received by the DEXT is all zeros, despite our firmware logs confirming that the correct data was prepared and sent.
We have gathered detailed forensic evidence and would appreciate any insights from the community.
Detailed Trace of a Failing INQUIRY Command:
1, DEXT Dispatches the Command:
Our UserProcessParallelTask implementation correctly receives the INQUIRY task. Logs show the requested transfer size is 6 bytes, and the DEXT obtains the IOVA (0x801c0000) to pass to the hardware.
DEXT Log:
[UserProcessParallelTask_Impl] --- FORENSIC ANALYSIS ---
[UserProcessParallelTask_Impl] fBufferIOVMAddr          = 0x801c0000
[UserProcessParallelTask_Impl] fRequestedTransferCount  = 6
2, Firmware Receives IOVA and Prepares Correct Data:
A probe in our firmware confirms that the hardware successfully received the correct IOVA and the 6-byte length requirement. The firmware then prepares the correct 6-byte INQUIRY response in its internal staging buffer.
Firmware Logs:
-- [FIRMWARE PROBE: INCOMING DMA DUMP] --
  Host IOVA (High:Low) = 0x00000000801c0000
  DataLength in Header   = 6 (0x6)
--- [Firmware Outgoing Data Dump from go_inquiry] ---
Source Address: 0x228BB800, Length: 6 bytes
0x0000: 00 00 05 12 1F 00
3, Hardware Reports a Successful Transfer, but Data is Lost:
After the firmware initiates the DMA write to the Host IOVA, the hardware reports a successful transfer of 6 bytes back to our DEXT.
DEXT Completion Log:
[AME_Host_Normal_Handler_SCSI_Request] [TaskID: 200] COMPLETING...
[AME_Host_Normal_Handler_SCSI_Request] Hardware Transferred  = 6 bytes
[AME_Host_Normal_Handler_SCSI_Request]   - ReplyStatus         = SUCCESS (0x0)
[AME_Host_Normal_Handler_SCSI_Request]   - SCSIStatus          = SUCCESS (0x0)
The Core Contradiction:
Despite the firmware preparing the correct data and the hardware reporting a successful DMA transfer, the fDataBuffer in our DEXT remains filled with zeros. The 6 bytes of data are lost somewhere between the PCIe bus and host memory.
This "data-in-firmware, zeros-in-DEXT" phenomenon leads us to believe the issue lies in memory address translation or a system security policy, as our legacy KEXT works perfectly on the same hardware.
Compared to a KEXT, are there any known, stricter IOMMU/security policies for a DEXT that could cause this kind of "silent write failure" (even with a correct IOVA)?
Alternatively, what is the correct and complete expected workflow in DriverKit for preparing an IOMemoryDescriptor* fDataBuffer (received in UserProcessParallelTask) for a PCI hardware device to use as a DMA write target?
Any official documentation, examples, or advice on the IOMemoryDescriptor to PCI Bus Address workflow would be immensely helpful.
Thank you.
Charles
                    
                  
                
                    
                      We've developed a PCIDriverKit driver for the capture card on macOS and have identified an issue: CreateMemoryDescriptorFromClient can only read data from the user space to the driver, but cannot write data back to the user.
typedef struct _MWCAP_EDID_DATA {
    uint64_t size;
    uint64_t uaddr;
} MWCAP_EDID_DATA;
// App
size_t xxx::GetEdid(void *buff, size_t size)
{
    MWCAP_EDID_DATA edid;
    edid.size = size;  
    edid.uaddr = (uint64_t)buff;
    kr = IOConnectCallStructMethod(
                            connect,
                            kUserGetEdid,
                            &edid,
                            sizeof(MWCAP_EDID_DATA),
                            NULL, 
                            NULL
                            );
    // kr is 0. But However, the data in the buffer remains unchanged; 
    // it does not reflect the EDID copied from the DEXT.
    return size;
}
// Driver
MWCAP_EDID_DATA *edid = (MWCAP_EDID_DATA *)input;
IOMemoryDescriptor *user_buf_mem = NULL;
IOAddressSegment segment;
segment.address = edid->uaddr;
segment.length = edid->size;
// We have verified that the values in edid->uaddr and edid->size are consistent with what was set by the application.
ret = CreateMemoryDescriptorFromClient(kIOMemoryDirectionOutIn, 1, &segment, &user_buf_mem);
if (ret != kIOReturnSuccess) {
    os_log(OS_LOG_DEFAULT, "Failed to create memdesc with error: 0x%08x", ret);
    break;
}
IOMemoryMap* user_buf_map = nullptr;
ret = user_buf_mem->CreateMapping(0, 0, 0, 0, 0, &user_buf_map);
if (ret != kIOReturnSuccess) {
    os_log(OS_LOG_DEFAULT, "Failed to create mapping with error: 0x%08x", ret);
    OSSafeReleaseNULL(user_buf_mem);
    break;
}
// ... fill the user_buf_map with edid data ...
// For example:
// memcpy(user_buf_map->GetAddress(), source_edid_data, edid->size);
// At this point we have also verified the data in user_buf_map->GetAddress(), which matches our expectations.
OSSafeReleaseNULL(user_buf_map);
OSSafeReleaseNULL(user_buf_mem);
Please help take a look, thank you!
                    
                  
                
                    
                      We have developed the driver for the ProCapture video capture card based on PCIDriverKit. The App can communicate with the driver through the UserClient API. Currently, there is an issue where, when the App starts, there is a small probability that it causes a driver crash. However, the crash stack trace does not point to our code but appears to be within the PCIDriverKit framework. We have spent several weeks debugging but still cannot identify the root cause of the crash. Could you please review the crash log and suggest any methods to help pinpoint the issue?
com.magewell.ProCaptureDriver-2025-09-15-153522.ips
com.magewell.ProCaptureDriver-2025-09-15-082500.ips
                    
                  
                
                    
                      I'm trying to help out one of our vendors by building a skeleton PCI dext which they can flesh out.
However, I can't seem to get the signing right.
I can't sign it at all using no team or my personal team. "Signing for  requires a development team", and "Personal development teams ... do not support the System Extension capability".
I can't sign the driver because "DriverKit Team Provisioning Profile:  doesn't match the entitlements file's value for the com.apple.developer.driverkit.transport.pci entitlement.
I think this problem occurs because our company has already been assigned a transport.pci entitlement, but for our own PCI vendor ID. But I want to build and test software that works with our vendor's PCI device.
I tried generating a profile for the driver manually, it contained only our own company's PCI driver match:
IOPCIPrimaryMatch = "0x0000MMMM&0x0000FFFF";
where MMMM is our own PCI vendor ID.
Is there a better way to inspect the profile Xcode is using than the postage-stamped sized info popup which truncates the information? I would download the generated profile but it doesn't appear on the profile, but Xcode is accessing it from somewhere.
When I look at the available capabilities I can add to an app identifier on the Developer portal, I see com.apple.developer.driverkit.transport.usb, which is "development only". There's no "development only" capability for PCI. Does this mean it isn't possible to develop even a proof-of-concept PCI driver without being first granted the DriverKit PCI (Primary Match) entitlement?
When adding capabilities to a driver, the list of available capabilities shown in Xcode has one "DriverKit PCI (Primary Match) entry", but if I double click it, two such entries appear in the Signing and Capabilities tab for my driver target. On the Developer portal, when I look at my driver's Identifier, there are two Capabilities labelled DriverKit PCI (Primary Match). Why?
                    
                  
                
                    
                      We have a management application which manages security enable and disable for an external PCIe based storage device using Kernel Extension(SCSI Architecture Model Family for External USB Mass Storage devices which deals with IOSCSIBlockCommandsDevice, IOSCSIPeripheralDeviceType00 and IOBlockStorageService)
Now the issue we are facing is when we try to unlock the device using security code (already being set) , we will relink the device using VU command (RelinkBridge). Even-though both the commands are successful , the device is not getting relinked due to which we are not able to use the device for storage.
If someone have faced similar issue or any pointer on how to resolve this issue , it would be helpful.
Thanks in advance.
                    
                  
                
                    
                      Hello everyone,
I’m working on implementing hardware interrupt handling in DriverKit and came across the InterruptOccurred method in IOInterruptDispatchSource. I noticed that its declaration ends with a TYPE macro:
virtual void InterruptOccurred(OSAction* action, uint64_t count, uint64_t time) 
TYPE(IOInterruptDispatchSource::InterruptOccurred);
This structure seems similar to how Timer Events are set up, where an event is linked to a callback and triggered by a timer. I’m attempting to use a similar approach, but for hardware-triggered interrupts rather than timer events.
I’m currently in the trial-and-error phase of the implementation, but if anyone has a working example or reference on how to properly implement and register InterruptOccurred, it would be greatly appreciated!
Best regards,
Charles
                    
                  
                
                    
                      Hi everyone,
I was following the Video Modernize PCI and SCSI drivers with DriverKit and the Document to implement UserMapHBAData(), and here’s my current implementation:
// kern_return_t DRV_MAIN_CLASS_NAME::UserMapHBAData_Impl(uint32_t *uniqueTaskID)
kern_return_t IMPL(DRV_MAIN_CLASS_NAME, UserMapHBAData)
{
    Log("UserMapHBAData() - Start");
    
    // Define the vm_page_size explicitly
    const uint32_t vm_page_size = 4096;
    kern_return_t ret;
    IOBufferMemoryDescriptor *buffer = nullptr;
    IOMemoryMap *memMap = nullptr;
    void *taskData = nullptr;
    // Create a buffer for HBA-specific task data
    ret = IOBufferMemoryDescriptor::Create(kIOMemoryDirectionOutIn, ivars->fTaskDataSize, vm_page_size, &buffer);
    __Require((kIOReturnSuccess == ret), Exit);
    // Map memory to the driver extension's memory space
    ret = buffer->CreateMapping(0, 0, 0, 0, 0, &memMap);
    __Require((kIOReturnSuccess == ret), Exit);
    // Retrieve mapped memory address
    taskData = reinterpret_cast<void *>(memMap->GetAddress());
    __Require(taskData, Exit);
    // WARNING: Potential leak of an object stored into 'buffer'
    // WARNING: Potential leak of an object stored into 'memMap'
    // Assign a unique task ID
    ivars->fTaskID++; // ERROR: No member named 'fTaskID' in 'DriverKitAcxxx_IVars'
    ivars->fTaskArray[ivars->fTaskID] = taskData;
    *uniqueTaskID = ivars->fTaskID;
    Log("UserMapHBAData() - End");
    
    return kIOReturnSuccess;
Exit:
    // Cleanup in case of failure
    if (memMap) {
        memMap->free();  // Correct method for releasing memory maps
    }
    if (buffer) {
        buffer->free();  // Correct method for releasing buffer memory
    }
    
    LogErr("ret = 0x%0x", ret);
    Log("UserMapHBAData() - End");
    
    return ret;
}
For reference, in KEXT, memory allocation is typically done using:
IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions(
    kernel_task,          // Task in which memory is allocated
    kIODirectionOutIn,    // Direction (read/write)
    1024,                 // Size of the buffer in bytes
    4);                   // Alignment requirements
However, after installing the dext, macOS hangs, and I have to do a hardware reset. After rebooting, the sysctl list output shows:
% sectl list
1 extension(s)
--- com.apple.system_extension.driver_extension
enabled active  teamID  bundleID (version)  name    [state]
    *   -   com.accusys.DriverKitAcxxx (5.0/11) com.accusys.DriverKitAcxxx  [activated waiting for user]
Questions:
What could be causing macOS to halt?
How should I approach debugging and resolving this issue?
Looking forward to your insights, any suggestions would be greatly appreciated!
Best regards, Charles
                    
                  
                
                    
                      Hello all,
I am interested in developing a small driver that would facilitate host-to-host communication via Thunderbolt 4/5. While I am aware of features such as Thunderbolt Bridge/Thunderbolt Networking, I find that for my application the overhead is too great. I am interested in sharing a simple, static memory buffer between the two hosts for IO and with some synchronisation primitives. The idea being that the communication is facilitated between different platforms.
Would it be possible to develop a driver/service like this? Currently, going through the documentation, to use PCIDriverKit specifying a Vendor and Product Ids is required, so I doubt that this is a viable path.
I know that Linux exposes the "XDomain" protocol to announce thunderbolt services (This is the same protocol that is used in macOS to discover Thunderbolt Networking peers). Is this functionality exposed to macOS driver developers?
                    
                  
                
                    
                      Hello everyone
I have been developing PCIe device driver through Thunderbolt. However, it was confirmed that up to three devices connected to the daisy chain worked normally, but the fourth device failed to operate the _CopyDeviceMemoryWithIndex() function for connection with the BAR0 App and did not work properly.
The standard specification of Thunderbolt 3/4 is said to be supported by daisy chain connection up to 6 units, but in reality, it is only 3 units, so I ask the forum for technical confirmation.
Of course total 4 device by 2-port x 2-device daisy chain connecting has working well.
And the PCI entry in System information app indicates that all devices have normal load of the PCIe device driver.
                    
                  
                
                    
                      Hello everyone.
I have been developing PCIe device driver through Thunderbolt.
However, it was confirmed that up to three devices connected to the daisy chain worked normally,
but the fourth device failed to operate the _CopyDeviceMemoryWithIndex() function for connection with the BAR0 App and did not work properly.
The standard specification of Thunderbolt 3/4 is said to be supported by daisy chain connection up to 6-device,
but in reality, it is only 3 units,
so I ask the forum for technical confirmation.
Of course total 4 device by 2-port x 2-device daisy chain connecting has working well.
The PCI entry in System information indicates that all devices have normal load of the PCIe device driver.
Thank you.
                    
                  
                
                    
                      Hello Everyone,
I'm encountering an issue while setting up a timer event in DriverKit and would appreciate any guidance.
Here's my current implementation:
void DRV_MAIN_CLASS_NAME::SetupEventTimer() 
{
    // 1. Create dispatch queue
    kern_return_t ret = IODispatchQueue::Create("TimerQueue", 0, 0, &ivars->dispatchQueue);
    if (ret != kIOReturnSuccess) {
        LogErr("Failed to create dispatch queue: 0x%x", ret);
        return;
    }
    // 2. Create timer source
    ret = IOTimerDispatchSource::Create(ivars->dispatchQueue, &ivars->dispatchSource);
    if (ret != kIOReturnSuccess) {
        LogErr("Failed to create timer: 0x%x", ret);
        OSSafeReleaseNULL(ivars->dispatchQueue);
        return;
    }
    /*!
     * @brief       Create an instance of OSAction.
     * @discussion  Methods to allocate an OSAction instance are generated for each method defined in a class with
     *              a TYPE attribute, so there should not be any need to directly call OSAction::Create().
     * @param       target OSObject to receive the callback. This object will be retained until the OSAction is
     *              canceled or freed.
     * @param       targetmsgid Generated message ID for the target method.
     * @param       msgid Generated message ID for the method invoked by the receiver of the OSAction
     *              to generate the callback.
     * @param       referenceSize Size of additional state structure available to the creator of the OSAction
     *              with GetReference.
     * @param       action Created OSAction with +1 retain count to be released by the caller.
     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
     */
    // 3: Create an OSAction for the TimerOccurred method
    // THIS IS WHERE I NEED HELP 
    OSAction* timerAction = nullptr;
    ret = OSAction::Create(this, 0, 0, 0, &timerAction);
    if (ret != kIOReturnSuccess) {
        LogErr("Failed to create OSAction: 0x%x", ret);
        goto cleanup;
    }
    // 4. Set handler
    ret = ivars->dispatchSource->SetHandler(timerAction);
    if (ret != kIOReturnSuccess) {
        LogErr("Failed to set handler: 0x%x", ret);
        goto cleanup;
    }
    // 5. Schedule timer (1 second)
    uint64_t deadline = mach_absolute_time() + NSEC_PER_SEC;
    ivars->dispatchSource->WakeAtTime(0, deadline, 0);
cleanup:
    if (ret != kIOReturnSuccess) {
        OSSafeReleaseNULL(timerAction);
        OSSafeReleaseNULL(ivars->dispatchSource);
        OSSafeReleaseNULL(ivars->dispatchQueue);
    }
}
Problem:
The code runs but the OSAction callback binding seems incorrect (Step 3).
According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method. But I try to use
TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred)
kern_return_t TimerOccurred() LOCALONLY;
TYPE(TimerOccurred)
kern_return_t TimerOccurred() LOCALONLY;
kern_return_t TimerOccurred() TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) LOCALONLY;
All results in Out-of-line definition of 'TimerOccurred' does not match any declaration in 'DRV_MAIN_CLASS_NAME'
Questions:
What is the correct way to declare a timer callback method using TYPE?
How to get the values targetmsgid & msgid generated by Xcode?
Any help would be greatly appreciated!
Best Regards, Charles
                    
                  
                
                    
                      Hello Everyone,
I encountered an issue with PCI memory access in DriverKit. In my case, BAR0 is not available, but BAR1 is ready for use. Here’s the log output:
!!! ERROR : Failed to get BAR0 info (error: 0xe00002f0). !!!
BAR1 - MemoryIndex: 0x00000000, Size: 0x00040000, Type: 0
Issue Description
When I initially wrote to BAR0 using memoryIndex = 0, it worked successfully:
AME_Address_Write_32(pAMEData, pAMEData->memoryIndex, AME_HOST_INT_MASK_REGISTER, 0x0F);
However, I mistakenly forgot to update memoryIndex to 1 for BAR1. Surprisingly, the write operation still succeeded.
When I fixed memoryIndex = 1 for BAR1, the write operation no longer had any effect. There was no error, but the expected behavior did not occur.
Relevant API (From IOPCIDevice.iig)
/*!
/*!
     * @brief       Writes a 32-bit value to the PCI device's aperture at a given memory index.
     * @discussion  This method writes a 32-bit register on the device and returns its value.
     * @param       memoryIndex An index into the array of ranges assigned to the device.
     * @param       offset An offset into the device's memory specified by the index.
     * @param       data A 32-bit value to be written in host byte order.
     */
    void
    MemoryWrite32(uint8_t  memoryIndex,
                  uint64_t offset,
                  uint32_t data) LOCALONLY;
Log Output:
Writes to BAR0 (memoryIndex = 0)
AME_Address_Write_32() called
memoryIndex: 0, offset: 0x34, data: 0xf
Wrote data 0xF to offset 52
AME_Address_Write_32() called
memoryIndex: 0, offset: 0xa0, data: 0x1
Wrote data 0x1 to offset 160
AME_Address_Write_32() called
memoryIndex: 0, offset: 0x20, data: 0xffffffff
Wrote data 0xFFFFFFFF to offset 32
Writes to BAR1 (memoryIndex = 1) – No Response
AME_Address_Write_32() called
memoryIndex: 1, offset: 0x34, data: 0xf
No confirmation log, no visible effect.
Questions
What should memoryIndex be set to for BAR1?
The log shows "BAR1 - MemoryIndex: 0x00000000", but should I be using 1 instead?
How can I verify if a write operation to BAR1 is successful?
Is there a way to check if the memory region is actually writable?
Should I use MemoryRead32() to confirm the written value?
Any guidance would be greatly appreciated!
Best Regards,
Charles
                    
                  
                
                    
                      We have a macOS application which interacts with our USB and PCI devices to perform SCSI and NVME commands on them.
We use IOUSBHost, IOUSBLib and IOKitLib for USB interface and have created a custom driver to interact with PCI devices.
Is there a way we can implement a similar functionality for iOS as well if we connect the cards and readers using OTG?
                    
                  
                
                    
                      Hello Everyone,
I am trying to create a Fake SCSI target based on SCSIControllerDriverKit.framework and inherent from IOUserSCSIParallelInterfaceController, here is the code
kern_return_t IMPL(DRV_MAIN_CLASS_NAME, Start)
{
...
    // Programmatically create a null SCSI Target
    SCSIDeviceIdentifier nullTargetID = 0; // Example target ID, adjust as needed
    ret = UserCreateTargetForID(nullTargetID, nullptr);
    if (ret != kIOReturnSuccess) {
        Log("Failed to create Null SCSI Target for ID %llu", nullTargetID);
        return ret;
    }
...
}
According the document UserCreateTargetForID, after creating a TargetID successfully, the framework will call the UserInitializeTargetForID()
The document said:
As part of the UserCreateTargetForID call, the kernel calls several APIs like UserInitializeTargetForID which run on the default dispatch queue of the dext.
But after UserCreateTargetForID created, why the UserInitializeTargetForID() not be invoked automatically?
Here is the part of log show
init() - Start
init() - End
Start() - Start
Start() - try 1 times
UserCreateTargetForID() - Start
   Allocating resources for Target ID 0
UserCreateTargetForID() - End
Start() - Finished.
UserInitializeController() - Start
 - PCI vendorID: 0x14d6, deviceID: 0x626f.
 - BAR0: 0x1, BAR1: 0x200004.
 - GetBARInfo() - BAR1 - MemoryIndex: 0, Size: 262144, Type: 0.
UserInitializeController() - End
UserStartController() - Start
 - msiInterruptIndex : 0x00000000
 - interruptType info is 0x00010000
 - PCI Dext interrupt final value, return status info is 0x00000000
UserStartController() - End
Any assistance would be greatly appreciated!
Thank you in advance for your support.
Best regards, Charles
                    
                  
                
                    
                      I would like to know if macOS DEXT supports the following networking features: Tx/Rx Multiqueue, RSS, RSC, NS/ARP offload, PTP or packet timestamping and TSN.
I couldn't find relevant documentation for these features in the Apple Developer Documentation.
If they are supported, could you let me know which features are supported and how to find the corresponding official Apple documentation?
Thanks
                    
                  
                
              
                
              
              
                
                Topic:
                  
	
		Developer Tools & Services
  	
                
                
                SubTopic:
                  
                    
	
		General
		
  	
                  
                
              
              
                Tags:
              
              
  
  
    
      
      
      
        
          
            Network Extension
          
        
        
      
      
    
      
      
      
        
          
            NetworkingDriverKit
          
        
        
      
      
    
      
      
      
        
          
            PCIDriverKit
          
        
        
      
      
    
      
      
      
        
          
            DriverKit
          
        
        
      
      
    
  
  
              
                
                
              
            
          
                    
                      Hello Everyone,
I am trying to develop a DriverKit for RAID system, using PCIDriverKit & SCSIControllerDriverKit framework. The driver can detect the Vendor ID and Device ID. But before communicating to the RAID system, I would like to simulate a virtual Volume using a memory block to talk with macOS.
In the UserInitializeController(), I allocated a 512K memory for a IOBufferMemoryDescriptor* volumeBuffer, but fail to use Map() to map memory for volumeBuffer.
result = ivars->volumeBuffer->Map(
        0,                       // Options: Use default
        0,                       // Offset: Start of the buffer
        ivars->volumeSize,       // Length: Must not exceed buffer size
        0,                       // Flags: Use default
        nullptr,                 // Address space: Default address space
        &mappedAddress           // Output parameter
);
Log("Memory mapped completed at address: 0x%llx", mappedAddress); // this line never run
The Log for Map completed never run, just restart to run the Start() and makes this Driver re-run again and again, in the end, the driver eat out macOS's memory and system halt.
Are the parameters for Map() error? or I should not put this code in UserInitializeController()?
Any help is appreciated!
Thanks in advance.
Charles
                    
                  
                
                  
                    
                      
                      
                      
                        
                      
                      
                        
                      
                      
                      DriverKit CppUserClient Searching for dext service but Failed opening service with error: 0xe00002c7
                    
                  
                  
                
                
                    
                      Hi Everybody,
Follow Communicating between a DriverKit extension and a client app to migrate our kext to dext. The dext might have been loaded successfully by using the command systemextensionsctl list, the dext is loaded and enabled.
 % sectl list
1 extension(s)
--- com.apple.system_extension.driver_extension
enabled	active	teamID	bundleID (version)	name	[state]
*	*	K3TDMD9Y6B	com.accusys.scsidriver (1.0/1)	com.accusys.scsidriver	[activated enabled]
We try to use the CppUserClient.cpp to communicate with the dext, but can not get the dext service. The debug message as below:
Failed opening service with error: 0xe00002c7.
Here is the part of CppUserClient.cpp
    static const char* dextIdentifier = "com.accusys.scsidriver";
    kern_return_t ret = kIOReturnSuccess;
    io_iterator_t iterator = IO_OBJECT_NULL;
    io_service_t service = IO_OBJECT_NULL;
    ret = IOServiceGetMatchingServices(kIOMasterPortDefault, 
    IOServiceMatching("IOUserServer"), &iterator);
    printf("dextIdentifier = %s\n", dextIdentifier);
    printf("IOServiceNameMatching return = %d\n", ret);
    if (ret != kIOReturnSuccess)
    {
        printf("Unable to find service for identifier with error: 0x%08x.\n", ret);
        PrintErrorDetails(ret);
    }
    printf("Searching for dext service...\n");
    while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
    {
        // Open a connection to this user client as a server to that client, and store the instance in "service"
        ret = IOServiceOpen(service, mach_task_self_, kIOHIDServerConnectType, &connection);
        if (ret == kIOReturnSuccess)
        {
            printf("\tOpened service.\n");
            break;
        }
        else
        {
            printf("\tFailed opening service with error: 0x%08x.\n", ret);
        }
        IOObjectRelease(service);
    }
    IOObjectRelease(iterator);
    if (service == IO_OBJECT_NULL)
    {
        printf("Failed to match to device.\n");
        return EXIT_FAILURE;
    }
The console output message is
dextIdentifier = com.accusys.scsidriver
IOServiceNameMatching return = 0
Searching for dext service...
    Failed opening service with error: 0xe00002c7.
    Failed opening service with error: 0xe00002c7.
    Failed opening service with error: 0xe00002c7.
    Failed opening service with error: 0xe00002c7.
Failed to match to device.
Here is the log show message
fredapp start UserInitializeController
pcitest: fredapp pci vendorID: 14d6 deviceID: 626f
fredapp nnnnnew configuaration read32 0x10 info: 1
fredapp nnnnnew configuaration read32 0x14 info: 80100004
fredapp new 128 before enable busmaster ReqMSGport_info 0x00000040 : fffff
pcitest: fredapp 131 pci ConfigurationRead16 busmaster value 0
pcitest: fredapp 134 Enable BusMaster and IO space done......
locate 139 fredapp MemoryWrite32 function done......
fredapp new 143 after enable busmaster ReqMSGport_info 0x00000040 : 0
fredapp newwww before GetBARInfo  memoryIndex1 info is: 5
fredapp GetBARInfo 1 kernel return status is: 0
fredapp GetBARInfo  memoryIndex1 info is: 0
fredapp GetBARInfo  barSize1 info is: 262144
fredapp GetBARInfo  barType1 info is: 0
fredapp GetBARInfo  result0 info is: 3758097136
fredapp GetBARInfo  memoryIndex0 info is: 0
fredapp GetBARInfo  barSize0 info is: 0
fredapp GetBARInfo  barType0 info is: 0
pcitest: newwww fredapp againnnn test ReqMSGport info: 8
fredapp Start MPIO_Init_Prepare
fredapp end MPIO_Init_Prepare.
fredapp call 741 Total_memory_size: 1bb900
fredapp Start MemoryAllocationForAME_Module.
fredapp IOBufferMemoryDescriptor create return status info is kIOReturnSuc
fredapp IOBufferMemoryDescriptor virtualAddressSegment address info:   0x1
fredapp virtualAddressSegment length info:   0x00080000
fredapp end IOBufferMemoryDescriptor Create.
fredapp dmaSpecification maxAddressBits:  0x00000000
fredapp dmaSpecification maxAddressBits:  0x00000027
fredapp IODMACommand create return status info is kIOReturnSuccess
fredapp end IODMACommand Create.
fredapp PrepareForDMA  return status info is kIOReturnSuccess
fredapp PrepareForDMA  return status info is 0x00000000
fredapp Allocate memory PrepareforDMA return flags info:   0x00000003
fredapp Allocate memory PrepareforDMA return segmentsCount info:   0x00000
fredapp Allocate memory PrepareforDMA return physicalAddressSegment info: 
fredapp IOBufferMemoryDescriptor virtualAddressSegment address info-2:   0
fredapp verify data success
init() - Finished.
fredapp start UserGetDMASpecification
fredapp end UserGetDMASpecification
fredapp start UserMapHBAData
fredapp end UserMapHBAData
fredapp start UserStartController
fredapp interruptType info is 0x00010000
fredapp PCI Dext interrupt final value  return status info is 0x00000000
Any suggestions?
Best Regards,
Charles
                    
                  
                
                    
                      I have a DriverKit system extension (dext) that uses PCIDriverKit.  I would like to get the build environment straightened out to successfully distribute the dext and associated software to end users.
There are three types of software involved:
The Dext-hosting application - this is the application that must be installed to /Applications/, and will perform the registration of the dext.  The dext is deployed "within" this application, and can be found in the /Contents/Library/SystemExtensions folder of the app bundle.
The dext itself - this is the actual binary system extension, which will be registered by its owning application, and will operate in its own application space independent of the hosting application.
Additional applications that communicate with the dext - these are applications which will connect to the dext through user clients, but these applications do not contain the dext themselves.
There are multiple locations where settings need to be exactly correct for each type of software to be signed, provisioned, and notarized properly in order to be distributed to users:
developer.apple.com - where "identifiers" and "provisioning profiles" are managed. Note that there are differences in access between "Team Agent", "Admin", and "Developer" at this site.
Xcode project's Target "Signing & Capabilities" tab - this is where "automatically manage signing" can be selected, as well as team selection, provisioning profile selection, and capabilities can be modified.
Xcode project's Target "Build Settings" tab - this is where code signing identity, code signing development team, code signing entitlements file selection, Info.plist options and file selection,  and provisioning profile selection.
Xcode's Organizer window, which is where you manage archives and select for distribution.  In this case, I am interested in "Developer ID" Direct Distribution - I want the software signed with our company's credentials (Team Developer ID) so that users know they can trust the software.
Choosing "automatically manage signing" does not work for deployment.  The debug versions of software include DriverKit (development) capability (under App ID configuration at developer.apple.com), and this apparently must not be present in distributable provisioning. I believe this means that different provisioning needs to occur between debug and release builds?
I have tried many iterations of selections at all the locations, for all three types of binaries, and rather than post everything that does not work, I am asking, "what is supposed to work?"
                    
                  
                
                    
                      Hi, I’m developing my own Pcie Ethernet driverkit. My Pcie Ethernet card connect on Razor Core X and connect to MacBook via thunderbolt 3.
The Problem:
Click Driver application and send activate system extension request, then go to System setting -> Privacy & Security, in Extension section ->click “allow” , the peripherals malfunction immediately after "allow" clicked and type in the password.I can't control all peripherals devices like touchpad, keyboard and all of thunderbolt ports. However, it can regain functionality after plugging and unplugging the device.
results I expected:
User approve Driver Extensions enable and all peripherals work normally and Ethernet Card works.
Has anyone encountered this problem? maybe something wrong in "OSSystemExtensionRequestDelegate" but I have no idea how to fix it
Please Help.
My Xcode version is Version 15.3 (15E204a).
Thanks