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

📄 write.c

📁 基于xilinx vierex5得pci express dma设计实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
    // Setup the pointer to the next DMA_TRANSFER_ELEMENT
    // for both virtual and physical address references.
    //
    dteVA = (PDMA_TRANSFER_ELEMENT) devExt->WriteCommonBufferBase;
    dteLA = (devExt->WriteCommonBufferBaseLA.LowPart +
                        sizeof(DMA_TRANSFER_ELEMENT));

    //
    // Translate the System's SCATTER_GATHER_LIST elements
    // into the device's DMA_TRANSFER_ELEMENT elements.
    //
    for (i=0; i < SgList->NumberOfElements; i++) {

        //
        // Construct this DTE.
        //
        // NOTE: The LocalAddress is the offset into the SRAM from
        //       where this Write will start.
        //
        dteVA->PciAddressLow  = SgList->Elements[i].Address.LowPart;
        dteVA->PciAddressHigh = SgList->Elements[i].Address.HighPart;
        dteVA->TransferSize   = SgList->Elements[i].Length;

        dteVA->LocalAddress   = (ULONG) offset;

        dteVA->DescPtr.DescLocation  = DESC_PTR_DESC_LOCATION__PCI;
        dteVA->DescPtr.TermCountInt  = FALSE;
        dteVA->DescPtr.LastElement   = FALSE;
        dteVA->DescPtr.DirOfTransfer = DESC_PTR_DIRECTION__TO_DEVICE;
        dteVA->DescPtr.Address       = DESC_PTR_ADDR( dteLA );

        //
        // Increment the DmaTransaction length by this element length
        //
        offset += SgList->Elements[i].Length;

        //
        // If at end of SgList, then set LastElement bit in final NTE.
        //
        if (i == SgList->NumberOfElements - 1) {

            dteVA->DescPtr.LastElement = TRUE;

#if 0 // set to 1 for recording the details
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                        "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
                        "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
                        i,
                        dteVA->PciAddressHigh,
                        dteVA->PciAddressLow,
                        dteVA->TransferSize,
                        dteVA->LocalAddress,
                        dteVA->DescPtr.DescLocation,
                        dteVA->DescPtr.LastElement,
                        dteVA->DescPtr.TermCountInt,
                        dteVA->DescPtr.DirOfTransfer );
#endif
            break;
        }

#if 0 // set to 1 for recording the details
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                    "\tDTE[%d] : Addr #%X%08X Len %5d, Local %08X, "
                    "Loc(%d), Last(%d), TermInt(%d), ToPci(%d)\n",
                    i,
                    dteVA->PciAddressHigh,
                    dteVA->PciAddressLow,
                    dteVA->TransferSize,
                    dteVA->LocalAddress,
                    dteVA->DescPtr.DescLocation,
                    dteVA->DescPtr.LastElement,
                    dteVA->DescPtr.TermCountInt,
                    dteVA->DescPtr.DirOfTransfer );
#endif

        //
        // Adjust the next DMA_TRANSFER_ELEMEMT
        //
        dteVA++;
        dteLA += sizeof(DMA_TRANSFER_ELEMENT);
    }

    //
    // Start the DMA operation.
    // Acquire this device's InterruptSpinLock.
    //
    WdfInterruptAcquireLock( devExt->Interrupt );

    //
    // DMA 0 Mode Register - (DMAMODE0)
    // Enable Scatter/Gather Mode, Interrupt On Done,
    // and route Ints to PCI.
    //
    {
        union {
            DMA_MODE  bits;
            ULONG     ulong;
        } dmaMode;

        dmaMode.ulong =
            READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode );

        dmaMode.bits.SgModeEnable  = TRUE;
        dmaMode.bits.DoneIntEnable = TRUE;
        dmaMode.bits.IntToPci      = TRUE;

        WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Mode,
                              dmaMode.ulong );
    }

    //
    // Interrupt CSR Register - (INTCSR)
    // Enable PCI Ints and DMA Channel 0 Ints.
    //
    {
        union {
            INT_CSR   bits;
            ULONG     ulong;
        } intCSR;

        intCSR.ulong =
            READ_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr );

        intCSR.bits.PciIntEnable      = TRUE;
        intCSR.bits.DmaChan0IntEnable = TRUE;

        WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Int_Csr,
                              intCSR.ulong );
    }

    //
    // DMA 0 Descriptor Pointer Register - (DMADPR0)
    // Write the base LOGICAL address of the DMA_TRANSFER_ELEMENT list.
    //
    {
        union {
            DESC_PTR  bits;
            ULONG     ulong;
        } ptr;

        ptr.bits.DescLocation = DESC_PTR_DESC_LOCATION__PCI;
        ptr.bits.TermCountInt = TRUE;
        ptr.bits.Address      =
            DESC_PTR_ADDR( devExt->WriteCommonBufferBaseLA.LowPart );

        WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->Dma0_Desc_Ptr,
                              ptr.ulong );
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
                "    PCIEEvtProgramWriteDma: Start a Write DMA operation");

    //
    // DMA 0 CSR Register - (DMACSR0)
    // Start the DMA operation: Set Enable and Start bits.
    //
    {
        union {
            DMA_CSR  bits;
            UCHAR    uchar;
        } dmaCSR;

        dmaCSR.uchar =
            READ_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr );

        dmaCSR.bits.Enable = TRUE;
        dmaCSR.bits.Start  = TRUE;

        WRITE_REGISTER_UCHAR( (PUCHAR) &devExt->Regs->Dma0_Csr,
                              dmaCSR.uchar );
    }

    //
    // Release our interrupt spinlock
    //
    WdfInterruptReleaseLock( devExt->Interrupt );

    //
    // NOTE: This shows how to process errors which occur in the
    //       PFN_WDF_PROGRAM_DMA function in general.
    //       Basically the DmaTransaction must be deleted and
    //       the Request must be completed.
    //
    if (errors) {
        //
        // Must abort the transaction before deleting it.
        //
        NTSTATUS status;

        (VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
        ASSERT(NT_SUCCESS(status));
        PCIEWriteRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
                    "<-- PCIEEvtProgramWriteDma: error ****");
        return FALSE;
    }

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

    return TRUE;
}


VOID
PCIEWriteRequestComplete(
    IN WDFDMATRANSACTION  DmaTransaction,
    IN NTSTATUS           Status
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    WDFDEVICE          device;
    WDFREQUEST         request;
    PDEVICE_EXTENSION  devExt;
    size_t             bytesTransferred;

    //
    // Initialize locals
    //
    device  = WdfDmaTransactionGetDevice(DmaTransaction);
    devExt  = PCIEGetDeviceContext(device);

#ifdef ASSOC_WRITE_REQUEST_WITH_DMA_TRANSACTION

    request = WdfDmaTransactionGetRequest(DmaTransaction);

#else
    //
    // If CreateDirect was used then there will be no assoc. Request.
    //
    {
        PTRANSACTION_CONTEXT transContext = PCIEGetTransactionContext(DmaTransaction);

        request = transContext->Request;
        transContext->Request = NULL;
        
    }
#endif

    //
    // Get the final bytes transferred count.
    //
    bytesTransferred =  WdfDmaTransactionGetBytesTransferred( DmaTransaction );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
                "PCIEWriteRequestComplete:  Request %p, Status %!STATUS!, "
                "bytes transferred %d\n",
                 request, Status, (int) bytesTransferred );

    WdfDmaTransactionRelease(DmaTransaction);        

    WdfRequestCompleteWithInformation( request, Status, bytesTransferred);

}


⌨️ 快捷键说明

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