Reading and Writing to Device Registers in UMDF 1.x Drivers

Warning

UMDF 2 is the latest version of UMDF and supersedes UMDF 1. All new UMDF drivers should be written using UMDF 2. No new features are being added to UMDF 1 and there is limited support for UMDF 1 on newer versions of Windows 10. Universal Windows drivers must use UMDF 2.

The archived UMDF 1 samples can be found in the Windows 11, version 22H2 - May 2022 Driver Samples Update.

For more info, see Getting Started with UMDF.

Starting in UMDF version 1.11, the framework provides a set of routines to access registers in memory space and I/O port space. The UMDF register/port access routines are very similar to the HAL routines used by kernel-mode drivers. After a driver has mapped registers as described in Finding and Mapping Hardware Resources in a UMDF Driver, the driver uses the READ/WRITE_REGISTER_Xxx routines to read and write to individual registers. For I/O ports, the driver calls the READ/WRITE_PORT_Xxx routines.

This example shows how to write to a memory-mapped register.

VOID
CMyQueue::WriteToDevice(
    __in IWDFDevice3* pWdfDevice,
    __in UCHAR Value
    )
{
    //
    // Write the UCHAR value at offset 2 from register base
    //
    WRITE_REGISTER_UCHAR(pWdfDevice, 
                      (m_MyDevice->m_RegBase)+2, 
                       Value);
}

By default, UMDF internally uses system calls to access the registers mapped either in memory space or in I/O port space. A register in I/O port space is always accessed through a system call. However, when accessing memory-mapped registers, a UMDF driver can cause the framework to map the memory-mapped registers into user-mode address space by setting the INF directive UmdfRegisterAccessMode to RegisterAccessUsingUserModeMapping. Some drivers may need to do this for performance reasons. See Specifying WDF Directives in INF Files for a complete list of UMDF INF directives.

The driver should use the READ/WRITE_REGISTER_Xxx routines even if it has mapped registers into user-mode. These routines validate driver input and ensure that the driver doesn't request access to invalid locations. Rarely, a driver may need to access user-mode mapped registers directly, without using these routines. To do so, a driver retrieves the user-mode mapped address by calling IWDFDevice3::GetHardwareRegisterMappedAddress on the mapped base address. Because UMDF doesn't validate read and write accesses performed in this way, this technique is not recommended for register access.