Bagikan melalui


Menyiapkan Operasi Transfer

Ketika AllocateAdapterChannel mentransfer kontrol ke rutinitas AdapterControl driver, ia telah mengalokasikan sekumpulan register peta. Namun, driver harus memetakan memori fisik sistem untuk permintaan transfer IRP saat ini ke rentang alamat logis adaptor master bus, sebagai berikut:

  1. Panggil MmGetMdlVirtualAddress dengan MDL di Irp-MdlAddress> untuk mendapatkan indeks untuk alamat fisik sistem tempat transfer harus dimulai.

    Nilai yang dikembalikan adalah parameter yang diperlukan (CurrentVa) ke MapTransfer.

  2. Panggil MapTransfer untuk memetakan rentang alamat fisik sistem untuk buffer IRP ke rentang alamat logis adaptor master bus.

Driver kemudian dapat mengatur adaptor untuk operasi transfer. Gambar berikut menunjukkan langkah-langkah yang terlibat dalam menyiapkan transfer.

diagram yang mengilustrasikan pengaturan operasi transfer.

Seperti yang ditunjukkan oleh gambar sebelumnya, rutinitas AdapterControl driver menyiapkan operasi DMA master bus sebagai berikut:

  1. Rutinitas AdapterControl mendapatkan alamat untuk memulai transfer. Untuk transfer awal yang diperlukan untuk memenuhi IRP, rutinitas AdapterControl memanggil MmGetMdlVirtualAddress, meneruskan pointer ke MDL di Irp-MdlAddress>, yang menjelaskan buffer untuk transfer DMA ini.

    MmGetMdlVirtualAddress mengembalikan alamat virtual yang dapat digunakan driver sebagai indeks untuk alamat fisik sistem tempat transfer harus dimulai.

    Jika IRP memerlukan lebih dari satu operasi transfer, driver menghitung alamat awal yang diperbarui, seperti yang dijelaskan nanti di bagian ini.

  2. Rutinitas AdapterControl menyimpan alamat yang dikembalikan oleh MmGetMdlVirtualAddress atau dihitung di Langkah 1. Alamat ini adalah parameter yang diperlukan (CurrentVa) ke MapTransfer.

  3. Rutinitas AdapterControl memanggil MapTransfer, yang mengembalikan alamat logis di mana driver dapat memprogram adaptor bus-master untuk memulai operasi transfer. Dalam panggilan ke MapTransfer, driver menyediakan parameter berikut:

    • Penunjuk objek adaptor yang dikembalikan oleh IoGetDmaAdapter

    • Penunjuk ke MDL di Irp-MdlAddress> untuk IRP saat ini

    • Handel MapRegisterBase diteruskan ke rutinitas AdapterControl driver oleh AllocateAdapterChannel (lihat Mengalokasikan Objek Adapter Bus-Master)

    • Nilai yang dikembalikan oleh MmGetMdlVirtualAddress jika ini adalah panggilan pertama ke MapTransfer untuk IRP saat ini

      Jika tidak, driver menyediakan nilai CurrentVa yang diperbarui, menunjukkan pemetaan fisik ke logis berikutnya yang akan dilakukan. (Cara menghitung CurrentVa yang diperbarui dijelaskan nanti di bagian ini.)

    • Penunjuk ke variabel (Panjang), yang menunjukkan jumlah byte untuk transfer ini

      Jika driver memiliki cukup daftar peta untuk mentransfer semua data yang diminta dalam satu operasi DMA dan tidak memiliki batasan khusus perangkat pada operasi DMA-nya, Panjang dapat diatur ke nilai Panjang di lokasi tumpukan I/O driver dari IRP. Paling banyak, panjang input dalam byte dapat berupa (PAGE_SIZE * NumberOfMapRegisters yang dikembalikan oleh IoGetDmaAdapter). Jika tidak, driver harus membagi permintaan, seperti yang dijelaskan dalam Permintaan Transfer Pemisahan, dan harus memperbarui nilai Panjang dalam panggilan berikutnya ke MapTransfer untuk IRP saat ini.

    • Nilai Boolean (WriteToDevice), menunjukkan arah operasi transfer (TRUE untuk mentransfer data dari memori ke perangkat)

  4. Rutinitas AdapterControl menyiapkan perangkat untuk operasi DMA.

  5. Rutinitas AdapterControl mengembalikan DeallocateObjectKeepRegisters.

Jika driver harus memanggil MapTransfer lebih dari sekali untuk memenuhi Proses Permintaan I/O (IRP) saat ini, itu menyediakan penunjuk-penunjuk objek adaptor yang sama, penunjuk-penunjuk Mdl, handel MapRegisterBase, dan arah transfer pada setiap pemanggilan ke MapTransfer. Namun, driver harus menyediakan nilai CurrentVa dan Length yang diperbarui dalam panggilan kedua dan berikutnya ke MapTransfer. Gunakan rumus berikut untuk menghitung nilai-nilai ini:

  • CurrentVa = CurrentVa + (Panjang yang diminta pada panggilan sebelumnya ke MapTransfer)

  • Panjang = Minimum (sisa Panjang yang akan ditransfer, (PAGE_SIZE * NumberOfMapRegisters yang dikembalikan oleh IoGetDmaAdapter))

Informasi konteks yang harus dipertahankan setiap driver tentang transfer DMA-nya tergantung pada kebutuhan perangkat tertentu. Konteks umum mungkin mencakup alamat virtual saat ini dalam MDL (CurrentVa), jumlah byte yang ditransfer sejauh ini, jumlah byte yang tersisa untuk ditransfer, dan mungkin penunjuk ke IRP saat ini.

Untuk pengandar perangkat dengan kapabilitas scatter/gather, parameter Panjang pada MapTransfer berfungsi sebagai parameter input dan output. Saat kembali dari MapTransfer, ini menunjukkan berapa banyak byte data yang telah dipetakan sistem. Artinya, nilai pengembalian Panjang, dalam kombinasi dengan alamat logis yang dikembalikan, menunjukkan rentang alamat logis yang dapat digunakan adaptor master bus untuk bagian transfer ini dalam operasi DMA ini.

Nota Karena Panjang ditimpa oleh MapTransfer, ikuti panduan implementasi ini: Jangan pernah meneruskan penunjuk ke Panjang di lokasi tumpukan I/O driver dari IRP sebagai parameter Panjang ke MapTransfer jika perangkat Anda mendukung sebar/kumpulkan.

Melakukan ini dapat menghancurkan nilai dalam IRP saat ini, sehingga tidak mungkin untuk menentukan apakah driver telah mentransfer semua data yang diminta.

Di akhir setiap operasi DMA, driver harus memanggil FlushAdapterBuffers dengan penunjuk objek adaptor yang valid dan handel MapRegisterBase untuk memastikan bahwa semua data telah ditransfer, dan untuk merilis pemetaan fisik ke logis untuk operasi DMA saat ini. Jika driver harus menyiapkan operasi DMA tambahan untuk memenuhi IRP saat ini, driver harus memanggil FlushAdapterBuffers setelah setiap operasi transfer selesai.

Ketika semua transfer yang diminta telah selesai atau driver harus mengembalikan status kesalahan untuk IRP, driver harus segera memanggil FreeMapRegisters setelah panggilan terakhirnya ke FlushAdapterBuffers untuk mendapatkan throughput terbaik bagi adaptor pengendali-bus. Dalam panggilannya ke FreeMapRegisters, driver harus memberikan pointer objek adapter yang sama yang diteruskannya dalam panggilan sebelumnya ke AllocateAdapterChannel.