5.2.1 Device Driver's Initialization

The DriverEntry routine of an NT device driver should initialize in the following stages:

1.Allocate memory to hold the hardware configuration information necessary to communicate with its device(s).

2.Gather hardware configuration information for the physical device(s) from the registry, from the I/O bus(es) in the machine, and/or by interrogating the device on the bus; otherwise, the driver must supply a set of default hardware configuration values for its device(s).

3.Set the driver's Dispatch, StartIo (if any), and Unload (if any) entry points in the given driver object.

4.Attempt to claim the hardware resources that the driver uses to carry out device I/O operations, such as device memory, bus-relative interrupt vector, and so forth, in the registry.

5.If the driver can claim the hardware resources it needs in the registry, initialize the physical device(s) and set up the NT objects and any other resources, such as spin locks, that the driver will use to process device I/O requests.

6.If the driver succeeds in initializing its device(s) and setting up all the resources it needs to process IRPs to its device(s), free the memory it allocated to hold configuration information, or possibly call IoRegisterDriverReinitialization passing a Context pointer to the configuration information, and return STATUS_SUCCESS.

Otherwise, free any objects and system resources it allocated, including the memory it used to hold configuration information, and return an appropriate NTSTATUS error.

Every NT device driver writer should consider the following guidelines when implementing a DriverEntry routine:

·Never attempt to initialize a physical device without claiming the necessary bus-relative I/O ports, memory ranges, interrupt, and/or DMA channel/port hardware resources in the registry first.

Every NT device driver must call IoAssignResources, IoReportResourceUsage, or HalAssignSlotResources and attempt to claim the bus-relative hardware resources for a device before the driver attempts to initialize that device. If there is no conflicting claim on the given hardware resources, the driver's claims are written in the \Registry\Machine\Hardware\ResourceMap tree.

Claiming hardware resources in the registry prevents resource conflicts between NT drivers and between devices in the machine. In other words, a successful claim on a set of hardware resources prevents a subsequently loaded driver from "stealing" an already loaded driver's hardware resources and from resetting that driver's already initialized device.

·Hardware resource specifications written under the registry \ResourceMap tree are the bus-relative "physical" range, interrupt, and/or DMA values returned by IoQueryDeviceDescription, HalGetBusData, HalGetBusDataByOffset, or similar driver-supplied bus-relative values. They are not the mapped system values returned by HalTranslateBusAddress and/or MmMapIoSpace that a driver can use to communicate with its device, nor the mapped vector/IRQL returned by HalGetInterruptVector that the driver uses to register its ISR with IoConnectInterrupt.

·An NT device driver's ISR should be capable of determining whether it has been called with a spurious interrupt even during the driver's initialization. On return from the DriverEntry's call to IoConnectInterrupt, the ISR can be called immediately if interrupts are enabled on the device or if the driver shares a vector or IRQL with other devices.

·Because the DriverEntry routine runs in a system thread context at IRQL PASSIVE_LEVEL, any memory allocated with ExAllocatePool for use exclusively during initialization can be from paged pool, as long as the driver does not control the device that holds the system page file. Such a memory allocation must be released with ExFreePool before DriverEntry returns control unless the driver passes a pointer to this memory in a call to IoRegisterDriverReinitialization, making the driver's Reinitialize routine responsible for freeing the memory allocation.

·If the driver has a Reinitialize routine, its DriverEntry routine must not call IoRegisterDriverReinitialization unless it will return STATUS_SUCCESS.