Kernel-Mode Driver Framework

From Wikipedia, the free encyclopedia

The Kernel-Mode Driver Framework (KMDF) is a Microsoft-developed driver framework that was developed to make it easier for driver developers to create and maintain Kernel mode device drivers for Windows 2000[1] and later releases. It is one of the frameworks included in the Windows Driver Foundation. The current version is 1.5.

Contents

[edit] Relationship to WDM

In general, KMDF supports drivers that were written for the Windows Driver Model, and it runs on WDM. WDM is the driver model used for Windows 98, Windows Me, Windows 2000 and beyond, whereas KMDF is the driver framework Microsoft is planning to use for Windows 2000 and beyond.

In general, because more features like Power Management and Plug and Play are handled by the framework, a KMDF driver is less complicated and has less code than an equivalent WDM driver.

KMDF is object based, built on top of WDM. The functionality is contained in different types of objects, KMDF implementation contains of:

[edit] The driver entry point

Every driver starts with a DriverEntry function in Windows, DriverEntry is the driver entry point. In DriverEntry implementation, you need to instantiate your WDFDRIVER object, and tell the WDF framework where to call you back of your devices in system.

NTSTATUS DriverEntry(
   IN PDRIVER_OBJECT  DriverObject, 
   IN PUNICODE_STRING  RegistryPath
   )
{
 WDF_DRIVER_CONFIG config;
 NTSTATUS status = S_OK;

 KdPrint((__DRIVER_NAME "DriverEntry Begin\n"));

 WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd);
 status = WdfDriverCreate(
                     DriverObject,
                     RegistryPath,
                     WDF_NO_OBJECT_ATTRIBUTES,
                     &config, // Pointer to config structure
                     WDF_NO_HANDLE); // or NULL, Pointer to get WDFDRIVER handle
 if(!NT_SUCCESS(status))
 {
   KdPrint((__DRIVER_NAME "WdfDriverCreate failed with status 0x%08x\n", status));
 }

 KdPrint((__DRIVER_NAME "DriverEntry End\n"));

 return status;
}

[edit] Add Device

In Framework, EvtDeviceAdd event is called from the PnP manager with a handle to our WDFDRIVER object, and a pointer to a WDFDEVICE_INIT structure. Before the device created, the driver needs to configure the device initialization.

WDFSTATUS DioEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{
 WDFSTATUS status = STATUS_SUCCESS;
 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
 WDF_OBJECT_ATTRIBUTES objAttributes;
 WDFDEVICE device;
 PDIO_DEVICE_CONTEXT devContext;
 WDF_IO_QUEUE_CONFIG ioCallbacks;
 WDF_INTERRUPT_CONFIG interruptConfig;
 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;

 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
 pnpPowerCallbacks.EvtDevicePrepareHardware = DioEvtPrepareHardware;
 pnpPowerCallbacks.EvtDeviceReleaseHardware = DioEvtReleaseHardware;
 pnpPowerCallbacks.EvtDeviceD0Entry= DioEvtDeviceD0Entry;
 pnpPowerCallbacks.EvtDeviceD0Exit = DioEvtDeviceD0Exit;
 
 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, pnpPowerCallbacks);

 WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes);

 WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes, DIO_DEVICE_CONTEXT);

 status = WdfDeviceInitUpdateName(DeviceInit, L"\\device\\WDFDIO");

 status = WdfDeviceCreate(&DeviceInit,    // Device Init structure
                          &objAttributes, // Attributes for WDF Device
                          &device);       // return new WDF Device pointer, 

 devContext = DioGetContextFromDevice(device); // Get device extension

 devContext->WdfDevice = device;

 // Create a symbolic link for the control object 
 status = WdfDeviceCreateSymbolicLink(device, L"\\DosDevices\\WDFDIO");

 WDF_IO_QUEUE_CONFIG_INIT(&ioCallbacks,
                            WdfIoQueueDispatchSerial,
                            WDF_NO_EVENT_CALLBACK,     // StartIo
                            WDF_NO_EVENT_CALLBACK);    // CancelRoutine

 ioCallbacks.EvtIoDeviceControl = DioEvtDeviceControlIoctl;
 status = WdfDeviceCreateDefaultQueue(device,
                                       &ioCallbacks,
                                       WDF_NO_OBJECT_ATTRIBUTES,
                                       NULL); // pointer to default queue

 WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,       // Configure the Interrupt object
                           DioIsr,                 // ISR
                           DioDpc);                // Deferred Procedure Call

 interruptConfig.EvtInterruptEnable  = DioEvtInterruptEnable;
 interruptConfig.EvtInterruptDisable = DioEvtInterruptDisable;

 status = WdfInterruptCreate(device,
                             &interruptConfig,
                             &objAttributes,
                             &devContext->WdfInterrupt);
 
 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings,  // Initialize idle policy
                                             IdleCannotWakeFromS0);

 status = WdfDeviceUpdateS0IdleSettings(device, &idleSettings);

 return status;
}

[edit] Prepare Hardware

If the EvtDeviceAdd function has succeeded, EvtDevicePrepareHardware is the next function, to make sure that the driver can access the hardware, that will be called by the framework.

NTSTATUS EvtDevicePrepareHardware(
   IN WDFDEVICE    Device,
   IN WDFCMRESLIST ResourceList,
   IN WDFCMRESLIST ResourceListTranslated
   )
{
 NTSTATUS status = STATUS_SUCCESS;

 UNREFERENCED_PARAMETER(Device);
 UNREFERENCED_PARAMETER(ResourceList);
 UNREFERENCED_PARAMETER(ResourceListTranslated);

 return status;
}

EvtDeviceD0Entry is first called, after EvtDevicePrepareHardware has been called. EvtDeviceD0Entry function is responsible for starting the activities that the driver is supposed to perform. The EvtDeviceD0Exit function performs actions that are the opposite of the EvtDeviceD0Entry function.

NTSTATUS EvtDeviceD0Entry(
   IN WDFDEVICE  Device,
   IN WDF_POWER_DEVICE_STATE  PreviousState
   )
{
 NTSTATUS status = STATUS_SUCCESS;
 
 return status;
}

NTSTATUS EvtDeviceD0Exit(
   IN WDFDEVICE  Device,
   IN WDF_POWER_DEVICE_STATE  TargetState
   )
{
 NTSTATUS status = STATUS_SUCCESS;

 return status;
}

[edit] IO requests

There is only one IO handler was registered, EvtDeviceIoDefault would be built , when default IO queue was created. The EvtDeviceIoDefault function will accept any request, and will fail because no IO functionality has yet been implemented.

VOID EvtDeviceIoDefault(
   IN WDFQUEUE  Queue,
   IN WDFREQUEST  Request
   )
{
 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
}

[edit] See also

[edit] Notes

  1. ^ The original release of KMDF only supported Windows XP and Server 2003. Support for Windows 2000 was added in KMDF version 1.1.

[edit] References

In other languages