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.
| Access | Description |
| 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.
| Flag | Description |
| NOTIFY_FLAGS_NEVER | No 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 IRB | Type of notification | Driver 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_LEVEL | Below DISPATCH_LEVEL |
| Yes | IoCallDriver | IoCallDriver |
| No | Port driver's physical mapping routine | IoCallDriver |
Requirements
IRQL: See Operation section.
Headers: Defined in 1394.h. Include 1394.h.
See Also
IOCTL_IEEE1394_API_REQUEST