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 <asm/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 28static 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 */ 35static 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 */ 46struct sclp_buffer * 47sclp_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 */ 78void * 79sclp_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 */ 88static int 89sclp_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 */ 138static void 139sclp_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 */ 175int 176sclp_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 */ 311int 312sclp_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 */ 327int 328sclp_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 */ 341void 342sclp_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 350void 351sclp_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 */ 359int 360sclp_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 */ 380static void 381sclp_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 */ 448int 449sclp_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