这几天发现在Redhat AS6.5 X86_64下用outl(index, 0xcf8)和inl(0xcfc)下读取PCIe配置空间是系统有时性的会hang, 于是去寻找解决方案,首先想到的是用/dev/port这种方案去替代,折腾了半天发现不行,后来想到为什么不用lspci的方法了,结果就成功了,如下为分享。

1.基本介绍

Lspci的工具包名为pciutils, 是由捷克的大伽Martin Mares 开发的,目前最新的版本为3.5.1, 你可以通过mj@ucw.cz 联系他, 他的个人主页为http://mj.ucw.cz/, 在上面可以找到他的联系方式。

 

Lspci支持众多OS,

    Linux        (via /sys/bus/pci, /proc/bus/pci or i386 ports)

    FreeBSD        (via /dev/pci)

    NetBSD        (via libpci)

    OpenBSD        (via /dev/pci)

    GNU/kFreeBSD    (via /dev/pci)

    Solaris/i386    (direct port access)

    Aix        (via /dev/pci and odmget)

    GNU Hurd    (direct port access)

    Windows        (direct port access, see README.Windows for caveats)

    CYGWIN        (direct port access)

    BeOS        (via syscalls)

    Haiku        (via /dev/misc/poke)

    Darwin        (via IOKit)

当然我们最关心的Linux.

 

2.下载

你可以从ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/ 下载到最新的pciutils,下载后将pciutils-3.5.1.tar.gz解压。然后进入目录运行make进行编译, 编译后你会看到如下目录。

 

3.Libpci库

进入lib目录, 就会看到生成了一个libpci.a的静态库,这个库你是可以调用的,如果想调用动态库,只需要修改Makefile, 将SHARED参数改为yes即可

SHARED=yes

#make clean

#make

就会有libpci.so.3.5.1生成,如果嫌后面的版本麻烦,可以将其直接改名为libpci.so.

实际上无论是lspci还是setpci都是调用libpci这个库的。

4. libpci库的调用

首先将libpci.so加到makefile中去,以下为一个例子。

LIB+=-lpthread -ldl ../../lib/libpci.so

 

 

以下是具体的调用例子:

 

将lib目录下的头文件全部copy到/usr/include/pci目录下,有些Linux系统是没有pci目录的,需要创建一个。

 

#include <pci/pci.h>

 

bool PCIe::getPCIConfig(PCI_CONFIG *pci_cfg, unsigned
char BusNum, unsigned
char DevNum, unsigned
char FuncNum)

{

    bool bRet = true;

    unsigned
int* pPCIConfig = (unsigned
int*)pci_cfg;

    int i,j;

    unsigned
char value[256];

    memset(value, 0, sizeof(value));

    struct pci_access *pacc;

    struct pci_dev *dev;

    pacc = pci_alloc();        /* Get the pci_access structure */

    /* Set all options you want -- here we stick with the defaults */

    pci_init(pacc);        /* Initialize the PCI library */

    pci_scan_bus(pacc);        /* We want to get the list of devices */

    for (dev=pacc->devices; dev; dev=dev->next)    /* Iterate over all devices */

    {

        if(! pci_read_block(dev, 0, value, 256))

        {

            printf("Get PCIE configuration space block fail \n");

            break;

        }

 

        if((BusNum == dev->bus) && (DevNum == dev->dev) && (FuncNum == dev->func))

        {

            for(i=0, j=0;i<64, j<256;i++, j+=4)

            {

                pPCIConfig[i] = value[j] | (value[j+1] <<8) | (value[j+2] <<16) | (value[j+3] <<24);

                // printf("%d: %04x\n", i, pPCIConfig[i] );

                if (i == 0 && ((pPCIConfig[i] == 0xFFFFFFFF) || ((pPCIConfig[i]&0xFFFF) == 0L)))

                {

                    bRet = false;

                    break;

                }

            }

            break;

        }

    }

    pci_cleanup(pacc);        /* Close everything */

    return bRet;

}

 

调用的函数都在pci.h中可以参考如下。

/*

*    The PCI Library

*

*    Copyright (c) 1997--2016 Martin Mares <mj@ucw.cz>

*

*    Can be freely distributed and used under the terms of the GNU GPL.

*/

 

#ifndef _PCI_LIB_H

#define _PCI_LIB_H

 

#ifndef PCI_CONFIG_H

#include
"config.h"

#endif

 

#include
"header.h"

#include
"types.h"

 

#define PCI_LIB_VERSION 0x030501

 

#ifndef PCI_ABI

#define PCI_ABI

#endif

 

/*

*    PCI Access Structure

*/

 

struct pci_methods;

 

enum pci_access_type {

/* Known access methods, remember to update access.c as well */

PCI_ACCESS_AUTO,            /* Autodetection */

PCI_ACCESS_SYS_BUS_PCI,        /* Linux /sys/bus/pci */

PCI_ACCESS_PROC_BUS_PCI,        /* Linux /proc/bus/pci */

PCI_ACCESS_I386_TYPE1,        /* i386 ports, type 1 */

PCI_ACCESS_I386_TYPE2,        /* i386 ports, type 2 */

PCI_ACCESS_FBSD_DEVICE,        /* FreeBSD /dev/pci */

PCI_ACCESS_AIX_DEVICE,        /* /dev/pci0, /dev/bus0, etc. */

PCI_ACCESS_NBSD_LIBPCI,        /* NetBSD libpci */

PCI_ACCESS_OBSD_DEVICE,        /* OpenBSD /dev/pci */

PCI_ACCESS_DUMP,            /* Dump file */

PCI_ACCESS_DARWIN,            /* Darwin */

PCI_ACCESS_MAX

};

 

struct pci_access {

/* Options you can change: */

unsigned
int method;            /* Access method */

int writeable;            /* Open in read/write mode */

int buscentric;            /* Bus-centric view of the world */

 

char *id_file_name;            /* Name of ID list file (use pci_set_name_list_path()) */

int free_id_name;            /* Set if id_file_name is malloced */

int numeric_ids;            /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */

 

unsigned
int id_lookup_mode;        /* pci_lookup_mode flags which are set automatically */

                    /* Default: PCI_LOOKUP_CACHE */

 

int debugging;            /* Turn on debugging messages */

 

/* Functions you can override: */

void (*error)(char *msg, ...) PCI_PRINTF(1,2);    /* Write error message and quit */

void (*warning)(char *msg, ...) PCI_PRINTF(1,2);    /* Write a warning message */

void (*debug)(char *msg, ...) PCI_PRINTF(1,2);    /* Write a debugging message */

 

struct pci_dev *devices;        /* Devices found on this bus */

 

/* Fields used internally: */

struct pci_methods *methods;

struct pci_param *params;

struct id_entry **id_hash;        /* names.c */

struct id_bucket *current_id_bucket;

int id_load_failed;

int id_cache_status;            /* 0=not read, 1=read, 2=dirty */

struct udev *id_udev;            /* names-hwdb.c */

struct udev_hwdb *id_udev_hwdb;

int fd;                /* proc/sys: fd for config space */

int fd_rw;                /* proc/sys: fd opened read-write */

int fd_pos;                /* proc/sys: current position */

int fd_vpd;                /* sys: fd for VPD */

struct pci_dev *cached_dev;        /* proc/sys: device the fds are for */

};

 

/* Initialize PCI access */

struct pci_access *pci_alloc(void) PCI_ABI;

void pci_init(struct pci_access *) PCI_ABI;

void pci_cleanup(struct pci_access *) PCI_ABI;

 

/* Scanning of devices */

void pci_scan_bus(struct pci_access *acc) PCI_ABI;

struct pci_dev *pci_get_dev(struct pci_access *acc, int domain, int bus, int dev, int func) PCI_ABI; /* Raw access to specified device */

void pci_free_dev(struct pci_dev *) PCI_ABI;

 

/* Names of access methods */

int pci_lookup_method(char *name) PCI_ABI;    /* Returns -1 if not found */

char *pci_get_method_name(int index) PCI_ABI;    /* Returns "" if unavailable, NULL if index out of range */

 

/*

*    Named parameters

*/

 

struct pci_param {

struct pci_param *next;        /* Please use pci_walk_params() for traversing the list */

char *param;                /* Name of the parameter */

char *value;                /* Value of the parameter */

int value_malloced;            /* used internally */

char *help;                /* Explanation of the parameter */

};

 

char *pci_get_param(struct pci_access *acc, char *param) PCI_ABI;

int pci_set_param(struct pci_access *acc, char *param, char *value) PCI_ABI;    /* 0 on success, -1 if no such parameter */

/* To traverse the list, call pci_walk_params repeatedly, first with prev=NULL, and do not modify the parameters during traversal. */

struct pci_param *pci_walk_params(struct pci_access *acc, struct pci_param *prev) PCI_ABI;

 

/*

*    Devices

*/

 

struct pci_dev {

struct pci_dev *next;            /* Next device in the chain */

u16 domain_16;            /* 16-bit version of the PCI domain for backward compatibility */

                    /* 0xffff if the real domain doesn't fit in 16 bits */

u8 bus, dev, func;            /* Bus inside domain, device and function */

 

/* These fields are set by pci_fill_info() */

int known_fields;            /* Set of info fields already known */

u16 vendor_id, device_id;        /* Identity of the device */

u16 device_class;            /* PCI device class */

int irq;                /* IRQ number */

pciaddr_t base_addr[6];        /* Base addresses including flags in lower bits */

pciaddr_t size[6];            /* Region sizes */

pciaddr_t rom_base_addr;        /* Expansion ROM base address */

pciaddr_t rom_size;            /* Expansion ROM size */

struct pci_cap *first_cap;        /* List of capabilities */

char *phy_slot;            /* Physical slot */

char *module_alias;            /* Linux kernel module alias */

char *label;                /* Device name as exported by BIOS */

int numa_node;            /* NUMA node */

pciaddr_t flags[6];            /* PCI_IORESOURCE_* flags for regions */

pciaddr_t rom_flags;            /* PCI_IORESOURCE_* flags for expansion ROM */

int domain;                /* PCI domain (host bridge) */

 

/* Fields used internally: */

struct pci_access *access;

struct pci_methods *methods;

u8 *cache;                /* Cached config registers */

int cache_len;

int hdrtype;                /* Cached low 7 bits of header type, -1 if unknown */

void *aux;                /* Auxillary data */

};

 

#define PCI_ADDR_IO_MASK (~(pciaddr_t) 0x3)

#define PCI_ADDR_MEM_MASK (~(pciaddr_t) 0xf)

#define PCI_ADDR_FLAG_MASK 0xf

 

u8 pci_read_byte(struct pci_dev *, int pos) PCI_ABI; /* Access to configuration space */

u16 pci_read_word(struct pci_dev *, int pos) PCI_ABI;

u32 pci_read_long(struct pci_dev *, int pos) PCI_ABI;

int pci_read_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI;

int pci_read_vpd(struct pci_dev *d, int pos, u8 *buf, int len) PCI_ABI;

int pci_write_byte(struct pci_dev *, int pos, u8 data) PCI_ABI;

int pci_write_word(struct pci_dev *, int pos, u16 data) PCI_ABI;

int pci_write_long(struct pci_dev *, int pos, u32 data) PCI_ABI;

int pci_write_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI;

 

int pci_fill_info(struct pci_dev *, int flags) PCI_ABI; /* Fill in device information */

 

#define PCI_FILL_IDENT        0x0001

#define PCI_FILL_IRQ        0x0002

#define PCI_FILL_BASES        0x0004

#define PCI_FILL_ROM_BASE    0x0008

#define PCI_FILL_SIZES        0x0010

#define PCI_FILL_CLASS        0x0020

#define PCI_FILL_CAPS        0x0040

#define PCI_FILL_EXT_CAPS    0x0080

#define PCI_FILL_PHYS_SLOT    0x0100

#define PCI_FILL_MODULE_ALIAS    0x0200

#define PCI_FILL_LABEL        0x0400

#define PCI_FILL_NUMA_NODE    0x0800

#define PCI_FILL_IO_FLAGS    0x1000

#define PCI_FILL_RESCAN        0x00010000

 

void pci_setup_cache(struct pci_dev *, u8 *cache, int len) PCI_ABI;

 

/*

*    Capabilities

*/

 

struct pci_cap {

struct pci_cap *next;

u16 id;                /* PCI_CAP_ID_xxx */

u16 type;                /* PCI_CAP_xxx */

unsigned
int addr;            /* Position in the config space */

};

 

#define PCI_CAP_NORMAL        1    /* Traditional PCI capabilities */

#define PCI_CAP_EXTENDED    2    /* PCIe extended capabilities */

 

struct pci_cap *pci_find_cap(struct pci_dev *, unsigned
int id, unsigned
int type) PCI_ABI;

 

/*

*    Filters

*/

 

struct pci_filter {

int domain, bus, slot, func;            /* -1 = ANY */

int vendor, device, device_class;

int rfu[3];

};

 

void pci_filter_init(struct pci_access *, struct pci_filter *) PCI_ABI;

char *pci_filter_parse_slot(struct pci_filter *, char *) PCI_ABI;

char *pci_filter_parse_id(struct pci_filter *, char *) PCI_ABI;

int pci_filter_match(struct pci_filter *, struct pci_dev *) PCI_ABI;

 

/*

*    Conversion of PCI ID's to names (according to the pci.ids file)

*

*    Call pci_lookup_name() to identify different types of ID's:

*

*    VENDOR                (vendorID) -> vendor

*    DEVICE                (vendorID, deviceID) -> device

*    VENDOR | DEVICE            (vendorID, deviceID) -> combined vendor and device

*    SUBSYSTEM | VENDOR        (subvendorID) -> subsystem vendor

*    SUBSYSTEM | DEVICE        (vendorID, deviceID, subvendorID, subdevID) -> subsystem device

*    SUBSYSTEM | VENDOR | DEVICE    (vendorID, deviceID, subvendorID, subdevID) -> combined subsystem v+d

*    SUBSYSTEM | ...            (-1, -1, subvendorID, subdevID) -> generic subsystem

*    CLASS                (classID) -> class

*    PROGIF                (classID, progif) -> programming interface

*/

 

char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...) PCI_ABI;

 

int pci_load_name_list(struct pci_access *a) PCI_ABI;    /* Called automatically by pci_lookup_*() when needed; returns success */

void pci_free_name_list(struct pci_access *a) PCI_ABI;    /* Called automatically by pci_cleanup() */

void pci_set_name_list_path(struct pci_access *a, char *name, int to_be_freed) PCI_ABI;

void pci_id_cache_flush(struct pci_access *a) PCI_ABI;

 

enum pci_lookup_mode {

PCI_LOOKUP_VENDOR = 1,        /* Vendor name (args: vendorID) */

PCI_LOOKUP_DEVICE = 2,        /* Device name (args: vendorID, deviceID) */

PCI_LOOKUP_CLASS = 4,            /* Device class (args: classID) */

PCI_LOOKUP_SUBSYSTEM = 8,

PCI_LOOKUP_PROGIF = 16,        /* Programming interface (args: classID, prog_if) */

PCI_LOOKUP_NUMERIC = 0x10000,        /* Want only formatted numbers; default if access->numeric_ids is set */

PCI_LOOKUP_NO_NUMBERS = 0x20000,    /* Return NULL if not found in the database; default is to print numerically */

PCI_LOOKUP_MIXED = 0x40000,        /* Include both numbers and names */

PCI_LOOKUP_NETWORK = 0x80000,        /* Try to resolve unknown ID's by DNS */

PCI_LOOKUP_SKIP_LOCAL = 0x100000,    /* Do not consult local database */

PCI_LOOKUP_CACHE = 0x200000,        /* Consult the local cache before using DNS */

PCI_LOOKUP_REFRESH_CACHE = 0x400000,    /* Forget all previously cached entries, but still allow updating the cache */

PCI_LOOKUP_NO_HWDB = 0x800000,    /* Do not ask udev's hwdb */

};

 

#endif

 

 

 

Libpci库的调用的更多相关文章

  1. 调用libpci库出现的问题和解决方法

    调用libpci库出现的问题和解决方法   本方案以pciutils-3.5.1为例.   1. 从以下地址下载pciutils-3.5.1.tar.xz https://www.kernel.org ...

  2. [转]如何利用ndk-stack工具查看so库的调用堆栈【代码示例】?

    如何利用ndk-stack工具查看so库的调用堆栈[代码示例]? http://hi.baidu.com/subo4110/item/d00395b3bf63e4432bebe36d Step1:An ...

  3. C# - VS2019调用AForge库实现调用摄像头拍照功能

    前言 作为一名资深Delphi7程序员,想要实现摄像头扫描一维码/二维码功能,发现所有免费的第三方库都没有简便的实现办法,通用的OpenCV或者ZXing库基本上只支持XE以上的版本,而且一维码的识别 ...

  4. scikitlearn库中调用k-近邻算法的操作步骤

    1.k近邻算法可以说是唯一一个没有训练过程的机器学习算法,它含有训练基础数据集,但是是一种没有模型的算法,为了将其和其他算法进行统一,我们把它的训练数据集当做它的模型本身.2.在scikitlearn ...

  5. C++Builder及VC的库相互调用

    coff2omf  vc.lib  bc.lib implib -f xxx.lib xxx.dll dll文件为VC编译的动态库lib文件为你需要转换的c++ builder 使用的静态库. 这也是 ...

  6. C语言下动态库相互调用

    前段时间需要完成多个模块业务,而这些模块的接口都是一样的,于是为了方便管理就把每个模块都根据接口封装成了SO库,这里就留下SO库调用样例 SO库源文件代码: //TestSo.c #include & ...

  7. 6.关于QT中的内存管理,动态的制作,动态库的调用,静态库的制作

     一  QT的内存管理 1  QT中的内存管理是QObject来管理的 2  QT中的内存管理没有cocos2dx中的引用计数 3  组件能够指定父对象 QTimer *timer = QTime ...

  8. NDK中android.mk文件的简单介绍和第三方库的调用

    先贴一个样例,然后解释一下: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := mydjvuapi SRC_FILE_ ...

  9. 『Python CoolBook』C扩展库_其五_C语言层面Python库之间调用API

    点击进入项目 一.C层面模块添加API 我们仍然操作如下结构体, #include <math.h> typedef struct Point { double x,y; } Point; ...

随机推荐

  1. div水平居中和垂直居中

    水平居中和垂直居中 水平居中包含两种情况:        块级元素的水平居中:margin:0px auto;        文字内容的水平居中:text-align: center;        ...

  2. Foundation框架

    1.框架是由许多类.方法.函数.文档按照一定的逻辑组织起来的集合,以便使研发程序变的更容易 清除缓存,删除这个文件夹下的所有文件/Users/fanyafang/Library/Developer/X ...

  3. .NET工程师技术进阶

    通常,一个人对技术的掌握程度可以分为精通.熟练.熟悉.了解,详细解析如下: 精通:能够掌握此技术的85%技术要点以上,使用此技术时间超过两年,并使用此技术成功实施5个以上的项目.能使用此技术优化性能或 ...

  4. [转]Linux进程间通信——使用消息队列

    点击此处阅读原文 另收藏作者ljianhui的专栏初学Linux 下面来说说如何使用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linu ...

  5. 【iOS开发】在 App 中加入 AdMob 广告 - 入门介绍与编程技巧

    前言 虽然在App中加入广告来盈利是比较低级的商业化方式,但对于个人开发者或者小团队开发者来说,做出一个简单易用的免费小工具(举个栗子),在里面加入一些广告,如果用的人多,也是可以带来一些可观的收入的 ...

  6. python 随机生成固定长度的字串

    from random import Random#随机生成4到20位的用户名def random_username(): username = '' chars = 'AaBbCcDdEeFfGgH ...

  7. cf 710 E Generate a String

    题意: 开始你有数字$0$,你可以用代价$x$将该数字加$1$或减$1$(当$x > 0$时),或用代价$y$将该数字变为$2x$,那么问得到数字$n$所需的最少代价是多少. 数据范围$1 \l ...

  8. [译]使用JMH进行微基准测试:不要猜,要测试!

    英文原文:Micro Benchmarking with JMH: Measure, don't guess!翻译地址:使用JMH进行微基准测试:不要猜,要测试!原文作者:Antonio翻译作者:Ho ...

  9. windows 7系统下出现某盘回收站损坏解决办法

    今天遇到一个从没有遇见的问题,就是领导说他的回收站损坏了,要我去看下,我一开始也没用辙,网上搜了很多,说在命令提示符里面修改,我试了不行,后来我这样做就好了:1.打开计算机 2.找到工具选项,单击选择 ...

  10. php set_time_limit()用法测试详解

    在php中set_time_limit函数是用来限制页面执行时间的,如我想把一个php页面的执行时间定义为5秒就可以set_time_limit(5)了.   一个php脚本通过crontab每5分钟 ...