sclp_con.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * drivers/s390/char/sclp_con.c
  3. * SCLP line mode console driver
  4. *
  5. * S390 version
  6. * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  7. * Author(s): Martin Peschke <mpeschke@de.ibm.com>
  8. * Martin Schwidefsky <schwidefsky@de.ibm.com>
  9. */
  10. #include <linux/kmod.h>
  11. #include <linux/console.h>
  12. #include <linux/init.h>
  13. #include <linux/timer.h>
  14. #include <linux/jiffies.h>
  15. #include <linux/bootmem.h>
  16. #include <linux/err.h>
  17. #include "sclp.h"
  18. #include "sclp_rw.h"
  19. #include "sclp_tty.h"
  20. #define SCLP_CON_PRINT_HEADER "sclp console driver: "
  21. #define sclp_console_major 4 /* TTYAUX_MAJOR */
  22. #define sclp_console_minor 64
  23. #define sclp_console_name "ttyS"
  24. /* Lock to guard over changes to global variables */
  25. static spinlock_t sclp_con_lock;
  26. /* List of free pages that can be used for console output buffering */
  27. static struct list_head sclp_con_pages;
  28. /* List of full struct sclp_buffer structures ready for output */
  29. static struct list_head sclp_con_outqueue;
  30. /* Counter how many buffers are emitted (max 1) and how many */
  31. /* are on the output queue. */
  32. static int sclp_con_buffer_count;
  33. /* Pointer to current console buffer */
  34. static struct sclp_buffer *sclp_conbuf;
  35. /* Timer for delayed output of console messages */
  36. static struct timer_list sclp_con_timer;
  37. /* Output format for console messages */
  38. static unsigned short sclp_con_columns;
  39. static unsigned short sclp_con_width_htab;
  40. static void
  41. sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
  42. {
  43. unsigned long flags;
  44. void *page;
  45. do {
  46. page = sclp_unmake_buffer(buffer);
  47. spin_lock_irqsave(&sclp_con_lock, flags);
  48. /* Remove buffer from outqueue */
  49. list_del(&buffer->list);
  50. sclp_con_buffer_count--;
  51. list_add_tail((struct list_head *) page, &sclp_con_pages);
  52. /* Check if there is a pending buffer on the out queue. */
  53. buffer = NULL;
  54. if (!list_empty(&sclp_con_outqueue))
  55. buffer = list_entry(sclp_con_outqueue.next,
  56. struct sclp_buffer, list);
  57. spin_unlock_irqrestore(&sclp_con_lock, flags);
  58. } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback));
  59. }
  60. static inline void
  61. sclp_conbuf_emit(void)
  62. {
  63. struct sclp_buffer* buffer;
  64. unsigned long flags;
  65. int count;
  66. int rc;
  67. spin_lock_irqsave(&sclp_con_lock, flags);
  68. buffer = sclp_conbuf;
  69. sclp_conbuf = NULL;
  70. if (buffer == NULL) {
  71. spin_unlock_irqrestore(&sclp_con_lock, flags);
  72. return;
  73. }
  74. list_add_tail(&buffer->list, &sclp_con_outqueue);
  75. count = sclp_con_buffer_count++;
  76. spin_unlock_irqrestore(&sclp_con_lock, flags);
  77. if (count)
  78. return;
  79. rc = sclp_emit_buffer(buffer, sclp_conbuf_callback);
  80. if (rc)
  81. sclp_conbuf_callback(buffer, rc);
  82. }
  83. /*
  84. * When this routine is called from the timer then we flush the
  85. * temporary write buffer without further waiting on a final new line.
  86. */
  87. static void
  88. sclp_console_timeout(unsigned long data)
  89. {
  90. sclp_conbuf_emit();
  91. }
  92. /*
  93. * Writes the given message to S390 system console
  94. */
  95. static void
  96. sclp_console_write(struct console *console, const char *message,
  97. unsigned int count)
  98. {
  99. unsigned long flags;
  100. void *page;
  101. int written;
  102. if (count == 0)
  103. return;
  104. spin_lock_irqsave(&sclp_con_lock, flags);
  105. /*
  106. * process escape characters, write message into buffer,
  107. * send buffer to SCLP
  108. */
  109. do {
  110. /* make sure we have a console output buffer */
  111. if (sclp_conbuf == NULL) {
  112. while (list_empty(&sclp_con_pages)) {
  113. spin_unlock_irqrestore(&sclp_con_lock, flags);
  114. sclp_sync_wait();
  115. spin_lock_irqsave(&sclp_con_lock, flags);
  116. }
  117. page = sclp_con_pages.next;
  118. list_del((struct list_head *) page);
  119. sclp_conbuf = sclp_make_buffer(page, sclp_con_columns,
  120. sclp_con_width_htab);
  121. }
  122. /* try to write the string to the current output buffer */
  123. written = sclp_write(sclp_conbuf, (const unsigned char *)
  124. message, count);
  125. if (written == count)
  126. break;
  127. /*
  128. * Not all characters could be written to the current
  129. * output buffer. Emit the buffer, create a new buffer
  130. * and then output the rest of the string.
  131. */
  132. spin_unlock_irqrestore(&sclp_con_lock, flags);
  133. sclp_conbuf_emit();
  134. spin_lock_irqsave(&sclp_con_lock, flags);
  135. message += written;
  136. count -= written;
  137. } while (count > 0);
  138. /* Setup timer to output current console buffer after 1/10 second */
  139. if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 &&
  140. !timer_pending(&sclp_con_timer)) {
  141. init_timer(&sclp_con_timer);
  142. sclp_con_timer.function = sclp_console_timeout;
  143. sclp_con_timer.data = 0UL;
  144. sclp_con_timer.expires = jiffies + HZ/10;
  145. add_timer(&sclp_con_timer);
  146. }
  147. spin_unlock_irqrestore(&sclp_con_lock, flags);
  148. }
  149. static struct tty_driver *
  150. sclp_console_device(struct console *c, int *index)
  151. {
  152. *index = c->index;
  153. return sclp_tty_driver;
  154. }
  155. /*
  156. * This routine is called from panic when the kernel
  157. * is going to give up. We have to make sure that all buffers
  158. * will be flushed to the SCLP.
  159. */
  160. static void
  161. sclp_console_unblank(void)
  162. {
  163. unsigned long flags;
  164. sclp_conbuf_emit();
  165. spin_lock_irqsave(&sclp_con_lock, flags);
  166. if (timer_pending(&sclp_con_timer))
  167. del_timer(&sclp_con_timer);
  168. while (sclp_con_buffer_count > 0) {
  169. spin_unlock_irqrestore(&sclp_con_lock, flags);
  170. sclp_sync_wait();
  171. spin_lock_irqsave(&sclp_con_lock, flags);
  172. }
  173. spin_unlock_irqrestore(&sclp_con_lock, flags);
  174. }
  175. /*
  176. * used to register the SCLP console to the kernel and to
  177. * give printk necessary information
  178. */
  179. static struct console sclp_console =
  180. {
  181. .name = sclp_console_name,
  182. .write = sclp_console_write,
  183. .device = sclp_console_device,
  184. .unblank = sclp_console_unblank,
  185. .flags = CON_PRINTBUFFER,
  186. .index = 0 /* ttyS0 */
  187. };
  188. /*
  189. * called by console_init() in drivers/char/tty_io.c at boot-time.
  190. */
  191. static int __init
  192. sclp_console_init(void)
  193. {
  194. void *page;
  195. int i;
  196. int rc;
  197. if (!CONSOLE_IS_SCLP)
  198. return 0;
  199. rc = sclp_rw_init();
  200. if (rc)
  201. return rc;
  202. /* Allocate pages for output buffering */
  203. INIT_LIST_HEAD(&sclp_con_pages);
  204. for (i = 0; i < MAX_CONSOLE_PAGES; i++) {
  205. page = alloc_bootmem_low_pages(PAGE_SIZE);
  206. if (page == NULL)
  207. return -ENOMEM;
  208. list_add_tail((struct list_head *) page, &sclp_con_pages);
  209. }
  210. INIT_LIST_HEAD(&sclp_con_outqueue);
  211. spin_lock_init(&sclp_con_lock);
  212. sclp_con_buffer_count = 0;
  213. sclp_conbuf = NULL;
  214. init_timer(&sclp_con_timer);
  215. /* Set output format */
  216. if (MACHINE_IS_VM)
  217. /*
  218. * save 4 characters for the CPU number
  219. * written at start of each line by VM/CP
  220. */
  221. sclp_con_columns = 76;
  222. else
  223. sclp_con_columns = 80;
  224. sclp_con_width_htab = 8;
  225. /* enable printk-access to this driver */
  226. register_console(&sclp_console);
  227. return 0;
  228. }
  229. console_initcall(sclp_console_init);