##########################################
# opengl probe, used by milkymist-tmu2
if test "$opengl" != "no" ; then
- opengl_libs="-lGL"
+ opengl_libs="-lGL -lX11"
cat > $TMPC << EOF
#include <X11/Xlib.h>
#include <GL/gl.h>
ETEXI
{
- .name = "memchar_write",
+ .name = "ringbuf_write",
.args_type = "device:s,data:s",
.params = "device data",
- .help = "Provide writing interface for CirMemCharDriver. Write"
- "'data' to it.",
- .mhandler.cmd = hmp_memchar_write,
+ .help = "Write to a ring buffer character device",
+ .mhandler.cmd = hmp_ringbuf_write,
},
STEXI
-@item memchar_write @var{device} @var{data}
-@findex memchar_write
-Provide writing interface for CirMemCharDriver. Write @var{data}
-to char device 'memory'.
+@item ringbuf_write @var{device} @var{data}
+@findex ringbuf_write
+Write @var{data} to ring buffer character device @var{device}.
+@var{data} must be a UTF-8 string.
ETEXI
{
- .name = "memchar_read",
+ .name = "ringbuf_read",
.args_type = "device:s,size:i",
.params = "device size",
- .help = "Provide read interface for CirMemCharDriver. Read from"
- "it and return the data with size.",
- .mhandler.cmd = hmp_memchar_read,
+ .help = "Read from a ring buffer character device",
+ .mhandler.cmd = hmp_ringbuf_read,
},
STEXI
-@item memchar_read @var{device}
-@findex memchar_read
-Provide read interface for CirMemCharDriver. Read from char device
-'memory' and return the data.
-
-@var{size} is the size of data want to read from. Refer to unencoded
-size of the raw data, would adjust to the init size of the memchar
-if the requested size is larger than it.
+@item ringbuf_read @var{device}
+@findex ringbuf_read
+Read and print up to @var{size} bytes from ring buffer character
+device @var{device}.
+Certain non-printable characters are printed \uXXXX, where XXXX is the
+character code in hexadecimal. Character \ is printed \\.
+Bug: can screw up when the buffer contains invalid UTF-8 sequences,
+NUL characters, after the ring buffer lost data, and when reading
+stops because the size limit is reached.
ETEXI
@end table
ETEXI
- {
- .name = "chardev-add",
- .args_type = "args:s",
- .params = "args",
- .help = "add chardev",
- .mhandler.cmd = hmp_chardev_add,
- },
-
-STEXI
-@item chardev_add args
-@findex chardev_add
-
-chardev_add accepts the same parameters as the -chardev command line switch.
-
-ETEXI
-
- {
- .name = "chardev-remove",
- .args_type = "id:s",
- .params = "id",
- .help = "remove chardev",
- .mhandler.cmd = hmp_chardev_remove,
- },
-
-STEXI
-@item chardev_remove id
-@findex chardev_remove
-
-Removes the chardev @var{id}.
-
-ETEXI
+HXCOMM Disabled for now, because it isn't built on top of QMP's chardev-add
+HXCOMM {
+HXCOMM .name = "chardev-add",
+HXCOMM .args_type = "args:s",
+HXCOMM .params = "args",
+HXCOMM .help = "add chardev",
+HXCOMM .mhandler.cmd = hmp_chardev_add,
+HXCOMM },
+HXCOMM
+HXCOMM STEXI
+HXCOMM @item chardev_add args
+HXCOMM @findex chardev_add
+HXCOMM
+HXCOMM chardev_add accepts the same parameters as the -chardev command line switch.
+HXCOMM
+HXCOMM ETEXI
+HXCOMM
+HXCOMM {
+HXCOMM .name = "chardev-remove",
+HXCOMM .args_type = "id:s",
+HXCOMM .params = "id",
+HXCOMM .help = "remove chardev",
+HXCOMM .mhandler.cmd = hmp_chardev_remove,
+HXCOMM },
+HXCOMM
+HXCOMM STEXI
+HXCOMM @item chardev_remove id
+HXCOMM @findex chardev_remove
+HXCOMM
+HXCOMM Removes the chardev @var{id}.
+HXCOMM
+HXCOMM ETEXI
{
.name = "info",
hmp_handle_error(mon, &errp);
}
-void hmp_memchar_write(Monitor *mon, const QDict *qdict)
+void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
{
- uint32_t size;
const char *chardev = qdict_get_str(qdict, "device");
const char *data = qdict_get_str(qdict, "data");
Error *errp = NULL;
- size = strlen(data);
- qmp_memchar_write(chardev, size, data, false, 0, &errp);
+ qmp_ringbuf_write(chardev, data, false, 0, &errp);
hmp_handle_error(mon, &errp);
}
-void hmp_memchar_read(Monitor *mon, const QDict *qdict)
+void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
{
uint32_t size = qdict_get_int(qdict, "size");
const char *chardev = qdict_get_str(qdict, "device");
- MemCharRead *meminfo;
+ char *data;
Error *errp = NULL;
+ int i;
- meminfo = qmp_memchar_read(chardev, size, false, 0, &errp);
+ data = qmp_ringbuf_read(chardev, size, false, 0, &errp);
if (errp) {
monitor_printf(mon, "%s\n", error_get_pretty(errp));
error_free(errp);
return;
}
- if (meminfo->count > 0) {
- monitor_printf(mon, "%s\n", meminfo->data);
- }
+ for (i = 0; data[i]; i++) {
+ unsigned char ch = data[i];
- qapi_free_MemCharRead(meminfo);
+ if (ch == '\\') {
+ monitor_printf(mon, "\\\\");
+ } else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
+ monitor_printf(mon, "\\u%04X", ch);
+ } else {
+ monitor_printf(mon, "%c", ch);
+ }
+
+ }
+ monitor_printf(mon, "\n");
+ g_free(data);
}
static void hmp_cont_cb(void *opaque, int err)
void hmp_cpu(Monitor *mon, const QDict *qdict);
void hmp_memsave(Monitor *mon, const QDict *qdict);
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
-void hmp_memchar_write(Monitor *mon, const QDict *qdict);
-void hmp_memchar_read(Monitor *mon, const QDict *qdict);
+void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
+void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
void hmp_cont(Monitor *mon, const QDict *qdict);
void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
return retval;
}
-static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
+static int put_fid(V9fsPDU *pdu, V9fsFidState *fidp)
{
BUG_ON(!fidp->ref);
fidp->ref--;
pdu->s->migration_blocker = NULL;
}
}
- free_fid(pdu, fidp);
+ return free_fid(pdu, fidp);
}
+ return 0;
}
static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid)
* free the fid.
*/
fidp->ref++;
- err = offset;
-
- put_fid(pdu, fidp);
+ err = put_fid(pdu, fidp);
+ if (!err) {
+ err = offset;
+ }
out_nofid:
complete_pdu(s, pdu, err);
}
set_phy_ctrl(E1000State *s, int index, uint16_t val)
{
if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
- qemu_get_queue(s->nic)->link_down = true;
e1000_link_down(s);
s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
DBGOUT(PHY, "Start link auto negotiation\n");
e1000_autoneg_timer(void *opaque)
{
E1000State *s = opaque;
- qemu_get_queue(s->nic)->link_down = false;
- e1000_link_up(s);
+ if (!qemu_get_queue(s->nic)->link_down) {
+ e1000_link_up(s);
+ }
s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
DBGOUT(PHY, "Auto negotiation is completed\n");
}
{
E1000State *s = qemu_get_nic_opaque(nc);
- return (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
+ return (s->mac_reg[STATUS] & E1000_STATUS_LU) &&
+ (s->mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(s, 1);
}
static uint64_t rx_desc_base(E1000State *s)
size_t desc_size;
size_t total_size;
- if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
+ if (!(s->mac_reg[STATUS] & E1000_STATUS_LU)) {
+ return -1;
+ }
+
+ if (!(s->mac_reg[RCTL] & E1000_RCTL_EN)) {
return -1;
+ }
/* Pad to minimum Ethernet frame length */
if (size < sizeof(min_buf)) {
return version_id == 1;
}
+static void e1000_pre_save(void *opaque)
+{
+ E1000State *s = opaque;
+ NetClientState *nc = qemu_get_queue(s->nic);
+ /*
+ * If link is down and auto-negotiation is ongoing, complete
+ * auto-negotiation immediately. This allows is to look at
+ * MII_SR_AUTONEG_COMPLETE to infer link status on load.
+ */
+ if (nc->link_down &&
+ s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
+ s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG) {
+ s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+ }
+}
+
static int e1000_post_load(void *opaque, int version_id)
{
E1000State *s = opaque;
NetClientState *nc = qemu_get_queue(s->nic);
/* nc.link_down can't be migrated, so infer link_down according
- * to link status bit in mac_reg[STATUS] */
+ * to link status bit in mac_reg[STATUS].
+ * Alternatively, restart link negotiation if it was in progress. */
nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
+ if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
+ s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
+ !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
+ nc->link_down = false;
+ qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ }
return 0;
}
.version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .pre_save = e1000_pre_save,
.post_load = e1000_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, E1000State),
#define BSWAP_H
#include "config-host.h"
-
#include <inttypes.h>
+#include <limits.h>
#include "fpu/softfloat.h"
#ifdef CONFIG_MACHINE_BSWAP_H
static inline unsigned long leul_to_cpu(unsigned long v)
{
- return le_bswap(v, HOST_LONG_BITS);
+ /* In order to break an include loop between here and
+ qemu-common.h, don't rely on HOST_LONG_BITS. */
+#if ULONG_MAX == UINT32_MAX
+ return le_bswap(v, 32);
+#elif ULONG_MAX == UINT64_MAX
+ return le_bswap(v, 64);
+#else
+# error Unknown sizeof long
+#endif
}
#undef le_bswap
#
# An enumeration of data format.
#
-# @utf8: The data format is 'utf8'.
+# @utf8: Data is a UTF-8 string (RFC 3629)
#
-# @base64: The data format is 'base64'.
+# @base64: Data is Base64 encoded binary (RFC 3548)
#
# Since: 1.4
##
'data': [ 'utf8', 'base64' ] }
##
-# @memchar-write:
+# @ringbuf-write:
#
-# Provide writing interface for memchardev. Write data to char
-# device 'memory'.
+# Write to a ring buffer character device.
#
-# @device: the name of the memory char device.
+# @device: the ring buffer character device name
#
-# @size: the size to write in bytes.
+# @data: data to write
#
-# @data: the source data write to memchar.
-#
-# @format: #optional the format of the data write to chardev 'memory',
-# by default is 'utf8'.
+# @format: #optional data encoding (default 'utf8').
+# - base64: data must be base64 encoded text. Its binary
+# decoding gets written.
+# Bug: invalid base64 is currently not rejected.
+# Whitespace *is* invalid.
+# - utf8: data's UTF-8 encoding is written
+# - data itself is always Unicode regardless of format, like
+# any other string.
#
# Returns: Nothing on success
-# If @device is not a valid char device, DeviceNotFound
#
# Since: 1.4
##
-{ 'command': 'memchar-write',
- 'data': {'device': 'str', 'size': 'int', 'data': 'str',
+{ 'command': 'ringbuf-write',
+ 'data': {'device': 'str', 'data': 'str',
'*format': 'DataFormat'} }
##
-# @MemCharRead
-#
-# Result of QMP command memchar-read.
-#
-# @data: The data read from memchar as string.
-#
-# @count: The numbers of bytes read from.
-#
-# Since: 1.4
-##
-{ 'type': 'MemCharRead',
- 'data': { 'data': 'str', 'count': 'int' } }
-
-##
-# @memchar-read:
+# @ringbuf-read:
#
-# Provide read interface for memchardev. Read from the char
-# device 'memory' and return the data.
+# Read from a ring buffer character device.
#
-# @device: the name of the memory char device.
+# @device: the ring buffer character device name
#
-# @size: the size to read in bytes.
+# @size: how many bytes to read at most
#
-# @format: #optional the format of the data want to read from
-# memchardev, by default is 'utf8'.
+# @format: #optional data encoding (default 'utf8').
+# - base64: the data read is returned in base64 encoding.
+# - utf8: the data read is interpreted as UTF-8.
+# Bug: can screw up when the buffer contains invalid UTF-8
+# sequences, NUL characters, after the ring buffer lost
+# data, and when reading stops because the size limit is
+# reached.
+# - The return value is always Unicode regardless of format,
+# like any other string.
#
-# Returns: @MemCharRead
-# If @device is not a valid memchr device, DeviceNotFound
+# Returns: data read from the device
#
# Since: 1.4
##
-{ 'command': 'memchar-read',
+{ 'command': 'ringbuf-read',
'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
- 'returns': 'MemCharRead' }
+ 'returns': 'str' }
##
# @CommandInfo:
#include "ui/qemu-spice.h"
#define READ_BUF_LEN 4096
-#define CBUFF_SIZE 65536
/***********************************************************/
/* character device */
}
/*********************************************************/
-/*CircularMemory chardev*/
+/* Ring buffer chardev */
typedef struct {
size_t size;
size_t prod;
size_t cons;
uint8_t *cbuf;
-} CirMemCharDriver;
+} RingBufCharDriver;
-static bool cirmem_chr_is_empty(const CharDriverState *chr)
+static size_t ringbuf_count(const CharDriverState *chr)
{
- const CirMemCharDriver *d = chr->opaque;
+ const RingBufCharDriver *d = chr->opaque;
- return d->cons == d->prod;
+ return d->prod - d->cons;
}
-static size_t qemu_chr_cirmem_count(const CharDriverState *chr)
+static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
- const CirMemCharDriver *d = chr->opaque;
-
- return (d->prod - d->cons);
-}
-
-static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
- CirMemCharDriver *d = chr->opaque;
+ RingBufCharDriver *d = chr->opaque;
int i;
if (!buf || (len < 0)) {
}
for (i = 0; i < len; i++ ) {
- /* Avoid writing the IAC information to the queue. */
- if ((unsigned char)buf[i] == IAC) {
- continue;
- }
-
- d->cbuf[d->prod++ % d->size] = buf[i];
- if ((d->prod - d->cons) > d->size) {
+ d->cbuf[d->prod++ & (d->size - 1)] = buf[i];
+ if (d->prod - d->cons > d->size) {
d->cons = d->prod - d->size;
}
}
return 0;
}
-static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
+static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len)
{
- CirMemCharDriver *d = chr->opaque;
+ RingBufCharDriver *d = chr->opaque;
int i;
- for (i = 0; i < len && !cirmem_chr_is_empty(chr); i++) {
- buf[i] = d->cbuf[d->cons++ % d->size];
+ for (i = 0; i < len && d->cons != d->prod; i++) {
+ buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
}
return i;
}
-static void cirmem_chr_close(struct CharDriverState *chr)
+static void ringbuf_chr_close(struct CharDriverState *chr)
{
- CirMemCharDriver *d = chr->opaque;
+ RingBufCharDriver *d = chr->opaque;
g_free(d->cbuf);
g_free(d);
chr->opaque = NULL;
}
-static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
{
CharDriverState *chr;
- CirMemCharDriver *d;
+ RingBufCharDriver *d;
chr = g_malloc0(sizeof(CharDriverState));
d = g_malloc(sizeof(*d));
- d->size = qemu_opt_get_number(opts, "maxcapacity", 0);
+ d->size = qemu_opt_get_size(opts, "size", 0);
if (d->size == 0) {
- d->size = CBUFF_SIZE;
+ d->size = 65536;
}
/* The size must be power of 2 */
if (d->size & (d->size - 1)) {
- fprintf(stderr, "chardev: size of memory device must be power of 2\n");
+ error_report("size of ringbuf device must be power of two");
goto fail;
}
d->cbuf = g_malloc0(d->size);
chr->opaque = d;
- chr->chr_write = cirmem_chr_write;
- chr->chr_close = cirmem_chr_close;
+ chr->chr_write = ringbuf_chr_write;
+ chr->chr_close = ringbuf_chr_close;
return chr;
return NULL;
}
-static bool qemu_is_chr(const CharDriverState *chr, const char *filename)
+static bool chr_is_ringbuf(const CharDriverState *chr)
{
- return strcmp(chr->filename, filename);
+ return chr->chr_write == ringbuf_chr_write;
}
-void qmp_memchar_write(const char *device, int64_t size,
- const char *data, bool has_format,
- enum DataFormat format,
+void qmp_ringbuf_write(const char *device, const char *data,
+ bool has_format, enum DataFormat format,
Error **errp)
{
CharDriverState *chr;
- guchar *write_data;
+ const uint8_t *write_data;
int ret;
- gsize write_count;
+ size_t write_count;
chr = qemu_chr_find(device);
if (!chr) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+ error_setg(errp, "Device '%s' not found", device);
return;
}
- if (qemu_is_chr(chr, "memory")) {
- error_setg(errp,"%s is not memory char device", device);
+ if (!chr_is_ringbuf(chr)) {
+ error_setg(errp,"%s is not a ringbuf device", device);
return;
}
- write_count = (gsize)size;
-
if (has_format && (format == DATA_FORMAT_BASE64)) {
write_data = g_base64_decode(data, &write_count);
} else {
write_data = (uint8_t *)data;
+ write_count = strlen(data);
}
- ret = cirmem_chr_write(chr, write_data, write_count);
+ ret = ringbuf_chr_write(chr, write_data, write_count);
+
+ if (write_data != (uint8_t *)data) {
+ g_free((void *)write_data);
+ }
if (ret < 0) {
error_setg(errp, "Failed to write to device %s", device);
}
}
-MemCharRead *qmp_memchar_read(const char *device, int64_t size,
- bool has_format, enum DataFormat format,
- Error **errp)
+char *qmp_ringbuf_read(const char *device, int64_t size,
+ bool has_format, enum DataFormat format,
+ Error **errp)
{
CharDriverState *chr;
- guchar *read_data;
- MemCharRead *meminfo;
+ uint8_t *read_data;
size_t count;
+ char *data;
chr = qemu_chr_find(device);
if (!chr) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+ error_setg(errp, "Device '%s' not found", device);
return NULL;
}
- if (qemu_is_chr(chr, "memory")) {
- error_setg(errp,"%s is not memory char device", device);
+ if (!chr_is_ringbuf(chr)) {
+ error_setg(errp,"%s is not a ringbuf device", device);
return NULL;
}
return NULL;
}
- meminfo = g_malloc0(sizeof(MemCharRead));
-
- count = qemu_chr_cirmem_count(chr);
- if (count == 0) {
- meminfo->data = g_strdup("");
- return meminfo;
- }
-
+ count = ringbuf_count(chr);
size = size > count ? count : size;
- read_data = g_malloc0(size + 1);
+ read_data = g_malloc(size + 1);
- meminfo->count = cirmem_chr_read(chr, read_data, size);
+ ringbuf_chr_read(chr, read_data, size);
if (has_format && (format == DATA_FORMAT_BASE64)) {
- meminfo->data = g_base64_encode(read_data, (size_t)meminfo->count);
+ data = g_base64_encode(read_data, size);
+ g_free(read_data);
} else {
- meminfo->data = (char *)read_data;
+ /*
+ * FIXME should read only complete, valid UTF-8 characters up
+ * to @size bytes. Invalid sequences should be replaced by a
+ * suitable replacement character. Except when (and only
+ * when) ring buffer lost characters since last read, initial
+ * continuation characters should be dropped.
+ */
+ read_data[size] = 0;
+ data = (char *)read_data;
}
- return meminfo;
+ return data;
}
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
qemu_opt_set(opts, "path", filename);
return opts;
}
- if (strstart(filename, "memory", &p)) {
- qemu_opt_set(opts, "backend", "memory");
- qemu_opt_set(opts, "maxcapacity", p);
- return opts;
- }
if (strstart(filename, "file:", &p)) {
qemu_opt_set(opts, "backend", "file");
qemu_opt_set(opts, "path", p);
{ .name = "udp", .open = qemu_chr_open_udp },
{ .name = "msmouse", .open = qemu_chr_open_msmouse },
{ .name = "vc", .open = text_console_init },
- { .name = "memory", .open = qemu_chr_open_cirmemchr },
+ { .name = "memory", .open = qemu_chr_open_ringbuf },
#ifdef _WIN32
{ .name = "file", .open = qemu_chr_open_win_file_out },
{ .name = "pipe", .open = qemu_chr_open_win_pipe },
.name = "debug",
.type = QEMU_OPT_NUMBER,
},{
- .name = "maxcapacity",
- .type = QEMU_OPT_NUMBER,
+ .name = "size",
+ .type = QEMU_OPT_SIZE,
},
{ /* end of list */ }
},
"-chardev msmouse,id=id[,mux=on|off]\n"
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
" [,mux=on|off]\n"
- "-chardev memory,id=id,maxcapacity=maxcapacity\n"
+ "-chardev ringbuf,id=id[,size=size]\n"
"-chardev file,id=id,path=path[,mux=on|off]\n"
"-chardev pipe,id=id,path=path[,mux=on|off]\n"
#ifdef _WIN32
@option{udp},
@option{msmouse},
@option{vc},
-@option{memory},
+@option{ringbuf},
@option{file},
@option{pipe},
@option{console},
@option{cols} and @option{rows} specify that the console be sized to fit a text
console with the given dimensions.
-@item -chardev memory ,id=@var{id} ,maxcapacity=@var{maxcapacity}
+@item -chardev ringbuf ,id=@var{id} [,size=@var{size}]
-Create a circular buffer with fixed size indicated by optionally @option{maxcapacity}
-which will be default 64K if it is not given.
-
-@option{maxcapacity} specifies the max capacity of the size of circular buffer
-to create. Should be power of 2.
+Create a ring buffer with fixed size @option{size}.
+@var{size} must be a power of two, and defaults to @code{64K}).
@item -chardev file ,id=@var{id} ,path=@var{path}
EQMP
{
- .name = "memchar-write",
- .args_type = "device:s,size:i,data:s,format:s?",
- .mhandler.cmd_new = qmp_marshal_input_memchar_write,
+ .name = "ringbuf-write",
+ .args_type = "device:s,data:s,format:s?",
+ .mhandler.cmd_new = qmp_marshal_input_ringbuf_write,
},
SQMP
-memchar-write
+ringbuf-write
-------------
-Provide writing interface for CirMemCharDriver. Write data to memory
-char device.
+Write to a ring buffer character device.
Arguments:
-- "device": the name of the char device, must be unique (json-string)
-- "size": the memory size, in bytes, should be power of 2 (json-int)
-- "data": the source data write to memory (json-string)
-- "format": the data format write to memory, default is
- utf8. (json-string, optional)
- - Possible values: "utf8", "base64"
+- "device": ring buffer character device name (json-string)
+- "data": data to write (json-string)
+- "format": data format (json-string, optional)
+ - Possible values: "utf8" (default), "base64"
+ Bug: invalid base64 is currently not rejected.
+ Whitespace *is* invalid.
Example:
--> { "execute": "memchar-write",
- "arguments": { "device": foo,
- "size": 8,
+-> { "execute": "ringbuf-write",
+ "arguments": { "device": "foo",
"data": "abcdefgh",
"format": "utf8" } }
<- { "return": {} }
EQMP
{
- .name = "memchar-read",
+ .name = "ringbuf-read",
.args_type = "device:s,size:i,format:s?",
- .mhandler.cmd_new = qmp_marshal_input_memchar_read,
+ .mhandler.cmd_new = qmp_marshal_input_ringbuf_read,
},
SQMP
-memchar-read
+ringbuf-read
-------------
-Provide read interface for CirMemCharDriver. Read from the char
-device memory and return the data with size.
+Read from a ring buffer character device.
Arguments:
-- "device": the name of the char device, must be unique (json-string)
-- "size": the memory size wanted to read in bytes (refer to unencoded
- size of the raw data), would adjust to the init size of the
- memchar if the requested size is larger than it. (json-int)
-- "format": the data format write to memchardev, default is
- utf8. (json-string, optional)
- - Possible values: "utf8", "base64"
+- "device": ring buffer character device name (json-string)
+- "size": how many bytes to read at most (json-int)
+ - Number of data bytes, not number of characters in encoded data
+- "format": data format (json-string, optional)
+ - Possible values: "utf8" (default), "base64"
+ - Naturally, format "utf8" works only when the ring buffer
+ contains valid UTF-8 text. Invalid UTF-8 sequences get
+ replaced. Bug: replacement doesn't work. Bug: can screw
+ up on encountering NUL characters, after the ring buffer
+ lost data, and when reading stops because the size limit
+ is reached.
Example:
--> { "execute": "memchar-read",
- "arguments": { "device": foo,
+-> { "execute": "ringbuf-read",
+ "arguments": { "device": "foo",
"size": 1000,
"format": "utf8" } }
-<- { "return": { "data": "data string...", "count": 1000 } }
+<- {"return": "abcdefgh"}
EQMP
return gen_ldst(s, opsize, tmp, val, what);
}
-/* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
+/* Generate code to load/store a value from/into an EA. If VAL > 0 this is
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
ADDRP is non-null for readwrite operands. */
static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
{ "Zabovedot", 0x1af},
{ "zacute", 0x1bc},
{ "Zacute", 0x1ac},
+{ "Odoubleacute", 0x1d5},
+{ "Udoubleacute", 0x1db},
{ "cacute", 0x1e6},
{ "Cacute", 0x1c6},
{ "nacute", 0x1f1},
{ "Nacute", 0x1d1},
+{ "odoubleacute", 0x1f5},
+{ "udoubleacute", 0x1fb},
/* modifiers */
{"ISO_Level3_Shift", 0xfe03}, /* XK_ISO_Level3_Shift */
{
int i;
size_t done;
+
+ if (!sbytes) {
+ return;
+ }
assert(dst->nalloc != -1);
for (i = 0, done = 0; done < sbytes && i < src_cnt; i++) {
if (soffset < src_iov[i].iov_len) {