(续)X64的WINDRIVER开发

下面开始讲述利用WINDRIVER进行开发PCIE驱动,具体步骤如下图所示。在例子程序里有两种DMA传输方式 , 一种是通过查询方式,另一种是通过中断方式,上图是按照查询方式进行的,比较简单。简易来说,就是先打开PCIE的设备,然后为它分配内核物理内存,将分配到的物理地址写到PCIE卡里相应的寄存器,然后配置一些必须的DMA传输的包大小、包数等寄存器后便可开始DMA传输。    主要代码如下

static void myDMATranlation(WDC_DEVICE_HANDLE hDev, PDIAG_DMA pDma, BOOL fPolling, BOOL IsRead, char *mypBuf)在此完成所有的DMA传输操作,包括读写
{
    DWORD dwStatus, dwOptions, i;
    UINT32 u32Pattern;
    WORD wSize, wCount;
    BOOL fIsRead;
    BOOL fEnable64bit;
    BYTE bTrafficClass;
	DWORD dwTotalCount;

	u32Pattern = 0x10203040;
	wCount = 256;

	if(IsRead)
		dwOptions = DMA_TO_DEVICE;//设置为读
	else
		dwOptions = DMA_FROM_DEVICE;

    fIsRead = dwOptions & DMA_FROM_DEVICE ? FALSE : TRUE;

    /* The BMD reference design does not support s/g DMA, so we use contiguous
     */
    dwOptions |= DMA_KERNEL_BUFFER_ALLOC;    ///采用内核分配BUFFER的方式

    /* Get the max payload size from the device */
   // wSize = VIRTEX5_DMAGetMaxPacketSize(hDev, fIsRead) / sizeof(UINT32);
    wSize = 32;    固定为128!!!!!!!!


    dwTotalCount = (DWORD)wCount * (DWORD)wSize;

    /* Open DMA handle */
    dwStatus = VIRTEX5_DMAOpen(hDev, &pDma->pBuf, dwOptions,
        dwTotalCount * sizeof(UINT32), &pDma->hDma);
    if (WD_STATUS_SUCCESS != dwStatus)
    {
        printf("\nFailed to open DMA handle. Error 0x%lx - %s\n", dwStatus,
            Stat2Str(dwStatus));
        return;
    }

    printf("\nDMA handle was opened successfully (handle 0x%lx)\n", pDma->hDma);
    printf("Payload packet size in dwords 0x%hx\n", wSize);

	/* Prepare the device registers for DMA transfer */
	fEnable64bit = FALSE;
	bTrafficClass = 0;
	VIRTEX5_DMADevicePrepare(pDma->hDma, fIsRead, wSize, wCount, u32Pattern,
		fEnable64bit, bTrafficClass, myaddr_offset);      /*配置卡上的DMA控制器寄存器*/

	VIRTEX5_DmaIntDisable(hDev, fIsRead);
	/* Initialize the DMA buffer with user defined pattern */

	if(fIsRead)
		memcpy((char *)pDma->pBuf,mypBuf,dwTotalCount * sizeof(UINT32));
	else
		memset((char *)pDma->pBuf, 0xdeadbeaf, dwTotalCount * sizeof(UINT32));

	/* Start DMA */
	printf("Start DMA transfer\n");
	VIRTEX5_DMAStart(pDma->hDma, fIsRead);//DMA从此开始占用CPU,开始
	 /* Poll for completion (if polling selected) */
   
	if (fPolling)
    {
        if (VIRTEX5_DMAPollCompletion(pDma->hDma, fIsRead))
        {
          //  DmaTransferVerify(hDev, pDma->pBuf, dwTotalCount, u32Pattern, fIsRead);
			printf("tranlation is done!\n");
        }
        else 
            printf("timeout\n");
    }
    return;
Error:
    DIAG_DMAClose(hDev, pDma);
}


void VIRTEX5_DMADevicePrepare(VIRTEX5_DMA_HANDLE hDma, BOOL fIsRead, WORD wSize,
    WORD wCount, UINT32 u32Pattern, BOOL fEnable64bit, BYTE bTrafficClass, WORD wPcieAddr)
{
    UINT32 tlps;
    UINT32 LowerAddr;
    BYTE UpperAddr;
    WDC_DEVICE_HANDLE hDev;
    PVIRTEX5_DEV_CTX pDevCtx;

    if (!IsValidDmaHandle(hDma, "VIRTEX5_DMADevicePrepare"))
        return;

    hDev = hDma->hDev;

    /* Assert Initiator Reset */
    VIRTEX5_WriteReg32(hDev, DCR_OFFSET, 0x1);   /*复位,写1*/

    /* De-assert Initiator Reset */
    VIRTEX5_WriteReg32(hDev, DCR_OFFSET, 0x0);  /*复位,写0*/

    LowerAddr = (UINT32)hDma->pDma->Page[0].pPhysicalAddr;    ///低地址,物理地址
    UpperAddr = (BYTE)((hDma->pDma->Page[0].pPhysicalAddr >> 32) & 0xFF);///高地址,物理地址

	printf("LowerAddr is %x\n", LowerAddr);
	printf("UpperAddr is %x\n", UpperAddr);

    //tlps = (wSize & 0x1FFF) | /* tlps[0:12] - DMA TLP size */
   //     ((bTrafficClass & 0x7) << 16) | /* tlps[16:18] -
   //                                        DMA TLP Traffic Class */
   //     (fEnable64bit ? BIT19 : 0) | /* tlps[19] enable 64bit TLP */
   //     (UpperAddr << 24); /* tlps[24:31] - upper bits 33:39 of DMA addr*/

	tlps = wSize & 0x1fff;    //只有低12位有效

    if (fIsRead)
    {
        /* Set lower 32bit of DMA address */
        VIRTEX5_WriteReg32(hDev, READ_ADDR_OFFSET, LowerAddr);

        /* Set size, traffic class, 64bit enable, upper 8bit of DMA address */
        VIRTEX5_WriteReg32(hDev, READ_SIZE_OFFSET, tlps);

        /* Set TLP count */
        VIRTEX5_WriteReg16(hDev, READ_COUNT_OFFSET, wCount);

        /* Set Read DMA pattern */
        VIRTEX5_WriteReg32(hDev, READ_PATTERN_OFFSET, u32Pattern);

        VIRTEX5_WriteReg32(hDev, PCIE_READ_ADDR_OFFSET, wPcieAddr);
    }
    else
    {
        /* Set lower 32bit of DMA address */
        VIRTEX5_WriteReg32(hDev, WRITE_ADDR_OFFSET, LowerAddr);

        /* Set size, traffic class, 64bit enable, upper 8bit of DMA address */
        VIRTEX5_WriteReg32(hDev, WRITE_SIZE_OFFSET, tlps);

        /* Set TLP count */
        VIRTEX5_WriteReg16(hDev, WRITE_COUNT_OFFSET, wCount);

        /* Set Read DMA pattern */
        VIRTEX5_WriteReg32(hDev, WRITE_PATTERN_OFFSET, u32Pattern);

		VIRTEX5_WriteReg32(hDev, PCIE_WRITE_ADDR_OFFSET, wPcieAddr);
    }

    pDevCtx = (PVIRTEX5_DEV_CTX)WDC_GetDevContext(hDev);
    pDevCtx->fIsRead = fIsRead;
    pDevCtx->u32Pattern = u32Pattern;
    pDevCtx->dwTotalCount = (DWORD)wCount * (DWORD)wSize;
}


void VIRTEX5_DMAStart(VIRTEX5_DMA_HANDLE hDma, BOOL fIsRead)
{
    if (!IsValidDmaHandle(hDma, "VIRTEX5_DMAStart"))
        return;

    VIRTEX5_DMASyncCpu(hDma);

    /* Start DMA Transfer */
    VIRTEX5_WriteReg32(hDma->hDev, VIRTEX5_DDMACR_OFFSET,   /*此处0X10000指读DMA操作开始, 0X1表示写DMA操作开始**/
        fIsRead ? 0x10000 : 0x1);
}

流程图



  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值