转载自chinaunix

枚举所有PCI设备 冷胜魁(Seaquester) lengshengkui@gmail.com 2009-11-16 在Linux下,lspci可以枚举所有PCI设备。它是通过读取PCI配置空间(PCI Configuration Space)信息来实现PCI设备的枚举的。这里,我通过两种方式来简单的模拟一下lspci的功能。一种是通过PCI总线的CF8和CFC端口来枚举(参考PCI总线规范);另一种是利用proc filesystem。 方法一:这种方法需要对端口进行操作,在Linux下,普通应用程序没有权限读写I/O 端口,需要通过iopl或ioperm来提升权限,我的代码里面使用iopl。

/*  * Enum all pci device via the PCI config register(CF8 and CFC).  */ #include  #include  #include  #include  #define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */ #define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */ #define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */ #define CONFIG_ADDRESS 0xCF8 #define CONFIG_DATA 0xCFC #define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */ #define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */ #define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */ #define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */ #define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */ void list_pci_devices() {     unsigned int bus, dev, fun;     unsigned int addr, data;     //printf("BB:DD:FF VID:DID\n");     for (bus = 0; bus <= PCI_MAX_BUS; bus++) {         for (dev = 0; dev <= PCI_MAX_DEV; dev++) {             for (fun = 0; fun <= PCI_MAX_FUN; fun++) {                 addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8);                 outl(addr, CONFIG_ADDRESS);                 data = inl(CONFIG_DATA);                 /* Identify vendor ID */                 if ((data != 0xFFFFFFFF) && (data != 0)) {                     printf("%02X:%02X:%02X ", bus, dev, fun);                     printf("%04X:%04X", data&0xFFFF, data>>16);                     addr = 0x80000000L | (bus<<16) | (dev<<11) | (fun<<8) | PCICFG_REG_RID;                     outl(addr, CONFIG_ADDRESS);                     data = inl(CONFIG_DATA);                     if (data&0xFF) {                         printf(" (rev %02X)\n", data&0xFF);                     } else {                         printf("\n");                     }                 }             }         }     } } int main() {     int ret;     /* Enable r/w permission of all 65536 ports */     ret = iopl(3);     if (ret

方法二:这种方法需不需要对端口进行操作,而是利用Linux procfs来实现对PCI 配置空间的访问。

/*  * Enum all pci device via /proc/bus/pci/.  */ #include  #include  #include  #include  #include  #include  #define PCI_MAX_BUS 255 /* 8 bits (0 ~ 255) */ #define PCI_MAX_DEV 31 /* 5 bits (0 ~ 31) */ #define PCI_MAX_FUN 7 /* 3 bits (0 ~ 7) */ /*  * PCI Configuration Header offsets  */ #define PCICFG_REG_VID 0x00 /* Vendor id, 2 bytes */ #define PCICFG_REG_DID 0x02 /* Device id, 2 bytes */ #define PCICFG_REG_CMD 0x04 /* Command register, 2 bytes */ #define PCICFG_REG_STAT 0x06 /* Status register, 2 bytes */ #define PCICFG_REG_RID 0x08 /* Revision id, 1 byte */ #define PCICFG_REG_PROG_INTF 0x09 /* Programming interface code, 1 byte */ #define PCICFG_REG_SUBCLASS 0x0A /* Sub-class code, 1 byte */ #define PCICFG_REG_BASCLASS 0x0B /* Base class code, 1 byte */ #define PCICFG_REG_CACHE_LINESZ 0x0C /* Cache line size, 1 byte */ #define PCICFG_REG_LATENCY_TIMER 0x0D /* Latency timer, 1 byte */ #define PCICFG_REG_HEADER_TYPE 0x0E /* Header type, 1 byte */ #define PCICFG_REG_BIST 0x0F /* Builtin self test, 1 byte */ #define PCICFG_REG_BAR0 0x10 /* Base addr register 0, 4 bytes */ #define PCICFG_REG_BAR1 0x14 /* Base addr register 1, 4 bytes */ #define PCICFG_REG_BAR2 0x18 /* Base addr register 2, 4 bytes */ #define PCICFG_REG_BAR3 0x1C /* Base addr register 3, 4 bytes */ #define PCICFG_REG_BAR4 0x20 /* Base addr register 4, 4 bytes */ #define PCICFG_REG_BAR5 0x24 /* Base addr register 5, 4 bytes */ #define PCICFG_REG_CIS 0x28 /* Cardbus CIS Pointer */ #define PCICFG_REG_SVID 0x2C /* Subsystem Vendor ID, 2 bytes */ #define PCICFG_REG_SDID 0x2E /* Subsystem ID, 2 bytes */ #define PCICFG_REG_ROMBAR 0x30 /* ROM base register, 4 bytes */ #define PCICFG_REG_CAPPTR 0x34 /* Capabilities pointer, 1 byte */ #define PCICFG_REG_INT_LINE 0x3C /* Interrupt line, 1 byte */ #define PCICFG_REG_INT_PIN 0x3D /* Interrupt pin, 1 byte */ #define PCICFG_REG_MIN_GNT 0x3E /* Minimum grant, 1 byte */ #define PCICFG_REG_MAX_LAT 0x3F /* Maximum lat, 1 byte */ void list_pci_devices() {     unsigned int bus, dev, fun;     //printf("BB:DD:FF VID:DID(RID)\n");     for (bus = 0; bus <= PCI_MAX_BUS; bus++) {         for (dev = 0; dev <= PCI_MAX_DEV; dev++) {             for (fun = 0; fun <= PCI_MAX_FUN; fun++) {                 char proc_name[64];                 int cfg_handle;                 uint32_t data;                 uint16_t vid, did;                 uint8_t rid;                 snprintf(proc_name, sizeof(proc_name),                     "/proc/bus/pci/%02x/%02x.%x", bus, dev, fun);                 cfg_handle = open(proc_name, O_RDWR);                 if (cfg_handle <= 0) {                     continue;                 }                 lseek(cfg_handle, PCICFG_REG_VID, SEEK_SET);                 read(cfg_handle, &data, sizeof(data));                 /* Identify vendor ID */                 if ((data != 0xFFFFFFFF) && (data != 0)) {                     lseek(cfg_handle, PCICFG_REG_RID, SEEK_SET);                     read(cfg_handle, &rid, sizeof(rid));                     vid = data&0xFFFF;                     did = data>>16;                                         printf("%02X:%02X:%02X", bus, dev, fun);                     if (rid > 0) {                         printf(" %04X:%04X (rev %02X)\n", vid, did, rid);                     } else {                         printf(" %04X:%04X\n", vid, did);                     }                 }             }         }     } } int main(int argc, char **argv) {     list_pci_devices();     return 0; }

这两种方法各有优缺点,第一种方法方便移植到其他OS,第二种就只适用于Linux。但是,第一种方法需要对I/O port进行直接操作。第二种就不需要。

注意:执行这两段代码时,需要超级用户(root) 权限。

补充:今天在枚举 Westmere-EP Processor(Intel Xeon Processor 5500 Series(Nehalem-EP))的 IMC(Integrated Memory Controller)时发现一个问题。lspci无法枚举到IMC设备。Westmere-EP 是 Intel 新的处理器架构。和以往的CPU不一样,它把Memory Controller集成到了CPU里面。IMC控制器被映射到了PCI总线上,Bus Number 是0xFE~0xFF,procfs(/proc/bus/pci/)下没有这几个设备。但是,通过 CF8/CFC 端口可以枚举到这些设备。

还有pci设备枚举过程http://blog.chinaunix.net/uid-27149258-id-3375993.html

linux枚举pcie设备,pcie设备枚举(转载)相关推荐

  1. linux下看pcie的设备id,linux lspci查看pci总线设备信息

    linux lspci查看pci总线设备信息 linux中lspci是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具,比如查看网卡.存储等信息. 参数 -v 使得 lspci 以 ...

  2. Pci设备驱动:设备枚举

    有了设备模型基础及usb设备驱动的基础知识,来了解PCI设备驱动,就相对简单了,因为PCI设备驱动仍然套用了设备驱动模型的方式,用到的仍然是设备模型的相应函数,只是把相应的pci设备挂载到PCI总线的 ...

  3. USB设备驱动之设备初始化(设备枚举)

    USB设备从接入HUB到正常工作之前.都属于设备枚举阶段.所谓设备枚举.就是让host控制器认识USB设备,并为其准备资源.建立好主机与设备间的数据传递机制. 该阶段的工作,是USB通信协议规定的,所 ...

  4. 使枚举成功的USB设备成为WINUSB设备

    <使枚举成功的USB设备成为WINUSB设备> ** 更新声明:各位不好意思,这篇文章是我本科期间所作,而且我已经很久没有涉足过硬件了,文中可能会有遗漏或者错误,并且很多关于USB的细节我 ...

  5. linux设备驱动归纳总结--转载小白的博客

    主要是为了自己浏览方便... linux设备驱动归纳总结 linux设备驱动归纳总结(一):内核的相关基础概念 linux设备驱动归纳总结(二):模块的相关基础概念 linux设备驱动归纳总结(三): ...

  6. linux中流设备_Linux设备驱动子系统终极弹

    0. 预备理论 1. USB Core 2. USB Hub 3. USB OTG 4. USB Host 5. USB Gadget 6. USB Mass Storage USB博大精深,不是一两 ...

  7. 从需求的角度去理解Linux系列:总线、设备和驱动

    <从需求的角度去理解Linux系列:总线.设备和驱动>是一篇有关如何学习嵌入式Linux系统的方法论文章,也是从需求的角度去理解Linux系统软件的开篇.这是作者精心撰写的经验总结,希望嵌 ...

  8. Linux内核中识别USB设备过程

    1.usb全速模式和高速模式的区别,名字上感觉速度应该差不多?? Usb1.1又是usb2.0全速模式,传输速率只有12Mbps Usb2.0高速模式达到了480mbps 擦类这明显不是一个等级... ...

  9. Linux设备模型——设备驱动模型和sysfs文件系统解读笔记

    Linux设备模型--设备驱动模型和sysfs文件系统解读笔记 原文:https://blog.csdn.net/yj4231/article/details/7799245 将对Linux系统中的s ...

  10. linux下 usb 和pci设备的reset

    linux下 usb 和pci设备的reset 1. 什么是设备的reset 设备的寄存器 设备的结构体 usb device reset pci device reset pci 设备的functi ...

最新文章

  1. 产品经理说以后接口不找你写了!啥情况?我要凉了?
  2. 对话预训练_百度发布首个大规模隐变量对话模型PLATO
  3. 监控调优工具详细参数整理
  4. Asp.net Core全局异常监控和记录日志
  5. 常用Smarty变量操作符
  6. 为什么负数的补码是取反加一
  7. Java 1.2.2 格式化输出
  8. laravel 5 : Class 'input' not found
  9. 直播策划方案怎么做?
  10. 手把手BC26模组OpenCPU开发之旅-1.简介
  11. python产品质量分析报告范文_Python Jinja2 徒手生成数据分析报告
  12. easyefi添加引导盘重启消失引导解决办法
  13. 软件工程之功能性需求和非功能性需求
  14. 3-3 uniapp、HTML5+、Native.js 功能代码汇总
  15. TMO (time-triggered message-triggered object)
  16. 一个学机械的中年人半年时间入门物联网嵌入式的历程
  17. python基础知识整理13-正则re
  18. Ajax --- 客户端与服务器端之间传递数据
  19. 用canvas画一个太极图(八卦图)
  20. ubuntu中中文名新加卷修改为英文名新加卷

热门文章

  1. React 中的受控组件和非受控组件的区别
  2. 职业生涯规划成功100口诀。
  3. 要么读书,要么健身,要么恋爱(九)从0到1:开启商业与未来
  4. 小米5预装android版本,小米 Mi5(小米5 安卓8.0)获取Root权限服务含精简系统方案...
  5. 哥白尼哨兵2021年日历壁纸
  6. ResNet详解——通俗易懂版
  7. 有关聚合支付的三大问题
  8. python量化交易:基础知识_主流的比较流行的Python量化开源框架
  9. 4.1.2 组织碳足迹 Organizational Carbon Footprint
  10. crsd.bin Fail With Error CRS-1019 When ohasd Restarted (文档 ID 2291799.1)