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

📄 init.c

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

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


        devExt->WriteEndTsc = 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->WriteEndTsc == 0 && (i64End - i64Start) < 0xffffffff);

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

        *(ULONG *)outBuffer = READ_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMAPerformance);
        *(ULONG *)((PUCHAR)outBuffer + sizeof(ULONG)) = (ULONG)(devExt->WriteEndTsc - i64Start);

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

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

        KdPrint(("DMA_PCI_TEST: begin"));


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

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

        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 = 1;
        DMACSR2.bits.ReadDMADone   = 0;
        DMACSR2.bits.ReadDMAStart  = 1;

        devExt->WriteEndTsc = 0;
        devExt->ReadEndTsc  = 0;

        i64End  = 0;
        i64End2 = 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 i64Temp, EAX
            _asm mov DWORD PTR (i64Temp + 4), EDX

            if (DMACSR2.bits.WriteDMADone && (i64End == 0))
            {
                i64End = i64Temp;
            }
            if (DMACSR2.bits.ReadDMADone && (i64End2 == 0))
            {
                i64End2 = i64Temp;
            }
        }while((devExt->ReadEndTsc == 0 || devExt->WriteEndTsc == 0) && (i64Temp - i64Start) < 0xffffffff);

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


        pOutBuffer = (PULONG)outBuffer;

        *pOutBuffer = READ_REGISTER_ULONG((PULONG)&devExt->Regs->ReadDMAPerformance);
        ++pOutBuffer;
        
        *pOutBuffer = (ULONG)(devExt->ReadEndTsc - i64Start);
        ++pOutBuffer;
        
        *pOutBuffer = READ_REGISTER_ULONG((PULONG)&devExt->Regs->NumberOfReadCompletionWithData);
        ++pOutBuffer;
        
        *pOutBuffer = READ_REGISTER_ULONG((PULONG)&devExt->Regs->WriteDMAPerformance);
        ++pOutBuffer;
        
        *pOutBuffer = (ULONG)(devExt->WriteEndTsc - i64Start);
        

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


    case IOCTL_GET_BUFFERADDRESS:
    {
        // SIZE_T length
        if (OutputBufferLength != sizeof(ULONG) * 6)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d", OutputBufferLength));
            break;
        }

        // buffer
        KdPrint(("PHYADDRESS    : 0X%08X",  devExt->BufferPhysicalAddress));
        KdPrint(("LogicalADDRESS: 0X%08X",  devExt->BufferLogicalAddress));

        phyAddress.HighPart = 0;
        phyAddress.LowPart  = (ULONG)devExt->BufferPhysicalAddress;

        devExt->BufferSystemVirtualAddress = MmMapIoSpace(phyAddress, PCIE_BUFFER_SIZE, MmNonCached);
        devExt->BufferMdl = IoAllocateMdl(devExt->BufferSystemVirtualAddress, PCIE_BUFFER_SIZE, FALSE, FALSE, NULL);

        MmBuildMdlForNonPagedPool(devExt->BufferMdl);

        devExt->BufferUserVirtualAddress = (PVOID)(((ULONG)PAGE_ALIGN(MmMapLockedPages(devExt->BufferMdl, UserMode))) + MmGetMdlByteOffset(devExt->BufferMdl));

        KdPrint(("SystemVirtualAddress: 0x%08X", devExt->BufferSystemVirtualAddress));
        KdPrint(("UserVirtualAddress:   0x%08X", devExt->BufferUserVirtualAddress));

        

        // buffer2
        KdPrint(("PHYADDRESS2    : 0X%08X",  devExt->Buffer2PhysicalAddress));
        KdPrint(("LogicalADDRESS2: 0X%08X",  devExt->Buffer2LogicalAddress));

        phyAddress.HighPart = 0;
        phyAddress.LowPart  = (ULONG)devExt->Buffer2PhysicalAddress;

        devExt->Buffer2SystemVirtualAddress = MmMapIoSpace(phyAddress, PCIE_BUFFER_SIZE, MmNonCached);
        devExt->Buffer2Mdl = IoAllocateMdl(devExt->Buffer2SystemVirtualAddress, PCIE_BUFFER_SIZE, FALSE, FALSE, NULL);

        MmBuildMdlForNonPagedPool(devExt->Buffer2Mdl);

        devExt->Buffer2UserVirtualAddress = (PVOID)(((ULONG)PAGE_ALIGN(MmMapLockedPages(devExt->Buffer2Mdl, UserMode))) + MmGetMdlByteOffset(devExt->Buffer2Mdl));

        KdPrint(("SystemVirtualAddress2: 0x%08X", devExt->Buffer2SystemVirtualAddress));
        KdPrint(("UserVirtualAddress2:   0x%08X", devExt->Buffer2UserVirtualAddress));



        *(PULONG)outBuffer                                = (ULONG)devExt->BufferUserVirtualAddress;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG))      = (ULONG)devExt->BufferPhysicalAddress;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG) * 2)  = PCIE_BUFFER_SIZE;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG) * 3)  = (ULONG)devExt->Buffer2UserVirtualAddress;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG) * 4)  = (ULONG)devExt->Buffer2PhysicalAddress;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG) * 5)  = PCIE_BUFFER_SIZE;

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

    case IOCTL_FREE_BUFFERADDRESS:
    {
        if (devExt->BufferUserVirtualAddress && devExt->BufferSystemVirtualAddress && devExt->BufferMdl)
        {
            MmUnmapLockedPages(devExt->BufferUserVirtualAddress, devExt->BufferMdl);
            IoFreeMdl(devExt->BufferMdl);
            MmUnmapIoSpace(devExt->BufferSystemVirtualAddress, PCIE_BUFFER_SIZE);

            devExt->BufferSystemVirtualAddress  = NULL;
            devExt->BufferUserVirtualAddress    = NULL;
            devExt->BufferMdl                   = NULL;
        }

        if (devExt->Buffer2UserVirtualAddress && devExt->Buffer2SystemVirtualAddress && devExt->Buffer2Mdl)
        {
            MmUnmapLockedPages(devExt->Buffer2UserVirtualAddress, devExt->Buffer2Mdl);
            IoFreeMdl(devExt->Buffer2Mdl);
            MmUnmapIoSpace(devExt->Buffer2SystemVirtualAddress, PCIE_BUFFER_SIZE);

            devExt->Buffer2SystemVirtualAddress  = NULL;
            devExt->Buffer2UserVirtualAddress    = NULL;
            devExt->Buffer2Mdl                   = NULL;
        }
        status = STATUS_SUCCESS;
        length = 0;
        
        break;
    }

    case IOCTL_READ_REG:
    {
        // input : ULONG addr, ULONG repeat
        if (InputBufferLength != sizeof(ULONG) * 2)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d", InputBufferLength));
            break;
        }

        // output : ULONG data, ULONG tsc
        if (OutputBufferLength != sizeof(ULONG) * 2)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d", OutputBufferLength));
            break;
        }

        uLong = *(PULONG)inBuffer;
        uTemp = *(PULONG)((PUCHAR)inBuffer + sizeof(ULONG));

        if (uLong >= devExt->RegsLength)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Offset address: %d", uLong));
            break;
        }

        _asm rdtsc
        _asm mov DWORD PTR i64Start, EAX
        _asm mov DWORD PTR (i64Start + 4), EDX

        for(i=0; i<uTemp; ++i)
            *(PULONG)outBuffer   = READ_REGISTER_ULONG((PULONG)(devExt->RegsBase + uLong));

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

        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG)) = (ULONG)(i64End - i64Start);
        
        status = STATUS_SUCCESS;
        length = sizeof(ULONG) * 2;
        
        break;
    }

    case IOCTL_WRITE_REG:
    {
        // input : ULONG addr, ULONG data, ULONG repeattimes
        if (InputBufferLength != sizeof(ULONG) * 3)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d, should be %d", InputBufferLength, sizeof(ULONG) * 2));
            break;
        }
        // output : ULONG data
        if (OutputBufferLength != sizeof(ULONG))
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d", OutputBufferLength));
            break;
        }

        uLong = *(PULONG)inBuffer;
        uData = *(PULONG)((PUCHAR)inBuffer + sizeof(ULONG));
        uTemp = *(PULONG)((PUCHAR)inBuffer + sizeof(ULONG)*2);

        if (uLong >= devExt->RegsLength)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Offset address: %d", uLong));
            break;
        }

        _asm rdtsc
        _asm mov DWORD PTR i64Start, EAX
        _asm mov DWORD PTR (i64Start + 4), EDX

        for(i=0; i<uTemp; ++i)
            WRITE_REGISTER_ULONG((PULONG)(devExt->RegsBase + uLong), uData);

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

        *(PULONG)outBuffer = (ULONG)(i64End - i64Start);
        
        status = STATUS_SUCCESS;
        length = sizeof(ULONG);
        
        break;
    }

    case IOCTL_DEVICE_RESET:
    {
        PCIEHardwareReset(devExt);
        
        status = STATUS_SUCCESS;
        length = 0;
        break;
    }

    case IOCTL_GET_REGADDRESS:
    {
        
        // output : ULONG logical address, ULONG phyaddress, ULONG len
        if (OutputBufferLength != sizeof(ULONG) * 3)
        {
            status = STATUS_INVALID_PARAMETER;
            length = 0;

            KdPrint(("Length: %d", OutputBufferLength));
            break;
        }


        *(PULONG)outBuffer                       = (ULONG)devExt->RegsPhyBase;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG))     = (ULONG)devExt->RegsBase;
        *(PULONG)((PUCHAR)outBuffer + sizeof(ULONG) * 2) = (ULONG)devExt->RegsLength;

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

        break;
    }
    
    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        length = 0;
        break;
    }

    if (status != STATUS_PENDING)
    {
        WdfRequestCompleteWithInformation(Request, status, length);
    }

}



⌨️ 快捷键说明

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