1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * SCLP line mode and ASCII console driver 4 * Some parts taken from the Linux kernel. 5 * 6 * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 7 * 8 * Copyright IBM Corp. 1999 9 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 10 * Martin Schwidefsky <schwidefsky@de.ibm.com> 11 */ 12 13 #include <libcflat.h> 14 #include <string.h> 15 #include <asm/page.h> 16 #include <asm/arch_def.h> 17 #include <asm/io.h> 18 #include <asm/spinlock.h> 19 #include "hardware.h" 20 #include "sclp.h" 21 22 /* 23 * ASCII (IBM PC 437) -> EBCDIC 037 24 */ 25 static uint8_t _ascebc[256] = { 26 /*00 NUL SOH STX ETX EOT ENQ ACK BEL */ 27 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 28 /*08 BS HT LF VT FF CR SO SI */ 29 /* ->NL */ 30 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 31 /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ 32 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 33 /*18 CAN EM SUB ESC FS GS RS US */ 34 /* ->IGS ->IRS ->IUS */ 35 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, 36 /*20 SP ! " # $ % & ' */ 37 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 38 /*28 ( ) * + , - . / */ 39 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, 40 /*30 0 1 2 3 4 5 6 7 */ 41 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 42 /*38 8 9 : ; < = > ? */ 43 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, 44 /*40 @ A B C D E F G */ 45 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 46 /*48 H I J K L M N O */ 47 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 48 /*50 P Q R S T U V W */ 49 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 50 /*58 X Y Z [ \ ] ^ _ */ 51 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, 52 /*60 ` a b c d e f g */ 53 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 54 /*68 h i j k l m n o */ 55 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 56 /*70 p q r s t u v w */ 57 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 58 /*78 x y z { | } ~ DL */ 59 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, 60 /*80*/ 61 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 62 /*88*/ 63 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 64 /*90*/ 65 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 66 /*98*/ 67 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 68 /*A0*/ 69 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 70 /*A8*/ 71 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 72 /*B0*/ 73 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 74 /*B8*/ 75 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 76 /*C0*/ 77 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 78 /*C8*/ 79 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 80 /*D0*/ 81 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 82 /*D8*/ 83 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 84 /*E0 sz */ 85 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 86 /*E8*/ 87 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 88 /*F0*/ 89 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 90 /*F8*/ 91 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF 92 }; 93 94 static const uint8_t _ebcasc[] = { 95 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, 96 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 97 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, 98 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 99 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, 100 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, 101 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, 102 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, 103 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, 104 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, 105 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, 106 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, 107 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, 108 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, 109 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 110 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, 111 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 112 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, 113 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 114 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, 115 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 116 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, 117 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, 118 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07, 119 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 120 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, 121 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 122 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, 123 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 124 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, 125 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 126 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07, 127 }; 128 129 static bool lpar_ascii_compat; 130 131 static char lm_buff[120]; 132 static unsigned char lm_buff_off; 133 static struct spinlock lm_buff_lock; 134 135 static char read_buf[4096]; 136 static int read_index = sizeof(read_buf) - 1; 137 static int read_buf_length = 0; 138 139 static void sclp_print_ascii(const char *str) 140 { 141 int len = strlen(str); 142 WriteEventData *sccb = (void *)_sccb; 143 char *str_dest = (char *)&sccb->msg; 144 int src_ind, dst_ind; 145 146 sclp_mark_busy(); 147 memset(sccb, 0, sizeof(*sccb)); 148 149 for (src_ind = 0, dst_ind = 0; 150 src_ind < len && dst_ind < (PAGE_SIZE / 2); 151 src_ind++, dst_ind++) { 152 str_dest[dst_ind] = str[src_ind]; 153 /* Add a \r to the \n for HMC ASCII console */ 154 if (str[src_ind] == '\n' && lpar_ascii_compat) { 155 dst_ind++; 156 str_dest[dst_ind] = '\r'; 157 } 158 } 159 160 /* Len might have changed because of the compat behavior */ 161 len = dst_ind; 162 sccb->h.length = offsetof(WriteEventData, msg) + len; 163 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 164 sccb->ebh.length = sizeof(EventBufferHeader) + len; 165 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 166 167 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 168 } 169 170 static void lm_print(const char *buff, int len) 171 { 172 unsigned char *ptr, *end, ch; 173 unsigned int count, offset; 174 struct WriteEventData *sccb; 175 struct mdb *mdb; 176 struct mto *mto; 177 struct go *go; 178 179 sclp_mark_busy(); 180 sccb = (struct WriteEventData *) _sccb; 181 end = (unsigned char *) sccb + 4096 - 1; 182 memset(sccb, 0, sizeof(*sccb)); 183 ptr = (unsigned char *) &sccb->msg.mdb.mto; 184 offset = 0; 185 do { 186 for (count = sizeof(*mto); offset < len; count++) { 187 ch = buff[offset++]; 188 if (ch == 0x0a || ptr + count > end) 189 break; 190 ptr[count] = _ascebc[ch]; 191 } 192 mto = (struct mto *) ptr; 193 mto->length = count; 194 mto->type = 4; 195 mto->line_type_flags = LNTPFLGS_ENDTEXT; 196 ptr += count; 197 } while (offset < len && ptr + sizeof(*mto) <= end); 198 len = ptr - (unsigned char *) sccb; 199 sccb->h.length = len - offsetof(struct WriteEventData, h); 200 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 201 sccb->ebh.type = EVTYP_MSG; 202 sccb->ebh.length = len - offsetof(struct WriteEventData, ebh); 203 mdb = &sccb->msg.mdb; 204 mdb->header.type = 1; 205 mdb->header.tag = 0xD4C4C240; 206 mdb->header.revision_code = 1; 207 mdb->header.length = len - offsetof(struct WriteEventData, msg.mdb.header); 208 go = &mdb->go; 209 go->length = sizeof(*go); 210 go->type = 1; 211 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 212 } 213 214 215 /* 216 * In contrast to the ascii console, linemode produces a new 217 * line with every write of data. The report() function uses 218 * several printf() calls to generate a line of data which 219 * would all end up on different lines. 220 * 221 * Hence we buffer here until we encounter a \n or the buffer 222 * is full. That means that linemode output can look a bit 223 * different from ascii and that it takes a bit longer for 224 * lines to appear. 225 */ 226 static void sclp_print_lm(const char *str) 227 { 228 int i; 229 const int len = strlen(str); 230 231 spin_lock(&lm_buff_lock); 232 233 for (i = 0; i < len; i++) { 234 lm_buff[lm_buff_off++] = str[i]; 235 236 /* Buffer full or newline? */ 237 if (str[i] == '\n' || lm_buff_off == (ARRAY_SIZE(lm_buff) - 1)) { 238 lm_print(lm_buff, lm_buff_off); 239 lm_buff_off = 0; 240 } 241 } 242 spin_unlock(&lm_buff_lock); 243 } 244 245 /* 246 * SCLP needs to be initialized by setting a send and receive mask, 247 * indicating which messages the control program (we) want(s) to 248 * send/receive. 249 */ 250 static void sclp_write_event_mask(int receive_mask, int send_mask) 251 { 252 WriteEventMask *sccb = (void *)_sccb; 253 254 sclp_mark_busy(); 255 memset(_sccb, 0, sizeof(*sccb)); 256 sccb->h.length = sizeof(WriteEventMask); 257 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 258 sccb->mask_length = sizeof(sccb_mask_t); 259 260 sccb->cp_receive_mask = receive_mask; 261 sccb->cp_send_mask = send_mask; 262 263 sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 264 assert(sccb->h.response_code == SCLP_RC_NORMAL_COMPLETION); 265 } 266 267 static void sclp_console_enable_read(void) 268 { 269 sclp_write_event_mask(SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_OPCMD, 270 SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 271 } 272 273 static void sclp_console_disable_read(void) 274 { 275 sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 276 } 277 278 void sclp_console_setup(void) 279 { 280 lpar_ascii_compat = detect_host() == HOST_IS_LPAR; 281 282 /* We send ASCII and line mode. */ 283 sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 284 /* Hard terminal reset to clear screen for HMC ASCII console */ 285 if (lpar_ascii_compat) 286 sclp_print_ascii("\ec"); 287 } 288 289 void sclp_print(const char *str) 290 { 291 /* 292 * z/VM advertises a vt220 console which is not functional: 293 * (response code 05F0, "not active because of the state of 294 * the machine"). Hence testing the masks would only work if 295 * we also use stsi data to distinguish z/VM. 296 * 297 * Let's rather print on all available consoles. 298 */ 299 if (strlen(str) > (PAGE_SIZE / 2)) { 300 sclp_print_ascii("Warning: Printing is limited to 2KB of data."); 301 sclp_print_lm("Warning: Printing is limited to 2KB of data."); 302 return; 303 } 304 sclp_print_ascii(str); 305 sclp_print_lm(str); 306 } 307 308 static char *console_read_ascii(struct EventBufferHeader *ebh, int *len) 309 { 310 struct ReadEventDataAsciiConsole *evdata = (void *)ebh; 311 const int max_event_buffer_len = SCCB_SIZE - offsetof(ReadEventDataAsciiConsole, ebh); 312 const int event_buffer_ascii_recv_header_len = offsetof(ReadEventDataAsciiConsole, data); 313 314 assert(ebh->length <= max_event_buffer_len); 315 assert(ebh->length > event_buffer_ascii_recv_header_len); 316 317 *len = ebh->length - event_buffer_ascii_recv_header_len; 318 return evdata->data; 319 } 320 321 322 static struct gds_vector *sclp_find_gds_vector(void *start, void *end, uint16_t id) 323 { 324 struct gds_vector *v; 325 326 for (v = start; (void *)v < end; v = (void *)v + v->length) 327 if (v->gds_id == id) 328 return v; 329 return NULL; 330 } 331 332 static struct gds_subvector *sclp_eval_selfdeftextmsg(struct gds_subvector *sv) 333 { 334 void *end; 335 336 end = (void *)sv + sv->length; 337 for (sv = sv + 1; (void *)sv < end; sv = (void *)sv + sv->length) 338 if (sv->key == 0x30) 339 return sv; 340 return NULL; 341 } 342 343 static struct gds_subvector *sclp_eval_textcmd(struct gds_vector *v) 344 { 345 struct gds_subvector *sv; 346 void *end; 347 348 end = (void *)v + v->length; 349 for (sv = (struct gds_subvector *)(v + 1); (void *)sv < end; 350 sv = (void *)sv + sv->length) 351 if (sv->key == GDS_KEY_SELFDEFTEXTMSG) 352 return sclp_eval_selfdeftextmsg(sv); 353 return NULL; 354 } 355 356 static struct gds_subvector *sclp_eval_cpmsu(struct gds_vector *v) 357 { 358 void *end; 359 360 end = (void *)v + v->length; 361 for (v = v + 1; (void *)v < end; v = (void *)v + v->length) 362 if (v->gds_id == GDS_ID_TEXTCMD) 363 return sclp_eval_textcmd(v); 364 return NULL; 365 } 366 367 static struct gds_subvector *sclp_eval_mdsmu(struct gds_vector *v) 368 { 369 v = sclp_find_gds_vector(v + 1, (void *)v + v->length, GDS_ID_CPMSU); 370 if (v) 371 return sclp_eval_cpmsu(v); 372 return NULL; 373 } 374 375 static char *console_read_lm(struct EventBufferHeader *ebh, int *len) 376 { 377 struct gds_vector *v = (void *)ebh + sizeof(*ebh); 378 struct gds_subvector *sv; 379 380 v = sclp_find_gds_vector(v, (void *)ebh + ebh->length, 381 GDS_ID_MDSMU); 382 if (!v) 383 return NULL; 384 385 sv = sclp_eval_mdsmu(v); 386 if (!sv) 387 return NULL; 388 389 *len = sv->length - (sizeof(*sv)); 390 return (char *)(sv + 1); 391 } 392 393 static void ebc_to_asc(char *data, int len) 394 { 395 int i; 396 397 for (i = 0; i < len; i++) 398 data[i] = _ebcasc[(uint8_t)data[i]]; 399 } 400 401 static int console_refill_read_buffer(void) 402 { 403 struct SCCBHeader *sccb = (struct SCCBHeader *)_sccb; 404 struct EventBufferHeader *ebh = (void *)_sccb + sizeof(struct SCCBHeader); 405 char *data; 406 int ret = -1, len; 407 408 sclp_console_enable_read(); 409 410 sclp_mark_busy(); 411 memset(_sccb, 0, SCCB_SIZE); 412 sccb->length = PAGE_SIZE; 413 sccb->function_code = SCLP_UNCONDITIONAL_READ; 414 sccb->control_mask[2] = SCLP_CM2_VARIABLE_LENGTH_RESPONSE; 415 416 sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb); 417 418 if (sccb->response_code == SCLP_RC_NO_EVENT_BUFFERS_STORED) 419 goto out; 420 421 switch (ebh->type) { 422 case SCLP_EVENT_OP_CMD: 423 data = console_read_lm(ebh, &len); 424 if (data) 425 ebc_to_asc(data, len); 426 break; 427 case SCLP_EVENT_ASCII_CONSOLE_DATA: 428 data = console_read_ascii(ebh, &len); 429 break; 430 default: 431 goto out; 432 } 433 434 if (!data) 435 goto out; 436 437 assert(len <= sizeof(read_buf)); 438 memcpy(read_buf, data, len); 439 440 read_index = 0; 441 ret = 0; 442 443 out: 444 sclp_console_disable_read(); 445 446 return ret; 447 } 448 449 int __getchar(void) 450 { 451 int ret; 452 453 if (read_index >= read_buf_length) { 454 ret = console_refill_read_buffer(); 455 if (ret < 0) 456 return ret; 457 } 458 459 return read_buf[read_index++]; 460 } 461