+static inline void
+pci_log_device(struct pci_device* pcidev)
+{
+ pciaddr_t loc = pcidev->loc;
+ struct device_def* binddef = pcidev->binding.def;
+
+ if (!binddef) {
+ kprintf("pci.%d:%d:%d, no binding",
+ PCILOC_BUS(loc),
+ PCILOC_DEV(loc),
+ PCILOC_FN(loc));
+ return;
+ }
+
+ kprintf("pci.%d:%d:%d, dev.%xh:%xh.%d, %s",
+ PCILOC_BUS(loc),
+ PCILOC_DEV(loc),
+ PCILOC_FN(loc),
+ binddef->class.fn_grp,
+ binddef->class.device,
+ binddef->class.variant,
+ binddef->name);
+}
+
+static struct pci_device*
+pci_create_device(pciaddr_t loc, ptr_t pci_base, int devinfo)
+{
+ pci_reg_t class = pci_read_cspace(pci_base, 0x8);
+ struct hbucket* bucket = device_definitions_byif(DEVIF_PCI);
+
+ u32_t devid = PCI_DEV_DEVID(devinfo);
+ u32_t vendor = PCI_DEV_VENDOR(devinfo);
+ pci_reg_t intr = pci_read_cspace(pci_base, 0x3c);
+
+ struct pci_device* device = vzalloc(sizeof(struct pci_device));
+ device->class_info = class;
+ device->device_info = devinfo;
+ device->cspace_base = pci_base;
+ device->intr_info = intr;
+
+ device_create(&device->dev, pcidev_cat, DEV_IFSYS, NULL);
+
+ pci_probe_msi_info(device);
+ pci_probe_bar_info(device);
+
+ llist_append(&pci_devices, &device->dev_chain);
+ device_register(&device->dev, &pci_def.class, "%x", loc);
+ pci_def.class.variant++;
+
+ // find a suitable binding
+
+ struct pci_device_def *pos, *n;
+ hashtable_bucket_foreach(bucket, pos, n, devdef.hlist_if)
+ {
+ if (pos->dev_class != PCI_DEV_CLASS(class)) {
+ continue;
+ }
+
+ u32_t idm = pos->ident_mask;
+ int result = (pos->dev_ident & idm) == (devinfo & idm);
+
+ if (result) {
+ goto found;
+ }
+ }
+
+ goto done;
+
+found:
+ if (!pos->devdef.bind) {
+ kprintf(KERROR "pci_loc:%x, (%xh:%xh.%d) unbindable",
+ loc,
+ pos->devdef.class.fn_grp,
+ pos->devdef.class.device,
+ pos->devdef.class.variant);
+ goto done;
+ }
+
+ int errno = pos->devdef.bind(&pos->devdef, &device->dev);
+ if (errno) {
+ kprintf(KERROR "pci_loc:%x, (%xh:%xh.%d) failed, e=%d",
+ loc,
+ pos->devdef.class.fn_grp,
+ pos->devdef.class.device,
+ pos->devdef.class.variant,
+ errno);
+ goto done;
+ }
+
+ device->binding.def = &pos->devdef;
+
+done:
+ return device;
+}
+