Bagikan melalui


Menulis Driver Audio 64-Bit

Jika Anda menulis driver 64-bit atau menulis driver yang dapat dikompilasi untuk dijalankan pada sistem 32 dan 64-bit, ikuti panduan porting dalam Teknik Pemrograman Driver. Beberapa jebakan yang mungkin Anda temui dalam menulis driver audio 64-bit dijelaskan di bawah ini.

Pertama dan yang terdepan, potensi masalah untuk dicari dalam kode driver 32-bit yang ada adalah konversi antara jenis pointer dan jenis bilangan bulat seperti DWORD atau ULONG. Programmer dengan pengalaman menulis kode untuk komputer 32-bit dapat digunakan untuk mengasumsikan bahwa nilai pointer cocok dengan DWORD atau ULONG. Untuk kode 64-bit, asumsi ini berbahaya. Transmisi pointer ke jenis DWORD atau ULONG dapat menyebabkan pointer 64-bit terpotong. Pendekatan yang lebih baik adalah melemparkan pointer untuk mengetik DWORD_PTR atau ULONG_PTR. Bilangan bulat jenis DWORD_PTR atau ULONG_PTR yang tidak ditandatangani selalu cukup besar untuk menyimpan seluruh pointer, terlepas dari apakah kode dikompilasi untuk mesin 32 atau 64-bit.

Misalnya, bidang penunjuk IRPIoStatus. Informasi berjenis ULONG_PTR. Kode berikut menunjukkan apa yang tidak boleh dilakukan saat menyalin nilai pointer 64-bit ke bidang ini:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG)pDeviceRelations;  // wrong

Sampel kode ini secara keliru mentransmisikan pDeviceRelations pointer untuk mengetik ULONG, yang dapat memotong nilai pointer jika sizeof(pDeviceRelations) > sizeof(ULONG). Pendekatan yang benar adalah mentransmisikan penunjuk ke ULONG_PTR, seperti yang ditunjukkan dalam hal berikut:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations;  // correct

Ini mempertahankan semua 64 bit nilai penunjuk.

Daftar sumber daya menyimpan alamat fisik sumber daya dalam struktur jenis PHYSICAL_ADDRESS (lihat IResourceList). Untuk menghindari memotong alamat 64-bit, Anda harus mengakses anggota QuadPart struktur daripada anggota LowPart-nya saat menyalin alamat ke dalam struktur atau membaca alamat dari struktur. Misalnya, makro FindTranslatedPort mengembalikan penunjuk ke struktur CM_PARTIAL_RESOURCE_DESCRIPTOR yang berisi alamat dasar port I/O. U. Port. Anggota awal struktur ini adalah penunjuk PHYSICAL_ADDRESS ke alamat dasar. Kode berikut menunjukkan apa yang tidak boleh dilakukan:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart;  // wrong

Sekali lagi, ini dapat memotong penunjuk. Sebagai gantinya, Anda harus mengakses QuadPart anggota ini, seperti yang ditunjukkan dalam hal berikut:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart;  // correct

Ini menyalin seluruh pointer 64-bit.

Fungsi Win64 sebaris seperti PtrToUlong dan UlongToPtr dengan aman mengonversi antara jenis pointer dan bilangan bulat tanpa mengandalkan asumsi tentang ukuran relatif dari jenis ini. Jika satu jenis lebih pendek dari jenis lainnya, jenis tersebut harus diperluas saat mengonversi ke jenis yang lebih panjang. Apakah jenis yang lebih pendek diperpanjang dengan mengisi dengan bit tanda atau dengan nol didefinisikan dengan baik untuk setiap fungsi Win64. Ini berarti bahwa setiap cuplikan kode seperti

    ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // wrong

harus digantikan oleh

    ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // correct

Ini lebih disukai meskipun ulSlotPhysAddr mungkin mewakili nilai register perangkat keras yang hanya 32 daripada 64 bit panjang. Untuk daftar semua fungsi pembantu Win64 baru untuk mengonversi antara jenis pointer dan bilangan bulat, lihat Jenis Data Baru.