免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3445 | 回复: 0
打印 上一主题 下一主题

Solaris PCI相关解读 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-31 13:30 |只看该作者 |倒序浏览

                我们以e1000g网卡驱动为例,驱动程序由pci_config_setup(9F)或者ddi_regs_map_setup(9F)得到访问配置地址空间的句柄。下面我们通过mdb来看看这个句柄是个怎样的数据结构。
# mdb -k
> ::prtconf ! grep e1000g
        300004271b0      pci8086,1001, instance #0 (driver name: e1000g)
> 300004271b0::print -t struct dev_info devi_driver_data |::print -t e1000g_t osdep.cfg_handle |::print -t struct ddi_acc_hdl ah_addr
caddr_t ah_addr = 0x29ebf9e3800
> 0x29ebf9e3800::sfmmu_vtop
virtual 29ebf9e3800 mapped to physical 7fe00001800
> 300004271b0::print -t struct dev_info devi_driver_data |::print -t e1000g_t osdep.cfg_handle |::print -t struct ddi_acc_hdl
{
    int ah_vers = 0x1
    void *ah_bus_private = 0
    void *ah_platform_private = 0x60011a99cc0
    dev_info_t *ah_dip = 0x300004271b0
    uint_t ah_rnumber = 0
    caddr_t ah_addr = 0x29ebf9e3800
    off_t ah_offset = 0
    off_t ah_len = 0
    uint_t ah_hat_flags = 0x2000
    pfn_t ah_pfn = 0x3ff00000
    uint_t ah_pnum = 0x1
    ulong_t ah_xfermodes = 0
    ddi_device_acc_attr_t ah_acc = {
        ushort_t devacc_attr_version = 0x2
        uchar_t devacc_attr_endian_flags = 0x1
        uchar_t devacc_attr_dataorder = 0
        uchar_t devacc_attr_access = 0x2
    }
}
驱动程序通过pci_config_setup(9F)或者ddi_regs_map_setup(9F)建立了PCI设备配置地址空间和内核虚拟地址之间的映射,在上例中,配置地址空间的物理地址是0x7fe00001800,内核虚拟地址是0x29ebf9e3800。这个物理地址也可以通过pcitool得到验证:
# pcitool -v
...
Bus Number: 0 Device Number: 3 Function Number: 0
Physical Address: 0x7fe00001800
Vendor ID: 8086
Device ID: 1026
Command: 0157
Status: 0230
Revision ID: 04
Class Code: 020000
Cache Line Size: 10
Latency Timer: 40
Header Type: 00
BIST: 00
Base Address Register 0 (@10): 00100004
Base Address Register 1 (@14): 00000000
Base Address Register 2 (@18): 00140004
Base Address Register 3 (@1C): 00000000
Base Address Register 4 (@20): 00000941
Base Address Register 5 (@24): 00000000
Expansion ROM Base Address Register (@30): 00180000
...
BAR0的内核虚拟地址和物理地址也可以通过类似的方法得到:
# mdb -k
> ::prtconf ! grep e1000g
        300004271b0      pci8086,1001, instance #0 (driver name: e1000g)
> 300004271b0::print -t struct dev_info devi_driver_data |::print -t e1000g_t osdep.reg_handle |::print -t struct ddi_acc_hdl ah_addr
caddr_t ah_addr = 0x29ebf9e4000
> 0x29ebf9e4000::sfmmu_vtop
virtual 29ebf9e4000 mapped to physical 7ff00100000
> 300004271b0::print -t struct dev_info devi_driver_data |::print -t e1000g_t osdep.reg_handle |::print -t struct ddi_acc_hdl
{
    int ah_vers = 0x1
    void *ah_bus_private = 0
    void *ah_platform_private = 0x60011a99b80
    dev_info_t *ah_dip = 0x300004271b0
    uint_t ah_rnumber = 0x1
    caddr_t ah_addr = 0x29ebf9e4000
    off_t ah_offset = 0
    off_t ah_len = 0x20000
    uint_t ah_hat_flags = 0x2000
    pfn_t ah_pfn = 0x3ff80080
    uint_t ah_pnum = 0x10
    ulong_t ah_xfermodes = 0
    ddi_device_acc_attr_t ah_acc = {
        ushort_t devacc_attr_version = 0x1
        uchar_t devacc_attr_endian_flags = 0x1
        uchar_t devacc_attr_dataorder = 0
        uchar_t devacc_attr_access = 0x1
    }
}
或者
> 300004271b0::print -t struct dev_info devi_driver_data |::print -t e1000g_t shared.hw_addr
u8 *shared.hw_addr = 0x29ebf9e4000
Solaris在SPARC平台下没有scanpci和lspci等相应的命令,prtconf是一个可以得到系统配置信息的命令,当然也包括PCI设备。
# prtconf -vp
...
        Node 0xf00d1b0c
            assigned-addresses:  83001810.00000000.00100000.00000000.00020000.83001818.00000000.00140000.00000000.00040000.81001820.00000000.00000940.0000000
0.00000040.82001830.00000000.00180000.00000000.00040000
            reg:  00001800.00000000.00000000.00000000.00000000.03001810.00000000.00000000.00000000.00020000.03001818.00000000.00000000.00000000.00040000.0100
1820.00000000.00000000.00000000.00000040.02001830.00000000.00000000.00000000.00040000
            compatible: 'pci8086,1026.8086.1001.4' + 'pci8086,1026.8086.1001' + 'pci8086,1001' + 'pci8086,1026.4' + 'pci8086,1026' + 'pciclass,020000' + 'pciclass,0200'
            name:  'ethernet'
            66mhz-capable:  
            devsel-speed:  00000001
            class-code:  00020000
            interrupts:  00000001
            latency-timer:  00000040
            cache-line-size:  00000010
            max-latency:  00000000
            min-grant:  000000ff
            subsystem-id:  00001001
            subsystem-vendor-id:  00008086
            revision-id:  00000004
            device-id:  00001026
            vendor-id:  00008086
...
其中reg属性中包含了什么信息可以从pci(4) man page中得到,也可以通过下面的C程序得到。
#include
/*
                   Bits 0 - 7           8-bit register number
                   Bits 8 - 10          3-bit function number
                   Bits 11 - 15         5-bit device number
                   Bits 16 - 23         8-bit bus number
                   Bits 24 - 25         2-bit address space type identifier
                   Bits 28 - 31         Register number extended bits  8:11
                                        for extended config space. Zero for
                                        conventional configuration space.
                   The  address  space  type  identifier  can  be
                   interpreted as follows:
                   0x0                  configuration space
                   0x1                  I/O space
                   0x2                  32-bit memory space address
                   0x3                  64-bit memory space address
*/
#define REG 0x000000ff
#define FUN 0x00000700
#define DEV 0x0000f800
#define BUS 0x00ff0000
#define ADD 0x03000000
#define EXT 0xf0000000
int main(int argc, char *argv[])
{
    int i, regs[]={
/*
            0x0200c810,
            0x8200c814,
            0x8100c818,
            0x0000c800,
            0x0200c810,
            0x0200c814,
            0x0100c818,
            0,
            0x83001110,
            0x83001010,
            0,
            0x83001810,
*/
            0x00001800,
            0x03001810,
            0x03001818,
            0x01001820,
            0x02001830,
            1 };
    for(i=0; regs != 1; i++) {
        if (regs == 0) {
            printf("\n");
            continue;
        }
        printf("REG: %x\t", regs & REG);
        printf("FUN: %x\t", (regs & FUN) >> 8);
        printf("DEV: %x\t", (regs & DEV) >> 11);
        printf("BUS: %x\t", (regs & BUS) >> 16);
        printf("ADD: %x\t", (regs & ADD) >> 24);
        printf("EXT: %x\n", (regs & EXT) >> 28);
    }
    return 0;
}
# ./reg
REG: 0    FUN: 0    DEV: 3    BUS: 0    ADD: 0    EXT: 0
REG: 10    FUN: 0    DEV: 3    BUS: 0    ADD: 3    EXT: 0
REG: 18    FUN: 0    DEV: 3    BUS: 0    ADD: 3    EXT: 0
REG: 20    FUN: 0    DEV: 3    BUS: 0    ADD: 1    EXT: 0
REG: 30    FUN: 0    DEV: 3    BUS: 0    ADD: 2    EXT: 0
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/23177/showart_1950293.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP