1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * SCLP ASCII access driver 4 * 5 * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 6 */ 7 8 #include <libcflat.h> 9 #include <string.h> 10 #include <asm/page.h> 11 #include <asm/arch_def.h> 12 #include <asm/io.h> 13 #include <asm/spinlock.h> 14 #include "hardware.h" 15 #include "sclp.h" 16 17 /* 18 * ASCII (IBM PC 437) -> EBCDIC 037 19 */ 20 static uint8_t _ascebc[256] = { 21 /*00 NUL SOH STX ETX EOT ENQ ACK BEL */ 22 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 23 /*08 BS HT LF VT FF CR SO SI */ 24 /* ->NL */ 25 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 26 /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ 27 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 28 /*18 CAN EM SUB ESC FS GS RS US */ 29 /* ->IGS ->IRS ->IUS */ 30 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, 31 /*20 SP ! " # $ % & ' */ 32 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 33 /*28 ( ) * + , - . / */ 34 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, 35 /*30 0 1 2 3 4 5 6 7 */ 36 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 37 /*38 8 9 : ; < = > ? */ 38 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, 39 /*40 @ A B C D E F G */ 40 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 41 /*48 H I J K L M N O */ 42 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 43 /*50 P Q R S T U V W */ 44 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 45 /*58 X Y Z [ \ ] ^ _ */ 46 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, 47 /*60 ` a b c d e f g */ 48 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 49 /*68 h i j k l m n o */ 50 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 51 /*70 p q r s t u v w */ 52 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 53 /*78 x y z { | } ~ DL */ 54 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, 55 /*80*/ 56 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 57 /*88*/ 58 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 59 /*90*/ 60 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 61 /*98*/ 62 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 63 /*A0*/ 64 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 65 /*A8*/ 66 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 67 /*B0*/ 68 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 69 /*B8*/ 70 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 71 /*C0*/ 72 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 73 /*C8*/ 74 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 75 /*D0*/ 76 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 77 /*D8*/ 78 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 79 /*E0 sz */ 80 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 81 /*E8*/ 82 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 83 /*F0*/ 84 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 85 /*F8*/ 86 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF 87 }; 88 89 static bool lpar_ascii_compat; 90 91 static char lm_buff[120]; 92 static unsigned char lm_buff_off; 93 static struct spinlock lm_buff_lock; 94 95 static char read_buf[4096]; 96 static int read_index = sizeof(read_buf) - 1; 97 static int read_buf_length = 0; 98 99 static void sclp_print_ascii(const char *str) 100 { 101 int len = strlen(str); 102 WriteEventData *sccb = (void *)_sccb; 103 char *str_dest = (char *)&sccb->msg; 104 int src_ind, dst_ind; 105 106 sclp_mark_busy(); 107 memset(sccb, 0, sizeof(*sccb)); 108 109 for (src_ind = 0, dst_ind = 0; 110 src_ind < len && dst_ind < (PAGE_SIZE / 2); 111 src_ind++, dst_ind++) { 112 str_dest[dst_ind] = str[src_ind]; 113 /* Add a \r to the \n for HMC ASCII console */ 114 if (str[src_ind] == '\n' && lpar_ascii_compat) { 115 dst_ind++; 116 str_dest[dst_ind] = '\r'; 117 } 118 } 119 120 /* Len might have changed because of the compat behavior */ 121 len = dst_ind; 122 sccb->h.length = offsetof(WriteEventData, msg) + len; 123 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 124 sccb->ebh.length = sizeof(EventBufferHeader) + len; 125 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 126 127 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 128 } 129 130 static void lm_print(const char *buff, int len) 131 { 132 unsigned char *ptr, *end, ch; 133 unsigned int count, offset; 134 struct WriteEventData *sccb; 135 struct mdb *mdb; 136 struct mto *mto; 137 struct go *go; 138 139 sclp_mark_busy(); 140 sccb = (struct WriteEventData *) _sccb; 141 end = (unsigned char *) sccb + 4096 - 1; 142 memset(sccb, 0, sizeof(*sccb)); 143 ptr = (unsigned char *) &sccb->msg.mdb.mto; 144 offset = 0; 145 do { 146 for (count = sizeof(*mto); offset < len; count++) { 147 ch = buff[offset++]; 148 if (ch == 0x0a || ptr + count > end) 149 break; 150 ptr[count] = _ascebc[ch]; 151 } 152 mto = (struct mto *) ptr; 153 mto->length = count; 154 mto->type = 4; 155 mto->line_type_flags = LNTPFLGS_ENDTEXT; 156 ptr += count; 157 } while (offset < len && ptr + sizeof(*mto) <= end); 158 len = ptr - (unsigned char *) sccb; 159 sccb->h.length = len - offsetof(struct WriteEventData, h); 160 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 161 sccb->ebh.type = EVTYP_MSG; 162 sccb->ebh.length = len - offsetof(struct WriteEventData, ebh); 163 mdb = &sccb->msg.mdb; 164 mdb->header.type = 1; 165 mdb->header.tag = 0xD4C4C240; 166 mdb->header.revision_code = 1; 167 mdb->header.length = len - offsetof(struct WriteEventData, msg.mdb.header); 168 go = &mdb->go; 169 go->length = sizeof(*go); 170 go->type = 1; 171 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 172 } 173 174 175 /* 176 * In contrast to the ascii console, linemode produces a new 177 * line with every write of data. The report() function uses 178 * several printf() calls to generate a line of data which 179 * would all end up on different lines. 180 * 181 * Hence we buffer here until we encounter a \n or the buffer 182 * is full. That means that linemode output can look a bit 183 * different from ascii and that it takes a bit longer for 184 * lines to appear. 185 */ 186 static void sclp_print_lm(const char *str) 187 { 188 int i; 189 const int len = strlen(str); 190 191 spin_lock(&lm_buff_lock); 192 193 for (i = 0; i < len; i++) { 194 lm_buff[lm_buff_off++] = str[i]; 195 196 /* Buffer full or newline? */ 197 if (str[i] == '\n' || lm_buff_off == (ARRAY_SIZE(lm_buff) - 1)) { 198 lm_print(lm_buff, lm_buff_off); 199 lm_buff_off = 0; 200 } 201 } 202 spin_unlock(&lm_buff_lock); 203 } 204 205 /* 206 * SCLP needs to be initialized by setting a send and receive mask, 207 * indicating which messages the control program (we) want(s) to 208 * send/receive. 209 */ 210 static void sclp_write_event_mask(int receive_mask, int send_mask) 211 { 212 WriteEventMask *sccb = (void *)_sccb; 213 214 sclp_mark_busy(); 215 memset(_sccb, 0, sizeof(*sccb)); 216 sccb->h.length = sizeof(WriteEventMask); 217 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 218 sccb->mask_length = sizeof(sccb_mask_t); 219 220 sccb->cp_receive_mask = receive_mask; 221 sccb->cp_send_mask = send_mask; 222 223 sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 224 assert(sccb->h.response_code == SCLP_RC_NORMAL_COMPLETION); 225 } 226 227 static void sclp_console_enable_read(void) 228 { 229 sclp_write_event_mask(SCLP_EVENT_MASK_MSG_ASCII, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 230 } 231 232 static void sclp_console_disable_read(void) 233 { 234 sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 235 } 236 237 void sclp_console_setup(void) 238 { 239 lpar_ascii_compat = detect_host() == HOST_IS_LPAR; 240 241 /* We send ASCII and line mode. */ 242 sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); 243 /* Hard terminal reset to clear screen for HMC ASCII console */ 244 if (lpar_ascii_compat) 245 sclp_print_ascii("\ec"); 246 } 247 248 void sclp_print(const char *str) 249 { 250 /* 251 * z/VM advertises a vt220 console which is not functional: 252 * (response code 05F0, "not active because of the state of 253 * the machine"). Hence testing the masks would only work if 254 * we also use stsi data to distinguish z/VM. 255 * 256 * Let's rather print on all available consoles. 257 */ 258 if (strlen(str) > (PAGE_SIZE / 2)) { 259 sclp_print_ascii("Warning: Printing is limited to 2KB of data."); 260 sclp_print_lm("Warning: Printing is limited to 2KB of data."); 261 return; 262 } 263 sclp_print_ascii(str); 264 sclp_print_lm(str); 265 } 266 267 static int console_refill_read_buffer(void) 268 { 269 const int max_event_buffer_len = SCCB_SIZE - offsetof(ReadEventDataAsciiConsole, ebh); 270 ReadEventDataAsciiConsole *sccb = (void *)_sccb; 271 const int event_buffer_ascii_recv_header_len = sizeof(sccb->ebh) + sizeof(sccb->type); 272 int ret = -1; 273 274 sclp_console_enable_read(); 275 276 sclp_mark_busy(); 277 memset(sccb, 0, SCCB_SIZE); 278 sccb->h.length = PAGE_SIZE; 279 sccb->h.function_code = SCLP_UNCONDITIONAL_READ; 280 sccb->h.control_mask[2] = SCLP_CM2_VARIABLE_LENGTH_RESPONSE; 281 282 sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb); 283 284 if (sccb->h.response_code == SCLP_RC_NO_EVENT_BUFFERS_STORED || 285 sccb->ebh.type != SCLP_EVENT_ASCII_CONSOLE_DATA || 286 sccb->type != SCLP_EVENT_ASCII_TYPE_DATA_STREAM_FOLLOWS) { 287 ret = -1; 288 goto out; 289 } 290 291 assert(sccb->ebh.length <= max_event_buffer_len); 292 assert(sccb->ebh.length > event_buffer_ascii_recv_header_len); 293 294 read_buf_length = sccb->ebh.length - event_buffer_ascii_recv_header_len; 295 296 assert(read_buf_length <= sizeof(read_buf)); 297 memcpy(read_buf, sccb->data, read_buf_length); 298 299 read_index = 0; 300 ret = 0; 301 302 out: 303 sclp_console_disable_read(); 304 305 return ret; 306 } 307 308 int __getchar(void) 309 { 310 int ret; 311 312 if (read_index >= read_buf_length) { 313 ret = console_refill_read_buffer(); 314 if (ret < 0) 315 return ret; 316 } 317 318 return read_buf[read_index++]; 319 } 320