static void ss_stream_out(SlaveBootInt *s) { uint8_t *data; uint32_t len; if (!DEP_AF_EX32(s->regs, SBI_MODE, SELECT)) { return; } /*FIXME: Impement JTAG, AXI interface */ while (!s->cs && s->rdwr) { if (IF_BURST(s->fifo.num)) { data = (uint8_t *) fifo_pop_buf(&s->fifo, SMAP_BURST_SIZE(s), &len); qemu_chr_fe_write(&s->chr, data, len); } if (IF_NON_BURST(s->fifo.num)) { data = (uint8_t *) fifo_pop_buf(&s->fifo, 4, &len); qemu_chr_fe_write(&s->chr, data, len); } ss_update_busy_line(s); if (s->busy_line) { break; } } }
static void ccid_card_vscard_send_msg(PassthruState *s, VSCMsgType type, uint32_t reader_id, const uint8_t *payload, uint32_t length) { VSCMsgHeader scr_msg_header; scr_msg_header.type = htonl(type); scr_msg_header.reader_id = htonl(reader_id); scr_msg_header.length = htonl(length); qemu_chr_fe_write(s->cs, (uint8_t *)&scr_msg_header, sizeof(VSCMsgHeader)); qemu_chr_fe_write(s->cs, payload, length); }
static void uart_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { SiFiveUARTState *s = opaque; uint32_t value = val64; unsigned char ch = value; switch (addr) { case SIFIVE_UART_TXFIFO: qemu_chr_fe_write(&s->chr, &ch, 1); update_irq(s); return; case SIFIVE_UART_IE: s->ie = val64; update_irq(s); return; case SIFIVE_UART_TXCTRL: s->txctrl = val64; return; case SIFIVE_UART_RXCTRL: s->rxctrl = val64; return; case SIFIVE_UART_DIV: s->div = val64; return; } hw_error("%s: bad write: addr=0x%x v=0x%x\n", __func__, (int)addr, (int)value); }
static void rng_egd_request_entropy(RngBackend *b, size_t size, EntropyReceiveFunc *receive_entropy, void *opaque) { RngEgd *s = RNG_EGD(b); RngRequest *req; req = g_malloc(sizeof(*req)); req->offset = 0; req->size = size; req->receive_entropy = receive_entropy; req->opaque = opaque; req->data = g_malloc(req->size); while (size > 0) { uint8_t header[2]; uint8_t len = MIN(size, 255); /* synchronous entropy request */ header[0] = 0x02; header[1] = len; qemu_chr_fe_write(s->chr, header, sizeof(header)); size -= len; } s->requests = g_slist_append(s->requests, req); }
static void uart_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { AlteraUART *s = opaque; uint32_t value = val64; unsigned char ch = value; addr >>= 2; addr &= 0x7; switch (addr) { case R_TXDATA: if (s->chr) { qemu_chr_fe_write(s->chr, &ch, 1); } s->regs[addr] = value; break; case R_RXDATA: case R_STATUS: /* No writeable bits */ break; default: s->regs[addr] = value; break; } uart_update_irq(s); }
static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct etrax_serial *s = opaque; unsigned char ch = value; D(CPUState *env = s->env); D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value)); addr >>= 2; switch (addr) { case RW_DOUT: qemu_chr_fe_write(s->chr, &ch, 1); s->regs[R_INTR] |= 3; s->pending_tx = 1; s->regs[addr] = value; break; case RW_ACK_INTR: if (s->pending_tx) { value &= ~1; s->pending_tx = 0; D(qemu_log("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR])); } s->regs[addr] = value; s->regs[R_INTR] &= ~value; D(printf("r_intr=%x\n", s->regs[R_INTR])); break; default: s->regs[addr] = value; break; } ser_update_irq(s); }
static void ser_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { ETRAXSerial *s = opaque; uint32_t value = val64; unsigned char ch = val64; D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value)); addr >>= 2; switch (addr) { case RW_DOUT: qemu_chr_fe_write(s->chr, &ch, 1); s->regs[R_INTR] |= 3; s->pending_tx = 1; s->regs[addr] = value; break; case RW_ACK_INTR: if (s->pending_tx) { value &= ~1; s->pending_tx = 0; D(qemu_log("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR])); } s->regs[addr] = value; s->regs[R_INTR] &= ~value; D(printf("r_intr=%x\n", s->regs[R_INTR])); break; default: s->regs[addr] = value; break; } ser_update_irq(s); }
/* * Triggered by SCLP's write_event_data * - write console data to character layer * returns < 0 if an error occurred */ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) { int ret = 0; const uint8_t *buf_offset; SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); if (!scon->chr) { /* If there's no backend, we can just say we consumed all data. */ return len; } buf_offset = buf; while (len > 0) { ret = qemu_chr_fe_write(scon->chr, buf, len); if (ret == 0) { /* a pty doesn't seem to be connected - no error */ len = 0; } else if (ret == -EAGAIN || (ret > 0 && ret < len)) { len -= ret; buf_offset += ret; } else { len = 0; } } return ret; }
static void uart_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { MilkymistUartState *s = opaque; unsigned char ch = value; trace_milkymist_uart_memory_write(addr, value); addr >>= 2; switch (addr) { case R_RXTX: if (s->chr) { qemu_chr_fe_write(s->chr, &ch, 1); } s->regs[R_STAT] |= STAT_TX_EVT; break; case R_DIV: case R_CTRL: case R_DBG: s->regs[addr] = value; break; case R_STAT: /* write one to clear bits */ s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT)); break; default: error_report("milkymist_uart: write access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } uart_update_irq(s); }
static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { UART *uart = opaque; unsigned char c = 0; addr &= 0xff; /* Unit registers */ switch (addr) { case DATA_OFFSET: c = value & 0xFF; qemu_chr_fe_write(uart->chr, &c, 1); return; case STATUS_OFFSET: /* Read Only */ return; case CONTROL_OFFSET: /* Not supported */ return; case SCALER_OFFSET: /* Not supported */ return; default: break; } trace_grlib_apbuart_writel_unknown(addr, value); }
static int rdmacm_mux_send(RdmaBackendDev *backend_dev, RdmaCmMuxMsg *msg) { int rc = 0; msg->hdr.msg_type = RDMACM_MUX_MSG_TYPE_REQ; trace_rdmacm_mux("send", msg->hdr.msg_type, msg->hdr.op_code); disable_rdmacm_mux_async(backend_dev); rc = qemu_chr_fe_write(backend_dev->rdmacm_mux.chr_be, (const uint8_t *)msg, sizeof(*msg)); if (rc != sizeof(*msg)) { enable_rdmacm_mux_async(backend_dev); rdma_error_report("Failed to send request to rdmacm_mux (rc=%d)", rc); return -EIO; } rc = rdmacm_mux_check_op_status(backend_dev->rdmacm_mux.chr_be); if (rc) { rdma_error_report("Failed to execute rdmacm_mux request %d (rc=%d)", msg->hdr.op_code, rc); } enable_rdmacm_mux_async(backend_dev); return 0; }
/* Callback function that's called when the guest sends us data */ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, ssize_t len) { VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); ssize_t ret; if (!vcon->chr) { /* If there's no backend, we can just say we consumed all data. */ return len; } ret = qemu_chr_fe_write(vcon->chr, buf, len); trace_virtio_console_flush_buf(port->id, len, ret); if (ret < len) { VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); /* * Ideally we'd get a better error code than just -1, but * that's what the chardev interface gives us right now. If * we had a finer-grained message, like -EPIPE, we could close * this connection. */ if (ret < 0) ret = 0; if (!k->is_console) { virtio_serial_throttle_port(port, true); if (!vcon->watch) { vcon->watch = qemu_chr_fe_add_watch(vcon->chr, G_IO_OUT, chr_write_unblocked, vcon); } } } return ret; }
static void xencons_send(struct XenConsole *con) { ssize_t len, size; size = con->buffer.size - con->buffer.consumed; if (qemu_chr_fe_backend_connected(&con->chr)) { len = qemu_chr_fe_write(&con->chr, con->buffer.data + con->buffer.consumed, size); } else { len = size; } if (len < 1) { if (!con->backlog) { con->backlog = 1; xen_pv_printf(&con->xendev, 1, "backlog piling up, nobody listening?\n"); } } else { buffer_advance(&con->buffer, len); if (con->backlog && len == size) { con->backlog = 0; xen_pv_printf(&con->xendev, 1, "backlog is gone\n"); } } }
static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) { UartState *s = opaque; int ret; /* instant drain the fifo when there's no back-end */ if (!s->chr) { s->tx_count = 0; } if (!s->tx_count) { return FALSE; } ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count); s->tx_count -= ret; memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count); if (s->tx_count) { int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT, cadence_uart_xmit, s); assert(r); } uart_update_status(s); return FALSE; }
static void uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { LM32UartState *s = opaque; unsigned char ch = value; trace_lm32_uart_memory_write(addr, value); addr >>= 2; switch (addr) { case R_RXTX: if (s->chr) { qemu_chr_fe_write(s->chr, &ch, 1); } break; case R_IER: case R_LCR: case R_MCR: case R_DIV: s->regs[addr] = value; break; case R_IIR: case R_LSR: case R_MSR: error_report("lm32_uart: write access to read only register 0x" TARGET_FMT_plx, addr << 2); break; default: error_report("lm32_uart: write access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } uart_update_irq(s); }
/* Callback function that's called when the guest sends us data */ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, ssize_t len) { VirtConsole *vcon = VIRTIO_CONSOLE(port); ssize_t ret; if (!qemu_chr_fe_backend_connected(&vcon->chr)) { /* If there's no backend, we can just say we consumed all data. */ return len; } ret = qemu_chr_fe_write(&vcon->chr, buf, len); trace_virtio_console_flush_buf(port->id, len, ret); if (ret < len) { VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); /* * Ideally we'd get a better error code than just -1, but * that's what the chardev interface gives us right now. If * we had a finer-grained message, like -EPIPE, we could close * this connection. */ if (ret < 0) ret = 0; /* XXX we should be queuing data to send later for the * console devices too rather than silently dropping * console data on EAGAIN. The Linux virtio-console * hvc driver though does sends with spinlocks held, * so if we enable throttling that'll stall the entire * guest kernel, not merely the process writing to the * console. * * While we could queue data for later write without * enabling throttling, this would result in the guest * being able to trigger arbitrary memory usage in QEMU * buffering data for later writes. * * So fixing this problem likely requires fixing the * Linux virtio-console hvc driver to not hold spinlocks * while writing, and instead merely block the process * that's writing. QEMU would then need some way to detect * if the guest had the fixed driver too, before we can * use throttling on host side. */ if (!k->is_console) { virtio_serial_throttle_port(port, true); if (!vcon->watch) { vcon->watch = qemu_chr_fe_add_watch(&vcon->chr, G_IO_OUT|G_IO_HUP, chr_write_unblocked, vcon); } } } return ret; }
static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size) { if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) { return; } while (size) { size -= qemu_chr_fe_write(s->chr, buf, size); } }
/* * Appelé quand une entrée de led reçoit une IT */ static void stm32_led_recvirq(void * opaque, int numPin, int level) { // the LED change state printf("La LED change d'état->%d\n", level); stm32_led_state *s = (stm32_led_state *) opaque; if(s->chr) { uint8_t buffer = (uint8_t)level; qemu_chr_fe_write(s->chr, &buffer, 1); } }
static void socket_read(void *opaque, const uint8_t *buf, int size) { SocketIdleData *data = opaque; g_assert_cmpint(size, ==, 1); g_assert_cmpint(*buf, ==, 'Z'); size = qemu_chr_fe_write(data->be, (const uint8_t *)"hello", 5); g_assert_cmpint(size, ==, 5); }
/* Called with chr_write_lock held. */ static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) { MuxChardev *d = MUX_CHARDEV(chr); int ret; if (!d->timestamps) { ret = qemu_chr_fe_write(&d->chr, buf, len); } else { int i; ret = 0; for (i = 0; i < len; i++) { if (d->linestart) { char buf1[64]; int64_t ti; int secs; ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); if (d->timestamps_start == -1) { d->timestamps_start = ti; } ti -= d->timestamps_start; secs = ti / 1000; snprintf(buf1, sizeof(buf1), "[%02d:%02d:%02d.%03d] ", secs / 3600, (secs / 60) % 60, secs % 60, (int)(ti % 1000)); /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(&d->chr, (uint8_t *)buf1, strlen(buf1)); d->linestart = 0; } ret += qemu_chr_fe_write(&d->chr, buf + i, 1); if (buf[i] == '\n') { d->linestart = 1; } } } return ret; }
static void debugcon_ioport_write(void *opaque, uint32_t addr, uint32_t val) { DebugconState *s = opaque; unsigned char ch = val; #ifdef DEBUG_DEBUGCON printf("debugcon: write addr=0x%04x val=0x%02x\n", addr, val); #endif qemu_chr_fe_write(s->chr, &ch, 1); }
static void uart_tx_pw(DepRegisterInfo *reg, uint64_t value) { XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque); if (s->cfg.use_tx) { unsigned char ch = value; qemu_chr_fe_write(&s->chr, &ch, 1); if (s->cfg.tx_interrupt) { qemu_irq_pulse(s->irq_tx); } } }
void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx) { LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev); unsigned char ch = jtx & 0xff; trace_lm32_juart_set_jtx(s->jtx); s->jtx = jtx; if (s->chr) { qemu_chr_fe_write(s->chr, &ch, 1); } }
/* Update TxRDY flag and set data if present and enabled. */ static void mcf_uart_do_tx(mcf_uart_state *s) { if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) { if (s->chr) qemu_chr_fe_write(s->chr, (unsigned char *)&s->tb, 1); s->sr |= MCF_UART_TxEMP; } if (s->tx_enabled) { s->sr |= MCF_UART_TxRDY; } else { s->sr &= ~MCF_UART_TxRDY; } }
static void char_ringbuf_test(void) { QemuOpts *opts; Chardev *chr; CharBackend be; char *data; int ret; opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label", 1, &error_abort); qemu_opt_set(opts, "backend", "ringbuf", &error_abort); qemu_opt_set(opts, "size", "5", &error_abort); chr = qemu_chr_new_from_opts(opts, NULL); g_assert_null(chr); qemu_opts_del(opts); opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label", 1, &error_abort); qemu_opt_set(opts, "backend", "ringbuf", &error_abort); qemu_opt_set(opts, "size", "2", &error_abort); chr = qemu_chr_new_from_opts(opts, &error_abort); g_assert_nonnull(chr); qemu_opts_del(opts); qemu_chr_fe_init(&be, chr, &error_abort); ret = qemu_chr_fe_write(&be, (void *)"buff", 4); g_assert_cmpint(ret, ==, 4); data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort); g_assert_cmpstr(data, ==, "ff"); g_free(data); data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort); g_assert_cmpstr(data, ==, ""); g_free(data); qemu_chr_fe_deinit(&be, true); /* check alias */ opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label", 1, &error_abort); qemu_opt_set(opts, "backend", "memory", &error_abort); qemu_opt_set(opts, "size", "2", &error_abort); chr = qemu_chr_new_from_opts(opts, NULL); g_assert_nonnull(chr); object_unparent(OBJECT(chr)); qemu_opts_del(opts); }
static void receive_from_chr_layer(SCLPConsoleLM *scon, const uint8_t *buf, int size) { assert(size == 1); if (*buf == '\r' || *buf == '\n') { scon->event.event_pending = true; return; } scon->buf[scon->length] = *buf; scon->length += 1; if (scon->echo) { qemu_chr_fe_write(scon->chr, buf, size); } }
static void qtest_send(CharDriverState *chr, const char *fmt, ...) { va_list ap; char buffer[1024]; size_t len; va_start(ap, fmt); len = vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); qemu_chr_fe_write(chr, (uint8_t *)buffer, len); if (qtest_log_fp && qtest_opened) { fprintf(qtest_log_fp, "%s", buffer); } }
static void char_stdio_test_subprocess(void) { Chardev *chr; CharBackend be; int ret; chr = qemu_chr_new("label", "stdio"); g_assert_nonnull(chr); qemu_chr_fe_init(&be, chr, &error_abort); qemu_chr_fe_set_open(&be, true); ret = qemu_chr_fe_write(&be, (void *)"buf", 4); g_assert_cmpint(ret, ==, 4); qemu_chr_fe_deinit(&be, true); }
static void chr_read(void *opaque, const uint8_t *buf, int size) { SCLPConsoleLM *scon = opaque; assert(size == 1); if (*buf == '\r' || *buf == '\n') { scon->event.event_pending = true; sclp_service_interrupt(0); return; } scon->buf[scon->length] = *buf; scon->length += 1; if (scon->echo) { qemu_chr_fe_write(scon->chr, buf, size); } }
static void continue_send(IPMIBmcExtern *ibe) { int ret; if (ibe->outlen == 0) { goto check_reset; } send: ret = qemu_chr_fe_write(&ibe->chr, ibe->outbuf + ibe->outpos, ibe->outlen - ibe->outpos); if (ret > 0) { ibe->outpos += ret; } if (ibe->outpos < ibe->outlen) { /* Not fully transmitted, try again in a 10ms */ timer_mod_ns(ibe->extern_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 10000000); } else { /* Sent */ ibe->outlen = 0; ibe->outpos = 0; if (!ibe->sending_cmd) { ibe->waiting_rsp = true; } else { ibe->sending_cmd = false; } check_reset: if (ibe->connected && ibe->send_reset) { /* Send the reset */ ibe->outbuf[0] = VM_CMD_RESET; ibe->outbuf[1] = VM_CMD_CHAR; ibe->outlen = 2; ibe->outpos = 0; ibe->send_reset = false; ibe->sending_cmd = true; goto send; } if (ibe->waiting_rsp) { /* Make sure we get a response within 4 seconds. */ timer_mod_ns(ibe->extern_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 4000000000ULL); } } return; }