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