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