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 #define SCLP_RW_PRINT_HEADER "sclp low level driver: " 23 24 /* 25 * The room for the SCCB (only for writing) is not equal to a pages size 26 * (as it is specified as the maximum size in the SCLP documentation) 27 * because of the additional data structure described above. 28 */ 29 #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) 30 31 /* Event type structure for write message and write priority message */ 32 static struct sclp_register sclp_rw_event = { 33 .send_mask = EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK 34 }; 35 36 /* 37 * Setup a sclp write buffer. Gets a page as input (4K) and returns 38 * a pointer to a struct sclp_buffer structure that is located at the 39 * end of the input page. This reduces the buffer space by a few 40 * bytes but simplifies things. 41 */ 42 struct sclp_buffer * 43 sclp_make_buffer(void *page, unsigned short columns, unsigned short htab) 44 { 45 struct sclp_buffer *buffer; 46 struct write_sccb *sccb; 47 48 sccb = (struct write_sccb *) page; 49 /* 50 * We keep the struct sclp_buffer structure at the end 51 * of the sccb page. 52 */ 53 buffer = ((struct sclp_buffer *) ((addr_t) sccb + PAGE_SIZE)) - 1; 54 buffer->sccb = sccb; 55 buffer->retry_count = 0; 56 buffer->mto_number = 0; 57 buffer->mto_char_sum = 0; 58 buffer->current_line = NULL; 59 buffer->current_length = 0; 60 buffer->columns = columns; 61 buffer->htab = htab; 62 63 /* initialize sccb */ 64 memset(sccb, 0, sizeof(struct write_sccb)); 65 sccb->header.length = sizeof(struct write_sccb); 66 sccb->msg_buf.header.length = sizeof(struct msg_buf); 67 sccb->msg_buf.header.type = EVTYP_MSG; 68 sccb->msg_buf.mdb.header.length = sizeof(struct mdb); 69 sccb->msg_buf.mdb.header.type = 1; 70 sccb->msg_buf.mdb.header.tag = 0xD4C4C240; /* ebcdic "MDB " */ 71 sccb->msg_buf.mdb.header.revision_code = 1; 72 sccb->msg_buf.mdb.go.length = sizeof(struct go); 73 sccb->msg_buf.mdb.go.type = 1; 74 75 return buffer; 76 } 77 78 /* 79 * Return a pointer to the original page that has been used to create 80 * the buffer. 81 */ 82 void * 83 sclp_unmake_buffer(struct sclp_buffer *buffer) 84 { 85 return buffer->sccb; 86 } 87 88 /* 89 * Initialize a new Message Text Object (MTO) at the end of the provided buffer 90 * with enough room for max_len characters. Return 0 on success. 91 */ 92 static int 93 sclp_initialize_mto(struct sclp_buffer *buffer, int max_len) 94 { 95 struct write_sccb *sccb; 96 struct mto *mto; 97 int mto_size; 98 99 /* max size of new Message Text Object including message text */ 100 mto_size = sizeof(struct mto) + max_len; 101 102 /* check if current buffer sccb can contain the mto */ 103 sccb = buffer->sccb; 104 if ((MAX_SCCB_ROOM - sccb->header.length) < mto_size) 105 return -ENOMEM; 106 107 /* find address of new message text object */ 108 mto = (struct mto *)(((addr_t) sccb) + sccb->header.length); 109 110 /* 111 * fill the new Message-Text Object, 112 * starting behind the former last byte of the SCCB 113 */ 114 memset(mto, 0, sizeof(struct mto)); 115 mto->length = sizeof(struct mto); 116 mto->type = 4; /* message text object */ 117 mto->line_type_flags = LNTPFLGS_ENDTEXT; /* end text */ 118 119 /* set pointer to first byte after struct mto. */ 120 buffer->current_line = (char *) (mto + 1); 121 buffer->current_length = 0; 122 123 return 0; 124 } 125 126 /* 127 * Finalize MTO initialized by sclp_initialize_mto(), updating the sizes of 128 * MTO, enclosing MDB, event buffer and SCCB. 129 */ 130 static void 131 sclp_finalize_mto(struct sclp_buffer *buffer) 132 { 133 struct write_sccb *sccb; 134 struct mto *mto; 135 int str_len, mto_size; 136 137 str_len = buffer->current_length; 138 buffer->current_line = NULL; 139 buffer->current_length = 0; 140 141 /* real size of new Message Text Object including message text */ 142 mto_size = sizeof(struct mto) + str_len; 143 144 /* find address of new message text object */ 145 sccb = buffer->sccb; 146 mto = (struct mto *)(((addr_t) sccb) + sccb->header.length); 147 148 /* set size of message text object */ 149 mto->length = mto_size; 150 151 /* 152 * update values of sizes 153 * (SCCB, Event(Message) Buffer, Message Data Block) 154 */ 155 sccb->header.length += mto_size; 156 sccb->msg_buf.header.length += mto_size; 157 sccb->msg_buf.mdb.header.length += mto_size; 158 159 /* 160 * count number of buffered messages (= number of Message Text 161 * Objects) and number of buffered characters 162 * for the SCCB currently used for buffering and at all 163 */ 164 buffer->mto_number++; 165 buffer->mto_char_sum += str_len; 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 buffer->sccb->msg_buf.mdb.go.general_msg_flags |= 218 GNRLMSGFLGS_SNDALRM; 219 break; 220 case '\t': /* horizontal tabulator */ 221 /* check if new mto needs to be created */ 222 if (buffer->current_line == NULL) { 223 rc = sclp_initialize_mto(buffer, 224 buffer->columns); 225 if (rc) 226 return i_msg; 227 } 228 /* "go to (next htab-boundary + 1, same line)" */ 229 do { 230 if (buffer->current_length >= buffer->columns) 231 break; 232 /* ok, add a blank */ 233 *buffer->current_line++ = 0x40; 234 buffer->current_length++; 235 } while (buffer->current_length % buffer->htab); 236 break; 237 case '\f': /* form feed */ 238 case '\v': /* vertical tabulator */ 239 /* "go to (actual column, actual line + 1)" */ 240 /* = new line, leading spaces */ 241 if (buffer->current_line != NULL) { 242 spaces = buffer->current_length; 243 sclp_finalize_mto(buffer); 244 rc = sclp_initialize_mto(buffer, 245 buffer->columns); 246 if (rc) 247 return i_msg; 248 memset(buffer->current_line, 0x40, spaces); 249 buffer->current_line += spaces; 250 buffer->current_length = spaces; 251 } else { 252 /* one an empty line this is the same as \n */ 253 rc = sclp_initialize_mto(buffer, 254 buffer->columns); 255 if (rc) 256 return i_msg; 257 sclp_finalize_mto(buffer); 258 } 259 break; 260 case '\b': /* backspace */ 261 /* "go to (actual column - 1, actual line)" */ 262 /* decrement counter indicating position, */ 263 /* do not remove last character */ 264 if (buffer->current_line != NULL && 265 buffer->current_length > 0) { 266 buffer->current_length--; 267 buffer->current_line--; 268 } 269 break; 270 case 0x00: /* end of string */ 271 /* transfer current line to SCCB */ 272 if (buffer->current_line != NULL) 273 sclp_finalize_mto(buffer); 274 /* skip the rest of the message including the 0 byte */ 275 i_msg = count - 1; 276 break; 277 default: /* no escape character */ 278 /* do not output unprintable characters */ 279 if (!isprint(msg[i_msg])) 280 break; 281 /* check if new mto needs to be created */ 282 if (buffer->current_line == NULL) { 283 rc = sclp_initialize_mto(buffer, 284 buffer->columns); 285 if (rc) 286 return i_msg; 287 } 288 *buffer->current_line++ = sclp_ascebc(msg[i_msg]); 289 buffer->current_length++; 290 break; 291 } 292 /* check if current mto is full */ 293 if (buffer->current_line != NULL && 294 buffer->current_length >= buffer->columns) 295 sclp_finalize_mto(buffer); 296 } 297 298 /* return number of processed characters */ 299 return i_msg; 300 } 301 302 /* 303 * Return the number of free bytes in the sccb 304 */ 305 int 306 sclp_buffer_space(struct sclp_buffer *buffer) 307 { 308 int count; 309 310 count = MAX_SCCB_ROOM - buffer->sccb->header.length; 311 if (buffer->current_line != NULL) 312 count -= sizeof(struct mto) + buffer->current_length; 313 return count; 314 } 315 316 /* 317 * Return number of characters in buffer 318 */ 319 int 320 sclp_chars_in_buffer(struct sclp_buffer *buffer) 321 { 322 int count; 323 324 count = buffer->mto_char_sum; 325 if (buffer->current_line != NULL) 326 count += buffer->current_length; 327 return count; 328 } 329 330 /* 331 * sets or provides some values that influence the drivers behaviour 332 */ 333 void 334 sclp_set_columns(struct sclp_buffer *buffer, unsigned short columns) 335 { 336 buffer->columns = columns; 337 if (buffer->current_line != NULL && 338 buffer->current_length > buffer->columns) 339 sclp_finalize_mto(buffer); 340 } 341 342 void 343 sclp_set_htab(struct sclp_buffer *buffer, unsigned short htab) 344 { 345 buffer->htab = htab; 346 } 347 348 /* 349 * called by sclp_console_init and/or sclp_tty_init 350 */ 351 int 352 sclp_rw_init(void) 353 { 354 static int init_done = 0; 355 int rc; 356 357 if (init_done) 358 return 0; 359 360 rc = sclp_register(&sclp_rw_event); 361 if (rc == 0) 362 init_done = 1; 363 return rc; 364 } 365 366 #define SCLP_BUFFER_MAX_RETRY 1 367 368 /* 369 * second half of Write Event Data-function that has to be done after 370 * interruption indicating completion of Service Call. 371 */ 372 static void 373 sclp_writedata_callback(struct sclp_req *request, void *data) 374 { 375 int rc; 376 struct sclp_buffer *buffer; 377 struct write_sccb *sccb; 378 379 buffer = (struct sclp_buffer *) data; 380 sccb = buffer->sccb; 381 382 if (request->status == SCLP_REQ_FAILED) { 383 if (buffer->callback != NULL) 384 buffer->callback(buffer, -EIO); 385 return; 386 } 387 /* check SCLP response code and choose suitable action */ 388 switch (sccb->header.response_code) { 389 case 0x0020 : 390 /* Normal completion, buffer processed, message(s) sent */ 391 rc = 0; 392 break; 393 394 case 0x0340: /* Contained SCLP equipment check */ 395 if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) { 396 rc = -EIO; 397 break; 398 } 399 /* remove processed buffers and requeue rest */ 400 if (sclp_remove_processed((struct sccb_header *) sccb) > 0) { 401 /* not all buffers were processed */ 402 sccb->header.response_code = 0x0000; 403 buffer->request.status = SCLP_REQ_FILLED; 404 rc = sclp_add_request(request); 405 if (rc == 0) 406 return; 407 } else 408 rc = 0; 409 break; 410 411 case 0x0040: /* SCLP equipment check */ 412 case 0x05f0: /* Target resource in improper state */ 413 if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) { 414 rc = -EIO; 415 break; 416 } 417 /* retry request */ 418 sccb->header.response_code = 0x0000; 419 buffer->request.status = SCLP_REQ_FILLED; 420 rc = sclp_add_request(request); 421 if (rc == 0) 422 return; 423 break; 424 default: 425 if (sccb->header.response_code == 0x71f0) 426 rc = -ENOMEM; 427 else 428 rc = -EINVAL; 429 break; 430 } 431 if (buffer->callback != NULL) 432 buffer->callback(buffer, rc); 433 } 434 435 /* 436 * Setup the request structure in the struct sclp_buffer to do SCLP Write 437 * Event Data and pass the request to the core SCLP loop. Return zero on 438 * success, non-zero otherwise. 439 */ 440 int 441 sclp_emit_buffer(struct sclp_buffer *buffer, 442 void (*callback)(struct sclp_buffer *, int)) 443 { 444 struct write_sccb *sccb; 445 446 /* add current line if there is one */ 447 if (buffer->current_line != NULL) 448 sclp_finalize_mto(buffer); 449 450 /* Are there messages in the output buffer ? */ 451 if (buffer->mto_number == 0) 452 return -EIO; 453 454 sccb = buffer->sccb; 455 if (sclp_rw_event.sclp_receive_mask & EVTYP_MSG_MASK) 456 /* Use normal write message */ 457 sccb->msg_buf.header.type = EVTYP_MSG; 458 else if (sclp_rw_event.sclp_receive_mask & EVTYP_PMSGCMD_MASK) 459 /* Use write priority message */ 460 sccb->msg_buf.header.type = EVTYP_PMSGCMD; 461 else 462 return -ENOSYS; 463 buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; 464 buffer->request.status = SCLP_REQ_FILLED; 465 buffer->request.callback = sclp_writedata_callback; 466 buffer->request.callback_data = buffer; 467 buffer->request.sccb = sccb; 468 buffer->callback = callback; 469 return sclp_add_request(&buffer->request); 470 } 471