MmAllocateMdlForIoSpace 関数 (wdm.h)
MmAllocateMdlForIoSpace ルーチンは、MDL を割り当て、この MDL を初期化して、I/O アドレス空間内の物理アドレス範囲のセットを記述します。
構文
NTSTATUS MmAllocateMdlForIoSpace(
[in] PMM_PHYSICAL_ADDRESS_LIST PhysicalAddressList,
[in] SIZE_T NumberOfEntries,
[out] PMDL *NewMdl
);
パラメーター
[in] PhysicalAddressList
割り当てられた MDL に含める物理アドレス範囲を記述する MM_PHYSICAL_ADDRESS_LIST構造体の 配列へのポインター。
[in] NumberOfEntries
PhysicalAddressList が指すMM_PHYSICAL_ADDRESS_LIST配列内の要素の数。
[out] NewMdl
ルーチンが新しく割り当てられた MDL へのポインターを書き込む場所へのポインター。
戻り値
MmAllocateMdlForIoSpace は、成功した場合STATUS_SUCCESSを返します。 考えられるエラーの戻り値には、次の状態コードが含まれます。
リターン コード | 説明 |
---|---|
STATUS_INVALID_PARAMETER_1 | 物理アドレスがページ境界に配置されていません。または、物理アドレス範囲がページ サイズの倍数ではありません。または物理アドレス範囲が RAM のオペレーティング システムによって使用され、I/O 領域として使用できません。 |
STATUS_INSUFFICIENT_RESOURCES | 要求された操作を実行するために使用できるシステム リソースが不足しています。 |
上記のエラー リターン コードの一覧が完全であると想定しないでください。 ルーチンは、一覧に表示されないエラー コードを返す場合があります。
注釈
このルーチンは、入力パラメーターとして、I/O アドレス空間内の物理アドレス範囲のセットを記述する MM_PHYSICAL_ADDRESS_LIST 構造体の配列を受け取り、これらの範囲を記述する MDL を割り当てます。 配列内の連続する物理アドレス範囲は連続している必要はありません。
PhysicalAddressList 配列の物理アドレス範囲は、次の条件を満たす必要があります。
各範囲の基本物理アドレスは、メモリ内のPAGE_SIZE境界に配置する必要があります。
各範囲のサイズ (バイト単位) は、PAGE_SIZEの整数倍数である必要があります。
すべての物理アドレス範囲は、I/O アドレス空間として使用できるメモリ内に存在する必要があります。 RAM 用のオペレーティング システムで使用されるメモリ領域にすることはできません。
すべての範囲の合計サイズは、4 ギガバイト未満である必要があります。 具体的には、合計サイズは 2^32 - 1 バイトを超えてはなりません。
呼び出し元は、割り当てられた MDL が不要になったときに解放する必要があります。 MDL を解放するには、 IoFreeMdl ルーチンを呼び出します。 MDL の詳細については、「MDL の使用」を参照してください。
MmAllocateMdlForIoSpace によって作成された MDL は仮想メモリにマップされませんが、MapTransferEx などのルーチンに提供して、MDL によって記述された物理メモリ範囲との間で DMA 転送を開始できます。 この MDL を連続した範囲の仮想アドレスにマップしてプロセッサからアクセスできるようにするには、 MmMapLockedPagesSpecifyCache ルーチンを呼び出します。
オペレーティング システムによってメモリとして使用するために予約されていない物理アドレス空間の範囲のみが、ドライバーで I/O アドレス空間として使用できます。 ドライバーは、I/O アドレス空間を使用して、デバイス レジスタなどのメモリ マップされたハードウェア リソースにアクセスします。 ドライバーが起動すると、1 つ以上の物理アドレス範囲が変換されたハードウェア リソースとして受信される場合があります。 詳細については、「 Bus-Relative アドレスと仮想アドレスのマッピング」を参照してください。
x86 などの一部のプロセッサ アーキテクチャでは、デバイスをメモリ マップするか、デバイス専用のメモリ アドレス空間とは別の特殊な I/O アドレス空間内のポート アドレスにマップできます。 ドライバーは MmAllocateMdlForIoSpace を使用して、メモリ マップされたデバイスにのみ MDL を割り当てることができます。
例
次のコード例は、割り当てられた MDL に含める物理アドレス範囲を記述する MM_PHYSICAL_ADDRESS_LIST 構造体の配列を構築する方法を示しています。
extern ULONG64 BasePhysicalAddress;
extern SIZE_T ChunkSize;
extern SIZE_T Stride;
#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
NTSTATUS Status;
PMDL Mdl;
MM_PHYSICAL_ADDRESS_LIST AddressList[3];
AddressList[0].PhysicalAddress.QuadPart = BasePhysicalAddress;
AddressList[0].NumberOfBytes = ChunkSize;
BasePhysicalAddress += Stride;
AddressList[1].PhysicalAddress.QuadPart = BasePhysicalAddress;
AddressList[1].NumberOfBytes = ChunkSize;
BasePhysicalAddress += Stride;
AddressList[2].PhysicalAddress.QuadPart = BasePhysicalAddress;
AddressList[2].NumberOfBytes = ChunkSize;
Status = MmAllocateMdlForIoSpace (AddressList, ARRAYSIZE(AddressList), &Mdl);
この例では、 変数によって BasePhysicalAddress
開始物理アドレスが指定されています。 各物理アドレス範囲のバイト数は、 変数によって ChunkSize
指定されます。 1 つの物理範囲の開始から次の開始までのバイト オフセットは、 変数によって Stride
指定されます。 BasePhysicalAddress
はメモリ内のページ境界に配置する必要がありChunkSize
Stride
、ページ サイズの倍数である必要があります。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows 8以降で使用できます。 |
対象プラットフォーム | ユニバーサル |
Header | wdm.h (Wdm.h を含む) |
Library | NtosKrnl.lib |
[DLL] | NtosKrnl.exe |
IRQL | <= DISPATCH_LEVEL |