static void virtconsole_realize(DeviceState *dev, Error **errp) { VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); VirtConsole *vcon = VIRTIO_CONSOLE(dev); VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev); if (port->id == 0 && !k->is_console) { error_setg(errp, "Port number 0 on virtio-serial devices reserved " "for virtconsole devices for backward compatibility."); return; } if (qemu_chr_fe_backend_connected(&vcon->chr)) { /* * For consoles we don't block guest data transfer just * because nothing is connected - we'll just let it go * whetherever the chardev wants - /dev/null probably. * * For serial ports we need 100% reliable data transfer * so we use the opened/closed signals from chardev to * trigger open/close of the device */ if (k->is_console) { qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, NULL, chr_be_change, vcon, NULL, true); virtio_serial_open(port); } else { qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, chr_event, chr_be_change, vcon, NULL, false); } } }
static void colo_compare_iothread(CompareState *s) { object_ref(OBJECT(s->iothread)); s->worker_context = iothread_get_g_main_context(s->iothread); qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read, compare_pri_chr_in, NULL, NULL, s, s->worker_context, true); qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read, compare_sec_chr_in, NULL, NULL, s, s->worker_context, true); colo_compare_timer_init(s); }
static void milkymist_uart_realize(DeviceState *dev, Error **errp) { MilkymistUartState *s = MILKYMIST_UART(dev); qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, s, NULL, true); }
static void usb_serial_realize(USBDevice *dev, Error **errp) { USBSerialState *s = USB_SERIAL_DEV(dev); Error *local_err = NULL; CharDriverState *chr = qemu_chr_fe_get_driver(&s->cs); usb_desc_create_serial(dev); usb_desc_init(dev); dev->auto_attach = 0; if (!chr) { error_setg(errp, "Property chardev is required"); return; } usb_check_attach(dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; } qemu_chr_fe_set_handlers(&s->cs, usb_serial_can_read, usb_serial_read, usb_serial_event, s, NULL, true); usb_serial_handle_reset(dev); if (chr->be_open && !dev->attached) { usb_device_attach(dev, &error_abort); } }
static void lm32_uart_realize(DeviceState *dev, Error **errp) { LM32UartState *s = LM32_UART(dev); qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, s, NULL, true); }
static void mcf_uart_realize(DeviceState *dev, Error **errp) { mcf_uart_state *s = MCF_UART(dev); qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive, mcf_uart_event, s, NULL, true); }
/* Create a S3C serial port, the port implementation is common to all * current s3c devices only differing in the I/O base address and number of * ports. */ struct s3c24xx_serial_dev_s * s3c24xx_serial_init(S3CState *soc, Chardev *chr, hwaddr base_addr, int irqn) { /* Initialise a serial port at the given port address */ s3c24xx_serial_dev *s = g_new0(s3c24xx_serial_dev, 1); /* initialise serial port context */ s->rx_irq = s3c24xx_get_irq(soc->irq, irqn); s->rx_level = s3c24xx_get_irq(soc->irq, irqn + 64); s->tx_irq = s3c24xx_get_irq(soc->irq, irqn + 1); s->tx_level = s3c24xx_get_irq(soc->irq, irqn + 1 + 64); /* Register the MMIO region. */ memory_region_init_io(&s->mmio, OBJECT(s), &s3c24xx_serial_ops, s, "s3c24xx.serial", 44); memory_region_add_subregion(get_system_memory(), base_addr, &s->mmio); qemu_chr_fe_set_handlers(&s->chr, s3c24xx_serial_can_receive, s3c24xx_serial_receive, s3c24xx_serial_event, NULL, s, NULL, true); return s; }
static void chr_closed_bh(void *opaque) { const char *name = opaque; NetClientState *ncs[MAX_QUEUE_NUM]; VhostUserState *s; Error *err = NULL; int queues; queues = qemu_find_net_clients_except(name, ncs, NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); assert(queues < MAX_QUEUE_NUM); s = DO_UPCAST(VhostUserState, nc, ncs[0]); qmp_set_link(name, false, &err); vhost_user_stop(queues, ncs); qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, NULL, opaque, NULL, true); if (err) { error_report_err(err); } }
static int uart_be_change(void *opaque) { SiFiveUARTState *s = opaque; qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, uart_be_change, s, NULL, true); return 0; }
static void virtconsole_enable_backend(VirtIOSerialPort *port, bool enable) { VirtConsole *vcon = VIRTIO_CONSOLE(port); if (!qemu_chr_fe_backend_connected(&vcon->chr)) { return; } if (enable) { VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, k->is_console ? NULL : chr_event, chr_be_change, vcon, NULL, false); } else { qemu_chr_fe_set_handlers(&vcon->chr, NULL, NULL, NULL, NULL, NULL, NULL, false); } }
static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp) { IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev); if (!qemu_chr_fe_backend_connected(&ibe->chr)) { error_setg(errp, "IPMI external bmc requires chardev attribute"); return; } qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive, chr_event, NULL, ibe, NULL, true); }
/* * Called from the main thread on the primary for packets * arriving over the socket from the secondary. */ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size) { CompareState *s = COLO_COMPARE(opaque); int ret; ret = net_fill_rstate(&s->sec_rs, buf, size); if (ret == -1) { qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL, NULL, NULL, true); error_report("colo-compare secondary_in error"); } }
static void xlx_iom_realize(DeviceState *dev, Error **errp) { XilinxUART *s = XILINX_IO_MODULE_UART(dev); unsigned int i, rmap; uint32_t *regmaps[3] = { &s->regs[0], &s->baud }; s->prefix = object_get_canonical_path(OBJECT(dev)); for (rmap = 0; rmap < ARRAY_SIZE(uart_reginfos); rmap++) { for (i = 0; i < uart_reginfo_sizes[rmap]; ++i) { DepRegisterInfo *r = &s->regs_infos[rmap][i]; *r = (DepRegisterInfo) { .data = (uint8_t *)®maps[rmap][i], .data_size = sizeof(uint32_t), .access = &uart_reginfos[rmap][i], .debug = XILINX_IO_MODULE_UART_ERR_DEBUG, .prefix = s->prefix, .opaque = s, }; memory_region_init_io(&r->mem, OBJECT(dev), &iom_uart_ops, r, r->access->name, 4); memory_region_add_subregion(&s->iomem[rmap], i * 4, &r->mem); } } if (s->cfg.use_rx || s->cfg.use_tx) { qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, NULL, s, NULL, true); } } static void xlx_iom_init(Object *obj) { XilinxUART *s = XILINX_IO_MODULE_UART(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); unsigned int i; s->regs_infos[0] = s->regs_info0; s->regs_infos[1] = s->regs_info1; for (i = 0; i < ARRAY_SIZE(s->iomem); i++) { char *region_name = g_strdup_printf("%s-%d", TYPE_XILINX_IO_MODULE_UART, i); memory_region_init_io(&s->iomem[i], obj, &iom_uart_ops, s, region_name, uart_reginfo_sizes[i] * 4); g_free(region_name); sysbus_init_mmio(sbd, &s->iomem[i]); } sysbus_init_irq(sbd, &s->irq_err); sysbus_init_irq(sbd, &s->irq_tx); sysbus_init_irq(sbd, &s->irq_rx); }
static void test_server_create_chr(TestServer *server, const gchar *opt) { gchar *chr_path; Chardev *chr; chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt); chr = qemu_chr_new(server->chr_name, chr_path); g_free(chr_path); qemu_chr_fe_init(&server->chr, chr, &error_abort); qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read, chr_event, NULL, server, NULL, true); }
/* * Create UART device. */ SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, Chardev *chr, qemu_irq irq) { SiFiveUARTState *s = g_malloc0(sizeof(SiFiveUARTState)); s->irq = irq; qemu_chr_fe_init(&s->chr, chr, &error_abort); qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, uart_be_change, s, NULL, true); memory_region_init_io(&s->mmio, NULL, &uart_ops, s, TYPE_SIFIVE_UART, SIFIVE_UART_MAX); memory_region_add_subregion(address_space, base, &s->mmio); return s; }
void mux_chr_set_handlers(Chardev *chr, GMainContext *context) { MuxChardev *d = MUX_CHARDEV(chr); /* Fix up the real driver with mux routines */ qemu_chr_fe_set_handlers(&d->chr, mux_chr_can_read, mux_chr_read, mux_chr_event, NULL, chr, context, true); }
static int altera_juart_init(SysBusDevice *dev) { AlteraJUARTState *s = ALTERA_JUART(dev); sysbus_init_irq(dev, &s->irq); memory_region_init_io(&s->mmio, OBJECT(s), &juart_ops, s, TYPE_ALTERA_JUART, 2 * 4); sysbus_init_mmio(dev, &s->mmio); qemu_chr_fe_set_handlers(&s->chr, juart_can_receive, juart_receive, juart_event, NULL, s, NULL, true); return 0; }
static void net_vhost_user_event(void *opaque, int event) { const char *name = opaque; NetClientState *ncs[MAX_QUEUE_NUM]; VhostUserState *s; Chardev *chr; Error *err = NULL; int queues; queues = qemu_find_net_clients_except(name, ncs, NET_CLIENT_DRIVER_NIC, MAX_QUEUE_NUM); assert(queues < MAX_QUEUE_NUM); s = DO_UPCAST(VhostUserState, nc, ncs[0]); chr = qemu_chr_fe_get_driver(&s->chr); trace_vhost_user_event(chr->label, event); switch (event) { case CHR_EVENT_OPENED: if (vhost_user_start(queues, ncs, &s->chr) < 0) { qemu_chr_fe_disconnect(&s->chr); return; } s->watch = qemu_chr_fe_add_watch(&s->chr, G_IO_HUP, net_vhost_user_watch, s); qmp_set_link(name, true, &err); s->started = true; break; case CHR_EVENT_CLOSED: /* a close event may happen during a read/write, but vhost * code assumes the vhost_dev remains setup, so delay the * stop & clear to idle. * FIXME: better handle failure in vhost code, remove bh */ if (s->watch) { AioContext *ctx = qemu_get_current_aio_context(); g_source_remove(s->watch); s->watch = 0; qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL, NULL, false); aio_bh_schedule_oneshot(ctx, chr_closed_bh, opaque); } break; } if (err) { error_report_err(err); } }
static int chr_be_change(void *opaque) { VirtConsole *vcon = opaque; VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon); VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); if (k->is_console) { qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, NULL, chr_be_change, vcon, NULL, true); } else { qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, chr_event, chr_be_change, vcon, NULL, false); } if (vcon->watch) { g_source_remove(vcon->watch); vcon->watch = qemu_chr_fe_add_watch(&vcon->chr, G_IO_OUT | G_IO_HUP, chr_write_unblocked, vcon); } return 0; }
static void redirector_chr_event(void *opaque, int event) { NetFilterState *nf = opaque; MirrorState *s = FILTER_REDIRECTOR(nf); switch (event) { case CHR_EVENT_CLOSED: qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL, NULL, NULL, true); break; default: break; } }
static void filter_redirector_setup(NetFilterState *nf, Error **errp) { MirrorState *s = FILTER_REDIRECTOR(nf); Chardev *chr; if (!s->indev && !s->outdev) { error_setg(errp, "filter redirector needs 'indev' or " "'outdev' at least one property set"); return; } else if (s->indev && s->outdev) { if (!strcmp(s->indev, s->outdev)) { error_setg(errp, "'indev' and 'outdev' could not be same " "for filter redirector"); return; } } net_socket_rs_init(&s->rs, redirector_rs_finalize); if (s->indev) { chr = qemu_chr_find(s->indev); if (chr == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "IN Device '%s' not found", s->indev); return; } if (!qemu_chr_fe_init(&s->chr_in, chr, errp)) { return; } qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read, redirector_chr_read, redirector_chr_event, nf, NULL, true); } if (s->outdev) { chr = qemu_chr_find(s->outdev); if (chr == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "OUT Device '%s' not found", s->outdev); return; } if (!qemu_chr_fe_init(&s->chr_out, chr, errp)) { return; } } }
static int console_init(SCLPEvent *event) { static bool console_available; SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); if (console_available) { error_report("Multiple line-mode operator consoles are not supported"); return -1; } console_available = true; qemu_chr_fe_set_handlers(&scon->chr, chr_can_read, chr_read, NULL, NULL, scon, NULL, true); return 0; }
static int net_vhost_user_init(NetClientState *peer, const char *device, const char *name, Chardev *chr, int queues) { Error *err = NULL; NetClientState *nc, *nc0 = NULL; VhostUserState *s; int i; assert(name); assert(queues > 0); for (i = 0; i < queues; i++) { nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s", i, chr->label); nc->queue_index = i; if (!nc0) { nc0 = nc; s = DO_UPCAST(VhostUserState, nc, nc); if (!qemu_chr_fe_init(&s->chr, chr, &err)) { error_report_err(err); return -1; } } } s = DO_UPCAST(VhostUserState, nc, nc0); do { if (qemu_chr_fe_wait_connected(&s->chr, &err) < 0) { error_report_err(err); return -1; } qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, NULL, nc0->name, NULL, true); } while (!s->started); assert(s->vhost_net); return 0; }
static int grlib_apbuart_init(SysBusDevice *dev) { UART *uart = GRLIB_APB_UART(dev); qemu_chr_fe_set_handlers(&uart->chr, grlib_apbuart_can_receive, grlib_apbuart_receive, grlib_apbuart_event, uart, NULL, true); sysbus_init_irq(dev, &uart->irq); memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart, "uart", UART_REG_SIZE); sysbus_init_mmio(dev, &uart->iomem); return 0; }
static int mad_init(RdmaBackendDev *backend_dev, CharBackend *mad_chr_be) { int ret; backend_dev->rdmacm_mux.chr_be = mad_chr_be; ret = qemu_chr_fe_backend_connected(backend_dev->rdmacm_mux.chr_be); if (!ret) { rdma_error_report("Missing chardev for MAD multiplexer"); return -EIO; } rdma_protected_qlist_init(&backend_dev->recv_mads_list); enable_rdmacm_mux_async(backend_dev); qemu_chr_fe_set_handlers(backend_dev->rdmacm_mux.chr_be, rdmacm_mux_can_receive, rdmacm_mux_read, NULL, NULL, backend_dev, NULL, true); return 0; }
static void redirector_to_filter(NetFilterState *nf, const uint8_t *buf, int len) { struct iovec iov = { .iov_base = (void *)buf, .iov_len = len, }; if (nf->direction == NET_FILTER_DIRECTION_ALL || nf->direction == NET_FILTER_DIRECTION_TX) { qemu_netfilter_pass_to_next(nf->netdev, 0, &iov, 1, nf); } if (nf->direction == NET_FILTER_DIRECTION_ALL || nf->direction == NET_FILTER_DIRECTION_RX) { qemu_netfilter_pass_to_next(nf->netdev->peer, 0, &iov, 1, nf); } } static int redirector_chr_can_read(void *opaque) { return REDIRECTOR_MAX_LEN; } static void redirector_chr_read(void *opaque, const uint8_t *buf, int size) { NetFilterState *nf = opaque; MirrorState *s = FILTER_REDIRECTOR(nf); int ret; ret = net_fill_rstate(&s->rs, buf, size); if (ret == -1) { qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL, NULL, NULL, true); } }
static int con_initialise(struct XenDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); int limit; if (xenstore_read_int(con->console, "ring-ref", &con->ring_ref) == -1) return -1; if (xenstore_read_int(con->console, "port", &con->xendev.remote_port) == -1) return -1; if (xenstore_read_int(con->console, "limit", &limit) == 0) con->buffer.max_capacity = limit; if (!xendev->dev) { xen_pfn_t mfn = con->ring_ref; con->sring = xenforeignmemory_map(xen_fmem, con->xendev.dom, PROT_READ|PROT_WRITE, 1, &mfn, NULL); } else { con->sring = xengnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom, con->ring_ref, PROT_READ|PROT_WRITE); } if (!con->sring) return -1; xen_be_bind_evtchn(&con->xendev); qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive, xencons_receive, NULL, NULL, con, NULL, true); xen_pv_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", con->ring_ref, con->xendev.remote_port, con->xendev.local_port, con->buffer.max_capacity); return 0; }
static void char_mux_test(void) { QemuOpts *opts; Chardev *chr, *base; char *data; FeHandler h1 = { 0, }, h2 = { 0, }; CharBackend chr_be1, chr_be2; opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label", 1, &error_abort); qemu_opt_set(opts, "backend", "ringbuf", &error_abort); qemu_opt_set(opts, "size", "128", &error_abort); qemu_opt_set(opts, "mux", "on", &error_abort); chr = qemu_chr_new_from_opts(opts, &error_abort); g_assert_nonnull(chr); qemu_opts_del(opts); qemu_chr_fe_init(&chr_be1, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be1, fe_can_read, fe_read, fe_event, NULL, &h1, NULL, true); qemu_chr_fe_init(&chr_be2, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, true); qemu_chr_fe_take_focus(&chr_be2); base = qemu_chr_find("mux-label-base"); g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; /* switch focus */ qemu_chr_be_write(base, (void *)"\1c", 2); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h2.read_count, ==, 0); g_assert_cmpint(h1.read_count, ==, 6); g_assert_cmpstr(h1.read_buf, ==, "hello"); h1.read_count = 0; /* remove first handler */ qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, NULL, true); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 0); qemu_chr_be_write(base, (void *)"\1c", 2); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; /* print help */ qemu_chr_be_write(base, (void *)"\1?", 2); data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort); g_assert_cmpint(strlen(data), !=, 0); g_free(data); qemu_chr_fe_deinit(&chr_be1, false); qemu_chr_fe_deinit(&chr_be2, true); }
static void ss_realize(DeviceState *dev, Error **errp) { SlaveBootInt *s = SBI(dev); const char *prefix = object_get_canonical_path(OBJECT(dev)); unsigned int i; const char *port_name; Chardev *chr; for (i = 0; i < ARRAY_SIZE(slave_boot_regs_info); ++i) { DepRegisterInfo *r = &s->regs_info[ slave_boot_regs_info[i].decode.addr / 4]; *r = (DepRegisterInfo) { .data = (uint8_t *)&s->regs[ slave_boot_regs_info[i].decode.addr / 4], .data_size = sizeof(uint32_t), .access = &slave_boot_regs_info[i], .debug = SBI_ERR_DEBUG, .prefix = prefix, .opaque = s, }; } port_name = g_strdup("smap_busy_b"); qdev_init_gpio_out_named(dev, &s->smap_busy, port_name, 1); g_free((gpointer) port_name); port_name = g_strdup("smap_in_b"); qdev_init_gpio_in_named(dev, smap_update, port_name, 2); g_free((gpointer) port_name); chr = qemu_chr_find("sbi"); qdev_prop_set_chr(dev, "chardev", chr); if (!qemu_chr_fe_get_driver(&s->chr)) { DPRINT("SBI interface not connected\n"); } else { qemu_chr_fe_set_handlers(&s->chr, ss_sbi_can_receive, ss_sbi_receive, NULL, NULL, s, NULL, true); } fifo_create8(&s->fifo, 1024 * 4); } static void ss_reset(DeviceState *dev) { SlaveBootInt *s = SBI(dev); uint32_t i; for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { dep_register_reset(&s->regs_info[i]); } fifo_reset(&s->fifo); s->busy_line = 1; qemu_set_irq(s->smap_busy, s->busy_line); ss_update_busy_line(s); sbi_update_irq(s); /* Note : cs always 0 when rp is not connected * i.e slave always respond to master data irrespective of * master state * * as rdwr is also 0, initial state of sbi is data load. Hack this bit * to become 1, when sbi changes to write mode. So, its assumed in * non remote-port model master should expect data when slave wishes * to send. */ }
static void boston_mach_init(MachineState *machine) { DeviceState *dev; BostonState *s; Error *err = NULL; const char *cpu_model; MemoryRegion *flash, *ddr, *ddr_low_alias, *lcd, *platreg; MemoryRegion *sys_mem = get_system_memory(); XilinxPCIEHost *pcie2; PCIDevice *ahci; DriveInfo *hd[6]; Chardev *chr; int fw_size, fit_err; bool is_64b; if ((machine->ram_size % G_BYTE) || (machine->ram_size > (2 * G_BYTE))) { error_report("Memory size must be 1GB or 2GB"); exit(1); } cpu_model = machine->cpu_model ?: "I6400"; dev = qdev_create(NULL, TYPE_MIPS_BOSTON); qdev_init_nofail(dev); s = BOSTON(dev); s->mach = machine; s->cps = g_new0(MIPSCPSState, 1); if (!cpu_supports_cps_smp(cpu_model)) { error_report("Boston requires CPUs which support CPS"); exit(1); } is_64b = cpu_supports_isa(cpu_model, ISA_MIPS64); object_initialize(s->cps, sizeof(MIPSCPSState), TYPE_MIPS_CPS); qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default()); object_property_set_str(OBJECT(s->cps), cpu_model, "cpu-model", &err); object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err); object_property_set_bool(OBJECT(s->cps), true, "realized", &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); exit(1); } sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); flash = g_new(MemoryRegion, 1); memory_region_init_rom_device(flash, NULL, &boston_flash_ops, s, "boston.flash", 128 * M_BYTE, &err); memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0); ddr = g_new(MemoryRegion, 1); memory_region_allocate_system_memory(ddr, NULL, "boston.ddr", machine->ram_size); memory_region_add_subregion_overlap(sys_mem, 0x80000000, ddr, 0); ddr_low_alias = g_new(MemoryRegion, 1); memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr", ddr, 0, MIN(machine->ram_size, (256 * M_BYTE))); memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0); xilinx_pcie_init(sys_mem, 0, 0x10000000, 32 * M_BYTE, 0x40000000, 1 * G_BYTE, get_cps_irq(s->cps, 2), false); xilinx_pcie_init(sys_mem, 1, 0x12000000, 32 * M_BYTE, 0x20000000, 512 * M_BYTE, get_cps_irq(s->cps, 1), false); pcie2 = xilinx_pcie_init(sys_mem, 2, 0x14000000, 32 * M_BYTE, 0x16000000, 1 * M_BYTE, get_cps_irq(s->cps, 0), true); platreg = g_new(MemoryRegion, 1); memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, "boston-platregs", 0x1000); memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0); if (!serial_hds[0]) { serial_hds[0] = qemu_chr_new("serial0", "null"); } s->uart = serial_mm_init(sys_mem, 0x17ffe000, 2, get_cps_irq(s->cps, 3), 10000000, serial_hds[0], DEVICE_NATIVE_ENDIAN); lcd = g_new(MemoryRegion, 1); memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8); memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0); chr = qemu_chr_new("lcd", "vc:320x240"); qemu_chr_fe_init(&s->lcd_display, chr, NULL); qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL, boston_lcd_event, s, NULL, true); ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus, PCI_DEVFN(0, 0), true, TYPE_ICH9_AHCI); g_assert(ARRAY_SIZE(hd) == ICH_AHCI(ahci)->ahci.ports); ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); ahci_ide_create_devs(ahci, hd); if (machine->firmware) { fw_size = load_image_targphys(machine->firmware, 0x1fc00000, 4 * M_BYTE); if (fw_size == -1) { error_printf("unable to load firmware image '%s'\n", machine->firmware); exit(1); } } else if (machine->kernel_filename) { fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s); if (fit_err) { error_printf("unable to load FIT image\n"); exit(1); } gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000, s->kernel_entry, s->fdt_base, is_64b); } else if (!qtest_enabled()) { error_printf("Please provide either a -kernel or -bios argument\n"); exit(1); } }