Introduction to Plug and Play and Power Management[Copy link]
Introduction to Plug and Play and Power Management
This chapter describes the main concepts related to writing drivers that support Plug and Play and power management. This information is organized as follows:
1.1 What is Plug and Play?
1.1.1 PnP components
1.1.2 Levels of PnP support
1.2 What is power management?
1.2.1 The original meaning of power management
1.2.2 Levels of power management support
1.2.3 Overview of system-wide power management
1.2.4 Power states
1.3 Device tree
1.4 Driver layering and device objects
1.4.1 Driver types
1.4.1.1 Bus drivers
1.4.1.2 Function drivers
1.4.1.3 Filter drivers
1.4.2 Driver layering - an example
1.4.3 Device object types
1.4.4 Device objects - an example
Read Chapter 2 to get an overall impression of how drivers support PnP and power management. Read Part 2 for more information about PnP, Part 3 for more information about power management, and Part 4 for more information about drivers and device installation.
1.1 What is Plug and Play? Plug and Play (PnP) is a combination of hardware and software support that enables a system to recognize or adapt to small changes in hardware configuration without user intervention. Users can add or remove devices from a computer system without having to do cumbersome and confusing manual configuration and without requiring intricate knowledge of computer hardware. For example, a user can connect a laptop and use a docking station keyboard, mouse, and monitor without having to manually change the configuration.
PnP requires support from hardware devices, system software, and drivers. The original idea of the hardware industry was to define standards (such as the PnP ISA definition and the PC Card standard) for easily identifiable plug-in boards and basic system components. This DDK documentation focuses on system software support for PnP and how drivers use this support to implement PnP.
System software support for PnP, along with PnP drivers, provides the following functionality:
n Automatic and dynamic identification of installed hardware
System software identifies hardware during initial system installation, identifies PnP hardware changes that occur between system boots, and responds to run-time hardware events such as connections or disconnections and device additions or removals.
n Hardware resource allocation (and reallocation)
The PnP manager determines the hardware resources requested by each device (for example, input/output [I/O] ports, interrupt requests [IRQs], direct memory access [DMA] channels, and memory locations) and allocates the hardware resources appropriately. The PnP manager reconfigures resource allocations when necessary, for example when new devices are added to the system that must use resources.
PnP device drivers do not allocate resources; instead, when a device is enumerated, the resources requested by the device are identified. During the resource allocation process, the PnP manager finds each driver's request. For an older device, resources are not dynamically allocated, so the PnP manager first allocates resources to the older driver.
n Loading of appropriate drivers
The PnP manager determines which drivers are necessary to support each device and loads these drivers.
n Programming interfaces for drivers to interact with the PnP system The interfaces
include IoXxx routines, PnP IRPs, necessary driver entry points, and registry information.
n Mechanisms for drivers and applications to learn about changes in the hardware environment and take appropriate actions
PnP allows drivers and user-mode code to register and be notified of certain hardware events.
PnP drivers are an important part of PnP support. As a qualified PnP driver, it must provide necessary PnP entry points, handle necessary PnP IRPs, and follow PnP wizards. For more information, see Chapter 2.
1.1.1 PnP Components Figure 1.1 shows a set of components that work together to support PnP
Figure 1.1 PnP software components
The PnP manager has two parts: the kernel-mode PnP manager and the user-mode PnP manager. The kernel-mode PnP manager interacts with OS components and drivers to configure, manage, and maintain devices. The user-mode PnP manager interacts with user-installed components, such as class installers, to configure and install devices. The user-mode PnP Manager also interacts with some applications, for example, registering an application for device change notification and notifying the application when a device event occurs.
PnP drivers support physical, logical, and virtual machine devices. WDM drivers follow the Microsoft driver model and support devices on Microsoft Windows 2000 and Windows 98 systems. WDM PnP drivers communicate with the PnP Manager and other kernel components through well-defined APIs and IRPs. See Volume 1 of the Windows 2000 Driver Development Reference for a detailed description of these APIs and IRPs. Machines with Windows 2000 installed may have some PnP drivers that do not support WDM.
All PnP drivers should support PnP and power management. If a single PnP driver does not support PnP and power management, it constrains PnP drivers and power management for the system as a whole.
Refer to Part 4 for information about device and driver installation, including INF files, .cat files, and the registry.
1.1.2 Levels of PnP Support The extent to which a device supports PnP depends on the device hardware and the PnP support in the device driver (see Table 1.1).
Table 1.1 PnP Capability Levels for Driver/Device Combinations
PnP Driver Non-PnP Driver
PnP Device Full PnP No PnP
Non-PnP Device Possible Partial PnP No PnP
Any device that supports PnP should have PnP support in its driver.
A non-PnP device can have some PnP capabilities if it is driven by a PnP driver. For example, an ISA sound card and an EISA network card can be manually installed, and then the PnP driver can treat the card like a PnP device.
If a driver does not support PnP, its device behaves as a non-PnP device regardless of any hardware PnP support. A non-PnP driver can restrict the PnP and power management capabilities of the entire system.
Older drivers written before the OS supported PnP continue to work as before, but without any PnP capabilities. New drivers should include PnP support.
1.2 What is Power Management? Power management is a system-wide, integrated approach to using and conserving power. Computer systems that include power management hardware and software support provide the following features:
n Minimized startup and shutdown delays
Systems can be hibernated in a low-power state, from which they can resume operation without a complete reboot of the system. From the user's perspective, waking a dormant computer is roughly like turning a television on and off.
n Greater power efficiency and battery life Power
is applied to devices only when they are delivering functionality to the user. If a device is not in use, power can be disconnected and then reapplied on command.
n Quieter operation
Disconnecting power to unused devices reduces noise. In addition, hardware and software can manage power loading and heat loading, resulting in virtually no sound when the computer is dormant. The
industry OnNow Initiative defines the hardware and software requirements for power management. For details, see the industry initiative on power management.
In Windows 2000, Windows 98, and other operating systems that support power management, computers and other external devices are maintained at the lowest feasible level required to complete the task at hand. Drivers work with the operating system to manage the power of their devices. If all drivers support power management, the operating system can manage power consumption on a system-wide basis so that power conservation, power cuts and quick resumes, and wakeups when needed can all be managed.
This integrated approach to power management -- in the operating system, system hardware, device drivers, and device hardware -- produces the following results:
n Smarter power management decisions. At each level, optimally informed components direct power usage.
n Higher reliability. Better power management decisions reduce the potential for untimely shutdowns and data loss.
n Platform independence. The operating system manages power in a controlled, single approach across different hardware platforms, allowing for maximum power conservation across different devices. n
Better device integration. Device drivers that conform to industry specifications ensure maximum power conservation regardless of the hardware platform.
Taken together, these benefits result in more power conservation and more efficient use of power that was not possible before.
1.2.1 The Original Meaning of Power Management The OnNow Initiative describes the hardware and software support required for power management.
The OnNow Initiative portion of the Advanced Configuration and Power Management Interface specification describes a hardware-level interface that enables the operating system to implement power management in a consistent, platform-independent manner.
Device Class Power Management Reference Specifications are available for each common device class, such as audio or communications devices. Each specification describes the power management requirements for a device class. Driver writers should refer to these specifications, and device-specific details are available on the Microsoft website.
1.2.2 Levels of Power Management Support Drivers that support PnP must support power management, and drivers that support power management must also support PnP. Power management and PnP are integrated and not independent of each other.
Power management operates at two levels: system-wide and per-device.
The power manager, part of the operating system kernel, manages the power level of the entire system. If all drivers in the system support power management, the power manager can manage power consumption on a system-wide basis, not only using a fully on or fully off state, but also a variety of intermediate system sleep states.
Older drivers written before the operating system supported power management can continue to work as before. However, systems that include older drivers cannot enter any intermediate system sleep states; they can only operate in the fully on or fully off state as before.
Drivers handle device power management. A driver that supports power management can turn its device on when needed and turn it off when not needed. Devices can enter intermediate power states if the device has the hardware capabilities to do so. Older drivers in the current system have no effect on the ability of newer drivers to manage the power of their devices.
1.2.3 Overview of System-Wide Power Management Power management requires support from both the system and device hardware and from system software and drivers. As described in the "What is Power Management Originally" section, the necessary hardware support is covered in industry specifications. This section covers software support, specifically what drivers should do to comply with the operating system's requests and properly manage the power of their devices.
Figure 1.2 gives an overview of system-wide power management
Applications and users have entered power management decisions, respectively, through the API and the Control Panel. Users can set certain power options through the Control Panel, including device-specific GUID controls, which are then provided by the user interface if the corresponding driver supports it. Through WMI, the Control Panel notifies the power manager and drivers of changes in GUID controls.
The power manager manages the system-wide power policy, which contains the rules that govern system power usage. (See System Power Management in Chapter 3, Part 3, for details.) Using information from the Control Panel and the information it obtains, the power manager can determine when applications are in use or may need to use different devices, so that it can adjust the system's power policy appropriately.
The power manager also provides a driver interface that consists primarily of PoXxx routines, power management IRPs, and necessary driver entry points.
When the power manager requests a change in the system power state, drivers respond by placing their devices in the appropriate device power state. In addition, drivers can detect if a device is idle and set unused devices to sleep. Bus-specific mechanisms report device power capabilities, set and report device states, and change device power. How and when exactly to change device power depends on the device type and the capabilities of the device hardware.
Although ACPI hardware is aware of maximum power reserves, the hardware does not need to comply with the ACPI specification for power management to be effective in drivers.
1.2.4 Power States Power states indicate the level of consumption of the system or individual devices and also indicate the scope of enumeration activity. The power manager sets the power state of the entire system, while device drivers set the power state of their individual devices.
The ACPI specification defines discrete power states for the system and individual devices. System power states are referenced as Sx, where x is a state number between 0 and 5, and device states are referenced as Dx, where x is a state number between 0 and 3. The number of states is inversely related to power consumption: the higher the number of states, the less power they use. States S0 and D0 are the highest power, most functional, and most complete states, and states S5 and D3 are the lowest power states and have the longest wake-up times.
Strictly defined power states allow many devices from different manufacturers to work together consistently and predictably. For example, when the power manager sets the system to state S3, it can rely on drivers that support the power manager to set their devices to the appropriate device states and return to working state in a predictable manner.
1.1 Device Tree
The OS maintains a device tree that keeps track of the devices in the system. Figure 1.3 shows an example of a device tree for a system configuration.
The device tree keeps information about the devices that exist in the system. The OS builds this tree when the machine boots, using information obtained from drivers and other components, and updates the tree when devices are added or removed. The device tree is hierarchical, with devices on the bus represented as "children" of the bus adapter or controller. You can see the device tree hierarchy in the Device Manager in Use (select "View", then "Devices by connection").
Each node in the device tree is a device node (devnode). A devnode contains the device object of the device driver plus internal information maintained by the OS. See Section 1.4.3 for more information.
Figure 1.3 Example of a PnP device tree
The hierarchy of the device tree reflects the structure of device attachments in the machine, and the OS uses this hierarchy when it manages devices. For example, if a user requests to unplug the USB controller from the machine shown in Figure 1.3, the PnP manager determines from the device tree that this action will also cause three other devices to be unplugged (the USB hub, the joystick, and the camera). When the PnP manager asks the driver for the USB controller whether it is safe to remove the controller, the PnP manager similarly queries the driver for any children of the controller (the USB hub, the joystick, and the camera).
In addition to the hierarchical relationships given in the device tree, there are other relationships between machine devices, including deletion and extraction relationships. For more information, see the IRP_MN_QUERY_DEVICE_RELATIONS reference page in Volume 1 of the Windows 2000 Driver Development Reference.
1.3 Driver Hierarchy and Device Objects The I/O system provides a layered driver architecture. This section discusses the architecture from the perspective of drivers that support PnP and power management. The discussion includes the various types of drivers, driver hierarchies, and device objects.
1.3.1 Driver Types From a PnP perspective, there are three types of drivers:
n Bus drivers—drive the I/O bus and provide individual per-slot functionality between devices
n Function drivers—drive a single device
n Filter drivers—filter I/O requests for a device, device class, or bus
In this book, a bus is any physical, logical, or virtual device to which devices can be attached; buses include traditional buses such as SCSI and PCI, as well as parallel, serial, and i8042 ports.
It is important for a driver programmer to know the different types of PnP drivers and which type of driver they are writing. For example, whether a driver handles each PnP IRP and how it handles the IRP depends on which type of driver is being written (a bus driver, function driver, or filter driver).
Figure 1.4 shows the relationship between the bus driver, function driver, and filter driver for a device.
Each device typically has a bus driver that manages the parent I/O bus, a function driver for the device, and zero or more filter drivers for the device. A driver design that requires many filter drivers does not produce optimal performance. The
drivers in Figure 1.4 are as follows:
1. Bus drivers service a bus controller, adapters, and bridges. Bus drivers are required drivers; there is one driver for each type of bus on a machine. Microsoft provides bus drivers for most common buses, and IHVs and OEMs provide others.
2. Bus filter drivers typically add value to a bus. They are provided by Microsoft or the system OEM. There can be any number of bus filter drivers for a bus.
3. Lower-level filter drivers typically modify the behavior of the device hardware. They are optional and typically provided by the IHV. There can be any number of lower-level filter drivers for a device.
Figure 1.4 Possible driver hierarchy
4. Function drivers are the primary device drivers. A function driver is typically and must be written by the device vendor (unless the device uses raw mode).
5. Top-level filter drivers typically provide value-added features for a device. They are optional and are typically provided by the IHV.
The following sections describe the general types of drivers (bus drivers, function drivers, and filter drivers).
1.3.1.1 Bus Drivers A bus driver services a bus controller, adapter, or bridge (see Figure 1.4). Microsoft provides bus drivers for most common buses, such as PCI, PnpISA, SCSI, and USB. Other bus drivers are provided by IHVs and OEMs. Bus drivers are required drivers; there is one bus driver for each type of bus in a machine. If there is more than one bus of the same type in the machine, a bus driver can service more than one bus.
The main tasks of a bus driver are:
n Enumerate the devices on its bus
n Respond to PnP and power management IRPs
n Multiplex bus access (for some buses)
n Overall management of the devices on its bus
During enumeration, a bus driver identifies the devices on its bus and creates device objects for them. The method a bus driver uses to identify connected devices depends on the particular bus.
A bus driver performs certain operations on behalf of the devices on its bus, including accessing device registers to physically change the power state of the device. For example, when a device goes to sleep, the bus driver sets the device registers to give the device the appropriate power state.
Note, however, that a bus driver cannot handle read and write requests from devices on its bus; read and write requests for a device are handled by the device's function driver (see Section 1.4.1.2). The parent bus driver handles reads and writes to a device only when the device is used in raw mode.
A bus driver acts as a function driver for a controller, adapter, or bridge, and thus manages the device power policy for the controller, adapter, or bridge.
A bus driver can be implemented as a driver/minidriver pair, which is the way a SCSI port/miniport pair drives a SCSI HBA (host bus adapter). In such a driver pair, the minidriver is linked to a second-level driver (which is a DLL).
1.3.1.2 Function Drivers A function driver is the primary driver for a device (see Figure 1.4). A function driver is typically written by the device manufacturer and must be written by the device manufacturer (unless the device uses raw mode). The PnP manager loads at least one function driver for a device. A function driver can service one or more devices.
A function driver provides an operating interface for its device. Typically, a function driver handles reading and writing to the device and manages the device power policy.
A device's function driver can be implemented as a driver/minidriver pair, such as a port/miniport or a class/miniclass pair. In such a driver pair, the minidriver is linked to the next-level driver (which is a DLL).
If a device is driven in raw mode, it has no function driver and top or lower filter drivers. All raw model I/O is implemented through the bus driver and the optional bus filter driver.
1.3.1.3 Filter Drivers A filter driver is an optional driver that adds value to a device or modifies the behavior of a device. A filter driver can service one or more devices.
Bus filter driver
Bus filter drivers typically add value to the bus and are provided by Microsoft or the system OEM (see Figure 1.4). Bus filter drivers are optional, and there can be any number of bus filter drivers for a bus.
For example, bus filter drivers can implement feature enhancements to standard bus hardware.
For devices described by the ACPI BIOS, power management inserts a Microsoft-provided ACPI filter (bus filter driver) on top of the bus driver for each such device. The ACPI filter enforces device power policy and turns the device power on and off. The ACPI filter is transparent to other drivers and is not present on non-ACPI machines.
Low-level filter drivers
Low-level filter drivers typically modify the behavior of the device hardware (see Figure 1.4). They are typically provided by the IHV and are optional. There can be any number of low-level filter drivers for a device.
Low-level device filter drivers monitor and/or modify I/O requests for a specific device. Typically, these filters redefine the hardware behavior to match the expected specification.
A low-level class filter driver monitors and/or modifies I/O requests for a device class. For example, a low-level class filter driver for a mouse device can provide acceleration by performing a nonlinear conversion of mouse motion data.
Top-level filter drivers
Top-level filter drivers typically provide value-added features for a device (see Figure 1.4). Such drivers are usually provided by the IHV and are optional. A device can have any number of top-level filter drivers.
Top-level device filter drivers add value for a particular device. For example, a top-level device filter driver for a keyboard can enforce additional security checks.
Top-level class filter drivers add value for all devices of a particular class.
1.3.2 Driver Hierarchy - An Example This section describes a possible set of PnP drivers for USB hardware to illustrate the PnP driver hierarchy.
Figure 1.5 shows an example of a PnP hardware configuration for a USB joystick. In Figure 1.5, the USB joystick is plugged into a port on a USB hub. The USB hub in this example resides on a USB host controller board and plugs into a single port on the USB host controller board. The USB host controller is plugged into a PCI bus. From a PnP perspective, the USB hub, USB host controller, and PCI bus are all bus devices because each of them provides ports. A joystick is not a bus device.
Figure 1.5 Example of a USB joystick for PnP hardware
Figure 1.6 gives an example of a set of drivers that might be loaded for the USB joystick hardware in Figure 1.5.
Starting at the bottom of Figure 1.6, the drivers in the example stack include:
n A PCI driver that drives the PCI bus. This is a PnP bus driver. The PCI bus driver comes with Microsoft's system.
n The bus driver for the USB host controller is implemented as a class/miniclass driver pair. Microsoft's system comes with a USB host controller class and miniclass driver.
n The USB hub bus driver drives the USB hub. Microsoft's system provides a USB hub driver.
n Three drivers for the joystick device, one of which is a class/miniclass pair.
Figure 1.6 Example of a PnP driver hierarchy---The USB joystick
function driver, the primary driver for the USB joystick device, is a HID class driver/HID USB miniclass driver pair. (HID stands for "human interface device") The HID USB miniclass driver supports the USB-specific syntax for HID devices, relying on the HID class driver DLL for overall HID driver support.
Function drivers can be dedicated to a specific device, or in the HID state, a function driver can service a group of devices. In this example, the HID class/HID USB miniclass driver pair services any HID-compliant device in a USB bus system. A HID class driver/HID 1394 miniclass driver pair will service any HID-compliant device in a 1394 bus system.
Function drivers are written by the device manufacturer or by Microsoft. In this example, the function driver (HID class/HID USB miniclass driver pair) was written by Microsoft. In this example
, the joystick device has two filter drivers: a top-level class filter that adds a macro button feature and a low-level device filter that enables the joystick to enumerate as a mouse device.
Joystick I/O writers who need to filter write the top-level filter, and joystick vendors write the low-level filter drivers.
n Kernel-mode and user-mode HID clients and applications are not drivers, but are included for completeness.
1.3.3 Types of Device Objects A driver creates a device object for each device it controls. The device object represents the driver's device. From the PnP perspective, there are three types of device objects:
n Physical Device Object (PDO) --- represents a bus driver's device
n Functional Device Object (FDO) --- represents a function driver's device
n Filter Device Object (Filter DO) --- represents a filter driver's device
All three types of device objects are of type DEVICE_OBJECT, but are used differently and have different device extensions.
A driver adds itself to the I/O driver stack that handles a device by creating a device object (IoCreateDevice) and attaching it to the device stack (IoAttachDeviceToDevice_Stack). IoAttachDeviceToDeviceStack determines the current top level of the device stack and attaches the new device object to the top level of the device stack.
Figure 1.7 shows the possible types of device objects that can be attached to the device stack to represent the driver that handles I/O requests for a device.
This section describes each type of device object and notes when the class is created. See Chapter 2 for details on creating device objects in the necessary PnP driver routines, and for more information on PnP device enumeration, see Part 2.
Starting at the bottom of Figure 1.7:
The bus driver creates a PDO for each device on the bus that it enumerates.
As the bus driver enumerates its devices, it creates a PDO for each child device. The bus driver enumerates a device in response to an IRP_MN_QUERY_DEVICE_RELATIONS request to the PnP manager's BusRelations. If the device has been added to the bus since the last time the bus driver responded to a query relations request to BusRelations (or if this is the first time the machine has been booted), the bus driver creates a PDO for each child device.
The PDO represents the device to the bus driver, as do other kernel-mode system components such as the power manager, the PnP manager, and the I/O manager.
Other drivers for a device attach to the device object at the top of the PDO, but the PDO is always at the bottom of the device stack.
n Optional bus filter drivers create filter DOs for each device they filter.
When the PnP Manager discovers a new device in the BusRelations list, it determines whether there are any bus filter drivers for the device. If so, for each such driver the PnP Manager ensures that they are loaded (calling DriverEntry if necessary) and calls the driver's AddDevice routine. If a bus filter driver filters for this device, the filter driver creates a device object and attaches it to the device stack in the AddDevice routine. If more than one bus filter driver exists and is associated with this device, each such filter driver creates and attaches its own device object.
n Optionally, lower-level filter drivers create filter DOs for each device they filter.
If an optional lower-level filter driver exists for this device, the PnP Manager makes sure such a driver is loaded after the bus driver and any bus filter drivers. The PnP Manager calls the filter driver's AddDevice routine. In its AddDevice routine, the lower filter driver creates a filter DO for the device and attaches it to the device stack. If more than one lower filter driver exists, each such driver creates and attaches its own filter DO.
n The function driver creates an FDO for the device.
The PnP Manager makes sure that the function driver for the device is installed and calls the function driver's AddDevice routine. The function driver creates an FDO and attaches it to the device stack.
n Optional, top-level filter drivers create filter DOs for each device they filter.
If any optional, top-level filter drivers exist for the device, the PnP Manager makes sure that they are installed after the function drivers call their AddDevice routines. Each such filter driver attaches its device object to the device stack.
In summary, the device stack contains a device object for each driver that participates in I/O processing for a particular device. The parent bus driver has one PDO, the function driver has one FDO, and each optional filter driver has one filter DO.
Note that all devices--bus adapter/controller devices and non-bus devices--have a PDO and FDO in their device stack. The PDO for a bus adapter/controller is created by the bus driver for the parent bus. For example, if a SCSI adapter is plugged into a PCI bus, the PCI bus driver creates a PDO for the SCSI adapter.
If a device is being used in raw mode, there are no function drivers or filter drivers (no FDO or filter DOs). There is also a PDO for the parent bus driver and zero or more bus filter DOs.
For information about which driver routines are responsible for creating and attaching device objects, see Chapter 2.
The device stack and some additional information make up a devnode device. In a device's devnode, the PnP manager keeps track of information such as whether the device is started and which drivers, if any, are registered to be notified of changes on the device. Kernel debugger! The devnode command displays information about a devnode.
1.3.4 Device Objects--An Example This section describes a possible driver's device object created by the driver for USB hardware to illustrate PnP device objects and how they are layered.
Figure 1.8 shows the device objects created by the example driver described in Section 1.4.2.
Figure 1.8 Example of PnP Device Object Hierarchy—USB Joystick
Starting at the bottom of Figure 1.8, the device objects in the device stack example include:
1. A PDO and an FDO for the PCI bus
The root bus driver enumerates the internal system bus (the root bus) and creates a PDO for each device it finds, one of which supports the PCI bus. (The PDO and FDO for the root bus are not shown in the figure.)
The PnP manager identifies the PCI driver as the function driver for the PCI bus, installs the driver (if it is not already installed), and passes the PDO to the PCI driver. In its AddDevice routine, the PCI driver creates an FDO for the PCI bus (IoCreateDevice) and adds the FDO to the PCI bus's device stack (IoAttachDeviceToDeviceStack). Like the function driver for the PCI bus, the PCI driver creates and attaches this FDO as part of its job.
In this example, there is no filter driver for the PCI bus.
2. A PDO and an FDO for the USB host controller
The PnP manager instructs the PCI driver to start its device (IRP_MN_START_DEVICE) and then queries its child (IRP_MN_QUERY_DEVICE_RELATIONS BusRelations) PCI drivers. In response, the PCI driver enumerates the devices on its bus. In this example, the PCI driver discovers a USB host controller and creates a PDO for that device. The wide arrow in the figure indicates that the USB host controller is a "child" of the PCI bus. The PCI driver creates the PDO for its child device as part of its task as a bus driver supporting the PCI bus.
The PnP manager identifies the USB host controller miniclass/class driver pair as the function driver for the USB host controller and loads the driver pair, which the PnP manager calls upon at the appropriate time to create and attach an FDO for the USB host controller.
In this example, there is no filter driver supporting the USB host controller.
3. A PDO and an FDO for the USB hub
The USB host controller enumerates its bus, locates the USB hub on a single port, and creates a PDO for the hub. The USB hub driver creates and attaches an FDO for the hub.
In this example, there is no filter driver for the USB hub.
4. One PDO, One FDO, and Two Filter DOs for the Joystick Device
The USB hub driver enumerates its bus, locates a HID device (the joystick), and creates a joystick PDO.
In this example, the lower-level filter driver has been set up in the registry for the joystick device, so the PnP manager loads the filter driver. The filter driver determines the associated device and creates and attaches a filter DO to the device stack.
The PnP manager determines that the function driver for the joystick device is the HID class/miniclass driver pair and loads these drivers. The driver pair consists of a miniclass driver that links to the class driver DLL; together they act as a function driver for the device. The class/miniclass driver pair creates a device object, an FDO, and attaches it to the device stack. The
top-level filter driver creates and attaches a filter DO to the device stack in a similar manner to the lower-level filters.
Note that the FDO created by the parent bus driver is always at the bottom of the device stack for a particular device. When drivers handle PnP or power IRPs, they must pass each IRP down the device stack to the PDO and its associated bus driver.
Figure 1.9 shows the same device stack as Figure 1.8, but emphasizes which device objects are created and managed by which drivers.
Figure 1.9 Example of a device object hierarchy from a driver's perspective
A bus driver spans multiple device stacks. A bus driver creates FDOs for its bus adapter/controller and a PDO for each of its child devices.
Chapter 2 Required Driver Support for PnP and Power Management
This chapter describes the routines and IRP handling that are required to support Plug and Play (PnP) and power management in Windows 2000 and WDM drivers. It covers the following topics:
2.1 Overview of Required PnP Support
2.2 PnP and Power Management DriverEntry Routine
2.3 PnP and Power Management AddDevice Routine
2.3.1 Guidelines for Writing AddDevice Routine
2.4 Dispatch PnP Routine
2.5 DispatchPower Routine
2.6 PnP and Power Management Unload Routine
Some drivers are isolated from the details of the PnP and power systems through system-provided port or class drivers; such drivers do not need to implement all of these mechanisms. For example, a SCSI port driver shields a SCSI miniport driver from many of the details of the power management and PnP systems; such a SCSI miniport driver does not need to handle power and PnP IRPs directly. For such drivers, refer to the driver-specific files for details of the necessary PnP support.
See Chapter 1 for an introduction to PnP and power management concepts and terminology.
2.1 Overview of Required PnP Support A driver that supports PnP and power management must have the following features:
n An INF file to install the driver
n A .cat (catalog) file that has the WHQL digital signature of the driver package
n A DriverEntry routine to initialize the driver
n An AddDevice routine to initialize the device
n A DispatchPnP routine that handles IRPs for PnP operations, such as starting, stopping, and removing the device
n A DispatchPower routine that handles IRPs for power operations
n An Unload routine that removes any driver-specific resources set by DriverEntry
These routines are discussed in the following sections. See Section 4 for information about INF files, .cat files, and driver installation.
2.2 PnP and Power Management DriverEntry Routine A DriverEntry routine initializes a driver. All drivers must have a DriverEntry routine. When loading drivers, the PnP manager calls DriverEntry once for each driver. After the driver is initialized, the PnP Manager can call the driver's AddDevice routine to initialize the device controlled by the driver.
The DriverEntry routine is defined as follows:
NTSTATUS
(*PDRIVER_INITIALIZE) (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
You can give the initialization routine a name other than DriverEntry, as long as the driver identifies the initialization routine name to the linker. The linker must have the name of the initialization routine to link the driver's transport addresses to the OS loader. A driver initialization routine named DriverEntry automatically makes this link.
The DriverEntry routine is called in the context of a system thread at IRQL PASSIVE_LEVEL.
A DriverEntry routine can use the registry to get some of the information it needs to initialize the driver. The DriverEntry routine must set information in the registry for other drivers and/or protected subsystems to use. For more information about using the registry, see Section 4.
A DriverEntry routine is pageable and should be in the INIT segment so that it will be discarded.
A DriverEntry routine must take the following steps:
1. Initialize the driver dispatch table
. A driver must specify entry points for the driver's AddDevice routine, Dispatch routine, StartIo routine (if any), Unload routine, and any other driver entry points. For example, a driver should set entry points for its AddDevice, DispatchPnp, and DispatchPower routines as follows (Xxx is a prefix that identifies the driver):
2. Initialize any other global driver variables and data structures.
Because a DriverEntry routine runs in the context of a system thread at IRQL PASSIVE_LEVEL, any memory allocated by ExAllocatePool and used exclusively during initialization can be obtained from the paged pool, as long as the driver does not control a device that has a system paging file. Such memory allocations must be freed by ExFreePool before DriverEntry returns control.
3. [Optional] Use ZwXxx and RtlXxx routines to read or set device-independent values in the registry.
4. Save the RegistryPath parameter entered in DriverEntry.
This parameter points to an enumerated Unicode string that specifies a path to the driver's registry key: \Registry\Machine\System\CurrentControlSet\Services\Drivername. The routine should save a copy of this string, not the pointer itself. The pointer is no longer valid after the DriverEntry routine returns control.
5. Return status.
If the DriverEntry routine returns something other than STATUS_SUCCESS, the driver does not need to retain the loaded state. However, before deinitializing and returning control, a DriverEntry routine must do the following:
n Release any system resources it set up.
n Log errors. See Error Logging and NTSTATUS Values in the Kernel-Mode Driver Design Guide for more information.
2.3 PnP and Power Management AddDevice Routines In a driver's AddDevice routine, the driver creates a device object as the target of its I/O device and attaches the device object to the device stack, which includes one device object for each associated device driver.
The PnP Manager calls a driver's AddDevice routine for each device controlled by the driver. AddDevice routines are called at system initialization, when devices are first enumerated. AddDevice routines are called any time a new device is enumerated while the system is running.
A driver's AddDevice routine should be named XxxAddDevice, where Xxx is a prefix that identifies the specific driver. During DriverEntry, a driver stores the address of its AddDevice routine in DriverObject_>DriverExtension->AddDevice:.
An AddDevice routine is called in the context of a system thread at IRQL PASSIVE_LEVEL.
The AddDevice routine is defined by the PnP Manager as follows:
NTSTATUS
(*PDRIVER_ADD_DEVICE) (
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
);
DriverObject points to the driver object that represents the driver, and PhysicalDeviceObject points to the PDO of the PnP device being added.
In a function or filter driver, an AddDevice routine should have the following steps:
1. Call IoCreateDevice to create a device object (an FDO) for the device being added.
Do not specify a device name for the FDO; naming an FDO bypasses the PnP Manager's security management. If a user-mode component requires a symbolic link to the device, register a device interface (see the next step). If a kernel-mode component requires an earlier device name, the driver must name the FDO, but naming is not recommended.
Include FILE_DEVICE_SECURE_OPEN in the device characteristics parameter; this characteristic instructs the I/O Manager to perform security checks to prevent all open requests to the device object, including relative opens and trailing filename opens.
2. [Optional] Create one or more symbolic links to the device.
Call IoRegisterDeviceInterface to register the device's capabilities and create a symbolic link through which applications or system components can open the device. When the driver handles the IRP_MN_STRAT_DEVICE request, the driver should activate the interface (see Section 2).
3. Store a pointer to the device's PDO in the device extension.
The PnP Manager provides a PDO pointer as the PhysicalDeviceObject parameter of AddDevice. The driver uses the PDO pointer to call routines such as IoGetDeviceProperty.
4. Define flags in the device extension to track certain PnP states of the device, such as paused, removed, and suddenly removed.
For example, define a flag to indicate that incoming IRPs should be held while the device is in a paused state. If the driver does not already have a mechanism for queuing IRPs, create a queue to hold IRPs. For more information, see Part 2.
Also allocate an IO_REMOVE_LOCK structure in the device extension and call IoInitializeRemoveLock to initialize the structure.
5. Set the DO_POWER_INRUSH or DO_POWER_PAGABLE flags for power management, if necessary. Pageable drivers must set the DO_POWER_PAGABLE flag. Device object flags are typically set by the bus driver when the device object creates the device PDO. However, higher-level drivers sometimes need to change the values of these flags in their AddDevice routines when they create PDOs. See Setting Device Object Flags in Power Management for details.
6. Create and/or initialize any other software resources that the driver uses to manage the device, such as events, spin locks, or other objects. (Hardware resources, such as I/O ports, are later configured in response to an IRP_MN_START_DEVICE request.)
Because an AddDevice routine runs in the context of a system thread at IRQL PASSIVE_LEVEL, any memory allocated by ExAllocatePool and used exclusively during initialization is obtained from paged pool as long as the driver does not control a device that reserves the system paging file. Such memory allocations must be freed by ExFreePoolAddDevice before returning control.
7. Attach the device object to the device stack (IoAttavhDeviceToDeviceStack).
Specify a pointer to the device's PDO in the TargetDevice parameter.
Stores the pointer returned by IoAttavhDeviceToDeviceStack. This pointer is a required parameter for IoCallDriver and PoCallDriver when passed down the device stack. This pointer points to the device object of the next lower supporting driver.
8. Clears the DO_DEVICE_INITIALIZING flag in the FDO or filter DO with a status like this: FunctionalDeviceObject->Flags &=~DO_DEVICE_INITIALIZING;
9. Prepares to handle PnP IRPs for the device (such as IRP_MN_QUERY_RESOURCE_REQUIREMENTS and IRP_MN_STRAT_DEVICE).
Until a driver receives an IRP_MN_STRAT_DEVICE, it keeps a list of the hardware resources assigned to the device by the PnP Manager and cannot start controlling the device.
A PnP bus driver has an AddDevice routine, but it is called only when the bus driver is acting as a function driver for its controllers and adapters. For example, the PnP Manager calls a USB hub bus driver's AddDevice routine to add the hub device; the hub driver's AddDevice routine is not called for a child hub (a device that is plugged into the hub).
2.3.1 Guidelines for Writing AddDevice Routines When writing an AddDevice routine, consider the following design guidelines:
n If a filter driver decides that its AddDevice routine is called for a device that it does not need to service, the filter driver must return STATUS_SUCCESS to allow the rest of the stack to be loaded for the device. The filter driver does not create a device object nor does it attach it to the device stack; the filter driver simply returns success and allows the rest of the drivers to be added to the stack.
n Typically in a device object's device extension, a driver must also provide storage for pointers to specific objects obtained from the I/O manager or other system components for any kernel-defined objects it uses and for executing program spin locks.
You might decide to allocate additional system-space memory to meet the needs of the driver, such as a long-term buffer or an auxiliary list. If so, an AddDevice routine can call the following routines:
n ExAllocatePool for paged or nonpaged system-space memory
n ExInitializePagedLooksideList or ExInitializeNPagedLooksideList to initialize a paged or nonpaged auxiliary list
n If the driver has a thread dedicated to servicing the device or waits on any kernel-defined scheduler object, its AddDevice routine must initialize the scheduler object. The scheduler object's thread or driver calls the appropriate KeInitializeXxx support routine, which has driver-supplied storage for event pointers, semaphores, mutexes, and/or timers.
Because it executes in the context of a system thread, an AddDevice routine itself can wait on a dispatcher object for a nonzero interval, as long as the dispatcher object has been initialized before the wait begins.
See Kernel Scheduler Objects in Chapter 3 of the Kernel-Mode Driver Design Guide for more information.
n If the driver uses any executive spin locks or provides storage for an interrupt spin lock, the AddDevice routine must call KeInitializeSpinLock with each such spin lock before passing it to any other support routines. See Spinlock Use in Chapter 16 of the Kernel-Mode Driver Design Guide for more information.
n Enforce file open security when calling IoCreateDevice.
Specify the FILE_DEVICE_SECURE_OPEN feature when calling IoCreateDevice. Windows 2000 and Windows NT 4.0 SP5 support this feature. It instructs the I/O Manager to perform security checks on the device object for all open requests. If the FILE_DEVICE_SECURE_OPEN attribute is not set in the device's class installer INF or in the device's INF, and drivers do not perform security checks on their own open requests, vendors should specify this flag when calling IoCreateDevice.
If a driver sets the FILE_DEVICE_SECURE_OPEN flag when calling IoCreateDevice, the I/O Manager applies the device object's security descriptor to any relative opens or trailing filename opens. For example, if FILE_DEVICE_SECURE_OPEN is set for \Device\foo, and if \Device\foo can only be opened by administrators, then \Device\foo\abc can also be opened by administrators. However, the I/O Manager prevents a normal user from opening \Device\foo and \Device\foo\abc.
If a device's driver sets FILE_DEVICE_SECURE_OPEN. The PnP Manager passes it to all device objects for the device.
2.4 DispatchPnP Routine The PnP Manager uses IRPs to instruct drivers to start, stop, and remove devices and to query drivers for devices. All PnP IRPs have the major function code IRP_MJ_PNP.
Each PnP driver is required to handle certain IRPs and can optionally handle other IRPs. See Volume 1 of the Windows 2000 Driver Development Reference for information about which IRPs are required and which IRPs are optional for each type of driver (function drivers, filter drivers, and bus drivers).
Drivers should handle PnP IRPs in an XxxDispatchPnp routine, where Xxx is a prefix used to identify the driver. During the driver's initialization of its DriverEntry routine, the driver sets the address of its DispatchPnp routine in DriverObject->MajorFunction[IRP_MJ_PNP]. Through the I/O Manager, the PnP Manager calls a driver's DispatchPnp routine.
All drivers supporting a device must have the opportunity to handle the device's PnP IRPs, except in rare circumstances. (That is, a function or filter driver allows the IRP to fail.) Read Section 2 for information about PnP IRPs, including when PnP IRPs are sent and the rules for their processing.
2.5 DispatchPower Routine The power manager uses IRPs to instruct drivers to change power states, to wait for and respond to system wake events, and to query drivers for devices. All power IRPs have the major function code IRP_MJ_POWER.
Drivers should handle power IRPs in an XxxDispatchPower routine, where Xxx is a prefix that identifies the driver. The DriverEntry routine sets the address of the driver's DispatchPower routine in DriverObject->MajorFunction[IRP_MJ_POWER]. When a power IRP is sent, the PnP manager calls the driver's DispatchPower routine.
The DispatchPower routine should handle IRPs with only the major function code IRP_MJ_POWER. The routine performs the following tasks:
n Processes the IRP, if possible
n Passes the IRP to the next lower driver in the device stack, using PoCallDriver
n If it is a bus driver, performs the power operation request on the device and fulfills the IRP
All drivers for a device must have a chance to handle the device's power IRPs, except in rare circumstances. (That is, a function or filter driver is allowed to fail the IRP.) Most function and filter drivers either perform some processing or set an IoCompletion routine for each power IRP, then pass the IRP down to the next lower driver without implementing it. Eventually the IRP reaches the bus driver, which physically changes the device's power state if necessary and completes the IRP.
After completing the IRP, the I/O Manager calls any IoCompletion routines set by the driver as the IRP passes down the device stack. Whether a driver needs to set a completion routine depends on the type of IRP and the individual driver
's requirements. A power IRP that powers up a device must first be handled by the lowest driver in the device stack (the base bus driver), then successively by each driver in the stack above. A power IRP that powers down a device must first be handled by the first driver at the top of the device stack, then successively by each driver in the stack below.
Special Handling of Removable Devices
In their DispatchPower routine, drivers for removable devices should check whether the device is still present. If the device has been removed, the driver should not pass the IRP down to the next lower driver. Instead, the driver should do the following:
n Call PoStartNextPowerIrp to begin processing the next power IRP
n Set Irp->IoStatus.Status to STATUS_DELETE_PENDING
n Call IoCompleteRequest, specifying IO_NO_INCREMENT, to complete the IRP
n Return STATUS_DELETE_PENDING
2.6 PnP and Power Management Unload Routines A PnP driver must have an Unload routine to delete any driver-specific resources, such as memory, threads, and events, that are generated by the DriverEntry routine. If there are no driver-specific resources to remove, the driver must still have an Unload routine, but it can simply return. A
driver's Unload routine can be called at any time after all devices have been removed. The PnP Manager calls a driver's Unload routine in the context of the system thread at IRQL PASSIVE_LEVEL.