Windows Driver Kit: Buses
REQUEST_ALLOCATE_ADDRESS_RANGE

The REQUEST_ALLOCATE_ADDRESS_RANGE request allocates addresses in the computer's IEEE 1394 address space.

The relevant members of the IRB for this request are:

typedef struct _IRB {
  ULONG FunctionNumber;
    .
    .
    .
  union {
    struct {
      PMDL            Mdl;
      ULONG           fulFlags;
      ULONG           nLength;
      ULONG           MaxSegmentSize;
      ULONG           fulAccessType;
      ULONG           fulNotificationOptions;
      PVOID           Callback;
      PVOID           Context;
      ADDRESS_OFFSET  Required1394Offset;
      PSLIST_HEADER   FifoSListHead;
      PKSPIN_LOCK     FifoSpinLock;
      ULONG           AddressesReturned;
      PADDRESS_RANGE  p1394AddressRange;
      HANDLE          hAddressRange;
      PVOID           DeviceExtension;
    } AllocateAddressRange;
    .
    .
    .
  } u;
} IRB;

IRB Input

FunctionNumber
REQUEST_ALLOCATE_ADDRESS_RANGE
u.AllocateAddressRange.Mdl
If non-NULL, points to the MDL that describes the application's buffer where asynchronous operations are to be read, written, or locked. The memory for the MDL must be allocated from nonpaged pool or locked down by means of a call to MmProbeAndLockPages. If the driver specifies u.AllocateAddressRange.Mdl, then u.AllocateAddressRange.FifoSListHead and u.AllocateAddressRange.FifoSpinLock must be NULL.
u.AllocateAddressRange.fulFlags
Specifies whether the array entries in p1394AddressRange use big-endian byte order. If the caller specifies BIG_ENDIAN_ADDRESS_RANGE, the array entries are in big-endian byte order (the native byte order of the IEEE 1394 protocol), even if the local host is a little-endian machine. In order to specify a little-endian address range, the caller must explicitly guarantee that the BIG_ENDIAN_ADDRESS_RANGE flag is not set using a statement similar to the following:
fulFlags = fulFlags & ~(0x0ffffffff & BIG_ENDIAN_ADDRESS_RANGE)
u.AllocateAddressRange.nLength
Specifies the number of the IEEE 1394 addresses to allocate.
u.AllocateAddressRange.MaxSegmentSize
Specifies the maximum size for each range of addresses that the bus driver allocates. Use zero to indicate that the driver does not have a required maximum segment size. If a nonzero value is specified for MaxSegmentSize, the value must be less than 64 KB (65,536 bytes). In other words, it must be less than or equal to 65,535 (0xFFFF) due to the fact that the address range size is stored in a 16-bit word. This member is ignored if u.AllocateAddressRange.Required1394Offset is non-NULL.
u.AllocateAddressRange.fulAccessType
Specifies access type using one or more of the following flags.
AccessDescription
ACCESS_FLAGS_TYPE_READ Allocated addresses can be read.
ACCESS_FLAGS_TYPE_WRITE Allocated addresses can be written to.
ACCESS_FLAGS_TYPE_LOCK Allocated addresses can be the target of a lock operation.
ACCESS_FLAGS_TYPE
_BROADCAST
Allocated addresses can receive asynchronous I/O requests from any node on the bus. (By default, only the device driver's device can send requests to the allocated addresses).

Special considerations apply to drivers of virtual devices. Virtual devices do not have node IDs, and so when a driver sends a request to a virtual device, the bus driver has no means of identifying which device is the target. Thus in order for a virtual device to receive requests, its driver must allocate a range of addresses with the ACCESS_FLAGS_TYPE_BROADCAST flag set in fulAccessType. This permits the virtual device to receive all request packets, no matter what node ID is indicated in the request packet.

u.AllocateAddressRange.fulNotificationOptions
If the device driver requests that the bus driver handle each request, and notifies the device driver upon completion, this specifies which asynchronous I/O request types will trigger the bus driver to the notify the device driver upon completion. See the Operation section for more details. The driver may specify one or more of the NOTIFY_FLAGS_AFTER_XXX flags.
FlagDescription
NOTIFY_FLAGS_NEVERNo notification.
NOTIFY_FLAGS_AFTER_READ Notify the device driver after carrying out an asynchronous read operation.
NOTIFY_FLAGS_AFTER_WRITE Notify the device driver after carrying out an asynchronous write operation.
NOTIFY_FLAGS_AFTER_LOCK Notify the device driver after carrying out an asynchronous lock operation.

u.AllocateAddressRange.Callback
Points to a device driver callback routine. If the device driver specifies that the bus driver notify the device driver for each asynchronous I/O request, u.AllocateAddressRange.Callback points to the device driver's notification routine, which must have the following prototype:

VOID DriverNotificationRoutine(IN PNOTIFICATION_INFO );

If the device driver specifies that it receives no notification, and submits this request at raised IRQL through the port driver's physical mapping routine, then u.AllocateAddressRange.Callback points to the device driver's allocation completion routine, which must have the following prototype:

VOID AllocationCompletionRoutine( IN PVOID );

Drivers that do not request notification, and submit this request in the normal way at PASSIVE_LEVEL, must set this member to NULL.

u.AllocateAddressRange.Context
Points to any context data that that the device driver wants to pass for this set of addresses. If the provided callback (see previous) is a notification routine, the bus driver passes u.AllocateAddressRange.Context within the NOTIFICATION_INFO the parameter. If the callback is an allocation completion routine, the bus driver passes u.AllocateAddressRange.Context as the sole parameter to the routine.
u.AllocateAddressRange.Required1394Offset
Specifies a hard-coded address in the computer's IEEE 1394 address space. The bus driver allocates the addresses beginning at u.AllocateAddressRange.Required1394Offset. If no specific address is required, the driver should fill in each member of the ADDRESS_OFFSET with zero. The bus driver then chooses the addresses to allocate.
u.AllocateAddressRange.FifoSListHead
If non-NULL, specifies a properly initialized (for example, by ExInitializeSListHead) interlocked, singly-linked list of ADDRESS_FIFO elements. Each ADDRESS_FIFO contains an MDL. As the bus driver handles each incoming write request to the allocated addresses, it pops off the first element on the list and writes incoming data to the MDL. It then calls the driver's notification routine.

Each MDL provided must only span one page in memory. The driver can add or remove elements from the ADDRESS_FIFO list by using ExInterlockedPushEntrySList and ExInterlockedPopEntrySList.

If this member is non-NULL, the Mdl member of u.AllocateAddress range must be NULL, the fulNotificationFlags member must be NOTIFY_FLAGS_AFTER_WRITE (no other flags must be specified), and the driver must provide a spin lock in FifoSpinLock. This implies that the order in which packets are filled and returned is guaranteed to be based on a FIFO algorithm. In fact, this SLIST-based mechanism acts more like a stack, or Last-In-First-Out (LIFO).

u.AllocateAddressRange.FifoSpinLock
If non-NULL, specifies a properly initialized spin lock (for example, by KeInitializeSpinLock). The spin lock is used to serialize access to the SList provided in u.AllocateAddressRange.FifoSListHead.

The u.AllocateAddressRange.FifoSpinLock member is non-NULL if and only if u.AllocateAddressRange.FifoSListHead is non-NULL as well.

u.AllocateAddressRange.p1394AddressRange
Points to an array of ADDRESS_RANGE structures. The array must be large enough to hold the maximum number of structures the bus driver can return.

If the driver specifies a required address offset, or if the driver does not provide any backing store, the bus driver only returns one address range. If the driver provides backing store in u.AllocateAddressRange.Mdl the bus driver segments the allocated addresses along physical memory boundaries. If the MaxSegmentSize of u.AllocateAddressRange is 0, or if MaxSegmentSize is bigger than the page size, the driver can use the ALLOCATE_AND_SIZE_TO_SPAN_PAGES macro to determine the worst case. Otherwise, the maximum number of addresses ranges returned by the bus driver is u.AllocateAddressRange.nLength / u.MaxSegmentSize. If a nonzero value is specified for MaxSegmentSize, the value must be less than 64 KB (65,536 bytes). In other words, it must be less than or equal to 65,535 (0xFFFF) due to the fact that the address range size is stored in a 16-bit word.

u.AllocateAddressRange.DeviceExtension
Reserved.

IRB Output

u.AllocateAddressRange.AddressesReturned
Specifies the number of ADDRESS_RANGE structures returned in the p1394Address member.
u.AllocateAddressRange.p1394AddressRange
If the request is successful, this points to an array of ADDRESS_RANGE structures that describe the set of address ranges allocated to fulfill this request.
u.AllocateAddressRange.hAddressRange
If the request is successful, this specifies the handle to use when freeing the allocated address ranges with the REQUEST_FREE_ADDRESS_RANGE request.

I/O Status Block

The bus driver sets Irp->IoStatus.Status to STATUS_SUCCESS on success, or the appropriate error code on failure.

Operation

If the driver provides an address in u.AllocateAddressRange.Required1394Offset, the bus driver allocates one contiguous range of addresses, beginning at that address. Otherwise, the bus driver allocates several ranges of addresses to fulfill the request.

Asynchronous I/O packets sent to the allocated address range are received by the bus driver. What the bus driver does with the packet depends on settings in the IRB when it is submitted. These settings also determine when the bus driver notifies the client driver of the operation and whether the client driver or the bus driver sends the response packet.

There are three types of notification used by the bus driver to inform the client that it has received a packet:

  • No-notification - the bus driver does not notify the client that it has received a request packet.
  • Postnotification - the bus driver handles the request packet, then notifies the client that it has received a request.
  • Prenotification - the bus driver, does not handle the request, but rather passes it to the client upon receiving it.

The following table explains how the bus driver and the client share responsibility for handling request and response packets.

Values of fields in address allocation IRBType of notificationDriver responsible for sending response packet
Case 1:

Mdl != NULL

fulNotificationFlags = NOTIFY_FLAGS_NEVER

No notification

(Bus driver handles request packets transparently, no prenotifications or postnotifications).

Bus driver
Case 2:

Mdl != NULL

fulNotificationFlags = one or more of NOTIFY_FLAGS_AFTER_XXX

FifoSListHead = NULL FifoSpinLock = NULL

Postnotification

(Bus driver handles request packet, then notifies the client driver upon completion using the client's callback routine).

Bus driver
Case 3:

Mdl = NULL

FifoSListHead != NULL FifoSpinLock != NULL

fulNotificationFlags = NOTIFY_FLAGS_AFTER_WRITE

Postnotification
(Bus driver handles request packet, then notifies the client driver upon completion using the client's callback routine).
Bus driver
Case 4:

Mdl = NULL

FifoSListHead = NULL

FifoSpinLock = NULL



Prenotification

(Client handles the request packet. Instead of using the callback routine to send a notification, the bus driver uses the callback routine to pass the request packet to the client driver. In this case, the client driver must also send its own response packet).

Client driver

The following is a detailed description of the four cases listed in the preceding table:

  • Case 1: The bus driver transparently handles the request packet by reading or writing data using the MDL. The device driver receives no notification. For this setting, the bus driver allocates the address range asynchronously. Upon completion, it calls the allocation completion routine that the driver passed in u.AllocateAddressRange.Callback. As a parameter, it passes u.AllocateAddressRange.Context. This form of REQUEST_ALLOCATE_ADDRESS_RANGE can only be submitted in the normal way at IRQL PASSIVE_LEVEL. At raised IRQL, the driver can submit the IRB directly to the port driver through a special interface. See the following discussion for details.
  • Case 2: The bus driver handles the request packet by reading or writing data using the MDL. After each request type specified by NOTIFY_FLAGS_AFTER_XXX, the bus driver calls the driver's notification routine (passed in u.AllocateAddressRange.Callback), and passes a description of the operation in NOTIFICATION_INFO. See NOTIFICATION_INFO for details. Drivers can submit this form of REQUEST_ALLOCATE_ADDRESS_RANGE at any IRQL.
  • Case 3: The bus driver acquires the spin lock, pops the first element off the list, and uses the MDL to handle the request packet. It then calls the driver's notification routine (passed in u.AllocateAddressRange.Callback), and passes a description of the operation in NOTIFICATION_INFO. See NOTIFICATION_INFO for details. Drivers can submit this form of REQUEST_ALLOCATE_ADDRESS_RANGE at any IRQL.
  • Case 4: The bus driver passes the request packet in the NOTIFICATION_INFO parameter of the driver's notification routine (passed in u.AllocateAddressRange.Callback). The device driver must provide the response packet. See NOTIFICATION_INFO. The NOTIFY_FLAGS_XXX flags are ignored. The bus driver ignores the setting of u.AllocateAddressRange.MaxSegmentSize, and always returns a contiguous range of addresses. Drivers can submit this setting of REQUEST_ALLOCATE_ADDRESS_RANGE at any IRQL.

REQUEST_ALLOCATE_ADDRESS_RANGE can be submitted through IoCallDriver at any IRQL, with one exception. If the driver receives no notification (u.AllocateAddressRange.Mdl is non-NULL and u.AllocateAddressRange.fulNotificationFlags is NOTIFY_FLAGS_NEVER), the request can only be submitted through IoCallDriver at PASSIVE_LEVEL.

In this specific circumstance, the driver can submit the request through an alternative method, the port driver's physical mapping routine. The device driver can hand off the IRB directly to the physical mapping routine. Drivers can get a pointer to the physical mapping routine by submitting the REQUEST_GET_LOCAL_HOST_INFO bus request with nLevel = GET_PHYS_ADDR_ROUTINE. See GET_LOCAL_HOST_INFO4 for details.

The following table explains how to submit the request at different IRQLs.

Notification?DISPATCH_LEVELBelow DISPATCH_LEVEL
YesIoCallDriverIoCallDriver
NoPort driver's physical mapping routineIoCallDriver

Requirements

IRQL: See Operation section.

Headers: Defined in 1394.h. Include 1394.h.

See Also

IOCTL_IEEE1394_API_REQUEST


Send feedback on this topic
Built on November 19, 2009
Page view tracker