pci: revamp the PCI system to have a hierarchial format
authorH. Peter Anvin <hpa@zytor.com>
Tue, 12 Aug 2008 18:30:19 +0000 (11:30 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 12 Aug 2008 18:30:19 +0000 (11:30 -0700)
Create the concept of a PCI domain, as a hierarcy of busses, devices
and functions.  This avoids large static-sized arrays and allows for
geographical addressing of devices.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
com32/include/sys/pci.h
com32/lib/pci/scan.c
com32/modules/ethersel.c
com32/modules/pcitest.c

index 120c03d..1de095a 100644 (file)
 typedef uint32_t pciaddr_t;
 
 /* a structure for extended pci information */
+/* XXX: use pointers for these? */
 struct pci_dev_info {
-       char     vendor_name[255];
-       char     product_name[255];
-       char     linux_kernel_module[64];
+  char vendor_name[256];
+  char product_name[256];
+  char linux_kernel_module[64];
 };
 
-/* a struct to represent a pci device */
+/* PCI device (really, function) */
 struct pci_device {
-       pciaddr_t addr;
-       uint16_t vendor;
-       uint16_t product;
-       uint16_t sub_vendor;
-       uint16_t sub_product;
-       uint8_t  revision;
-       struct pci_dev_info *pci_dev_info;
+  union {
+    struct {
+      uint16_t vendor;
+      uint16_t product;
+      uint16_t sub_vendor;
+      uint16_t sub_product;
+      uint8_t  revision;
+      uint8_t  class[3];
+    };
+    struct {
+      uint32_t vid_did;
+      uint32_t svid_sdid;
+      uint32_t rid_class;
+    };
+  };
+  struct pci_dev_info *dev_info;
+  struct pci_device *next;
 };
 
-struct pci_bus {
-       uint16_t id;
-       struct pci_device *pci_device[MAX_PCI_DEVICES * MAX_PCI_FUNC];
-       uint32_t pci_device_count;
+/* PCI device ("slot") structure */
+struct pci_slot {
+  struct pci_device *func[MAX_PCI_FUNC];
 };
 
-struct pci_device_list {
-       struct pci_device pci_device[MAX_PCI_BUSES * MAX_PCI_DEVICES * MAX_PCI_FUNC];
-       uint32_t count;
+/* PCI bus structure */
+struct pci_bus {
+  struct pci_slot *slot[MAX_PCI_DEVICES];
 };
 
-struct pci_bus_list {
-       struct pci_bus pci_bus[MAX_PCI_BUSES];
-       uint32_t count;
+/* PCI domain structure */
+struct pci_domain {
+  struct pci_bus *bus[MAX_PCI_BUSES];
 };
 
+/* Iterate over a PCI domain */
+#define for_each_pci_func(funcp, domain) \
+  for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \
+    if ((domain)->bus[__pci_bus]) \
+      for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \
+       if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \
+         for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \
+           if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \
+                func[__pci_func]))
+
 struct match {
   struct match *next;
   uint32_t did;
@@ -93,8 +113,11 @@ void pci_writeb(uint8_t, pciaddr_t);
 void pci_writew(uint16_t, pciaddr_t);
 void pci_writel(uint32_t, pciaddr_t);
 
-extern int pci_scan(struct pci_bus_list *pci_bus_list, struct pci_device_list *pci_device_list);
-extern struct match * find_pci_device(struct pci_device_list *pci_device_list, struct match *list);
-extern void get_name_from_pci_ids(struct pci_device_list *pci_device_list);
-extern void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list);
+struct pci_domain *pci_scan(void);
+void free_pci_domain(struct pci_domain *domain);
+struct match * find_pci_device(const struct pci_domain *pci_domain,
+                              struct match *list);
+int get_name_from_pci_ids(struct pci_domain *pci_domain);
+int get_module_name_from_pci_ids(struct pci_domain *pci_domain);
+
 #endif /* _SYS_PCI_H */
index 1c3f526..2f6cfe8 100644 (file)
@@ -65,7 +65,7 @@ static void remove_eol(char *string)
  for(i = 0; i < j; i++) if(string[i] == '\n') string[i] = 0;
 }
 
-/* converting a hexa string into its numerical value*/
+/* converting a hexa string into its numerical value */
 static int hex_to_int(char *hexa)
 {
   return strtoul(hexa, NULL, 16);
@@ -73,7 +73,7 @@ static int hex_to_int(char *hexa)
 
 /* Try to match any pci device to the appropriate kernel module */
 /* it uses the modules.pcimap from the boot device*/
-void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
+int get_module_name_from_pci_ids(struct pci_domain *domain)
 {
   char line[MAX_LINE];
   char module_name[21]; // the module name field is 21 char long
@@ -83,29 +83,24 @@ void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
   char sub_vendor_id[16];
   char sub_product_id[16];
   FILE *f;
-  int pci_dev;
+  struct pci_device *dev;
 
   /* Intializing the linux_kernel_module for each pci device to "unknow" */
-  /* adding a pci_dev_info member if needed*/
-  for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-    struct pci_device *pci_device = &(pci_device_list->pci_device[pci_dev]);
-
-    /* initialize the pci_dev_info structure if it doesn't exist yet. */
-    if (! pci_device->pci_dev_info) {
-      pci_device->pci_dev_info = calloc(1,sizeof *pci_device->pci_dev_info);
-
-      if (!pci_device->pci_dev_info) {
-       printf("Can't allocate memory\n");
-       return;
-      }
+  /* adding a dev_info member if needed*/
+  for_each_pci_func(dev, domain) {
+    /* initialize the dev_info structure if it doesn't exist yet. */
+    if (! dev->dev_info) {
+      dev->dev_info = zalloc(sizeof *dev->dev_info);
+      if (!dev->dev_info)
+       return -1;
     }
-    strlcpy(pci_device->pci_dev_info->linux_kernel_module,"unknown",7);
+    strcpy(dev->dev_info->linux_kernel_module, "unknown");
   }
 
   /* Opening the modules.pcimap (ofa linux kernel) from the boot device*/
-  f=fopen("modules.pcimap","r");
+  f=fopen("modules.pcimap", "r");
   if (!f)
-    return;
+    return -1;
 
   strcpy(vendor_id,"0000");
   strcpy(product_id,"0000");
@@ -141,26 +136,23 @@ void get_module_name_from_pci_ids(struct pci_device_list *pci_device_list)
    }
     /* if a pci_device match an entry, fill the linux_kernel_module with
        the appropriate kernel module */
-    for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-      struct pci_device *pci_device =
-       &pci_device_list->pci_device[pci_dev];
-
-      if (hex_to_int(vendor_id) == pci_device->vendor &&
-         hex_to_int(product_id) == pci_device->product &&
-         (hex_to_int(sub_product_id) & pci_device->sub_product)
-         == pci_device->sub_product &&
-         (hex_to_int(sub_vendor_id) & pci_device->sub_vendor)
-         == pci_device->sub_vendor)
-       strcpy(pci_device->pci_dev_info->linux_kernel_module,
-              module_name);
+    for_each_pci_func(dev, domain) {
+      if (hex_to_int(vendor_id) == dev->vendor &&
+         hex_to_int(product_id) == dev->product &&
+         (hex_to_int(sub_product_id) & dev->sub_product)
+         == dev->sub_product &&
+         (hex_to_int(sub_vendor_id) & dev->sub_vendor)
+         == dev->sub_vendor)
+       strcpy(dev->dev_info->linux_kernel_module, module_name);
     }
   }
- fclose(f);
+  fclose(f);
+  return 0;
 }
 
 /* Try to match any pci device to the appropriate vendor and product name */
 /* it uses the pci.ids from the boot device*/
-void get_name_from_pci_ids(struct pci_device_list *pci_device_list)
+int get_name_from_pci_ids(struct pci_domain *domain)
 {
   char line[MAX_LINE];
   char vendor[255];
@@ -170,156 +162,138 @@ void get_name_from_pci_ids(struct pci_device_list *pci_device_list)
   char sub_product_id[5];
   char sub_vendor_id[5];
   FILE *f;
-  int pci_dev;
-
- /* Intializing the vendor/product name for each pci device to "unknow" */
- /* adding a pci_dev_info member if needed*/
- for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-    struct pci_device *pci_device = &pci_device_list->pci_device[pci_dev];
-
-    /* initialize the pci_dev_info structure if it doesn't exist yet. */
-    if (! pci_device->pci_dev_info) {
-      pci_device->pci_dev_info = calloc(1,sizeof *pci_device->pci_dev_info);
-
-      if (!pci_device->pci_dev_info) {
-       printf("Can't allocate memory\n");
-       return;
-      }
+  struct pci_device *dev;
+
+  /* Intializing the vendor/product name for each pci device to "unknown" */
+  /* adding a dev_info member if needed*/
+  for_each_pci_func(dev, domain) {
+    /* initialize the dev_info structure if it doesn't exist yet. */
+    if (! dev->dev_info) {
+      dev->dev_info = zalloc(sizeof *dev->dev_info);
+      if (!dev->dev_info)
+       return -1;
     }
-
-    strlcpy(pci_device->pci_dev_info->vendor_name,"unknown",7);
-    strlcpy(pci_device->pci_dev_info->product_name,"unknown",7);
+    strcpy(dev->dev_info->vendor_name,"unknown");
+    strcpy(dev->dev_info->product_name,"unknown");
   }
 
   /* Opening the pci.ids from the boot device*/
-  f=fopen("pci.ids","r");
+  f = fopen("pci.ids","r");
   if (!f)
-        return;
+    return -1;
+
   strcpy(vendor_id,"0000");
   strcpy(product_id,"0000");
   strcpy(sub_product_id,"0000");
   strcpy(sub_vendor_id,"0000");
 
-
   /* for each line we found in the pci.ids*/
   while ( fgets(line, sizeof line, f) ) {
     /* Skipping uncessary lines */
     if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 'C') ||
        (line[0] == 10))
-        continue;
+      continue;
     /* If the line doesn't start with a tab, it means that's a vendor id */
     if (line[0] != '\t') {
-
-       /* the 4th first chars are the vendor_id */
-        strlcpy(vendor_id,line,4);
-
-       /* the vendor name is the next field*/
-        vendor_id[4]=0;
-        strlcpy(vendor,skipspace(strstr(line," ")),255);
-
-        remove_eol(vendor);
-       /* init product_id, sub_product and sub_vendor */
-        strcpy(product_id,"0000");
-        strcpy(sub_product_id,"0000");
-        strcpy(sub_vendor_id,"0000");
-
-       /* ffff is an invalid vendor id */
-       if (strstr(vendor_id,"ffff")) break;
-       /* assign the vendor_name to any matching pci device*/
-       for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-         struct pci_device *pci_device =
-           &pci_device_list->pci_device[pci_dev];
-
-         if (hex_to_int(vendor_id) == pci_device->vendor)
-           strlcpy(pci_device->pci_dev_info->vendor_name,vendor,255);
-       }
-    /* if we have a tab + a char, it means this is a product id */
+      
+      /* the 4th first chars are the vendor_id */
+      strlcpy(vendor_id,line,4);
+      
+      /* the vendor name is the next field*/
+      vendor_id[4]=0;
+      strlcpy(vendor,skipspace(strstr(line," ")),255);
+      
+      remove_eol(vendor);
+      /* init product_id, sub_product and sub_vendor */
+      strcpy(product_id,"0000");
+      strcpy(sub_product_id,"0000");
+      strcpy(sub_vendor_id,"0000");
+      
+      /* ffff is an invalid vendor id */
+      if (strstr(vendor_id,"ffff")) break;
+      /* assign the vendor_name to any matching pci device*/
+      for_each_pci_func(dev, domain) {
+       if (hex_to_int(vendor_id) == dev->vendor)
+         strlcpy(dev->dev_info->vendor_name,vendor,255);
+      }
+      /* if we have a tab + a char, it means this is a product id */
     } else if ((line[0] == '\t') && (line[1] != '\t')) {
-
-       /* the product name the second field */
-        strlcpy(product,skipspace(strstr(line," ")),255);
-        remove_eol(product);
-
-       /* the product id is first field */
-       strlcpy(product_id,&line[1],4);
-        product_id[4]=0;
-
-       /* init sub_product and sub_vendor */
-        strcpy(sub_product_id,"0000");
-        strcpy(sub_vendor_id,"0000");
-
-       /* assign the product_name to any matching pci device*/
-       for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-         struct pci_device *pci_device =
-           &pci_device_list->pci_device[pci_dev];
-         if (hex_to_int(vendor_id) == pci_device->vendor &&
-             hex_to_int(product_id) == pci_device->product)
-           strlcpy(pci_device->pci_dev_info->product_name,product,255);
-       }
-
-    /* if we have two tabs, it means this is a sub product */
+      
+      /* the product name the second field */
+      strlcpy(product,skipspace(strstr(line," ")),255);
+      remove_eol(product);
+      
+      /* the product id is first field */
+      strlcpy(product_id,&line[1],4);
+      product_id[4]=0;
+      
+      /* init sub_product and sub_vendor */
+      strcpy(sub_product_id,"0000");
+      strcpy(sub_vendor_id,"0000");
+      
+      /* assign the product_name to any matching pci device*/
+      for_each_pci_func(dev, domain) {
+       if (hex_to_int(vendor_id) == dev->vendor &&
+           hex_to_int(product_id) == dev->product)
+         strlcpy(dev->dev_info->product_name,product,255);
+      }
+      
+      /* if we have two tabs, it means this is a sub product */
     } else if ((line[0] == '\t') && (line[1] == '\t')) {
-
+      
       /* the product name is last field */
       strlcpy(product,skipspace(strstr(line," ")),255);
       strlcpy(product,skipspace(strstr(product," ")),255);
       remove_eol(product);
-
+      
       /* the sub_vendor id is first field */
       strlcpy(sub_vendor_id,&line[2],4);
       sub_vendor_id[4]=0;
-
+      
       /* the sub_vendor id is second field */
       strlcpy(sub_product_id,&line[7],4);
       sub_product_id[4]=0;
-
+      
       /* assign the product_name to any matching pci device*/
-      for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-       struct pci_device *pci_device =
-         &pci_device_list->pci_device[pci_dev];
-
-       if (hex_to_int(vendor_id) == pci_device->vendor &&
-           hex_to_int(product_id) == pci_device->product &&
-           hex_to_int(sub_product_id) == pci_device->sub_product &&
-           hex_to_int(sub_vendor_id) == pci_device->sub_vendor)
-         strlcpy(pci_device->pci_dev_info->product_name,product,255);
+      for_each_pci_func(dev, domain) {
+       if (hex_to_int(vendor_id) == dev->vendor &&
+           hex_to_int(product_id) == dev->product &&
+           hex_to_int(sub_product_id) == dev->sub_product &&
+           hex_to_int(sub_vendor_id) == dev->sub_vendor)
+         strlcpy(dev->dev_info->product_name,product,255);
       }
     }
   }
   fclose(f);
+  return 0;
 }
 
 /* searching if any pcidevice match our query */
-struct match *find_pci_device(struct pci_device_list * pci_device_list,
+struct match *find_pci_device(const struct pci_domain *domain,
                              struct match *list)
 {
-  int pci_dev;
   uint32_t did, sid;
   struct match *m;
+  const struct pci_device *dev;
+
   /* for all matches we have to search */
   for (m = list; m; m = m->next) {
-         /* for each pci device we know */
-    for (pci_dev = 0; pci_dev < pci_device_list->count; pci_dev++) {
-      struct pci_device *pci_device =
-       &pci_device_list->pci_device[pci_dev];
-
+    /* for each pci device we know */
+    for_each_pci_func(dev, domain) {
       /* sid & did are the easiest way to compare devices */
       /* they are made of vendor/product subvendor/subproduct ids */
-      sid =
-       ((pci_device->sub_product) << 16 | (pci_device->
-                                           sub_vendor));
-      did = ((pci_device->product << 16) | (pci_device->vendor));
-
+      sid = dev->svid_sdid;
+      did = dev->vid_did;
       /*if the current device match */
       if (((did ^ m->did) & m->did_mask) == 0 &&
          ((sid ^ m->sid) & m->sid_mask) == 0 &&
-         pci_device->revision >= m->rid_min
-         && pci_device->revision <= m->rid_max) {
+         dev->revision >= m->rid_min
+         && dev->revision <= m->rid_max) {
        dprintf("PCI Match: Vendor=%04x Product=%04x Sub_vendor=%04x Sub_Product=%04x Release=%02x\n",
-               pci_device->vendor, pci_device->product,
-               pci_device->sub_vendor,
-               pci_device->sub_product,
-               pci_device->revision);
+               dev->vendor, dev->product,
+               dev->sub_vendor,
+               dev->sub_product,
+               dev->revision);
        /* returning the matched pci device */
        return m;
       }
@@ -329,45 +303,32 @@ struct match *find_pci_device(struct pci_device_list * pci_device_list,
 }
 
 /* scanning the pci bus to find pci devices */
-int pci_scan(struct pci_bus_list * pci_bus_list, struct pci_device_list * pci_device_list)
+struct pci_domain *pci_scan(void)
 {
-  unsigned int bus, dev, func, maxfunc;
-  uint32_t did, sid;
-  uint8_t hdrtype, rid;
+  struct pci_domain *domain = NULL;
+  struct pci_bus    *bus    = NULL;
+  struct pci_slot   *slot   = NULL;
+  struct pci_device *func   = NULL;
+  unsigned int nbus, ndev, nfunc, maxfunc;
+  uint32_t did, sid, rcid;
+  uint8_t hdrtype;
   pciaddr_t a;
   int cfgtype;
 
-  pci_device_list->count = 0;
-
-#ifdef DEBUG
-  outl(~0, 0xcf8);
-  printf("Poking at port CF8 = %#08x\n", inl(0xcf8));
-  outl(0, 0xcf8);
-#endif
-
   cfgtype = pci_set_config_type(PCI_CFG_AUTO);
   (void)cfgtype;
 
   dprintf("PCI configuration type %d\n", cfgtype);
   dprintf("Scanning PCI Buses\n");
 
-  /* We try to detect 256 buses */
-  for (bus = 0; bus < MAX_PCI_BUSES; bus++) {
-
+  for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) {
     dprintf("Probing bus 0x%02x... \n", bus);
 
-    pci_bus_list->pci_bus[bus].id = bus;
-    pci_bus_list->pci_bus[bus].pci_device_count = 0;
-    pci_bus_list->count = 0;;
-
-    for (dev = 0; dev < MAX_PCI_DEVICES ; dev++) {
+    for (ndev = 0; ndev < MAX_PCI_DEVICES ; ndev++) {
       maxfunc = 1;             /* Assume a single-function device */
-      for (func = 0; func < maxfunc; func++) {
-       struct pci_device *pci_device =
-         &pci_device_list->pci_device[pci_device_list->count];
-
-       a = pci_mkaddr(bus, dev, func, 0);
 
+      for (nfunc = 0; nfunc < maxfunc; nfunc++) {
+       a = pci_mkaddr(nbus, ndev, nfunc, 0);
        did = pci_readl(a);
 
        if (did == 0xffffffff || did == 0xffff0000 ||
@@ -379,36 +340,79 @@ int pci_scan(struct pci_bus_list * pci_bus_list, struct pci_device_list * pci_de
        if (hdrtype & 0x80)
          maxfunc = MAX_PCI_FUNC; /* Multifunction device */
 
-       rid = pci_readb(a + 0x08);
-       sid = pci_readl(a + 0x2c);
+       rcid = pci_readl(a + 0x08);
+       sid  = pci_readl(a + 0x2c);
 
-       pci_device->addr = a;
-       pci_device->product = did >> 16;
-       pci_device->sub_product = sid >> 16;
-       pci_device->vendor = (did << 16) >> 16;
-       pci_device->sub_vendor = (sid << 16) >> 16;
-       pci_device->revision = rid;
-       pci_device_list->count++;
-       pci_device++;
+       if (!domain) {
+         domain = zalloc(sizeof *domain);
+         if (!domain)
+           goto bail;
+       }
+       if (!bus) {
+         bus = zalloc(sizeof *bus);
+         if (!bus)
+           goto bail;
+         domain->bus[nbus] = bus;
+       }
+       if (!slot) {
+         slot = zalloc(sizeof *slot);
+         if (!slot)
+           goto bail;
+         bus->slot[ndev] = slot;
+       }
+       func = zalloc(sizeof *func);
+       if (!func)
+         goto bail;
+
+       slot->func[nfunc] = func;
+
+       func->vid_did   = did;
+       func->svid_sdid = sid;
+       func->rid_class = rcid;
 
        dprintf
          ("Scanning: BUS %02x DID %08x (%04x:%04x) SID %08x RID %02x\n",
           bus, did, did >> 16, (did << 16) >> 16,
-          sid, rid);
-       /* Adding the detected pci device to the bus */
-       pci_bus_list->pci_bus[bus].
-         pci_device[pci_bus_list->pci_bus[bus].
-                    pci_device_count] = pci_device;
-       pci_bus_list->pci_bus[bus].pci_device_count++;
+          sid, rcid & 0xff);
       }
     }
   }
 
-  /* Detecting pci buses that have pci devices connected */
-  for (bus = 0; bus < MAX_PCI_BUSES; bus++) {
-    if (pci_bus_list->pci_bus[bus].pci_device_count > 0) {
-      pci_bus_list->count++;
+  return domain;
+
+ bail:
+  free_pci_domain(domain);
+  return NULL;
+}
+
+void free_pci_domain(struct pci_domain *domain)
+{  
+  struct pci_bus    *bus;
+  struct pci_slot   *slot;
+  struct pci_device *func;
+  unsigned int nbus, ndev, nfunc;
+
+  if (domain) {
+    for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) {
+      bus = domain->bus[nbus];
+      if (bus) {
+       for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) {
+         slot = bus->slot[ndev];
+         if (slot) {
+           for (nfunc = 0; nfunc < MAX_PCI_FUNC; nfunc++) {
+             func = slot->func[nfunc];
+             if (func) {
+               if (func->dev_info)
+                 free(func->dev_info);
+               free(func);
+             }
+             free(slot);
+           }
+         }
+         free(bus);
+       }
+      }
+      free(domain);
     }
   }
-  return 0;
 }
index d200d62..9bd445c 100644 (file)
@@ -192,18 +192,19 @@ parse_config(const char *filename)
 int main(int argc, char *argv[])
 {
   struct match *list, *match;
-  struct pci_device_list pci_device_list;
-  struct pci_bus_list pci_bus_list;
+  struct pci_domain *pci_domain;
 
   openconsole(&dev_null_r, &dev_stdcon_w);
-  pci_scan(&pci_bus_list,&pci_device_list);
+  pci_domain = pci_scan();
 
-  list = parse_config(argc < 2 ? NULL : argv[1]);
+  if (pci_domain) {
+    list = parse_config(argc < 2 ? NULL : argv[1]);
 
-  match = find_pci_device(&pci_device_list,list);
+    match = find_pci_device(pci_domain, list);
 
-  if ( match )
-    syslinux_run_command(match->filename);
+    if ( match )
+      syslinux_run_command(match->filename);
+  }
 
   /* On error, return to the command line */
   fputs("Error: no recognized network card found!\n", stderr);
index 38ef251..240f19f 100644 (file)
@@ -59,59 +59,38 @@ char display_line;
     printf ( __VA_ARGS__);                     \
   } while (0);
 
-void display_pci_devices(struct pci_device_list *pci_device_list) {
-  int pci_dev;
-  for (pci_dev=0; pci_dev < pci_device_list->count; pci_dev++) {
-    struct pci_device *pci_device = &pci_device_list->pci_device[pci_dev];
-    printf("PCI: Vendor=%04x(%s) Product=%04x(%s) "
-          "Sub_vendor=%04x Sub_Product=%04x Release=%02x\n",
-          pci_device->vendor, pci_device->pci_dev_info->vendor_name,
-          pci_device->product, pci_device->pci_dev_info->product_name,
-          pci_device->sub_vendor, pci_device->sub_product,
-          pci_device->revision);
+void display_pci_devices(struct pci_domain *pci_domain) {
+  struct pci_device *pci_device;
+  int ndev = 0;
+  for_each_pci_func(pci_device, pci_domain) {
+       printf("[%02x:%02x.%01x]: %s: %04x:%04x[%04x:%04x]) %s:%s\n",
+              __pci_bus, __pci_slot, __pci_func,
+              pci_device->dev_info->linux_kernel_module,
+              pci_device->vendor, pci_device->product,
+              pci_device->sub_vendor, pci_device->sub_product,
+              pci_device->dev_info->vendor_name,
+              pci_device->dev_info->product_name);
+    ndev++;
   }
-  printf("PCI: %d devices found\n",pci_device_list->count);
-}
-
-void display_pci_bus(struct pci_bus_list *pci_bus_list, bool display_pci_devices) {
-  int bus;
-  for (bus=0; bus<pci_bus_list->count;bus++) {
-    struct pci_bus pci_bus = pci_bus_list->pci_bus[bus];
-    printf("\nPCI BUS No %d:\n", pci_bus.id);
-    if (display_pci_devices) {
-      int pci_dev;
-      for (pci_dev=0; pci_dev < pci_bus.pci_device_count; pci_dev++) {
-       struct pci_device pci_device=*(pci_bus.pci_device[pci_dev]);
-       printf("%s :%04x:%04x[%04x:%04x]) %s:%s\n",
-               pci_device.pci_dev_info->linux_kernel_module,
-              pci_device.vendor, pci_device.product,
-               pci_device.sub_vendor, pci_device.sub_product,
-              pci_device.pci_dev_info->vendor_name,
-              pci_device.pci_dev_info->product_name);
-      }
-    }
-  }
-  printf("PCI: %d bus%s found\n",
-        pci_bus_list->count,
-        pci_bus_list->count == 1 ? "" : "es");
+  printf("PCI: %d devices found\n", ndev);
 }
 
 int main(int argc, char *argv[])
 {
-  struct pci_device_list pci_device_list;
-  struct pci_bus_list pci_bus_list;
+  struct pci_domain *pci_domain;
+
   openconsole(&dev_null_r, &dev_stdcon_w);
 
   /* Scanning to detect pci buses and devices */
-  pci_scan(&pci_bus_list,&pci_device_list);
+  pci_domain = pci_scan();
 
   /* Assigning product & vendor name for each device*/
-  get_name_from_pci_ids(&pci_device_list);
+  get_name_from_pci_ids(pci_domain);
 
   /* Detecting which kernel module should match each device */
-  get_module_name_from_pci_ids(&pci_device_list);
+  get_module_name_from_pci_ids(pci_domain);
 
   /* display the pci devices we found */
-  display_pci_bus(&pci_bus_list,true);
+  display_pci_devices(pci_domain);
   return 1;
 }