• 怎样訪问pcie整个4k的配置空间


    眼下用于訪问PCIe配置空间寄存器的方法须要追溯到原始的PCI规范。

    为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这样的方法能够訪问全部PCI设备的255 bytes配置寄存器。Intel Chipsets眼下仍然支持这样的訪问PCI配置空间的方法。

        PCIe规范在PCI规范的基础上,将配置空间扩展到4K bytes,至于为什么扩展到4K,详细能够參考PCIe规范,这些功能都须要配置空间。原来的CF8/CFC方法仍然能够訪问全部PCIe设备配置空间的头255 bytes,可是该方法訪问不了剩下的(4K-255)配置空间。

    怎么办呢?Intel提供了第二种PCIe配置空间訪问方法。Intel Chipset通过将配置空间映射到内存地址空间。PCIe配置空间能够像对映射范围内的内存进行read/write一样来訪问了。

    这样的映射是由北桥芯片来完毕的,可是不同芯片的映射方式也是不同的。

    1、CF8h/CFCH Method

        Intel Chipsets使用IO空间的CF8h/CFCh地址来訪问PCI设备的配置寄存器。该方法相同能够訪问PCIe设备的头255配置寄存器。

    Chipsets

        为了对已知PCI设备发起一个PCI总线配置周期,软件必须运行下面步骤:

    1. PCI设备的总线号必须被填写到IO地址CF8h的[23:16] bits

    2. PCI设备的设备号必须被填写到IO地址CF8h的[15:11] bits

    3. PCI设备的功能号必须被填写到IO地址CF8h的[10:8] bits

    4. 须要訪问的寄存器双字地址必须被填写到IO地址CF8h的[7:2] bits

    5. CF8h的最高位为配置位。该位必须设置为1

    6. 对于写操作,将设备的特定信息组合成一个双字(4bytes)后。写到CFCh地址

    7. 对于读操作,将设备的特定信息组合成一个双字后,把数据从CFCh读回来

       

        当运行6或者7步骤时,对应的PCI配置read/write cycle被Created by Intel Chipset,并在须要时传递到整个系统。在步骤4配置须要读写的寄存器地址时。该空间仅仅有6位,也就说仅仅有64个地址可写,可是PCI配置空间不是256吗?别急,记得是双字地址,一个Dword=4 bytes。也就是说4 * 64 = 256。刚好,不是吗?

     

    2、Memory Mapped Method

        PCIe规范为每一个PCIe设备加入了很多其它的配置寄存器。空间为4K。虽然CF8h/CFCh方法仍然可以訪问lower 255 bytes,可是必须提供第二种方法来訪问剩下的4K range寄存器。

    Intel的解决方式是使用了预留256MB内存地址空间,对这段内存的不论什么訪问都会发起PCI 配置cycle。可是为什么是256MB?

    ?

    ?

    听我慢慢解释给大家听:犹豫4K的配置空间是directly mapped to memory的,那么PCIe规范必须保证全部的PCIe设备的配置空间占用不同的内存地址,依照PCIe规范,支持最多256个buses。每一个Bus支持最多32个PCI devices,每一个device支持最多8个function,也就是说:占用内存的最大值为:256 * 32 * 8 * 4K = 256MB。

        这段256MB的内存区将依据intel chipset的不同。能够映射到系统内存映射范围内的不论什么位置,一般北桥芯片都会有一个寄存器来指明PCI配置空间的内存映射地址,它叫PCIe Configuration Register Base Address Register (BAR),例如以下图:

    PCIe

        当软件訪问指定PCIe设备的配置寄存器时,必须正确计算该寄存器映射到内存的详细地址,那么怎么计算呢,參考上图我们能够知道,busNo=0,deviceNo=0,funcNo=0的地址刚好是BAR,一条总线占用的最大空间计算例如以下:

        SIZE_PER_BUS = 4K * 32 * 8 = 256K = 1M = 100000h

        SIZE_PER_DEVICE = 4K * 8 = 8000h

        SIZE_PER_FUNC = 4K = 1000h

        訪问总线号为busNo,设备号为DevNo,功能号为funcNo的offset寄存器的计算公式是:

        Memory Address = PCIe Configuration Register Base Address Register (BAR)

                                        + busNo * SIZE_PER_BUS

                                        + devNo * SIZE_PER_DEVICE

                                        + funcNo * SIZE_PER_FUNC

                                        + offset

        For example, to access the following configuration register:
        • PCI Express Configuration Register F0000000h
        • Bus Number 15h
        • Device Number 00h
        • Function Number 05h
        • Register Offset 84h

    Memory Address = F0000000h + 15h * 100000h + 00h * 8000h  + 05h * 1000h + 84h

                            = F1505084h

        如今我们能够从已知的busNo,devNo,funcNo和offset来计算映射后的内存地址。那么反过来。给定的内存地址,我们想知道这个地址的busNo, devNo, funcNo和offset信息,能够吗?当然能够,计算公式例如以下:

        busNo = (Memory Address - BAR) / SIZE_PER_BUS;

        devNo = (Memory Address - BAR - busNo * SIZE_PER_BUS) / SIZE_PER_DEVICE;

        funcNo = (Memory Address - BAR - busNo * SIZE_PER_BUS 

                        - devNo * SIZE_PER_DEVICE) / SIZE _PER_FUNC;

        offset = Memory Address - BAR - busNo * SIZE_PER_BUS - devNo * SIZE_PER_DEVICE

                        - funcNo * SIZE_PER_FUNC;

        又或offset = Memory Address & 0x0FFFh;(为什么是0x0FFFh?自己想想啦)

        想起来了么?因此PCIe的配置空间大小就是4K啊。

    3、芯片组的异同

        上面说的BAR,也就是PCI配置空间寄存器映射到内存的基地址寄存器。在intel chipset中的实现方式也千差万别。在前期的intel chipset中。该寄存器被包括在芯片组(MCH ,GMCH)的内存控制器部分。

        另外。因为被PCIe配置空间占用的256M内存空间会屏蔽掉DRAM使用该段内存区。大部分的Intel Chipset同意BIOS来配置该空间大小,因此在实际应用中,一般就应用前面几个总线号,BIOS通过检測PCIe总线的扩展深度来动态设置该映射内存区的大小,比方PM965芯片组,假设配置软件检測系统使用不大于64的总线号,那么该软件将编程内存映射大小为64M,剩下的(256M-64M = 192M)留给DRAM。

    4、PCIe配置空间的内存映射对32bit系统的影响

        因为PCIe配置空间占用了256M内存空间,并且该被占用空间对DRAM来说是不可用的,这意味着256M空间消失于系统内存,这在32bit系统中更为明显。

        比方。在32 bit WINxp中,理论上能够訪问到的内存是4G,假设4G空间都被DRAM给占用。因为PCIe的存在。被PCIe占用的那部分内存空间对OS来说是不可用的,莫名的消失了最多256M内存,这也是大部分Intel Chipset同意BIOS来配置该空间大小的原因。

        在64 bit 系统中。不存在这个问题,由于系统能够訪问超过4G的内存空间。Intel Chipset会包括控制逻辑把该PCIe的内存映射到above 4G。这样跟DRAM就没有冲突。

    在64bit系统中,不可能使用2的64次方的内存吧。哈哈,总会没有使用到的内存空间。

    5、訪问PCIe配置空间的C转换代码

    //**********************************************************************
    unsigned long PCIeBase = 0xF0000000UL;
    unsigned long FinalAddress;
    unsigned long Bus = 0;
    unsigned long Device = 0;
    unsigned long Function = 0;
    unsigned long Register = 0;
    //**********************************************************************
    void Convert_to_Memory()
    {
        FinalAddress = PCIeBase +
                            (Bus*0x100000UL) +
                            (Device*0x8000) +
                            (Function*0x1000) +
                            Register;
    }
    //**********************************************************************
    void Convert_to_Register()
    {
        Bus = (FinalAddress-PCIeBase) / (0x100000UL);
        Device = (FinalAddress-PCIeBase - (Bus*0x100000UL)) / (0x8000);
        Function = (FinalAddress-PCIeBase - (Bus*0x100000UL) -
        (Device*0x8000)) / (0x1000);
        Register = (FinalAddress) & (0x00000FFF)

    }

  • 相关阅读:
    HDU 5115 Dire Wolf (区间DP)
    HDU 4283 You Are the One(区间DP(最优出栈顺序))
    ZOJ 3469 Food Delivery(区间DP好题)
    LightOJ 1422 Halloween Costumes(区间DP)
    POJ 1651 Multiplication Puzzle(区间DP)
    NYOJ 石子合并(一)(区间DP)
    POJ 2955 Brackets(括号匹配一)
    POJ 1141 Brackets Sequence(括号匹配二)
    ZOJ 3537 Cake(凸包+区间DP)
    Graham求凸包模板
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6910577.html
Copyright © 2020-2023  润新知