The MmAllocateMdlForIoSpace routine allocates an MDL and initializes this MDL to describe a set of physical address ranges in I/O address space.
NTSTATUS MmAllocateMdlForIoSpace( _In_ PMM_PHYSICAL_ADDRESS_LIST PhysicalAddressList, _In_ SIZE_T NumberOfEntries, _Out_ PMDL *NewMdl );
- PhysicalAddressList [in]
A pointer to an array of MM_PHYSICAL_ADDRESS_LIST structures that describe the physical address ranges to include in the allocated MDL.
- NumberOfEntries [in]
The number of elements in the MM_PHYSICAL_ADDRESS_LIST array pointed to by PhysicalAddressList.
- NewMdl [out]
A pointer to a location to which the routine writes a pointer to the newly allocated MDL.
MmAllocateMdlForIoSpace returns STATUS_SUCCESS if it is successful. Possible error return values include the following status codes.
A physical address is not aligned to a page boundary; or a physical address range is not a multiple of the page size; or a physical address range is used by the operating system for RAM and is not available for use as I/O space.
Insufficient system resources are available to perform the requested operation.
Do not assume that the preceding list of error return codes is exhaustive. The routine might return error codes that do not appear in the list.
This routine accepts, as an input parameter, an array of MM_PHYSICAL_ADDRESS_LIST structures that describe a set of physical address ranges in I/O address space, and allocates an MDL that describes these ranges. Consecutive physical address ranges in the array are not required to be contiguous.
The physical address ranges in the PhysicalAddressList array must satisfy the following conditions:
- The base physical address for each range must be aligned to a PAGE_SIZE boundary in memory.
- The size, in bytes, of each range must be an integer multiple of PAGE_SIZE.
- All physical address ranges must be in memory that is available for use as I/O address space. They cannot be in memory space that is used by the operating system for RAM.
- The total size of all the ranges must be less than 4 gigabytes. Specifically, the total size must not exceed 2³²-1 bytes.
The MDL that is created by MmAllocateMdlForIoSpace is not mapped to virtual memory, but can be supplied to a routine such as MapTransferEx to initiate a DMA transfer to or from the physical memory ranges described by the MDL. To map this MDL to a contiguous range of virtual addresses so that it can be accessed by the processor, call the MmMapLockedPagesSpecifyCache routine.
Only ranges of the physical address space that are not reserved by the operating system for use as memory are available to drivers for use as I/O address space. Drivers use I/O address space to access memory-mapped hardware resources such as device registers. When a driver starts, it might receive one or more physical address ranges as translated hardware resources. For more information, see Mapping Bus-Relative Addresses to Virtual Addresses.
In some processor architectures, such as the x86, devices can be either memory-mapped or mapped to port addresses in a special I/O address space that is dedicated to devices and is separate from the memory address space. Drivers can use MmAllocateMdlForIoSpace to allocate MDLs only for memory-mapped devices.
The following code example shows how to construct an array of MM_PHYSICAL_ADDRESS_LIST structures that describe the physical address ranges to include in the allocated MDL.
extern ULONG64 BasePhysicalAddress; extern SIZE_T ChunkSize; extern SIZE_T Stride; #define ARRAYSIZE(x) (sizeof(x)/sizeof((x))) NTSTATUS Status; PMDL Mdl; MM_PHYSICAL_ADDRESS_LIST AddressList; AddressList.PhysicalAddress.QuadPart = BasePhysicalAddress; AddressList.NumberOfBytes = ChunkSize; BasePhysicalAddress += Stride; AddressList.PhysicalAddress.QuadPart = BasePhysicalAddress; AddressList.NumberOfBytes = ChunkSize; BasePhysicalAddress += Stride; AddressList.PhysicalAddress.QuadPart = BasePhysicalAddress; AddressList.NumberOfBytes = ChunkSize; Status = MmAllocateMdlForIoSpace (AddressList, ARRAYSIZE(AddressList), &Mdl);
In this example, the starting physical address is specified by the
BasePhysicalAddress variable. The number of bytes in each physical address range is specified by the
ChunkSize variable. The byte offset from the start of one physical range to the start of the next is specified by the
BasePhysicalAddress must be aligned to a page boundary in memory, and
Stride must be multiples of the page size.
|Available starting with Windows 8.|