+static struct pci_device*
+pci_create_device(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);
+
+ kappendf(".%x:%x, ", vendor, devid);
+
+ struct pci_device_def *pos, *n;
+ hashtable_bucket_foreach(bucket, pos, n, devdef.hlist_if)
+ {
+ if (pos->dev_class != PCI_DEV_CLASS(class)) {
+ continue;
+ }
+
+ int result = (pos->dev_vendor & vendor) == vendor &&
+ (pos->dev_id & devid) == devid;
+
+ if (result) {
+ goto found;
+ }
+ }
+
+ kappendf(KWARN "unknown device\n");
+
+ return NULL;
+
+found:
+ 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_prepare(&device->dev);
+
+ pci_probe_msi_info(device);
+ pci_probe_bar_info(device);
+
+ kappendf("%s (dev.%x:%x:%x) \n",
+ pos->devdef.name,
+ pos->devdef.class.meta,
+ pos->devdef.class.device,
+ pos->devdef.class.variant);
+
+ if (!pos->devdef.init_for) {
+ kappendf(KERROR "bad def\n");
+ goto fail;
+ }
+
+ int errno = pos->devdef.init_for(&pos->devdef, &device->dev);
+ if (errno) {
+ kappendf(KERROR "failed (e=%d)\n", errno);
+ goto fail;
+ }
+
+ llist_append(&pci_devices, &device->dev_chain);
+
+ return device;
+
+fail:
+ vfree(device);
+ return NULL;
+}
+