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