PCI驱动访问设备内存方式


pci_request_selected_regions功能:为设备内存分配物理地址空间。

ioremap功能:将设备物理地址空间映射成虚拟地址空间,从而驱动可以访问。


static int nvme_dev_map(struct nvme_dev *dev)
{
int bars, result = -ENOMEM;
struct pci_dev *pdev = dev->pci_dev;


if (pci_enable_device_mem(pdev))
return result;

dev->entry[0].vector = pdev->irq;
pci_set_master(pdev);
bars = pci_select_bars(pdev, IORESOURCE_MEM);

 // request iomem for the selected bars, means alloc physical addrs for the mem in pci device.

        /* 1.PCI设备的256字节配置的header中包含6个bar,每个bar制定一个io port地址空间,或者io mem地址

            空间,实际使用中,可能一个bar就够用了。

            2.pci_request_selected_regions函数的工作就是按照bar要求的起始地址和长度分配物理地址空间。

            3.分配地址的目的就是希望驱动可以直接通过这些地址访问PCI设备的内存,但是该函数返回的是物理地址

             在基于分页的虚拟内存管理系统中,驱动无法直接访问物理地址,要调用ioremap函数将物理地址映射到

             虚拟地址,从而达到驱动可以访问PCI设备中内存的目的。

        */

if (pci_request_selected_regions(pdev, bars, "nvme"))
  goto disable_pci;


if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)))
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)))
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
else
goto disable_pci;


pci_set_drvdata(pdev, dev);
// the driver can't access the physical addrs allocatd for pci bars memory, must call ioremap to map
// the physical addrs to virtual addrs so that driver can access them.
// Map the physical addrs to virtual addrs.
dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); // PCIE device have 8k bar memory.
if (!dev->bar)
goto disable;


dev->db_stride = NVME_CAP_STRIDE(readq(&dev->bar->cap));
dev->dbs = ((void __iomem *)dev->bar) + 4096;


return 0;


 disable:
pci_release_regions(pdev);
 disable_pci:
pci_disable_device(pdev);
return result;
}

你可能感兴趣的:(PCI-Device)