/ src / core / pci.cc
pci.cc
   1  #include "version.h"
   2  #include "config.h"
   3  #include "pci.h"
   4  #include "device-tree.h"
   5  #include "osutils.h"
   6  #include "options.h"
   7  #include "sysfs.h"
   8  #include <sys/types.h>
   9  #include <sys/stat.h>
  10  #include <fcntl.h>
  11  #include <stdint.h>
  12  #include <unistd.h>
  13  #include <stdio.h>
  14  #include <string.h>
  15  #include <stdlib.h>
  16  #include <dirent.h>
  17  #include <cstring>
  18  
  19  __ID("@(#) $Id$");
  20  
  21  #define PROC_BUS_PCI "/proc/bus/pci"
  22  #define SYS_BUS_PCI "/sys/bus/pci"
  23  #define PCIID_PATH DATADIR"/pci.ids:/usr/share/lshw/pci.ids:/usr/local/share/pci.ids:/usr/share/pci.ids:/etc/pci.ids:/usr/share/hwdata/pci.ids:/usr/share/misc/pci.ids"
  24  
  25  #define PCI_CLASS_REVISION      0x08              /* High 24 bits are class, low 8 revision */
  26  #define PCI_VENDOR_ID           0x00              /* 16 bits */
  27  #define PCI_DEVICE_ID           0x02              /* 16 bits */
  28  #define PCI_COMMAND             0x04              /* 16 bits */
  29  #define PCI_REVISION_ID         0x08              /* Revision ID */
  30  #define PCI_CLASS_PROG          0x09              /* Reg. Level Programming Interface */
  31  #define PCI_CLASS_DEVICE        0x0a              /* Device class */
  32  #define PCI_HEADER_TYPE         0x0e              /* 8 bits */
  33  #define PCI_HEADER_TYPE_NORMAL     0
  34  #define PCI_HEADER_TYPE_BRIDGE     1
  35  #define PCI_HEADER_TYPE_CARDBUS    2
  36  #define PCI_PRIMARY_BUS         0x18              /* Primary bus number */
  37  #define PCI_SECONDARY_BUS       0x19              /* Secondary bus number */
  38  #define PCI_STATUS              0x06              /* 16 bits */
  39  #define PCI_LATENCY_TIMER       0x0d              /* 8 bits */
  40  #define PCI_SEC_LATENCY_TIMER   0x1b              /* Latency timer for secondary interface */
  41  #define PCI_CB_LATENCY_TIMER    0x1b              /* CardBus latency timer */
  42  #define PCI_STATUS_66MHZ        0x20              /* Support 66 Mhz PCI 2.1 bus */
  43  #define PCI_STATUS_CAP_LIST     0x10              /* Support Capability List */
  44  #define PCI_COMMAND_IO          0x01              /* Enable response in I/O space */
  45  #define PCI_COMMAND_MEMORY      0x02              /* Enable response in Memory space */
  46  #define PCI_COMMAND_MASTER      0x04              /* Enable bus mastering */
  47  #define PCI_COMMAND_SPECIAL     0x08              /* Enable response to special cycles */
  48  #define PCI_COMMAND_INVALIDATE  0x10              /* Use memory write and invalidate */
  49  #define PCI_COMMAND_VGA_PALETTE 0x20              /* Enable palette snooping */
  50  #define PCI_COMMAND_PARITY      0x40              /* Enable parity checking */
  51  #define PCI_COMMAND_WAIT        0x80              /* Enable address/data stepping */
  52  #define PCI_COMMAND_SERR        0x100             /* Enable SERR */
  53  #define PCI_COMMAND_FAST_BACK   0x200             /* Enable back-to-back writes */
  54  
  55  #define PCI_MIN_GNT             0x3e              /* 8 bits */
  56  #define PCI_MAX_LAT             0x3f              /* 8 bits */
  57  
  58  #define PCI_CAPABILITY_LIST     0x34              /* Offset of first capability list entry */
  59  #define PCI_CAP_LIST_ID            0              /* Capability ID */
  60  #define PCI_CAP_ID_PM           0x01              /* Power Management */
  61  #define PCI_CAP_ID_AGP          0x02              /* Accelerated Graphics Port */
  62  #define PCI_CAP_ID_VPD          0x03              /* Vital Product Data */
  63  #define PCI_CAP_ID_SLOTID       0x04              /* Slot Identification */
  64  #define PCI_CAP_ID_MSI          0x05              /* Message Signalled Interrupts */
  65  #define PCI_CAP_ID_CHSWP        0x06              /* CompactPCI HotSwap */
  66  #define PCI_CAP_ID_PCIX         0x07              /* PCI-X */
  67  #define PCI_CAP_ID_HT           0x08              /* HyperTransport */
  68  #define PCI_CAP_ID_VNDR         0x09              /* Vendor specific */
  69  #define PCI_CAP_ID_DBG          0x0A              /* Debug port */
  70  #define PCI_CAP_ID_CCRC         0x0B              /* CompactPCI Central Resource Control */
  71  #define PCI_CAP_ID_AGP3         0x0E              /* AGP 8x */
  72  #define PCI_CAP_ID_EXP          0x10              /* PCI Express */
  73  #define PCI_CAP_ID_MSIX         0x11              /* MSI-X */
  74  #define PCI_CAP_LIST_NEXT          1              /* Next capability in the list */
  75  #define PCI_CAP_FLAGS              2              /* Capability defined flags (16 bits) */
  76  #define PCI_CAP_SIZEOF             4
  77  #define PCI_FIND_CAP_TTL          48
  78  
  79  #define PCI_SID_ESR                2              /* Expansion Slot Register */
  80  #define PCI_SID_ESR_NSLOTS      0x1f              /* Number of expansion slots available */
  81  
  82  
  83  /*
  84   * The PCI interface treats multi-function devices as independent
  85   * devices.  The slot/function address of each device is encoded
  86   * in a single byte as follows:
  87   *
  88   *	7:3 = slot
  89   *	2:0 = function
  90   */
  91  #define PCI_DEVFN(slot,func)  ((((slot) & 0x1f) << 3) | ((func) & 0x07))
  92  #define PCI_SLOT(devfn)   (((devfn) >> 3) & 0x1f)
  93  #define PCI_FUNC(devfn)   ((devfn) & 0x07)
  94  
  95  /* Device classes and subclasses */
  96  
  97  #define PCI_CLASS_NOT_DEFINED        0x0000
  98  #define PCI_CLASS_NOT_DEFINED_VGA    0x0001
  99  
 100  #define PCI_BASE_CLASS_STORAGE       0x01
 101  #define PCI_CLASS_STORAGE_SCSI       0x0100
 102  #define PCI_CLASS_STORAGE_IDE        0x0101
 103  #define PCI_CLASS_STORAGE_FLOPPY     0x0102
 104  #define PCI_CLASS_STORAGE_IPI        0x0103
 105  #define PCI_CLASS_STORAGE_RAID       0x0104
 106  #define PCI_CLASS_STORAGE_SATA       0x0106
 107  #define PCI_CLASS_STORAGE_SAS        0x0107
 108  #define PCI_CLASS_STORAGE_NVME       0x0108
 109  #define PCI_CLASS_STORAGE_OTHER      0x0180
 110  
 111  #define PCI_BASE_CLASS_NETWORK       0x02
 112  #define PCI_CLASS_NETWORK_ETHERNET   0x0200
 113  #define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
 114  #define PCI_CLASS_NETWORK_FDDI       0x0202
 115  #define PCI_CLASS_NETWORK_ATM        0x0203
 116  #define PCI_CLASS_NETWORK_OTHER      0x0280
 117  
 118  #define PCI_BASE_CLASS_DISPLAY       0x03
 119  #define PCI_CLASS_DISPLAY_VGA        0x0300
 120  #define PCI_CLASS_DISPLAY_XGA        0x0301
 121  #define PCI_CLASS_DISPLAY_OTHER      0x0380
 122  
 123  #define PCI_BASE_CLASS_MULTIMEDIA    0x04
 124  #define PCI_CLASS_MULTIMEDIA_VIDEO   0x0400
 125  #define PCI_CLASS_MULTIMEDIA_AUDIO   0x0401
 126  #define PCI_CLASS_MULTIMEDIA_OTHER   0x0480
 127  
 128  #define PCI_BASE_CLASS_MEMORY        0x05
 129  #define PCI_CLASS_MEMORY_RAM         0x0500
 130  #define PCI_CLASS_MEMORY_FLASH       0x0501
 131  #define PCI_CLASS_MEMORY_OTHER       0x0580
 132  
 133  #define PCI_BASE_CLASS_BRIDGE        0x06
 134  #define PCI_CLASS_BRIDGE_HOST        0x0600
 135  #define PCI_CLASS_BRIDGE_ISA         0x0601
 136  #define PCI_CLASS_BRIDGE_EISA        0x0602
 137  #define PCI_CLASS_BRIDGE_MC          0x0603
 138  #define PCI_CLASS_BRIDGE_PCI         0x0604
 139  #define PCI_CLASS_BRIDGE_PCMCIA      0x0605
 140  #define PCI_CLASS_BRIDGE_NUBUS       0x0606
 141  #define PCI_CLASS_BRIDGE_CARDBUS     0x0607
 142  #define PCI_CLASS_BRIDGE_OTHER       0x0680
 143  
 144  #define PCI_BASE_CLASS_COMMUNICATION     0x07
 145  #define PCI_CLASS_COMMUNICATION_SERIAL   0x0700
 146  #define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
 147  #define PCI_CLASS_COMMUNICATION_MODEM    0x0703
 148  #define PCI_CLASS_COMMUNICATION_OTHER    0x0780
 149  
 150  #define PCI_BASE_CLASS_SYSTEM        0x08
 151  #define PCI_CLASS_SYSTEM_PIC         0x0800
 152  #define PCI_CLASS_SYSTEM_DMA         0x0801
 153  #define PCI_CLASS_SYSTEM_TIMER       0x0802
 154  #define PCI_CLASS_SYSTEM_RTC         0x0803
 155  #define PCI_CLASS_SYSTEM_OTHER       0x0880
 156  
 157  #define PCI_BASE_CLASS_INPUT         0x09
 158  #define PCI_CLASS_INPUT_KEYBOARD     0x0900
 159  #define PCI_CLASS_INPUT_PEN          0x0901
 160  #define PCI_CLASS_INPUT_MOUSE        0x0902
 161  #define PCI_CLASS_INPUT_OTHER        0x0980
 162  
 163  #define PCI_BASE_CLASS_DOCKING       0x0a
 164  #define PCI_CLASS_DOCKING_GENERIC    0x0a00
 165  #define PCI_CLASS_DOCKING_OTHER      0x0a01
 166  
 167  #define PCI_BASE_CLASS_PROCESSOR     0x0b
 168  #define PCI_CLASS_PROCESSOR_386      0x0b00
 169  #define PCI_CLASS_PROCESSOR_486      0x0b01
 170  #define PCI_CLASS_PROCESSOR_PENTIUM  0x0b02
 171  #define PCI_CLASS_PROCESSOR_ALPHA    0x0b10
 172  #define PCI_CLASS_PROCESSOR_POWERPC  0x0b20
 173  #define PCI_CLASS_PROCESSOR_CO       0x0b40
 174  
 175  #define PCI_BASE_CLASS_SERIAL        0x0c
 176  #define PCI_CLASS_SERIAL_FIREWIRE    0x0c00
 177  #define PCI_CLASS_SERIAL_ACCESS      0x0c01
 178  #define PCI_CLASS_SERIAL_SSA         0x0c02
 179  #define PCI_CLASS_SERIAL_USB         0x0c03
 180  #define PCI_CLASS_SERIAL_FIBER       0x0c04
 181  
 182  #define PCI_BASE_CLASS_ACCELERATOR   0x12
 183  #define PCI_CLASS_ACCELERATOR       0x1200
 184  
 185  #define PCI_CLASS_OTHERS             0xff
 186  
 187  #define PCI_ADDR_MEM_MASK (~(pciaddr_t) 0xf)
 188  #define PCI_BASE_ADDRESS_0              0x10              /* 32 bits */
 189  #define PCI_BASE_ADDRESS_SPACE          0x01              /* 0 = memory, 1 = I/O */
 190  #define PCI_BASE_ADDRESS_SPACE_IO       0x01
 191  #define PCI_BASE_ADDRESS_SPACE_MEMORY   0x00
 192  #define PCI_BASE_ADDRESS_MEM_TYPE_MASK  0x06
 193  #define PCI_BASE_ADDRESS_MEM_TYPE_32    0x00              /* 32 bit address */
 194  #define PCI_BASE_ADDRESS_MEM_TYPE_1M    0x02              /* Below 1M [obsolete] */
 195  #define PCI_BASE_ADDRESS_MEM_TYPE_64    0x04              /* 64 bit address */
 196  #define PCI_BASE_ADDRESS_MEM_PREFETCH   0x08              /* prefetchable? */
 197  #define PCI_BASE_ADDRESS_MEM_MASK       (~0x0fUL)
 198  #define PCI_BASE_ADDRESS_IO_MASK        (~0x03UL)
 199  
 200  #define PCI_SUBSYSTEM_VENDOR_ID      0x2c
 201  #define PCI_SUBSYSTEM_ID             0x2e
 202  
 203  #define PCI_CB_SUBSYSTEM_VENDOR_ID   0x40
 204  #define PCI_CB_SUBSYSTEM_ID          0x42
 205  
 206  bool pcidb_loaded = false;
 207  
 208  typedef unsigned long long pciaddr_t;
 209  typedef enum
 210  {
 211    pcidevice,
 212    pcisubdevice,
 213    pcisubsystem,
 214    pciclass,
 215    pcisubclass,
 216    pcivendor,
 217    pcisubvendor,
 218    pciprogif
 219  }
 220  
 221  
 222  catalog;
 223  
 224  struct pci_dev
 225  {
 226    u_int16_t domain;                               /* PCI domain (host bridge) */
 227    u_int16_t bus;                                  /* Higher byte can select host bridges */
 228    u_int8_t dev, func;                             /* Device and function */
 229  
 230    u_int16_t vendor_id, device_id;                 /* Identity of the device */
 231    unsigned int irq;                               /* IRQ number */
 232    pciaddr_t base_addr[6];                         /* Base addresses */
 233    pciaddr_t size[6];                              /* Region sizes */
 234    pciaddr_t rom_base_addr;                        /* Expansion ROM base address */
 235    pciaddr_t rom_size;                             /* Expansion ROM size */
 236  
 237    u_int8_t config[256];                           /* non-root users can only use first 64 bytes */
 238  };
 239  
 240  struct pci_entry
 241  {
 242    long ids[4];
 243    string description;
 244  
 245    pci_entry(const string & description,
 246      long u1 = -1,
 247      long u2 = -1,
 248      long u3 = -1,
 249      long u4 = -1);
 250  
 251    unsigned int matches(long u1 = -1,
 252      long u2 = -1,
 253      long u3 = -1,
 254      long u4 = -1);
 255  };
 256  
 257  static vector < pci_entry > pci_devices;
 258  static vector < pci_entry > pci_classes;
 259  
 260  pci_entry::pci_entry(const string & d,
 261  long u1,
 262  long u2,
 263  long u3,
 264  long u4)
 265  {
 266    description = d;
 267    ids[0] = u1;
 268    ids[1] = u2;
 269    ids[2] = u3;
 270    ids[3] = u4;
 271  }
 272  
 273  
 274  unsigned int pci_entry::matches(long u1,
 275  long u2,
 276  long u3,
 277  long u4)
 278  {
 279    unsigned int result = 0;
 280  
 281    if (ids[0] == u1)
 282    {
 283      result++;
 284      if (ids[1] == u2)
 285      {
 286        result++;
 287        if (ids[2] == u3)
 288        {
 289          result++;
 290          if (ids[3] == u4)
 291            result++;
 292        }
 293      }
 294    }
 295  
 296    return result;
 297  }
 298  
 299  
 300  static bool find_best_match(vector < pci_entry > &list,
 301  pci_entry & result,
 302  long u1 = -1,
 303  long u2 = -1,
 304  long u3 = -1,
 305  long u4 = -1)
 306  {
 307    int lastmatch = -1;
 308    unsigned int lastscore = 0;
 309  
 310    for (unsigned int i = 0; i < list.size(); i++)
 311    {
 312      unsigned int currentscore = list[i].matches(u1, u2, u3, u4);
 313  
 314      if (currentscore > lastscore)
 315      {
 316        lastscore = currentscore;
 317        lastmatch = i;
 318      }
 319    }
 320  
 321    if (lastmatch >= 0)
 322    {
 323      result = list[lastmatch];
 324      return true;
 325    }
 326  
 327    return false;
 328  }
 329  
 330  
 331  static const char *get_class_name(unsigned int c)
 332  {
 333    switch (c)
 334    {
 335      case PCI_CLASS_NOT_DEFINED_VGA:
 336        return "display";
 337      case PCI_CLASS_STORAGE_SCSI:
 338        return "scsi";
 339      case PCI_CLASS_STORAGE_IDE:
 340        return "ide";
 341      case PCI_CLASS_STORAGE_RAID:
 342        return "raid";
 343      case PCI_CLASS_STORAGE_SATA:
 344        return "sata";
 345      case PCI_CLASS_STORAGE_SAS:
 346        return "sas";
 347      case PCI_CLASS_STORAGE_NVME:
 348        return "nvme";
 349      case PCI_CLASS_BRIDGE_HOST:
 350        return "host";
 351      case PCI_CLASS_BRIDGE_ISA:
 352        return "isa";
 353      case PCI_CLASS_BRIDGE_EISA:
 354        return "eisa";
 355      case PCI_CLASS_BRIDGE_MC:
 356        return "mc";
 357      case PCI_CLASS_BRIDGE_PCI:
 358        return "pci";
 359      case PCI_CLASS_BRIDGE_PCMCIA:
 360        return "pcmcia";
 361      case PCI_CLASS_BRIDGE_NUBUS:
 362        return "nubus";
 363      case PCI_CLASS_BRIDGE_CARDBUS:
 364        return "pcmcia";
 365      case PCI_CLASS_SERIAL_FIREWIRE:
 366        return "firewire";
 367      case PCI_CLASS_SERIAL_USB:
 368        return "usb";
 369      case PCI_CLASS_SERIAL_FIBER:
 370        return "fiber";
 371    }
 372  
 373    switch (c >> 8)
 374    {
 375      case PCI_BASE_CLASS_STORAGE:
 376        return "storage";
 377      case PCI_BASE_CLASS_NETWORK:
 378        return "network";
 379      case PCI_BASE_CLASS_DISPLAY:
 380        return "display";
 381      case PCI_BASE_CLASS_MULTIMEDIA:
 382        return "multimedia";
 383      case PCI_BASE_CLASS_MEMORY:
 384        return "memory";
 385      case PCI_BASE_CLASS_BRIDGE:
 386        return "bridge";
 387      case PCI_BASE_CLASS_COMMUNICATION:
 388        return "communication";
 389      case PCI_BASE_CLASS_SYSTEM:
 390        return "generic";
 391      case PCI_BASE_CLASS_INPUT:
 392        return "input";
 393      case PCI_BASE_CLASS_DOCKING:
 394        return "docking";
 395      case PCI_BASE_CLASS_PROCESSOR:
 396        return "processor";
 397      case PCI_BASE_CLASS_SERIAL:
 398        return "serial";
 399      case PCI_BASE_CLASS_ACCELERATOR:
 400        return "accelerator";
 401    }
 402  
 403    return "generic";
 404  }
 405  
 406  
 407  static bool parse_pcidb(vector < string > &list)
 408  {
 409    long u[4];
 410    string line = "";
 411    catalog current_catalog = pcivendor;
 412    unsigned int level = 0;
 413  
 414    memset(u, 0, sizeof(u));
 415  
 416    for (unsigned int i = 0; i < list.size(); i++)
 417    {
 418      line = hw::strip(list[i]);
 419  
 420  // ignore empty or commented-out lines
 421      if (line.length() == 0 || line[0] == '#')
 422        continue;
 423  
 424      level = 0;
 425      while ((level < list[i].length()) && (list[i][level] == '\t'))
 426        level++;
 427  
 428      switch (level)
 429      {
 430        case 0:
 431          if ((line[0] == 'C') && (line.length() > 1) && (line[1] == ' '))
 432          {
 433            current_catalog = pciclass;
 434            line = line.substr(2);                  // get rid of 'C '
 435  
 436            if ((line.length() < 3) || (line[2] != ' '))
 437              return false;
 438            if (sscanf(line.c_str(), "%lx", &u[0]) != 1)
 439              return false;
 440            line = line.substr(3);
 441            line = hw::strip(line);
 442          }
 443          else
 444          {
 445            current_catalog = pcivendor;
 446  
 447            if ((line.length() < 5) || (line[4] != ' '))
 448              return false;
 449            if (sscanf(line.c_str(), "%lx", &u[0]) != 1)
 450              return false;
 451            line = line.substr(5);
 452            line = hw::strip(line);
 453          }
 454          u[1] = u[2] = u[3] = -1;
 455          break;
 456        case 1:
 457          if ((current_catalog == pciclass) || (current_catalog == pcisubclass)
 458            || (current_catalog == pciprogif))
 459          {
 460            current_catalog = pcisubclass;
 461  
 462            if ((line.length() < 3) || (line[2] != ' '))
 463              return false;
 464            if (sscanf(line.c_str(), "%lx", &u[1]) != 1)
 465              return false;
 466            line = line.substr(3);
 467            line = hw::strip(line);
 468          }
 469          else
 470          {
 471            current_catalog = pcidevice;
 472  
 473            if ((line.length() < 5) || (line[4] != ' '))
 474              return false;
 475            if (sscanf(line.c_str(), "%lx", &u[1]) != 1)
 476              return false;
 477            line = line.substr(5);
 478            line = hw::strip(line);
 479          }
 480          u[2] = u[3] = -1;
 481          break;
 482        case 2:
 483          if ((current_catalog != pcidevice) && (current_catalog != pcisubvendor)
 484            && (current_catalog != pcisubclass)
 485            && (current_catalog != pciprogif))
 486            return false;
 487          if ((current_catalog == pcisubclass) || (current_catalog == pciprogif))
 488          {
 489            current_catalog = pciprogif;
 490            if ((line.length() < 3) || (line[2] != ' '))
 491              return false;
 492            if (sscanf(line.c_str(), "%lx", &u[2]) != 1)
 493              return false;
 494            u[3] = -1;
 495            line = line.substr(2);
 496            line = hw::strip(line);
 497          }
 498          else
 499          {
 500            current_catalog = pcisubvendor;
 501            if ((line.length() < 10) || (line[4] != ' ') || (line[9] != ' '))
 502              return false;
 503            if (sscanf(line.c_str(), "%lx%lx", &u[2], &u[3]) != 2)
 504              return false;
 505            line = line.substr(9);
 506            line = hw::strip(line);
 507          }
 508          break;
 509        default:
 510          return false;
 511      }
 512  
 513  //printf("%04x %04x %04x %04x %s\n", u[0], u[1], u[2], u[3], line.c_str());
 514      if ((current_catalog == pciclass) ||
 515        (current_catalog == pcisubclass) || (current_catalog == pciprogif))
 516      {
 517        pci_classes.push_back(pci_entry(line, u[0], u[1], u[2], u[3]));
 518      }
 519      else
 520      {
 521        pci_devices.push_back(pci_entry(line, u[0], u[1], u[2], u[3]));
 522      }
 523    }
 524    return true;
 525  }
 526  
 527  
 528  static bool load_pcidb()
 529  {
 530    vector < string > lines;
 531    vector < string > filenames;
 532  
 533    splitlines(PCIID_PATH, filenames, ':');
 534    for (int i = filenames.size() - 1; i >= 0; i--)
 535    {
 536      lines.clear();
 537      if (loadfile(filenames[i], lines) && (lines.size() > 0))
 538        parse_pcidb(lines);
 539    }
 540  
 541    return (pci_devices.size() > 0);
 542  }
 543  
 544  
 545  static string get_class_description(long c,
 546  long pi = -1)
 547  {
 548    pci_entry result("");
 549  
 550    if (find_best_match(pci_classes, result, c >> 8, c & 0xff, pi))
 551      return result.description;
 552    else
 553      return "";
 554  }
 555  
 556  
 557  static string get_device_description(long u1,
 558  long u2 = -1,
 559  long u3 = -1,
 560  long u4 = -1)
 561  {
 562    pci_entry result("");
 563  
 564    if (find_best_match(pci_devices, result, u1, u2, u3, u4))
 565      return result.description;
 566    else
 567      return "";
 568  }
 569  
 570  
 571  static u_int32_t get_conf_long(struct pci_dev d,
 572  unsigned int pos)
 573  {
 574    if (pos + 3 >= sizeof(d.config))
 575      return 0;
 576  
 577    return d.config[pos] | (d.config[pos + 1] << 8) |
 578      (d.config[pos + 2] << 16) | (d.config[pos + 3] << 24);
 579  }
 580  
 581  
 582  static u_int16_t get_conf_word(struct pci_dev d,
 583  unsigned int pos)
 584  {
 585    if (pos + 1 >= sizeof(d.config))
 586      return 0;
 587  
 588    return d.config[pos] | (d.config[pos + 1] << 8);
 589  }
 590  
 591  
 592  static u_int8_t get_conf_byte(struct pci_dev d,
 593  unsigned int pos)
 594  {
 595    if (pos >= sizeof(d.config))
 596      return 0;
 597  
 598    return d.config[pos];
 599  }
 600  
 601  
 602  static string pci_bushandle(u_int8_t bus, u_int16_t domain = 0)
 603  {
 604    char buffer[20];
 605  
 606    if(domain == (u_int16_t)(-1))
 607      snprintf(buffer, sizeof(buffer), "%02x", bus);
 608    else
 609      snprintf(buffer, sizeof(buffer), "%04x:%02x", domain, bus);
 610  
 611    return "PCIBUS:" + string(buffer);
 612  }
 613  
 614  
 615  static string pci_handle(u_int16_t bus,
 616  u_int8_t dev,
 617  u_int8_t fct,
 618  u_int16_t domain = 0)
 619  {
 620    char buffer[30];
 621  
 622    if(domain == (u_int16_t)(-1))
 623      snprintf(buffer, sizeof(buffer), "PCI:%02x:%02x.%x", bus, dev, fct);
 624    else
 625      snprintf(buffer, sizeof(buffer), "PCI:%04x:%02x:%02x.%x", domain, bus, dev, fct);
 626  
 627    return string(buffer);
 628  }
 629  
 630  
 631  static bool scan_resources(hwNode & n,
 632  struct pci_dev &d)
 633  {
 634    u_int16_t cmd = get_conf_word(d, PCI_COMMAND);
 635  
 636    n.setWidth(32);
 637  
 638    for (int i = 0; i < 6; i++)
 639    {
 640      u_int32_t flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4 * i);
 641      u_int32_t pos = d.base_addr[i];
 642      u_int32_t len = d.size[i];
 643  
 644      if (flg == 0xffffffff)
 645        flg = 0;
 646  
 647      if (!pos && !flg && !len)
 648        continue;
 649  
 650      if (pos && !flg)                              /* Reported by the OS, but not by the device */
 651      {
 652  //printf("[virtual] ");
 653        flg = pos;
 654      }
 655      if (flg & PCI_BASE_ADDRESS_SPACE_IO)
 656      {
 657        u_int32_t a = pos & PCI_BASE_ADDRESS_IO_MASK;
 658        if ((a != 0) && (cmd & PCI_COMMAND_IO) != 0)
 659          n.addResource(hw::resource::ioport(a, a + len - 1));
 660      }
 661      else                                          // resource is memory
 662      {
 663        int t = flg & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
 664        u_int64_t a = pos & PCI_ADDR_MEM_MASK;
 665        u_int64_t z = 0;
 666  
 667        if (t == PCI_BASE_ADDRESS_MEM_TYPE_64)
 668        {
 669          n.setWidth(64);
 670          if (i < 5)
 671          {
 672            i++;
 673            z = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4 * i);
 674            a += z << 4;
 675          }
 676        }
 677        if (a)
 678          n.addResource(hw::resource::iomem(a, a + len - 1));
 679      }
 680    }
 681  
 682    return true;
 683  }
 684  
 685  static bool scan_capabilities(hwNode & n, struct pci_dev &d)
 686  {
 687    unsigned int where = get_conf_byte(d, PCI_CAPABILITY_LIST) & ~3;
 688    string buffer;
 689    unsigned int ttl = PCI_FIND_CAP_TTL;
 690  
 691    while(where && ttl--)
 692    {
 693      unsigned int id, next, cap;
 694  
 695      id = get_conf_byte(d, where + PCI_CAP_LIST_ID);
 696      next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
 697      cap = get_conf_word(d, where + PCI_CAP_FLAGS);
 698  
 699      if(!id || id == 0xff)
 700        return false;
 701  
 702      switch(id)
 703      {
 704        case PCI_CAP_ID_PM:
 705          n.addCapability("pm", "Power Management");
 706          break;
 707        case PCI_CAP_ID_AGP:
 708          n.addCapability("agp", "AGP");
 709          buffer = hw::asString((cap >> 4) & 0x0f) + "." + hw::asString(cap & 0x0f);
 710          n.addCapability("agp-"+buffer, "AGP "+buffer);
 711          break;
 712        case PCI_CAP_ID_VPD:
 713          n.addCapability("vpd", "Vital Product Data");
 714          break;
 715        case PCI_CAP_ID_SLOTID:
 716          n.addCapability("slotid", "Slot Identification");
 717          n.setSlot(hw::asString(cap & PCI_SID_ESR_NSLOTS)+", chassis "+hw::asString(cap>>8));
 718          break;
 719        case PCI_CAP_ID_MSI:
 720          n.addCapability("msi", "Message Signalled Interrupts");
 721          break;
 722        case PCI_CAP_ID_CHSWP:
 723          n.addCapability("hotswap", "Hot-swap");
 724          break;
 725        case PCI_CAP_ID_PCIX:
 726          n.addCapability("pcix", "PCI-X");
 727          break;
 728        case PCI_CAP_ID_HT:
 729          n.addCapability("ht", "HyperTransport");
 730          break;
 731        case PCI_CAP_ID_DBG:
 732          n.addCapability("debug", "Debug port");
 733          break;
 734        case PCI_CAP_ID_CCRC:
 735          n.addCapability("ccrc", "CompactPCI Central Resource Control");
 736          break;
 737        case PCI_CAP_ID_AGP3:
 738          n.addCapability("agp8x", "AGP 8x");
 739          break;
 740        case PCI_CAP_ID_EXP:
 741          n.addCapability("pciexpress", _("PCI Express"));
 742          break;
 743        case PCI_CAP_ID_MSIX:
 744          n.addCapability("msix", "MSI-X");
 745          break;
 746      }
 747  
 748      where = next;
 749    }
 750  
 751    return true;
 752  }
 753  
 754  
 755  static void addHints(hwNode & n,
 756  long _vendor,
 757  long _device,
 758  long _subvendor,
 759  long _subdevice,
 760  long _class)
 761  {
 762    n.addHint("pci.vendor", _vendor);
 763    n.addHint("pci.device", _device);
 764    if(_subvendor && (_subvendor != 0xffff))
 765    {
 766      n.addHint("pci.subvendor", _subvendor);
 767      n.addHint("pci.subdevice", _subdevice);
 768    }
 769    n.addHint("pci.class", _class);
 770  }
 771  
 772  static hwNode *scan_pci_dev(struct pci_dev &d, hwNode & n)
 773  {
 774    hwNode *result = NULL;
 775    hwNode *core = n.getChild("core");
 776    if (!core)
 777    {
 778      n.addChild(hwNode("core", hw::bus));
 779      core = n.getChild("core");
 780    }
 781  
 782    if(!pcidb_loaded)
 783      pcidb_loaded = load_pcidb();
 784  
 785        u_int16_t tmp_vendor_id = get_conf_word(d, PCI_VENDOR_ID);
 786        u_int16_t tmp_device_id = get_conf_word(d, PCI_DEVICE_ID);
 787        if ((tmp_vendor_id & tmp_device_id) != 0xffff) {
 788          d.vendor_id = tmp_vendor_id;
 789          d.device_id = tmp_device_id;
 790        }
 791        u_int16_t dclass = get_conf_word(d, PCI_CLASS_DEVICE);
 792        u_int16_t cmd = get_conf_word(d, PCI_COMMAND);
 793        u_int16_t status = get_conf_word(d, PCI_STATUS);
 794        u_int8_t latency = get_conf_byte(d, PCI_LATENCY_TIMER);
 795        u_int8_t min_gnt = get_conf_byte(d, PCI_MIN_GNT);
 796        u_int8_t max_lat = get_conf_byte(d, PCI_MAX_LAT);
 797        u_int8_t progif = get_conf_byte(d, PCI_CLASS_PROG);
 798        u_int8_t rev = get_conf_byte(d, PCI_REVISION_ID);
 799        u_int8_t htype = get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f;
 800        u_int16_t subsys_v = 0, subsys_d = 0;
 801  
 802        char revision[10];
 803        snprintf(revision, sizeof(revision), "%02x", rev);
 804        string moredescription = get_class_description(dclass, progif);
 805  
 806        switch (htype)
 807        {
 808          case PCI_HEADER_TYPE_NORMAL:
 809            subsys_v = get_conf_word(d, PCI_SUBSYSTEM_VENDOR_ID);
 810            subsys_d = get_conf_word(d, PCI_SUBSYSTEM_ID);
 811            break;
 812          case PCI_HEADER_TYPE_BRIDGE:
 813            subsys_v = subsys_d = 0;
 814            latency = get_conf_byte(d, PCI_SEC_LATENCY_TIMER);
 815            break;
 816          case PCI_HEADER_TYPE_CARDBUS:
 817            subsys_v = get_conf_word(d, PCI_CB_SUBSYSTEM_VENDOR_ID);
 818            subsys_d = get_conf_word(d, PCI_CB_SUBSYSTEM_ID);
 819            latency = get_conf_byte(d, PCI_CB_LATENCY_TIMER);
 820            break;
 821        }
 822  
 823        if (dclass == PCI_CLASS_BRIDGE_HOST)
 824        {
 825          hwNode host("pci",
 826            hw::bridge);
 827  
 828          host.setDescription(get_class_description(dclass, progif));
 829          host.setVendor(get_device_description(d.vendor_id)+(enabled("output:numeric")?" ["+tohex(d.vendor_id)+"]":""));
 830          host.setProduct(get_device_description(d.vendor_id, d.device_id)+(enabled("output:numeric")?" ["+tohex(d.vendor_id)+":"+tohex(d.device_id)+"]":""));
 831          if (subsys_v != 0 || subsys_d != 0)
 832          {
 833            host.setSubVendor(get_device_description(subsys_v)+(enabled("output:numeric")?" ["+tohex(subsys_v)+"]":""));
 834            host.setSubProduct(get_device_description(subsys_v, subsys_d)+(enabled("output:numeric")?" ["+tohex(subsys_v)+":"+tohex(subsys_d)+"]":""));
 835          }
 836          host.setHandle(pci_bushandle(d.bus, d.domain));
 837          host.setVersion(revision);
 838          addHints(host, d.vendor_id, d.device_id, subsys_v, subsys_d, dclass);
 839          host.claim();
 840          if(latency)
 841            host.setConfig("latency", latency);
 842          if (d.size[0] > 0)
 843            host.setPhysId(0x100 + d.domain);
 844  
 845          if (moredescription != "" && moredescription != host.getDescription())
 846          {
 847            host.addCapability(moredescription);
 848            host.setDescription(host.getDescription() + " (" +
 849              moredescription + ")");
 850          }
 851  
 852          if (status & PCI_STATUS_66MHZ)
 853            host.setClock(66000000UL);              // 66MHz
 854          else
 855            host.setClock(33000000UL);              // 33MHz
 856  
 857          scan_resources(host, d);
 858  
 859          if (core)
 860            result = core->addChild(host);
 861          else
 862            result = n.addChild(host);
 863        }
 864        else
 865        {
 866          hw::hwClass deviceclass = hw::generic;
 867          string devicename = "generic";
 868          string deviceicon = "";
 869  
 870          switch (dclass >> 8)
 871          {
 872            case PCI_BASE_CLASS_STORAGE:
 873              deviceclass = hw::storage;
 874              deviceicon = "disc";
 875              if(dclass == PCI_CLASS_STORAGE_SCSI)
 876                deviceicon = "scsi";
 877              if(dclass == PCI_CLASS_STORAGE_RAID)
 878                deviceicon = "raid";
 879              break;
 880            case PCI_BASE_CLASS_NETWORK:
 881              deviceclass = hw::network;
 882              deviceicon = "network";
 883              break;
 884            case PCI_BASE_CLASS_MEMORY:
 885              deviceclass = hw::memory;
 886              deviceicon = "memory";
 887              break;
 888            case PCI_BASE_CLASS_BRIDGE:
 889              deviceclass = hw::bridge;
 890              break;
 891            case PCI_BASE_CLASS_MULTIMEDIA:
 892              deviceclass = hw::multimedia;
 893              if(dclass == PCI_CLASS_MULTIMEDIA_AUDIO)
 894                deviceicon = "audio";
 895              break;
 896            case PCI_BASE_CLASS_DISPLAY:
 897              deviceclass = hw::display;
 898              deviceicon = "display";
 899              break;
 900            case PCI_BASE_CLASS_COMMUNICATION:
 901              deviceclass = hw::communication;
 902              if(dclass == PCI_CLASS_COMMUNICATION_SERIAL)
 903                deviceicon = "serial";
 904              if(dclass == PCI_CLASS_COMMUNICATION_PARALLEL)
 905                deviceicon = "parallel";
 906              if(dclass == PCI_CLASS_COMMUNICATION_MODEM)
 907                deviceicon = "modem";
 908              break;
 909            case PCI_BASE_CLASS_SYSTEM:
 910              deviceclass = hw::generic;
 911              break;
 912            case PCI_BASE_CLASS_INPUT:
 913              deviceclass = hw::input;
 914              break;
 915           case PCI_BASE_CLASS_ACCELERATOR:
 916                 deviceclass = hw::accelerator;
 917                 deviceicon = "accelerator";
 918                 break;
 919            case PCI_BASE_CLASS_PROCESSOR:
 920              deviceclass = hw::processor;
 921              break;
 922            case PCI_BASE_CLASS_SERIAL:
 923              deviceclass = hw::bus;
 924              if(dclass == PCI_CLASS_SERIAL_USB)
 925                deviceicon = "usb";
 926              if(dclass == PCI_CLASS_SERIAL_FIREWIRE)
 927                deviceicon = "firewire";
 928              break;
 929          }
 930  
 931          devicename = get_class_name(dclass);
 932          hwNode *device = new hwNode(devicename, deviceclass);
 933  
 934          if (device)
 935          {
 936            if(deviceicon != "") device->addHint("icon", deviceicon);
 937            addHints(*device, d.vendor_id, d.device_id, subsys_v, subsys_d, dclass);
 938  
 939            if (deviceclass == hw::bridge || deviceclass == hw::storage)
 940              device->addCapability(devicename);
 941  
 942            if(device->isCapable("isa") ||
 943              device->isCapable("pci") ||
 944              device->isCapable("agp"))
 945              device->claim();
 946  
 947            scan_resources(*device, d);
 948            scan_capabilities(*device, d);
 949  
 950            if (deviceclass == hw::display)
 951              for (int j = 0; j < 6; j++)
 952                if ((d.size[j] != 0xffffffff)
 953              && (d.size[j] > device->getSize()))
 954                  device->setSize(d.size[j]);
 955  
 956            if (dclass == PCI_CLASS_BRIDGE_PCI)
 957            {
 958              device->setHandle(pci_bushandle(get_conf_byte(d, PCI_SECONDARY_BUS), d.domain));
 959              device->claim();
 960            }
 961            else
 962            {
 963              char irq[10];
 964  
 965              snprintf(irq, sizeof(irq), "%d", d.irq);
 966              device->setHandle(pci_handle(d.bus, d.dev, d.func, d.domain));
 967              device->setConfig("latency", latency);
 968              if(max_lat)
 969                device->setConfig("maxlatency", max_lat);
 970              if(min_gnt)
 971                device->setConfig("mingnt", min_gnt);
 972              if (d.irq != 0)
 973              {
 974  //device->setConfig("irq", irq);
 975                device->addResource(hw::resource::irq(d.irq));
 976              }
 977            }
 978            device->setDescription(get_class_description(dclass));
 979  
 980            if (dclass == PCI_CLASS_STORAGE_IDE)
 981            {
 982              // IDE programming interface names are really long and awkward,
 983              // so don't add them as capabilities
 984              if (progif == 0x00 || progif == 0x80)
 985                device->addCapability("isa_compat_mode", "ISA compatibility mode");
 986              else if (progif == 0x05 || progif == 0x85)
 987                device->addCapability("pci_native_mode", "PCI native mode");
 988              else if (progif == 0x0a || progif == 0x0f || progif == 0x8a || progif == 0x8f)
 989              {
 990                device->addCapability("isa_compat_mode", "ISA compatibility mode");
 991                device->addCapability("pci_native_mode", "PCI native mode");
 992              }
 993            }
 994            else if (moredescription != ""
 995              && moredescription != device->getDescription())
 996            {
 997              device->addCapability(moredescription);
 998            }
 999            device->setVendor(get_device_description(d.vendor_id)+(enabled("output:numeric")?" ["+tohex(d.vendor_id)+"]":""));
1000            device->setVersion(revision);
1001            device->setProduct(get_device_description(d.vendor_id, d.device_id)+(enabled("output:numeric")?" ["+tohex(d.vendor_id)+":"+tohex(d.device_id)+"]":""));
1002            if (subsys_v != 0 || subsys_d != 0)
1003            {
1004              device->setSubVendor(get_device_description(subsys_v)+(enabled("output:numeric")?" ["+tohex(subsys_v)+"]":""));
1005              device->setSubProduct(get_device_description(subsys_v, subsys_d)+(enabled("output:numeric")?" ["+tohex(subsys_v)+":"+tohex(subsys_d)+"]":""));
1006            }
1007            if (cmd & PCI_COMMAND_MASTER)
1008              device->addCapability("bus master", "bus mastering");
1009            if (cmd & PCI_COMMAND_VGA_PALETTE)
1010              device->addCapability("VGA palette", "VGA palette");
1011            if (status & PCI_STATUS_CAP_LIST)
1012              device->addCapability("cap list", "PCI capabilities listing");
1013            if (status & PCI_STATUS_66MHZ)
1014              device->setClock(66000000UL);         // 66MHz
1015            else
1016              device->setClock(33000000UL);         // 33MHz
1017  
1018            device->setPhysId(d.dev, d.func);
1019  
1020            hwNode *bus = NULL;
1021  
1022            bus = n.findChildByHandle(pci_bushandle(d.bus, d.domain));
1023  
1024            device->describeCapability("vga", "VGA graphical framebuffer");
1025            device->describeCapability("pcmcia", "PC-Card (PCMCIA)");
1026            device->describeCapability("generic", "Generic interface");
1027            device->describeCapability("ohci", "Open Host Controller Interface");
1028            device->describeCapability("uhci", "Universal Host Controller Interface (USB1)");
1029            device->describeCapability("ehci", "Enhanced Host Controller Interface (USB2)");
1030            if (bus)
1031              result = bus->addChild(*device);
1032            else
1033            {
1034              if (core)
1035                result = core->addChild(*device);
1036              else
1037                result = n.addChild(*device);
1038            }
1039            delete device;
1040  
1041          }
1042        }
1043    return result;
1044  }
1045  
1046  bool scan_pci_legacy(hwNode & n)
1047  {
1048    FILE *f;
1049    hwNode *core = n.getChild("core");
1050    if (!core)
1051    {
1052      n.addChild(hwNode("core", hw::bus));
1053      core = n.getChild("core");
1054    }
1055  
1056    if(!pcidb_loaded)
1057      pcidb_loaded = load_pcidb();
1058  
1059    f = fopen(PROC_BUS_PCI "/devices", "r");
1060    if (f)
1061    {
1062      char buf[512];
1063  
1064      while (fgets(buf, sizeof(buf) - 1, f))
1065      {
1066        unsigned int dfn, vend, cnt;
1067        struct pci_dev d;
1068        int fd = -1;
1069        string devicepath = "";
1070        char devicename[20];
1071        char businfo[20];
1072        char driver[50];
1073        hwNode *device = NULL;
1074  
1075        memset(&d, 0, sizeof(d));
1076        memset(driver, 0, sizeof(driver));
1077        cnt = sscanf(buf,
1078          "%x %x %x %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %[ -z]s",
1079          &dfn,
1080          &vend,
1081          &d.irq,
1082          &d.base_addr[0],
1083          &d.base_addr[1],
1084          &d.base_addr[2],
1085          &d.base_addr[3],
1086          &d.base_addr[4],
1087          &d.base_addr[5],
1088          &d.rom_base_addr,
1089          &d.size[0],
1090          &d.size[1],
1091          &d.size[2],
1092          &d.size[3], &d.size[4], &d.size[5], &d.rom_size, driver);
1093  
1094        if (cnt != 9 && cnt != 10 && cnt != 17 && cnt != 18)
1095          break;
1096  
1097        d.bus = dfn >> 8;
1098        d.dev = PCI_SLOT(dfn & 0xff);
1099        d.func = PCI_FUNC(dfn & 0xff);
1100        d.vendor_id = vend >> 16;
1101        d.device_id = vend & 0xffff;
1102  
1103        snprintf(devicename, sizeof(devicename), "%02x/%02x.%x", d.bus, d.dev,
1104          d.func);
1105        devicepath = string(PROC_BUS_PCI) + "/" + string(devicename);
1106        snprintf(businfo, sizeof(businfo), "%02x:%02x.%x", d.bus, d.dev,
1107          d.func);
1108  
1109        fd = open(devicepath.c_str(), O_RDONLY);
1110        if (fd >= 0)
1111        {
1112          if(read(fd, d.config, sizeof(d.config)) != sizeof(d.config))
1113            memset(&d.config, 0, sizeof(d.config));
1114          close(fd);
1115        }
1116  
1117        device = scan_pci_dev(d, n);
1118        if(device)
1119        {
1120          device->setBusInfo(businfo);
1121        }
1122  
1123      }
1124      fclose(f);
1125    }
1126  
1127    return false;
1128  }
1129  
1130  bool scan_pci(hwNode & n)
1131  {
1132    bool result = false;
1133    dirent **devices = NULL;
1134    int count = 0;
1135    hwNode *core = n.getChild("core");
1136  
1137    if (!core)
1138    {
1139      n.addChild(hwNode("core", hw::bus));
1140      core = n.getChild("core");
1141    }
1142  
1143    pcidb_loaded = load_pcidb();
1144  
1145    if(!pushd(SYS_BUS_PCI"/devices"))
1146      return false;
1147    count = scandir(".", &devices, selectlink, alphasort);
1148    if(count>=0)
1149    {
1150      int i = 0;
1151      for(i=0; i<count; i++)
1152      if(matches(devices[i]->d_name, "^[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+\\.[[:xdigit:]]+$"))
1153      {
1154        string devicepath = string(devices[i]->d_name)+"/config";
1155        sysfs::entry device_entry = sysfs::entry::byBus("pci", devices[i]->d_name);
1156        struct pci_dev d;
1157        memset(&d, 0, sizeof(d));
1158        int fd = open(devicepath.c_str(), O_RDONLY);
1159        if (fd >= 0)
1160        {
1161          if(read(fd, d.config, 64) == 64)
1162          {
1163            if(read(fd, d.config+64, sizeof(d.config)-64) != sizeof(d.config)-64)
1164              memset(d.config+64, 0, sizeof(d.config)-64);
1165          }
1166          close(fd);
1167        }
1168  
1169        sscanf(devices[i]->d_name, "%hx:%hx:%hhx.%hhx", &d.domain, &d.bus, &d.dev, &d.func);
1170        sscanf(device_entry.vendor().c_str(), "%hx", &d.vendor_id);
1171        sscanf(device_entry.device().c_str(), "%hx", &d.device_id);
1172        hwNode *device = scan_pci_dev(d, n);
1173  
1174        if(device)
1175        {
1176          string resourcename = string(devices[i]->d_name)+"/resource";
1177  
1178          device->setBusInfo(devices[i]->d_name);
1179          if(exists(string(devices[i]->d_name)+"/driver"))
1180          {
1181            string drivername = readlink(string(devices[i]->d_name)+"/driver");
1182            string modulename = readlink(string(devices[i]->d_name)+"/driver/module");
1183  
1184            device->setConfig("driver", shortname(drivername));
1185            if(exists(modulename))
1186              device->setConfig("module", shortname(modulename));
1187  
1188            if(exists(string(devices[i]->d_name)+"/rom"))
1189            {
1190              device->addCapability("rom", "extension ROM");
1191            }
1192  
1193            if(exists(string(devices[i]->d_name)+"/irq"))
1194            {
1195              long irq = get_number(string(devices[i]->d_name)+"/irq", -1);
1196              if(irq>=0)
1197                device->addResource(hw::resource::irq(irq));
1198            }
1199            device->claim();
1200          }
1201  
1202          device->setModalias(device_entry.modalias());
1203  
1204          if(exists(resourcename))
1205          {
1206              FILE*resource = fopen(resourcename.c_str(), "r");
1207  
1208              if(resource)
1209              {
1210                while(!feof(resource))
1211                {
1212                  unsigned long long start, end, flags;
1213  
1214                  start = end = flags = 0;
1215  
1216                  if(fscanf(resource, "%llx %llx %llx", &start, &end, &flags) != 3)
1217                    break;
1218  
1219                  if(flags & 0x101)
1220                    device->addResource(hw::resource::ioport(start, end));
1221                  else
1222                  if(flags & 0x100)
1223                    device->addResource(hw::resource::iomem(start, end));
1224                  else
1225                  if(flags & 0x200)
1226                    device->addResource(hw::resource::mem(start, end, flags & 0x1000));
1227                }
1228                fclose(resource);
1229              }
1230          }
1231  	add_device_tree_info(*device, devices[i]->d_name);
1232  
1233          result = true;
1234        }
1235  
1236        free(devices[i]);
1237      }
1238  
1239      free(devices);
1240    }
1241    popd();
1242    return result;
1243  }