Bagikan melalui


NDIS Menyebar/Mengumpulkan DMA

Perhatian

Untuk prosesor Arm dan Arm64, kami sangat menyarankan agar penulis driver NDIS menggunakan WDF DMA atau WDM DMA alih-alih NDIS Scatter/Gather DMA.

Untuk informasi selengkapnya tentang WDF DMA, lihat Menangani Operasi DMA di Driver KMDF.

Untuk informasi selengkapnya tentang WDM DMA, lihat topik anak terkait DMA dari Mengelola Input/Output untuk Driver.

Driver miniport NDIS dapat menggunakan metode Scatter/Gather DMA (SGDMA) untuk mentransfer data antara NIC dan memori sistem. Transfer DMA yang berhasil mengharuskan alamat fisik data berada dalam rentang alamat yang didukung NIC. HAL menyediakan mekanisme bagi driver untuk mendapatkan daftar alamat fisik untuk rantai MDL dan, jika perlu, akan menyangga data dua kali ke rentang alamat fisik.

Dalam versi NDIS sebelum NDIS 6.0, dukungan SGDMA dalam driver miniport dan NDIS terbatas dalam beberapa hal, dan khususnya tidak berfungsi dengan baik dalam skenario pengiriman multipaket. Dukungan NDIS 6.0 SGDMA mengatasi keterbatasan ini sambil menyediakan antarmuka sederhana untuk driver miniport.

Sejarah SGDMA NDIS

Dalam versi NDIS sebelum NDIS 6.0, NDIS mendapatkan daftar pengumpulan sebar (SG) untuk setiap paket sebelum mengirim paket ke driver miniport. NDIS juga menangani kasus di mana upaya asli untuk mendapatkan daftar SG gagal karena fragmentasi yang berlebihan. Dalam hal ini, NDIS menyangga ganda paket ke buffer yang berdekatan dan mencoba lagi. HAL juga dapat menyangga dua kali data ke alamat fisik yang didukung NIC jika, misalnya, alamat fisik data berada di atas maksimum 32-bit dan NIC tidak mendukung DMA 64-bit.

Untuk menghindari situasi kebuntuan, NDIS mendapatkan daftar SG untuk paket, dan mengirim satu paket pada satu waktu. Jika NDIS mencoba memetakan semua paket sebelum mengirimkannya ke driver miniport, sistem dapat kehabisan sumber daya. Dalam hal ini, NDIS akan menunggu register peta tersedia sementara beberapa register peta dikunci untuk paket yang belum dikirim. Paket terkunci tidak dapat digunakan kembali.

Pendekatan untuk dukungan SGDMA ini memiliki batasan berikut:

  • Karena paket dipetakan sebelum sampai ke driver miniport, driver tidak dapat mengoptimalkan paket kecil atau paket yang terlalu terfragmentasi. Driver miniport tidak dapat menggandakan buffer paket ke alamat fisik yang diketahui.

  • Tidak ada jaminan bahwa array alamat fisik yang diteruskan NDIS ke peta driver miniport ke alamat virtual data asli. Oleh karena itu, jika driver mengubah data di alamat virtual dalam rantai MDL sebelum mengirimkannya, modifikasi yang dilakukan pada data tidak tercermin dalam data di alamat fisik. Dalam hal ini, NIC mengirim data yang tidak dimodifikasi.

  • NDIS terbatas pada pengiriman satu paket pada satu waktu untuk menghindari kebuntuan karena masalah sumber daya. Ini tidak seefisien mengirim beberapa paket.

  • Karena NDIS tidak dapat menentukan kemampuan transmisi driver miniport, NDIS tidak dapat melakukan pra-alokasi penyimpanan untuk buffer daftar SG. Oleh karena itu, NDIS harus mengalokasikan penyimpanan yang diperlukan pada durasi. Ini tidak seefisien pra-alokasi penyimpanan.

  • Fungsi HAL yang mengalokasikan daftar SG harus dipanggil di IRQL = DISPATCH_LEVEL. NDIS tidak memiliki informasi IRQL saat ini, sehingga harus mengatur IRQL ke DISPATCH_LEVEL meskipun sudah DISPATCH_LEVEL. Ini tidak efisien jika IRQL sudah DISPATCH_LEVEL.

Manfaat Dukungan SGDMA NDIS

Di antarmuka SGDMA NDIS 6.0 dan yang lebih baru, NDIS tidak memetakan buffer data sebelum mengirimkannya ke driver miniport. Sebagai gantinya, NDIS menyediakan antarmuka bagi driver untuk memetakan data jaringan.

Pendekatan ini menghasilkan manfaat berikut:

  • Karena NDIS menyediakan antarmuka ke HAL untuk memetakan data jaringan, NDIS melindungi driver miniport dari kompleksitas dan detail proses pemetaan.

  • Driver miniport memiliki akses ke data sebelum dipetakan. Oleh karena itu, setiap perubahan yang dilakukan pada data asli tercermin dalam data yang diwakili oleh daftar SG meskipun NDIS atau HAL menyangga data.

  • Driver miniport dapat mengoptimalkan transmisi paket kecil atau sangat terfragmentasi dengan menyalinnya ke buffer yang telah dialokasikan sebelumnya dengan alamat fisik yang diketahui. Pendekatan ini menghindari pemetaan yang tidak diperlukan dan oleh karena itu meningkatkan performa sistem.

  • NDIS dapat mengirim beberapa buffer ke driver miniport dengan aman. Ini menghasilkan lebih sedikit panggilan ke driver miniport dan karena itu meningkatkan performa sistem.

  • Driver miniport dapat melakukan pra-alokasi memori untuk daftar SG sebagai bagian dari blok deskriptor transmisi. Oleh karena itu, driver NDIS atau miniport tidak diperlukan untuk mengalokasikan memori untuk daftar SG pada durasi.

  • Karena driver miniport dapat berjalan di IRQL = DISPATCH_LEVEL, driver miniport dapat menghindari panggilan yang tidak perlu untuk menaikkan IRQL ke DISPATCH_LEVEL. Misalnya, karena menyelesaikan pengiriman terjadi dalam konteks DPC yang mengganggu, driver miniport dapat membebaskan daftar SG tanpa menaikkan IRQL.

Mendaftarkan dan Membatalkan Pendaftaran Saluran DMA

Driver miniport NDIS memanggil fungsi NdisMRegisterScatterGatherDma dari fungsi MiniportInitializeEx untuk mendaftarkan saluran DMA dengan NDIS.

Driver miniport meneruskan deskripsi DMA ke NdisMRegisterScatterGatherDma dalam parameter DmaDescription . NdisMRegisterScatterGatherDma mengembalikan ukuran untuk buffer yang harus cukup besar untuk menahan daftar sebar/kumpulkan. Driver miniport harus menggunakan ukuran ini untuk melakukan pra-alokasi penyimpanan untuk daftar sebar/kumpulkan.

Driver miniport juga melewati NdisMRegisterScatterGatherDma titik masuk untuk fungsi MiniportXxx yang dipanggil NDIS untuk memproses daftar sebar/kumpulkan. NDIS memanggil fungsi MiniportProcessSGList driver miniport setelah HAL membangun daftar sebar/kumpulkan untuk buffer. NdisMRegisterScatterGatherDma memasok handel dalam parameter pNdisMiniportDmaHandle , yang harus digunakan driver miniport dalam panggilan berikutnya ke fungsi NDIS menyebar/mengumpulkan DMA.

Driver miniport NDIS memanggil fungsi NdisMDeregisterScatterGatherDma dari fungsi MiniportHaltEx-nya untuk merilis sumber daya DMA yang menyebar/mengumpulkan.

Mengalokasikan dan Membebaskan Daftar Sebar/Kumpulkan

Driver miniport NDIS memanggil fungsi NdisMAllocateNetBufferSGList dalam fungsi MiniportSendNetBufferLists-nya . Driver miniport memanggil NdisMAllocateNetBufferSGList sekali untuk setiap struktur NET_BUFFER yang harus dipetakan. Setelah sumber daya tersedia dan HAL menyiapkan daftar SG, NDIS memanggil fungsi MiniportProcessSGList driver. NDIS dapat memanggil miniportProcessSGList sebelum atau sesudah panggilan driver miniport ke pengembalian NdisMAllocateNetBufferSGList .

Untuk meningkatkan performa sistem, daftar sebar/kumpulkan dihasilkan dari data jaringan mulai dari awal MDL yang ditentukan pada anggota CurrentMdl dari struktur NET_BUFFER_DATA terkait. Awal data jaringan dalam daftar SG diimbangi dari awal daftar SG dengan nilai yang ditentukan dalam anggota CurrentMdlOffset dari struktur NET_BUFFER_DATA terkait.

Saat menangani DPC untuk gangguan send-complete, dan setelah driver miniport tidak memerlukan daftar SG lagi, driver miniport harus memanggil fungsi NdisMFreeNetBufferSGList untuk membebaskan daftar SG.

Catatan Jangan panggil NdisMFreeNetBufferSGList saat driver atau perangkat keras masih mengakses memori yang dijelaskan oleh struktur NET_BUFFER yang terkait dengan daftar sebar/kumpulkan. 

Sebelum mengakses data yang diterima, driver miniport harus memanggil NdisMFreeNetBufferSGList untuk membersihkan cache memori.