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:
- Plug and Play and power management
- I/O queues
- Direct memory access (DMA)
- Windows Management Instrumentation (WMI)
- Synchronization
[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
- ^ The original release of KMDF only supported Windows XP and Server 2003. Support for Windows 2000 was added in KMDF version 1.1.