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