linux-device-driver - 在 Qemu 上编写用于 DMA 传输的 PCI 驱动程序

标签 linux-device-driver qemu dma pci

我正在客户操作系统中的 Qemu 和驱动程序(LKM)上编写 PCI 设备。 Qemu 提供了一个示例 PCI 设备,教育 ( edu.txtedu.c )在它的发行版中,我无法编写内核模块来进行 DMA 传输。一个基本的驱动程序已覆盖here但它不支持 DMA。

我正在关注链接的实现和 this .我试图从 IRQ 处理程序将缓冲区传输到 PCI 设备。设备可以读取数据( pci_dma_read ),但我没有得到我应该接收的正确数据。这是进行 DMA 传输的代码段:

static int write_to_HyPerf(void *dev, void* addr, uint32_t size)
{
    /* ----------------------------------------------------------------------------
    * PCI address 'addr':
    * addr     -> DMA source address
    * 0x40000  -> DMA destination address
    * 100      -> DMA transfer count
    * 1        -> DMA command register
    * while (DMA command register & 1)
    *--------------------------------------------------------------------------------
    */
    iowrite32((u32 *)dma_handle_to_device, mmio + IO_DMA_SRC);
    iowrite32(DMA_START, mmio + IO_DMA_DST);
    iowrite32((u32 *)size, mmio + IO_DMA_XCNT);
    iowrite32(DMA_CMD | DMA_IRQ, mmio + IO_DMA_CMD);
}

我还使用 设置了相干映射dma_alloc_coherent .
vaddr_to_device = dma_alloc_coherent(&(dev->dev), DMA_SIZE, &dma_handle_to_device, GFP_ATOMIC);

完整代码可用here .我究竟做错了什么?

最佳答案

可能是您的驱动程序有问题。
在这种情况下,您可以使用:
https://github.com/cirosantilli/linux-kernel-module-cheat/blob/master/kernel_modules/qemu_edu.c
并且您可以在此脚本中使用 dd 命令来写入和读取您的设备:
https://github.com/cirosantilli/linux-kernel-module-cheat/blob/master/rootfs_overlay/lkmc/qemu_edu.sh
然后您只需将所需的 dma 值写入正确的地址
就像在 edu.c 代码中一样:

    case 0x80:
        dma_rw(edu, false, &val, &edu->dma.src, false);
        break;
    case 0x88:
        dma_rw(edu, false, &val, &edu->dma.dst, false);
        break;
    case 0x90:
        dma_rw(edu, false, &val, &edu->dma.cnt, false);
        break;
    case 0x98:
        dma_rw(edu, false, &val, &edu->dma.cmd, false);
        break;

关于linux-device-driver - 在 Qemu 上编写用于 DMA 传输的 PCI 驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51005341/

相关文章:

linux - arm-eabi arm-gnueabi 和 gnueabi-hf 编译器之间的区别

linux - 在 QEMU 中记录动态指令轨迹或直方图?

linux eth0 不能与网桥一起工作

c++ - 如何使用 GPU-CUDA 代码中的 GPU-DMA 来复制数据?

linux-kernel - 读取linux设备驱动中的配置文件

android - linux 中/dev/kmem char 设备的真正用途是什么?

sockets - 如何路由QEMU内部的TCP端口/套接字?

io - 了解内存映射文件

c - Linux 4.4 PCIe DMA 进入用户空间页面不工作 - highmem 不可用于 DMA?

c - 通过设备驱动程序访问 AXIS FIFO 寄存器时出现未处理的故障