Книга: Writing Windows WDM Device Drivers

Processor Model

Processor Model

Windows 98, NT, and Windows 2000 all primarily run in x86 systems. However, NT and W2000 can also run on Alpha processors. To handle any differences, WDM uses a model of a general processor and provides an abstract view of the resources available on the supported processors.

Always use kernel routines to access hardware. For some types of drivers, you do not need to talk to hardware directly. Instead, make the appropriate calls to the relevant bus driver to get it to perform the low-level I/O for you.

Processor Modes

The operating system requires that the processor support only two modes: a user mode for one or more applications to run in and a kernel mode for the bulk of the operating system. User mode programs are protected so that they cannot easily damage each other or the kernel. Conversely, the kernel can do anything it wants to and can access all memory.

Interrupts and exceptions are ways of stopping the processor from doing something and asking it to do something else. A hardware interrupt is an input signal to the processor from external hardware. Software interrupts are instructions that interrupt the processor to switch it to kernel mode. Exceptions are interrupts generated by the processor, usually when something goes wrong.

User programs make kernel function calls using software interrupts. In fact, a Win32 call initially goes to a user mode Win32 subsystem DLL. If appropriate, this then calls the main operating system in kernel mode.

The kernel uses a regular timer hardware interrupt to switch between the available user program threads of execution. This makes it appear that the threads are running simultaneously. On multiprocessor systems, the threads really can be running simultaneously. The kernel can also have its own threads running, which are switched in the same way as user threads.

The result is that drivers can be called in several ways. A user application can issue a Win32 device I/O request. Eventually, a driver is called to process this call. The driver might then start its hardware. If its hardware generates an interrupt, then the driver is called to process it (i.e., stop the interrupt), flag that it has happened, and, if necessary, start another operation. In both these cases, the driver does not necessarily operate in the context of the user application that called it.

Drivers can also be called in the context of a kernel thread. For example, the Plug and Play calls to a driver are usually called in the context of a system thread. As will be shown, this gives the driver more scope to do things. Finally drivers can set up their own kernel mode threads that can run as long as needed, getting their own share of the processor time.

Interrupt Levels

Hardware or software interrupts stop the processor from doing one task and force it to run some interrupt handling code. A processor prioritizes interrupts so that lower priority interrupts can themselves be interrupted by higher priority interrupts. This makes sure that very important tasks are not interrupted by jobs that can be done at a later stage.

Table 3.3 Abstract Processor Interrupt Levels

IRQL Description
No interrupts PASSIVE_LEVEL Normal thread execution
Software interrupts APC_LEVEL Asynchronous Procedure Call execution
DISPATCH_LEVEL Thread scheduling Deferred Procedure Call execution
Hardware interrupts DIRQLs Device Interrupt Request Level handler execution
PROFILE_LEVEL Profiling timer
CLOCK2_LEVEL Clock
SYNCH_LEVEL Synchronization level
IPI_LEVEL Interprocessor interrupt level
POWER_LEVEL Power failure level

Table 3.3 shows the interrupt levels that Windows uses to provide an abstract view of the actual processor interrupt levels. The lowest priority interrupt levels are at the top. Hardware-generated interrupts always take priority over software interrupts.

Drivers only use three of these interrupt levels. Somewhat confusingly, driver dispatch routines are called at PASSIVE_LEVEL[5] (i.e., with no interrupts). Many driver callbacks run at DISPATCH_LEVEL. Finally, driver hardware interrupt service routines operate at Device Interrupt Request Level (DIRQL).

The DIRQLs level in fact represents the many hardware interrupt levels that are available on the specific processor. A disk hardware interrupt level may well have higher priority than a parallel port hardware interrupt, so the disk may interrupt a parallel port interrupt. Usually a driver has just one DIRQL, though there is no reason why it cannot support more, if that is how its hardware works. The relevant driver interrupt level is referred to as its DIRQL.

The interrupt level at which a driver is operating is very important, as it determines the types of operation that can be undertaken. For example, driver hardware interrupt service routines cannot access memory that might be paged out to a swap file.

A driver has to be aware that it could be interrupted by a higher priority task at any stage. This means that its own interrupt service routine could run in the middle of its own dispatch routines. For this reason, if a normal driver routine is about to interact with its own hardware, it uses a kernel function to raise its interrupt level temporarily to its DIRQL. This stops its own interrupt handler from running at the same time. In addition, in a multiprocessor system, another driver routine might be attempting the same task on another processor. The KeSynchronizeExecution routine is used to run such critical sections in a multiprocessor-safe way.

Runtime Priorities

The Interrupt Level should not be confused with the scheduling priority. All threads normally run at the lowest interrupt level, PASSIVE_LEVEL. The scheduler uses the priority values to determine which thread to run next. Any other interrupt takes priority over a thread.

Drivers need to be aware of scheduling priorities. When it completes an IRP, it can give the calling thread a temporary priority boost so that, for example, programs that interact with the mouse can continue their run more quickly. This technique generally improves the perceived responsiveness of the system.

Deferred Procedure Calls

Any routine servicing a hardware interrupt stops normal program execution. For this reason, it is best to make an interrupt service routine as quickly as possible.

Any nonessential interrupt processing should be deferred until later. Windows lets driver writers use Deferred Procedure Call (DPC) routines, which are called at DISPATCH_LEVEL. The interrupt routine requests that the driver's DPC post-interrupt routine (DpcForIsr) is called when things have calmed down. A typical job in this routine is to indicate that the current I/O request is complete; the relevant kernel call can only be carried out at DISPATCH_LEVEL

When writing your driver, be careful to comment the interrupt level at which each routine can be called. Similarly, make only kernel calls that are appropriate for the current interrupt level.

Оглавление книги


Генерация: 0.593. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз