1 /* 2 * SCLP event types 3 * Operations Command - Line Mode input 4 * Message - Line Mode output 5 * 6 * Copyright IBM, Corp. 2013 7 * 8 * Authors: 9 * Heinz Graalfs <graalfs@linux.vnet.ibm.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2 or (at your 12 * option) any later version. See the COPYING file in the top-level directory. 13 * 14 */ 15 16 #include "qemu/osdep.h" 17 #include "hw/qdev.h" 18 #include "qemu/thread.h" 19 #include "qemu/error-report.h" 20 #include "qemu/module.h" 21 #include "chardev/char-fe.h" 22 23 #include "hw/s390x/sclp.h" 24 #include "hw/s390x/event-facility.h" 25 #include "hw/s390x/ebcdic.h" 26 27 #define SIZE_BUFFER 4096 28 #define NEWLINE "\n" 29 30 typedef struct OprtnsCommand { 31 EventBufferHeader header; 32 MDMSU message_unit; 33 char data[0]; 34 } QEMU_PACKED OprtnsCommand; 35 36 /* max size for line-mode data in 4K SCCB page */ 37 #define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand)) 38 39 typedef struct SCLPConsoleLM { 40 SCLPEvent event; 41 CharBackend chr; 42 bool echo; /* immediate echo of input if true */ 43 uint32_t write_errors; /* errors writing to char layer */ 44 uint32_t length; /* length of byte stream in buffer */ 45 uint8_t buf[SIZE_CONSOLE_BUFFER]; 46 } SCLPConsoleLM; 47 48 #define TYPE_SCLPLM_CONSOLE "sclplmconsole" 49 #define SCLPLM_CONSOLE(obj) \ 50 OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) 51 52 /* 53 * Character layer call-back functions 54 * 55 * Allow 1 character at a time 56 * 57 * Accumulate bytes from character layer in console buffer, 58 * event_pending is set when a newline character is encountered 59 * 60 * The maximum command line length is limited by the maximum 61 * space available in an SCCB. Line mode console input is sent 62 * truncated to the guest in case it doesn't fit into the SCCB. 63 */ 64 65 static int chr_can_read(void *opaque) 66 { 67 SCLPConsoleLM *scon = opaque; 68 69 if (scon->event.event_pending) { 70 return 0; 71 } 72 return 1; 73 } 74 75 static void chr_read(void *opaque, const uint8_t *buf, int size) 76 { 77 SCLPConsoleLM *scon = opaque; 78 79 assert(size == 1); 80 81 if (*buf == '\r' || *buf == '\n') { 82 scon->event.event_pending = true; 83 sclp_service_interrupt(0); 84 return; 85 } 86 if (scon->length == SIZE_CONSOLE_BUFFER) { 87 /* Eat the character, but still process CR and LF. */ 88 return; 89 } 90 scon->buf[scon->length] = *buf; 91 scon->length += 1; 92 if (scon->echo) { 93 /* XXX this blocks entire thread. Rewrite to use 94 * qemu_chr_fe_write and background I/O callbacks */ 95 qemu_chr_fe_write_all(&scon->chr, buf, size); 96 } 97 } 98 99 /* functions to be called by event facility */ 100 101 static bool can_handle_event(uint8_t type) 102 { 103 return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD; 104 } 105 106 static sccb_mask_t send_mask(void) 107 { 108 return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD; 109 } 110 111 static sccb_mask_t receive_mask(void) 112 { 113 return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD; 114 } 115 116 /* 117 * Triggered by SCLP's read_event_data 118 * - convert ASCII byte stream to EBCDIC and 119 * - copy converted data into provided (SCLP) buffer 120 */ 121 static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, 122 int avail) 123 { 124 int len; 125 126 SCLPConsoleLM *cons = SCLPLM_CONSOLE(event); 127 128 len = cons->length; 129 /* data need to fit into provided SCLP buffer */ 130 if (len > avail) { 131 return 1; 132 } 133 134 ebcdic_put(buf, (char *)&cons->buf, len); 135 *size = len; 136 cons->length = 0; 137 /* data provided and no more data pending */ 138 event->event_pending = false; 139 qemu_notify_event(); 140 return 0; 141 } 142 143 static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, 144 int *slen) 145 { 146 int avail, rc; 147 size_t src_len; 148 uint8_t *to; 149 OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr; 150 151 if (!event->event_pending) { 152 /* no data pending */ 153 return 0; 154 } 155 156 to = (uint8_t *)&oc->data; 157 avail = *slen - sizeof(OprtnsCommand); 158 rc = get_console_data(event, to, &src_len, avail); 159 if (rc) { 160 /* data didn't fit, try next SCCB */ 161 return 1; 162 } 163 164 oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU; 165 oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU)); 166 167 oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU; 168 oc->message_unit.cpmsu.length = 169 cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector)); 170 171 oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD; 172 oc->message_unit.text_command.length = 173 cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector))); 174 175 oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG; 176 oc->message_unit.self_def_text_message.length = 177 cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector))); 178 179 oc->message_unit.text_message.key = GDS_KEY_TEXTMSG; 180 oc->message_unit.text_message.length = 181 cpu_to_be16(sizeof(GdsSubvector) + src_len); 182 183 oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len); 184 oc->header.type = SCLP_EVENT_OPRTNS_COMMAND; 185 *slen = avail - src_len; 186 187 return 1; 188 } 189 190 /* 191 * Triggered by SCLP's write_event_data 192 * - write console data to character layer 193 * returns < 0 if an error occurred 194 */ 195 static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) 196 { 197 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 198 199 if (!qemu_chr_fe_backend_connected(&scon->chr)) { 200 /* If there's no backend, we can just say we consumed all data. */ 201 return len; 202 } 203 204 /* XXX this blocks entire thread. Rewrite to use 205 * qemu_chr_fe_write and background I/O callbacks */ 206 return qemu_chr_fe_write_all(&scon->chr, buf, len); 207 } 208 209 static int process_mdb(SCLPEvent *event, MDBO *mdbo) 210 { 211 int rc; 212 int len; 213 uint8_t buffer[SIZE_BUFFER]; 214 215 len = be16_to_cpu(mdbo->length); 216 len -= sizeof(mdbo->length) + sizeof(mdbo->type) 217 + sizeof(mdbo->mto.line_type_flags) 218 + sizeof(mdbo->mto.alarm_control) 219 + sizeof(mdbo->mto._reserved); 220 221 assert(len <= SIZE_BUFFER); 222 223 /* convert EBCDIC SCLP contents to ASCII console message */ 224 ascii_put(buffer, mdbo->mto.message, len); 225 rc = write_console_data(event, (uint8_t *)NEWLINE, 1); 226 if (rc < 0) { 227 return rc; 228 } 229 return write_console_data(event, buffer, len); 230 } 231 232 static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh) 233 { 234 int len; 235 int written; 236 int errors = 0; 237 MDBO *mdbo; 238 SclpMsg *data = (SclpMsg *) ebh; 239 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 240 241 len = be16_to_cpu(data->mdb.header.length); 242 if (len < sizeof(data->mdb.header)) { 243 return SCLP_RC_INCONSISTENT_LENGTHS; 244 } 245 len -= sizeof(data->mdb.header); 246 247 /* first check message buffers */ 248 mdbo = data->mdb.mdbo; 249 while (len > 0) { 250 if (be16_to_cpu(mdbo->length) > len 251 || be16_to_cpu(mdbo->length) == 0) { 252 return SCLP_RC_INCONSISTENT_LENGTHS; 253 } 254 len -= be16_to_cpu(mdbo->length); 255 mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 256 } 257 258 /* then execute */ 259 len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header); 260 mdbo = data->mdb.mdbo; 261 while (len > 0) { 262 switch (be16_to_cpu(mdbo->type)) { 263 case MESSAGE_TEXT: 264 /* message text object */ 265 written = process_mdb(event, mdbo); 266 if (written < 0) { 267 /* character layer error */ 268 errors++; 269 } 270 break; 271 default: /* ignore */ 272 break; 273 } 274 len -= be16_to_cpu(mdbo->length); 275 mdbo = (void *) mdbo + be16_to_cpu(mdbo->length); 276 } 277 if (errors) { 278 scon->write_errors += errors; 279 } 280 data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED; 281 282 return SCLP_RC_NORMAL_COMPLETION; 283 } 284 285 /* functions for live migration */ 286 287 static const VMStateDescription vmstate_sclplmconsole = { 288 .name = "sclplmconsole", 289 .version_id = 0, 290 .minimum_version_id = 0, 291 .fields = (VMStateField[]) { 292 VMSTATE_BOOL(event.event_pending, SCLPConsoleLM), 293 VMSTATE_UINT32(write_errors, SCLPConsoleLM), 294 VMSTATE_UINT32(length, SCLPConsoleLM), 295 VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER), 296 VMSTATE_END_OF_LIST() 297 } 298 }; 299 300 /* qemu object creation and initialization functions */ 301 302 /* tell character layer our call-back functions */ 303 304 static int console_init(SCLPEvent *event) 305 { 306 static bool console_available; 307 308 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 309 310 if (console_available) { 311 error_report("Multiple line-mode operator consoles are not supported"); 312 return -1; 313 } 314 console_available = true; 315 316 qemu_chr_fe_set_handlers(&scon->chr, chr_can_read, 317 chr_read, NULL, NULL, scon, NULL, true); 318 319 return 0; 320 } 321 322 static void console_reset(DeviceState *dev) 323 { 324 SCLPEvent *event = SCLP_EVENT(dev); 325 SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); 326 327 event->event_pending = false; 328 scon->length = 0; 329 scon->write_errors = 0; 330 } 331 332 static Property console_properties[] = { 333 DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr), 334 DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0), 335 DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true), 336 DEFINE_PROP_END_OF_LIST(), 337 }; 338 339 static void console_class_init(ObjectClass *klass, void *data) 340 { 341 DeviceClass *dc = DEVICE_CLASS(klass); 342 SCLPEventClass *ec = SCLP_EVENT_CLASS(klass); 343 344 dc->props = console_properties; 345 dc->reset = console_reset; 346 dc->vmsd = &vmstate_sclplmconsole; 347 ec->init = console_init; 348 ec->get_send_mask = send_mask; 349 ec->get_receive_mask = receive_mask; 350 ec->can_handle_event = can_handle_event; 351 ec->read_event_data = read_event_data; 352 ec->write_event_data = write_event_data; 353 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 354 } 355 356 static const TypeInfo sclp_console_info = { 357 .name = "sclplmconsole", 358 .parent = TYPE_SCLP_EVENT, 359 .instance_size = sizeof(SCLPConsoleLM), 360 .class_init = console_class_init, 361 .class_size = sizeof(SCLPEventClass), 362 }; 363 364 static void register_types(void) 365 { 366 type_register_static(&sclp_console_info); 367 } 368 369 type_init(register_types) 370