- Bus Drivers, responsible for enumerating the devices on the bus. Device object associated with this kind of driver is Physical Device Object (PDO).
- Function Drivers, responsible for handling read , write, and device power policies for the devices. These drivers provide operational interface for its devices. Device object associated with this kind of driver is Functional device Object (FDO).
- Filter Drivers, to add additional value for the devices. Device object associated with this kind of driver is Filter Device Object (Filter DO). These are optional drivers.
Typical Windows device driver code will have
DriverEntry(), AddDevice()
, I/O Request Packet routines like IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_READ, IRP_MJ_WRITE
and DriverUnload()
.DriverEntry:
A driver's entry point is through the DriverEntry routine.The IO Manager calls the DriverEntry as soon as the driver is loaded.
Syntax:
where XXXX is a user specified name eg. GdpDispatchCreate.
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
DriverObject->MajorFunction[IRP_MJ_CREATE] = XXXXDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = XXXXDispatchClose;
DriverObject->MajorFunction[IRP_MJ_PNP] = XXXXDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = XXXXDispatchPower;
DriverObject->MajorFunction[IRP_MJ_READ] = XXXXDispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = XXXXDispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = XXXXDispatchDeviceControl;
DriverObject->DriverUnload = XXXXUnload;
DriverObject->DeviceExtension->AddDevice = XXXXAddDevice;
}
The DriverEntry gets pointer to its own driver object (DriverObject).DriverEntry initializes entry points for other routines of the driver and stores their pointers in the DriverObject. DriverEntry also initializes DriverUnload routine and AddDevice routine.
AddDevice:
Syntax:
AddDevice routine is called after the devices get enumerated. AddDevice routine is like a DriverEntry for Plug and Play (PNP). AddDevice routine is responsible for creating Device Objects for the devices enumerated by the PNP Manager This routine calls
NTSTATUS XXXXAddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject)
{
//.....
}
IoCreateDevice
and IoCreateSymbolicLink
and IoAttachDeviceToDeviceStack
functions mainly. IoCreateDevice
function creates Device Object.It returns pointer to the Device Object. After creating the Device Object IoCreateSymbolicLink
function is used to create link between the device object name and the user visible name of the device so that the device is visible to Win32. IoAttachDeviceToDeviceStack
function is used to attach the device object created by IoCreateDevice to the stack. DriverUnload :
Syntax:
Unload routine checks if the device object is deleted or not.It frees up any memory allocated in the driver entry time.Unload routine gets called when the driver is Unloaded or reloaded or replaced with another driver or by the PNP Manager when there are no more device objects after
NTSTATUS XXXXUnload(PDRIVER_OBJECT DriverObject)
{
//…………..
}
IRP_MN_REMOVE_DEVICE
is called . Apart from DriverUnload and AddDevice rest all routines initialised in DriverEntry share same signature.
NTSTATUS XXXX(PDEVICE_OBJECT DeviceObject, PIRP Irp);
IRP_MJ_CREATE :
Syntax:
This IRP is called when
NTSTATUS XXXXDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
CreateFile
function is called to open a handle to file object or a device object.Win32 makes a call to CreateFile
function.Most of the drivers set STATUS_SUCCESS in the IO block and complete the request but this irp can be used to reserve any subsequent IO requests for that handle. The functionality implimented is based on the driver. All dispatch routines must make a call to the function IoGetCurrentIrpStackLocation
to get driver’s associate stack location. Also all dispatch routines must to fill out the PIRP
and complete the routine through IoCompleteRequest
.
PIRP can be filled as below:
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp,IO_NO_INCREMENT);
IRP_MJ_CLOSE :
Syntax:
This IRP is called when
NTSTATUS XXXXDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
CloseHandle
function is called to close the handle created by CreateFile
function.Win32 makes a call to CloseHandle
function.Most of the drivers set STATUS_SUCCESS in the IO block and complete the request .Additional functionality implimented will be dependent on the driver.Mostly it undos what ever is done by IRP_MJ_CREATE
with CreateFile
function. IRP_MJ_PNP:
Syntax
This IRP is called by the PnP manager during enumeration or device rebalancing or any other tine plug and play activity occurs.
NTSTATUS XXXXDispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
Plug-n-Play (PNP) is acombination of hardware and softawre support that enables a computer to recognize and adapt to new hardware configuration change with little or no user intervension (i.e) user can add or remove devices at run time.
PNP's main responsibilities:
- Automatic detection of hardware installation changes
- Loading appropriate drivers during run time.
When a device is added to the system at run time some of the steps to be taken care of can be describe briefly as:
- The user plugs in the device in a free slot
- Function driver on the bus determines that there is a new device on the bus
- Function driver notifies the PNP Manager about the new device addition
- PNP manager send an IRP and the function driver of the bus handles the IRP and creates the PDO for the new device.
- PNP manager gathers the information about the device through various IRPs and stores the information in the registry.
- User mode setup components call kernel mode to help them call AddDevice routine.
- PNP manager helps call the drivers DriverEntry and attaches the device to the stack
- Resources necessary for the device are added and the device is started.
PnP has minor functions to support each PnP request accordingly. Few of the required function codes are:
IRP_MN_START_DEVICE
IRP_MN_QUERY_REMOVE_DEVICE
IRP_MN_REMOVE_DEVICE
IRP_MN_CANCEL_REMOVE_DEVICE
IRP_MN_QUERY_STOP_DEVICE
IRP_MN_ STOP_DEVICE
IRP_MN_CANCEL_STOP_DEVICE
IRP_MN_SURPRISE_REMOVAL
IRP_MN_START_DEVICE:
PNP Manager sends this IRP after it has assigned hardware resources to the device.The device may have been recently enumerated and is being started for the very first time or is restarting after being stopped. It an also be sent when driver currently in use requires new set of resources.
IRP_MN_QUERY_REMOVE_DEVICE:
This IRP is sent to query if the device if the device can be removed with out disturbing the system. In response to this IRP drivers inform whether the device can be removed or not.
IRP_MN_REMOVE_DEVICE:
This IRP is used to remove to device’s software representations like device object from the system. This IRP is called when the device is removed in orderly fashion or plugged out with out prior notification or when the driver needs an update.
IRP_MN_CANCEL_REMOVE_DEVICE:
This IRP is sent to inform the driver that the device will not be removed from the system. The status prior to the IRP_MN_QUERY_REMOVE_DEVICE will be restored in this case.
IRP_MN_QUERY_STOP_DEVICE:
This IRP is sent to query whether a device can be stopped to rebalance the resources. In response to this IRP the device informs if it is safe to stop the device or not.
IRP_MN_ STOP_DEVICE:
This IRP is sent to stop the device to reconfigure the hardware resources. In response to this IRP driver stops the device and releases the hardware resources being used by the device.
IRP_MN_CANCEL_STOP_DEVICE:
This IRP is sent to inform the driver that the device will not be stopped for rebalancing of the resources. In response to this IRP the driver must return the device to the started state.
IRP_MN_SURPRISE_REMOVAL:
This IRP is sent to the drivers for a device to inform that the device is no longer available for I/O operations. This may happen for reasons like:-
- The bus has hot-plug notification and it notifies the device's parent bus driver that the device has disappeared.
- When the bus is enumerated the surprise removed device will not be there on the bus.
In response to this IRP, Some of the steps to be taken care of are:PoSetPowerState
and power down the bus slot of the device if possible IRP_MN_REMOVE_DEVICE
must be called.
IRP_MJ_POWER :
Syntax
Power manager can send this IRP any time the operating system is running. System power ranges from S0 to s5 and Device power state ranges from D0 to D3. Higher the number lowers the power consumption in either of the cases.
NTSTATUS XXXXDispatchPower(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
The minor IRPs supported by this IRP are:
IRP_MN_POWER_SEQUENCE
IRP_MN_SET_POWER
IRP_MN_WAIT_WAKE
IRP_MN_QUERY_POWER
IRP_MN_POWER_SEQUENCE:
This IRP is for optimization and is sent to determine whether its device actually entered a specific power state or not. IRP returns the power sequence values for the device.
IRP_MN_SET_POWER:
This IRP is sent to notify the drivers of the change to the system power state or to change the power state of a device for which the power manager is performing idle detection. PoRequestPowerIrp
must be called to send this IRP.
IRP_MN_WAIT_WAKE:
This IRP is used to awaken a system/device from sleep state.
IRP_MN_QUERY_POWER:
This IRP is sent to query whether the system power state or the device power state can be changed.PoRequestPowerIrp
must be called to send this IRP.
IRP_MJ_DEVICE_CONTROL :
Syntax
NTSTATUS XXXXDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
Every driver whose device objects belong to a particular device type and has a set of system-defined I/O control codes (IOCTLs) support this IRP. A driver receives this I/O control code because user-mode thread has called the Microsoft Win32 DeviceIoControl
function, or a higher-level kernel-mode driver has set up the request. On receipt of a device I/O control request for most I/O control codes, device drivers transfer a small amount of data to or from the buffer.
IRP_MJ_READ :
Syntax
If the driver needs to transfers data from its device to the system it must handle read requests through this IRP. It can also be invoked when a user application or Win32 requested data transfer from the device.
NTSTATUS XXXXDispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
IRP_MJ_WRITE :
Syntax
This IRP is sent by IO manager and is invoked when Win32 calls functions such as
NTSTATUS XXXXDispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//…………
}
WriteFile
.
References:
Windows® 2000 Device Driver Book: A Guide for Programmers, Second Edition
MSDN
___________________
Technorati tags:
Win32 | Windows | WDM | Device Drivers | Programming
No comments:
Post a Comment