The Role of a Filter Driver
A filter driver that s above the function driver is called an upper filter driver; a filter driver that s below the function driver (but still above the bus driver) is called a lower filter driver. Please refer to Figure 2-2 for an illustration of this layering. The mechanics of building either type of filter are exactly the same, even though the drivers themselves serve different purposes. In fact, you build a filter driver just as you build any other WDM driver with a DriverEntry routine, an AddDevice routine, a bunch of dispatch functions, and so on.
Upper Filter Drivers
Recall that the I/O Manager sends IRPs for a device to the topmost filter device object (FiDO) in that device s PnP stack. Upper filter drivers therefore see all requests before the function driver does and can edit the stream of requests in any desired way. Among the things you can accomplish with an upper filter are these:
Implement some consistent upper-edge interface for wildly different underlying hardware. I ll say more about this concept in the following paragraphs.
Gather and report metering information, say, in response to Windows Management Instrumentation (WMI) requests.
Work around a bug in a function driver.
Examples of upper filter drivers abound in Windows XP. I ll describe a few of them. I suggest you use the DevView utility mentioned in Chapter 2 in the companion content to examine some of the device stacks to better visualize the examples.
Disk and Tape Storage Driver Stacks
Several completely different technologies are in common use for disk and tape devices, including SCSI, IDE, USB, and 1394. Function drivers for these devices are therefore going to be very different at their lower edge, where they talk to their hardware. To simplify the overall system architecture, each disk or tape function driver exports a SCSI upper edge. That is, drivers higher in the stack send SCSI Request Blocks (SRBs) to the function driver. The driver for an actual SCSI device simply extracts standardized Command Description Blocks (CDBs) from the SRBs and sends them to the hardware more or less directly. Drivers for other types of device translate the CDBs into their own hardware protocol.
NOTE
Strictly speaking, there is no function driver in a storage stack because none of the drivers in the stack is so designated in the registry. The bus driver at the bottom of the stack acts as a function driver. All the other drivers in the stack are technically upper filter drivers.
Microsoft has implemented three upper filter drivers DISK.SYS, CDROM.SYS, and TAPE.SYS that implement the diskness or tapeness of hardware. Microsoft refers to these as class drivers, but here the word class is used differently than we ve been considering in this book. Elsewhere, we ve talked about class/minidriver pairs that add up to a function driver. Here the word just refers to a filter driver that implements an upper-edge interface appropriate to a class of devices.
The upper edge of the storage class drivers presents a unified disk, CD-ROM, or tape interface consisting of certain I/O control (IOCTL) requests and a defined behavior for read and write requests. At their lower edge, these drivers talk SCSI to whoever is underneath them in the stack.
Figure 16-1 shows the driver stack for a SCSI hard disk on one of my systems. At the bottom of the stack is AIC78U2.SYS, a SCSI miniport driver that works with a class driver named SCSIPORT.SYS to manage the particular SCSI adapter that came with my computer. DISK.SYS makes the hard disk look like a disk to everyone above. PARTMGR.SYS manages the two partitions that the manufacturer created on the disk.
Figure 16-1. Driver stack for a hard drive.
Figure 16-2 shows the driver stack for an IDE-based DVD-ROM drive on a different computer. Here ATAPI.SYS is at the bottom of the stack. At its upper edge, it looks like a SCSI port driver. At its lower edge, it acts like an IDE controller. Layered on top of ATAPI.SYS are IMAPI.SYS, CDROM.SYS (presents an ISO-standard CD-ROM image at its upper edge), and REDBOOK.SYS (implements the Redbook audio standard).
Figure 16-2. Driver stack for a DVD-ROM drive.
The PnP Manager constructs these driver stacks based on the type of device reported by the bus driver. In the hard-disk example (Figure 16-1), the device is class Disk. DISK.SYS and PARTMGR.SYS are listed as upper filters in the Disk class key. In the DVD-ROM example (Figure 16-2), the device is class Cdrom. REDBOOK.SYS and IMAPI.SYS are listed as upper and lower filters, respectively, in the hardware key; CDROM.SYS is listed as an upper filter in the Cdrom class key.
Mouse and Keyboard Drivers
Two connection technologies universal serial bus (USB) and 8042 are commonly used nowadays for keyboards and mice in Windows systems. Figure 16-3 illustrates the driver stack for a USB mouse. HIDUSB.SYS (a HIDCLASS mini driver) plays the role of a bus driver, while MOUHID.SYS acts as the function driver. MOUCLASS.SYS is a class upper filter for the Mouse class.
Figure 16-3. Driver stack for a USB mouse.
Figure 16-4 is a parallel diagram for a PS/2 mouse on a different system. I8042.SYS is the function driver for the PS/2 mouse port. On this particular system, ACPI.SYS (the driver with overall responsibility for power management) acts as the bus driver.
Figure 16-4. Driver stack for a PS/2 mouse.
Evidently, both driver stacks have MOUCLASS.SYS in common. MOUCLASS presents a consistent mouse interface to the rest of the system, which is how it comes to pass that you can use either type of mouse (or both at the same time) on a Windows computer.
For a keyboard, the only important difference in the driver stacks would be that KBDCLASS is at the top.
Serial Enumerator
You often plug other things in to a serial port. The most common things, of course, are modems and mice. Until the advent of USB, the serial port was also a popular place to attach a variety of other peripherals. Microsoft long ago defined a protocol whereby serial-attached devices can provide a Plug and Play identifier. The document Plug and Play External COM Device Specification describes the protocol but (because of indexing difficulties posed by the fact that the word serial doesn t appear in the title) is nearly impossible to find. I found a copy at http://www.microsoft.com/hwdev/resources/specs/pnpcom.asp, but it will probably have moved by the time you go looking for it.
Microsoft implements the serial PnP protocol in a device upper filter named SERENUM.SYS. SERENUM uses the standard serial port interface to talk downward to a serial port driver. If it detects a PnP identifier string, it acts as a bus driver by creating a physical device object (PDO). Thereafter, the PnP Manager loads function and filter drivers in the ordinary way.
Figure 16-5 shows the driver stack for a serial mouse. SERENUM.SYS is in the figure twice, once as a device upper filter for the serial port (whose function driver is SERIAL.SYS) and once as the bus driver at the bottom of the SERMOUSE stack. Note once again that MOUCLASS.SYS gets into the act to present that consistent mouse interface to the rest of the system.
Figure 16-5. Driver stack for a serial mouse.
The DISKPERF Driver
The DISKPERF driver in the DDK illustrates another use for an upper filter. DISK PERF is an optional driver that collects statistics about the disk I/O requests that pass through it. DISKPERF reports these statistics by means of WMI requests that any WMI-based performance monitor can use.
Lower Filter Drivers
Lower filter drivers are much less common than upper filters. Since (by definition) a lower filter driver is below the function driver in the PnP stack, it receives only those IRPs that the function driver chooses to send down. For a device attached to a traditional bus such as Peripheral Component Interconnect (PCI), the function driver will consume all the interesting IRPs by making hardware abstraction layer (HAL) calls to do actual I/O. The only IRPs that are likely to flow down from the function driver are power and PnP. Generally speaking, there s not much a filter driver can or should do about those.
You might design a system of drivers as shown in Figure 16-6. The idea is to create a single function driver that uses lower filter drivers to communicate to hardware on various bus architectures. The drivers for the built-in modem on one of my notebook computers use this idea. The function driver for the modem is the Microsoft-supplied MODEM.SYS. The modem vendor supplies a lower filter driver that supports the standard serial port interface and two additional lower filters for reasons that don t immediately meet the eye. This idea is really the same as the concept underlying DISK.SYS and MOUCLASS.SYS only the technical names assigned to the drivers are different. The really important thing is the way the drivers are layered, of course, and not their names.
I sometimes use a lower filter driver to snoop on the USB traffic generated by a function driver. Later in this chapter, I ll describe a lower filter I built to help me debug power-management problems in my own drivers; its job in life is to print debugging messages about all the IRP_MJ_POWER requests that the function driver generates or passes down.
Appendix A describes a lower filter driver named WDMSTUB.SYS. WDMSTUB defines a bunch of kernel functions that Windows 98 and Windows Me don t export. Making it a lower filter means that those functions get defined before the system tries to load a function driver that calls those functions. This fact in turn makes it possible to have true binary portability between Windows 2000, Windows XP, and Windows 98/Me.
Figure 16-6. Using lower filter drivers to achieve bus independence.