Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jun 21st, 2012  |  syntax: None  |  size: 5.44 KB  |  hits: 8  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <pci/pci.h>
  6.  
  7. #define FLAG(x,y) ((x & y) ? '+' : '-')
  8.  
  9. /*
  10.  * Constants for Intel APIC based MSI messages.
  11.  */
  12.  
  13. /*
  14.  * Shifts for MSI data
  15.  */
  16.  
  17. #define MSI_DATA_VECTOR_SHIFT           0
  18. #define  MSI_DATA_VECTOR_MASK           0x000000ff
  19. #define  MSI_DATA_VECTOR(v)             (((v) << MSI_DATA_VECTOR_SHIFT) & \
  20.                                          MSI_DATA_VECTOR_MASK)
  21.  
  22. #define MSI_DATA_DELIVERY_MODE_SHIFT    8
  23. #define  MSI_DATA_DELIVERY_FIXED        (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
  24. #define  MSI_DATA_DELIVERY_LOWPRI       (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
  25.  
  26. #define MSI_DATA_LEVEL_SHIFT            14
  27. #define  MSI_DATA_LEVEL_DEASSERT        (0 << MSI_DATA_LEVEL_SHIFT)
  28. #define  MSI_DATA_LEVEL_ASSERT          (1 << MSI_DATA_LEVEL_SHIFT)
  29.  
  30. #define MSI_DATA_TRIGGER_SHIFT          15
  31. #define  MSI_DATA_TRIGGER_EDGE          (0 << MSI_DATA_TRIGGER_SHIFT)
  32. #define  MSI_DATA_TRIGGER_LEVEL         (1 << MSI_DATA_TRIGGER_SHIFT)
  33.  
  34. /*
  35.  * Shift/mask fields for msi address
  36.  */
  37.  
  38. #define MSI_ADDR_BASE_HI                0
  39. #define MSI_ADDR_BASE_LO                0xfee00000
  40.  
  41. #define MSI_ADDR_DEST_MODE_SHIFT        2
  42. #define  MSI_ADDR_DEST_MODE_PHYSICAL    (0 << MSI_ADDR_DEST_MODE_SHIFT)
  43. #define  MSI_ADDR_DEST_MODE_LOGICAL     (1 << MSI_ADDR_DEST_MODE_SHIFT)
  44.  
  45. #define MSI_ADDR_REDIRECTION_SHIFT      3
  46. #define  MSI_ADDR_REDIRECTION_CPU       (0 << MSI_ADDR_REDIRECTION_SHIFT)
  47.                                         /* dedicated cpu */
  48. #define  MSI_ADDR_REDIRECTION_LOWPRI    (1 << MSI_ADDR_REDIRECTION_SHIFT)
  49.                                         /* lowest priority */
  50.  
  51. #define MSI_ADDR_DEST_ID_SHIFT          12
  52. #define  MSI_ADDR_DEST_ID_MASK          0x00ffff0
  53. #define  MSI_ADDR_DEST_ID(dest)         (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
  54.                                          MSI_ADDR_DEST_ID_MASK)
  55. #define MSI_ADDR_EXT_DEST_ID(dest)      ((dest) & 0xffffff00)
  56.  
  57. #define MSI_ADDR_IR_EXT_INT             (1 << 4)
  58. #define MSI_ADDR_IR_SHV                 (1 << 3)
  59. #define MSI_ADDR_IR_INDEX1(index)       ((index & 0x8000) >> 13)
  60. #define MSI_ADDR_IR_INDEX2(index)       ((index & 0x7fff) << 5)
  61.  
  62. typedef uint8_t byte;
  63. typedef uint16_t word;
  64.  
  65. struct device {
  66.   struct device *next;
  67.   struct pci_dev *dev;
  68.   unsigned int config_cnt;
  69.   byte config[256];
  70. };
  71.  
  72. /* Config space accesses */
  73.  
  74. static inline byte
  75. get_conf_byte(struct device *d, unsigned int pos)
  76. {
  77.   return d->config[pos];
  78. }
  79.  
  80. static word
  81. get_conf_word(struct device *d, unsigned int pos)
  82. {
  83.   return d->config[pos] | (d->config[pos+1] << 8);
  84. }
  85.  
  86. static u32
  87. get_conf_long(struct device *d, unsigned int pos)
  88. {
  89.   return d->config[pos] |
  90.     (d->config[pos+1] << 8) |
  91.     (d->config[pos+2] << 16) |
  92.     (d->config[pos+3] << 24);
  93. }
  94.  
  95. static void
  96. show_msi(struct device *d, int where, int cap)
  97. {
  98.   int is64;
  99.   u32 address_hi, address_lo;
  100.   u16 data;
  101.  
  102.   printf("Message Signalled Interrupts: 64bit%c Queue=%d/%d Enable%c\n",
  103.          FLAG(cap, PCI_MSI_FLAGS_64BIT),
  104.          (cap & PCI_MSI_FLAGS_QSIZE) >> 4,
  105.          (cap & PCI_MSI_FLAGS_QMASK) >> 1,
  106.          FLAG(cap, PCI_MSI_FLAGS_ENABLE));
  107.  
  108.   is64 = cap & PCI_MSI_FLAGS_64BIT;
  109.  
  110.   if (!pci_read_block(d->dev, where + PCI_MSI_ADDRESS_LO,
  111.                       d->config + where + PCI_MSI_ADDRESS_LO,
  112.                       (is64 ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32) + 2
  113.                       - PCI_MSI_ADDRESS_LO)) {
  114.           printf("Unable to read 4 bytes of configuration space.");
  115.           return ;
  116.   }
  117.  
  118.   if (is64) {
  119.           address_hi = get_conf_long(d, where + PCI_MSI_ADDRESS_HI);
  120.           data = get_conf_word(d, where + PCI_MSI_DATA_64);
  121.   }else{
  122.           address_hi = 0;
  123.           data = get_conf_word(d, where + PCI_MSI_DATA_32);
  124.   }
  125.   address_lo = get_conf_long(d, where + PCI_MSI_ADDRESS_LO);
  126.  
  127.   printf("address_hi=%x\n", address_hi);
  128.   printf("address_lo=%x dest_mode=%s redirection=%s dest_id=%u\n",
  129.          address_lo,
  130.          (address_lo & MSI_ADDR_DEST_MODE_LOGICAL) ? "logical" : "physical",
  131.          (address_lo & MSI_ADDR_REDIRECTION_LOWPRI) ? "lowpri" : "cpu",
  132.          (address_lo & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT);
  133.  
  134.   printf("data=%x trigger=%s level=%s delivery_mode=%s vector=%u\n",
  135.          data,
  136.          (data & MSI_DATA_TRIGGER_LEVEL) ? "level" : "edge",
  137.          (data & MSI_DATA_LEVEL_ASSERT) ? "assert" : "deassert",
  138.          (data & MSI_DATA_DELIVERY_LOWPRI) ? "lowpri" : "fixed",
  139.          data & MSI_DATA_VECTOR_MASK);
  140. }
  141.  
  142. int main(int argc, char **argv)
  143. {
  144.         struct pci_access *pacc;
  145.         struct pci_filter filter;       /* Device filter */
  146.         struct pci_dev *p;
  147.         struct device *d;
  148.         char *msg;
  149.         u16 vendor;
  150.         u8 header_type;
  151.         int found = 0;
  152.  
  153.         if (argc < 2) {
  154.                 printf("more args required\n");
  155.                 return -1;
  156.         }
  157.        
  158.         pacc = pci_alloc();
  159.         pci_filter_init(pacc, &filter);
  160.         pci_init(pacc);
  161.         if (msg = pci_filter_parse_slot(&filter, argv[1])) {
  162.                 printf("pci_filter_parse_slot %s\n", msg);
  163.                 return -1;
  164.         }
  165.         pci_scan_bus(pacc);
  166.         for (p = pacc->devices; p; p = p->next) {
  167.                 if (!pci_filter_match(&filter, p))
  168.                         continue;
  169.                 else {
  170.                         found = 1;
  171.                         break;
  172.                 }
  173.         }
  174.  
  175.         if (!found) {
  176.                 printf("device not found\n");
  177.                 return -1;
  178.         }
  179.         d = malloc(sizeof(struct device));
  180.         bzero(d, sizeof(*d));
  181.         d->dev = p;
  182.         if (!pci_read_block(p, 0, d->config, 64)) {
  183.                 printf("Unable to read 64 bytes of configuration space.");
  184.                 return -1;
  185.         }
  186.         d->config_cnt = 64;
  187.         pci_setup_cache(p, d->config, d->config_cnt);
  188.         pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
  189.         int where = get_conf_byte(d, PCI_CAPABILITY_LIST) & ~3;
  190.         while (where)
  191.         {
  192.                 int id, next, cap;
  193.  
  194.                 if (!pci_read_block(d->dev, where, d->config + where, 4)) {
  195.                         printf("Unable to read 4 bytes of configuration space.");
  196.                         return -1;
  197.                 }
  198.                 id = get_conf_byte(d, where + PCI_CAP_LIST_ID);
  199.                 next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
  200.                 cap = get_conf_word(d, where + PCI_CAP_FLAGS);
  201.                 if (id == 0xff)
  202.                 {
  203.                         printf("cap chain broken\n");
  204.                         break;
  205.                 }
  206.                 if (id == PCI_CAP_ID_MSI)
  207.                         show_msi(d, where, cap);
  208.                 where = next;
  209.         }
  210.         pci_cleanup(pacc);
  211.  
  212.         return 0;
  213. }