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

📄 init.c

📁 基于xilinx vierex5得pci express dma设计实现。
💻 C
📖 第 1 页 / 共 3 页
字号:
    KeDelayExecutionThread( KernelMode, TRUE, &delay );
}

// IoDeviceControl is called for IRP_MJ_DEVICE_CONTROL
VOID PCIEIOCtrlCode(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
 /*++
Routine Description:

    This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
    requests from the system.

Arguments:

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

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.
Return Value:

    VOID
    
--*/
{
    PDEVICE_EXTENSION       devExt;
    ULONG                   length;
    NTSTATUS                status = STATUS_SUCCESS;
    PVOID                   inBuffer;
    PVOID                   outBuffer;
    PHYSICAL_ADDRESS        phyAddress;
    SIZE_T                  copySize;
    PVOID                   logicalAddress;
    PVOID                   logicalAddress2;
    ULONG                   uLong;
    ULONG                   uData;
    ULONG                   dwDMASize;
    ULONG                   dwDMACount;
    ULONG                   dwDMAPattern;
    ULONG                   dwDMASize2;
    ULONG                   dwDMACount2;

    size_t                  InBufferSize;
    size_t                  OutBufferSize;

    ULONG                   i;
    ULONG                   uTemp;

    __int64     i64Start;
    __int64     i64End;
    __int64     i64End2;
    __int64     i64Temp;

    PVOID       pSrc;
    PVOID       pDst;
    PHYSICAL_ADDRESS        phyAddress1;
    PHYSICAL_ADDRESS        phyAddress2;

    LARGE_INTEGER delay;
    PULONG                  pOutBuffer;

    union
    {
        DMA_CSR2    bits;
        ULONG       ulong;
    }DMACSR2;

    union
    {
        DMA_CSR1    bits;
        ULONG       ulong;
    }DMACSR1;

    UNREFERENCED_PARAMETER( InputBufferLength  );

    //
    // Get the device extension.
    //
    devExt = PCIEGetDeviceContext(WdfIoQueueGetDevice( Queue ));


    if (InputBufferLength > 0)
    {
    status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inBuffer, &InBufferSize);
    if( !NT_SUCCESS(status) )
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, 
                        "WdfRequestRetrieveBuffer failed 0x%x\n", status);
        
        WdfRequestComplete(Request, status);
        return;
        }
    }
    else
    {
        inBuffer = NULL;
        InBufferSize = 0;
    }

    if (OutputBufferLength > 0)
    {
    status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outBuffer, &OutBufferSize);
    if( !NT_SUCCESS(status) )
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, 
                        "WdfRequestRetrieveBuffer failed 0x%x\n", status);
        
        WdfRequestComplete(Request, status);
        return;
        }
    }
    else
    {
        outBuffer = NULL;
        OutBufferSize = 0;
    }


    //
    // Handle this request's specific code.
    //
    switch (IoControlCode)
    {

    case IOCTL_GET_VERSION:
    {
        // ULONG version
        if (OutputBufferLength < sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        *(PULONG) outBuffer = 0x0004000A;

        status = STATUS_SUCCESS;
        length = sizeof(ULONG);
        break;
    }

    case IOCTL_PHY_TO_LOGICAL:
    {
        // ULONG phyaddress, SIZE_T length
        if (InputBufferLength != sizeof(ULONG) + sizeof(SIZE_T))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        // PVOID logicalAddress
        if (OutputBufferLength < sizeof(PVOID))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        phyAddress.LowPart  = *(PULONG)inBuffer;
        phyAddress.HighPart = 0;
        
        copySize  = *(SIZE_T *)((BYTE *)inBuffer + sizeof(ULONG));

        *(PVOID *)outBuffer = MmMapIoSpace(phyAddress, copySize, MmNonCached);

        status = STATUS_SUCCESS;
        length = sizeof(PVOID);
        break;
    }

    case IOCTL_LOGICAL_TO_PHY:
    {
        // PVOID logicaladdress
        if (InputBufferLength != sizeof(PVOID))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        // ULONG physicalAddress
        if (OutputBufferLength < sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        logicalAddress = *(PVOID *)inBuffer;

        // Get physical address
        phyAddress = MmGetPhysicalAddress(logicalAddress);
        *(PULONG)outBuffer = phyAddress.LowPart;

        status = STATUS_SUCCESS;
        length = sizeof(ULONG);
        break;
    }

    case IOCTL_ALLOC:
    {
        // ULONG length
        if (InputBufferLength != sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        // PVOID address
        if (OutputBufferLength < sizeof(PVOID))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }


        uLong = *(ULONG *)inBuffer;
        
        logicalAddress = MmAllocateNonCachedMemory(uLong);

        *(PVOID *)outBuffer = logicalAddress;

        status = STATUS_SUCCESS;
        length = sizeof(PVOID);
        
        break;
    }

    case IOCTL_FREE:
    {
        // PVOID address, SIZE_T length
        if (InputBufferLength != sizeof(PVOID) + sizeof(SIZE_T))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        logicalAddress = *(PVOID *)inBuffer;
        copySize       = *(SIZE_T *)((BYTE *)inBuffer + sizeof(PVOID));
        
        MmFreeNonCachedMemory(logicalAddress, copySize);

        status = STATUS_SUCCESS;
        length = 0;

        break;
    }

    case IOCTL_COPY_LOGICAL:
    {
        // PVOID sourceaddress, PVOID destaddress, SIZE_t length
        if (InputBufferLength != sizeof(PVOID) + sizeof(PVOID) + sizeof(SIZE_T))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }
        // SIZE_t length
        if (OutputBufferLength != sizeof(SIZE_T))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        logicalAddress  = *(PVOID *)inBuffer;
        logicalAddress2 = *(PVOID *)((BYTE *)inBuffer + sizeof(PVOID));
        copySize        = *(SIZE_T *)((BYTE *)inBuffer + sizeof(PVOID) + sizeof(PVOID));

        RtlCopyMemory(logicalAddress2, logicalAddress, copySize);

        *(SIZE_T *)outBuffer = copySize;

        status = STATUS_SUCCESS;
        length = sizeof(SIZE_T);

        break;
    }

    case IOCTL_DMA_HOST_DEVICE:
    {
        // DEVICE READ. 
        // in : SIZE_t size, SIZE_t count
        // out: ULONG performance, ULONG tscCounter_Int, ULONG deviceReadCompletionSize
        if (InputBufferLength != sizeof(SIZE_T) + sizeof(SIZE_T))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }
        // SIZE_t length
        if (OutputBufferLength != sizeof(ULONG) * 3)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        KdPrint(("DMA_HOST_DEVICE: begin"));


        dwDMASize      = *(SIZE_T *)((char *)inBuffer);
        dwDMACount     = *(SIZE_T *)((char *)inBuffer + sizeof(SIZE_T));
        
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->ReadDMATLPAddress, (ULONG)devExt->BufferPhysicalAddress);
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->ReadDMATLPSize,    dwDMASize);
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->ReadDMATLPCount,   dwDMACount);

        DMACSR2.ulong = READ_REGISTER_ULONG((PULONG)&devExt->Regs->DCSR2);

        DMACSR2.bits.WriteDMADone  = 0;
        DMACSR2.bits.WriteDMAStart = 0;
        DMACSR2.bits.ReadDMADone   = 0;
        DMACSR2.bits.ReadDMAStart  = 1;

        devExt->ReadEndTsc  = 0;
        i = 0;
        
        _asm rdtsc
        _asm mov DWORD PTR i64Start, EAX
        _asm mov DWORD PTR (i64Start+4), EDX

        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->DCSR2,   DMACSR2.ulong);

        // wait while dmadone signal

        do{
            _asm rdtsc
            _asm mov DWORD PTR i64End, EAX
            _asm mov DWORD PTR (i64End+4), EDX

        }while(devExt->ReadEndTsc == 0 && (i64End - i64Start) < 0xffffffff);        // wait for 2 second(for 2GHZ)

        if (devExt->ReadEndTsc == 0)
        {
            status = STATUS_SUCCESS;
            *(ULONG *)outBuffer = (ULONG)-1;
            length = sizeof(ULONG);
            break;
        }

        *(ULONG *)outBuffer                                           = READ_REGISTER_ULONG((PULONG)&devExt->Regs->ReadDMAPerformance);
        *(ULONG *)((PUCHAR)outBuffer + sizeof(ULONG))                 = (ULONG)(devExt->ReadEndTsc - i64Start);
        *(ULONG *)((PUCHAR)outBuffer + sizeof(ULONG) + sizeof(ULONG)) = READ_REGISTER_ULONG((PULONG)&devExt->Regs->NumberOfReadCompletionWithData);

        status = STATUS_SUCCESS;
        length = sizeof(ULONG) * 3;

        break;
    }

    case IOCTL_DMA_DEVICE_HOST:
    {
        // DEVICE WRITE. 
        // in : SIZE_T size, SIZE_T count, ULONG pattern
        // out: ULONG performance, ULONG tscCounter_Int
        if (InputBufferLength != sizeof(SIZE_T) + sizeof(SIZE_T) + sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }
        // SIZE_T length
        if (OutputBufferLength != sizeof(ULONG) + sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;
            break;
        }

        KdPrint(("DMA_DEVICE_HOST: begin"));


        dwDMASize      = *(SIZE_T *)((char *)inBuffer);
        dwDMACount     = *(SIZE_T *)((char *)inBuffer + sizeof(SIZE_T));
        dwDMAPattern   = *(ULONG  *)((char *)inBuffer + sizeof(SIZE_T) + sizeof(SIZE_T));


        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMATLPAddress,     (ULONG)devExt->Buffer2PhysicalAddress);
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMATLPSize,        dwDMASize);
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMATLPCount,       dwDMACount);
        WRITE_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMATLPDataPattern, dwDMAPattern);


        DMACSR2.ulong = READ_REGISTER_ULONG((PULONG)&devExt->Regs->DCSR2);

⌨️ 快捷键说明

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