root/drivers/s390/char/sclp_vt220.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sclp_vt220_process_queue
  2. sclp_vt220_callback
  3. __sclp_vt220_emit
  4. sclp_vt220_emit_current
  5. sclp_vt220_initialize_page
  6. sclp_vt220_space_left
  7. sclp_vt220_chars_stored
  8. sclp_vt220_add_msg
  9. sclp_vt220_timeout
  10. sclp_vt220_drop_buffer
  11. __sclp_vt220_write
  12. sclp_vt220_write
  13. sclp_vt220_reset_session
  14. sclp_vt220_handle_input
  15. sclp_vt220_reset_session
  16. sclp_vt220_handle_input
  17. sclp_vt220_receiver_fn
  18. sclp_vt220_open
  19. sclp_vt220_close
  20. sclp_vt220_put_char
  21. sclp_vt220_flush_chars
  22. sclp_vt220_write_room
  23. sclp_vt220_chars_in_buffer
  24. sclp_vt220_flush_buffer
  25. __sclp_vt220_free_pages
  26. __sclp_vt220_cleanup
  27. __sclp_vt220_init
  28. sclp_vt220_tty_init
  29. __sclp_vt220_flush_buffer
  30. sclp_vt220_resume
  31. sclp_vt220_suspend
  32. sclp_vt220_pm_event_fn
  33. sclp_vt220_con_write
  34. sclp_vt220_con_device
  35. sclp_vt220_notify
  36. sclp_vt220_con_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * SCLP VT220 terminal driver.
   4  *
   5  * Copyright IBM Corp. 2003, 2009
   6  *
   7  * Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/spinlock.h>
  12 #include <linux/list.h>
  13 #include <linux/wait.h>
  14 #include <linux/timer.h>
  15 #include <linux/kernel.h>
  16 #include <linux/sysrq.h>
  17 #include <linux/tty.h>
  18 #include <linux/tty_driver.h>
  19 #include <linux/tty_flip.h>
  20 #include <linux/errno.h>
  21 #include <linux/mm.h>
  22 #include <linux/major.h>
  23 #include <linux/console.h>
  24 #include <linux/kdev_t.h>
  25 #include <linux/interrupt.h>
  26 #include <linux/init.h>
  27 #include <linux/reboot.h>
  28 #include <linux/slab.h>
  29 
  30 #include <linux/uaccess.h>
  31 #include "sclp.h"
  32 #include "ctrlchar.h"
  33 
  34 #define SCLP_VT220_MAJOR                TTY_MAJOR
  35 #define SCLP_VT220_MINOR                65
  36 #define SCLP_VT220_DRIVER_NAME          "sclp_vt220"
  37 #define SCLP_VT220_DEVICE_NAME          "ttysclp"
  38 #define SCLP_VT220_CONSOLE_NAME         "ttyS"
  39 #define SCLP_VT220_CONSOLE_INDEX        1       /* console=ttyS1 */
  40 
  41 /* Representation of a single write request */
  42 struct sclp_vt220_request {
  43         struct list_head list;
  44         struct sclp_req sclp_req;
  45         int retry_count;
  46 };
  47 
  48 /* VT220 SCCB */
  49 struct sclp_vt220_sccb {
  50         struct sccb_header header;
  51         struct evbuf_header evbuf;
  52 };
  53 
  54 #define SCLP_VT220_MAX_CHARS_PER_BUFFER (PAGE_SIZE - \
  55                                          sizeof(struct sclp_vt220_request) - \
  56                                          sizeof(struct sclp_vt220_sccb))
  57 
  58 /* Structures and data needed to register tty driver */
  59 static struct tty_driver *sclp_vt220_driver;
  60 
  61 static struct tty_port sclp_vt220_port;
  62 
  63 /* Lock to protect internal data from concurrent access */
  64 static spinlock_t sclp_vt220_lock;
  65 
  66 /* List of empty pages to be used as write request buffers */
  67 static struct list_head sclp_vt220_empty;
  68 
  69 /* List of pending requests */
  70 static struct list_head sclp_vt220_outqueue;
  71 
  72 /* Suspend mode flag */
  73 static int sclp_vt220_suspended;
  74 
  75 /* Flag that output queue is currently running */
  76 static int sclp_vt220_queue_running;
  77 
  78 /* Timer used for delaying write requests to merge subsequent messages into
  79  * a single buffer */
  80 static struct timer_list sclp_vt220_timer;
  81 
  82 /* Pointer to current request buffer which has been partially filled but not
  83  * yet sent */
  84 static struct sclp_vt220_request *sclp_vt220_current_request;
  85 
  86 /* Number of characters in current request buffer */
  87 static int sclp_vt220_buffered_chars;
  88 
  89 /* Counter controlling core driver initialization. */
  90 static int __initdata sclp_vt220_init_count;
  91 
  92 /* Flag indicating that sclp_vt220_current_request should really
  93  * have been already queued but wasn't because the SCLP was processing
  94  * another buffer */
  95 static int sclp_vt220_flush_later;
  96 
  97 static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf);
  98 static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
  99                                    enum sclp_pm_event sclp_pm_event);
 100 static int __sclp_vt220_emit(struct sclp_vt220_request *request);
 101 static void sclp_vt220_emit_current(void);
 102 
 103 /* Registration structure for SCLP output event buffers */
 104 static struct sclp_register sclp_vt220_register = {
 105         .send_mask              = EVTYP_VT220MSG_MASK,
 106         .pm_event_fn            = sclp_vt220_pm_event_fn,
 107 };
 108 
 109 /* Registration structure for SCLP input event buffers */
 110 static struct sclp_register sclp_vt220_register_input = {
 111         .receive_mask           = EVTYP_VT220MSG_MASK,
 112         .receiver_fn            = sclp_vt220_receiver_fn,
 113 };
 114 
 115 
 116 /*
 117  * Put provided request buffer back into queue and check emit pending
 118  * buffers if necessary.
 119  */
 120 static void
 121 sclp_vt220_process_queue(struct sclp_vt220_request *request)
 122 {
 123         unsigned long flags;
 124         void *page;
 125 
 126         do {
 127                 /* Put buffer back to list of empty buffers */
 128                 page = request->sclp_req.sccb;
 129                 spin_lock_irqsave(&sclp_vt220_lock, flags);
 130                 /* Move request from outqueue to empty queue */
 131                 list_del(&request->list);
 132                 list_add_tail((struct list_head *) page, &sclp_vt220_empty);
 133                 /* Check if there is a pending buffer on the out queue. */
 134                 request = NULL;
 135                 if (!list_empty(&sclp_vt220_outqueue))
 136                         request = list_entry(sclp_vt220_outqueue.next,
 137                                              struct sclp_vt220_request, list);
 138                 if (!request || sclp_vt220_suspended) {
 139                         sclp_vt220_queue_running = 0;
 140                         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 141                         break;
 142                 }
 143                 spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 144         } while (__sclp_vt220_emit(request));
 145         if (request == NULL && sclp_vt220_flush_later)
 146                 sclp_vt220_emit_current();
 147         tty_port_tty_wakeup(&sclp_vt220_port);
 148 }
 149 
 150 #define SCLP_BUFFER_MAX_RETRY           1
 151 
 152 /*
 153  * Callback through which the result of a write request is reported by the
 154  * SCLP.
 155  */
 156 static void
 157 sclp_vt220_callback(struct sclp_req *request, void *data)
 158 {
 159         struct sclp_vt220_request *vt220_request;
 160         struct sclp_vt220_sccb *sccb;
 161 
 162         vt220_request = (struct sclp_vt220_request *) data;
 163         if (request->status == SCLP_REQ_FAILED) {
 164                 sclp_vt220_process_queue(vt220_request);
 165                 return;
 166         }
 167         sccb = (struct sclp_vt220_sccb *) vt220_request->sclp_req.sccb;
 168 
 169         /* Check SCLP response code and choose suitable action  */
 170         switch (sccb->header.response_code) {
 171         case 0x0020 :
 172                 break;
 173 
 174         case 0x05f0: /* Target resource in improper state */
 175                 break;
 176 
 177         case 0x0340: /* Contained SCLP equipment check */
 178                 if (++vt220_request->retry_count > SCLP_BUFFER_MAX_RETRY)
 179                         break;
 180                 /* Remove processed buffers and requeue rest */
 181                 if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
 182                         /* Not all buffers were processed */
 183                         sccb->header.response_code = 0x0000;
 184                         vt220_request->sclp_req.status = SCLP_REQ_FILLED;
 185                         if (sclp_add_request(request) == 0)
 186                                 return;
 187                 }
 188                 break;
 189 
 190         case 0x0040: /* SCLP equipment check */
 191                 if (++vt220_request->retry_count > SCLP_BUFFER_MAX_RETRY)
 192                         break;
 193                 sccb->header.response_code = 0x0000;
 194                 vt220_request->sclp_req.status = SCLP_REQ_FILLED;
 195                 if (sclp_add_request(request) == 0)
 196                         return;
 197                 break;
 198 
 199         default:
 200                 break;
 201         }
 202         sclp_vt220_process_queue(vt220_request);
 203 }
 204 
 205 /*
 206  * Emit vt220 request buffer to SCLP. Return zero on success, non-zero
 207  * otherwise.
 208  */
 209 static int
 210 __sclp_vt220_emit(struct sclp_vt220_request *request)
 211 {
 212         request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
 213         request->sclp_req.status = SCLP_REQ_FILLED;
 214         request->sclp_req.callback = sclp_vt220_callback;
 215         request->sclp_req.callback_data = (void *) request;
 216 
 217         return sclp_add_request(&request->sclp_req);
 218 }
 219 
 220 /*
 221  * Queue and emit current request.
 222  */
 223 static void
 224 sclp_vt220_emit_current(void)
 225 {
 226         unsigned long flags;
 227         struct sclp_vt220_request *request;
 228         struct sclp_vt220_sccb *sccb;
 229 
 230         spin_lock_irqsave(&sclp_vt220_lock, flags);
 231         if (sclp_vt220_current_request) {
 232                 sccb = (struct sclp_vt220_sccb *) 
 233                                 sclp_vt220_current_request->sclp_req.sccb;
 234                 /* Only emit buffers with content */
 235                 if (sccb->header.length != sizeof(struct sclp_vt220_sccb)) {
 236                         list_add_tail(&sclp_vt220_current_request->list,
 237                                       &sclp_vt220_outqueue);
 238                         sclp_vt220_current_request = NULL;
 239                         if (timer_pending(&sclp_vt220_timer))
 240                                 del_timer(&sclp_vt220_timer);
 241                 }
 242                 sclp_vt220_flush_later = 0;
 243         }
 244         if (sclp_vt220_queue_running || sclp_vt220_suspended)
 245                 goto out_unlock;
 246         if (list_empty(&sclp_vt220_outqueue))
 247                 goto out_unlock;
 248         request = list_first_entry(&sclp_vt220_outqueue,
 249                                    struct sclp_vt220_request, list);
 250         sclp_vt220_queue_running = 1;
 251         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 252 
 253         if (__sclp_vt220_emit(request))
 254                 sclp_vt220_process_queue(request);
 255         return;
 256 out_unlock:
 257         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 258 }
 259 
 260 #define SCLP_NORMAL_WRITE       0x00
 261 
 262 /*
 263  * Helper function to initialize a page with the sclp request structure.
 264  */
 265 static struct sclp_vt220_request *
 266 sclp_vt220_initialize_page(void *page)
 267 {
 268         struct sclp_vt220_request *request;
 269         struct sclp_vt220_sccb *sccb;
 270 
 271         /* Place request structure at end of page */
 272         request = ((struct sclp_vt220_request *)
 273                         ((addr_t) page + PAGE_SIZE)) - 1;
 274         request->retry_count = 0;
 275         request->sclp_req.sccb = page;
 276         /* SCCB goes at start of page */
 277         sccb = (struct sclp_vt220_sccb *) page;
 278         memset((void *) sccb, 0, sizeof(struct sclp_vt220_sccb));
 279         sccb->header.length = sizeof(struct sclp_vt220_sccb);
 280         sccb->header.function_code = SCLP_NORMAL_WRITE;
 281         sccb->header.response_code = 0x0000;
 282         sccb->evbuf.type = EVTYP_VT220MSG;
 283         sccb->evbuf.length = sizeof(struct evbuf_header);
 284 
 285         return request;
 286 }
 287 
 288 static inline unsigned int
 289 sclp_vt220_space_left(struct sclp_vt220_request *request)
 290 {
 291         struct sclp_vt220_sccb *sccb;
 292         sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
 293         return PAGE_SIZE - sizeof(struct sclp_vt220_request) -
 294                sccb->header.length;
 295 }
 296 
 297 static inline unsigned int
 298 sclp_vt220_chars_stored(struct sclp_vt220_request *request)
 299 {
 300         struct sclp_vt220_sccb *sccb;
 301         sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
 302         return sccb->evbuf.length - sizeof(struct evbuf_header);
 303 }
 304 
 305 /*
 306  * Add msg to buffer associated with request. Return the number of characters
 307  * added.
 308  */
 309 static int
 310 sclp_vt220_add_msg(struct sclp_vt220_request *request,
 311                    const unsigned char *msg, int count, int convertlf)
 312 {
 313         struct sclp_vt220_sccb *sccb;
 314         void *buffer;
 315         unsigned char c;
 316         int from;
 317         int to;
 318 
 319         if (count > sclp_vt220_space_left(request))
 320                 count = sclp_vt220_space_left(request);
 321         if (count <= 0)
 322                 return 0;
 323 
 324         sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
 325         buffer = (void *) ((addr_t) sccb + sccb->header.length);
 326 
 327         if (convertlf) {
 328                 /* Perform Linefeed conversion (0x0a -> 0x0a 0x0d)*/
 329                 for (from=0, to=0;
 330                      (from < count) && (to < sclp_vt220_space_left(request));
 331                      from++) {
 332                         /* Retrieve character */
 333                         c = msg[from];
 334                         /* Perform conversion */
 335                         if (c == 0x0a) {
 336                                 if (to + 1 < sclp_vt220_space_left(request)) {
 337                                         ((unsigned char *) buffer)[to++] = c;
 338                                         ((unsigned char *) buffer)[to++] = 0x0d;
 339                                 } else
 340                                         break;
 341 
 342                         } else
 343                                 ((unsigned char *) buffer)[to++] = c;
 344                 }
 345                 sccb->header.length += to;
 346                 sccb->evbuf.length += to;
 347                 return from;
 348         } else {
 349                 memcpy(buffer, (const void *) msg, count);
 350                 sccb->header.length += count;
 351                 sccb->evbuf.length += count;
 352                 return count;
 353         }
 354 }
 355 
 356 /*
 357  * Emit buffer after having waited long enough for more data to arrive.
 358  */
 359 static void
 360 sclp_vt220_timeout(struct timer_list *unused)
 361 {
 362         sclp_vt220_emit_current();
 363 }
 364 
 365 #define BUFFER_MAX_DELAY        HZ/20
 366 
 367 /*
 368  * Drop oldest console buffer if sclp_con_drop is set
 369  */
 370 static int
 371 sclp_vt220_drop_buffer(void)
 372 {
 373         struct list_head *list;
 374         struct sclp_vt220_request *request;
 375         void *page;
 376 
 377         if (!sclp_console_drop)
 378                 return 0;
 379         list = sclp_vt220_outqueue.next;
 380         if (sclp_vt220_queue_running)
 381                 /* The first element is in I/O */
 382                 list = list->next;
 383         if (list == &sclp_vt220_outqueue)
 384                 return 0;
 385         list_del(list);
 386         request = list_entry(list, struct sclp_vt220_request, list);
 387         page = request->sclp_req.sccb;
 388         list_add_tail((struct list_head *) page, &sclp_vt220_empty);
 389         return 1;
 390 }
 391 
 392 /* 
 393  * Internal implementation of the write function. Write COUNT bytes of data
 394  * from memory at BUF
 395  * to the SCLP interface. In case that the data does not fit into the current
 396  * write buffer, emit the current one and allocate a new one. If there are no
 397  * more empty buffers available, wait until one gets emptied. If DO_SCHEDULE
 398  * is non-zero, the buffer will be scheduled for emitting after a timeout -
 399  * otherwise the user has to explicitly call the flush function.
 400  * A non-zero CONVERTLF parameter indicates that 0x0a characters in the message
 401  * buffer should be converted to 0x0a 0x0d. After completion, return the number
 402  * of bytes written.
 403  */
 404 static int
 405 __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
 406                    int convertlf, int may_fail)
 407 {
 408         unsigned long flags;
 409         void *page;
 410         int written;
 411         int overall_written;
 412 
 413         if (count <= 0)
 414                 return 0;
 415         overall_written = 0;
 416         spin_lock_irqsave(&sclp_vt220_lock, flags);
 417         do {
 418                 /* Create an sclp output buffer if none exists yet */
 419                 if (sclp_vt220_current_request == NULL) {
 420                         if (list_empty(&sclp_vt220_empty))
 421                                 sclp_console_full++;
 422                         while (list_empty(&sclp_vt220_empty)) {
 423                                 if (may_fail || sclp_vt220_suspended)
 424                                         goto out;
 425                                 if (sclp_vt220_drop_buffer())
 426                                         break;
 427                                 spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 428 
 429                                 sclp_sync_wait();
 430                                 spin_lock_irqsave(&sclp_vt220_lock, flags);
 431                         }
 432                         page = (void *) sclp_vt220_empty.next;
 433                         list_del((struct list_head *) page);
 434                         sclp_vt220_current_request =
 435                                 sclp_vt220_initialize_page(page);
 436                 }
 437                 /* Try to write the string to the current request buffer */
 438                 written = sclp_vt220_add_msg(sclp_vt220_current_request,
 439                                              buf, count, convertlf);
 440                 overall_written += written;
 441                 if (written == count)
 442                         break;
 443                 /*
 444                  * Not all characters could be written to the current
 445                  * output buffer. Emit the buffer, create a new buffer
 446                  * and then output the rest of the string.
 447                  */
 448                 spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 449                 sclp_vt220_emit_current();
 450                 spin_lock_irqsave(&sclp_vt220_lock, flags);
 451                 buf += written;
 452                 count -= written;
 453         } while (count > 0);
 454         /* Setup timer to output current console buffer after some time */
 455         if (sclp_vt220_current_request != NULL &&
 456             !timer_pending(&sclp_vt220_timer) && do_schedule) {
 457                 sclp_vt220_timer.expires = jiffies + BUFFER_MAX_DELAY;
 458                 add_timer(&sclp_vt220_timer);
 459         }
 460 out:
 461         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 462         return overall_written;
 463 }
 464 
 465 /*
 466  * This routine is called by the kernel to write a series of
 467  * characters to the tty device.  The characters may come from
 468  * user space or kernel space.  This routine will return the
 469  * number of characters actually accepted for writing.
 470  */
 471 static int
 472 sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
 473 {
 474         return __sclp_vt220_write(buf, count, 1, 0, 1);
 475 }
 476 
 477 #define SCLP_VT220_SESSION_ENDED        0x01
 478 #define SCLP_VT220_SESSION_STARTED      0x80
 479 #define SCLP_VT220_SESSION_DATA         0x00
 480 
 481 #ifdef CONFIG_MAGIC_SYSRQ
 482 
 483 static int sysrq_pressed;
 484 static struct sysrq_work sysrq;
 485 
 486 static void sclp_vt220_reset_session(void)
 487 {
 488         sysrq_pressed = 0;
 489 }
 490 
 491 static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
 492 {
 493         int i;
 494 
 495         for (i = 0; i < count; i++) {
 496                 /* Handle magic sys request */
 497                 if (buffer[i] == ('O' ^ 0100)) { /* CTRL-O */
 498                         /*
 499                          * If pressed again, reset sysrq_pressed
 500                          * and flip CTRL-O character
 501                          */
 502                         sysrq_pressed = !sysrq_pressed;
 503                         if (sysrq_pressed)
 504                                 continue;
 505                 } else if (sysrq_pressed) {
 506                         sysrq.key = buffer[i];
 507                         schedule_sysrq_work(&sysrq);
 508                         sysrq_pressed = 0;
 509                         continue;
 510                 }
 511                 tty_insert_flip_char(&sclp_vt220_port, buffer[i], 0);
 512         }
 513 }
 514 
 515 #else
 516 
 517 static void sclp_vt220_reset_session(void)
 518 {
 519 }
 520 
 521 static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
 522 {
 523         tty_insert_flip_string(&sclp_vt220_port, buffer, count);
 524 }
 525 
 526 #endif
 527 
 528 /*
 529  * Called by the SCLP to report incoming event buffers.
 530  */
 531 static void
 532 sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
 533 {
 534         char *buffer;
 535         unsigned int count;
 536 
 537         buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
 538         count = evbuf->length - sizeof(struct evbuf_header);
 539 
 540         switch (*buffer) {
 541         case SCLP_VT220_SESSION_ENDED:
 542         case SCLP_VT220_SESSION_STARTED:
 543                 sclp_vt220_reset_session();
 544                 break;
 545         case SCLP_VT220_SESSION_DATA:
 546                 /* Send input to line discipline */
 547                 buffer++;
 548                 count--;
 549                 sclp_vt220_handle_input(buffer, count);
 550                 tty_flip_buffer_push(&sclp_vt220_port);
 551                 break;
 552         }
 553 }
 554 
 555 /*
 556  * This routine is called when a particular tty device is opened.
 557  */
 558 static int
 559 sclp_vt220_open(struct tty_struct *tty, struct file *filp)
 560 {
 561         if (tty->count == 1) {
 562                 tty_port_tty_set(&sclp_vt220_port, tty);
 563                 sclp_vt220_port.low_latency = 0;
 564                 if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
 565                         tty->winsize.ws_row = 24;
 566                         tty->winsize.ws_col = 80;
 567                 }
 568         }
 569         return 0;
 570 }
 571 
 572 /*
 573  * This routine is called when a particular tty device is closed.
 574  */
 575 static void
 576 sclp_vt220_close(struct tty_struct *tty, struct file *filp)
 577 {
 578         if (tty->count == 1)
 579                 tty_port_tty_set(&sclp_vt220_port, NULL);
 580 }
 581 
 582 /*
 583  * This routine is called by the kernel to write a single
 584  * character to the tty device.  If the kernel uses this routine,
 585  * it must call the flush_chars() routine (if defined) when it is
 586  * done stuffing characters into the driver.
 587  */
 588 static int
 589 sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
 590 {
 591         return __sclp_vt220_write(&ch, 1, 0, 0, 1);
 592 }
 593 
 594 /*
 595  * This routine is called by the kernel after it has written a
 596  * series of characters to the tty device using put_char().  
 597  */
 598 static void
 599 sclp_vt220_flush_chars(struct tty_struct *tty)
 600 {
 601         if (!sclp_vt220_queue_running)
 602                 sclp_vt220_emit_current();
 603         else
 604                 sclp_vt220_flush_later = 1;
 605 }
 606 
 607 /*
 608  * This routine returns the numbers of characters the tty driver
 609  * will accept for queuing to be written.  This number is subject
 610  * to change as output buffers get emptied, or if the output flow
 611  * control is acted.
 612  */
 613 static int
 614 sclp_vt220_write_room(struct tty_struct *tty)
 615 {
 616         unsigned long flags;
 617         struct list_head *l;
 618         int count;
 619 
 620         spin_lock_irqsave(&sclp_vt220_lock, flags);
 621         count = 0;
 622         if (sclp_vt220_current_request != NULL)
 623                 count = sclp_vt220_space_left(sclp_vt220_current_request);
 624         list_for_each(l, &sclp_vt220_empty)
 625                 count += SCLP_VT220_MAX_CHARS_PER_BUFFER;
 626         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 627         return count;
 628 }
 629 
 630 /*
 631  * Return number of buffered chars.
 632  */
 633 static int
 634 sclp_vt220_chars_in_buffer(struct tty_struct *tty)
 635 {
 636         unsigned long flags;
 637         struct list_head *l;
 638         struct sclp_vt220_request *r;
 639         int count;
 640 
 641         spin_lock_irqsave(&sclp_vt220_lock, flags);
 642         count = 0;
 643         if (sclp_vt220_current_request != NULL)
 644                 count = sclp_vt220_chars_stored(sclp_vt220_current_request);
 645         list_for_each(l, &sclp_vt220_outqueue) {
 646                 r = list_entry(l, struct sclp_vt220_request, list);
 647                 count += sclp_vt220_chars_stored(r);
 648         }
 649         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 650         return count;
 651 }
 652 
 653 /*
 654  * Pass on all buffers to the hardware. Return only when there are no more
 655  * buffers pending.
 656  */
 657 static void
 658 sclp_vt220_flush_buffer(struct tty_struct *tty)
 659 {
 660         sclp_vt220_emit_current();
 661 }
 662 
 663 /* Release allocated pages. */
 664 static void __init __sclp_vt220_free_pages(void)
 665 {
 666         struct list_head *page, *p;
 667 
 668         list_for_each_safe(page, p, &sclp_vt220_empty) {
 669                 list_del(page);
 670                 free_page((unsigned long) page);
 671         }
 672 }
 673 
 674 /* Release memory and unregister from sclp core. Controlled by init counting -
 675  * only the last invoker will actually perform these actions. */
 676 static void __init __sclp_vt220_cleanup(void)
 677 {
 678         sclp_vt220_init_count--;
 679         if (sclp_vt220_init_count != 0)
 680                 return;
 681         sclp_unregister(&sclp_vt220_register);
 682         __sclp_vt220_free_pages();
 683         tty_port_destroy(&sclp_vt220_port);
 684 }
 685 
 686 /* Allocate buffer pages and register with sclp core. Controlled by init
 687  * counting - only the first invoker will actually perform these actions. */
 688 static int __init __sclp_vt220_init(int num_pages)
 689 {
 690         void *page;
 691         int i;
 692         int rc;
 693 
 694         sclp_vt220_init_count++;
 695         if (sclp_vt220_init_count != 1)
 696                 return 0;
 697         spin_lock_init(&sclp_vt220_lock);
 698         INIT_LIST_HEAD(&sclp_vt220_empty);
 699         INIT_LIST_HEAD(&sclp_vt220_outqueue);
 700         timer_setup(&sclp_vt220_timer, sclp_vt220_timeout, 0);
 701         tty_port_init(&sclp_vt220_port);
 702         sclp_vt220_current_request = NULL;
 703         sclp_vt220_buffered_chars = 0;
 704         sclp_vt220_flush_later = 0;
 705 
 706         /* Allocate pages for output buffering */
 707         rc = -ENOMEM;
 708         for (i = 0; i < num_pages; i++) {
 709                 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 710                 if (!page)
 711                         goto out;
 712                 list_add_tail(page, &sclp_vt220_empty);
 713         }
 714         rc = sclp_register(&sclp_vt220_register);
 715 out:
 716         if (rc) {
 717                 __sclp_vt220_free_pages();
 718                 sclp_vt220_init_count--;
 719                 tty_port_destroy(&sclp_vt220_port);
 720         }
 721         return rc;
 722 }
 723 
 724 static const struct tty_operations sclp_vt220_ops = {
 725         .open = sclp_vt220_open,
 726         .close = sclp_vt220_close,
 727         .write = sclp_vt220_write,
 728         .put_char = sclp_vt220_put_char,
 729         .flush_chars = sclp_vt220_flush_chars,
 730         .write_room = sclp_vt220_write_room,
 731         .chars_in_buffer = sclp_vt220_chars_in_buffer,
 732         .flush_buffer = sclp_vt220_flush_buffer,
 733 };
 734 
 735 /*
 736  * Register driver with SCLP and Linux and initialize internal tty structures.
 737  */
 738 static int __init sclp_vt220_tty_init(void)
 739 {
 740         struct tty_driver *driver;
 741         int rc;
 742 
 743         /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
 744          * symmetry between VM and LPAR systems regarding ttyS1. */
 745         driver = alloc_tty_driver(1);
 746         if (!driver)
 747                 return -ENOMEM;
 748         rc = __sclp_vt220_init(MAX_KMEM_PAGES);
 749         if (rc)
 750                 goto out_driver;
 751 
 752         driver->driver_name = SCLP_VT220_DRIVER_NAME;
 753         driver->name = SCLP_VT220_DEVICE_NAME;
 754         driver->major = SCLP_VT220_MAJOR;
 755         driver->minor_start = SCLP_VT220_MINOR;
 756         driver->type = TTY_DRIVER_TYPE_SYSTEM;
 757         driver->subtype = SYSTEM_TYPE_TTY;
 758         driver->init_termios = tty_std_termios;
 759         driver->flags = TTY_DRIVER_REAL_RAW;
 760         tty_set_operations(driver, &sclp_vt220_ops);
 761         tty_port_link_device(&sclp_vt220_port, driver, 0);
 762 
 763         rc = tty_register_driver(driver);
 764         if (rc)
 765                 goto out_init;
 766         rc = sclp_register(&sclp_vt220_register_input);
 767         if (rc)
 768                 goto out_reg;
 769         sclp_vt220_driver = driver;
 770         return 0;
 771 
 772 out_reg:
 773         tty_unregister_driver(driver);
 774 out_init:
 775         __sclp_vt220_cleanup();
 776 out_driver:
 777         put_tty_driver(driver);
 778         return rc;
 779 }
 780 __initcall(sclp_vt220_tty_init);
 781 
 782 static void __sclp_vt220_flush_buffer(void)
 783 {
 784         unsigned long flags;
 785 
 786         sclp_vt220_emit_current();
 787         spin_lock_irqsave(&sclp_vt220_lock, flags);
 788         if (timer_pending(&sclp_vt220_timer))
 789                 del_timer(&sclp_vt220_timer);
 790         while (sclp_vt220_queue_running) {
 791                 spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 792                 sclp_sync_wait();
 793                 spin_lock_irqsave(&sclp_vt220_lock, flags);
 794         }
 795         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 796 }
 797 
 798 /*
 799  * Resume console: If there are cached messages, emit them.
 800  */
 801 static void sclp_vt220_resume(void)
 802 {
 803         unsigned long flags;
 804 
 805         spin_lock_irqsave(&sclp_vt220_lock, flags);
 806         sclp_vt220_suspended = 0;
 807         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 808         sclp_vt220_emit_current();
 809 }
 810 
 811 /*
 812  * Suspend console: Set suspend flag and flush console
 813  */
 814 static void sclp_vt220_suspend(void)
 815 {
 816         unsigned long flags;
 817 
 818         spin_lock_irqsave(&sclp_vt220_lock, flags);
 819         sclp_vt220_suspended = 1;
 820         spin_unlock_irqrestore(&sclp_vt220_lock, flags);
 821         __sclp_vt220_flush_buffer();
 822 }
 823 
 824 static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
 825                                    enum sclp_pm_event sclp_pm_event)
 826 {
 827         switch (sclp_pm_event) {
 828         case SCLP_PM_EVENT_FREEZE:
 829                 sclp_vt220_suspend();
 830                 break;
 831         case SCLP_PM_EVENT_RESTORE:
 832         case SCLP_PM_EVENT_THAW:
 833                 sclp_vt220_resume();
 834                 break;
 835         }
 836 }
 837 
 838 #ifdef CONFIG_SCLP_VT220_CONSOLE
 839 
 840 static void
 841 sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
 842 {
 843         __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
 844 }
 845 
 846 static struct tty_driver *
 847 sclp_vt220_con_device(struct console *c, int *index)
 848 {
 849         *index = 0;
 850         return sclp_vt220_driver;
 851 }
 852 
 853 static int
 854 sclp_vt220_notify(struct notifier_block *self,
 855                           unsigned long event, void *data)
 856 {
 857         __sclp_vt220_flush_buffer();
 858         return NOTIFY_OK;
 859 }
 860 
 861 static struct notifier_block on_panic_nb = {
 862         .notifier_call = sclp_vt220_notify,
 863         .priority = 1,
 864 };
 865 
 866 static struct notifier_block on_reboot_nb = {
 867         .notifier_call = sclp_vt220_notify,
 868         .priority = 1,
 869 };
 870 
 871 /* Structure needed to register with printk */
 872 static struct console sclp_vt220_console =
 873 {
 874         .name = SCLP_VT220_CONSOLE_NAME,
 875         .write = sclp_vt220_con_write,
 876         .device = sclp_vt220_con_device,
 877         .flags = CON_PRINTBUFFER,
 878         .index = SCLP_VT220_CONSOLE_INDEX
 879 };
 880 
 881 static int __init
 882 sclp_vt220_con_init(void)
 883 {
 884         int rc;
 885 
 886         rc = __sclp_vt220_init(sclp_console_pages);
 887         if (rc)
 888                 return rc;
 889         /* Attach linux console */
 890         atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
 891         register_reboot_notifier(&on_reboot_nb);
 892         register_console(&sclp_vt220_console);
 893         return 0;
 894 }
 895 
 896 console_initcall(sclp_vt220_con_init);
 897 #endif /* CONFIG_SCLP_VT220_CONSOLE */
 898 

/* [<][>][^][v][top][bottom][index][help] */