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

📄 init.c

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

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:

    Init.c

Abstract:

    Contains most of initialization functions

Environment:

    Kernel mode

--*/

#include "precomp.h"

#include "Init.tmh"

#include <wdm.h>


#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, PCIEInitializeDeviceExtension)
#pragma alloc_text (PAGE, PCIEPrepareHardware)
#pragma alloc_text (PAGE, PCIEInitializeDMA)
#pragma alloc_text (PAGE, PCIEInitWrite)
#pragma alloc_text (PAGE, PCIEInitRead)
#endif

void PCIEWait(int ms);


VOID PCIEIOCtrlCode(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    );

NTSTATUS
PCIEInitializeDeviceExtension(
    IN PDEVICE_EXTENSION DevExt
    )
/*++
Routine Description:

    This routine is called by EvtDeviceAdd. Here the device context is
    initialized and all the software resources required by the device is
    allocated.

Arguments:

    DevExt     Pointer to the Device Extension

Return Value:

     NTSTATUS

--*/
{
    NTSTATUS    status;
    ULONG       dteCount;
    WDF_IO_QUEUE_CONFIG  queueConfig;

    PAGED_CODE();

    DevExt->MaximumTransferLength = PCIE_MAXIMUM_TRANSFER_LENGTH;    
    DevExt->BufferSystemVirtualAddress  = NULL;
    DevExt->BufferUserVirtualAddress    = NULL;
    DevExt->BufferMdl                   = NULL;
    
    DevExt->Buffer2SystemVirtualAddress = NULL;
    DevExt->Buffer2UserVirtualAddress   = NULL;    
    DevExt->Buffer2Mdl                  = NULL;

    //
    // Setup a queue to handle only IRP_MJ_WRITE requests in Sequential
    // dispatch mode. This mode ensures there is only one write request
    // outstanding in the driver at any time. Framework will present the next
    // request only if the current request is completed.
    // Since we have configured the queue to dispatch all the specific requests
    // we care about, we don't need a default queue.  A default queue is
    // used to receive requests that are not preconfigured to goto
    // a specific queue.
    //
    WDF_IO_QUEUE_CONFIG_INIT ( &queueConfig,
                              WdfIoQueueDispatchSequential);

    queueConfig.EvtIoDeviceControl = PCIEIOCtrlCode;

    status = WdfIoQueueCreate( DevExt->Device,
                                &queueConfig,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &DevExt->IOCtrlQueue );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed: %!STATUS!", status);
        return status;
    }

    //
    // Set the Write Queue forwarding for IRP_MJ_WRITE requests.
    //
    status = WdfDeviceConfigureRequestDispatching( DevExt->Device,
                                       DevExt->IOCtrlQueue,
                                       WdfRequestTypeDeviceControl);

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed: %!STATUS!", status);
        return status;
    }

    //
    // Create a WDFINTERRUPT object.
    //
    status = PCIEInterruptCreate(DevExt);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    return status;
}


NTSTATUS
PCIEPrepareHardware(
    IN PDEVICE_EXTENSION DevExt,
    IN WDFCMRESLIST     ResourcesTranslated
    )
/*++
Routine Description:

    Gets the HW resources assigned by the bus driver from the start-irp
    and maps it to system address space.

Arguments:

    DevExt      Pointer to our DEVICE_EXTENSION

Return Value:

     None

--*/
{
    ULONG               i;
    NTSTATUS            status = STATUS_SUCCESS;

    BOOLEAN             foundAddress   = FALSE;
    PHYSICAL_ADDRESS    AddressBasePA  = {0};
    ULONG               AddressLength  = 0;
    
    PHYSICAL_ADDRESS    physicalAddress = {0, 0};
    
    ULONG               j;

    WDF_DMA_ENABLER_CONFIG   dmaConfig;

    PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;

    PAGED_CODE();


    DevExt->BufferPhysicalAddress = NULL;
    DevExt->BufferLogicalAddress  = NULL;
    DevExt->BufferSize            = 0;

    DevExt->Buffer2PhysicalAddress = NULL;
    DevExt->Buffer2LogicalAddress  = NULL;
    DevExt->Buffer2Size            = 0;


    //
    // Parse the resource list and save the resource information.
    //
    for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {

        desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i );


        if(!desc) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfResourceCmGetDescriptor failed");
            return STATUS_DEVICE_CONFIGURATION_ERROR;
        }

        switch (desc->Type) {

            case CmResourceTypeMemory:

                if (!foundAddress )
                {
                    AddressBasePA = desc->u.Memory.Start;
                    AddressLength = desc->u.Memory.Length;
                    foundAddress  = TRUE;
                    
                    
                    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                                " BAR0 TRACED");
                }

                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                            " - Memory Resource [%I64X-%I64X] BAR0",
                            desc->u.Memory.Start.QuadPart,
                            desc->u.Memory.Start.QuadPart + desc->u.Memory.Length );
                break;

            default:
                //
                // Ignore all other descriptors
                //
                break;
        }
    }

    if (!foundAddress)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "PCIEMapResources: Missing resources");
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    //
    // Map in the Registers Memory resource: BAR0
    //


    // ????
    AddressLength       = sizeof(ULONG) * 64;
    DevExt->RegsPhyBase = (PUCHAR)AddressBasePA.LowPart;
    DevExt->RegsBase    = (PUCHAR) MmMapIoSpace( AddressBasePA,
                                              AddressLength,
                                              MmNonCached );

    DevExt->RegsLength = AddressLength;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                " - Registers %p, length %d",
                DevExt->RegsBase, DevExt->RegsLength );

    if (!DevExt->RegsBase) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    " - Unable to map BAR1 memory %08I64X, length %d",
                    AddressBasePA.QuadPart,  AddressLength);
        return STATUS_INSUFFICIENT_RESOURCES;
    }


    DevExt->Regs = (PPCIE_REGS)DevExt->RegsBase;


    // Allocate The Buffer for DMA
    // DWORD X 0x20 X MAXCount(1024) = 4 x 32 x 1024 = 128 K
    DevExt->BufferSize            = PCIE_BUFFER_SIZE;       // 16 M     
    DevExt->Buffer2Size           = PCIE_BUFFER_SIZE;       // 16 M     

    physicalAddress.LowPart  = 0x80000000;
    physicalAddress.HighPart = 0;
    DevExt->BufferLogicalAddress   = MmAllocateContiguousMemory(DevExt->BufferSize, physicalAddress);
    DevExt->Buffer2LogicalAddress  = MmAllocateContiguousMemory(DevExt->Buffer2Size, physicalAddress);

    if (DevExt->BufferLogicalAddress)
    {
        physicalAddress = MmGetPhysicalAddress((PVOID)DevExt->BufferLogicalAddress);
        DevExt->BufferPhysicalAddress = (PUCHAR)physicalAddress.LowPart;

        KdPrint(("PCIE: Alloc Physical Buffer  OK!"));

    }
    else
    {
        KdPrint(("PCIE: Alloc Physical Buffer  FAILED!"));
    }

    if (DevExt->Buffer2LogicalAddress)
    {
        physicalAddress = MmGetPhysicalAddress((PVOID)DevExt->Buffer2LogicalAddress);
        DevExt->Buffer2PhysicalAddress = (PUCHAR)physicalAddress.LowPart;

        KdPrint(("PCIE: Alloc Physical Buffer 2  OK!"));

    }
    else
    {
        KdPrint(("PCIE: Alloc Physical Buffer 2 FAILED!"));
    }

    return status;
}

VOID
PCIEShutdown(
    IN PDEVICE_EXTENSION DevExt
    )
/*++

Routine Description:

    Reset the device to put the device in a known initial state.
    This is called from D0Exit when the device is torn down or
    when the system is shutdown. Note that Wdf has already
    called out EvtDisable callback to disable the interrupt.

Arguments:

    DevExt -  Pointer to our adapter

Return Value:

    None

--*/
{
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "---> PCIEShutdown");

    //
    // WdfInterrupt is already disabled so issue a full reset
    //
    if (DevExt->Regs) {

        PCIEHardwareReset(DevExt);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--- PCIEShutdown");
}

VOID
PCIEHardwareReset(
    IN PDEVICE_EXTENSION DevExt
    )
/*++
Routine Description:

    Called by D0Exit when the device is being disabled or when the system is shutdown to
    put the device in a known initial state.

Arguments:

    DevExt     Pointer to Device Extension

Return Value:

--*/
{

    LARGE_INTEGER delay;

    union {
        DMA_CSR1    bits;
        ULONG       ulong;
    } DMACSR1;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PCIEHardwareReset");

    //
    // Drive the device into soft reset.
    //
    DMACSR1.ulong = READ_REGISTER_ULONG( (PULONG) &DevExt->Regs->DCSR1 );

    DMACSR1.bits.InitiatorReset = 1;

    WRITE_REGISTER_ULONG((PULONG) &DevExt->Regs->DCSR1, DMACSR1.ulong );

    //
    // Wait 100 msec.
    //
    delay.QuadPart =  WDF_REL_TIMEOUT_IN_MS(100);

    KeDelayExecutionThread( KernelMode, TRUE, &delay );

    //
    // Finally pull the device out of reset.
    //
    DMACSR1.bits.InitiatorReset = 0;

    WRITE_REGISTER_ULONG((PULONG) &DevExt->Regs->DCSR1, DMACSR1.ulong );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PCIEIssueFullReset");
}


void PCIEWait(int ms)
{
    LARGE_INTEGER delay;
    
    delay.QuadPart =  WDF_REL_TIMEOUT_IN_MS(ms);

⌨️ 快捷键说明

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