]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/s390/char/sclp_rw.c
Replace <asm/uaccess.h> with <linux/uaccess.h> globally
[mirror_ubuntu-hirsute-kernel.git] / drivers / s390 / char / sclp_rw.c
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 }