Skip to content

Instantly share code, notes, and snippets.

@syuu1228
Created January 6, 2012 03:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syuu1228/1568777 to your computer and use it in GitHub Desktop.
Save syuu1228/1568777 to your computer and use it in GitHub Desktop.
Register Dump Tool for MSI Address Register & MSI Data Register / GPLv2
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <pci/pci.h>
#define FLAG(x,y) ((x & y) ? '+' : '-')
/*
* Constants for Intel APIC based MSI messages.
*/
/*
* Shifts for MSI data
*/
#define MSI_DATA_VECTOR_SHIFT 0
#define MSI_DATA_VECTOR_MASK 0x000000ff
#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & \
MSI_DATA_VECTOR_MASK)
#define MSI_DATA_DELIVERY_MODE_SHIFT 8
#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
#define MSI_DATA_LEVEL_SHIFT 14
#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
#define MSI_DATA_TRIGGER_SHIFT 15
#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
/*
* Shift/mask fields for msi address
*/
#define MSI_ADDR_BASE_HI 0
#define MSI_ADDR_BASE_LO 0xfee00000
#define MSI_ADDR_DEST_MODE_SHIFT 2
#define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT)
#define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT)
#define MSI_ADDR_REDIRECTION_SHIFT 3
#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
/* dedicated cpu */
#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
/* lowest priority */
#define MSI_ADDR_DEST_ID_SHIFT 12
#define MSI_ADDR_DEST_ID_MASK 0x00ffff0
#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
MSI_ADDR_DEST_ID_MASK)
#define MSI_ADDR_EXT_DEST_ID(dest) ((dest) & 0xffffff00)
#define MSI_ADDR_IR_EXT_INT (1 << 4)
#define MSI_ADDR_IR_SHV (1 << 3)
#define MSI_ADDR_IR_INDEX1(index) ((index & 0x8000) >> 13)
#define MSI_ADDR_IR_INDEX2(index) ((index & 0x7fff) << 5)
typedef uint8_t byte;
typedef uint16_t word;
struct device {
struct device *next;
struct pci_dev *dev;
unsigned int config_cnt;
byte config[256];
};
/* Config space accesses */
static inline byte
get_conf_byte(struct device *d, unsigned int pos)
{
return d->config[pos];
}
static word
get_conf_word(struct device *d, unsigned int pos)
{
return d->config[pos] | (d->config[pos+1] << 8);
}
static u32
get_conf_long(struct device *d, unsigned int pos)
{
return d->config[pos] |
(d->config[pos+1] << 8) |
(d->config[pos+2] << 16) |
(d->config[pos+3] << 24);
}
static void
show_msi(struct device *d, int where, int cap)
{
int is64;
u32 address_hi, address_lo;
u16 data;
printf("Message Signalled Interrupts: 64bit%c Queue=%d/%d Enable%c\n",
FLAG(cap, PCI_MSI_FLAGS_64BIT),
(cap & PCI_MSI_FLAGS_QSIZE) >> 4,
(cap & PCI_MSI_FLAGS_QMASK) >> 1,
FLAG(cap, PCI_MSI_FLAGS_ENABLE));
is64 = cap & PCI_MSI_FLAGS_64BIT;
if (!pci_read_block(d->dev, where + PCI_MSI_ADDRESS_LO,
d->config + where + PCI_MSI_ADDRESS_LO,
(is64 ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32) + 2
- PCI_MSI_ADDRESS_LO)) {
printf("Unable to read 4 bytes of configuration space.");
return ;
}
if (is64) {
address_hi = get_conf_long(d, where + PCI_MSI_ADDRESS_HI);
data = get_conf_word(d, where + PCI_MSI_DATA_64);
}else{
address_hi = 0;
data = get_conf_word(d, where + PCI_MSI_DATA_32);
}
address_lo = get_conf_long(d, where + PCI_MSI_ADDRESS_LO);
printf("address_hi=%x\n", address_hi);
printf("address_lo=%x dest_mode=%s redirection=%s dest_id=%u\n",
address_lo,
(address_lo & MSI_ADDR_DEST_MODE_LOGICAL) ? "logical" : "physical",
(address_lo & MSI_ADDR_REDIRECTION_LOWPRI) ? "lowpri" : "cpu",
(address_lo & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT);
printf("data=%x trigger=%s level=%s delivery_mode=%s vector=%u\n",
data,
(data & MSI_DATA_TRIGGER_LEVEL) ? "level" : "edge",
(data & MSI_DATA_LEVEL_ASSERT) ? "assert" : "deassert",
(data & MSI_DATA_DELIVERY_LOWPRI) ? "lowpri" : "fixed",
data & MSI_DATA_VECTOR_MASK);
}
int main(int argc, char **argv)
{
struct pci_access *pacc;
struct pci_filter filter; /* Device filter */
struct pci_dev *p;
struct device *d;
char *msg;
u16 vendor;
u8 header_type;
int found = 0;
if (argc < 2) {
printf("more args required\n");
return -1;
}
pacc = pci_alloc();
pci_filter_init(pacc, &filter);
pci_init(pacc);
if (msg = pci_filter_parse_slot(&filter, argv[1])) {
printf("pci_filter_parse_slot %s\n", msg);
return -1;
}
pci_scan_bus(pacc);
for (p = pacc->devices; p; p = p->next) {
if (!pci_filter_match(&filter, p))
continue;
else {
found = 1;
break;
}
}
if (!found) {
printf("device not found\n");
return -1;
}
d = malloc(sizeof(struct device));
bzero(d, sizeof(*d));
d->dev = p;
if (!pci_read_block(p, 0, d->config, 64)) {
printf("Unable to read 64 bytes of configuration space.");
return -1;
}
d->config_cnt = 64;
pci_setup_cache(p, d->config, d->config_cnt);
pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
int where = get_conf_byte(d, PCI_CAPABILITY_LIST) & ~3;
while (where)
{
int id, next, cap;
if (!pci_read_block(d->dev, where, d->config + where, 4)) {
printf("Unable to read 4 bytes of configuration space.");
return -1;
}
id = get_conf_byte(d, where + PCI_CAP_LIST_ID);
next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
cap = get_conf_word(d, where + PCI_CAP_FLAGS);
if (id == 0xff)
{
printf("cap chain broken\n");
break;
}
if (id == PCI_CAP_ID_MSI)
show_msi(d, where, cap);
where = next;
}
pci_cleanup(pacc);
return 0;
}
@brunoalexsantos
Copy link

Hello,
How I can compile and execute this code? Can you share the make file?

@sharathkumardm
Copy link

sharathkumardm commented Nov 4, 2022

need to be built inside pciutils package
replace "#include <pci/pci.h>" to "#include "lib/pci.h"" in msireg.c file

updated Makefile as below
The example of use of libpci
example$(EXEEXT): example.o lib/$(PCIIMPLIB)
example.o: example.c $(PCIINC)
msireg$(EXEEXT): msireg.o lib/$(PCIIMPLIB)
msireg.o: msireg.c $(PCIINC)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment