Bagikan melalui


Permintaan Digital Aman yang Menggunakan I/O Yang Diperluas

Permintaan Secure Digital (SD) yang membaca atau menulis lebih dari sekadar beberapa byte data harus menggunakan perintah I/O yang diperluas (disebut sebagai CMD53 dalam spesifikasi SD). Perintah I/O yang diperluas menginstruksikan pengemudi bus untuk mengirimkan data melalui baris DAT kartu SD. Karakteristik transfer data bergantung pada kemampuan pengontrol SD. Misalnya, beberapa pengontrol hanya mengizinkan I/O (PIO) yang dapat diprogram; lainnya mengizinkan akses memori langsung (DMA). Untuk kompatibilitas maksimum di berbagai jenis pengontrol SD, driver perangkat harus memuat paket permintaan dengan pointer ke MDL yang menjelaskan buffer data. Driver perangkat harus membangun MDL sendiri, kecuali driver di lapisan yang lebih tinggi membangun MDL dan meneruskannya ke driver perangkat.

Contoh kode berikut menunjukkan bagaimana driver dapat melakukan permintaan I/O yang diperluas menggunakan buffer data yang dijelaskan oleh MDL. Contoh kode ini mirip dalam format dengan contoh kode I/O langsung yang dijelaskan dalam Permintaan Digital Aman yang Menggunakan I/O Langsung, oleh karena itu mungkin berguna untuk mempelajari contoh kode I/O langsung sebelum mempelajari contoh kode I/O yang diperluas.

Perbedaan prinsip antara kedua contoh adalah bahwa contoh kode I/O yang diperluas menggambarkan cara menggunakan MDL dengan permintaan SD. Ada juga sedikit perbedaan dalam cara deskriptor dan paket permintaan didefinisikan untuk I/O langsung dan diperpanjang.

    const SDCMD_DESCRIPTOR WriteIoExtendedDesc =
    {SDCMD_IO_RW_EXTENDED, SDCC_STANDARD,
    SDTD_WRITE, SDTT_SINGLE_BLOCK, SDRT_1};
    
    // first, get an MDL to map the data. Call IoAllocateMdl to
    // allocate an MDL and pass in a pointer to a buffer  
    // allocated from the non-paged pool.
    
    mdl = IoAllocateMdl(Data, Length, FALSE, FALSE, NULL);
    
    if (mdl == NULL) {
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    MmBuildMdlForNonPagedPool (mdl);
    
    // next, allocate a request packet for the arguments of the command
     
    sdrp = ExAllocatePool(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET));
    
    if (!sdrp) {
      IoFreeMdl(mdl);
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(sdrp, sizeof(SDBUS_REQUEST_PACKET));
    sdrp->RequestFunction = SDRF_DEVICE_COMMAND;
    sdrp->Parameters.DeviceCommand.CmdDesc = 
    WriteIoExtendedDesc;
    
    // then, set up the argument and command descriptor
    sdIoArgument.u.AsULONG = 0;
    sdIoArgument.u.bits.Address = Offset;
    
    // retrieve function number, the driver previously initialized 
    // this value with the SdBus GetProperty call
    sdIoArgument.u.bits.Function = pDevExt->FunctionNumber;
    sdIoArgument.u.bits.WriteToDevice = 1;
    
    sdrp->Parameters.DeviceCommand.Argument = 
        sdIoArgument.u.AsULONG;
    
    sdrp->Parameters.DeviceCommand.Mdl = mdl;
    sdrp->Parameters.DeviceCommand.Length = Length;
    // finally, submit the request
    status = SdBusSubmitRequest(pDevExt->BusInterface.Context,sdrp);
    
    IoFreeMdl(mdl);
    ExFreePool(sdrp);

Contoh kode ini mencakup langkah-langkah berikut:

  1. Menginisialisasi Deskriptor

    Langkah pertama dalam mengirim permintaan perintah perangkat adalah menentukan deskriptor perintah SD, SDCMD_DESCRIPTOR. Deskriptor dalam contoh kode mendefinisikan operasi penulisan I/O yang diperluas dengan elemen berikut:

    Elemen Deskripsi

    SD_COMMAND_CODE

    Operasi yang ditentukan oleh deskriptor melakukan penulisan I/O yang diperluas, sehingga nilai kode perintah SDCMD_IO_RW_DIRECT.

    SD_COMMAND_CLASS

    Operasi penulisan I/O yang diperluas milik set perintah standar (kode perintah 0 hingga 63), sehingga nilai yang ditetapkan untuk anggota deskriptor ini SDCC_STANDARD.

    SD_TRANSFER_DIRECTION

    Operasi tulis memerlukan transfer dari host ke perangkat, sehingga nilai yang ditetapkan untuk anggota deskriptor ini SDTD_WRITE.

    SD_TRANSFER_TYPE

    Deskriptor untuk operasi penulisan I/O yang diperluas harus menyertakan jenis transfer. Contoh kode menentukan satu blok tulis, SDTT_SINGLE_BLOCK, yang menunjukkan bahwa host menulis satu blok data ke perangkat. Driver menetapkan ukuran blok dengan perintah SET_BLOCKLEN sebelumnya (tidak diilustrasikan dalam contoh kode ini). Untuk penjelasan tentang perintah SET_BLOCKLEN dan jenis transfer SDTT_SINGLE_BLOCK, lihat Spesifikasi Kartu MultiMedia , yang diterbitkan oleh komite teknis Asosiasi Kartu MultiMedia (MMCA).

    SD_RESPONSE_TYPE

    Deskriptor menentukan jenis respons SDRT_1, yang menentukan respons R1 standar terhadap perintah dan berisi data status. Untuk penjelasan tentang respons R1, lihat spesifikasi Asosiasi Kartu MultiMedia .

  2. Menyiapkan MDL

    Panggil IoAllocateMdl untuk mengalokasikan MDL dan meneruskan penunjuk ke buffer yang dialokasikan dari kumpulan non-halaman. Selanjutnya, rutinitas MmBuildMdlForNonPagedPool mengambil MDL yang baru dialokasikan yang menentukan buffer memori virtual di kumpulan non-halaman dan memperbaruinya untuk menjelaskan halaman fisik yang mendasar. Pemanggil MmBuildMdlForNonPagedPool harus berjalan di IRQL <= DISPATCH_LEVEL.

  3. Inisialisasi Paket Permintaan dengan menyelesaikan langkah-langkah berikut:

    • Tentukan Fungsi Permintaan:

      Setelah membuat deskriptor SD, contoh kode menginisialisasi paket permintaan, SDBUS_REQUEST_PACKET. Anggota RequestFunction dari paket permintaan menentukan apakah permintaan berisi perintah perangkat (nilai SDRF_DEVICE_COMMAND) atau operasi properti (nilai SDRF_GET_PROPERTY atau SDRF_SET_PROPERTY). Contoh kode mengirim perintah perangkat, sehingga mengatur anggota RequestFunction ke SDRF_DEVICE_COMMAND.

    • Muat Deskriptor Perintah. Selanjutnya, contoh kode menyimpan deskriptor yang baru diinisialisasi di anggota Parameters.DeviceCommand.CmdDesc dari paket permintaan.

    • Menginisialisasi Argumen Baca/Tulis:

      Paket permintaan berisi struktur SD_RW_DIRECT_ARGUMENT dengan lokasi penulisan sopir bus. Struktur ini juga menyimpan jumlah fungsi yang ruang I/O-nya dibaca pengemudi bus. Contoh kode mengambil nomor fungsi dari ekstensi perangkat, yang menyiratkan bahwa driver sebelumnya mengambil informasi ini dari kartu (mungkin ketika memulai perangkat dengan permintaan SDRF_GET_PROPERTY dan menyimpannya di ekstensi perangkat.

  4. Mengirimkan Permintaan

    Setelah menginisialisasi deskriptor dan paket permintaan, contohnya menggunakan rutinitas permintaan sinkron, SdBusSubmitRequest untuk mengirimkan permintaan. Ini meneruskan paket permintaan dan informasi konteks antarmuka yang disediakan sistem kepada driver ketika membuka antarmuka SD. Karena ini adalah permintaan sinkron, driver harus berjalan di IRQL kurang dari DISPATCH_LEVEL.

  5. Hasil Perintah

    Karena contoh kode menggunakan perintah I/O langsung, tidak ada buffer data selain bidang ResponseData dalam paket permintaan SD.

Contoh kode mengalokasikan buffer transfer data dari kumpulan non-halaman. Driver dapat menggunakan PagedPool untuk buffer transfer data, asalkan mengunci halaman. Namun, driver harus selalu mengalokasikan buffer transfer data dari kumpulan non-halaman saat melakukan permintaan SDRF_GET_PROPERTY dan SDRF_SET_PROPERTY. Driver juga harus mengalokasikan paket permintaan SD dari kumpulan non-halaman karena rutinitas penyelesaian IRP yang menyertai permintaan SD mungkin berjalan dalam panggilan prosedur yang ditangguhkan (DPC).

Untuk semua jenis permintaan, ada manfaat performa untuk mengalokasikan buffer dari kumpulan non-halaman ketika buffer kecil dan driver memegangnya sebentar.