16a444f85SHeinz Graalfs /*
26a444f85SHeinz Graalfs * SCLP event types
36a444f85SHeinz Graalfs * Operations Command - Line Mode input
46a444f85SHeinz Graalfs * Message - Line Mode output
56a444f85SHeinz Graalfs *
66a444f85SHeinz Graalfs * Copyright IBM, Corp. 2013
76a444f85SHeinz Graalfs *
86a444f85SHeinz Graalfs * Authors:
96a444f85SHeinz Graalfs * Heinz Graalfs <graalfs@linux.vnet.ibm.com>
106a444f85SHeinz Graalfs *
116a444f85SHeinz Graalfs * This work is licensed under the terms of the GNU GPL, version 2 or (at your
126a444f85SHeinz Graalfs * option) any later version. See the COPYING file in the top-level directory.
136a444f85SHeinz Graalfs *
146a444f85SHeinz Graalfs */
156a444f85SHeinz Graalfs
169615495aSPeter Maydell #include "qemu/osdep.h"
176a444f85SHeinz Graalfs #include "qemu/thread.h"
186a444f85SHeinz Graalfs #include "qemu/error-report.h"
190b8fa32fSMarkus Armbruster #include "qemu/module.h"
204d43a603SMarc-André Lureau #include "chardev/char-fe.h"
216a444f85SHeinz Graalfs
226a444f85SHeinz Graalfs #include "hw/s390x/sclp.h"
23d6454270SMarkus Armbruster #include "migration/vmstate.h"
246a444f85SHeinz Graalfs #include "hw/s390x/event-facility.h"
25a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
26ce35e229SEduardo Habkost #include "hw/qdev-properties-system.h"
276a444f85SHeinz Graalfs #include "hw/s390x/ebcdic.h"
28db1015e9SEduardo Habkost #include "qom/object.h"
296a444f85SHeinz Graalfs
306a444f85SHeinz Graalfs #define SIZE_BUFFER 4096
316a444f85SHeinz Graalfs #define NEWLINE "\n"
326a444f85SHeinz Graalfs
336a444f85SHeinz Graalfs typedef struct OprtnsCommand {
346a444f85SHeinz Graalfs EventBufferHeader header;
356a444f85SHeinz Graalfs MDMSU message_unit;
36880a7817SPhilippe Mathieu-Daudé char data[];
376a444f85SHeinz Graalfs } QEMU_PACKED OprtnsCommand;
386a444f85SHeinz Graalfs
396a444f85SHeinz Graalfs /* max size for line-mode data in 4K SCCB page */
406a444f85SHeinz Graalfs #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand))
416a444f85SHeinz Graalfs
42db1015e9SEduardo Habkost struct SCLPConsoleLM {
436a444f85SHeinz Graalfs SCLPEvent event;
44becdfa00SMarc-André Lureau CharBackend chr;
456a444f85SHeinz Graalfs bool echo; /* immediate echo of input if true */
466a444f85SHeinz Graalfs uint32_t write_errors; /* errors writing to char layer */
476a444f85SHeinz Graalfs uint32_t length; /* length of byte stream in buffer */
486a444f85SHeinz Graalfs uint8_t buf[SIZE_CONSOLE_BUFFER];
49db1015e9SEduardo Habkost };
50db1015e9SEduardo Habkost typedef struct SCLPConsoleLM SCLPConsoleLM;
516a444f85SHeinz Graalfs
52e563c59bSxiaoqiang zhao #define TYPE_SCLPLM_CONSOLE "sclplmconsole"
DECLARE_INSTANCE_CHECKER(SCLPConsoleLM,SCLPLM_CONSOLE,TYPE_SCLPLM_CONSOLE)538110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(SCLPConsoleLM, SCLPLM_CONSOLE,
548110fa1dSEduardo Habkost TYPE_SCLPLM_CONSOLE)
55e563c59bSxiaoqiang zhao
566a444f85SHeinz Graalfs /*
576a444f85SHeinz Graalfs * Character layer call-back functions
586a444f85SHeinz Graalfs *
596a444f85SHeinz Graalfs * Allow 1 character at a time
606a444f85SHeinz Graalfs *
616a444f85SHeinz Graalfs * Accumulate bytes from character layer in console buffer,
626a444f85SHeinz Graalfs * event_pending is set when a newline character is encountered
636a444f85SHeinz Graalfs *
646a444f85SHeinz Graalfs * The maximum command line length is limited by the maximum
65b3191432SHeinz Graalfs * space available in an SCCB. Line mode console input is sent
66b3191432SHeinz Graalfs * truncated to the guest in case it doesn't fit into the SCCB.
676a444f85SHeinz Graalfs */
686a444f85SHeinz Graalfs
696a444f85SHeinz Graalfs static int chr_can_read(void *opaque)
706a444f85SHeinz Graalfs {
716a444f85SHeinz Graalfs SCLPConsoleLM *scon = opaque;
726a444f85SHeinz Graalfs
736a444f85SHeinz Graalfs if (scon->event.event_pending) {
746a444f85SHeinz Graalfs return 0;
756a444f85SHeinz Graalfs }
76b3191432SHeinz Graalfs return 1;
776a444f85SHeinz Graalfs }
786a444f85SHeinz Graalfs
chr_read(void * opaque,const uint8_t * buf,int size)794f3ed190SChristian Borntraeger static void chr_read(void *opaque, const uint8_t *buf, int size)
806a444f85SHeinz Graalfs {
814f3ed190SChristian Borntraeger SCLPConsoleLM *scon = opaque;
824f3ed190SChristian Borntraeger
836a444f85SHeinz Graalfs assert(size == 1);
846a444f85SHeinz Graalfs
856a444f85SHeinz Graalfs if (*buf == '\r' || *buf == '\n') {
866a444f85SHeinz Graalfs scon->event.event_pending = true;
874f3ed190SChristian Borntraeger sclp_service_interrupt(0);
886a444f85SHeinz Graalfs return;
896a444f85SHeinz Graalfs }
90b3191432SHeinz Graalfs if (scon->length == SIZE_CONSOLE_BUFFER) {
91b3191432SHeinz Graalfs /* Eat the character, but still process CR and LF. */
92b3191432SHeinz Graalfs return;
93b3191432SHeinz Graalfs }
946a444f85SHeinz Graalfs scon->buf[scon->length] = *buf;
956a444f85SHeinz Graalfs scon->length += 1;
966a444f85SHeinz Graalfs if (scon->echo) {
976ab3fc32SDaniel P. Berrange /* XXX this blocks entire thread. Rewrite to use
986ab3fc32SDaniel P. Berrange * qemu_chr_fe_write and background I/O callbacks */
995345fdb4SMarc-André Lureau qemu_chr_fe_write_all(&scon->chr, buf, size);
1006a444f85SHeinz Graalfs }
1016a444f85SHeinz Graalfs }
1026a444f85SHeinz Graalfs
1036a444f85SHeinz Graalfs /* functions to be called by event facility */
1046a444f85SHeinz Graalfs
can_handle_event(uint8_t type)1056a444f85SHeinz Graalfs static bool can_handle_event(uint8_t type)
1066a444f85SHeinz Graalfs {
1076a444f85SHeinz Graalfs return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD;
1086a444f85SHeinz Graalfs }
1096a444f85SHeinz Graalfs
send_mask(void)1101ffed98fSClaudio Imbrenda static sccb_mask_t send_mask(void)
1116a444f85SHeinz Graalfs {
1126a444f85SHeinz Graalfs return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD;
1136a444f85SHeinz Graalfs }
1146a444f85SHeinz Graalfs
receive_mask(void)1151ffed98fSClaudio Imbrenda static sccb_mask_t receive_mask(void)
1166a444f85SHeinz Graalfs {
1176a444f85SHeinz Graalfs return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD;
1186a444f85SHeinz Graalfs }
1196a444f85SHeinz Graalfs
1206a444f85SHeinz Graalfs /*
1216a444f85SHeinz Graalfs * Triggered by SCLP's read_event_data
1226a444f85SHeinz Graalfs * - convert ASCII byte stream to EBCDIC and
1236a444f85SHeinz Graalfs * - copy converted data into provided (SCLP) buffer
1246a444f85SHeinz Graalfs */
get_console_data(SCLPEvent * event,uint8_t * buf,size_t * size,int avail)1256a444f85SHeinz Graalfs static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
1266a444f85SHeinz Graalfs int avail)
1276a444f85SHeinz Graalfs {
1286a444f85SHeinz Graalfs int len;
1296a444f85SHeinz Graalfs
130e563c59bSxiaoqiang zhao SCLPConsoleLM *cons = SCLPLM_CONSOLE(event);
1316a444f85SHeinz Graalfs
1326a444f85SHeinz Graalfs len = cons->length;
1336a444f85SHeinz Graalfs /* data need to fit into provided SCLP buffer */
1346a444f85SHeinz Graalfs if (len > avail) {
1356a444f85SHeinz Graalfs return 1;
1366a444f85SHeinz Graalfs }
1376a444f85SHeinz Graalfs
1386a444f85SHeinz Graalfs ebcdic_put(buf, (char *)&cons->buf, len);
1396a444f85SHeinz Graalfs *size = len;
1406a444f85SHeinz Graalfs cons->length = 0;
1416a444f85SHeinz Graalfs /* data provided and no more data pending */
1426a444f85SHeinz Graalfs event->event_pending = false;
14387f2eff0SHeinz Graalfs qemu_notify_event();
1446a444f85SHeinz Graalfs return 0;
1456a444f85SHeinz Graalfs }
1466a444f85SHeinz Graalfs
read_event_data(SCLPEvent * event,EventBufferHeader * evt_buf_hdr,int * slen)1476a444f85SHeinz Graalfs static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
1486a444f85SHeinz Graalfs int *slen)
1496a444f85SHeinz Graalfs {
1506a444f85SHeinz Graalfs int avail, rc;
1516a444f85SHeinz Graalfs size_t src_len;
1526a444f85SHeinz Graalfs uint8_t *to;
1536a444f85SHeinz Graalfs OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr;
1546a444f85SHeinz Graalfs
1556a444f85SHeinz Graalfs if (!event->event_pending) {
1566a444f85SHeinz Graalfs /* no data pending */
1576a444f85SHeinz Graalfs return 0;
1586a444f85SHeinz Graalfs }
1596a444f85SHeinz Graalfs
1606a444f85SHeinz Graalfs to = (uint8_t *)&oc->data;
1616a444f85SHeinz Graalfs avail = *slen - sizeof(OprtnsCommand);
1626a444f85SHeinz Graalfs rc = get_console_data(event, to, &src_len, avail);
1636a444f85SHeinz Graalfs if (rc) {
1646a444f85SHeinz Graalfs /* data didn't fit, try next SCCB */
1656a444f85SHeinz Graalfs return 1;
1666a444f85SHeinz Graalfs }
1676a444f85SHeinz Graalfs
1686a444f85SHeinz Graalfs oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU;
1696a444f85SHeinz Graalfs oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU));
1706a444f85SHeinz Graalfs
1716a444f85SHeinz Graalfs oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU;
1726a444f85SHeinz Graalfs oc->message_unit.cpmsu.length =
1736a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector));
1746a444f85SHeinz Graalfs
1756a444f85SHeinz Graalfs oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD;
1766a444f85SHeinz Graalfs oc->message_unit.text_command.length =
1776a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector)));
1786a444f85SHeinz Graalfs
1796a444f85SHeinz Graalfs oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG;
1806a444f85SHeinz Graalfs oc->message_unit.self_def_text_message.length =
1816a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector)));
1826a444f85SHeinz Graalfs
1836a444f85SHeinz Graalfs oc->message_unit.text_message.key = GDS_KEY_TEXTMSG;
1846a444f85SHeinz Graalfs oc->message_unit.text_message.length =
1856a444f85SHeinz Graalfs cpu_to_be16(sizeof(GdsSubvector) + src_len);
1866a444f85SHeinz Graalfs
1876a444f85SHeinz Graalfs oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len);
1886a444f85SHeinz Graalfs oc->header.type = SCLP_EVENT_OPRTNS_COMMAND;
1896a444f85SHeinz Graalfs *slen = avail - src_len;
1906a444f85SHeinz Graalfs
1916a444f85SHeinz Graalfs return 1;
1926a444f85SHeinz Graalfs }
1936a444f85SHeinz Graalfs
1946a444f85SHeinz Graalfs /*
1956a444f85SHeinz Graalfs * Triggered by SCLP's write_event_data
1966a444f85SHeinz Graalfs * - write console data to character layer
1976a444f85SHeinz Graalfs * returns < 0 if an error occurred
1986a444f85SHeinz Graalfs */
write_console_data(SCLPEvent * event,const uint8_t * buf,int len)1996a444f85SHeinz Graalfs static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
2006a444f85SHeinz Graalfs {
201e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
2026a444f85SHeinz Graalfs
20330650701SAnton Nefedov if (!qemu_chr_fe_backend_connected(&scon->chr)) {
2046a444f85SHeinz Graalfs /* If there's no backend, we can just say we consumed all data. */
2056a444f85SHeinz Graalfs return len;
2066a444f85SHeinz Graalfs }
2076a444f85SHeinz Graalfs
2087983e829SDaniel P. Berrange /* XXX this blocks entire thread. Rewrite to use
2097983e829SDaniel P. Berrange * qemu_chr_fe_write and background I/O callbacks */
2105345fdb4SMarc-André Lureau return qemu_chr_fe_write_all(&scon->chr, buf, len);
2116a444f85SHeinz Graalfs }
2126a444f85SHeinz Graalfs
process_mdb(SCLPEvent * event,MDBO * mdbo)2136a444f85SHeinz Graalfs static int process_mdb(SCLPEvent *event, MDBO *mdbo)
2146a444f85SHeinz Graalfs {
2156a444f85SHeinz Graalfs int rc;
2166a444f85SHeinz Graalfs int len;
2176a444f85SHeinz Graalfs uint8_t buffer[SIZE_BUFFER];
2186a444f85SHeinz Graalfs
2196a444f85SHeinz Graalfs len = be16_to_cpu(mdbo->length);
2206a444f85SHeinz Graalfs len -= sizeof(mdbo->length) + sizeof(mdbo->type)
2216a444f85SHeinz Graalfs + sizeof(mdbo->mto.line_type_flags)
2226a444f85SHeinz Graalfs + sizeof(mdbo->mto.alarm_control)
2236a444f85SHeinz Graalfs + sizeof(mdbo->mto._reserved);
2246a444f85SHeinz Graalfs
2256a444f85SHeinz Graalfs assert(len <= SIZE_BUFFER);
2266a444f85SHeinz Graalfs
2276a444f85SHeinz Graalfs /* convert EBCDIC SCLP contents to ASCII console message */
2286a444f85SHeinz Graalfs ascii_put(buffer, mdbo->mto.message, len);
2296a444f85SHeinz Graalfs rc = write_console_data(event, (uint8_t *)NEWLINE, 1);
2306a444f85SHeinz Graalfs if (rc < 0) {
2316a444f85SHeinz Graalfs return rc;
2326a444f85SHeinz Graalfs }
2336a444f85SHeinz Graalfs return write_console_data(event, buffer, len);
2346a444f85SHeinz Graalfs }
2356a444f85SHeinz Graalfs
write_event_data(SCLPEvent * event,EventBufferHeader * ebh)2366a444f85SHeinz Graalfs static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
2376a444f85SHeinz Graalfs {
2386a444f85SHeinz Graalfs int len;
2396a444f85SHeinz Graalfs int written;
2406a444f85SHeinz Graalfs int errors = 0;
2416a444f85SHeinz Graalfs MDBO *mdbo;
2426a444f85SHeinz Graalfs SclpMsg *data = (SclpMsg *) ebh;
243e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
2446a444f85SHeinz Graalfs
2456a444f85SHeinz Graalfs len = be16_to_cpu(data->mdb.header.length);
2466a444f85SHeinz Graalfs if (len < sizeof(data->mdb.header)) {
2476a444f85SHeinz Graalfs return SCLP_RC_INCONSISTENT_LENGTHS;
2486a444f85SHeinz Graalfs }
2496a444f85SHeinz Graalfs len -= sizeof(data->mdb.header);
2506a444f85SHeinz Graalfs
2516a444f85SHeinz Graalfs /* first check message buffers */
2526a444f85SHeinz Graalfs mdbo = data->mdb.mdbo;
2536a444f85SHeinz Graalfs while (len > 0) {
2546a444f85SHeinz Graalfs if (be16_to_cpu(mdbo->length) > len
2556a444f85SHeinz Graalfs || be16_to_cpu(mdbo->length) == 0) {
2566a444f85SHeinz Graalfs return SCLP_RC_INCONSISTENT_LENGTHS;
2576a444f85SHeinz Graalfs }
2586a444f85SHeinz Graalfs len -= be16_to_cpu(mdbo->length);
2596a444f85SHeinz Graalfs mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
2606a444f85SHeinz Graalfs }
2616a444f85SHeinz Graalfs
2626a444f85SHeinz Graalfs /* then execute */
2636a444f85SHeinz Graalfs len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header);
2646a444f85SHeinz Graalfs mdbo = data->mdb.mdbo;
2656a444f85SHeinz Graalfs while (len > 0) {
2666a444f85SHeinz Graalfs switch (be16_to_cpu(mdbo->type)) {
2676a444f85SHeinz Graalfs case MESSAGE_TEXT:
2686a444f85SHeinz Graalfs /* message text object */
2696a444f85SHeinz Graalfs written = process_mdb(event, mdbo);
2706a444f85SHeinz Graalfs if (written < 0) {
2716a444f85SHeinz Graalfs /* character layer error */
2726a444f85SHeinz Graalfs errors++;
2736a444f85SHeinz Graalfs }
2746a444f85SHeinz Graalfs break;
2756a444f85SHeinz Graalfs default: /* ignore */
2766a444f85SHeinz Graalfs break;
2776a444f85SHeinz Graalfs }
2786a444f85SHeinz Graalfs len -= be16_to_cpu(mdbo->length);
2796a444f85SHeinz Graalfs mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
2806a444f85SHeinz Graalfs }
2816a444f85SHeinz Graalfs if (errors) {
2826a444f85SHeinz Graalfs scon->write_errors += errors;
2836a444f85SHeinz Graalfs }
2846a444f85SHeinz Graalfs data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED;
2856a444f85SHeinz Graalfs
2866a444f85SHeinz Graalfs return SCLP_RC_NORMAL_COMPLETION;
2876a444f85SHeinz Graalfs }
2886a444f85SHeinz Graalfs
2896a444f85SHeinz Graalfs /* functions for live migration */
2906a444f85SHeinz Graalfs
2916a444f85SHeinz Graalfs static const VMStateDescription vmstate_sclplmconsole = {
2926a444f85SHeinz Graalfs .name = "sclplmconsole",
2936a444f85SHeinz Graalfs .version_id = 0,
2946a444f85SHeinz Graalfs .minimum_version_id = 0,
2952f6cab05SRichard Henderson .fields = (const VMStateField[]) {
2966a444f85SHeinz Graalfs VMSTATE_BOOL(event.event_pending, SCLPConsoleLM),
2976a444f85SHeinz Graalfs VMSTATE_UINT32(write_errors, SCLPConsoleLM),
2986a444f85SHeinz Graalfs VMSTATE_UINT32(length, SCLPConsoleLM),
2996a444f85SHeinz Graalfs VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER),
3006a444f85SHeinz Graalfs VMSTATE_END_OF_LIST()
3016a444f85SHeinz Graalfs }
3026a444f85SHeinz Graalfs };
3036a444f85SHeinz Graalfs
3046a444f85SHeinz Graalfs /* qemu object creation and initialization functions */
3056a444f85SHeinz Graalfs
3066a444f85SHeinz Graalfs /* tell character layer our call-back functions */
3076a444f85SHeinz Graalfs
console_init(SCLPEvent * event)3086a444f85SHeinz Graalfs static int console_init(SCLPEvent *event)
3096a444f85SHeinz Graalfs {
3106a444f85SHeinz Graalfs static bool console_available;
3116a444f85SHeinz Graalfs
312e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
3136a444f85SHeinz Graalfs
3146a444f85SHeinz Graalfs if (console_available) {
3156a444f85SHeinz Graalfs error_report("Multiple line-mode operator consoles are not supported");
3166a444f85SHeinz Graalfs return -1;
3176a444f85SHeinz Graalfs }
3186a444f85SHeinz Graalfs console_available = true;
3196a444f85SHeinz Graalfs
3205345fdb4SMarc-André Lureau qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
32181517ba3SAnton Nefedov chr_read, NULL, NULL, scon, NULL, true);
3226a444f85SHeinz Graalfs
3236a444f85SHeinz Graalfs return 0;
3246a444f85SHeinz Graalfs }
3256a444f85SHeinz Graalfs
console_reset(DeviceState * dev)3266a444f85SHeinz Graalfs static void console_reset(DeviceState *dev)
3276a444f85SHeinz Graalfs {
3286a444f85SHeinz Graalfs SCLPEvent *event = SCLP_EVENT(dev);
329e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
3306a444f85SHeinz Graalfs
3316a444f85SHeinz Graalfs event->event_pending = false;
3326a444f85SHeinz Graalfs scon->length = 0;
3336a444f85SHeinz Graalfs scon->write_errors = 0;
3346a444f85SHeinz Graalfs }
3356a444f85SHeinz Graalfs
3366a444f85SHeinz Graalfs static Property console_properties[] = {
3376a444f85SHeinz Graalfs DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr),
3386a444f85SHeinz Graalfs DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0),
3396a444f85SHeinz Graalfs DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true),
3406a444f85SHeinz Graalfs DEFINE_PROP_END_OF_LIST(),
3416a444f85SHeinz Graalfs };
3426a444f85SHeinz Graalfs
console_class_init(ObjectClass * klass,void * data)3436a444f85SHeinz Graalfs static void console_class_init(ObjectClass *klass, void *data)
3446a444f85SHeinz Graalfs {
3456a444f85SHeinz Graalfs DeviceClass *dc = DEVICE_CLASS(klass);
3466a444f85SHeinz Graalfs SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
3476a444f85SHeinz Graalfs
3484f67d30bSMarc-André Lureau device_class_set_props(dc, console_properties);
349*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, console_reset);
3506a444f85SHeinz Graalfs dc->vmsd = &vmstate_sclplmconsole;
3516a444f85SHeinz Graalfs ec->init = console_init;
3526a444f85SHeinz Graalfs ec->get_send_mask = send_mask;
3536a444f85SHeinz Graalfs ec->get_receive_mask = receive_mask;
3546a444f85SHeinz Graalfs ec->can_handle_event = can_handle_event;
3556a444f85SHeinz Graalfs ec->read_event_data = read_event_data;
3566a444f85SHeinz Graalfs ec->write_event_data = write_event_data;
357183f6b8dSCornelia Huck set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
3586a444f85SHeinz Graalfs }
3596a444f85SHeinz Graalfs
3606a444f85SHeinz Graalfs static const TypeInfo sclp_console_info = {
3611a3bae79SEduardo Habkost .name = TYPE_SCLPLM_CONSOLE,
3626a444f85SHeinz Graalfs .parent = TYPE_SCLP_EVENT,
3636a444f85SHeinz Graalfs .instance_size = sizeof(SCLPConsoleLM),
3646a444f85SHeinz Graalfs .class_init = console_class_init,
3656a444f85SHeinz Graalfs .class_size = sizeof(SCLPEventClass),
3666a444f85SHeinz Graalfs };
3676a444f85SHeinz Graalfs
register_types(void)3686a444f85SHeinz Graalfs static void register_types(void)
3696a444f85SHeinz Graalfs {
3706a444f85SHeinz Graalfs type_register_static(&sclp_console_info);
3716a444f85SHeinz Graalfs }
3726a444f85SHeinz Graalfs
3736a444f85SHeinz Graalfs type_init(register_types)
374