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
sclp_print_ascii(const char * str)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
lm_print(const char * buff,int len)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 */
sclp_print_lm(const char * str)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 */
sclp_write_event_mask(int receive_mask,int send_mask)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
sclp_console_enable_read(void)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
sclp_console_disable_read(void)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
sclp_console_setup(void)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
sclp_print(const char * str)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
console_read_ascii(struct EventBufferHeader * ebh,int * len)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
sclp_find_gds_vector(void * start,void * end,uint16_t id)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
sclp_eval_selfdeftextmsg(struct gds_subvector * sv)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
sclp_eval_textcmd(struct gds_vector * v)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
sclp_eval_cpmsu(struct gds_vector * v)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
sclp_eval_mdsmu(struct gds_vector * v)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
console_read_lm(struct EventBufferHeader * ebh,int * len)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
ebc_to_asc(char * data,int len)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
console_refill_read_buffer(void)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
__getchar(void)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