这几天发现在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. 浅述WinForm多线程编程与Control.Invoke的应用

    VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...

  2. ES6里箭头函数的陷阱

    ECMAScript 6新增了箭头函数 原来的匿名函数 function(){},现在可以简化成()=>{} 看起来高大上,像C#什么的语法. 但是箭头函数的this对象,不能更改,总是指向函数 ...

  3. hadoop的自定义数据类型和与关系型数据库交互

    最近有一个需求就是在建模的时候,有少部分数据是postgres的,只能读取postgres里面的数据到hadoop里面进行建模测试,而不能导出数据到hdfs上去. 读取postgres里面的数据库有两 ...

  4. HDU 2732:Leapin' Lizards(最大流)

    http://acm.hdu.edu.cn/showproblem.php?pid=2732 题意:给出两个地图,蜥蜴从一个柱子跳跃到另外一个地方,那么这个柱子就可能会坍塌,第一个地图是柱子可以容忍跳 ...

  5. Android系统中自定义按键的短按、双击、长按事件

    在项目中碰到这样的问题: 由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成: 1.单击 ...

  6. java static静态方法的并发性

    在做一个web项目的时候需要做一个通用类去处理一些问题,想到这个类很多地方都有用到,又不想每次都new一个,因此就定义了里面的方法是静态方法,然后又因为多个静态方法都用到了同一个对象,结果定义了一个类 ...

  7. C# 正则表达式小坑 -- not enough

    今天遇到了一个奇怪的报错: 相关的代码是这样的: Regex regex = new Regex("(?<=wwwroot\\).*?$"); 然后把这段正则复制到任何正则测 ...

  8. filter-自己的理解

    在配置filter中的拦截功能时候 ,我们在web.xml中进行配置文件.filter过滤文件有系统自己带有的,还有就是我们手写的filter文件.网页调用servlter的时候,我们可以在此之前调用 ...

  9. [CF752D]Santa Claus and a Palindrome(优先队列,贪心乱搞)

    题目链接:http://codeforces.com/contest/752/problem/D 题意:给长度为k的n个字符串,每一个字符串有权值,求构造一个大回文串.使得权值最大. 因为字符串长度都 ...

  10. C4.5学习及源码阅读

    下面是C4.5源码的下载地址: http://www.rulequest.com/Personal/ 这里先立一个flag,后续更新...... 恕我孤陋寡闻,第一次看到这样的主函数: #includ ...