IOCTL_REGISTER_POWER_RELATIONSHIP | Enables a device driver to register as the proxy for another device driver, so that Power Manager passes all power requests to this device driver. |
IClass Power Management Interfaces
Power Manager supports an IClass registry entry that you can configure in the driver's registry subkey to associate your driver with one or more device class values. An IClass value is a globally unique identifier (GUID) referring to an interface, defined under the HKEY_LOCAL_MACHINESystemCurrentControlSetControlPower Interfaces registry key. The most important interface for driver developers is the interface for generic power management-enabled devices, associated with the GUID {A32942B7-920C-486b-B0E6-92A702A99B35}. By adding this GUID to the IClass registry entry of your device driver, you can inform Power Manager to send your driver IOCTLs for power management notifications, as illustrated in Figure 6-7.
Figure 6-7 Configuring the IClass registry entry to receive power management notifications
You can also use registry settings and device classes to configure the default power states for a device, as explained in Lesson 5, 'Implementing Power Management,' of Chapter 3.
Lesson Summary
To ensure reliable power management on Windows Embedded CE, device drivers should not change their own internal power state without the involvement of Power Manager. Operating system components, drivers, and applications can call the DevicePowerNotify function to request a power state change. Accordingly, Power Manager sends a power state change request to the driver if the power state change is consistent with the current state of the system. The recommended way to add power management capabilities to a stream driver is to add support for power management IOCTLs to the XXX_IOControl function. The XXX_PowerUp and XXX_PowerDown functions only provide limited capability because Power Manager calls these functions at a time when the system operates in single-thread mode. If the device advertises a power management interface through an IClass registry entry or calls the AdvertiseInterface to announce supported IOCTL interfaces dynamically, Power Manager will send IOCTLs to the device driver in response to power-related events.
Lesson 6: Marshaling Data across Boundaries
In Windows Embedded CE 6.0, each process has its own separate virtual memory space and memory context. Accordingly, marshaling data from one process to another requires either a copying process or a mapping of physical memory sections. Windows Embedded CE 6.0 handles most of the details and provides system functions, such as OALPAtoVA and MmMapIoSpace, to map physical memory addresses to virtual memory addresses in a relatively straightforward way. However, driver developers must understand the details of data marshaling to ensure a reliable and secure system. It is imperative to validate embedded pointers and properly handle asynchronous buffer access so that a user application cannot exploit a kernel- mode driver to manipulate memory regions that the application should not be able to access. Poorly implemented kernel-mode drivers can open a back door for malicious applications to take over the entire system.
After this lesson, you will be able to:
¦ Allocate and use buffers in device drivers.
¦ Use embedded pointers in an application.
¦ Verify the validity of embedded pointers in a device driver.
Estimated lesson time: 30 minutes.
Understanding Memory Access
Windows Embedded CE works in a virtual memory context and hides the physical memory, as illustrated in Figure 6-8. The operating system relies on the Virtual Memory Manager (VMM) and the processor's Memory Management Unit (MMU) for the translation of the virtual addresses into physical addresses and for other memory access management tasks.
Figure 6-8 Virtual memory regions in kernel space and user space
Physical addresses are not directly addressable by the CPU except during initialization before the kernel has enabled the MMU, yet this does not imply that the physical memory is no longer accessible. In fact, every fully allocated virtual memory page must map to some actual physical page on the target device. Processes in separate virtual address spaces only require a mechanism to map the same physical memory areas into an available virtual memory region to share data. The physical address is the same across all processes running on the system. Only the virtual addresses differ. By translating the physical address per process into a valid virtual address, processes can access the same physical memory region and share data across process boundaries.
As mentioned earlier in this chapter, kernel-mode routines, such as ISRs, can call OALPAtoVA to map a physical address (PA) into a cached or uncached virtual address (VA). Because OALPAtoVA maps the physical address to a virtual address in the kernel space, user-mode processes, such as ISTs, cannot use this function. The kernel space is inaccessible in user mode. However, threads in user-mode processes, such as ISTs, can call the MmMapIoSpace function to map a physical address to a nonpaged, cached or uncached virtual address in the user space. The MmMapIoSpace call results in the creation of a new entry in the MMU Table (TBL) if no match was found or it returns an existing mapping. By calling the MmUnmapIoSpace function, the user- mode process can release the memory again.
Applications and user-mode drivers cannot access physical device memory directly. User-mode processes must call HalTranslateBusAddress to map the physical device memory range for the bus to a physical system memory address before calling MmMapIoSpace. To convert a bus address into a virtual address in a single function call, use the TransBusAddrToVirtual function, which in turn calls HalTranslateBusAddress and MmMapIoSpace.