/* * Loop through all dynamically created sysbus devices and call * func() for each instance. */ void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque) { Object *container; SysBusFind find = { .func = func, .opaque = opaque, }; /* Loop through all sysbus devices that were spawened outside the machine */ container = container_get(qdev_get_machine(), "/peripheral"); find_sysbus_device(container, &find); container = container_get(qdev_get_machine(), "/peripheral-anon"); find_sysbus_device(container, &find); }
static void realize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char link_name[256]; gchar *child_name; Error *err = NULL; DPRINTFN("drc realize: %x", drck->get_index(drc)); /* NOTE: we do this as part of realize/unrealize due to the fact * that the guest will communicate with the DRC via RTAS calls * referencing the global DRC index. By unlinking the DRC * from DRC_CONTAINER_PATH/<drc_index> we effectively make it * inaccessible by the guest, since lookups rely on this path * existing in the composition tree */ root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc)); child_name = object_get_canonical_path_component(OBJECT(drc)); DPRINTFN("drc child name: %s", child_name); object_property_add_alias(root_container, link_name, drc->owner, child_name, &err); if (err) { error_report("%s", error_get_pretty(err)); error_free(err); object_unref(OBJECT(drc)); } g_free(child_name); DPRINTFN("drc realize complete"); }
PRManagerInfoList *qmp_query_pr_managers(Error **errp) { PRManagerInfoList *head = NULL; PRManagerInfoList **prev = &head; Object *container = container_get(object_get_root(), PR_MANAGER_PATH); object_child_foreach(container, query_one_pr_manager, &prev); return head; }
IOThreadInfoList *qmp_query_iothreads(Error **errp) { IOThreadInfoList *head = NULL; IOThreadInfoList **prev = &head; Object *container = container_get(object_get_root(), IOTHREADS_PATH); object_child_foreach(container, query_one_iothread, &prev); return head; }
static void main_system_bus_create(void) { /* assign main_system_bus before qbus_create_inplace() * in order to make "if (bus != sysbus_get_default())" work */ main_system_bus = g_malloc0(system_bus_info.instance_size); qbus_create_inplace(main_system_bus, system_bus_info.instance_size, TYPE_SYSTEM_BUS, NULL, "main-system-bus"); OBJECT(main_system_bus)->free = g_free; object_property_add_child(container_get(qdev_get_machine(), "/unattached"), "sysbus", OBJECT(main_system_bus), NULL); }
static void unrealize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char name[256]; Error *err = NULL; DPRINTFN("drc unrealize: %x", drck->get_index(drc)); root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); snprintf(name, sizeof(name), "%x", drck->get_index(drc)); object_property_del(root_container, name, &err); if (err) { error_report_err(err); object_unref(OBJECT(drc)); } }
static void test_qom_partial_path(void) { Object *root = object_get_objects_root(); Object *cont1 = container_get(root, "/cont1"); Object *obj1 = object_new(TYPE_DUMMY); Object *obj2a = object_new(TYPE_DUMMY); Object *obj2b = object_new(TYPE_DUMMY); bool ambiguous; /* Objects created: * /cont1 * /cont1/obj1 * /cont1/obj2 (obj2a) * /obj2 (obj2b) */ object_property_add_child(cont1, "obj1", obj1, &error_abort); object_unref(obj1); object_property_add_child(cont1, "obj2", obj2a, &error_abort); object_unref(obj2a); object_property_add_child(root, "obj2", obj2b, &error_abort); object_unref(obj2b); ambiguous = false; g_assert(!object_resolve_path_type("", TYPE_DUMMY, &ambiguous)); g_assert(ambiguous); g_assert(!object_resolve_path_type("", TYPE_DUMMY, NULL)); ambiguous = false; g_assert(!object_resolve_path("obj2", &ambiguous)); g_assert(ambiguous); g_assert(!object_resolve_path("obj2", NULL)); ambiguous = false; g_assert(object_resolve_path("obj1", &ambiguous) == obj1); g_assert(!ambiguous); g_assert(object_resolve_path("obj1", NULL) == obj1); object_unparent(obj2b); object_unparent(cont1); }
static Object *get_chardevs_root(void) { return container_get(object_get_root(), "/chardevs"); }
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; }
static void petalogix_ml605_init(QEMUMachineInitArgs *args) { ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev, *dma, *eth0; MicroBlazeCPU *cpu; SysBusDevice *busdev; CPUMBState *env; DriveInfo *dinfo; int i; hwaddr ddr_base = MEMORY_BASEADDR; MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; /* init CPUs */ if (cpu_model == NULL) { cpu_model = "microblaze"; } cpu = cpu_mb_init(cpu_model); env = &cpu->env; /* Attach emulated BRAM through the LMB. */ memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram", LMB_BRAM_SIZE); vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram); memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ddr_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); /* 5th parameter 2 means bank-width * 10th paremeter 0 means little-endian */ pflash_cfi01_register(FLASH_BASEADDR, NULL, "petalogix_ml605.flash", FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, (64 * 1024), FLASH_SIZE >> 16, 2, 0x89, 0x18, 0x0000, 0x0, 0); cpu_irq = microblaze_pic_init_cpu(env); dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4); for (i = 0; i < 32; i++) { irq[i] = qdev_get_gpio_in(dev, i); } serial_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2, irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN); /* 2 timers at irq 2 @ 100 Mhz. */ xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000); /* axi ethernet and dma initialization. */ dma = qdev_create(NULL, "xlnx.axi-dma"); /* FIXME: attach to the sysbus instead */ object_property_add_child(container_get(qdev_get_machine(), "/unattached"), "xilinx-dma", OBJECT(dma), NULL); eth0 = xilinx_axiethernet_create(&nd_table[0], STREAM_SLAVE(dma), 0x82780000, irq[3], 0x1000, 0x1000); xilinx_axiethernetdma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0], 100 * 1000000); { SSIBus *spi; dev = qdev_create(NULL, "xlnx.xps-spi"); qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0x40a00000); sysbus_connect_irq(busdev, 0, irq[4]); spi = (SSIBus *)qdev_get_child_bus(dev, "spi"); for (i = 0; i < NUM_SPI_FLASHES; i++) { qemu_irq cs_line; dev = ssi_create_slave_no_init(spi, "m25p80"); qdev_prop_set_string(dev, "partname", "n25q128"); qdev_init_nofail(dev); cs_line = qdev_get_gpio_in(dev, 0); sysbus_connect_irq(busdev, i+1, cs_line); } } microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE, machine_cpu_reset); }
static void zynq_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; A9MPPrivState *mpcore; ObjectClass *cpu_oc; ARMCPU *cpu[MAX_CPUS]; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); DeviceState *dev; SysBusDevice *busdev; qemu_irq pic[64]; Error *err = NULL; int n; if (machine->cpu_model) { error_report("Zynq does not support CPU model override!\n"); exit(1); } if (!cpu_model) { cpu_model = "cortex-a9"; } cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); for (n = 0; n < smp_cpus; n++) { cpu[n] = ARM_CPU(object_new(object_class_get_name(cpu_oc))); /* By default A9 CPUs have EL3 enabled. This board does not * currently support EL3 so the CPU EL3 property is disabled before * realization. */ if (object_property_find(OBJECT(cpu[n]), "has_el3", NULL)) { object_property_set_bool(OBJECT(cpu[n]), false, "has_el3", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } object_property_set_int(OBJECT(cpu[n]), ZYNQ_BOARD_MIDR, "midr", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_int(OBJECT(cpu[n]), MPCORE_PERIPHBASE, "reset-cbar", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_bool(OBJECT(cpu[n]), true, "realized", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } /* max 2GB ram */ if (ram_size > 0x80000000) { ram_size = 0x80000000; } /* pl353 */ dev = qdev_create(NULL, "arm.pl35x"); /* FIXME: handle this somewhere central */ object_property_add_child(container_get(qdev_get_machine(), "/unattached"), "pl353", OBJECT(dev), NULL); qdev_prop_set_uint8(dev, "x", 3); { DriveInfo *dinfo = drive_get_next(IF_PFLASH); BlockBackend *blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; DeviceState *att_dev = qdev_create(NULL, "cfi.pflash02"); Error *errp = NULL; if (blk && qdev_prop_set_drive(att_dev, "drive", blk)) { abort(); } qdev_prop_set_uint32(att_dev, "num-blocks", FLASH_SIZE/FLASH_SECTOR_SIZE); qdev_prop_set_uint32(att_dev, "sector-length", FLASH_SECTOR_SIZE); qdev_prop_set_uint8(att_dev, "width", 1); qdev_prop_set_uint8(att_dev, "mappings", 1); qdev_prop_set_uint8(att_dev, "big-endian", 0); qdev_prop_set_uint16(att_dev, "id0", 0x0066); qdev_prop_set_uint16(att_dev, "id1", 0x0022); qdev_prop_set_uint16(att_dev, "id2", 0x0000); qdev_prop_set_uint16(att_dev, "id3", 0x0000); qdev_prop_set_uint16(att_dev, "unlock-addr0", 0x0aaa); qdev_prop_set_uint16(att_dev, "unlock-addr1", 0x0555); qdev_prop_set_string(att_dev, "name", "pl353.pflash"); qdev_init_nofail(att_dev); object_property_set_link(OBJECT(dev), OBJECT(att_dev), "dev0", &errp); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } dinfo = drive_get_next(IF_PFLASH); att_dev = nand_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, NAND_MFR_STMICRO, 0xaa); object_property_set_link(OBJECT(dev), OBJECT(att_dev), "dev1", &errp); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xe000e000); sysbus_mmio_map(busdev, 1, 0xe2000000); sysbus_mmio_map(busdev, 2, 0xe1000000); /* DDR remapped to address zero. */ memory_region_allocate_system_memory(ext_ram, NULL, "zynq.ext_ram", ram_size); memory_region_add_subregion(address_space_mem, 0, ext_ram); /* 256K of on-chip memory */ memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10, &error_abort); vmstate_register_ram_global(ocm_ram); memory_region_add_subregion(address_space_mem, OCM_BASE, ocm_ram); DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); /* AMD */ pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE, dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, FLASH_SECTOR_SIZE, FLASH_SIZE/FLASH_SECTOR_SIZE, 1, 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); dev = qdev_create(NULL, "xilinx,zynq_slcr"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000); for (n = 0; n < smp_cpus; n++) { qdev_connect_gpio_out(dev, n, qdev_get_gpio_in(DEVICE(cpu[n]), 0)); } mpcore = A9MPCORE_PRIV(object_new("a9mpcore_priv")); qdev_prop_set_uint32(DEVICE(mpcore), "num-cpu", smp_cpus); object_property_set_bool(OBJECT(mpcore), true, "realized", &err); if (err != NULL) { error_report("Couldn't realize the Zynq A9MPCore: %s", error_get_pretty(err)); exit(1); } busdev = SYS_BUS_DEVICE(DEVICE(mpcore)); sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(cpu[n]), ARM_CPU_IRQ)); } for (n = 0; n < 64; n++) { pic[n] = qdev_get_gpio_in(dev, n); } zynq_init_zc70x_i2c(0xE0004000, pic[57-IRQ_OFFSET]); zynq_init_zc70x_i2c(0xE0005000, pic[80-IRQ_OFFSET]); dev = qdev_create(NULL, "xlnx,ps7-usb"); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xE0002000); sysbus_connect_irq(busdev, 0, pic[53-IRQ_OFFSET]); dev = qdev_create(NULL, "xlnx,ps7-usb"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); sysbus_mmio_map(busdev, 0, 0xE0003000); sysbus_connect_irq(busdev, 0, pic[76-IRQ_OFFSET]); zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true); sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); sysbus_create_varargs("cadence_ttc", 0xF8001000, pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL); sysbus_create_varargs("cadence_ttc", 0xF8002000, pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL); gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]); gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]); dev = qdev_create(NULL, TYPE_ZYNQ_XADC); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8007100); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]); dev = qdev_create(NULL, "pl330"); qdev_prop_set_uint8(dev, "num_chnls", 8); qdev_prop_set_uint8(dev, "num_periph_req", 4); qdev_prop_set_uint8(dev, "num_events", 16); qdev_prop_set_uint8(dev, "data_width", 64); qdev_prop_set_uint8(dev, "wr_cap", 8); qdev_prop_set_uint8(dev, "wr_q_dep", 16); qdev_prop_set_uint8(dev, "rd_cap", 8); qdev_prop_set_uint8(dev, "rd_q_dep", 16); qdev_prop_set_uint16(dev, "data_buffer_dep", 256); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xF8003000); sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */ for (n = 0; n < 8; ++n) { /* event irqs */ sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]); } dev = qdev_create(NULL, "xlnx.ps7-dev-cfg"); object_property_add_child(qdev_get_machine(), "xilinx-devcfg", OBJECT(dev), NULL); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_connect_irq(busdev, 0, pic[40-IRQ_OFFSET]); sysbus_mmio_map(busdev, 0, 0xF8007000); zynq_binfo.ram_size = ram_size; zynq_binfo.kernel_filename = kernel_filename; zynq_binfo.kernel_cmdline = kernel_cmdline; zynq_binfo.initrd_filename = initrd_filename; zynq_binfo.nb_cpus = smp_cpus; zynq_binfo.write_secondary_boot = zynq_write_secondary_boot; zynq_binfo.secondary_cpu_reset_hook = zynq_reset_secondary; zynq_binfo.smp_loader_start = SMP_BOOT_ADDR; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); }
/** * spapr_drc_populate_dt * * @fdt: libfdt device tree * @path: path in the DT to generate properties * @owner: parent Object/DeviceState for which to generate DRC * descriptions for * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding * to the types of DRCs to generate entries for * * generate OF properties to describe DRC topology/indices to guests * * as documented in PAPR+ v2.1, 13.5.2 */ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, uint32_t drc_type_mask) { Object *root_container; ObjectProperty *prop; ObjectPropertyIterator *iter; uint32_t drc_count = 0; GArray *drc_indexes, *drc_power_domains; GString *drc_names, *drc_types; int ret; /* the first entry of each properties is a 32-bit integer encoding * the number of elements in the array. we won't know this until * we complete the iteration through all the matching DRCs, but * reserve the space now and set the offsets accordingly so we * can fill them in later. */ drc_indexes = g_array_new(false, true, sizeof(uint32_t)); drc_indexes = g_array_set_size(drc_indexes, 1); drc_power_domains = g_array_new(false, true, sizeof(uint32_t)); drc_power_domains = g_array_set_size(drc_power_domains, 1); drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); /* aliases for all DRConnector objects will be rooted in QOM * composition tree at DRC_CONTAINER_PATH */ root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); iter = object_property_iter_init(root_container); while ((prop = object_property_iter_next(iter))) { Object *obj; sPAPRDRConnector *drc; sPAPRDRConnectorClass *drck; uint32_t drc_index, drc_power_domain; if (!strstart(prop->type, "link<", NULL)) { continue; } obj = object_property_get_link(root_container, prop->name, NULL); drc = SPAPR_DR_CONNECTOR(obj); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); if (owner && (drc->owner != owner)) { continue; } if ((drc->type & drc_type_mask) == 0) { continue; } drc_count++; /* ibm,drc-indexes */ drc_index = cpu_to_be32(drck->get_index(drc)); g_array_append_val(drc_indexes, drc_index); /* ibm,drc-power-domains */ drc_power_domain = cpu_to_be32(-1); g_array_append_val(drc_power_domains, drc_power_domain); /* ibm,drc-names */ drc_names = g_string_append(drc_names, drck->get_name(drc)); drc_names = g_string_insert_len(drc_names, -1, "\0", 1); /* ibm,drc-types */ drc_types = g_string_append(drc_types, spapr_drc_get_type_str(drc->type)); drc_types = g_string_insert_len(drc_types, -1, "\0", 1); } object_property_iter_free(iter); /* now write the drc count into the space we reserved at the * beginning of the arrays previously */ *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count); *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count); *(uint32_t *)drc_names->str = cpu_to_be32(drc_count); *(uint32_t *)drc_types->str = cpu_to_be32(drc_count); ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes", drc_indexes->data, drc_indexes->len * sizeof(uint32_t)); if (ret) { fprintf(stderr, "Couldn't create ibm,drc-indexes property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains", drc_power_domains->data, drc_power_domains->len * sizeof(uint32_t)); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-power-domains property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names", drc_names->str, drc_names->len); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-names property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types", drc_types->str, drc_types->len); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-types property\n"); goto out; } out: g_array_free(drc_indexes, true); g_array_free(drc_power_domains, true); g_string_free(drc_names, true); g_string_free(drc_types, true); return ret; }
void stm32_init( ram_addr_t flash_size, ram_addr_t ram_size, const char *kernel_filename, uint32_t osc_freq, uint32_t osc32_freq) { MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *flash_alias_mem = g_malloc(sizeof(MemoryRegion)); qemu_irq *pic; int i; Object *stm32_container = container_get(qdev_get_machine(), "/stm32"); pic = armv7m_init( stm32_container, address_space_mem, flash_size, ram_size, kernel_filename, "cortex-m3"); /* The STM32 family stores its Flash memory at some base address in memory * (0x08000000 for medium density devices), and then aliases it to the * boot memory space, which starts at 0x00000000 (the "System Memory" can also * be aliased to 0x00000000, but this is not implemented here). The processor * executes the code in the aliased memory at 0x00000000. We need to make a * QEMU alias so that reads in the 0x08000000 area are passed through to the * 0x00000000 area. Note that this is the opposite of real hardware, where the * memory at 0x00000000 passes reads through the "real" flash memory at * 0x08000000, but it works the same either way. */ /* TODO: Parameterize the base address of the aliased memory. */ memory_region_init_alias( flash_alias_mem, NULL, "stm32-flash-alias-mem", address_space_mem, 0, flash_size); memory_region_add_subregion(address_space_mem, 0x08000000, flash_alias_mem); DeviceState *rcc_dev = qdev_create(NULL, "stm32-rcc"); qdev_prop_set_uint32(rcc_dev, "osc_freq", osc_freq); qdev_prop_set_uint32(rcc_dev, "osc32_freq", osc32_freq); object_property_add_child(stm32_container, "rcc", OBJECT(rcc_dev), NULL); stm32_init_periph(rcc_dev, STM32_RCC_PERIPH, 0x40021000, pic[STM32_RCC_IRQ]); DeviceState **gpio_dev = (DeviceState **)g_malloc0(sizeof(DeviceState *) * STM32_GPIO_COUNT); for(i = 0; i < STM32_GPIO_COUNT; i++) { char child_name[8]; stm32_periph_t periph = STM32_GPIOA + i; gpio_dev[i] = qdev_create(NULL, TYPE_STM32_GPIO); QDEV_PROP_SET_PERIPH_T(gpio_dev[i], "periph", periph); qdev_prop_set_ptr(gpio_dev[i], "stm32_rcc", rcc_dev); snprintf(child_name, sizeof(child_name), "gpio[%c]", 'a' + i); object_property_add_child(stm32_container, child_name, OBJECT(gpio_dev[i]), NULL); stm32_init_periph(gpio_dev[i], periph, 0x40010800 + (i * 0x400), NULL); } DeviceState *exti_dev = qdev_create(NULL, TYPE_STM32_EXTI); object_property_add_child(stm32_container, "exti", OBJECT(exti_dev), NULL); stm32_init_periph(exti_dev, STM32_EXTI_PERIPH, 0x40010400, NULL); SysBusDevice *exti_busdev = SYS_BUS_DEVICE(exti_dev); sysbus_connect_irq(exti_busdev, 0, pic[STM32_EXTI0_IRQ]); sysbus_connect_irq(exti_busdev, 1, pic[STM32_EXTI1_IRQ]); sysbus_connect_irq(exti_busdev, 2, pic[STM32_EXTI2_IRQ]); sysbus_connect_irq(exti_busdev, 3, pic[STM32_EXTI3_IRQ]); sysbus_connect_irq(exti_busdev, 4, pic[STM32_EXTI4_IRQ]); sysbus_connect_irq(exti_busdev, 5, pic[STM32_EXTI9_5_IRQ]); sysbus_connect_irq(exti_busdev, 6, pic[STM32_EXTI15_10_IRQ]); sysbus_connect_irq(exti_busdev, 7, pic[STM32_PVD_IRQ]); sysbus_connect_irq(exti_busdev, 8, pic[STM32_RTCAlarm_IRQ]); sysbus_connect_irq(exti_busdev, 9, pic[STM32_OTG_FS_WKUP_IRQ]); DeviceState *afio_dev = qdev_create(NULL, TYPE_STM32_AFIO); qdev_prop_set_ptr(afio_dev, "stm32_rcc", rcc_dev); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[0]), "gpio[a]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[1]), "gpio[b]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[2]), "gpio[c]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[3]), "gpio[d]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[4]), "gpio[e]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[5]), "gpio[f]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(gpio_dev[6]), "gpio[g]", NULL); object_property_set_link(OBJECT(afio_dev), OBJECT(exti_dev), "exti", NULL); object_property_add_child(stm32_container, "afio", OBJECT(afio_dev), NULL); stm32_init_periph(afio_dev, STM32_AFIO_PERIPH, 0x40010000, NULL); stm32_create_uart_dev(stm32_container, STM32_UART1, 1, rcc_dev, gpio_dev, afio_dev, 0x40013800, pic[STM32_UART1_IRQ]); stm32_create_uart_dev(stm32_container, STM32_UART2, 2, rcc_dev, gpio_dev, afio_dev, 0x40004400, pic[STM32_UART2_IRQ]); stm32_create_uart_dev(stm32_container, STM32_UART3, 3, rcc_dev, gpio_dev, afio_dev, 0x40004800, pic[STM32_UART3_IRQ]); stm32_create_uart_dev(stm32_container, STM32_UART4, 4, rcc_dev, gpio_dev, afio_dev, 0x40004c00, pic[STM32_UART4_IRQ]); stm32_create_uart_dev(stm32_container, STM32_UART5, 5, rcc_dev, gpio_dev, afio_dev, 0x40005000, pic[STM32_UART5_IRQ]); }