linux枚举pcie设备,pcie设备枚举(转载)
转载自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设备枚举(转载)相关推荐
- linux下看pcie的设备id,linux lspci查看pci总线设备信息
linux lspci查看pci总线设备信息 linux中lspci是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具,比如查看网卡.存储等信息. 参数 -v 使得 lspci 以 ...
- Pci设备驱动:设备枚举
有了设备模型基础及usb设备驱动的基础知识,来了解PCI设备驱动,就相对简单了,因为PCI设备驱动仍然套用了设备驱动模型的方式,用到的仍然是设备模型的相应函数,只是把相应的pci设备挂载到PCI总线的 ...
- USB设备驱动之设备初始化(设备枚举)
USB设备从接入HUB到正常工作之前.都属于设备枚举阶段.所谓设备枚举.就是让host控制器认识USB设备,并为其准备资源.建立好主机与设备间的数据传递机制. 该阶段的工作,是USB通信协议规定的,所 ...
- 使枚举成功的USB设备成为WINUSB设备
<使枚举成功的USB设备成为WINUSB设备> ** 更新声明:各位不好意思,这篇文章是我本科期间所作,而且我已经很久没有涉足过硬件了,文中可能会有遗漏或者错误,并且很多关于USB的细节我 ...
- linux设备驱动归纳总结--转载小白的博客
主要是为了自己浏览方便... linux设备驱动归纳总结 linux设备驱动归纳总结(一):内核的相关基础概念 linux设备驱动归纳总结(二):模块的相关基础概念 linux设备驱动归纳总结(三): ...
- linux中流设备_Linux设备驱动子系统终极弹
0. 预备理论 1. USB Core 2. USB Hub 3. USB OTG 4. USB Host 5. USB Gadget 6. USB Mass Storage USB博大精深,不是一两 ...
- 从需求的角度去理解Linux系列:总线、设备和驱动
<从需求的角度去理解Linux系列:总线.设备和驱动>是一篇有关如何学习嵌入式Linux系统的方法论文章,也是从需求的角度去理解Linux系统软件的开篇.这是作者精心撰写的经验总结,希望嵌 ...
- Linux内核中识别USB设备过程
1.usb全速模式和高速模式的区别,名字上感觉速度应该差不多?? Usb1.1又是usb2.0全速模式,传输速率只有12Mbps Usb2.0高速模式达到了480mbps 擦类这明显不是一个等级... ...
- Linux设备模型——设备驱动模型和sysfs文件系统解读笔记
Linux设备模型--设备驱动模型和sysfs文件系统解读笔记 原文:https://blog.csdn.net/yj4231/article/details/7799245 将对Linux系统中的s ...
- linux下 usb 和pci设备的reset
linux下 usb 和pci设备的reset 1. 什么是设备的reset 设备的寄存器 设备的结构体 usb device reset pci device reset pci 设备的functi ...
最新文章
- 产品经理说以后接口不找你写了!啥情况?我要凉了?
- 对话预训练_百度发布首个大规模隐变量对话模型PLATO
- 监控调优工具详细参数整理
- Asp.net Core全局异常监控和记录日志
- 常用Smarty变量操作符
- 为什么负数的补码是取反加一
- Java 1.2.2 格式化输出
- laravel 5 : Class 'input' not found
- 直播策划方案怎么做?
- 手把手BC26模组OpenCPU开发之旅-1.简介
- python产品质量分析报告范文_Python Jinja2 徒手生成数据分析报告
- easyefi添加引导盘重启消失引导解决办法
- 软件工程之功能性需求和非功能性需求
- 3-3 uniapp、HTML5+、Native.js 功能代码汇总
- TMO (time-triggered message-triggered object)
- 一个学机械的中年人半年时间入门物联网嵌入式的历程
- python基础知识整理13-正则re
- Ajax --- 客户端与服务器端之间传递数据
- 用canvas画一个太极图(八卦图)
- ubuntu中中文名新加卷修改为英文名新加卷
热门文章
- React 中的受控组件和非受控组件的区别
- 职业生涯规划成功100口诀。
- 要么读书,要么健身,要么恋爱(九)从0到1:开启商业与未来
- 小米5预装android版本,小米 Mi5(小米5 安卓8.0)获取Root权限服务含精简系统方案...
- 哥白尼哨兵2021年日历壁纸
- ResNet详解——通俗易懂版
- 有关聚合支付的三大问题
- python量化交易:基础知识_主流的比较流行的Python量化开源框架
- 4.1.2 组织碳足迹 Organizational Carbon Footprint
- crsd.bin Fail With Error CRS-1019 When ohasd Restarted (文档 ID 2291799.1)