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 "hw/qdev.h" 186a444f85SHeinz Graalfs #include "qemu/thread.h" 196a444f85SHeinz Graalfs #include "qemu/error-report.h" 204d43a603SMarc-André Lureau #include "chardev/char-fe.h" 216a444f85SHeinz Graalfs 226a444f85SHeinz Graalfs #include "hw/s390x/sclp.h" 236a444f85SHeinz Graalfs #include "hw/s390x/event-facility.h" 246a444f85SHeinz Graalfs #include "hw/s390x/ebcdic.h" 256a444f85SHeinz Graalfs 266a444f85SHeinz Graalfs #define SIZE_BUFFER 4096 276a444f85SHeinz Graalfs #define NEWLINE "\n" 286a444f85SHeinz Graalfs 296a444f85SHeinz Graalfs typedef struct OprtnsCommand { 306a444f85SHeinz Graalfs EventBufferHeader header; 316a444f85SHeinz Graalfs MDMSU message_unit; 326a444f85SHeinz Graalfs char data[0]; 336a444f85SHeinz Graalfs } QEMU_PACKED OprtnsCommand; 346a444f85SHeinz Graalfs 356a444f85SHeinz Graalfs /* max size for line-mode data in 4K SCCB page */ 366a444f85SHeinz Graalfs #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand)) 376a444f85SHeinz Graalfs 386a444f85SHeinz Graalfs typedef struct SCLPConsoleLM { 396a444f85SHeinz Graalfs SCLPEvent event; 40becdfa00SMarc-André Lureau CharBackend chr; 416a444f85SHeinz Graalfs bool echo; /* immediate echo of input if true */ 426a444f85SHeinz Graalfs uint32_t write_errors; /* errors writing to char layer */ 436a444f85SHeinz Graalfs uint32_t length; /* length of byte stream in buffer */ 446a444f85SHeinz Graalfs uint8_t buf[SIZE_CONSOLE_BUFFER]; 456a444f85SHeinz Graalfs } SCLPConsoleLM; 466a444f85SHeinz Graalfs 47e563c59bSxiaoqiang zhao #define TYPE_SCLPLM_CONSOLE "sclplmconsole" 48e563c59bSxiaoqiang zhao #define SCLPLM_CONSOLE(obj) \ 49e563c59bSxiaoqiang zhao OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) 50e563c59bSxiaoqiang zhao 516a444f85SHeinz Graalfs /* 526a444f85SHeinz Graalfs * Character layer call-back functions 536a444f85SHeinz Graalfs * 546a444f85SHeinz Graalfs * Allow 1 character at a time 556a444f85SHeinz Graalfs * 566a444f85SHeinz Graalfs * Accumulate bytes from character layer in console buffer, 576a444f85SHeinz Graalfs * event_pending is set when a newline character is encountered 586a444f85SHeinz Graalfs * 596a444f85SHeinz Graalfs * The maximum command line length is limited by the maximum 60b3191432SHeinz Graalfs * space available in an SCCB. Line mode console input is sent 61b3191432SHeinz Graalfs * truncated to the guest in case it doesn't fit into the SCCB. 626a444f85SHeinz Graalfs */ 636a444f85SHeinz Graalfs 646a444f85SHeinz Graalfs static int chr_can_read(void *opaque) 656a444f85SHeinz Graalfs { 666a444f85SHeinz Graalfs SCLPConsoleLM *scon = opaque; 676a444f85SHeinz Graalfs 686a444f85SHeinz Graalfs if (scon->event.event_pending) { 696a444f85SHeinz Graalfs return 0; 706a444f85SHeinz Graalfs } 71b3191432SHeinz Graalfs return 1; 726a444f85SHeinz Graalfs } 736a444f85SHeinz Graalfs 744f3ed190SChristian Borntraeger static void chr_read(void *opaque, const uint8_t *buf, int size) 756a444f85SHeinz Graalfs { 764f3ed190SChristian Borntraeger SCLPConsoleLM *scon = opaque; 774f3ed190SChristian Borntraeger 786a444f85SHeinz Graalfs assert(size == 1); 796a444f85SHeinz Graalfs 806a444f85SHeinz Graalfs if (*buf == '\r' || *buf == '\n') { 816a444f85SHeinz Graalfs scon->event.event_pending = true; 824f3ed190SChristian Borntraeger sclp_service_interrupt(0); 836a444f85SHeinz Graalfs return; 846a444f85SHeinz Graalfs } 85b3191432SHeinz Graalfs if (scon->length == SIZE_CONSOLE_BUFFER) { 86b3191432SHeinz Graalfs /* Eat the character, but still process CR and LF. */ 87b3191432SHeinz Graalfs return; 88b3191432SHeinz Graalfs } 896a444f85SHeinz Graalfs scon->buf[scon->length] = *buf; 906a444f85SHeinz Graalfs scon->length += 1; 916a444f85SHeinz Graalfs if (scon->echo) { 926ab3fc32SDaniel P. Berrange /* XXX this blocks entire thread. Rewrite to use 936ab3fc32SDaniel P. Berrange * qemu_chr_fe_write and background I/O callbacks */ 945345fdb4SMarc-André Lureau qemu_chr_fe_write_all(&scon->chr, buf, size); 956a444f85SHeinz Graalfs } 966a444f85SHeinz Graalfs } 976a444f85SHeinz Graalfs 986a444f85SHeinz Graalfs /* functions to be called by event facility */ 996a444f85SHeinz Graalfs 1006a444f85SHeinz Graalfs static bool can_handle_event(uint8_t type) 1016a444f85SHeinz Graalfs { 1026a444f85SHeinz Graalfs return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD; 1036a444f85SHeinz Graalfs } 1046a444f85SHeinz Graalfs 105*1ffed98fSClaudio Imbrenda static sccb_mask_t send_mask(void) 1066a444f85SHeinz Graalfs { 1076a444f85SHeinz Graalfs return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD; 1086a444f85SHeinz Graalfs } 1096a444f85SHeinz Graalfs 110*1ffed98fSClaudio Imbrenda static sccb_mask_t receive_mask(void) 1116a444f85SHeinz Graalfs { 1126a444f85SHeinz Graalfs return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD; 1136a444f85SHeinz Graalfs } 1146a444f85SHeinz Graalfs 1156a444f85SHeinz Graalfs /* 1166a444f85SHeinz Graalfs * Triggered by SCLP's read_event_data 1176a444f85SHeinz Graalfs * - convert ASCII byte stream to EBCDIC and 1186a444f85SHeinz Graalfs * - copy converted data into provided (SCLP) buffer 1196a444f85SHeinz Graalfs */ 1206a444f85SHeinz Graalfs static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, 1216a444f85SHeinz Graalfs int avail) 1226a444f85SHeinz Graalfs { 1236a444f85SHeinz Graalfs int len; 1246a444f85SHeinz Graalfs 125e563c59bSxiaoqiang zhao SCLPConsoleLM *cons = SCLPLM_CONSOLE(event); 1266a444f85SHeinz Graalfs 1276a444f85SHeinz Graalfs len = cons->length; 1286a444f85SHeinz Graalfs /* data need to fit into provided SCLP buffer */ 1296a444f85SHeinz Graalfs if (len > avail) { 1306a444f85SHeinz Graalfs return 1; 1316a444f85SHeinz Graalfs } 1326a444f85SHeinz Graalfs 1336a444f85SHeinz Graalfs ebcdic_put(buf, (char *)&cons->buf, len); 1346a444f85SHeinz Graalfs *size = len; 1356a444f85SHeinz Graalfs cons->length = 0; 1366a444f85SHeinz Graalfs /* data provided and no more data pending */ 1376a444f85SHeinz Graalfs event->event_pending = false; 13887f2eff0SHeinz Graalfs qemu_notify_event(); 1396a444f85SHeinz Graalfs return 0; 1406a444f85SHeinz Graalfs } 1416a444f85SHeinz Graalfs 1426a444f85SHeinz Graalfs static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, 1436a444f85SHeinz Graalfs int *slen) 1446a444f85SHeinz Graalfs { 1456a444f85SHeinz Graalfs int avail, rc; 1466a444f85SHeinz Graalfs size_t src_len; 1476a444f85SHeinz Graalfs uint8_t *to; 1486a444f85SHeinz Graalfs OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr; 1496a444f85SHeinz Graalfs 1506a444f85SHeinz Graalfs if (!event->event_pending) { 1516a444f85SHeinz Graalfs /* no data pending */ 1526a444f85SHeinz Graalfs return 0; 1536a444f85SHeinz Graalfs } 1546a444f85SHeinz Graalfs 1556a444f85SHeinz Graalfs to = (uint8_t *)&oc->data; 1566a444f85SHeinz Graalfs avail = *slen - sizeof(OprtnsCommand); 1576a444f85SHeinz Graalfs rc = get_console_data(event, to, &src_len, avail); 1586a444f85SHeinz Graalfs if (rc) { 1596a444f85SHeinz Graalfs /* data didn't fit, try next SCCB */ 1606a444f85SHeinz Graalfs return 1; 1616a444f85SHeinz Graalfs } 1626a444f85SHeinz Graalfs 1636a444f85SHeinz Graalfs oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU; 1646a444f85SHeinz Graalfs oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU)); 1656a444f85SHeinz Graalfs 1666a444f85SHeinz Graalfs oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU; 1676a444f85SHeinz Graalfs oc->message_unit.cpmsu.length = 1686a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector)); 1696a444f85SHeinz Graalfs 1706a444f85SHeinz Graalfs oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD; 1716a444f85SHeinz Graalfs oc->message_unit.text_command.length = 1726a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector))); 1736a444f85SHeinz Graalfs 1746a444f85SHeinz Graalfs oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG; 1756a444f85SHeinz Graalfs oc->message_unit.self_def_text_message.length = 1766a444f85SHeinz Graalfs cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector))); 1776a444f85SHeinz Graalfs 1786a444f85SHeinz Graalfs oc->message_unit.text_message.key = GDS_KEY_TEXTMSG; 1796a444f85SHeinz Graalfs oc->message_unit.text_message.length = 1806a444f85SHeinz Graalfs cpu_to_be16(sizeof(GdsSubvector) + src_len); 1816a444f85SHeinz Graalfs 1826a444f85SHeinz Graalfs oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len); 1836a444f85SHeinz Graalfs oc->header.type = SCLP_EVENT_OPRTNS_COMMAND; 1846a444f85SHeinz Graalfs *slen = avail - src_len; 1856a444f85SHeinz Graalfs 1866a444f85SHeinz Graalfs return 1; 1876a444f85SHeinz Graalfs } 1886a444f85SHeinz Graalfs 1896a444f85SHeinz Graalfs /* 1906a444f85SHeinz Graalfs * Triggered by SCLP's write_event_data 1916a444f85SHeinz Graalfs * - write console data to character layer 1926a444f85SHeinz Graalfs * returns < 0 if an error occurred 1936a444f85SHeinz Graalfs */ 1946a444f85SHeinz Graalfs static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) 1956a444f85SHeinz Graalfs { 196e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 1976a444f85SHeinz Graalfs 19830650701SAnton Nefedov if (!qemu_chr_fe_backend_connected(&scon->chr)) { 1996a444f85SHeinz Graalfs /* If there's no backend, we can just say we consumed all data. */ 2006a444f85SHeinz Graalfs return len; 2016a444f85SHeinz Graalfs } 2026a444f85SHeinz Graalfs 2037983e829SDaniel P. Berrange /* XXX this blocks entire thread. Rewrite to use 2047983e829SDaniel P. Berrange * qemu_chr_fe_write and background I/O callbacks */ 2055345fdb4SMarc-André Lureau return qemu_chr_fe_write_all(&scon->chr, buf, len); 2066a444f85SHeinz Graalfs } 2076a444f85SHeinz Graalfs 2086a444f85SHeinz Graalfs static int process_mdb(SCLPEvent *event, MDBO *mdbo) 2096a444f85SHeinz Graalfs { 2106a444f85SHeinz Graalfs int rc; 2116a444f85SHeinz Graalfs int len; 2126a444f85SHeinz Graalfs uint8_t buffer[SIZE_BUFFER]; 2136a444f85SHeinz Graalfs 2146a444f85SHeinz Graalfs len = be16_to_cpu(mdbo->length); 2156a444f85SHeinz Graalfs len -= sizeof(mdbo->length) + sizeof(mdbo->type) 2166a444f85SHeinz Graalfs + sizeof(mdbo->mto.line_type_flags) 2176a444f85SHeinz Graalfs + sizeof(mdbo->mto.alarm_control) 2186a444f85SHeinz Graalfs + sizeof(mdbo->mto._reserved); 2196a444f85SHeinz Graalfs 2206a444f85SHeinz Graalfs assert(len <= SIZE_BUFFER); 2216a444f85SHeinz Graalfs 2226a444f85SHeinz Graalfs /* convert EBCDIC SCLP contents to ASCII console message */ 2236a444f85SHeinz Graalfs ascii_put(buffer, mdbo->mto.message, len); 2246a444f85SHeinz Graalfs rc = write_console_data(event, (uint8_t *)NEWLINE, 1); 2256a444f85SHeinz Graalfs if (rc < 0) { 2266a444f85SHeinz Graalfs return rc; 2276a444f85SHeinz Graalfs } 2286a444f85SHeinz Graalfs return write_console_data(event, buffer, len); 2296a444f85SHeinz Graalfs } 2306a444f85SHeinz Graalfs 2316a444f85SHeinz Graalfs static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh) 2326a444f85SHeinz Graalfs { 2336a444f85SHeinz Graalfs int len; 2346a444f85SHeinz Graalfs int written; 2356a444f85SHeinz Graalfs int errors = 0; 2366a444f85SHeinz Graalfs MDBO *mdbo; 2376a444f85SHeinz Graalfs SclpMsg *data = (SclpMsg *) ebh; 238e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 2396a444f85SHeinz Graalfs 2406a444f85SHeinz Graalfs len = be16_to_cpu(data->mdb.header.length); 2416a444f85SHeinz Graalfs if (len < sizeof(data->mdb.header)) { 2426a444f85SHeinz Graalfs return SCLP_RC_INCONSISTENT_LENGTHS; 2436a444f85SHeinz Graalfs } 2446a444f85SHeinz Graalfs len -= sizeof(data->mdb.header); 2456a444f85SHeinz Graalfs 2466a444f85SHeinz Graalfs /* first check message buffers */ 2476a444f85SHeinz Graalfs mdbo = data->mdb.mdbo; 2486a444f85SHeinz Graalfs while (len > 0) { 2496a444f85SHeinz Graalfs if (be16_to_cpu(mdbo->length) > len 2506a444f85SHeinz Graalfs || be16_to_cpu(mdbo->length) == 0) { 2516a444f85SHeinz Graalfs return SCLP_RC_INCONSISTENT_LENGTHS; 2526a444f85SHeinz Graalfs } 2536a444f85SHeinz Graalfs len -= be16_to_cpu(mdbo->length); 2546a444f85SHeinz Graalfs mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 2556a444f85SHeinz Graalfs } 2566a444f85SHeinz Graalfs 2576a444f85SHeinz Graalfs /* then execute */ 2586a444f85SHeinz Graalfs len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header); 2596a444f85SHeinz Graalfs mdbo = data->mdb.mdbo; 2606a444f85SHeinz Graalfs while (len > 0) { 2616a444f85SHeinz Graalfs switch (be16_to_cpu(mdbo->type)) { 2626a444f85SHeinz Graalfs case MESSAGE_TEXT: 2636a444f85SHeinz Graalfs /* message text object */ 2646a444f85SHeinz Graalfs written = process_mdb(event, mdbo); 2656a444f85SHeinz Graalfs if (written < 0) { 2666a444f85SHeinz Graalfs /* character layer error */ 2676a444f85SHeinz Graalfs errors++; 2686a444f85SHeinz Graalfs } 2696a444f85SHeinz Graalfs break; 2706a444f85SHeinz Graalfs default: /* ignore */ 2716a444f85SHeinz Graalfs break; 2726a444f85SHeinz Graalfs } 2736a444f85SHeinz Graalfs len -= be16_to_cpu(mdbo->length); 2746a444f85SHeinz Graalfs mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 2756a444f85SHeinz Graalfs } 2766a444f85SHeinz Graalfs if (errors) { 2776a444f85SHeinz Graalfs scon->write_errors += errors; 2786a444f85SHeinz Graalfs } 2796a444f85SHeinz Graalfs data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED; 2806a444f85SHeinz Graalfs 2816a444f85SHeinz Graalfs return SCLP_RC_NORMAL_COMPLETION; 2826a444f85SHeinz Graalfs } 2836a444f85SHeinz Graalfs 2846a444f85SHeinz Graalfs /* functions for live migration */ 2856a444f85SHeinz Graalfs 2866a444f85SHeinz Graalfs static const VMStateDescription vmstate_sclplmconsole = { 2876a444f85SHeinz Graalfs .name = "sclplmconsole", 2886a444f85SHeinz Graalfs .version_id = 0, 2896a444f85SHeinz Graalfs .minimum_version_id = 0, 2906a444f85SHeinz Graalfs .fields = (VMStateField[]) { 2916a444f85SHeinz Graalfs VMSTATE_BOOL(event.event_pending, SCLPConsoleLM), 2926a444f85SHeinz Graalfs VMSTATE_UINT32(write_errors, SCLPConsoleLM), 2936a444f85SHeinz Graalfs VMSTATE_UINT32(length, SCLPConsoleLM), 2946a444f85SHeinz Graalfs VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER), 2956a444f85SHeinz Graalfs VMSTATE_END_OF_LIST() 2966a444f85SHeinz Graalfs } 2976a444f85SHeinz Graalfs }; 2986a444f85SHeinz Graalfs 2996a444f85SHeinz Graalfs /* qemu object creation and initialization functions */ 3006a444f85SHeinz Graalfs 3016a444f85SHeinz Graalfs /* tell character layer our call-back functions */ 3026a444f85SHeinz Graalfs 3036a444f85SHeinz Graalfs static int console_init(SCLPEvent *event) 3046a444f85SHeinz Graalfs { 3056a444f85SHeinz Graalfs static bool console_available; 3066a444f85SHeinz Graalfs 307e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 3086a444f85SHeinz Graalfs 3096a444f85SHeinz Graalfs if (console_available) { 3106a444f85SHeinz Graalfs error_report("Multiple line-mode operator consoles are not supported"); 3116a444f85SHeinz Graalfs return -1; 3126a444f85SHeinz Graalfs } 3136a444f85SHeinz Graalfs console_available = true; 3146a444f85SHeinz Graalfs 3155345fdb4SMarc-André Lureau qemu_chr_fe_set_handlers(&scon->chr, chr_can_read, 31681517ba3SAnton Nefedov chr_read, NULL, NULL, scon, NULL, true); 3176a444f85SHeinz Graalfs 3186a444f85SHeinz Graalfs return 0; 3196a444f85SHeinz Graalfs } 3206a444f85SHeinz Graalfs 3216a444f85SHeinz Graalfs static void console_reset(DeviceState *dev) 3226a444f85SHeinz Graalfs { 3236a444f85SHeinz Graalfs SCLPEvent *event = SCLP_EVENT(dev); 324e563c59bSxiaoqiang zhao SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 3256a444f85SHeinz Graalfs 3266a444f85SHeinz Graalfs event->event_pending = false; 3276a444f85SHeinz Graalfs scon->length = 0; 3286a444f85SHeinz Graalfs scon->write_errors = 0; 3296a444f85SHeinz Graalfs } 3306a444f85SHeinz Graalfs 3316a444f85SHeinz Graalfs static Property console_properties[] = { 3326a444f85SHeinz Graalfs DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr), 3336a444f85SHeinz Graalfs DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0), 3346a444f85SHeinz Graalfs DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true), 3356a444f85SHeinz Graalfs DEFINE_PROP_END_OF_LIST(), 3366a444f85SHeinz Graalfs }; 3376a444f85SHeinz Graalfs 3386a444f85SHeinz Graalfs static void console_class_init(ObjectClass *klass, void *data) 3396a444f85SHeinz Graalfs { 3406a444f85SHeinz Graalfs DeviceClass *dc = DEVICE_CLASS(klass); 3416a444f85SHeinz Graalfs SCLPEventClass *ec = SCLP_EVENT_CLASS(klass); 3426a444f85SHeinz Graalfs 3436a444f85SHeinz Graalfs dc->props = console_properties; 3446a444f85SHeinz Graalfs dc->reset = console_reset; 3456a444f85SHeinz Graalfs dc->vmsd = &vmstate_sclplmconsole; 3466a444f85SHeinz Graalfs ec->init = console_init; 3476a444f85SHeinz Graalfs ec->get_send_mask = send_mask; 3486a444f85SHeinz Graalfs ec->get_receive_mask = receive_mask; 3496a444f85SHeinz Graalfs ec->can_handle_event = can_handle_event; 3506a444f85SHeinz Graalfs ec->read_event_data = read_event_data; 3516a444f85SHeinz Graalfs ec->write_event_data = write_event_data; 352183f6b8dSCornelia Huck set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 3536a444f85SHeinz Graalfs } 3546a444f85SHeinz Graalfs 3556a444f85SHeinz Graalfs static const TypeInfo sclp_console_info = { 3566a444f85SHeinz Graalfs .name = "sclplmconsole", 3576a444f85SHeinz Graalfs .parent = TYPE_SCLP_EVENT, 3586a444f85SHeinz Graalfs .instance_size = sizeof(SCLPConsoleLM), 3596a444f85SHeinz Graalfs .class_init = console_class_init, 3606a444f85SHeinz Graalfs .class_size = sizeof(SCLPEventClass), 3616a444f85SHeinz Graalfs }; 3626a444f85SHeinz Graalfs 3636a444f85SHeinz Graalfs static void register_types(void) 3646a444f85SHeinz Graalfs { 3656a444f85SHeinz Graalfs type_register_static(&sclp_console_info); 3666a444f85SHeinz Graalfs } 3676a444f85SHeinz Graalfs 3686a444f85SHeinz Graalfs type_init(register_types) 369