Porting Steps for Graphics Drivers

This section provides step-by-step porting details that pertain to both display and print drivers.

Most functions that were originally exported by winsrv.dll are now exported by win32k.sys, so a simple relink of the driver resolves references to these functions. However, all other functions imported by your driver (from kernel32.dll, advapi32.dll, or any other DLL) must be replaced or eliminated because they are no longer available. If your driver directly references functions from any image other than win32k.sys, the system will not load your image. Therefore, the basic requirement for enabling a graphics driver to run under Windows NT 4.0 is to remove any calls to Win32 functions, and replace them with the calls exported by win32k.sys.

An easy way to determine exactly which functions your driver calls is to dump the list of imports, or external references, in your driver. One way to obtain this list is to run the following command:
link -dump -imports your_driver.dll
 

Here are some common changes to make to your graphics drivers to port them from Windows NT 3.51 to 4.0.

Step 1. Clean out the files used to compile your driver.

Step 2. Replace Win32 calls with new kernel-mode counterparts.

Any remaining Win32 functions in the original Windows NT 3.51 driver must be removed. If your driver absolutely requires a function that is not currently exposed, then Microsoft should be made aware of this requirement so the function can be exposed or an appropriate alternative can be found.

Step 3. Clean out calls to C-runtime routines where necessary.

String routines, such as strcmp, are not exported from win32k.sys. Calls to these routines should be removed if possible. Limited C-runtime functionality is available in libcntpr.lib, which statically links to the driver.

Step 4. Replace floating point operations with FLOATOBJs.

Don’t use native floating point operations. Windows NT does not support kernel-mode floating point operations on some systems. Specifically, the Windows NT kernel does not preserve floating point registers on kernel-mode stack switches, so using floating point registers in the driver corrupts an application’s floating point registers.

GDI has introduced a new set of services that allows graphics drivers to emulate floating point arithmetic. See the reference pages for the FLOATOBJ_Xxx services for more information.

Step 5. Be frugal with the stack.

Each thread is allocated a limited amount of stack space for all function calls and interrupts. The Windows NT kernel allocates an initial 12K on x86 and MIPS platforms, and 16K on ALPHA and PowerPC platforms. The stack can grow to accommodate callbacks from the kernel to user mode and back; the maximum stack size is 60K/64K in the kernel. Only 12K/16K of the stack is visible at any point in time. The only exception to these policies is OpenGL, which is allocated the entire 60K/64K stack at once.

In Microsoft’s driver design, a guideline of 1K of stack space per function is used. This heuristic was arrived at by studying the stack needs of a typical graphics driver. The first few kilobytes on the stack contain the functions called to get from the application to the driver, such as the system service functions. The last 2-3 kilobytes are reserved for page faults and interrupts. The fact that some driver calls spawn several nested function calls is also accounted for. For example, the S3’s implementation of DrvStretchBlt calls EngStretchBlt, which calls DrvBitBlt, which calls another internal S3 fill function. Using the 1K per function guideline means that only up to 4K of the stack is used for these four functions.

You should also look at the size of your functions’ parameters. Only small structures and very small arrays of data should be stored on the stack. Arrays of 1024 or 512 elements and arrays the size of the screen’s width should not be passed. Consider the following: if each array element is a DWORD, 1024 elements uses 4K of stack space.

Memory beyond the stack pointer should not be touched in assembly routines because interrupts can occur at any time.

A routine is guaranteed to be using too much stack space if you get an undefined external for something such as _chkstk.

Step 6. Update your driver with other Windows NT 4.0 driver changes.

Because all Windows NT 3.51 drivers are incompatible in Windows NT 4.0, a few things have been cleaned up in the drivers:

Step 7. Examine the “Special Features” section of this appendix.

The section entitled Special Features of a User-Mode Process, described earlier in this document, should be examined. Drivers depending on any of these features must be changed to avoid these problems.

Step 8. Read the porting section of this appendix specific to your graphics driver type.

The sections that follow this one are Porting Steps for Display Drivers and Porting Steps for Printer Drivers. Read the section that pertains to your driver type for additional type-specific porting hints.

Step 9. Install your new driver.

Install your new driver, and test. Use the kernel-mode kd debugger or windbg to debug your driver. NTSD can no longer be used for debugging graphics drivers.