儲存類別驅動程式的 SplitTransferRequest 常式
傳回至 GetDescriptor 常式的STORAGE_ADAPTER_DESCRIPTOR資料會指出指定 HBA 傳送至類別驅動程式的傳輸功能。 特別是,此資料指出 MaximumTransferLength 位元組和 MaximumPhysicalPages:也就是說,HBA 可以在支援系統 (緩衝區的實體記憶體中管理多少個非連續頁面,也就是其散佈/收集支援範圍) 。
大部分的類別驅動程式會將此設定資料的指標儲存在每個裝置物件的裝置延伸模組中,因為儲存類別驅動程式負責分割超過 HBA 傳輸資料的所有傳輸要求。 換句話說,類別驅動程式的 DispatchReadWrite 常式必須判斷每個 IRP 要求傳輸是否超過 HBA 可以在單一傳輸作業中處理。
例如,這類 DispatchReadWrite 常式可能會有類似下列的程式碼:
PSTORAGE_ADAPTER_DESCRIPTOR adapterDescriptor =
commonExtension->PartitionZeroExtension->AdapterDescriptor;
ULONG transferPages;
ULONG maximumTransferLength =
adapterDescriptor->MaximumTransferLength;
: :
//
// Calculate number of pages in this transfer
//
transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
MmGetMdlVirtualAddress(Irp->MdlAddress),
currentIrpStack->Parameters.Read.Length);
//
// Check whether requested length is greater than the maximum number
// of bytes that can be transferred in a single operation
//
if (currentIrpStack->Parameters.Read.Length > maximumTransferLength ||
transferPages > adapterDescriptor->MaximumPhysicalPages) {
transferPages = adapterDescriptor->MaximumPhysicalPages - 1;
if (maximumTransferLength > transferPages << PAGE_SHIFT) {
maximumTransferLength = transferPages << PAGE_SHIFT;
}
IoMarkIrpPending(Irp);
SplitTransferRequest(DeviceObject,
Irp,
maximumTransferLength);
return STATUS_PENDING;
}
: :
類別驅動程式無法分辨緩衝區對應後,緩衝區將有多少個實體中斷,因此必須假設傳輸中的每個頁面都不明確,並比較允許的實體中斷數目。
請注意,這類驅動程式的 DispatchReadWrite 常式會呼叫 IoMarkIrpPending ,並在呼叫其 SplitTransferRequest 常式與原始 IRP 之後立即傳回STATUS_PENDING。
為了執行原始傳輸要求,驅動程式的 SplitTransferRequest 常式會建立一或多個 IRP 來處理大小為符合 HBA 功能的子緩衝區。 針對每個這類 IRP, SplitTransferRequest 常式:
設定 SRB,通常是藉由呼叫內部 BuildRequest 常式 (請參閱 儲存體類別驅動程式的 BuildRequest 常式)
將 MDL 位址從原始 IRP 複製到新的 IRP
將 SRB 中的 DataBuffer 設定為此傳輸片段的 MDL 位元組位移
使用IoCallDriver將 IRP 傳送至埠驅動程式之前,先設定其IoCompletion常式
為了追蹤傳輸的每個部分, SplitTransferRequest 會針對每個驅動程式配置的 IRP 註冊 IoCompletion 常式,以傳送至下一個較低的驅動程式。 IoCompletion常式會使用InterlockedIncrement和InterlockedDecrement維護原始 IRP 中已完成的部分傳輸要求計數,以確保計數正確無誤。
這類 IoCompletion 常式必須釋放驅動程式已配置的任何 IRP 和/或 SRB,而且必須在傳輸所有要求的資料或類別驅動程式耗盡 IRP 重試時完成原始 IRP,而且必須因裝置傳輸錯誤而失敗。