Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Embedded Systems

Device Driver Monitoring


MAR92: DEVICE DRIVER MONITORING

This article contains the following executables: DRVMONIT.ARC

Rick is a software engineer specializing in systems programming and is the coauthor of Screen Machine, a screen design/prototyping/code-generation utility. He can be reached at P. 0. Box 1109, Half Moon Bay, CA 94019.


Many times when developing device drivers, I've needed a program for monitoring and logging requests made to a given device driver. Such a monitoring program would be helpful for tracking the sequence of commands which lead up to a system crash or other problem. It could also be used for inspecting various parameters and buffer contents passed to and from a device driver.

When investigating a problem, a program such as this could help eliminate the tedious task of setting a breakpoint at the driver interrupt routine, dumping the request header, inspecting the command code, and looking up the command code in a manual. It could also be useful in dumping other memory areas depending on the type of command (that is, dumping using a pointer to a packet or transfer area), breaking at the completion of the interrupt routine, inspecting data buffers, and checking the error code in the request header status field (possibly looking that up in the manual).

Clearly, this was a tool I needed. Consequently, I've developed the device driver monitoring software described in this article. Benefits of this tool are the ability to log driver requests and the subsequent I/O that is performed. Thus, an expected results file can be created, providing the means to compare the results of an existing driver with one that is currently under development. Once created, these expected results files can be quite useful in regression testing.

The Monitor

The complete device driver monitor program, DRVMONIT.SYS, is made up of several modules: the device driver initialization code, a dispatcher to the driver functions, the command processor routines, equates and structures, and data for the program. In all, DRVMONIT.SYS consists of nearly 3000 lines of code, more than can be presented in this article. However, it is all available electronically.

DRVMONIT.SYS is itself an MS-DOS device driver. It must be an entry in your CONFIG.SYS file located anywhere before the entry for the driver you wish to monitor. This allows DRVMONIT to be available to log the earliest requests (such as INIT) made to the device driver being monitored.

DRVMONIT provides a log of all driver requests showing the request header contents, I/O buffers, and actual textual descriptions of the commands and completion status.

Configuring Logging Options

DRVMONIT is highly configurable in terms of where, when, which, and how much data is logged. The available configuration options are shown in Figure 1.

Figure 1: List of configuration options available in the device driver monitor

  Log data to printer, screen, or memory

  Display read and/or write buffers (the
   maximum number of blocks to be
   displayed can be configured for each)

  Show request header upon entry to and/
  or exit from the driver interrupt routine

  Start/stop logging after a specified
   number of driver requests

  Log only certain commands

  Optionally stop and wait for a key when
   an error is reported (useful for breaking
   in with your debugger for inspecting
   intermittent problems)

To select various configuration options, change the values in the configuration data area of the DRVMONIT source code. Alter the config_dat structure members to reflect the desired logging options. To enable/disable the logging of individual commands, a log flag located in structures of command information, cmd_table (described under "Logging commands") must be altered. The ability to disable the logging of a command really becomes useful when monitoring a driver which is constantly issuing a certain command (for example, a console driver which is forever polling the keyboard). As an aside, it would be useful to add to DRVMONIT a configuration screen where these values could be changed interactively.

Notice that output can only be directed to the screen, printer, or memory. Performing I/O using DOS functions is not possible while DOS is processing requests to device drivers. Direct sector I/O via the BIOS is available, but managing all of that seemed ugly. The output to memory option can be used by external programs to write logged data to disk. Such programs can communicate with DRVMONIT via IOCTL Input and Output commands supported by the DRVMONIT device driver.

The IOCTL Output command provides DRVMONIT with a far pointer to the user data area where data may be logged. In response to the IOCTL Input command, DRVMONIT provides the caller with pointers to its configuration information. The external program can use the pointers to change configuration information at any time. In fact, via these pointers, the external program could provide that interactive configuration facility just described.

Taking Control

DRVMONIT utilizes user software interrupt 60h to get control of a given device driver. The driver to be monitored must have Int 60h as the first instruction in its strategy routine. If it is inconvenient for you to actually place this instruction in your source code, the Int 60h instruction (Ocd60h) can be patched into the first 2 bytes of the strategy routine of your device driver. You then indicate that you have done this by supplying the /P switch on the command line. Following the /P switch, specify the hexadecimal values of the 2 bytes of code that were originally at offset zero of your strategy routine (for example, /P2e89).

With this one hook into a given device driver, DRVMONIT gets initial control. Then, by patching the device driver's code and manipulating stack values, DRVMONIT also gets control upon entry into the driver's interrupt routine and, upon return to the caller, of the driver's interrupt routine.

Int 60h Processing

The processing of these three monitored areas (strategy, interrupt, and return from interrupt) is handled via a state machine. When an Int 60h occurs, the monitor_process routine calls an appropriate processing routine based on the area from which an interrupt is expected.

Logging Commands

Logging of individual commands is performed by the record_cmd routine. It is called from process_int and/or process_ret depending on whether DRVMONIT has been configured to log request-header contents on entry to the driver interrupt routine, exit from the driver interrupt routine, or both. Record_cmd calls find_func, which does a table lookup on the command code in the request header.

The tables provide key information about each command. In order to effectively log a command, DRVMONIT needs to know the textual description of the command, whether the command is an I/O command, whether the command supports multiple functions which have their own packet information (which needs to be logged), and whether the user wants to log this particular command. The data that provides this information is found in the cmd_table structure.

To enable/disable the logging of individual commands, change the structure member, ri_log_flag, to either TRUE or FALSE. To enable/disable individual functions within a command, change fd_log_flag in the cmd_f_detail structure.

If a command is an I/O command, an offset is provided in element ri_iotbl_ptr, which points to a table of I/O information. This data is located at io_ cmd_table and follows the format defined in the io_table structure. Using this information, DRVMONIT can find I/O data to be displayed.

If a command supports multiple functions, an offset is provided in element ri_func_ptr, which points to a table of function information. This data is located in the cmd_func_tbl structure. If find_func detects that this pointer is not NULL, the routine find_sub_func is called to retrieve the following: a description of the command function; an indication of whether the function codes are located in the main request block or are contained in a packet area to which a pointer has been provided; the length of the packet area; and an indication of whether the function performs I/O, in which case a pointer to the I/O table information is included.

This table of information is used to handle two types of commands which have multiple functions within them: the generic IOCTL variety; and the IOCTL input/output commands used with MSCDEX (the Microsoft MS-DOS CD-ROM extensions). Note that if you are monitoring a device driver to be used with MSCDEX, assemble DRVMONIT with msc_flag defined. This will cause CDLOGDAT.INC, the include file which contains these special tables, to be used.

In the case of the generic IOCTL, the category and function codes are included in the request header, and a pointer is provided to a packet area. In the MSCDEX driver IOCTL input/output commands, the function code is not included in the request header, but is the first byte of a control block area pointed to by the transfer address pointer. These differences are handled by the information in the structures.

Final Steps

When DRVMONIT receives control at the return from a driver's interrupt routine, it finishes its eavesdropping with the following steps: First, it must always check for the INIT or BUILD BPB commands. This allows it to determine and store the sector size being used -- a good thing to know when you're dumping I/O buffers.

The last task is to inspect the error code in the status field of the request header and print a description. (For example, if the error code is 2, print "Drive not ready.") Also, if DRVMONIT has been configured to wait for a key in the event of an error, print a message and wait for any key to be pressed.

Future Enhancements

Enhancements which could be made to DRVMONIT might include a timing function which would report how long the driver took to process certain commands. Additional logging output options could be added, such as directing the logged data to a COM port.

In the future, I may attempt to provide a DRVMONIT which sets up an 80386 V86 monitor. This would enable DRVMONIT to monitor and log the values input and output to I/O addresses (as specified in the Task State Segment I/O permission bit map). Thus, for example, you could inspect the particular commands generated to a controller as a result of your driver receiving a particular request.

As you use DRVMONIT, you'll discover other uses for it. It might, for example, be useful for analyzing performance issues. Or, you may simply enjoy watching the DRVMONIT output. It can sometimes be entertaining as well as practical.


Copyright © 1992, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.