⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 write.c

📁 基于xilinx vierex5得pci express dma设计实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

    Write.c

Abstract:


Environment:

    Kernel mode

--*/

#include "precomp.h"

#include "Write.tmh"


//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
VOID
PCIEEvtIoWrite(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN size_t            Length
    )
/*++

Routine Description:

    Called by the framework as soon as it receives a write request.
    If the device is not ready, fail the request.
    Otherwise get scatter-gather list for this request and send the
    packet to the hardware for DMA.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    Length - Length of the IO operation
                 The default property of the queue is to not dispatch
                 zero lenght read & write requests to the driver and
                 complete is with status success. So we will never get
                 a zero length request.

Return Value:

--*/
{
    NTSTATUS          status = STATUS_UNSUCCESSFUL;
    PDEVICE_EXTENSION devExt = NULL;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "--> PCIEEvtIoWrite: Request %p", Request);

    //
    // Get the DevExt from the Queue handle
    //
    devExt = PCIEGetDeviceContext(WdfIoQueueGetDevice(Queue));

    //
    // Validate the Length parameter.
    //
    if (Length > PCIE_SRAM_SIZE)  {
        status = STATUS_INVALID_BUFFER_SIZE;
        goto CleanUp;
    }

    //
    // Following code illustrates two different ways of initializing a DMA
    // transaction object. If ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION is
    // defined in the sources file, the first section will be used.
    //
#ifdef ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION

    //
    // This section illustrates how to create and initialize
    // a DmaTransaction using a WDF Request.
    // This type of coding pattern would probably be the most commonly used
    // for handling client Requests.
    //
    status = WdfDmaTransactionInitializeUsingRequest(
                                           devExt->WriteDmaTransaction,
                                           Request,
                                           PCIEEvtProgramWriteDma,
                                           WdfDmaDirectionWriteToDevice );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                    "WdfDmaTransactionInitializeUsingRequest failed: "
                    "%!STATUS!", status);
        goto CleanUp;
    }
#else
    //
    // This section illustrates how to create and initialize
    // a DmaTransaction via direct parameters (e.g. not using a WDF Request).
    // This type of coding pattern might be used for driver-initiated DMA
    // operations (e.g. DMA operations not based on driver client requests.)
    //
    // NOTE: This example unpacks the WDF Request in order to get a set of
    //       parameters for the call to WdfDmaTransactionInitialize. While
    //       this is completely legimate, the represenative usage pattern
    //       for WdfDmaTransactionIniitalize would have the driver create/
    //       initialized a DmaTransactin without a WDF Request. A simple
    //       example might be where the driver needs to DMA the devices's
    //       firmware to it during device initialization. There would be
    //       no WDF Request; the driver would supply the parameters for
    //       WdfDmaTransactionInitialize directly.
    //
    {
        PTRANSACTION_CONTEXT  transContext;
        PMDL                  mdl;
        PVOID                 virtualAddress;
        ULONG                 length;

        //
        // Initialize this new DmaTransaction with direct parameters.
        //
        status = WdfRequestRetrieveInputWdmMdl(Request, &mdl);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "WdfRequestRetrieveInputWdmMdl failed: %!STATUS!", status);
            goto CleanUp;
        }

        virtualAddress = MmGetMdlVirtualAddress(mdl);
        length = MmGetMdlByteCount(mdl);

        status = WdfDmaTransactionInitialize( devExt->WriteDmaTransaction,
                                              PCIEEvtProgramWriteDma,
                                              WdfDmaDirectionWriteToDevice,
                                              mdl,
                                              virtualAddress,
                                              length );

        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                        "WdfDmaTransactionInitialize failed: %!STATUS!", status);
              goto CleanUp;
        }

        //
        // Retreive this DmaTransaction's context ptr (aka TRANSACTION_CONTEXT)
        // and fill it in with info.
        //
        transContext = PCIEGetTransactionContext( devExt->WriteDmaTransaction );
        transContext->Request = Request;
    }
#endif

#if 0 //FYI
        //
        // Modify the MaximumLength for this DmaTransaction only.
        //
        // Note: The new length must be less than or equal to that set when
        //       the DmaEnabler was created.
        //
        {
            ULONG length =  devExt->MaximumTransferLength / 2;

            //TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
            //            "Setting a new MaxLen %d", length);

            WdfDmaTransactionSetMaximumLength( devExt->WriteDmaTransaction, length );
        }
#endif

    //
    // Execute this DmaTransaction transaction.
    //
    status = WdfDmaTransactionExecute( devExt->WriteDmaTransaction, 
                                       WDF_NO_CONTEXT);

    if(!NT_SUCCESS(status)) {

        //
        // Couldn't execute this DmaTransaction, so fail Request.
        //
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                    "WdfDmaTransactionExecute failed: %!STATUS!", status);
        goto CleanUp;
    }

    //
    // Indicate that Dma transaction has been started successfully. The request
    // will be complete by the Dpc routine when the DMA transaction completes.
    //
    status = STATUS_SUCCESS;

CleanUp:

    //
    // If there are errors, then clean up and complete the Request.
    //
    if (!NT_SUCCESS(status)) {
        WdfDmaTransactionRelease(devExt->WriteDmaTransaction);        
        WdfRequestComplete(Request, status);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "<-- PCIEEvtIoWrite: %!STATUS!", status);

    return;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
BOOLEAN
PCIEEvtProgramWriteDma(
    IN  WDFDMATRANSACTION       Transaction,
    IN  WDFDEVICE               Device,
    IN  PVOID                   Context,
    IN  WDF_DMA_DIRECTION       Direction,
    IN  PSCATTER_GATHER_LIST    SgList
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    PDEVICE_EXTENSION        devExt;
    size_t                   offset;
    PDMA_TRANSFER_ELEMENT    dteVA;
    ULONG_PTR                dteLA;
    BOOLEAN                  errors;
    ULONG                    i;

    UNREFERENCED_PARAMETER( Context );
    UNREFERENCED_PARAMETER( Direction );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "--> PCIEEvtProgramWriteDma");

    //
    // Initialize locals
    //
    devExt = PCIEGetDeviceContext(Device);
    errors = FALSE;

    //
    // Get the number of bytes as the offset to the beginning of this
    // Dma operations transfer location in the buffer.
    //
    offset = WdfDmaTransactionGetBytesTransferred(Transaction);

    //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -