This source file includes following definitions.
- sclp_vt220_process_queue
 
- sclp_vt220_callback
 
- __sclp_vt220_emit
 
- sclp_vt220_emit_current
 
- sclp_vt220_initialize_page
 
- sclp_vt220_space_left
 
- sclp_vt220_chars_stored
 
- sclp_vt220_add_msg
 
- sclp_vt220_timeout
 
- sclp_vt220_drop_buffer
 
- __sclp_vt220_write
 
- sclp_vt220_write
 
- sclp_vt220_reset_session
 
- sclp_vt220_handle_input
 
- sclp_vt220_reset_session
 
- sclp_vt220_handle_input
 
- sclp_vt220_receiver_fn
 
- sclp_vt220_open
 
- sclp_vt220_close
 
- sclp_vt220_put_char
 
- sclp_vt220_flush_chars
 
- sclp_vt220_write_room
 
- sclp_vt220_chars_in_buffer
 
- sclp_vt220_flush_buffer
 
- __sclp_vt220_free_pages
 
- __sclp_vt220_cleanup
 
- __sclp_vt220_init
 
- sclp_vt220_tty_init
 
- __sclp_vt220_flush_buffer
 
- sclp_vt220_resume
 
- sclp_vt220_suspend
 
- sclp_vt220_pm_event_fn
 
- sclp_vt220_con_write
 
- sclp_vt220_con_device
 
- sclp_vt220_notify
 
- sclp_vt220_con_init
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   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       
  40 
  41 
  42 struct sclp_vt220_request {
  43         struct list_head list;
  44         struct sclp_req sclp_req;
  45         int retry_count;
  46 };
  47 
  48 
  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 
  59 static struct tty_driver *sclp_vt220_driver;
  60 
  61 static struct tty_port sclp_vt220_port;
  62 
  63 
  64 static spinlock_t sclp_vt220_lock;
  65 
  66 
  67 static struct list_head sclp_vt220_empty;
  68 
  69 
  70 static struct list_head sclp_vt220_outqueue;
  71 
  72 
  73 static int sclp_vt220_suspended;
  74 
  75 
  76 static int sclp_vt220_queue_running;
  77 
  78 
  79 
  80 static struct timer_list sclp_vt220_timer;
  81 
  82 
  83 
  84 static struct sclp_vt220_request *sclp_vt220_current_request;
  85 
  86 
  87 static int sclp_vt220_buffered_chars;
  88 
  89 
  90 static int __initdata sclp_vt220_init_count;
  91 
  92 
  93 
  94 
  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 
 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 
 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 
 118 
 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                 
 128                 page = request->sclp_req.sccb;
 129                 spin_lock_irqsave(&sclp_vt220_lock, flags);
 130                 
 131                 list_del(&request->list);
 132                 list_add_tail((struct list_head *) page, &sclp_vt220_empty);
 133                 
 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 
 154 
 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         
 170         switch (sccb->header.response_code) {
 171         case 0x0020 :
 172                 break;
 173 
 174         case 0x05f0: 
 175                 break;
 176 
 177         case 0x0340: 
 178                 if (++vt220_request->retry_count > SCLP_BUFFER_MAX_RETRY)
 179                         break;
 180                 
 181                 if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
 182                         
 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: 
 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 
 207 
 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 
 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                 
 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 
 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         
 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         
 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 
 307 
 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                 
 329                 for (from=0, to=0;
 330                      (from < count) && (to < sclp_vt220_space_left(request));
 331                      from++) {
 332                         
 333                         c = msg[from];
 334                         
 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 
 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 
 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                 
 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 
 394 
 395 
 396 
 397 
 398 
 399 
 400 
 401 
 402 
 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                 
 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                 
 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 
 445 
 446 
 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         
 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 
 467 
 468 
 469 
 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                 
 497                 if (buffer[i] == ('O' ^ 0100)) { 
 498                         
 499 
 500 
 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 
 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                 
 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 
 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 
 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 
 584 
 585 
 586 
 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 
 596 
 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 
 609 
 610 
 611 
 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 
 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 
 655 
 656 
 657 static void
 658 sclp_vt220_flush_buffer(struct tty_struct *tty)
 659 {
 660         sclp_vt220_emit_current();
 661 }
 662 
 663 
 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 
 675 
 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 
 687 
 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         
 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 
 737 
 738 static int __init sclp_vt220_tty_init(void)
 739 {
 740         struct tty_driver *driver;
 741         int rc;
 742 
 743         
 744 
 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 
 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 
 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 
 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         
 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 
 898