16.8.3.1 Calling IoReportResourceUsage

Figure 16.9 illustrates a device driver’s call to IoReportResourceUsage.

Figure 16.9 Claiming Hardware Resources with IoReportResourceUsage

As Figure 16.9 shows, each resource list that an NT driver writes into the registry under \Registry\Machine\Hardware\ResourceMap is a variable-sized array of CM_RESOURCE_DESCRIPTOR elements, containing the same information in the same form as shown in Figure 16.7.

In other words, values supplied for the driver or for each of its devices when it calls IoReportResourceUsage must specify the same CM_PARTIAL_RESOURCE_DESCRIPTOR Port, Interrupt, Memory, and Dma “hardware” values obtained from the driver’s call(s) to IoQueryDeviceDescription or by some other means.

A device driver frequently must supplement the information returned by IoQueryDeviceDescription, particularly with DeviceSpecificData, for each of its devices. For example, a floppy controller driver would fill in DeviceSpecificData information about the maximum density and mount density for each of the floppy drives it controlled, while a serial device driver would fill in information about the maximum baud clock for each of its serial ports. The system defines DeviceSpecificData structures for many kinds of peripheral devices, but an NT driver writer can define a new structure for any new device driver.

Making Calls to IoReportResourceUsage

When it calls IoReportResourceUsage, an NT device driver must supply the OverrideConflict and ConflictDetected parameters shown in Figure 16.9. The driver also must supply nonNULL and nonzero values for at least one of the following sets of parameters:

In general, the resource descriptors at DriverList specify those hardware resources that the driver uses in common for all its devices. The resource descriptors at DeviceList specify those used for a particular device. An NT driver must call IoReportResourceUsage more than once if the physical devices it controls each use device-dedicated hardware resources or if these physical devices do not have identical values for DeviceSpecificData.

While the DriverClassName parameter to IoReportResourceUsage can be NULL, such a Unicode string determines whether the driver’s resource lists are written under a registry key that is named according to the type of device, such as \Registry\Machine\Hardware\ResourceMap\Video, or under the default key (...\Other). If a named key already exists for a new driver’s type of device, the driver writer should supply the appropriate Unicode string at DriverClassName when that driver calls IoReportResourceUsage. In addition, the driver writer should have the driver store its \Registry\Machine\Hardware\DeviceMap information, if any, under the key with the same name.

The DriverClassName parameter is also passed in calls to IoAssignResources and HalAssignSlotResources.

When an NT driver for an entirely new kind of peripheral device supplies a unique string at DriverClassName, IoReportResourceUsage (as well as IoAssignResources or HalAssignSlotResources) creates a new key with that name in the registry. The designer of such a driver should create a generic device-type name, and should use the same name for the driver’s key, if it creates one, under \Registry\Machine\Hardware\DeviceMap.

Handling Resource Conflicts

The Boolean value returned to the driver at ConflictDetected indicates whether it has attempted to claim a hardware resource that another device driver already claimed. When such a hardware resource conflict occurs, the driver that “found” the conflict should log an error, as described in Section 16.6.

If its device can be reconfigured dynamically, the driver that finds a resource conflict can rebuild the offending resource list and call IoReportResourceUsage again to overwrite its “conflicted” value entries under \Registry\Machine\Hardware\ResourceMap. However, for the driver of such a device, calling HalAssignSlotResources or IoAssignResources, as described in Section 16.8.3.2, is more efficient that calling IoReportResourceUsage repeatedly to loop through a set of alternative resource lists.

The OverrideConflict parameter to IoReportResourceUsage is a value of type BOOLEAN, which should be set to FALSE. If IoReportResourceUsage detects a conflict and OverrideConflict was set to FALSE, this support routine logs an error showing the exact cause of the conflict (memory locations or interrupt) and which driver was not loaded due to the resource conflict. IoReportResourceUsage does not write such a caller’s resources into the registry, but a system administrator or user then can determine why a particular device is not working by using the Win32 event viewer to examine the entries in the NT error log file.

When OverrideConflict is set to TRUE in a call to IoReportResourceUsage, the driver’s resource lists are written into the registry under the \Registry\Machine\Hardware\ResourceMap key even if another driver has already claimed a resource in this driver’s resource lists. If such a conflict exists, the driver that loads later does not override the other driver’s claim on the hardware resource itself, nor does IoReportResourceUsage log a resource-conflict error.

Releasing Resources

If IoReportResourceUsage returns TRUE at ConflictDetected and a driver cannot carry out I/O operations without the specified hardware resources, the DriverEntry routine must release every system resource it has set up (free memory it has allocated, disconnect its interrupt objects, delete its device objects, and so forth), because that driver will be unloaded when its DriverEntry routine returns control, before the driver’s Reinitialize routine, if any, is called.

When an NT driver’s Unload routine is called, it must call IoReportResourceUsage one or more times with the DriverList and/or DeviceList CM_RESOURCE_LIST in which the Count is set to zero or call IoAssignResources with appropriate parameters, as described in Section 16.8.3.2. Such a call removes the driver’s resource list from the registry, releasing the resource(s) it claimed in its DriverEntry routine. For more information about the Unload routine, see Chapters 4 and 15.