IoAssignResources

NTSTATUS
    IoAssignResources(

        IN PUNICODE_STRING  RegistryPath,
        IN PUNICODE_STRING  DriverClassName,        /* optional */
        IN PDRIVER_OBJECT  DriverObject,
        IN PDEVICE_OBJECT  DeviceObject,            /* optional */
        IN PIO_RESOURCE_REQUIREMENTS_LIST  RequestedResources,
        IN OUT PCM_RESOURCE_LIST  *AllocatedResources
        );

IoAssignResources takes an input list of requested hardware resources for a driver or device, claims an available set of hardware resources, such as an interrupt vector, device memory range and/or I/O port range, and possibly a particular DMA controller channel, in the \Registry\Hardware\Machine\ResourceMap tree, and returns a list of allocated hardware resources for the driver or device. As an alternative, drivers of PCI-type devices can call HalAssignSlotResources.

Parameters

RegistryPath
Points to the \Registry\Machine\System\CurrentControlSet\Services\DriverName key or one of its subkeys, depending on whether the input DeviceObject pointer is NULL. If a driver uses resources in common for all its devices, RegistryPath is the pointer input to its DriverEntry routine and the DeviceObject pointer must be NULL. A driver that needs device-specific hardware resources, rather than driver-specific resources in common for all its devices, must pass a RegistryPath pointer to an updated, device-specific string naming a subkey of DriverName, at each call to IoAssignResources with a nonNULL pointer to a unique DeviceObject.
DriverClassName
Points to a buffered Unicode string that describes the class of driver under which the driver’s configuration information should be stored. A default type Other is used if none is given, and a new key is created in the registry if a unique name is supplied.
DriverObject
Points to the driver object that was input to the DriverEntry routine.
DeviceObject
This pointer is optional. If it is NULL, the caller-supplied RequestedResources list specifies resources that the driver itself needs, possibly to control several devices that it supports. Otherwise, DeviceObject points to the driver-created device object representing a physical device for which the driver is attempting to claim device-specific hardware resources.
RequestedResources
Points to a caller-supplied list of hardware resources needed to control its device(s), which the driver has found by calling HalGetBusData, HalGetBusDataByOffset, by interrogating its device, or by some other means. The caller must allocate a buffer, which can be paged memory, for its IO_RESOURCE_REQUIREMENTS_LIST(s), defined by the following structures:
typedef struct _IO_RESOURCE_REQUIREMENTS_LIST {
    //
    // This structure identifies the location on the I/O bus of the device
    // or multifunction adapter for which the driver is supplying
    // a variable-sized IO_RESOURCE_LIST requesting specific hardware resources.
    //
    ULONG ListSize;                  // in bytes
    INTERFACE_TYPE InterfaceType;    // system-defined enum for the bus, one of
                                     // Internal, Isa, Eisa, MicroChannel, TurboChannel
                                     // or PCIBus
    ULONG BusNumber;                 // system-assigned and zero-based number of this bus
    ULONG SlotNumber;                // logical slot or location on the bus of the device
    ULONG Reserved[3];               // for system use
    ULONG AlternativeLists;          // count of alternative IO_RESOURCE_LIST
                                     // elements with IO_RESOURCE_DESCRIPTORs
    IO_RESOURCE_LIST List[1];        // contains a variable-sized array of descriptors
} IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST

A driver can supply any number of IO_RESOURCE_LIST elements, each containing IO_RESOURCE_DESCRIPTORs specifying both preferred and alternative hardware resources the driver can use, if the device or I/O bus does not constrain that driver to using a fixed range of I/O ports or device memory, a fixed bus-specific interrupt vector, and/or a particular DMA channel or port number. In particular, drivers of devices that can be configured to use alternate sets of hardware resources are expected to take advantage of this capability, although drivers of PCI-type devices can call HalAssignSlotResources instead. If IoAssignResources cannot claim a preferred set of resources, it tries an alternative set and returns the set of resources claimed as soon as it can satisfy the request with a given alternate resource list. The IO_RESOURCE_LIST structure is defined as follows:

typedef struct _IO_RESOURCE_LIST {
    USHORT Version;                  // of this structure, currently 1
    USHORT Revision;                 // of this structure, currently 1
    ULONG Count;                     // of IO_RESOURCE_DESCRIPTORs in array
    IO_RESOURCE_DESCRIPTOR Descriptors[1];
} IO_RESOURCE_LIST, *PIO_RESOURCE_LIST

Each descriptor in the IO_RESOURCE_LIST’s array specifies a single hardware resource that the driver needs, prefers, or can use as an alternative to that specified in another array element. Members of the IO_RESOURCE_DESCRIPTOR structure are described separately, following this definition of the structure itself:

typedef struct _IO_RESOURCE_DESCRIPTOR {
    UCHAR Option;
    UCHAR Type;
    UCHAR ShareDisposition;
    UCHAR Spare1;                               // reserved for system use
    USHORT Flags;
    USHORT Spare2;                              // reserved for system use

    union{
         struct {
             ULONG Length;
             ULONG Alignment;
             PHYSICAL_ADDRESS MinimumAddress;  // 8-byte, bus-relative physical address
             PHYSICAL_ADDRESS MaximumAddress;
         } Port;
         struct {
             ULONG Length;
             ULONG Alignment;
             PHYSICAL_ADDRESS MinimumAddress;  // 8-byte, bus-relative physical address
             PHYSICAL_ADDRESS MaximumAddress;
         } Memory;
         struct {
             ULONG MinimumVector;
             ULONG MaximumVector;
         } Interrupt;
         struct {
             ULONG MinumumChannel;
             ULONG MaximumChannel;
         } Dma;
     } u;
} IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR

Members

Members of the IO_RESOURCE_DESCRIPTOR structure include the following:
Option

Is set to IO_RESOURCE_PREFERRED to indicate the caller’s preferred setting for the described resource if other descriptors in the list for the same type of resource have this member set to IO_RESOURCE_ALTERNATIVE. This member should be set to zero if the resource described is fixed: that is, the caller cannot use an alternative.

Type
Specifies which of the following is contained in this descriptor: CmResourceTypePort, CmResourceTypeMemory, CmResourceTypeInterrupt, or CmResourceTypeDma.
ShareDisposition
Specifies whether or how this resource can be shared as one of the following: CmResourceShareDeviceExclusive, CmResourceShareDriverExclusive, or CmResourceShareShared.
Flags
Specifies type-dependent information about this descriptor:

· When Type is set with CmResourceTypePort, can be either of the following: CM_RESOURCE_PORT_MEMORY or CM_RESOURCE_PORT_IO.

· When Type is set with CmResourceTypeMemory, can be one of the following: CM_RESOURCE_MEMORY_READ_WRITE, CM_RESOURCE_MEMORY_READ_ONLY, or CM_RESOURCE_MEMORY_WRITE_ONLY.

· When Type is set with CmResourceTypeInterrupt, can be either of the following: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE or CM_RESOURCE_INTERRUPT_LATCHED.

u.Port
Describes a bus-relative range of device ports in I/O space, including the Length in bytes of the port range, the required byte Alignment boundary for the range, its lowest possible MinimumAddress and its highest possible MaximumAddress in the bus-relative physical address range of I/O port space. Type must be CmResourceTypePort.
u.Memory
Describes a bus-relative range of device memory in memory space, including the Length in bytes of the range, the required byte Alignment boundary for the range, its lowest possible MinimumAddress and its highest possible MaximumAddress in the bus-relative physical address range of device-memory space. Type must be CmResourceTypeMemory.
u.Interrupt
Describes a range of one or more bus-relative interrupt vectors at which the device can interrupt. Type must be CmResourceTypeInterrupt.
u.Dma
Describes a range of one or more DMA channel numbers or MCA-type DMA port numbers that the device can use. Type must be CmResourceTypeDma.
AllocatedResources
Points to the address of an uninitialized pointer. If successful, IoAssignResources resets this uninitialized pointer to a buffer it allocates for a returned CM_RESOURCE_LIST, which describes the hardware resources it allocated for the caller. The caller is responsible for freeing the buffer.

Return Value

IoAssignResources returns STATUS_SUCCESS if it claimed a set of the specified hardware resources for the caller and returned information in the AllocatedResources buffer. Otherwise, it returns an error status, resets the pointer at AllocatedResources to NULL, and logs an error if it finds a resource conflict.

Comments

For most device drivers, calling IoAssignResources after locating the device and getting whatever configuration information HalGetBusData or HalGetBusDataByOffset can supply is preferable to making paired calls to IoQueryDeviceDescription and IoReportResourceUsage.

Note that IoAssignResources does not handle IO_RESOURCE_DESCRIPTOR entries with the Type member set to CmResourceTypeDeviceSpecific. Drivers that have hardware resources of this type can call IoReportResourceUsage to store this configuration information in the \\Registry\..\ResourceMap tree. Otherwise, a successful call to IoAssignResources writes the caller’s claims on every other type of hardware resource into the registry \ResourceMap tree.

IoAssignResources automatically searches the registry for resource conflicts between resources requested and resources claimed by previously installed drivers. It first matches the preferred entries in the RequestedResources descriptor array against all other resource lists stored in the registry to determine whether a conflict exists. If it finds a conflict, it then matches any supplied alternative descriptors for the already claimed resource again, attempting to allocate a set of resources the caller can use.

The caller is responsible for releasing the AllocatedResources buffer, which is pageable, with ExFreePool after it has consumed the returned information and before the DriverEntry routine returns control.

If a driver claims resources on a device-specific basis for more than one device, the driver must call this routine at least once for each such device, and must update the RegistryPath string to supply a unique subkey name for each call with a unique DeviceObject pointer.

This routine can be called more than once for a given device or driver. If a new list of RequestedResources is supplied, it will overwrite or, possibly, be appended to the previous resource list in the registry. However, making a single call for each set of device-specific resources makes a driver load much faster than if it calls IoAssignResources many times to amend or incrementally construct the input RequestedResources for each of its devices. Note that subsequent calls to IoAssignResources can reassign the caller’s previously claimed resources if that caller does not adjust the input RequestedReources to “fix” its claim on the resources to be kept.

A driver must call IoAssignResources with a value of NULL for the RequestedResources parameter to erase its claim on resources in the registry if the driver is unloaded.

Callers of IoAssignResources must be running at IRQL PASSIVE_LEVEL.

See Also

CM_RESOURCE_LIST, ExAllocatePool, ExAllocatePoolWithTag, ExFreePool, HalAssignSlotResources, HalGetBusData, HalGetBusDataByOffset, IoReportResourceUsage, IoQueryDeviceDescription