Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / s390 / char / sclp_rw.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * driver: reading from and writing to system console on S/390 via SCLP
4  *
5  * Copyright IBM Corp. 1999, 2009
6  *
7  * Author(s): Martin Peschke <mpeschke@de.ibm.com>
8  *            Martin Schwidefsky <schwidefsky@de.ibm.com>
9  */
10
11 #include <linux/kmod.h>
12 #include <linux/types.h>
13 #include <linux/err.h>
14 #include <linux/string.h>
15 #include <linux/spinlock.h>
16 #include <linux/ctype.h>
17 #include <linux/uaccess.h>
18
19 #include "sclp.h"
20 #include "sclp_rw.h"
21
22 /*
23  * The room for the SCCB (only for writing) is not equal to a pages size
24  * (as it is specified as the maximum size in the SCLP documentation)
25  * because of the additional data structure described above.
26  */
27 #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
28
29 static void sclp_rw_pm_event(struct sclp_register *reg,
30                              enum sclp_pm_event sclp_pm_event)
31 {
32         sclp_console_pm_event(sclp_pm_event);
33 }
34
35 /* Event type structure for write message and write priority message */
36 static struct sclp_register sclp_rw_event = {
37         .send_mask = EVTYP_MSG_MASK,
38         .pm_event_fn = sclp_rw_pm_event,
39 };
40
41 /*
42  * Setup a sclp write buffer. Gets a page as input (4K) and returns
43  * a pointer to a struct sclp_buffer structure that is located at the
44  * end of the input page. This reduces the buffer space by a few
45  * bytes but simplifies things.
46  */
47 struct sclp_buffer *
48 sclp_make_buffer(void *page, unsigned short columns, unsigned short htab)
49 {
50         struct sclp_buffer *buffer;
51         struct sccb_header *sccb;
52
53         sccb = (struct sccb_header *) page;
54         /*
55          * We keep the struct sclp_buffer structure at the end
56          * of the sccb page.
57          */
58         buffer = ((struct sclp_buffer *) ((addr_t) sccb + PAGE_SIZE)) - 1;
59         buffer->sccb = sccb;
60         buffer->retry_count = 0;
61         buffer->messages = 0;
62         buffer->char_sum = 0;
63         buffer->current_line = NULL;
64         buffer->current_length = 0;
65         buffer->columns = columns;
66         buffer->htab = htab;
67
68         /* initialize sccb */
69         memset(sccb, 0, sizeof(struct sccb_header));
70         sccb->length = sizeof(struct sccb_header);
71
72         return buffer;
73 }
74
75 /*
76  * Return a pointer to the original page that has been used to create
77  * the buffer.
78  */
79 void *
80 sclp_unmake_buffer(struct sclp_buffer *buffer)
81 {
82         return buffer->sccb;
83 }
84
85 /*
86  * Initialize a new message the end of the provided buffer with
87  * enough room for max_len characters. Return 0 on success.
88  */
89 static int
90 sclp_initialize_mto(struct sclp_buffer *buffer, int max_len)
91 {
92         struct sccb_header *sccb;
93         struct msg_buf *msg;
94         struct mdb *mdb;
95         struct go *go;
96         struct mto *mto;
97         int msg_size;
98
99         /* max size of new message including message text  */
100         msg_size = sizeof(struct msg_buf) + max_len;
101
102         /* check if current buffer sccb can contain the mto */
103         sccb = buffer->sccb;
104         if ((MAX_SCCB_ROOM - sccb->length) < msg_size)
105                 return -ENOMEM;
106
107         msg = (struct msg_buf *)((addr_t) sccb + sccb->length);
108         memset(msg, 0, sizeof(struct msg_buf));
109         msg->header.length = sizeof(struct msg_buf);
110         msg->header.type = EVTYP_MSG;
111
112         mdb = &msg->mdb;
113         mdb->header.length = sizeof(struct mdb);
114         mdb->header.type = 1;
115         mdb->header.tag = 0xD4C4C240;   /* ebcdic "MDB " */
116         mdb->header.revision_code = 1;
117
118         go = &mdb->go;
119         go->length = sizeof(struct go);
120         go->type = 1;
121
122         mto = &mdb->mto;
123         mto->length = sizeof(struct mto);
124         mto->type = 4;  /* message text object */
125         mto->line_type_flags = LNTPFLGS_ENDTEXT; /* end text */
126
127         /* set pointer to first byte after struct mto. */
128         buffer->current_msg = msg;
129         buffer->current_line = (char *) (mto + 1);
130         buffer->current_length = 0;
131
132         return 0;
133 }
134
135 /*
136  * Finalize message initialized by sclp_initialize_mto(),
137  * updating the sizes of MTO, enclosing MDB, event buffer and SCCB.
138  */
139 static void
140 sclp_finalize_mto(struct sclp_buffer *buffer)
141 {
142         struct sccb_header *sccb;
143         struct msg_buf *msg;
144
145         /*
146          * update values of sizes
147          * (SCCB, Event(Message) Buffer, Message Data Block)
148          */
149         sccb = buffer->sccb;
150         msg = buffer->current_msg;
151         msg->header.length += buffer->current_length;
152         msg->mdb.header.length += buffer->current_length;
153         msg->mdb.mto.length += buffer->current_length;
154         sccb->length += msg->header.length;
155
156         /*
157          * count number of buffered messages (= number of Message Text
158          * Objects) and number of buffered characters
159          * for the SCCB currently used for buffering and at all
160          */
161         buffer->messages++;
162         buffer->char_sum += buffer->current_length;
163
164         buffer->current_line = NULL;
165         buffer->current_length = 0;
166         buffer->current_msg = NULL;
167 }
168
169 /*
170  * processing of a message including escape characters,
171  * returns number of characters written to the output sccb
172  * ("processed" means that is not guaranteed that the character have already
173  *  been sent to the SCLP but that it will be done at least next time the SCLP
174  *  is not busy)
175  */
176 int
177 sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
178 {
179         int spaces, i_msg;
180         int rc;
181
182         /*
183          * parse msg for escape sequences (\t,\v ...) and put formated
184          * msg into an mto (created by sclp_initialize_mto).
185          *
186          * We have to do this work ourselfs because there is no support for
187          * these characters on the native machine and only partial support
188          * under VM (Why does VM interpret \n but the native machine doesn't ?)
189          *
190          * Depending on i/o-control setting the message is always written
191          * immediately or we wait for a final new line maybe coming with the
192          * next message. Besides we avoid a buffer overrun by writing its
193          * content.
194          *
195          * RESTRICTIONS:
196          *
197          * \r and \b work within one line because we are not able to modify
198          * previous output that have already been accepted by the SCLP.
199          *
200          * \t combined with following \r is not correctly represented because
201          * \t is expanded to some spaces but \r does not know about a
202          * previous \t and decreases the current position by one column.
203          * This is in order to a slim and quick implementation.
204          */
205         for (i_msg = 0; i_msg < count; i_msg++) {
206                 switch (msg[i_msg]) {
207                 case '\n':      /* new line, line feed (ASCII)  */
208                         /* check if new mto needs to be created */
209                         if (buffer->current_line == NULL) {
210                                 rc = sclp_initialize_mto(buffer, 0);
211                                 if (rc)
212                                         return i_msg;
213                         }
214                         sclp_finalize_mto(buffer);
215                         break;
216                 case '\a':      /* bell, one for several times  */
217                         /* set SCLP sound alarm bit in General Object */
218                         if (buffer->current_line == NULL) {
219                                 rc = sclp_initialize_mto(buffer,
220                                                          buffer->columns);
221                                 if (rc)
222                                         return i_msg;
223                         }
224                         buffer->current_msg->mdb.go.general_msg_flags |=
225                                 GNRLMSGFLGS_SNDALRM;
226                         break;
227                 case '\t':      /* horizontal tabulator  */
228                         /* check if new mto needs to be created */
229                         if (buffer->current_line == NULL) {
230                                 rc = sclp_initialize_mto(buffer,
231                                                          buffer->columns);
232                                 if (rc)
233                                         return i_msg;
234                         }
235                         /* "go to (next htab-boundary + 1, same line)" */
236                         do {
237                                 if (buffer->current_length >= buffer->columns)
238                                         break;
239                                 /* ok, add a blank */
240                                 *buffer->current_line++ = 0x40;
241                                 buffer->current_length++;
242                         } while (buffer->current_length % buffer->htab);
243                         break;
244                 case '\f':      /* form feed  */
245                 case '\v':      /* vertical tabulator  */
246                         /* "go to (actual column, actual line + 1)" */
247                         /* = new line, leading spaces */
248                         if (buffer->current_line != NULL) {
249                                 spaces = buffer->current_length;
250                                 sclp_finalize_mto(buffer);
251                                 rc = sclp_initialize_mto(buffer,
252                                                          buffer->columns);
253                                 if (rc)
254                                         return i_msg;
255                                 memset(buffer->current_line, 0x40, spaces);
256                                 buffer->current_line += spaces;
257                                 buffer->current_length = spaces;
258                         } else {
259                                 /* one an empty line this is the same as \n */
260                                 rc = sclp_initialize_mto(buffer,
261                                                          buffer->columns);
262                                 if (rc)
263                                         return i_msg;
264                                 sclp_finalize_mto(buffer);
265                         }
266                         break;
267                 case '\b':      /* backspace  */
268                         /* "go to (actual column - 1, actual line)" */
269                         /* decrement counter indicating position, */
270                         /* do not remove last character */
271                         if (buffer->current_line != NULL &&
272                             buffer->current_length > 0) {
273                                 buffer->current_length--;
274                                 buffer->current_line--;
275                         }
276                         break;
277                 case 0x00:      /* end of string  */
278                         /* transfer current line to SCCB */
279                         if (buffer->current_line != NULL)
280                                 sclp_finalize_mto(buffer);
281                         /* skip the rest of the message including the 0 byte */
282                         i_msg = count - 1;
283                         break;
284                 default:        /* no escape character  */
285                         /* do not output unprintable characters */
286                         if (!isprint(msg[i_msg]))
287                                 break;
288                         /* check if new mto needs to be created */
289                         if (buffer->current_line == NULL) {
290                                 rc = sclp_initialize_mto(buffer,
291                                                          buffer->columns);
292                                 if (rc)
293                                         return i_msg;
294                         }
295                         *buffer->current_line++ = sclp_ascebc(msg[i_msg]);
296                         buffer->current_length++;
297                         break;
298                 }
299                 /* check if current mto is full */
300                 if (buffer->current_line != NULL &&
301                     buffer->current_length >= buffer->columns)
302                         sclp_finalize_mto(buffer);
303         }
304
305         /* return number of processed characters */
306         return i_msg;
307 }
308
309 /*
310  * Return the number of free bytes in the sccb
311  */
312 int
313 sclp_buffer_space(struct sclp_buffer *buffer)
314 {
315         struct sccb_header *sccb;
316         int count;
317
318         sccb = buffer->sccb;
319         count = MAX_SCCB_ROOM - sccb->length;
320         if (buffer->current_line != NULL)
321                 count -= sizeof(struct msg_buf) + buffer->current_length;
322         return count;
323 }
324
325 /*
326  * Return number of characters in buffer
327  */
328 int
329 sclp_chars_in_buffer(struct sclp_buffer *buffer)
330 {
331         int count;
332
333         count = buffer->char_sum;
334         if (buffer->current_line != NULL)
335                 count += buffer->current_length;
336         return count;
337 }
338
339 /*
340  * sets or provides some values that influence the drivers behaviour
341  */
342 void
343 sclp_set_columns(struct sclp_buffer *buffer, unsigned short columns)
344 {
345         buffer->columns = columns;
346         if (buffer->current_line != NULL &&
347             buffer->current_length > buffer->columns)
348                 sclp_finalize_mto(buffer);
349 }
350
351 void
352 sclp_set_htab(struct sclp_buffer *buffer, unsigned short htab)
353 {
354         buffer->htab = htab;
355 }
356
357 /*
358  * called by sclp_console_init and/or sclp_tty_init
359  */
360 int
361 sclp_rw_init(void)
362 {
363         static int init_done = 0;
364         int rc;
365
366         if (init_done)
367                 return 0;
368
369         rc = sclp_register(&sclp_rw_event);
370         if (rc == 0)
371                 init_done = 1;
372         return rc;
373 }
374
375 #define SCLP_BUFFER_MAX_RETRY           1
376
377 /*
378  * second half of Write Event Data-function that has to be done after
379  * interruption indicating completion of Service Call.
380  */
381 static void
382 sclp_writedata_callback(struct sclp_req *request, void *data)
383 {
384         int rc;
385         struct sclp_buffer *buffer;
386         struct sccb_header *sccb;
387
388         buffer = (struct sclp_buffer *) data;
389         sccb = buffer->sccb;
390
391         if (request->status == SCLP_REQ_FAILED) {
392                 if (buffer->callback != NULL)
393                         buffer->callback(buffer, -EIO);
394                 return;
395         }
396         /* check SCLP response code and choose suitable action  */
397         switch (sccb->response_code) {
398         case 0x0020 :
399                 /* Normal completion, buffer processed, message(s) sent */
400                 rc = 0;
401                 break;
402
403         case 0x0340: /* Contained SCLP equipment check */
404                 if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
405                         rc = -EIO;
406                         break;
407                 }
408                 /* remove processed buffers and requeue rest */
409                 if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
410                         /* not all buffers were processed */
411                         sccb->response_code = 0x0000;
412                         buffer->request.status = SCLP_REQ_FILLED;
413                         rc = sclp_add_request(request);
414                         if (rc == 0)
415                                 return;
416                 } else
417                         rc = 0;
418                 break;
419
420         case 0x0040: /* SCLP equipment check */
421         case 0x05f0: /* Target resource in improper state */
422                 if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
423                         rc = -EIO;
424                         break;
425                 }
426                 /* retry request */
427                 sccb->response_code = 0x0000;
428                 buffer->request.status = SCLP_REQ_FILLED;
429                 rc = sclp_add_request(request);
430                 if (rc == 0)
431                         return;
432                 break;
433         default:
434                 if (sccb->response_code == 0x71f0)
435                         rc = -ENOMEM;
436                 else
437                         rc = -EINVAL;
438                 break;
439         }
440         if (buffer->callback != NULL)
441                 buffer->callback(buffer, rc);
442 }
443
444 /*
445  * Setup the request structure in the struct sclp_buffer to do SCLP Write
446  * Event Data and pass the request to the core SCLP loop. Return zero on
447  * success, non-zero otherwise.
448  */
449 int
450 sclp_emit_buffer(struct sclp_buffer *buffer,
451                  void (*callback)(struct sclp_buffer *, int))
452 {
453         /* add current line if there is one */
454         if (buffer->current_line != NULL)
455                 sclp_finalize_mto(buffer);
456
457         /* Are there messages in the output buffer ? */
458         if (buffer->messages == 0)
459                 return -EIO;
460
461         buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
462         buffer->request.status = SCLP_REQ_FILLED;
463         buffer->request.callback = sclp_writedata_callback;
464         buffer->request.callback_data = buffer;
465         buffer->request.sccb = buffer->sccb;
466         buffer->callback = callback;
467         return sclp_add_request(&buffer->request);
468 }