Using Filter Device Drivers

There are a number of scenarios in which it is useful to insert one or more filtering algorithms between a device manager and the adapter device driver that is driving the device interface. This is accomplished under the adapter device driver model by installing one or more filter device drivers into the call-down path between the DM and the device-interfacing adapter device driver. Filter device drivers are also referred to as filter adapter device drivers, filter drivers, or simply filters.

A sample scenario that utilizes a filter device driver to encrypt the data maintained on a DASD unit is depicted in the following figure: Without Filter                  With Filter

/\       /-\ |     System DASD DM     |        |   System DASD DM        | |     (OS2DASD.DM)      |        |    (OS2DASD.DM)         | \/       \-/            ^                                  ^            |                                  |            |                                  v            |                      /-\ |                     | Encryption Algorithm    | |                     |  (A Filter Driver)      | |                     \-/            |                                  ^            |                                  |            v                                  v /\        /-\ |ST-506 Interface Driver |       | ST-506 Interface Driver | |   (IBM1S506.ADD)      |        |     (IBM1S506.ADD)      | \/       \-/ Filter algorithms are packaged as filter device driver drivers and, in general, they provide the same set of services as any other adapter device driver. Once initialized, filter device drivers receive IORBs from upstream drivers (for example, device managers), perform the filtering function on the data in the IORB, then pass the IORB to call down to the adapter device drivers that the filter device driver is controlling.

One or more filter device drivers can be inserted into the call-down path for a selected device.

One or more call-down paths can share the same filter device driver. For example, multiple call-down paths can share a filter device driver that is providing an encryption function.

The remainder of this chapter contains detailed information on how filter device drivers can be constructed and, subsequently, inserted into the device support for a given I/O system.

Strategies for Providing Filter Functions
There are two strategies for inserting a filter device driver into the call-down path for a given unit's device support: In most cases, the first strategy, in which the caller does not permanently allocate the unit, is simpler than the second. The filter device driver simply daisy-chains a filter indicator into the UNITINFO structure of the target unit; then, I/O that otherwise would go directly to the target unit's adapter device driver is redirected through the filter device driver.
 * 1) Edit the target unit's UNITINFO table, but do not allocate permanent ownership of the unit.
 * 2) Allocate the target unit, and present a new UNITINFO table to any upstream driver that might issue I/O requests.

The second strategy is required when the filter device driver needs to hide units. For example, a data-stripping feature can be implemented using a filter device driver as follows. The data-stripping filter device driver must allocate all target units to hide them from upstream device managers. Then the data-stripping filter device driver constructs a new UNITINFO table to contain the appropriate information for presenting a logical view of a single, logical (stripped) drive.

Installation and Initialization
Filter device drivers are installed the same as adapter device drivers, using BASEDEV= statements in the CONFIG.SYS file of the workstation. In CONFIG.SYS, the filter device driver is loaded after any adapter device drivers it will control but before any device managers that the filter device driver will serve; this is ensured by use of the FLT file-name extension.

When the filter device driver receives its initialization packet from the kernel, it must scan the workstation's configuration to determine which units it wants to control, just as a device manager must when it initializes. A filter device driver uses the DevHlp_GetDOSVar to obtain a list of the entry points for all installed adapter device drivers, then it calls each ADD to obtain their device tables. The filter device driver must provide storage for these device tables.

Once the device tables are obtained, each is scanned by the filter device driver for units of interest. Having located the units of interest, the filter device driver must take one of the two actions previously listed, depending on whether the filter driver is using the permanent allocation method.

Editing an Adapter Device Driver Device Table
If the filter device driver does not need to hide the downstream units, it can initiate filtering operations by the following steps. When no filter device drivers are installed, the FilterADDHandle value will be 0. So, when a device manager (or other upstream adapter device driver) finds a 0 value in this field, the referenced adapter device driver is directly managing the device interface. Notice that the filter device driver is daisy-chaining itself into the call-down path for a given unit. As a result, the filter device driver must save the existing values in FilterADDHandle (if nonzero) and UnitHandle for the downstream driver. After the filter device driver processes a service request, it must pass the request to the downstream filter device driver or device-interface adapter driver.
 * 1) Change the value of the FilterADDHandle field in the target unit's UNITINFO structure so that the field selects the filter device driver.
 * 1) Change the UnitHandle field of the target unit's UNITINFO structure to a value assigned by the filter device driver.

The following protocol must be adhered to when editing a UNITINFO structure of another adapter device driver.

The filter device driver alters the information provided in the target UNITINFO structure by using the (IOCC_UNIT_CONTROL) IOCM_CHANGE_UNITINFO command. To issue IOCM_CHANGE_UNITINFO, the filter device driver first must allocate the unit, change the UNITINFO information, and then deallocate the unit.

Changing the UNITINFO information does not affect the operation of the downstream adapter device driver. For example, if a filter device driver changes the UF_HW_SCATGAT bit, the downstream device driver's treatment of the unit is not affected. However, the downstream adapter device driver must present the changed UNITINFO structure when its DEVICETABLE is requested. It is the responsibility of the filter device driver to convert the changed unit definition it sets to the actual unit definition of the adapter device driver owning the unit. A filter device driver can modify a unit's flags without actually hooking the unit. For example a filter device driver could UF_set the A_DRIVE flag without actually receiving requests by leaving the original UnitHandle and FilterADDHandle fields intact.

Allocating Permanent Ownership of a Unit
Alternatively, a filter device driver can allocate permanent ownership of the target unit from the downstream driver and present a device table containing the new representation of the unit to any upstream drivers. Since the filter device driver retains ownership of the downstream resource, it is not necessary to edit to the downstream driver's UNITINFO structures.

IORBs and Filtering
Once installed, a filter device driver can apply the following to the IORBs it is filtering: The filter device driver must not assume that the contents of the pIORB->ADDWorkSpace field will be preserved by a downstream driver.
 * Generally, the filter device driver will retain the original IORB and create new IORBs to pass on to the downstream drivers.
 * However, a filter device driver can modify an IORB it receives and pass on the same copy of the IORB data structure (as opposed to passing on a local copy of the IORB). If the adapter device driver does this, it must alter the notification address and restore any input fields it had modified prior to doing notification callouts back to the upstream driver.