int pflash_cfi01_fdt_init(char *node_path, FDTMachineInfo *fdti, void *opaque) { hwaddr flash_base = 0; int flash_size = 0; Error *errp = NULL; int be = *((int *)opaque); DriveInfo *dinfo; int bank_width; flash_base = qemu_devtree_getprop_cell(fdti->fdt, node_path, "reg", 0, false, &errp); flash_base += fdt_get_parent_base(node_path, fdti); flash_size = qemu_devtree_getprop_cell(fdti->fdt, node_path, "reg", 1, false, &errp); bank_width = qemu_devtree_getprop_cell(fdti->fdt, node_path, "bank-width", 0, false, &errp); assert_no_error(errp); printf("FDT: FLASH: baseaddr: 0x%"HWADDR_PRIX", size: 0x%x\n", flash_base, flash_size); dinfo = drive_get_next(IF_PFLASH); pflash_cfi01_register(flash_base, NULL, node_path, flash_size, dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE, flash_size/FLASH_SECTOR_SIZE, bank_width, 0x89, 0x18, 0x0000, 0x0, be); return 0; }
static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat) { int err; qemu_irq irq; hwaddr base; int offset; DeviceState *dev; char *dev_type = NULL; int is_intc; int i; dev = fdt_create_qdev_from_compat(compat, &dev_type); if (!dev) { DB_PRINT("no match found for %s\n", compat); return 1; } /* FIXME: attach to the sysbus instead */ object_property_add_child(container_get(qdev_get_machine(), "/unattached"), qemu_fdt_get_node_name(fdti->fdt, node_path), OBJECT(dev), NULL); fdt_init_set_opaque(fdti, node_path, dev); /* connect nic if appropriate */ static int nics; if (object_property_find(OBJECT(dev), "mac", NULL)) { qdev_set_nic_properties(dev, &nd_table[nics]); if (nd_table[nics].instantiated) { DB_PRINT("NIC instantiated: %s\n", dev_type); nics++; } } offset = fdt_path_offset(fdti->fdt, node_path); for (offset = fdt_first_property_offset(fdti->fdt, offset); offset != -FDT_ERR_NOTFOUND; offset = fdt_next_property_offset(fdti->fdt, offset)) { const char *propname; int len; const void *val = fdt_getprop_by_offset(fdti->fdt, offset, &propname, &len); propname = trim_vendor(propname); ObjectProperty *p = object_property_find(OBJECT(dev), propname, NULL); if (p) { DB_PRINT("matched property: %s of type %s, len %d\n", propname, p->type, len); } if (!p) { continue; } /* FIXME: handle generically using accessors and stuff */ if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") || !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) { uint64_t offset = (!strcmp(propname, "reg")) ? fdt_get_parent_base(node_path, fdti) : 0; object_property_set_int(OBJECT(dev), get_int_be(val, len) + offset, propname, &error_abort); DB_PRINT("set property %s to %#llx\n", propname, (long long unsigned int)get_int_be(val, len)); } else if (!strcmp(p->type, "bool")) { object_property_set_bool(OBJECT(dev), !!get_int_be(val, len), propname, &error_abort); DB_PRINT("set property %s to %#llx\n", propname, (long long unsigned int)get_int_be(val, len)); } else if (!strncmp(p->type, "link", 4)) { char target_node_path[DT_PATH_LENGTH]; DeviceState *linked_dev; if (qemu_fdt_get_node_by_phandle(fdti->fdt, target_node_path, get_int_be(val, len))) { abort(); } while (!fdt_init_has_opaque(fdti, target_node_path)) { fdt_init_yield(fdti); } linked_dev = fdt_init_get_opaque(fdti, target_node_path); object_property_set_link(OBJECT(dev), OBJECT(linked_dev), propname, &error_abort); } else if (!strcmp(p->type, "string")) { object_property_set_str(OBJECT(dev), strndup(val, len), propname, &error_abort); } } qdev_init_nofail(dev); /* map slave attachment */ base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0, false, &error_abort); base += fdt_get_parent_base(node_path, fdti); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); { int len; fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path), "interrupt-controller", &len); is_intc = len >= 0; DB_PRINT("is interrupt controller: %c\n", is_intc ? 'y' : 'n'); } /* connect irq */ for (i = 0; ; ++i) { char irq_info[1024]; irq = fdt_get_irq_info(fdti, node_path, i, &err, irq_info); /* INTCs inferr their top level, if no IRQ connection specified */ if (err && is_intc) { irq = fdti->irq_base; sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq); fprintf(stderr, "FDT: (%s) connected top level irq %s\n", dev_type, irq_info); break; } if (!err) { sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); fprintf(stderr, "FDT: (%s) connected irq %s\n", dev_type, irq_info); } else { break; } } if (dev_type) { g_free(dev_type); } return 0; }