version 1.1.1.4, 2018/04/24 18:30:11
|
version 1.1.1.7, 2018/04/24 19:29:31
|
Line 11
|
Line 11
|
*/ |
*/ |
|
|
#include "qemu-char.h" |
#include "qemu-char.h" |
|
#include "qemu-error.h" |
|
#include "trace.h" |
#include "virtio-serial.h" |
#include "virtio-serial.h" |
|
|
typedef struct VirtConsole { |
typedef struct VirtConsole { |
Line 20 typedef struct VirtConsole {
|
Line 22 typedef struct VirtConsole {
|
|
|
|
|
/* Callback function that's called when the guest sends us data */ |
/* Callback function that's called when the guest sends us data */ |
static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) |
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) |
{ |
{ |
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
ssize_t ret; |
|
|
qemu_chr_write(vcon->chr, buf, len); |
ret = qemu_chr_fe_write(vcon->chr, buf, len); |
|
trace_virtio_console_flush_buf(port->id, len, ret); |
|
|
|
if (ret < 0) { |
|
/* |
|
* 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. Absent such error messages, the most we |
|
* can do is to return 0 here. |
|
* |
|
* This will prevent stray -1 values to go to |
|
* virtio-serial-bus.c and cause abort()s in |
|
* do_flush_queued_data(). |
|
*/ |
|
ret = 0; |
|
} |
|
return ret; |
|
} |
|
|
|
/* Callback function that's called when the guest opens the port */ |
|
static void guest_open(VirtIOSerialPort *port) |
|
{ |
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
|
|
qemu_chr_fe_open(vcon->chr); |
|
} |
|
|
|
/* Callback function that's called when the guest closes the port */ |
|
static void guest_close(VirtIOSerialPort *port) |
|
{ |
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
|
|
qemu_chr_fe_close(vcon->chr); |
} |
} |
|
|
/* Readiness of the guest to accept data on a port */ |
/* Readiness of the guest to accept data on a port */ |
Line 40 static void chr_read(void *opaque, const
|
Line 76 static void chr_read(void *opaque, const
|
{ |
{ |
VirtConsole *vcon = opaque; |
VirtConsole *vcon = opaque; |
|
|
|
trace_virtio_console_chr_read(vcon->port.id, size); |
virtio_serial_write(&vcon->port, buf, size); |
virtio_serial_write(&vcon->port, buf, size); |
} |
} |
|
|
Line 47 static void chr_event(void *opaque, int
|
Line 84 static void chr_event(void *opaque, int
|
{ |
{ |
VirtConsole *vcon = opaque; |
VirtConsole *vcon = opaque; |
|
|
|
trace_virtio_console_chr_event(vcon->port.id, event); |
switch (event) { |
switch (event) { |
case CHR_EVENT_OPENED: { |
case CHR_EVENT_OPENED: |
virtio_serial_open(&vcon->port); |
virtio_serial_open(&vcon->port); |
break; |
break; |
} |
|
case CHR_EVENT_CLOSED: |
case CHR_EVENT_CLOSED: |
virtio_serial_close(&vcon->port); |
virtio_serial_close(&vcon->port); |
break; |
break; |
} |
} |
} |
} |
|
|
/* Virtio Console Ports */ |
static int virtconsole_initfn(VirtIOSerialPort *port) |
static int virtconsole_initfn(VirtIOSerialDevice *dev) |
|
{ |
{ |
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev); |
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev, |
|
vcon->port.dev.info); |
|
|
port->info = dev->info; |
if (port->id == 0 && !info->is_console) { |
|
error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility."); |
port->is_console = true; |
return -1; |
|
} |
|
|
if (vcon->chr) { |
if (vcon->chr) { |
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, |
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, |
vcon); |
vcon); |
port->info->have_data = flush_buf; |
info->have_data = flush_buf; |
|
info->guest_open = guest_open; |
|
info->guest_close = guest_close; |
} |
} |
|
|
return 0; |
return 0; |
} |
} |
|
|
static int virtconsole_exitfn(VirtIOSerialDevice *dev) |
static int virtconsole_exitfn(VirtIOSerialPort *port) |
{ |
{ |
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev); |
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
|
if (vcon->chr) { |
if (vcon->chr) { |
port->info->have_data = NULL; |
/* |
qemu_chr_close(vcon->chr); |
* Instead of closing the chardev, free it so it can be used |
|
* for other purposes. |
|
*/ |
|
qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL); |
} |
} |
|
|
return 0; |
return 0; |
Line 92 static int virtconsole_exitfn(VirtIOSeri
|
Line 135 static int virtconsole_exitfn(VirtIOSeri
|
static VirtIOSerialPortInfo virtconsole_info = { |
static VirtIOSerialPortInfo virtconsole_info = { |
.qdev.name = "virtconsole", |
.qdev.name = "virtconsole", |
.qdev.size = sizeof(VirtConsole), |
.qdev.size = sizeof(VirtConsole), |
|
.is_console = true, |
.init = virtconsole_initfn, |
.init = virtconsole_initfn, |
.exit = virtconsole_exitfn, |
.exit = virtconsole_exitfn, |
.qdev.props = (Property[]) { |
.qdev.props = (Property[]) { |
DEFINE_PROP_UINT8("is_console", VirtConsole, port.is_console, 1), |
|
DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID), |
|
DEFINE_PROP_CHR("chardev", VirtConsole, chr), |
DEFINE_PROP_CHR("chardev", VirtConsole, chr), |
DEFINE_PROP_STRING("name", VirtConsole, port.name), |
|
DEFINE_PROP_END_OF_LIST(), |
DEFINE_PROP_END_OF_LIST(), |
}, |
}, |
}; |
}; |
Line 109 static void virtconsole_register(void)
|
Line 150 static void virtconsole_register(void)
|
} |
} |
device_init(virtconsole_register) |
device_init(virtconsole_register) |
|
|
/* Generic Virtio Serial Ports */ |
|
static int virtserialport_initfn(VirtIOSerialDevice *dev) |
|
{ |
|
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev); |
|
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); |
|
|
|
port->info = dev->info; |
|
|
|
if (vcon->chr) { |
|
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, |
|
vcon); |
|
port->info->have_data = flush_buf; |
|
} |
|
return 0; |
|
} |
|
|
|
static VirtIOSerialPortInfo virtserialport_info = { |
static VirtIOSerialPortInfo virtserialport_info = { |
.qdev.name = "virtserialport", |
.qdev.name = "virtserialport", |
.qdev.size = sizeof(VirtConsole), |
.qdev.size = sizeof(VirtConsole), |
.init = virtserialport_initfn, |
.init = virtconsole_initfn, |
.exit = virtconsole_exitfn, |
.exit = virtconsole_exitfn, |
.qdev.props = (Property[]) { |
.qdev.props = (Property[]) { |
DEFINE_PROP_UINT32("nr", VirtConsole, port.id, VIRTIO_CONSOLE_BAD_ID), |
|
DEFINE_PROP_CHR("chardev", VirtConsole, chr), |
DEFINE_PROP_CHR("chardev", VirtConsole, chr), |
DEFINE_PROP_STRING("name", VirtConsole, port.name), |
|
DEFINE_PROP_END_OF_LIST(), |
DEFINE_PROP_END_OF_LIST(), |
}, |
}, |
}; |
}; |