PCI - Library and Command Line utilities

PCI Utils:
  • Set of utilities used for listing PCI Devices, getting status information, dumping the config registers, getting the BAR (Base Address Register) information, and setting configuration space registers.
  • Open source, cross-platform, portable library and utilities.
  • pcilib (similar to libpci.so in Linux).
  • lspci (list the devices, getting the device information and status information of PCI devices).
  • setpci (set the configuration parameters, update the configuration registers).
  • update-pciids (utility used to get the latest pci id information from the respective distributions).
    • pcilib:
      • Userspace library used for accessing PCI devices.
      • PCI command-line utilities, such as lspci, setpci, use pci library to talk to the devices.
      • Provides Libraries and Header files of Development,
        • /usr/include/pci
        • libpci.so
    • lspci:
      • Displays detailed information about all the devices including host controller (-vvv).
      • Displays the information about PCI buses and devices connected to them.
      • Shows the Vendor & Device identifier as readable name and number (-nnn).
      • Dumps whole PCI configuration space in hexadecimal format (-xxx).
      • Dumps extended configuration (4K Byte) space of PCI Express devices.
      • Shows kernel module information which handles respective devices (-k).
      • Displays tree-like diagram all buses, bridges, devices and connection between them (-t).
      • Shows all IRQ numbers and addresses.
      • Categorized display based on Domain Numbers.
FIG: For Example - 00.01.0 means this ISA Bridge is present on the Bus number 0
  • Representation: 
    • BUS is 00 to ff (8-Bit denotion).
    • Device Number: 00 to 1f (5-Bit denotion).
    • Function is 3-Bit denotion: 0 to 7.
FIG: lspci -vvv gives complete information about PCI device and Host Controller. Also provides information about the Kernel modules for the respective pci devices.

In the above figure, the SATA Controller information indicates the Kernel modules as 'ahci'.

FIG: lspci -nnn

FIG: lspci -xxx for hexdump.

Example: To filter SATA Controller Hexdump.

Tree Like Diagram (Here, there's only 1 Bus. In case of multiple buses we can see which device gets connected to which Bus by using 'lspci -t' command).

-k for a particular device.
    • setpci:
      • Used for querying and configuring the PCI Devices.
      • Dumps all the known PCI configuration registers and capabilities.
Example: Position and Data Type of a register. 'pos' is the position. Here, w = word register (16Bit register). B = 1 Byte Register. L = Long (32 Bit Register).
      • The Utility requires root privileges for all configuration operations.
      • Featured with demo that does not wire into the configuration space.
      • Demo mode which can be used to verify our complex operation sequences.
      • Used for two kinds of operations such as read and write operations.
    • update-pciids:
      • pci.ids is the file which contains the list of all PCI IDs.
      • Fetches the current version of pci.ids file from primary distribution and install.
      • Utility downloads the latest version of PCI ID list.

'setpci' Usage Demonstration below:
  • Shows type 0 / 1 config space registers.
  • setpci has 2 methods of accessing the registers - One with device function (Bus Device Function) or By using Device ID and Ventor ID.

  • Can be used to update or change register space (using sudo along with the commands).
  • Used for debugging pci drivers. For e.g. if something changes, we can use this to track and check the changes / update(s) made by linux device drivers. The Read only registers will not change.
  • pci Library can talk with the pci devices using this.
PCI Library: (Structure Definition, Application Programming)
  • Dependency Packages:
    • build-essential: contains makefile, gcc
    • vim editor: to write code
    • libpci-dev: contains header files and library files.
    • pciutils
    • How to install dependency packages in ubuntu
      • $ sudo apt-get install build-essential vim libpci-dev pciutils
    • After installation, we will get Libraries and Header files of development:
      • /usr/include/pci
      • libpci.so (available in the standard library path. In case of ubuntu it will be available in lib/x86-linux-gnu).
  • struct pci_access:
    • pci_dev member *devices: Single linked-list pointer. You can traverse all the devices available in the system.
    • Access Method: procfs, sysfs.
    • In this, we can load PCI ID id_filename.
    • And then, we can set bit to 1 on the file name.
    • Lookup numeric ids.
    • Use different callback functions.
    • pci_dev: for each device.
  • struct pci_dev:
    • struct pci_dev *next: Single linked-list pointer which points to the next PCI device in chain.
    • If *next is NULL, mean no more pci devices are available.
  • struct pci_filter:
  • PCI Access Initialization / Cleanup APIs:
    • pci_alloc: allocates pci structure dynamically.
      • struct pci_access *pci_alloc(void);
    • pci_init: initializes pci structure with default values.
      • void pci_init(struct pci_access *);
    • pci_cleanup: cleans and frees the memory.
      • coid pci_cleanup(struct pci_access *);
  • PCI Device Scan/Get/free APIs:
    • pci_scan_bus: Scans the complete bus and update into the pci access structure. Once done, struct pci_dev *devices gets updated. This is a single linkedlist chain, using which we can traverse the complete devices in the system.
      • void pci_scan_bus(struct pci_access *);
    • pci_get_dev: get our own structure. It has multiple single linkedlist, checks for our domain, bus, devices, function.
      • struct pci_dev *pci_get_dev(struct pci_access *, int domain, int bus, int dev, int func);
    • pci_free_dev: To free the pci_dev allocated memory.
      • coid pci_free_dev(struct pci_dev *);
    • pci_lookup_method: info about pci.
      • int pci_lookup_method(char *name);
    • pci_get_method_name
      • char *pci_get_method_name(int index);
  • PCI Configuration Space Access APIs:
    • u8 pci_read_byte(struct pci_dev *, int pos);
    • u16 pci_read_word(struct pci_dev *, int pos); (For e.g. VENDOR and DEVICE ID are 16-Bit)
    • u32 pci_read_long(struct pci_dev *, int pos); (For e.g. BAR register)
    • int pci_read_block(struct pci_dev *, int pos, u8 *buf, int len); 
    • int pci_write_byte(struct pci_dev *, int pos, u8 data);
    • int pci_write_word(struct pci_dev *, int pos, u16 data);
    • int pci_write_long(struct pci_dev *, int pos, u32 data);
    • int pci_write_block(struct pci_dev *, int pos, u8 *buf, int len);
  • PCI Filter Funtion APIs:
    • pci_filter_init
      • void pci_filter_init(struct pci_access *, struct pci_filter *)
    • pci_filter_parse_slot
      • char *pci_filter_parse_slot(struct pci_filter *, char *)
    • pci_filter_parse_id
      • char *pci_filter_parse_id(struct pci_filter *, char *)
    • pci_filter_match: used to check the vendor id or device id and returns true/false accordingly.
      • int pci_filter_match(struct pci_filter *, struct pci_dev *)
  • PCI ID Name List APIs:
    • int pci_load_name_list(struct pci_access *)
      • When this is used, our *id_file_name gets updated using this.
    • int pci_free_name_list(struct pci_access *)
    • void pci_set_name_list_path(struct pci_access *, char *name, int to_be_freed)
      • To set path.
    • void pci_id_cache_flush(struct pci_access *)