Chapter 7: Understanding Device Drivers
Overview
Device Driver Architecture
Native Device Drivers
Device Driver Memory Management
Device Driver Interrupt Handling
Stream Device Drivers
Display Driver Architecture
Primer on GDI Programming
Inside Display Drivers
Device Driver Architecture
Windows CE Architecture
Device Power Management
OEMOEM HardwareHardwareOEMOEM HardwareHardware
EmbeddedEmbedded ShellShellEmbeddedEmbedded ShellShell
ApplicationsApplicationsApplicationsApplications
WIN32WIN32 APIsAPIsCOREDLLCOREDLL, , WINSOCKWINSOCK, , OLEOLE, , COMMCTRLCOMMCTRL, , COMMDLGCOMMDLG, , WININETWININET, , TAPITAPI
WIN32WIN32 APIsAPIsCOREDLLCOREDLL, , WINSOCKWINSOCK, , OLEOLE, , COMMCTRLCOMMCTRL, , COMMDLGCOMMDLG, , WININETWININET, , TAPITAPI
WindowsWindows CECE ShellShell ServicesServicesWindowsWindows CECE ShellShell ServicesServices
RemoteRemote ConnectivityConnectivityRemoteRemote ConnectivityConnectivity
KernelKernelLibraryLibraryKernelKernelLibraryLibrary
IrDAIrDAIrDAIrDAGWESGWESGWESGWES Device Device ManagerManagerDevice Device
ManagerManagerFileFile
ManagerManagerFileFile
ManagerManagerTCP/IPTCP/IPTCP/IPTCP/IP
OALOALBootloaderBootloader
OALOALBootloaderBootloader DriversDriversDriversDrivers DeviceDevice
driversdriversDeviceDevice driversdrivers FileFile driversdriversFileFile driversdrivers
MicrosoftMicrosoftMicrosoftMicrosoft OEMOEMOEMOEM ISV,ISV, OEMOEMISV,ISV, OEMOEM
Windows CE Architecture
NetworkNetworkdriversdrivers
NetworkNetworkdriversdrivers
Device Power Management
Power status notification function
Shutdown operations
Save device state to preallocated storage
Issue commands to the device that is shutting down
Set a flag within the driver to note that it has been shut down
Do not call Win32 API functions during a shutdown sequence
Native Device Drivers
Overview of Native Device Drivers
Programming Model
MDD/PDD Layers
Battery and Notification LED Device Drivers
PC Card Socket Device Drivers
Keyboard Device Drivers
Overview of Native Device Drivers
Designed to drive built-in devices
Provided by OEMs
Supports custom interfaces
Loaded by GWES
Device Driver Interface (DDI)
Interface between the OS and device drivers is called DDI
DDI functions are defined for each device driver class
DDI functions are defined by Microsoft and cannot be changed
Programming Model
GWES
Monolithicdevice driver
Hardware
Device Driver
DDSI functions
MDD layer
PDD layer
DDI functions DDI functions
MDD/PDD Layers
Model Device Driver (MDD) Layer
Provided by Microsoft Platform-independent code Communicates with GWES and Kernel Handles interrupts
Platform-Dependent Driver (PDD) Layer
Provided by OEMs Focus only on specific platform porting issue Communicates with the hardware
MDD/PDD Layers (continued)
MDD layer handles the DDI interface
Interface between MDD and PDD is the Device Driver Service-Provider Interface (DDSI)
DDSI interfaces may be redefined by OEMs with corresponding changes in the MDD layer
When performance is an issue, the PDD layer can be bypassed - all processing can be done in MDD layer
MDD code is provided as source code and as libraries
Battery and Notification LED Device Drivers
Battery device driver
Provides information about power level of main and backup batteries
Library statically linked with GWES
Monolithic; uses only DDI functions
Notification LED driver
Library statically linked with GWES
Handles all requests to turn the system notification LED on or off
PC Card Socket Device Drivers
Manages any PC Card sockets
Abstracts hardware specifics so that a PC Card driver can run unchanged on any platform
The MDD Layer exposes functions that can be used when developing a stream interface device driver for individual PC Cards
MDD functions constitute the Card Services library
PPD layer exposes low-level functions that constitute the Socket Services library
Keyboard Device Drivers
MDD Layer
Maps scan code to virtual key code
Generates character data associated with VK code
Packages keyboard messages and puts them in the system message queue
PDD Layer
Retrieves scan code from hardware
Device Driver Memory Management
Memory Management Functions
Windows CE Address Space
Drivers and Pointer Data
Driver Memory Access
Memory Access in Drivers
Memory Management Functions
Device drivers are user-mode modules - it is necessary to map physical memory to virtual memory
VirtualAlloc, VirtualFree: reserve, free virtual memory
MEM_RESERVE
VirtualCopy: maps a physical memory range to a virtual memory range
PAGE_NOCACHE
PAGE_PHYSICAL
Memory Management Functions (continued)
MapPtrToProcess
GetCurrentProcess
GetOwnerProcess
UnMapPtr
SetProcPermissions
Volatile qualifier
Not Used
Slot 0Slot 0
Slot 32
64 KB64 KB
32 MB32 MB
64 MB64 MB
2 GB2 GB
3 GB3 GB
4 GB4 GB
Memory mapped filesMemory mapped files
Above 2G-3GAbove 2G-3GMapped to Mapped to physical memoryphysical memory
Virtual Virtual address address
spacespace
Slot 1Slot 1
Slot 32Slot 32
NULL pointers NULL pointers
Windows CE Address Space
512M Cached
512M Non-Cached
0x80000000
0xA0000000
Accessable via Accessable via MmMapiIoSpaceMmMapiIoSpace
Drivers and Pointer data
OS manages pointers passed directly as parameters
Driver must map All pointers contained in structs
DeviceIOControl buffers often are structs that contain data, some of which may be pointers.
Use MapPtrToProcess( SomePtr, GetOwnerProcess())GetOwnerProcess() is used only in the context of a driver and cannot be used by Apps.
Driver Memory Access
App Calls DeviceIOControlApp Calls DeviceIOControl
DM mapped into Slot 0DM mapped into Slot 0
App is mapped into Slot 0App is mapped into Slot 0
DM Calls xxx_IoControlDM Calls xxx_IoControl
DM Sets permissions to App spaceDM Sets permissions to App space
APP
DMSlot 0
APPAPPMapped Mapped pointerpointer
Driver Calls MapPtrToProcessDriver Calls MapPtrToProcess
Driver returns from xxx_IoControlDriver returns from xxx_IoControl
DM Re-Sets permissions to App spaceDM Re-Sets permissions to App space
App is mapped into Slot 0App is mapped into Slot 0
APPDMAPPOriginaOriginal l
pointerpointer
Memory Access in Drivers
If driver creates a thread to do the work. MapPtrToProcess() will not work without some help
You must use GetCurrentPermissions() and SetProcPermissions() to capture and reset the process permissions.
Device Driver Interrupt Handling
Interrupt Run Time
Interrupt Service Thread
Interrupt Management Functions
Typical IST Start
Typical IST
Typical Stop
Interrupt Run Time
I/O Routines
OEM Hardware
ISR OAL routinesOAL
ExceptionHandler
Interrupt Support Handler
Kernel
IST
Driver
1
3 4 9
5
7
6
2
8
Interrupt Service Thread
Uses user-mode thread of device drivers for built-in devices
Does the actual processing of the interrupt
Creates an event object associated with the logical interrupt
IST remains idle most of the time, awakened when the kernel signals the event object
IST usually runs at above-normal priority
Interrupt Service Thread (continued)
Boost IST priority with CeSetThreadPriority function
Create an event object with CreateEvent function
Associate event object with SYSINTR_ by calling InterruptInitialize function
Code a loop whose first operation is WaitForSingleObject
The kernel signals the event object, which causes WaitForSingleObject to return
Perform I/O in the device and process data
Call InterruptDone to signal interrupt handling completion
Interrupt Management Functions
ISR
HookInterrupt
UnhookInterrupt
IST
InterruptInitialize
InterruptDone
InterruptDisable
Typical IST Startstruct ISTData // Declare the Strucure to pass to the ISTstruct ISTData // Declare the Strucure to pass to the IST
{{
HANDLE hThread; // IST HandleHANDLE hThread; // IST Handle
DWORD sysIntr; // Logical IDDWORD sysIntr; // Logical ID
HANDLE hEvent; // handle to the event to wait for interruptHANDLE hEvent; // handle to the event to wait for interrupt
volatile BOOL abort; // flag to test to exit the ISTvolatile BOOL abort; // flag to test to exit the IST
};};
ISTData g_KeypadISTData;ISTData g_KeypadISTData;
// Create event to link to IST // Create event to link to IST
g_KeypadISTData.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);g_KeypadISTData.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// Translate IRQ to an logical ID (x86 CEPC)// Translate IRQ to an logical ID (x86 CEPC)
g_KeypadISTData.sysIntr =Mapirq2Sysintr(5);g_KeypadISTData.sysIntr =Mapirq2Sysintr(5);
// start the thread// start the thread
g_KeypadISTData.hThread = CreateThread(NULL,0,&KeypadIST,g_KeypadISTData.hThread = CreateThread(NULL,0,&KeypadIST,
&g_KeypadISTData, 0, NULL);&g_KeypadISTData, 0, NULL);
Typical IST Start (Continued)
//Change the threads priority//Change the threads priority
CeSetThreadPriority(g_KeypadISTData.hThread,0);CeSetThreadPriority(g_KeypadISTData.hThread,0);
//disconnect any previous event from logical ID//disconnect any previous event from logical ID
InterruptDisable(g_KeypadISTData.sysIntr);InterruptDisable(g_KeypadISTData.sysIntr);
// Connect Logical ID with Event// Connect Logical ID with Event
InterruptInitialize(g_KeypadISTData.sysIntr, g_KeypadISTData.InterruptInitialize(g_KeypadISTData.sysIntr, g_KeypadISTData.
hEvent,NULL,0);hEvent,NULL,0);
Typical IST
DWORD KeypadIST(void *dat)DWORD KeypadIST(void *dat)
{ {
ISTData* pData= (ISTData*)dat;ISTData* pData= (ISTData*)dat;
// loop until told to stop// loop until told to stop
While(!pData->abort)While(!pData->abort)
{ // wait for the interrupt event... { // wait for the interrupt event...
WaitForSingleObject(pData->hEvent, INFINITE)WaitForSingleObject(pData->hEvent, INFINITE)
if(pData->abort)if(pData->abort)
break;break;
// Handle the interrupt...// Handle the interrupt...
// Let OS know the interrupt processing is done// Let OS know the interrupt processing is done
InterruptDone(pData->sysIntr); InterruptDone(pData->sysIntr);
}}
Return 0;Return 0;
}}
Typical IST Stop
//disconnect event from logical ID//disconnect event from logical IDInterruptDisable(g_KeypadISTData.sysIntr);InterruptDisable(g_KeypadISTData.sysIntr);
// set abort flag to true to let thread know// set abort flag to true to let thread know// that it should exit// that it should exitg_KeypadISTData.abort =TRUE;g_KeypadISTData.abort =TRUE;
// manually set the event to break thread// manually set the event to break thread// out of wait call// out of wait callSetEvent(g_KeypadISTData.hEvent);SetEvent(g_KeypadISTData.hEvent);
//wait for thread to exit//wait for thread to exitWaitForSingleObject(g_KeypadISTData.hEvent,INFINITE);WaitForSingleObject(g_KeypadISTData.hEvent,INFINITE);
CloseHandle(g_KeypadISTData.hEvent);CloseHandle(g_KeypadISTData.hEvent);CloseHandle(g_KeypadISTData.hThread);CloseHandle(g_KeypadISTData.hThread);
Stream Device Drivers
Overview of Stream Interface Device Drivers
Device Manager
Programming Model
Loading Mechanism
Entry Points
Programming Considerations
Audio Device Drivers
File System Drivers
Overview of Stream Interface Device Drivers
Designed to support installable devices
Common interface for all device drivers
Expose device services through Win32 File I/O API functions
Loaded, controlled, and unloaded by the Device Manager
Can also be loaded directly by an application
Often uses services from underlying native drivers
Modem driver using the native serial driver
Device Manager
The goal of a user-level process is to:
Load device drivers either at startup or on connection notifications
Register special file names in the system
Locate device drivers by obtaining PnP ID or by executing detection routines
Track device drivers by reading and writing registry values
Unload device drivers
Device Manager (continued)
Device file name
All operations on device files are redirected to their respective drivers
Device file name format is XXXY: where
XXX is the prefix and consists of three letters in uppercase
Y is the index and allows several devices to be handled by the same driver
The names of the stream interface functions always begin with the device file name as a prefix
Programming Model
User application
Kernel
File system code
Devicemanager
Streaminterface
driver
Nativedevicedriver
Windows CE-based platform
Peripheral device
Loading Mechanism
Load Drivers Listed in HKLM\Drivers\BuiltIn
Required values : Dll, Prefix
Useful values : Index, Order
Load PCMCIA drivers when detected
HKLM\Drivers\PCMCIA\Plug and Play ID
HKLM\Drivers\PCMCIA\Detect
HKLM\Drivers\PCMCIA\Driver
Loading Mechanism (continued)
Application can load a driver dynamically by calling the RegisterDevice function
For each loaded device driver, the Device Manager creates a key under HKLM\Drivers\Active
Argument passed to the initialization function
Hnd : the device handle
Name : the device file name
Key : the registry path to the device key under HKLM
Entry Points
XXX_Init
Called when Device Manager loads the driver
Initializes resources that are to be used: memory mapping, etc.
XXX_Deinit
Called when Device Manager unloads the driver
Frees allocated resources, stops the IST
Entry Points (continued)
XXX_Open
Invoked when applications call CreateFile(XXX, …)
Returns a context handle that will be used in subsequent calls to XXX_Read, XXX_Write, XXX_Seek, XXX_IOControl, and XXX_Close
XXX_Close
Invoked when applications call CloseHandle function
Entry Points (continued)
XXX_Read
Invoked when application calls ReadFile function
XXX_Write
Invoked when application calls WriteFile function
XXX_Seek
Allows moving the current I/O pointer
Entry Points (continued)
XXX_IOControl
Allows performing custom operations that do not necessarily apply to files
I/O control code identifies the operation
I/O control code is device-specific
XXX_PowerXXXX
PowerUp and PowerDown notifications
Should complete execution as quickly as possible
Programming Considerations
Single or multiple access to a device
Multiple: XXX_Open always returns a unique context handle
Single: XXX_Open returns one context handle on the first call and NULL for subsequent calls
For unusual operations on files, use the XXX_IOControl function
Read-only or write-only device
Audio Device Drivers
Sample PCM Waveform Audio Driver
WAV prefix
Relies mostly on XXX_IOControl
You can use wavemdd.lib to build your own wavepdd.lib and link the two together to form the wavedev.dll
Audio Compression Manager driver
ACM prefix
Codec, Converter, Filter
You can refer to Windows NT ACM documentation
File System Drivers
Designed for drivers that allow data to be read or written in blocks of fixed size
Block device functionality
Extend the size of the Object Store
Store code and data
Interoperability between operating systems
Registry storage
Database storage
File System Drivers (continued)
ATA flash memory
Emulates the behavior of an ATA-style hard drive with a chip
Linear memory flash
Uses a software layer called flash translation layer (FTL) to emulate a disk drive
Block device prefix is DSK
All I/O are handled by the DSK_IOControl function with the same I/O control codes as the ones used by the FAT file system driver
Lab A: Developing a Stream Interface Device Driver
Display Driver Architecture
Windows CE Graphic Pipeline
GPE Driver Pipeline
Key Display Driver Source Files
HARDWARE
GWES.EXE
DDI.DLLCOREDLL.DLL
DRAWPROG.EXE
Windows CE Graphic PipelineWindows CE Graphic Pipeline
GPE Driver Architecture
HARDWARE – DIB-Compatible Video Buffer
GWES.EXE
DDI.DLL GPE.LIB
DrvEnableDriver
DrvEnableDriver
EMUL.LIBHardware Acceleration
Key Display Driver Source Files
In ..\public\common\oak\inc:
WINDDI.H – Driver interface definitions
EMUL.H – Drawing helpers for raster drawing
GPE.H – Basic set of data structures & defines
GPE Source Files
In ..\private\winceos\ coreos\gwe\mgdi\gpe
Primer on GDI Programming
Families of Drawing Functions
Drawing Coordinates
GDI Drawing Functions
Drawing Text
Drawing Raster Data
Drawing Vector Objects
Window Drawing: WM_PAINT
MINGDI Display Drawing
Text
Raster
Vector
AbcAbcdefghijklmnopqr
Abcdefghijklmnopqrstuvwxyz
AbcAbcdefghijklmnAbcdefghijklmn
Families of Drawing Functions
(0,0)(0,0)
+Y
+X
Drawing Coordinates
Text Drawing - ExtTextOut, DrawText
Vector Drawing - Polyline, Rectangle, Ellipse, Polygon, RoundRect
Raster Drawing - SetPixel, PatBlt, BitBlt, MaskBlt
GDI Drawing Functions
Draws a line of text.
ExtTextOut (hdc, x, y, Options, pRect, lpstr, cch, int * lpDX);
HDC hdc - DC handle. int x - X coordinate int y - Y coordinate UINT Options - NULL Ok. RECT * pRect - NULL Ok. LPTSTR psz - string UINT cch - string length. int * lpDX - NULL - Ok.
ExtTextOut(hdc,x,y,NULL, NULL, "hello", 5, NULL);
ExtTextOut(hdc,x,y,NULL, NULL, "hello", 5, NULL);
hello(x,y)
Drawing Text
Pixels
SetPixel
GetPixel
Fill An Area
PatBlt
Copy Device-Dependent Bitmaps
BitBlt
StretchBlt
Draw Device Independent Bitmaps
BitBlt
StretchDIBits
Drawing Raster Data
Lines
Polyline
Filled Figures
Polygon
Ellipse
Rectangle
Drawing Vector Objects
LRESULT CALLBACKWndProc(HWND hwnd, UINT msg,...){ switch (msg) { case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd,&ps);
// draw, draw, draw... TextOut (hdc,x,y,lp,cb);
EndPaint (hwnd, &ps); }
LRESULT CALLBACKWndProc(HWND hwnd, UINT msg,...){ switch (msg) { case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hwnd,&ps);
// draw, draw, draw... TextOut (hdc,x,y,lp,cb);
EndPaint (hwnd, &ps); }
Window Drawing: WM_PAINT
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
HDC hdc = CreateDC(L"display", 0, 0, 0); ExtTextOut(hdc, 10, 10, NULL, NULL, L"Hello World", 11, 0);
DeleteDC(hdc);
return 0;}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
HDC hdc = CreateDC(L"display", 0, 0, 0); ExtTextOut(hdc, 10, 10, NULL, NULL, L"Hello World", 11, 0);
DeleteDC(hdc);
return 0;}
MINGDI Display Drawing
Inside Display Drivers
Display Device Drivers
Connecting to a Driver
Queries, Attributes and Drawing
Disconnecting
DDI Vector Functions
DDI Raster Functions
DDI Text Functions
Display Device Drivers
Subset of the Windows NT DDI, with the following differences:
Display drivers always present the same functionality
Display drivers cannot reject an operation as too complex
Display drivers are native drivers because they have a custom interface with GWES
Loaded by GWES
Display Device Drivers (continued)
Display drivers are usually layered
Graphic Primitive Engine (GPE)
Acts as the MDD layer
Optional
Handles all the default drawing
Requires the display hardware to use a flat-frame buffer
PDD layer
IHVs provide hardware-specific code
Display Device Drivers (continued)
Secondary display driver
Loaded by the Device Manager when calling CreateDC You cannot use any window manager functions You can easily display the contents of the primary
display Accelerating BitBlt and line drawing
Default GPE routines Emulated library Hardware acceleration
CreateDC
Only way to access graphic devices
Calls driver’s initialization functions
Application
Driver
CreateDC
COREDLL.DLL + GWES.EXE
DrvEnableDriver,DrvEnablePDEV,DrvCompletePDEV
Hardware
Connecting to a Driver
GetDeviceCaps
Queries key values
SelectObject
Object selection function
No call to driver
Polyline
Request to draw
Calls driver to do “real-work”
Application
Driver
Hardware
COREDLL.DLL + GWES.EXE
SelectObject (…)
Polyline(…)
DrvStrokePath
GetDeviceCaps(…)
Queries, Attributes & Drawing
Application disconnects from GDI
GDI disconnects from driver.
Application
Driver
Hardware
COREDLL.DLL + GWES.EXE
DeleteDC
DrvDisablePDEV
Disconnecting
Application
COREDLL.DLL + GWES.EXE
DRIVER
MoveToEx Polyline Ellipse PolyBezier
DrvStrokePath DrvFillPath
DrvStrokeAndFillPath
DrvBitBlt DrvPaint
Polygon Rectangle
DDI Vector Functions
App
COREDLL.DLL + GWES.EXE
DRIVER
SetPixelBitBlt
MaskBltRectangle
SetDlBitsToDevice
DrvCopyBitsDrvBitBlt
GetDIBits SetDIBits
ExtTextOut
DDI Raster Functions
API
ExtTextOutDrawText
DDI
DrvBitBlt
DDI Text Functions
Lab B: Exploring Video Display Drivers
Review
Device Driver Architecture
Native Device Drivers
Device Driver Memory Management
Device Driver Interrupt Handling
Stream Device Drivers
Display Driver Architecture
Primer on GDI Programming
Inside Display Drivers