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