当前位置:网站首页>PCI bar register explanation (I)

PCI bar register explanation (I)

2022-06-10 01:00:00 Love little Zhizhi forever~

One 、PCI Equipment configuration space

 Insert picture description here

among Device ID and Vendor ID It is the key to distinguish different equipment ,OS In many cases, it is by matching them to find different device drivers (Class Code Sometimes it also plays a role ).

Let's focus on these Base Address Registers(BAR).BAR yes PCI From the configuration space 0x10 To 0x24 Of 6 individual register, Used to define PCI Required configuration space size and configuration PCI Address space occupied by the device .

This group of registers is called BAR register , BAR Registers save PCI The base address of the address space used by the device , The base address holds the location of the device in PCI Address in the bus domain . Each of these devices can have at most 6 Base address spaces , But most devices don't use so many groups of address spaces .

stay PCI After the device is reset , This register will store PCI The size of the base address space that the device needs to use , This space is I/O Space or memory space , If it is a memory space, whether the space can be prefetched , of PCI For a detailed description of the bus read ahead mechanism, see page 3.4.5 section .

The system software is right PCI When configuring the bus , First get BAR Initialization information in register , Then, according to the configuration of the processor system , Write a reasonable base address to the corresponding BAR In the register . The system software can also use this register , get PCI Used by the equipment BAR The length of space , The method is to BAR Register write 0xFFFF-FFFF, Then read the register .


Two 、Linux Driver code access BAR Space

Processor access PCI The equipment BAR When space , Need to use BAR The base address provided by the register .

It is worth noting that , The processor uses the address of the memory domain , and BAR Registers store PCI The address of the bus domain . Therefore, the processor system cannot be used directly “BAR register + The offset ” Mode of access PCI The register space of the device , and Need to put PCI The address of the bus domain is converted to the address of the memory domain .

stay Linux In the system , A processor system uses BAR The correct way to space is as follows :

#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
    // Linux  System use  BAR  The right way to space 
	pciaddr = pci_resource_start(pdev, 1);
    
    if(!pciaddr)
    {
    
        rc = -EIO;
        dev_err(&pdev->dev, "no MMIO resource\n");
        goto err_out_res;
    }
    
    ......
    
    regs = ioremap(pciaddr, CP_REGS_SIZE);

stay Linux In the system , Use pci_dev->resource[bar].start The parameter save BAR The address of the register in the memory field . Writing Linux Device driver , You have to use pci_resource_start Function to obtain BAR The physical address of the memory domain corresponding to the space , Instead of using from BAR Address read from register .

When the driver gets BAR The space is behind the physical address of the memory domain , Reuse ioremap The function converts this physical address to a virtual address .

Linux The system directly uses BAR The method of space is incorrect , As shown below :

    // Linux  System use  BAR  Wrong way of space 
	ret = pci_read_config_dword(pdev, 1, &pciaddr);
    
    if(!pciaddr)
    {
    
        rc = -EIO;
        dev_err(&pdev->dev, "no MMIO resource\n");
        goto err_out_res;
    }
    
    ......
    
    regs = ioremap(pciaddr, BAR_SIZE);

stay Linux In the system , Use pci_read_config_dword The function gets PCI The physical address of the bus domain , In many processor systems , Such as Alpha and PowerPC Processor system ,PCI The physical address of the bus domain is not equal to the physical address of the memory domain .

If X86 The processor system enables IOMMU after , The two addresses are not necessarily equal , Therefore, the processor system directly uses this PCI The physical address of the bus domain , Does not guarantee access to PCI The equipment BAR The correctness of space . In addition to that Linux In the system ,ioremap The input parameter of the function is the physical address of the memory domain , They can't be used PCI The physical address of the bus domain .

And in the pci_dev->resource[bar].start The address saved in the parameter has passed PCI Address translation from bus domain to memory domain , So I'm writing Linux Device driver for the system , Need to use pci_dev->resource[bar].start The physical address in the parameter , Reuse ioremap The function converts a physical address to “ Memory domain ” The virtual address of .


原网站

版权声明
本文为[Love little Zhizhi forever~]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206100026457773.html