sclp_con.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/s390/char/sclp_con.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCLP line mode console driver 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * S390 version 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s): Martin Peschke <mpeschke@de.ibm.com> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Martin Schwidefsky <schwidefsky@de.ibm.com> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kmod.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/jiffies.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sclp.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sclp_rw.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sclp_tty.h" 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCLP_CON_PRINT_HEADER "sclp console driver: " 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sclp_console_major 4 /* TTYAUX_MAJOR */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sclp_console_minor 64 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sclp_console_name "ttyS" 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lock to guard over changes to global variables */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic spinlock_t sclp_con_lock; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* List of free pages that can be used for console output buffering */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct list_head sclp_con_pages; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* List of full struct sclp_buffer structures ready for output */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct list_head sclp_con_outqueue; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Counter how many buffers are emitted (max 1) and how many */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* are on the output queue. */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sclp_con_buffer_count; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Pointer to current console buffer */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sclp_buffer *sclp_conbuf; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Timer for delayed output of console messages */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct timer_list sclp_con_timer; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Output format for console messages */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short sclp_con_columns; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short sclp_con_width_htab; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_conbuf_callback(struct sclp_buffer *buffer, int rc) 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *page; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds page = sclp_unmake_buffer(buffer); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove buffer from outqueue */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&buffer->list); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_buffer_count--; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail((struct list_head *) page, &sclp_con_pages); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if there is a pending buffer on the out queue. */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer = NULL; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&sclp_con_outqueue)) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer = list_entry(sclp_con_outqueue.next, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sclp_buffer, list); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback)); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_conbuf_emit(void) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sclp_buffer* buffer; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer = sclp_conbuf; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf = NULL; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buffer == NULL) { 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&buffer->list, &sclp_con_outqueue); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = sclp_con_buffer_count++; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = sclp_emit_buffer(buffer, sclp_conbuf_callback); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf_callback(buffer, rc); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When this routine is called from the timer then we flush the 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * temporary write buffer without further waiting on a final new line. 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_console_timeout(unsigned long data) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf_emit(); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Writes the given message to S390 system console 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_console_write(struct console *console, const char *message, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int count) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *page; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int written; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * process escape characters, write message into buffer, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * send buffer to SCLP 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure we have a console output buffer */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sclp_conbuf == NULL) { 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (list_empty(&sclp_con_pages)) { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_sync_wait(); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds page = sclp_con_pages.next; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del((struct list_head *) page); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf = sclp_make_buffer(page, sclp_con_columns, 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_width_htab); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* try to write the string to the current output buffer */ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds written = sclp_write(sclp_conbuf, (const unsigned char *) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds message, count); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (written == count) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Not all characters could be written to the current 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * output buffer. Emit the buffer, create a new buffer 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and then output the rest of the string. 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf_emit(); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds message += written; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count -= written; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (count > 0); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup timer to output current console buffer after 1/10 second */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 && 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !timer_pending(&sclp_con_timer)) { 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&sclp_con_timer); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_timer.function = sclp_console_timeout; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_timer.data = 0UL; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_timer.expires = jiffies + HZ/10; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&sclp_con_timer); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct tty_driver * 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_console_device(struct console *c, int *index) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *index = c->index; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sclp_tty_driver; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called from panic when the kernel 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is going to give up. We have to make sure that all buffers 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will be flushed to the SCLP. 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_console_unblank(void) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf_emit(); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timer_pending(&sclp_con_timer)) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&sclp_con_timer); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (sclp_con_buffer_count > 0) { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_sync_wait(); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sclp_con_lock, flags); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sclp_con_lock, flags); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * used to register the SCLP console to the kernel and to 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * give printk necessary information 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct console sclp_console = 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = sclp_console_name, 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = sclp_console_write, 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .device = sclp_console_device, 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unblank = sclp_console_unblank, 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flags = CON_PRINTBUFFER, 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .index = 0 /* ttyS0 */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called by console_init() in drivers/char/tty_io.c at boot-time. 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssclp_console_init(void) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *page; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!CONSOLE_IS_SCLP) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = sclp_rw_init(); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allocate pages for output buffering */ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sclp_con_pages); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_CONSOLE_PAGES; i++) { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds page = alloc_bootmem_low_pages(PAGE_SIZE); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (page == NULL) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail((struct list_head *) page, &sclp_con_pages); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sclp_con_outqueue); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&sclp_con_lock); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_buffer_count = 0; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_conbuf = NULL; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&sclp_con_timer); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set output format */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MACHINE_IS_VM) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * save 4 characters for the CPU number 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * written at start of each line by VM/CP 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_columns = 76; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_columns = 80; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sclp_con_width_htab = 8; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* enable printk-access to this driver */ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_console(&sclp_console); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconsole_initcall(sclp_console_init); 253