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