5. microsoft w indows 2000 treiber „processing irps in ... filesystemprogrammierung ii, winter...

50
Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 126 5. Microsoft Windows 2000 Treiber „Processing IRPs in Layered Drivers“ (aus Windows 2000 DDK)

Upload: nguyennhi

Post on 30-Mar-2019

215 views

Category:

Documents


0 download

TRANSCRIPT

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 126

5. Microsoft Windows 2000 Treiber

„Processing IRPs in Layered Drivers“

(aus Windows 2000 DDK)

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 127

5.1. L iteratur

• Microsoft Developer Network (MSDN): www.msdn.microsoft.com

• Device Driver Kits (DDKs): www.microsoft.com/ddk

• Hardware Entwicklung: www.microsoft.com/hwdev

• Hardware Newsletter: www.hwdev.org/whn.htm

• System-Internals: www.sysinternals.com

• NT-Insider: www.osr.com

• SoftICE: www.numega.com

• Bücher: − W. Oney, „ Programming the Windows Driver Model“ , Microsoft-Press, 2000. − A. Baker & J. Lozano, „ Windows 2000 Device Driver Book“ , Prentice-Hall, 2001. − D. Solomon und M. Russinovich, „ Inside Windows 2000“ , 3. Aufl., Microsoft-

Press, 2000.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 128

5.2. Einführung

5.2.1 Windows 2000 Architektur

• Viele Prozesse mit jeweils mindestens 1 Thread.

• Virtuelle Speicherverwaltung (32-Bit).

• Preemptives Multitasking & SMP.

• Kernel-Mode: − ein Prozeß und viele Systemthreads, − kein Zugriff auf User-Mode Adr., − keine Gleitkommaoperationen, − separater Stack (~ 8192 byte), − gemeinsamer Speicher.

• User-Mode: − viele Prozesse mit mind. einem Thread, − kein Zugriff auf Kernel-Mode Adr., − getrennter Adreßräume.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 129

• Kern: − Erweiterter NT 4.0 Kern, − objekt-orientiert, aber in „ C“ , − großes API (>1200 Fkt.) in ntoskrnl.exe (~1,6 MB)

• Registry: Datenbank für Konfiguration

• native API (NTDLL.DLL) angebunden über Software-Interrupt

Hardware Platform

Hardware Abstraction Layer (HAL)

NT Executive

user - mode

kernel - mode

system service

( software interrupt )

I /O- Mgr . PnP-Mgr. Power- Mgr .

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 130

5.2.2 Treiberar ten

• Kernel-Mode Treiber: − für logische, virtuelle und physikalische Geräte, − Windows 2000 Treiber (kein WDM, aber Pnp), − WDM-Treiber (Pnp & Powermanagement), − Legacy-Treiber (kein Pnp).

• User-Mode Treiber (VDDs).

• geschichtetes Treibermodel: − Highest Level Drivers (z.B. FAT), − Intermediate Drivers (z.B. virtuelle Disk), − Lowest Level Drivers (z.B. Bustreiber).

5.2.3 Neuerungen gegenüber NT 4.0

• zusätzlich Windows Driver Model (WDM), auch in Win 98/Me.

• WDM-Quelltexte austauschbar, aber nicht unbedingt die Binärdateien!

• Erweiterte Grafiktreiberschnittstelle (inkl. Gleitkommaunterstützung).

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 131

• Plug and Play (seit Windows 95),

• Powermanagement,

• Kernel Streaming & ATM Dienste

5.2.4 Relevante Kernschnittstellen

• Objekt-Manager "Ob": − nur wenige Funktionen, − Objektreferenzierung.

• I/O-Manager "Io": − Interrupt- und DMA-Funktionen, − Registry-Zugriff, − IRP-Funktionen, − Geräteobjekte.

• Executive "Ex": Speicherallokation und Synchronisierung.

• Memory-Manager "Mm": Adreßübersetzung und I/O-Adreßraum.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 132

• Process-Service "Ps": nur Erzeugung von System-Threads.

• Runtime Library "Rtl": String-Fkt., Gleitkomma-Emulation, ...

• Power-Manager "Po": − Power State Change Support, − Power-IRP Handling.

• Plug-and-Play "PnP": − kein extra Namenspräfix, − in den I/O-Manager integriert.

• Hardware Abstraction Layer "Hal": − Memory-Mapped Zugriff, − Interrupt-Dispatcher, − I/O-Portzugriff.

• Generell: − Asynchrone I/Os & Threads im Treiber. − Multiprozessorsynchronisierung. − Keine Standard-C Funktionen! − Nur Unicode-Strings im Kern.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 133

5.3. I /O Verarbeitung

• Ausführungsmodi von Kernel-Mode Code: − System-Thread, − Exception, − Interrupt.

• Plattformunabhängige CPU Prioritäten definiert als Interrupt Request Level (IRQL):

• IRQL definiert eine Interrupt-Priorität, keine Scheduling-Priorität für einen Thread.

Aus l öser I RQL Ur sacheHar dwar e HI GHEST_LEVEL Busf ehl er

POWER_LEVEL Power - f ai l ur e. . . . . .DI RQLs Ger ät e- I / O

Sof t war e DI SPATCH_LEVEL DPC. . .PASSI VE_LEVEL nor mal t hr eads

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 134

• Kernel-Mode Threads können ihren IRQL-Level verändern, um Interrupts zu maskieren.

• Software-Interrupts werden vom BS verwendet (z.B. Thread-Scheduling).

• Deferred Procedure Call: − Ziel: Verbesserung der Systemreaktion, indem möglichst wenig Code mit hoher

Priorität ausgeführt wird. − gewisse Teile einer Interrupt Service Routine (ISR) in eine DPC Routine verlagern

(z.B. Aufräumen nach einem I/O).

ISR (hohe Priorität)

DPC

Dispatcher

DPC-Interrupt System

DPC

Queue

DPC

Objekt

DPC

Routine

DPC

Objekt

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 135

Pufferzugr iff

• Problem: Treiber darf nicht auf virtuellen User-Mode Speicher zugreifen: − Getrennte Prozeßadreßräume → u. U. ist während der Abarbeitung des I/Os ein

anderer Prozeß aktiv. − (Bei hohen Prioritäten dürfen keine Page-Faults auftreten).

• Zugriffsmethode wird bei Initialisierung festgelegt: − gepuffer ter I /O: I/O-Manager

alloziert Puffer für jede I/O Operation und kopiert die Daten um.

− direct I /O: I/O-Manager erzeugt eine Memory Description List (MDL) die eine Beschreibung der physikalischen Kacheln enthält → kein Umkopieren

kernel - mode Speicher Physikalischer

Speicher

A

B

C

Daten

Seite A

Seite B

Seite C

MDL

A

B Daten

C

Daten Daten

Daten

Daten

Kopie

user-mode Speicher

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 136

5.4. I /O Request Packets

• BS kommuniziert mit Treibern ausschließlich asynchron über sogenannte I /O Request Packets (IRPs).

• IRP ist variable große Datenstruktur (ähnlich Stack) für die Unterstützung eines Treiber-Schichtenmodells

• Vordefinierte Funktionscodes: Create, Close, Read, Write, ...

IRP

Header

Stack

IRP_MJ_WRITE

Length

ByteOffset

Stackeintrag

IoStatus

* SysBuffer

* Mdl * UserBuffer

Cancel

Header

. . .

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 137

• Treiber kommunizieren untereinander ebenfalls asynchron:

• Aber auch direkte Aufrufe zwischen Treibern möglich: − Nicht empfohlen. − Funktionen exportieren (wie bei DLLs). − Importieren eines anderen Treibers bedeutet, daß dieser auto. mitgeladen wird.

I /O-Manager

Dr iver -2

Dr iver -1

Dr iver -0

Gerät

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 138

5.4.1 Das Schichtenmodell & IRPs

• Beispiel: synchrone Architektur

Driver A Driver A

Driver B Driver B

Driver C Driver C

App App

Param for A

Param for A

Return addr . to App

Param for B

Param for B

Return addr. to A

Param for C

Param for C

Return addr . to B

Param for A

Param for A

Return addr. to App

Param for B

Param for B

Return addr. to A

Param for C

Param for C

Return addr. to B

Thread Stack

Stack Pointer

Instruction

Pointer

User-Mode

Kernel -Mode

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 139

• IRPs: asynchroner Ablauf

• Vergleich:

IO_STACK_LOCATION

IoGetCurrentIrpStackLocation (and IoGetNextIrpStackLocation)

IoCallDriver

IoCompleteRequest

Completion routine (IoSetCompletionRoutine)

Irp-> IoStatus.Status/Information

Stack Frame

Stack Pointer

Subroutine call

Return from subroutine

Return Address

Return Value

Thread Stack Concept IRP Stack Concept

Callback for A Param B Param B

Callback for B Param C Param C

Callback for Initator Param A Param A

IRP Header

(Contains Status and Stack Pointer)

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 140

5.4.2 Treiber-Objekt

• DriverEntry ist die einzige mit Namen exportierte Funktion eines Treibers.

• Sonstige Funktionen sind im Treiber-Objekt vermerkt.

• Genau ein Treiber-Objekt pro geladenem Treiber.

Device-Object

DriverInit

DriverStartIo

Dr iver -Object

DriverUnload

DispatchRoutine0

...

DispatchRoutineN

StartIo

Unload

Disp-0

Disp-N

DriverInitDeviceObject

DeviceObject

Dr iver -Extension

AddDeviceDr iver -Ext.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 141

5.4.3 Geräte-Objekt

• Für jedes physikalische und virtuelle Gerät erzeugt der Treiber jeweils ein Geräte-Objekt:

− Enthält den aktuellen Status des Geräts. − Der I/O-Manager findet den Treiber über das Geräte-Objekt.

• Der Treiber muß reentrant sein →→→→ keine globale Variablen verwenden, sondern Device-Extension nutzen.

• Treiber löscht Geräte-Objekt(e), wenn er aus dem Speicher entfernt wird.

Device Queue Object

Flags

Driver - Object

Device - Object

Aktueller IRP

DeviceExtension

Driver

Object

Pending

IRP

NextDevice

Pending

IRP

Current IRP

Device -Extension

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 142

5.4.4 Inter rupt Objekt

• Für jeden Interrupt eines Gerätes wird ein Inter rupt-Objekt angelegt.

• Der Kernel Interrupt Dispatcher verwendet Interrupt-Objekte um die Inter rupt Service Routinen zu finden.

Interrupt- Object Interrupt

Service

Routine

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 143

5.4.5 WDM-Treiberstapel

• FDO behandelt typischerweise I/O IRPs.

• PnP & Power-IRPs traversieren den gesamten Stack.

• PDO wird durch den Bus-Treiber erzeugt.

• FDO's und Filter werden in "AddDevice" erzeugt (Parameter ist PDO).

PDOPhysical Device Object

PDOPhysical Device Object

DevNode

FDOFunctional Device Object

FDOFunctional Device Object

Upper Device Fi ltersUpper Device Fi lters

Lower Device Fi ltersLower Device Fi lters

Lower Class FiltersLower Class Filters

Upper Class FiltersUpper Class Filters

IRP

IRP

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 144

5.4.6 I /O-Anfrage durch eine Anwendung 1) I/O-Anfrage (z.B. „ReadFile“).

2) I/O-Manager erzeugt Interrupt Request Packet (IRP).

3) Zuständige Routine des Treibers wird gerufen.

4) Treiber teilt I/O-Mgr. mit, daß Geräte-I/O nötig ist.

5) I/O-Manager ruft „StartIO“ des Treibers.

6) Treiber kehrt zurück u. wartet auf Interrupt. Nach Abarbeiten des Interrupts wird ein DPC Objekt erzeugt.

7) Nach Abarbeiten der DPC Routine teilt der Treiber dem I/O-Manager den Abschluß mit.

8) Der I/O-Manager liefert die Daten der Anwendung

* ) Treiber-Objekt suchen und Zugriffsrechte überprüfen

Gerät

I /O-Manager

user - mode

kernel - mode

I/O Anfrage ( system service )

Objekt-Manager

Sicherheits -

Manager IRP

Treiber

1

*

2

3

4

5

6 7

8

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 145

5.5. Struktur eines Legacy-Treibers

• Initialisierung und Shutdown Routinen: − „ DriverEntry“ : Einstiegspunkt beim Laden. − „ Unload“ : Treiber wird aus Speicher entfernt.

• I/O System Funktionen: − „ Open“ , „ Close“ , "Write", "Read", ... − evt. Dispatcher.

• Routinen für die Datenübertragung: − Start I/O: Beginn einer Geräteoperation. − ISR: Kernel Interrupt Dispatcher ruft diese Routine, wenn das Gerät einen Interrupt

auslöst. − Eine oder mehrere DPC Routinen (z.B. Aufräumen nach Interrupts).

• NT-Treiber erweitert um "AddDevice"-Fkt.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 146

5.5.1 Treiber Initialisierung

• DriverEntry wird beim Laden des Treibers vom I/O-Manager gerufen.

• Aufgaben: − Zunächst Hardware suchen und Ressourcen allozieren. − Funktionen im Treiber-Objekt eintragen. − Geräte-Objekt erzeugen und Device-Extension initialisieren. − Evt. Gerät mit einem Interrupt Objekt verknüpfen & DPC-Obj. anlegen. − Gerät im Win32-Subsystem sichtbar machen.

\

Device DosDevices

Xx0 Xx1

Symbolischer L ink

Namensräume

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 147

5.5.2 Beispiel: „ Dr iverEntry“

NTSTATUS DriverEntry(PDRIVER_OBJECT DrvObj, PUNICODE_STRING RegistryPath) { NTSTATUS status; status = GetHardwareInfo(RegistryPath,&Cfg); // Hardware suchen

status = ReportHardwareUsage(DrvObj,Cfg); // Hardware Ressourcen belegen

// export driver entry points DrvObj->DriverStartIo = MyStartIo; DrvObj->DriverUnload = MyDriverUnload; DrvObj->MajorFunction[IRP_MJ_CREATE] = MyOpen; DrvObj->MajorFunction[IRP_MJ_CLOSE] = MyClose; DrvObj->MajorFunction[IRP_MJ_WRITE] = MyWrite;

DrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatch; DrvObj->DriverExtension->AddDevice = MyAddDevice;

status = MyCreateDevice(DrvObj,Cfg); // Geräte-Obj. erzeugen

ReleaseHardwareInfo(Cfg); // Freigabe von unbenötigten Strukturen

return status; }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 148

5.5.3 Beispiel: „ CreateDevice“

NTSTATUS MyCreateDev(IN PDRIVER_OBJECT pDrvObj) { MY_DEV_EXT pDevExt; UNICODE_STRING ntName, w32Name;

PDEVICE_OBJECT pDevObj;

RtlInitUnicodeString(&ntName, NT_NAME); // create NT name IoCreateDevice(pDrvObj, sizeof(MY_DEV_EXT), // create device object &ntName, FILE_DEVICE_NULL, 0, FALSE, &pDevObj);

pDevObj->Flags |= DO_BUFFERED_IO; // Pufferzugriff

// allocate device extension pDevExt = pDevObj->DeviceExtension; RtlZeroMemory(pDevExt, sizeof(MY_DEV_EXT));

RtlInitUnicodeString(&w32Name, DOS_NAME); // create Win32 name IoCreateSymbolicLink( &w32Name, &ntName); // symbolic link for the Win32 namespace

pDevObj->Flags &= ~DO_DEVICE_INITIALIZING; // clear init bit

return STATUS_SUCCESS; }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 149

5.5.4 Beispiel: „ Dispatcher“

NTSTATUS MyDispatch(PDEVICE_OBJECT pDevObj, PIRP I rp) { I rpStack = IoGetCurrentI rpStackLocation(I rp); // Stackposition ermitteln ioBuffer = I rp->AssociatedI rp.SystemBuffer; // Zeiger auf kopierten I /O Puffer // Informationen vom I /O stack lesen CtrlCode = I rpStack->Params.DevIoCtrl. IoCtrlCode; InpLen = I rpStack-Params.DevIoCtrl.InpBuffLen; OutLen = I rpStack->Params.DevIoCtrl.OutBuffLen; switch (CtrlCode) { case IOCTL_MY_IO: /* ... * / break; } I rp->IoStatus.Status = STATUS_INVALID_REQUEST; IoCompleteRequest(I rp, IO_NO_INCREMENT); return I rp->IoStatus.Status; }

r

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 150

5.5.5 Hardware erkennen & konfigur ieren

• Geräte erkennen: − automatisch durch „ NTDETECT“ (z.B. PCI-Geräte). − manuell über Registry Einstellungen (z. B. ISA-Karten).

• Geforderte HW-Ressourcen dem System mitteilen: Interrupts, DMA, ...

• Konflikte erkennen u. ggf. Treiber nicht laden.

• Während des Bootvorganges werden auto. erkannte Geräte in der Registry abgelegt:

HKEY_LOCAL_MACHINE

Hardware

DESCRIPTION

System

MultifunctionAdapter

3

ParallelController

0

ComponentInfo

ConfigurationData

Identifier

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 151

Manuelle Konfiguration

• Treiber Parameter aus der Registry für: − Nicht automatisch erkannte Geräte. − Zusatzinformationen für automatisch erkannte Geräte.

• Keine standardisiertes Format für Parameter!

HKEY_LOCAL_MACHINE

System

CurrentControlSet

Services

MyDriver

Parameters

Device0

PORT

IRQ

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 152

HW-Ressourcen allozieren

• Registry speichert allozierte Ressourcen.

• Treiber meldet gewünschte Ressourcen mit „ IoReportResourceUsage“ : − bei Erfolg trägt der I/O-Manager die Ressourcen in der Registry ein, − sonst legt er eine Fehlermeldung im Event-Log ab.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 153

5.5.6 Beispiel: Inter rupt-Handler & DPC

• Interrupt Service Routine mit IoConnectInterrupt registrieren: − Legacy-Treiber:

• Ressourcen aus Registry. • ISR beim Laden einrichten.

− PnP-Treiber: • Ressourcen vom Bus-Treiber. • ISR beim Start des Geräts (IRP_MN_START_DEVICE) registrieren.

IoConnectInterrupt( &pDevExt->pInterrupt, // Interrupt-Obj. MyIsr, // the handler pDevExt, // device extension for params. NULL, // Spin-Lock Vector, // Vector in IDT I rql // DIRQL of ISR, SynchronizeI rql, InterruptMode, // latched or level sensitive ShareVector, // shareable? ProcessorAffinity, FloatingSave ); // need to save FPU regs?

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 154

• Beispiel: Interrupt Se Routine: BOOLEAN MyIsr(PKINTERRUPT Interrupt, PVOID SvcContext) { pDE = (PDEVICE_EXTENSION) SvcContext; // device extension as context pDevObj = pDE->DeviceObject; // ptr. to device object I rp = pDevObj->CurrentI rp; // to get access to current IRP if (..) return FALSE; // see if this device requested an interrupt IoRequestDpc(pDevObj, I rp,pDE ); // request DPC for completion return TRUE; }

• DPC-Handler: void MyDpcForIsr(PKDPC pDpc, PDEVICE_OBJECT pDevObj, PIRP pI rp, PVOID pCtx) { pI rp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest(pI rp,IO_NO_INCREMENT); IoStartNextPacket(pDevObj,FALSE); // next IRP (if any) }

• Bem.: DPC-Routine wird beim Erzeugen des Geräteobjektes registriert: IoInitializeDpcRequest(pDevObj, MyDpcForIsr);

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 155

5.5.7 Geräte-I /O star ten

• Ein Geräte-I/O wird eingeleitet durch: IoMarkI rpPending(I rp); // further processing is required IoStartPacket(pDevObj, I rp, 0, NULL ); // call Start-IO function return STATUS_PENDING;

• Dies veranlaßt I/O-Manager die StartIo-Routine des Treibers zu rufen:

VOID MyStartIo(PDEVICE_OBJECT DevObj, PIRP I rp) { I rpStack = IoGetCurrentI rpStackLocation( I rp ); pDE = DevObj->DeviceExtension; // ptr. to our device extension switch( I rpStack->MajorFunction ) { case IRP_MJ_WRITE: pDE->NrOfBytes = I rpStack->Params.Write.Length; pDE->pBuffer = I rp->AssociatedI rp.SysBuffer; KeSynchronizeExecution(pDE->pInterrupt, MyTransmitBytes, pDE ); break;

... } }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 156

• Die StartIo-Routine muss im Treiber-Objekt registriert werden: DriverObject->DriverStartIo = MyStartIo;

• Gewisse Treiberfunktionen müssen mit der ISR synchronisiert werden.

• "KeSynchronizeExecution" wird verwendet, um den IRQL von Routinen auf DIRQL anzuheben, wodurch die ISR unterdrückt wird.

• Bem.: auf eine separate StartIo-Routine kann auch verzichtet werden.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 157

5.6. Plug and Play

• Ziele & Aufgaben des PnP-Managers: − Besteht aus Kernel- und User-Mode Komponente, − Verwaltung benötigter Hardware-Ressourcen, − Dynamische (Re)Konfiguration von Geräten, − Ressourcen-Konflikte vermeiden/auflösen, − Auto. Laden des zuständigen Treibers, − Installation ohne Neustarts.

• User-Mode Teil teilt Anwendungen neue oder entfernte Geräte mit, ...

• Nötige Treiber-Erweiterungen: − PnP-Dispatcher, − Installation über INF-Datei, − AddDevice-Routine implementieren.

• Einsparungen: − DriverEntry dient nur noch zum Export von Funktionen, − Geräte müssen nicht mehr manuell gesucht werden, − Hardware-Ressourcen teilt der Bustreiber mit.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 158

• Insgesamt 24 verschiedene PnP-IRPs mit Präfix " IRP_MJ_PNP" .

• Starten eines Gerätes: IRP_MN_START_DEVICE − IRP an unteren Treiber weiterreichen. − Auf Ergebnis mithilfe von Event-Objekt warten. − Ressourcen allozieren, die Bus-Treiber mitgeteilt hat.

• Stoppen eines Gerätes: IRP_MN_STOP_DEVICE − Laufende Operationen anhalten. − Ressourcen freigeben. − IRP weiterreichen.

• Konfigurierung: − Bus-Treiber ermittelt Anforderungen mit IRP_MN_QUERY_RESOURCE_REQUIREMENTS

− Anpassungen durch FDO-Treiber bei IRP_MN_FILTER_RESOURCE_REQUIREMENTS

− PnP-Manager schickt beste Ressourcen in IRP_START_DEVICE.

• Rekonfigurierung: − PnP Manager schickt IRP_MN_QUERY_STOP_DEVICE − Falls alle Treiber im Stapel mit SUCCESS antworten, folgt IRP_MN_STOP_DEVICE − Nun werden alle rekonfigurierte Geräte wieder gestartet IRP_MN_START_DEVICE

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 159

• PnP Geräte-Zustände: (Präfix IRP_MN_ fehlt)

Never started

Remove pending

Removed

QU

ER

Y_R

EM

OV

E_D

EV

ICE

CA

NC

EL

_RE

MO

VE

_DE

VIC

E

Stop pending

QU

ER

Y_S

TO

P_D

EV

ICE

CA

NC

EL

_ST

OP

_DE

VIC

E

Surprise removed

SUR

PR

ISE

_RE

MO

VA

LStarted

RE

MO

VE

_DE

VIC

E

RE

MO

VE

_DE

VIC

E

RE

MO

VE

_DE

VIC

E

Stopped

STA

RT

_DE

VIC

E

STO

P_D

EV

ICE

START_DEVICE

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 160

5.6.1 Beispiel: „ AddDevice“

NTSTATUS AddDevice(PDRIVER_OBJECT drvObj, PDEVICE_OBJECT PDO ) { // Geräteobjekt erzeugen RtlInitUnicodeString(&devObjName, NT_NAME); IoCreateDevice(drvObj, sizeof(DEV_EXT), &devObjName, FILE_DEVICE_NULL, 0, FALSE, &devObj);

devObj->Flags |= DO_BUFFERED_IO; // Umkopieren bei I /O

// symbolischen Verweis erzeugen RtlInitUnicodeString(&win32ObjName, DOS_NAME); IoCreateSymbolicLink( &win32ObjName, &devObjName);

devObj->Flags &= ~DO_DEVICE_INITIALIZING; // Initialisierung fertig // Einhängen in den Geräte-Stack lowerObj = IoAttachDeviceToDeviceStack(devObj,PDO); pDevExt->lowerObj = lowerObj pDevExt->Pdo = PDO;

return STATUS_SUCCESS; }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 161

5.6.2 Beispiel: „ PnpDispatcher“

NTSTATUS MyPnpDispatch (PDEVICE_OBJECT pDevObj, PIRP pI rp) { pI rpSp = IoGetCurrentI rpStackLocation(pI rp);

switch (pI rpSp->MinorFunction) { case IRP_MN_START_DEVICE: KeInitializeEvent(&devExt->startEvent, SynchronizationEvent, FALSE); IoCopyCurrentI rpStackLocationToNext(pI rp); IoSetCompletionRoutine(pI rp, MyCompl, &devExt->startEvent, TRUE, TRUE, TRUE); status = IoCallDriver(devExt->lowerDevObj,pI rp);

if (status == STATUS_PENDING) KeWaitForSingleObject (&devExt->startEvent, Executive, KernelMode, FALSE, 0); Stat = MyStartDevice(devObj, pI rpSp);

return stat; case IRP_MN_STOP_DEVICE: MyStopDevice(devObj, pI rpSp); IoDisconnectInterrupt(devExt->pInterrupt);

break; case IRP_MN_REMOVE_DEVICE:

IoDetachDevice(devExt->lowerDevObj); IoDeleteDevice(devObj); break;

} IoCopyCurrentI rpStackLocationToNext (pI rp); // copy IRP status = IoCallDriver(devExt->lowerDevObj, pI rp); // forward to next lower driver return status; }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 162

• Completion-Routine: NTSTATUS MyCompl(PDEVICE_OBJECT pDevObj, PIRP pI rp, PKEVENT syncEvt) { KeSetEvent(syncEvt,IO_NO_INCREMENT,FALSE); return STATUS_MORE_PROCESSING_REQUIRED; }

• MyStartDevice-Funktion: − Auslesen der HW-Ressourcen aus IRP-Stack (Eintrag durch Bus-Treiber). − Evt. ISR registrieren ("IoConnectInterrupt").

• Beispiel: „DeviceExtension“ : typedef struct MY_DEV_EXT { ULONG PNPState; DEVICE_POWER_STATE powerState;

PDRIVER_OBJECT drvObj; PDEVICE_OBJECT lowerDevObj, Pdo, self;

KEVENT startEvent; PKINTERRUPT pInterrupt; ULONG PortBase;

} MY_DEV_EXT;

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 163

5.7. Power Management

• Motherboard und BIOS muss ACPI unterstützen.

• ACPI Standard definiert vier Geräte- und sechs Systemzustände.

• Treiber muss Gerätezustand sichern und wiederherstellen können.

• Power-Manager schickt System-State-IRPs.

• Ein Treiber im Stapel konvertiert diese zu Device-State-IRPs.

Systemzustände

• S0: Working (Maschine ist voll verfügbar).

• S1: Standby (Prozessor ausgeschaltet � Wiederanlaufen ~ 2s).

• S2: Standby (weniger Strom als S1; Wiederanlaufen >2s).

• S3: Standby (nur noch Speicher unter Strom).

• S4: Hibernation (Maschine abgeschaltet; Speicher auf Platte gesichert).

• S5: Off.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 164

Gerätezustände

• D0: HW ist voll unter Strom.

• D1: Strom reduziert, Umschalten auf D0 erfolgt schnell. Treiber kann Gerät nicht zugreifen.

• D2: Strom reduziert, Umschalten auf D0 erfolgt langsamer. Treiber kann Gerät nicht zu-greifen.

• D3: Off � Gerät ist komplett abgeschaltet und kann nicht mehr zugegriffen werden.

Power-Management im Treiber

• Ein Treiber im Stapel definiert Power-Politik: − Typischerweise der FDO-Treiber. − Konvertiert System- in Geräte-Zustände. − Sichert und restauriert Gerätezustand bei Bedarf. − Legt Gerät schlafen, falls es nicht in Benutzung ist.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 165

• Verarbeitung eines System-IRPs im Treiber-Stapel: 1) PPO-Treiber (PPO = Power Policy Owner) registriert Completion-Routine und

reicht Power-IRP mit „ PoCallDriver“ nach unten weiter. 2) Completion-Routine:

• System-IRP in Device-IRP konvertieren. • Registrieren einer Completion-Routine2 für den Abschluss des Device-IRP. • Abschicken des Device-IRP an den Treiber-Stapel mit „ PoRequestPowerIrp“ . • Rückgabe von STATUS_MORE_PROCESSING_REQUIRED.

3) Device-IRP durchläuft ebenfalls den ganzen Treiber-Stapel. 4) Bei Abschluss des Device-IRPs wird Completion-Routine2 gerufen:

• Kopieren des Result-Codes des Device-IRPs in das System-IRP. • Abschließen des System-IRP.

PPOPPO

SS--IR

PIR

P

SS--IR

PIR

PPPOPPO

SS--IR

PIR

PDD

--IRP

IRP

PPOPPO

DD--IR

PIR

P

SS--IR

PIR

PPPOPPO

1) 2) 3) 4)

PPOPPO

SS--IR

PIR

P

SS--IR

PIR

PPPOPPO

SS--IR

PIR

PDD

--IRP

IRP

PPOPPO

DD--IR

PIR

P

SS--IR

PIR

PPPOPPOPPOPPO

SS--IR

PIR

P

PPOPPO

SS--IR

PIR

P

SS--IR

PIR

PPPOPPO

SS--IR

PIR

PDD

--IRP

IRP

PPOPPO

SS--IR

PIR

PDD

--IRP

IRP

PPOPPO

DD--IR

PIR

P

SS--IR

PIR

PPPOPPO

SS--IR

PIR

PPPOPPO

1) 2) 3) 4)

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 166

Beispiel: " Power-Dispatcher" – einfache Version

NTSTATUS MyDispatchPower(PDEVICE_OBJECT pDevObj, PIRP pI rp) { POWER_STATE cvPowerState; PIO_STACK_LOCATION sl;

sl = IoGetCurrentI rpStackLocation(pI rp); switch(sl->MinorFunction) {

case IRP_MN_SET_POWER: if (sl->Parameters.Power.Type==SystemPowerState) { // System-IRP? cvPowerState=MyGetDeviceState(sl); // convert IRP if (cvPowerState.DeviceState != devExt->PowerState) // are we in req. device state? PoRequestPowerI rp(pPdo,IRP_MN_SET_POWER,cvPowerState,0,0,0); } if (sl->Parameters.Power.Type==DevicePowerState) { // Device-IRP? PoSetPowerState(...); // transition done // power up: wait for IRP from lower stack - power down: save device state & pass down } break; } PoStartNextPowerI rp(pI rp); // we are ready for the next Power-IRP IoSkipCurrentI rpStackLocation(pI rp); // next driver should use same stack location return PoCallDriver(devExt->lowerDevObj,pI rp);

}

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 167

5.8. Installation

5.8.1 NT4

• Treiber nach „System32\Drivers“ kopieren,

• Registry-Einträge erstellen,

• System neu starten.

• Bem.: Funktioniert noch, aber ...

HKEY_LOCAL_MACHINE

System

CurrentControlSet

Services

MyDriver

Parameters

Device0

PORT: 0x2f8IRQ: 0x3

ErrorControl: 0x1Start: 0x1Type: 0x1

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 168

5.8.2 Windows 2000

• INF-Datei vorgeschrieben: − Dateien, − Registry-Keys, ... − Optional eine Catalog-Datei, − Klassennamen und Geräteklasse als GUID, − Hardware-ID (z.B.USB\VID_045E&PID_00B definiert eine Microsoft Tastatur am

USB-Bus).

• Vorhalten von INF-Dateien in „Windows\INF“ -Verzeichnis.

• Digitale Signatur: − Vergeben von WHQL (Windows Hardware Quality Labs) − Zunächst muß der Treiber die Tests des "Windows Logo Program" bestehen, − Dann muß er mit einem WHQL-Tester geprüft werden, − Schließlich wird er nochmals von MS getestet. − Info: http://www.microsoft.com/hwtest/default.asp

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 169

5.9. Zugr iff auf Treiber

• Zugriff über Win32 Dateisystem API.

• Beispiel: int main(void) { HANDLE hDevice; DWORD dwBytesWritten; char *szBuffer = „ hello world“ ; int res; hDevice = CreateFile( " \\\\.\\MyDevice0" , // UNC naming required! GENERIC_WRITE, // access mode

write-only 0, // no sharing NULL, // no security attributes OPEN_EXISTING, // open existing FILE_ATTRIBUTE_NORMAL, // various predefined attributes NULL // template file for attributes ); res=WriteFile(hDevice, szBuffer, lstrlen( szBuffer ), &dwBytesWritten, NULL ); CloseHandle( hDevice ); }

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 170

5.10. Besondere Treiberklassen

• Kernel Streaming: − Für Multimedia-Ströme, − Datenströme im Kern, Kontrolle im User-Mode, − Direkte Kommunikation zwischen Treibern, nicht über den I/O-Manager.

• Grafik: − Unterteilt in Display-Treiber (DLL) und Video-Miniport-Treiber, − Display-Treiber ist an win32k.sys angebunden.

• Netzwerktreiber: komplexe Architektur mit separaten Schnittstellen.

• In Zukunft wieder anstehende Änderungen durch 64-Bit.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 171

5.11. Grafik-Treiber

5.11.1 Grafiksystem

• Von der MFC-Methode „BitBlt“ bis zum Grafiktreiber.

Applikat ion

dc->BitBlt

MFC42.DLL

GDI32.DL L

BitBlt

_KiSystemService

NTOSK RNL .EXE

_NtGdiBitBlt

WIN32K .SYS

_DrvBitBlt

DDI.DLL

Use

r m

ode

Ker

nelm

ode

Applikat ion

dc->BitBlt

MFC42.DLL

GDI32.DL L

BitBlt

_KiSystemService

NTOSK RNL .EXE

_NtGdiBitBlt

WIN32K .SYS

_DrvBitBlt

DDI.DLL

Use

r m

ode

Ker

nelm

ode

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 172

• Grafiktreiber besteht immer aus zwei Teilen: Display Dr iver & Video Minipor t Dr iver .

• Display Driver: − DLL-Datei, gebunden an win32k. − übernimmt Zeichenoperationen. − greift direkt auf Hardware zu. − DirectDraw Interface.

• Video Miniport Driver: − Verwaltet Ressourcen. − Interagiert mit I/O-Manager. − Konfiguration, z.B. Auflösung setzen.

Kernel M ode

User M ode

System Services

KM DirectDraw

Win32 APIs

DD

RA

W

Hardware Abstraction Layer

Direct DrawHW Interface

DisplayDriver

I/O-Manager

VideoPort

VideoMiniport

Graphics Engine(win32k)

GD

I32

Kernel M ode

User M ode

System Services

KM DirectDraw

Win32 APIs

DD

RA

W

Hardware Abstraction Layer

Direct DrawHW Interface

DisplayDriver

I/O-Manager

VideoPort

VideoMiniport

Graphics Engine(win32k)

GD

I32

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 173

5.11.2 Display Dr iver Inter face

• Display Dr iver Inter face (DDI) ist die Schnittstelle zwischen Win32k und einem Display Driver.

• Grafiktreiber wird von Win32k geladen.

• Viele DDI Funktionen sind optional.

• DDI Routinen werden nur vom Win32k gerufen, nicht vom I/O-Manager!

• Grafiktreiber können nur Dienste von Win32k nutzen (z.B. „EngDeviceIoControl“ statt „ IoStartPacket“ )

• DDI Interface ist sehr flexibel: 1) „DrvPaint“ wird gerufen. 2) Treiber kann Parameter nicht verarbeiten

er ruft „EngPaint“ 3) Win32k simuliert Operation auf einer Bitmap

zeichnet Ergebnis mit „DrvCopyBits“ 4) Treiber gibt Bitmap aus und kehrt zurück 5) Rücksprung von „EngPaint“ 6) Rückkehr und Ende des ursprünglichen Aufrufs „DrvPaint“

Win32k

GraphicsDriver

1 2 3 457DDI

Win32k

GraphicsDriver

1 2 3 457DDI

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 174

5.11.3 Video Minipor t Dr iver

• Jeder Video Miniport Treiber wird mit dem Video Port Driver gelinkt und ruft nur dessen Routinen!

• Display Driver kommuniziert mit dem Video Miniport Treiber über den I/O-Manager:

− Mit der Funktion „ EngDeviceIoControl“ von Win32k. − I/O-Manager leitet alle IOCTL_VIDEO_xxx Anfragen an den Video Port Driver. − Der Video Port Driver bildet eingehende IRPs auf Video Request Packets (VRPs)

ab und leitet sie an den zuständigen Video Miniport Treiber.

5.11.4 DirectDraw & Freunde DirectDraw

• Direkter Zugriff auf die Hardware, aber einheitliche Schnittstelle für verschiedene Grafikkarten.

• gedacht für Spieleprogrammierung unter Windows.

Systemprogrammierung II, Winter 2002/03, P. Schulthess & M. Schöttner 175

• Emulation fehlender Spezialhardware (z.B. Blitter).

• Funktionen in Grafiktreiber-DLL integriert.

• Treiberfunktionen: − „ Blt“ : Bitblock-Transfer (z.B. nur innerhalb des Adapterspeichers) − „ Flip“ : Unterstützung für Multibuffering − „ MapMemory“ : Teile des Adapterspeichers in User-Mode Adreßraum einblenden − keine seperaten Zeichenfunktionen.

DirectX Video Acceleration

• Beschleunigung von Video-Decodern, z.B. MPEG-2.

• API und korrespondierendes DDI.

Direct3D

• Beschleunigung von 3D-Grafiken.

• API und korrespondierendes DDI.