Device Driver Introduction and a Brief History of Windows Drivers

Lets start with the question What is a Driver ?

A computer consists of various devices that provide input and output (I/O) to and from the outside world. Typical devices are keyboards, mice, audio controllers, video controllers, disk drives, networking ports, and so on. A driver is the software connection that handles communication between applications and the attached device to the computer.

Now, the windows kernel does not interact with devices attached to it directly but depends on device drivers to detect attached devices, mediate communication between the device and the Windows kernel and expose device capabilities to the upper layer application. The Windows OS provides an abstract device support interface called driver model. The job of driver developer is to provide an implementation of that interface to support specific requirements of their device.

Figure 1 gives a simplified version of this Windows I/O model which gives a high level view of how communication takes place between application and Hardware. 


A processor in a computer running Windows has two different modes: user mode and kernel mode. The processor switches between the two modes depending on what type of code is running on the processor. The operating system kernel code runs in a kernel mode (privileged processor mode) with access to system data and to the hardware; application code runs in a user mode (non-privileged processor mode) with a limited set of interfaces available, limited access to system data, and no data access to hardware.
Windows is essentially a monolithic operating system where bulk of the operating system and device driver code shares the same kernel-mode protected memory space.
Application running in user mode passes I/O request to the appropriate kernel mode drivers via the I/O manager (which exists in kernel mode). The I/O manager is the part of Windows OS and manages communication between applications and the interfaces provided by device drivers.
Device diver are loadable kernel mode modules (typically ending with .sys) that interface between I/O manager and the relevant hardware. Because devices operate at speeds that may not match the operating system, the communication between the operating system and device drivers is primarily done through I/O request packets (IRPs). These packets are similar to network packets or Windows message packets. They are passed from operating system to specific drivers and from one driver to another.

To understand the current model of Windows Device Driver lets look at the the brief history of the windows device driver.
The excerpt mainly has been taken from the starting chapter of Programming the Microsoft Windows Driver Model by Walter Oney.

A Brief History of Device Drivers.
The earliest PCs ran on an Intel processor chip that provided addressability for 640 KB of “real” memory that the processor addressed directly by means of a 20-bit physical address. The processor offered just one mode of operation, called real mode, wherein the processor combined information from two 16-bit registers to form a 20-bit memory address for every instruction that referenced memory. MS-DOS incorporated a scheme based on the CONFIG.SYS file whereby the operating system could load real-mode device drivers for original equipment and for add-on cards. These drivers were executable files with a .DRV extension programmed primarily in assembly language and relied to a greater or lesser extent on the INT instruction to talk to the BIOS and to system services within MS-DOS itself.

In 1983, Microsoft announced the development of Windows, a graphical user interface (GUI) for its own operating system (MS-DOS) which had shipped for IBM PC and compatible computer since 1981.
Later on, IBM introduced the AT class of personal computers based on the Intel 80286 processor. The 286 processor added a protected mode of operation wherein programs could address up to 16 MB of main and extended memory using a 24-bit segment address (specified indirectly via a segment selector in a 16-bit segment register) and a 16-bit offset. MS-DOS itself remained a real-mode operating system, so several software vendors built DOS extender products to allow programmers to migrate their real-mode applications to protected mode and gain access to all the memory that was becoming available on the market.

Microsoft released Windows 3.0 in May, 1990 with Intel 386, whose “enhanced” mode of operation took full advantage of the virtual memory capabilities. The 386 allowed programs to access up to 4 GB of virtual memory addressed indirectly via page tables, and it allowed programs to easily use 32-bit quantities for arithmetic and addressing.
Windows 3.0 was basically a virtual machine which managed applications by creating and maintaining a variety of virtual machines, to support multitasking.  Each MS-DOS application ran in its own virtual machine, as did the Windows graphical environment. But all those MS-DOS applications were trying to talk directly to hardware by issuing IN and OUT instructions, reading and writing device memory, and handling interrupts from the hardware. To allow multiple applications to share physical hardware, Microsoft introduced the concept of a virtual device driver, whose broad purpose is to “ virtualize” a hardware device. The OS created the appearance of virtual machines outfitted with separate instances of many hardware devices. These Virtual Device Drivers, mitigate access between multiple programs, running more or less in parallel with each other. But the devices themselves continued, in most cases, to be driven by real-mode MS-DOS drivers. A virtual driver role was to mediate application access to hardware by first intercepting the application’s attempts to touch the hardware and briefly switching the processor to a sort of real mode called virtual 8086 mode to run the MS-DOS driver.
Another important thing introduced along the Windows 3.0 time frame was that Windows 3.0 formally divided the software world into user-mode and kernel-mode programs. (Explained above)

Windows 3.0 had many bugs whose root cause was the very feature of the architecture and the Microsoft’s answer to this problem was to be OS/2, which it was developing in harmony with IBM.
Microsoft’s version of OS/2 became Windows NT, whose first public release was in the early 1990s, shortly after Windows 3.1. Microsoft built Windows NT from the ground up with the intention of making it a durable and secure platform on which to run Windows. Drivers for Windows NT used a brand-new kernel-mode technology that shared practically nothing with the other two driver technologies then in vogue. Windows NT drivers used the C programming language almost exclusively so that they could be recompiled for new CPU architectures without requiring any source changes.
Computing power didn’t really advance to the point where an average PC could run Windows NT well until quite recently. Microsoft therefore had to keep the Windows product line alive. Windows 3.0 grew into 3.1, 3.11, and 95. Starting with Windows 95, if you wanted to write a device driver, you would write something called a VxD that was really just a 32-bit protected-mode driver. Also starting with Windows 95, end users could throw away their I/O maps because the new Plug and Play feature of the operating system identified and configured hardware somewhat automatically. As a hardware maker, though, you might have had to write a real-mode driver to keep happy those of your customers who weren’t upgrading from Windows 3.1.

Thus, the product line has changed from GUI product to a modern operating system over two families of design with its own codebase and default file system.
- The 3.x and 4.x family includes Windows 3.11, Windows 95, Windows 98 and Windows ME -> The MS-DOS-Based Windows.
- Windows NT Family started with NT 3.1 in 1993 -> Modern Windows operating system versions are based on the newer version of Windows NT Kernel that was originally intended for OS/2.

Realizing that the market was split between Windows and Windows NT, Microsoft saw a need to introduce a single driver model, so that device drivers could be portable between Windows and Windows NT. In addition, Microsoft knew that drivers had to be writable in a higher-level language, like C, in order to be code-compatible for different hardware systems. To meet these needs, Microsoft created the Windows Driver Model(WDM). WDM drivers are compiled using the DDK, they are written in C, and they follow exacting specifications that ensure they can be executed on any windows system.
WDM model was more closely tied to the operating system. Drivers interact directly with the operating system by calling system service routines and manipulating operating system structures. Later, the WDM was further improved with a new Device Model introduced called Windows Driver Foundation (WDF).
Although WDF represents an entirely new driver model, it is not distinct from WDM. WDF functions as an abstraction layer between WDM and simplifies the task of implementing robust, secure and efficient drivers. It is a set of Microsoft tools that aid in the creation of device drivers for Windows 2000 and later versions. Windows Foundation was introduced with Windows Vista and available downlevel for Windows 2000 and Windows XP. WDF largely supersedes WDM and is designed to enable developers to focus on the requirements on their hardware and provides the framework library handles the majority of the interactions with the system.

Figure 2 illustrates the evolution of the Windows family of operating system, with their approximate dates relative to each other. It could not have been better illustrated than this image taken from the book Inside Windows Debugging: A Practical Guide to Debugging and Tracing Strategies in Windows, by Tarik Soulami. 


Figure 2 - Timeline of major client and server releases of the Windows operating systems since the early 90's. 




2 comments:

  1. This is good stuff. I am new to drivers and your blog really helped me understand the basics. Please keep updating so that I can follow. !!

    ReplyDelete