OSRLogo
OSRLogoOSRLogoOSRLogo x
OSRLogo
x

Everything Windows Driver Development

x
x
x
GoToHomePage xLoginx
 
 

    Thu, 02 Sep 2010     81215 members

   Login
   Join


 
 
Contents
  About This Site
What's New?
Hector's Memos
The NT Insider
The Basics
File Systems
Downloads
ListServer / Forum
Driver Jobs
Store
  Express Links
  · It's Here: The NT Insider -- Digital Edition!
  · WDK Community Bug Bash 2010 -- Submit a Bug... Get FREE STUFF!
  · File Systems and Filters: A Specialty
  · It's All About The Basics
  · The NT Insider - Digital Edition

Try This -- Interactive Driver Testing


Drivers can be tough to test, especially early in their development cycle. Often, you need to get a ton of code written and running just so you can get to the point where you can start testing to see if some of the basic assumptions you’ve made about how your hardware works are valid.

Well, maybe not. One of the most unique ideas I’ve seen in driver testing was recently proposed by NTDEV member (and DDK MVP) Don Burn.

Let’s say you want to do some basic tests to see if you can actually get your hardware initialized. Why not stick your code into the world’s most minimal driver skeleton using a DriverEntry routine like that shown in Figure 1?


NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObj, PUNICODE_STRING RegistryPath)
{
    ULONG function;
    NTSTATUS status;
    BOOLEAN done = FALSE;

    DbgPrint("\n MyDriver -- Compiled %s %s\n",__DATE__, __TIME__);

    while(done == FALSE)  {

        DbgPrint("\nMyDriver TEST -- Functions:\n\n");
        DbgPrint("\t1. Input Port Address\n");
        DbgPrint("\t2. Input Shared Memory Address\n");
        DbgPrint("\t3. Call HwInit\n");
        DbgPrint("\t4. Test InitStatus\n");
        DbgPrint("\n\t0. Exit\n");
     
 DbgPrompt("\n\tSelection: %x", &function);
      
 DbgPrint("\n");

        switch(function)  {

            case 0:
                done = TRUE;
                break;

            case 1:
                DbgPrompt("\nPort to use: %x", &Port)
                break;
           
  
            case 2:   {
                ULONG mem;
                PHYSICAL_ADDRESS pa;

                DbgPrompt("Shared Memory low-part: %x", &mem);
                pa.LowPart = pa;
                DbgPrompt("Shared Memory high-part: %x", &mem);
                pa.HighPart = pa;

                MappedMem = MmMapIoSpace(pa, SHARED_SIZE, MmNonCached);
                break;               
            }

            case 3:
                DbgPrint("Calling HwInit");
                status = HwInit();
                DbgPrint("HwInit returned 0x%0x\n", status);
                break;

            case 4:
                DbgPrompt("How many MS to wait?? %d", &mem);

                DbgPrint("Calling TestInitStatus");   
                status = TestInitStatus(mem);
                DbgPrint("TestInitStatus returned 0x%0x\n", status);

                break;

        }

    }

    DbgPrint(DRIVER_NAME "DriverEntry: Leaving\n");

    if(MammpedMem)  {
        MmUnmapIoSpace(MappedMem, SHARED_SIZE);
    }

    return(STATUS_UNSUCCESSFUL);
}

Figure 1

The trick here is that you write a DriverEntry routine that uses DbgPrint and DbgPrompt in a loop to interact with you via the debugger. When you’re done playing (er, testing); your code breaks out of the loop, reverses any changes it made in the system, and returns an error. That’ll cause your driver to unload.

Given that you’ll be performing the majority of this testing on one or two test machines at the most, with a limited set of hardware, you will almost certainly know the port and/or shared memory address assigned to your device. If you don’t know these from your hardware specification, you can always use one of the many PCI bus examination utilities and read the information from your device’s BARs. After all, these registers were assigned to your device during system initialization. You can very happily use them on a limited basis and in a test environment only without doing the usual StartDevice song-and-dance.

Before you go all frothy at the mouth, understand that this whole idea is limited to early test scenarios. We’re talking about a technique that’ll help you get something going fast with the least possible annoyance and smallest-possible investment in test code. Once you get some solid code in your driver, you’ll want to change over to properly allocating the ports and shared memory address like you’re supposed to, and using a user-mode test app to send testing IOCTLs to you driver.

And, be warned, this idea might not work with SoftICE.

But for early stage testing, where you need to continuously vary timer values and other test information, this might be just the trick you need. Have fun!

 

User Comments
Rate this article and give us feedback. Do you find anything missing? Share your opinion with the community!
Post Your Comment

"Why is DbgPrompt not mentioned in the DDK help?"
.

Rating:
04-Jan-07, Alexandru Pojoga


"DbgPrompt"
Where the heck does DbgPrompt come from? I'd love to be able to use it....

Rating:
16-Nov-05, Greg de Valois


Post Your Comments.
Print this article.
Email this article.

Writing WDM Drivers LAB
Seattle, WA
16-Aug-2010 to 20-Aug-2010

Writing WDF Drivers LAB
Santa Clara, CA
27-Sept-2010 to 1-Oct-2010

Kernel Debugging &
Crash Analysis LAB

Portland, OR
18-Oct-2010 to 22-Oct-2010

Developing File Systems
Santa Clara, CA
26-Oct-2010 to 29-Oct-2010

Windows Internals &
Software Drivers LAB

Santa Clara, CA
15-Nov-2010 to 19-Nov-2010

 
 

Windows Debugger
V6.12.2.633 -- 26 Feb 10

Checked Build Downloads
29-Apr-10

Debugging Symbols
5-Oct-09
 

WDK Doc Updates
Now updated bi-monthly!

Windows WDK
V7.1.0 -- 26 Feb 10

 
 
x
LetUsHelp
 

Need to develop a Windows file system solution?

We've got a kit for that.

Need Windows internals or kernel driver expertise?

Bring us your most challenging project - we can help!

System hangs/crashes?

We've got a special diagnostic team that's standing by.

Visit the OSR Corporate Web site for more information about how OSR can help!

 
bottom nav links