Выбрать главу

Lesson 7: Enhancing Driver Portability

Device drivers help to increase the flexibility and portability of the operating system. Ideally, they require no code changes to run on different target devices with varying communication requirements. There are several relatively straightforward techniques that you can use to make your drivers portable and reusable. One common approach is to maintain configuration settings in the registry instead of hardcoding the parameters into the OAL or the driver. Windows Embedded CE also supports a layered architecture based on MDD and PDD that you can leverage in your device driver design, and there are further techniques that you can use to implement drivers in a bus-agnostic way to support peripheral devices regardless of the bus type to which they are connected.

After this lesson, you will be able to:

■ Describe how to use registry settings to increase the portability and reusability of a device driver.

■ Implement a device driver in a bus-agnostic way.

Estimated lesson time: 15 minutes.

Accessing Registry Settings in a Driver

To increase the portability and reusability of a device driver, you can configure registry entries, which you should add to the driver's registry subkey. For example, you can define I/O-mapped memory addresses or settings for installable ISRs that the device driver loads dynamically. To access the entries in a device driver's registry key, the driver has to identify where its own settings are located. This is not necessarily the HKEY_LOCAL_MACHINE\Drivers\BuiltIn key. However, the correct path information is available in the Key value that you can find under the HKEY_LOCAL_MACHINE\Drivers\Active key in the loaded driver's subkey. Device Manager passes the path to the driver's Drivers\Active subkey to the XXX_Init function in the LPCTSTR pContext parameter. The device driver can then use this LPCTSTR value in a call to OpenDeviceKey to obtain a handle to the device's registry key. It is not necessary to read the Key values from the driver's Drivers\Active subkey directly. The handle returned by OpenDeviceKey points to the driver's registry key, which you can use like any other registry handle. Most importantly, do not forget to close the handle when it is no longer needed.

TIP
XXX_Init function and driver settings

The XXX_Init function is the best place to determine all configuration settings for a driver defined in the registry. Rather than accessing the registry repeatedly in subsequent stream function calls, it is good practice to store the configuration information in the device context created and returned to Device Manager in response to the XXX_Init call.

Interrupt-Related Registry Settings

If your device driver must load an installable ISR for a device and you want to increase the portability of your code, you can register the ISR handler, IRQ, and SYSINTR values in registry keys, read these values from the registry when initializing the driver, verify that the IRQ and SYSINTR values are valid, and then install the specified ISR by using the LoadIntChainHandler function.

Table 6-9 lists the registry entries that you can configure for this purpose. By calling the DDKReg_GetIsrInfo function, you can then read these values and pass them to the LoadIntChainHandler function dynamically. For more information about interrupt handing in device drivers, see Lesson 4, "Implementing an Interrupt Mechanism in a Device Driver," earlier in this chapter.

Table 6-9 Interrupt-related registry entries for device drivers

Registry Entry Type Description
IRQ REG_DWORD Specifies the IRQ used to request a SYSINTR for setting up an IST within the driver.
SYSINTR REG_DWORD Specifies a SYSINTR value to use for setting up an IST within the driver.
IsrDll REG_SZ The filename of the DLL containing the installable ISR.
IsrHandler REG_SZ Specifies the entry point for the installable ISR that the specified DLL exposes.

Memory-Related Registry Settings

Memory-related registry values enable you to configure a device through the registry. Table 6-10 lists the memory-related registry information that a driver can obtain in a DDKWINDOWINFO structure by calling DDKReg_GetWindowInfo. By using the BusTransBusAddrToVirtual function, you can map the bus addresses of memory-mapped windows to physical system addresses you can then translate into virtual addresses by using MnMapIoSpace.

Table 6-10 Memory-related registry entries for device drivers

Registry Entry Type Description
IoBase REG_DWORD A bus-relative base of a single memory-mapped window used by the device.
IoLen REG_DWORD Specifies the length of the memory-mapped window defined in IoBase.
MemBase REG_MULTI_SZ A bus-relative base of multiple memory-mapped windows used by the device.
MemLen REG_MULTI_SZ Specifies the length of the memory-mapped memory windows defined in MemBase.

PCI-Related Registry Settings

Another registry helper function that you can use to populate a DDKPCIINFO structure with the standard PCI device instance information is DDKReg_GetPciInfo. Table 6-11 lists the PCI-related settings you can configure in a driver's registry subkey.