pciutils的架构分析

本文深入分析了PCIUtils库的结构,包括`struct pci_access`及其成员,以及不同操作系统的访问方法如`struct pci_methods`。内容涉及错误处理、设备扫描、配置空间读写等功能,并探讨了在没有高级访问方法时,如何退化到I/O端口访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Basice definations
=====================

"struct pci_access", the structure used to communicate with lipci

lib/pci.h:
 43 struct pci_access {
 44   /* Options you can change: */
 45   unsigned int method;                  /* Access method */
 46   int writeable;                        /* Open in read/write mode */
 47   int buscentric;                       /* Bus-centric view of the world */
 48
 49   char *id_file_name;                   /* Name of ID list file (use pci_set_name_list_path()) */
 50   int free_id_name;                     /* Set if id_file_name is malloced */
 51   int numeric_ids;                      /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */
 52
 53   unsigned int id_lookup_mode;          /* pci_lookup_mode flags which are set automatically */
 54                                         /* Default: PCI_LOOKUP_CACHE */
 55
 56   int debugging;                        /* Turn on debugging messages */
 57
 58   /* Functions you can override: */
 59   void (*error)(char *msg, ...) PCI_PRINTF(1,2);        /* Write error message and quit */
 60   void (*warning)(char *msg, ...) PCI_PRINTF(1,2);      /* Write a warning message */
 61   void (*debug)(char *msg, ...) PCI_PRINTF(1,2);        /* Write a debugging message */
 62
 63   struct pci_dev *devices;              /* Devices found on this bus */
 64
 65   /* Fields used internally: */
 66   struct pci_methods *methods;
 67   struct pci_param *params;
 68   struct id_entry **id_hash;            /* names.c */
 69   struct id_bucket *current_id_bucket;
 70   int id_load_failed;
 71   int id_cache_status;                  /* 0=not read, 1=read, 2=dirty */
 72   int fd;                               /* proc: fd */
 73   int fd_rw;                            /* proc: fd opened read-write */
 74   struct pci_dev *cached_dev;           /* proc: device the fd is for */
 75   int fd_pos;                           /* proc: current position */
 76 };


struct pci_methods: the methods to access pci configure space

lib/internal.h:
 16 struct pci_methods {
 17   char *name;
 18   char *help;
 19   void (*config)(struct pci_access *);
 20   int (*detect)(struct pci_access *);
 21   void (*init)(struct pci_access *);
 22   void (*cleanup)(struct pci_access *);
 23   void (*scan)(struct pci_access *);
 24   int (*fill_info)(struct pci_dev *, int flags);
 25   int (*read)(struct pci_dev *, int pos, byte *buf, int len);
 26   int (*write)(struct pci_dev *, int pos, byte *buf, int len);
 27   void (*init_dev)(struct pci_dev *);
 28   void (*cleanup_dev)(struct pci_dev *);
 29 };

The methods are OS depended:

lib/init.c:
 16 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
 17   NULL,
 18 #ifdef PCI_HAVE_PM_LINUX_SYSFS
 19   &pm_linux_sysfs,
 20 #else
 21   NULL,
 22 #endif
 23 #ifdef PCI_HAVE_PM_LINUX_PROC
 24   &pm_linux_proc,
 25 #else
 26   NULL,
 27 #endif
 28 #ifdef PCI_HAVE_PM_INTEL_CONF
 29   &pm_intel_conf1,
 30   &pm_intel_conf2,
 31 #else
 32   NULL,
 33   NULL,
 34 #endif
 35 #ifdef PCI_HAVE_PM_FBSD_DEVICE
 36   &pm_fbsd_device,
 37 #else
 38   NULL,
 39 #endif
 40 #ifdef PCI_HAVE_PM_AIX_DEVICE
 41   &pm_aix_device,
 42 #else
 43   NULL,
 44 #endif
 45 #ifdef PCI_HAVE_PM_NBSD_LIBPCI
 46   &pm_nbsd_libpci,
 47 #else
 48   NULL,
 49 #endif  
 50 #ifdef PCI_HAVE_PM_OBSD_DEVICE
 51   &pm_obsd_device,
 52 #else
 53   NULL,
 54 #endif
 55 #ifdef PCI_HAVE_PM_DUMP
 56   &pm_dump,
 57 #else
 58   NULL,
 59 #endif
 60 };

lib/pci.h:
 28 enum pci_access_type {
 29   /* Known access methods, remember to update access.c as well */
 30   PCI_ACCESS_AUTO,                      /* Autodetection */
 31   PCI_ACCESS_SYS_BUS_PCI,               /* Linux /sys/bus/pci */
 32   PCI_ACCESS_PROC_BUS_PCI,              /* Linux /proc/bus/pci */
 33   PCI_ACCESS_I386_TYPE1,                /* i386 ports, type 1 */
 34   PCI_ACCESS_I386_TYPE2,                /* i386 ports, type 2 */
 35   PCI_ACCESS_FBSD_DEVICE,               /* FreeBSD /dev/pci */
 36   PCI_ACCESS_AIX_DEVICE,                /* /dev/pci0, /dev/bus0, etc. */
 37   PCI_ACCESS_NBSD_LIBPCI,               /* NetBSD libpci */
 38   PCI_ACCESS_OBSD_DEVICE,               /* OpenBSD /dev/pci */
 39   PCI_ACCESS_DUMP,                      /* Dump file */
 40   PCI_ACCESS_MAX
 41 };

For SUNOS, we always get the following method:
255 struct pci_methods pm_intel_conf1 = {
256   "intel-conf1",
257   "Raw I/O port access using Intel conf1 interface",
258   NULL,                                 /* config */
259   conf1_detect,
260   conf12_init,
261   conf12_cleanup,
262   pci_generic_scan,
263   pci_generic_fill_info,
264   conf1_read,
265   conf1_write,
266   NULL,                                 /* init_dev */
267   NULL                                  /* cleanup_dev */
268 };

Other methods should be all NULL's.

2. libpci interface
===================

pci_alloc()
alloc a pci_access structure

pci_init()
specify the debugging method and pci access methods

Since pci access methods are OS depended, it's a neccesarity to choose the method dynamically. In pci_alloc(), each config() function of each member in pci_methods[] is invoked to let the methods declaim themselves. If this failed, libpci has to specify a suitable method, otherwise it should be result in error. In pci_init(), if no method is claimed for pci access, the detect() of pci_methods are invoked in turn, once a success return, the mothod for pci access is specified with it.

So in the real case, the io port access is always support. So if there is no advandced method is chosed on an OS. The io port access the last choose.

3. rough architecture of pciutils

        pci utilities: lspci, setpci ...
************************************************
 libpci interfaces(pci_alloc, pci_init, bus_scan)

       OS dependent pci access method( ... )
************************************************
            pci device configure space
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值