]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/char/sclpconsole.c
target/arm: Implement SVE2 saturating/rounding bitwise shift left (predicated)
[mirror_qemu.git] / hw / char / sclpconsole.c
index fca105db4ea53679710b24ccf4c63decdb650c39..c36b5722224934c16ea93bf2942fb435177f947b 100644 (file)
  *
  */
 
-#include <hw/qdev.h>
+#include "qemu/osdep.h"
 #include "qemu/thread.h"
 #include "qemu/error-report.h"
+#include "qemu/module.h"
 
 #include "hw/s390x/sclp.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
 #include "hw/s390x/event-facility.h"
-#include "sysemu/char.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
 
 typedef struct ASCIIConsoleData {
     EventBufferHeader ebh;
-    char data[0];
+    char data[];
 } QEMU_PACKED ASCIIConsoleData;
 
 /* max size for ASCII data in 4K SCCB page */
 #define SIZE_BUFFER_VT220 4080
 
-typedef struct SCLPConsole {
+struct SCLPConsole {
     SCLPEvent event;
-    CharDriverState *chr;
+    CharBackend chr;
     uint8_t iov[SIZE_BUFFER_VT220];
     uint32_t iov_sclp;      /* offset in buf for SCLP read operation       */
     uint32_t iov_bs;        /* offset in buf for char layer read operation */
     uint32_t iov_data_len;  /* length of byte stream in buffer             */
     uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP     */
-} SCLPConsole;
+    bool notify;            /* qemu_notify_event() req'd if true           */
+};
+typedef struct SCLPConsole SCLPConsole;
+
+#define TYPE_SCLP_CONSOLE "sclpconsole"
+DECLARE_INSTANCE_CHECKER(SCLPConsole, SCLP_CONSOLE,
+                         TYPE_SCLP_CONSOLE)
 
 /* character layer call-back functions */
 
@@ -44,8 +55,12 @@ typedef struct SCLPConsole {
 static int chr_can_read(void *opaque)
 {
     SCLPConsole *scon = opaque;
+    int avail = SIZE_BUFFER_VT220 - scon->iov_data_len;
 
-    return SIZE_BUFFER_VT220 - scon->iov_data_len;
+    if (avail == 0) {
+        scon->notify = true;
+    }
+    return avail;
 }
 
 /* Send data from a char device over to the guest */
@@ -73,12 +88,12 @@ static bool can_handle_event(uint8_t type)
     return type == SCLP_EVENT_ASCII_CONSOLE_DATA;
 }
 
-static unsigned int send_mask(void)
+static sccb_mask_t send_mask(void)
 {
     return SCLP_EVENT_MASK_MSG_ASCII;
 }
 
-static unsigned int receive_mask(void)
+static sccb_mask_t receive_mask(void)
 {
     return SCLP_EVENT_MASK_MSG_ASCII;
 }
@@ -89,7 +104,7 @@ static unsigned int receive_mask(void)
 static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
                              int avail)
 {
-    SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event);
+    SCLPConsole *cons = SCLP_CONSOLE(event);
 
     /* first byte is hex 0 saying an ascii string follows */
     *buf++ = '\0';
@@ -113,6 +128,10 @@ static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
         cons->iov_sclp += avail;
         /* more data pending */
     }
+    if (cons->notify) {
+        cons->notify = false;
+        qemu_notify_event();
+    }
 }
 
 static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
@@ -147,14 +166,16 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
 static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
                                   size_t len)
 {
-    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
+    SCLPConsole *scon = SCLP_CONSOLE(event);
 
-    if (!scon->chr) {
+    if (!qemu_chr_fe_backend_connected(&scon->chr)) {
         /* If there's no backend, we can just say we consumed all data. */
         return len;
     }
 
-    return qemu_chr_fe_write_all(scon->chr, buf, len);
+    /* XXX this blocks entire thread. Rewrite to use
+     * qemu_chr_fe_write and background I/O callbacks */
+    return qemu_chr_fe_write_all(&scon->chr, buf, len);
 }
 
 static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
@@ -204,17 +225,15 @@ static int console_init(SCLPEvent *event)
 {
     static bool console_available;
 
-    SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
+    SCLPConsole *scon = SCLP_CONSOLE(event);
 
     if (console_available) {
         error_report("Multiple VT220 operator consoles are not supported");
         return -1;
     }
     console_available = true;
-    if (scon->chr) {
-        qemu_chr_add_handlers(scon->chr, chr_can_read,
-                              chr_read, NULL, scon);
-    }
+    qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
+                             chr_read, NULL, NULL, scon, NULL, true);
 
     return 0;
 }
@@ -222,18 +241,14 @@ static int console_init(SCLPEvent *event)
 static void console_reset(DeviceState *dev)
 {
    SCLPEvent *event = SCLP_EVENT(dev);
-   SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
+   SCLPConsole *scon = SCLP_CONSOLE(event);
 
    event->event_pending = false;
    scon->iov_sclp = 0;
    scon->iov_bs = 0;
    scon->iov_data_len = 0;
    scon->iov_sclp_rest = 0;
-}
-
-static int console_exit(SCLPEvent *event)
-{
-    return 0;
+   scon->notify = false;
 }
 
 static Property console_properties[] = {
@@ -246,20 +261,20 @@ static void console_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
 
-    dc->props = console_properties;
+    device_class_set_props(dc, console_properties);
     dc->reset = console_reset;
     dc->vmsd = &vmstate_sclpconsole;
     ec->init = console_init;
-    ec->exit = console_exit;
     ec->get_send_mask = send_mask;
     ec->get_receive_mask = receive_mask;
     ec->can_handle_event = can_handle_event;
     ec->read_event_data = read_event_data;
     ec->write_event_data = write_event_data;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
 static const TypeInfo sclp_console_info = {
-    .name          = "sclpconsole",
+    .name          = TYPE_SCLP_CONSOLE,
     .parent        = TYPE_SCLP_EVENT,
     .instance_size = sizeof(SCLPConsole),
     .class_init    = console_class_init,