使用散佈圖/收集 DMA

執行系統或匯流排主機、封包型 DMA 的驅動程式可以使用專為散佈/收集 DMA 而設計的支援常式。 驅動程式可以使用GetScatterGatherListPutScatterGatherList,而不是呼叫使用 Packet-Based system DMAPacket-Based Bus-Master DMA中所述的常式序列。

裝置不需要有內建散佈/收集支援,其驅動程式才能使用這些常式。

使用封包型 DMA 的驅動程式會針對散佈/收集作業呼叫下列一般支援常式:

  1. MmGetMdlVirtualAddress以取得 MDL 中的索引,在呼叫 GetScatterGatherList時需要做為參數

  2. 當驅動程式準備好為其裝置進行 DMA 的程式設計,且需要系統 DMA 控制器或匯流排主機介面卡時,GetScatterGatherList

    GetScatterGatherList 會配置系統 DMA 控制器或匯流排主機介面卡、決定需要多少地圖暫存器並配置它們、填入散佈/收集清單,並在 DMA 控制器或配接器及地圖暫存器可用時呼叫驅動程式的 AdapterListControl 常式。

  3. 一旦傳輸所有要求的資料,或驅動程式因為裝置 I/O 錯誤而失敗,PutScatterGatherList

    PutScatterGatherList 會排清配接器緩衝區、釋放地圖暫存器,並釋放散佈/收集清單。 驅動程式必須先呼叫 PutScatterGatherList ,才能存取緩衝區中的資料。

IoGetDmaAdapter所傳回的配接器物件指標是每個常式的必要參數,但 MmGetMdlVirtualAddress除外,這需要 Irp-MdlAddress > 上的MDL指標。

GetScatterGatherList常式包含AllocateAdapterChannelMapTransfer的呼叫,因此驅動程式不需要進行這些呼叫。 常式會採用下列作為參數:

  • IoGetDmaAdapter所傳回之DMA_ADAPTER結構的指標

  • DMA 作業之目標裝置物件的指標

  • 描述Irp-MdlAddress> 緩衝區之 MDL 的指標

  • Mdl 所描述之緩衝區中目前虛擬位址的指標

  • 要對應的位元組數目

  • 執行傳輸之 AdapterListControl 常式的指標

  • 要傳遞至 AdapterListControl 常式之驅動程式定義內容區域的指標

  • 布林值:傳送至裝置的TRUE;否則為 FALSE

判斷所需的地圖暫存器數目、配置配接器通道和地圖暫存器、填入散佈/收集清單並準備傳輸之後, GetScatterGatherList 會呼叫驅動程式提供的 AdapterListControl 常式。 AdapterListControl常式是在 IRQL = DISPATCH_LEVEL的任意執行緒內容中執行。

驅動程式在呼叫GetScatterGatherList時提供的 AdapterListControl常式與下列重要方面傳遞給AllocateAdapterChannelAdapterControl常式不同:

  • AdapterListControl常式沒有傳回值,而AdapterControl常式則會傳回IO_ALLOCATION_ACTION

  • 相較于系統組態之對應暫存器的 MapRegisterBase 指標, AdapterListControl 常式的第三個參數會指向驅動程式可執行 DMA 的 SCATTER_GATHER_LIST 結構。

  • AdapterListControl常式會執行AdapterControl常式中所需的工作子集。

    AdapterListControl常式不會呼叫AllocateAdapterChannelMapTransfer。 其唯一的責任是儲存輸入散佈圖/收集清單指標、設定其裝置,並使用散佈圖/收集清單來執行 DMA。

散佈/收集清單結構包含 SCATTER_GATHER_ELEMENT 陣列和陣列中的元素數目。 陣列的每個元素都會提供實體連續散佈/收集區域的長度和開始實體位址。 驅動程式會在資料傳輸中使用長度和位址。

不論其裝置是否支援散佈/收集 DMA,驅動程式都可以使用 GetScatterGatherList 。 對於不支援散佈/收集 DMA 的裝置,散佈圖/收集清單只會包含一個專案。

使用散佈/收集常式可改善呼叫 AllocateAdapterChannel (的效能,如先前 使用 Packet-Based System DMAUsing Packet-Based Bus-Master DMA) 中所述。 不同于 AllocateAdapterChannel的呼叫,一次可以針對裝置物件排入一個以上的 GetScatterGatherList 呼叫。 驅動程式可以在其AdapterListControl常式完成執行之前,針對相同驅動程式物件上的另一個 DMA 作業再次呼叫GetScatterGatherList

從驅動程式提供的 AdapterListControl 常式傳回時, GetScatterGatherList 會保留地圖暫存器,但釋放 DMA 配接器結構。

當驅動程式滿足目前的 IRP 傳輸要求,或因為裝置或匯流排 I/O 錯誤而失敗 IRP 時,它必須先呼叫 PutScatterGatherList ,才能存取緩衝區中傳輸的資料。 PutScatterGatherList 會排清配接器緩衝區,並釋放地圖暫存器和散佈/收集清單。