Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Data STORAGE_ADAPTER_DESCRIPTOR yang dikembalikan ke rutinitas GetDescriptor menunjukkan kemampuan transfer HBA tertentu ke driver kelas. Secara khusus, data ini menunjukkan MaximumTransferLength dalam byte dan MaximumPhysicalPages: yaitu, berapa banyak halaman yang tidak bersebelahan yang dapat dikelola HBA dalam memori fisik yang mendukung buffer sistem (yaitu, sejauh mana dukungannya menyebar/mengumpulkan).
Sebagian besar driver kelas menyimpan pointer ke data konfigurasi ini di ekstensi perangkat setiap objek perangkat karena driver kelas penyimpanan bertanggung jawab untuk membagi semua permintaan transfer yang melebihi kemampuan HBA untuk mentransfer data. Dengan kata lain, rutinitas DispatchReadWrite driver kelas harus menentukan apakah setiap IRP meminta transfer yang lebih besar dari yang dapat ditangani oleh HBA dalam satu operasi transfer.
Misalnya, rutinitas DispatchReadWrite seperti itu dapat memiliki kode yang mirip dengan yang berikut:
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;
}
: :
Driver kelas tidak dapat mengetahui berapa banyak pemutusan fisik yang akan terjadi pada buffer setelah dipetakan, oleh karena itu, harus mengasumsikan bahwa setiap halaman dalam transfer tidak berurutan dan membandingkan jumlah halaman dengan jumlah pemutusan fisik yang diizinkan.
Perhatikan bahwa rutinitas DispatchReadWrite driver tersebut memanggil IoMarkIrpPending dan segera mengembalikan STATUS_PENDING setelah panggilan ke rutinitas SplitTransferRequest dengan IRP asli.
Untuk melaksanakan permintaan transfer yang asli, rutinitas SplitTransferRequest driver membuat satu atau beberapa IRP untuk menangani subbuffer yang ukurannya sesuai dengan kemampuan HBA. Untuk setiap IRP tersebut, rutinitas SplitTransferRequest :
Menyiapkan SRB, biasanya dengan memanggil rutinitas BuildRequest internal (lihat Rutinitas BuildRequest Driver Kelas Penyimpanan)
Menyalin alamat MDL dari IRP asli ke IRP baru
Mengatur DataBuffer di SRB ke offset dalam byte pada MDL untuk bagian transfer ini.
Menyiapkan rutinitas IoCompletion-nya sebelum mengirim IRP ke driver port dengan IoCallDriver
Untuk melacak setiap bagian transfer, SplitTransferRequest mendaftarkan rutinitas IoCompletion untuk setiap IRP yang dialokasikan driver yang dikirim ke driver lapis berikutnya. Rutinitas IoCompletion mempertahankan jumlah permintaan transfer parsial yang telah selesai di IRP asli, menggunakan InterlockedIncrement dan InterlockedDecrement untuk memastikan bahwa jumlahnya akurat.
Rutinitas IoCompletion semacam itu harus membebaskan IRP dan/atau SRB yang telah dialokasikan oleh driver dan harus menyelesaikan IRP asli ketika semua data yang diminta telah ditransfer atau ketika driver kelas tersebut telah menghabiskan upaya untuk mengulang IRP dan harus gagal karena kesalahan pengiriman data perangkat.