dummycon.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/drivers/video/dummycon.c -- A dummy console driver
  4. *
  5. * To be used if there's no other console driver (e.g. for plain VGA text)
  6. * available, usually until fbcon takes console over.
  7. */
  8. #include <linux/types.h>
  9. #include <linux/kdev_t.h>
  10. #include <linux/console.h>
  11. #include <linux/vt_kern.h>
  12. #include <linux/screen_info.h>
  13. #include <linux/init.h>
  14. #include <linux/module.h>
  15. /*
  16. * Dummy console driver
  17. */
  18. #if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_VGA_CONSOLE)
  19. #include <asm/vga.h>
  20. #define DUMMY_COLUMNS vgacon_screen_info.orig_video_cols
  21. #define DUMMY_ROWS vgacon_screen_info.orig_video_lines
  22. #else
  23. /* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */
  24. #define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
  25. #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS
  26. #endif
  27. #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
  28. /* These are both protected by the console_lock */
  29. static RAW_NOTIFIER_HEAD(dummycon_output_nh);
  30. static bool dummycon_putc_called;
  31. void dummycon_register_output_notifier(struct notifier_block *nb)
  32. {
  33. WARN_CONSOLE_UNLOCKED();
  34. raw_notifier_chain_register(&dummycon_output_nh, nb);
  35. if (dummycon_putc_called)
  36. nb->notifier_call(nb, 0, NULL);
  37. }
  38. void dummycon_unregister_output_notifier(struct notifier_block *nb)
  39. {
  40. WARN_CONSOLE_UNLOCKED();
  41. raw_notifier_chain_unregister(&dummycon_output_nh, nb);
  42. }
  43. static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
  44. unsigned int x)
  45. {
  46. WARN_CONSOLE_UNLOCKED();
  47. dummycon_putc_called = true;
  48. raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
  49. }
  50. static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
  51. unsigned int ypos, unsigned int xpos)
  52. {
  53. unsigned int i;
  54. if (!dummycon_putc_called) {
  55. /* Ignore erases */
  56. for (i = 0 ; i < count; i++) {
  57. if (s[i] != vc->vc_video_erase_char)
  58. break;
  59. }
  60. if (i == count)
  61. return;
  62. dummycon_putc_called = true;
  63. }
  64. raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
  65. }
  66. static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
  67. bool mode_switch)
  68. {
  69. /* Redraw, so that we get putc(s) for output done while blanked */
  70. return true;
  71. }
  72. static bool dummycon_switch(struct vc_data *vc)
  73. {
  74. /*
  75. * Redraw, so that we get putc(s) for output done while switched
  76. * away. Informs deferred consoles to take over the display.
  77. */
  78. return true;
  79. }
  80. #else
  81. static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
  82. unsigned int x) { }
  83. static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
  84. unsigned int ypos, unsigned int xpos) { }
  85. static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
  86. bool mode_switch)
  87. {
  88. return false;
  89. }
  90. static bool dummycon_switch(struct vc_data *vc)
  91. {
  92. return false;
  93. }
  94. #endif
  95. static const char *dummycon_startup(void)
  96. {
  97. return "dummy device";
  98. }
  99. static void dummycon_init(struct vc_data *vc, bool init)
  100. {
  101. vc->vc_can_do_color = 1;
  102. if (init) {
  103. vc->vc_cols = DUMMY_COLUMNS;
  104. vc->vc_rows = DUMMY_ROWS;
  105. } else
  106. vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS);
  107. }
  108. static void dummycon_deinit(struct vc_data *vc) { }
  109. static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
  110. unsigned int width) { }
  111. static void dummycon_cursor(struct vc_data *vc, bool enable) { }
  112. static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
  113. unsigned int bottom, enum con_scroll dir,
  114. unsigned int lines)
  115. {
  116. return false;
  117. }
  118. /*
  119. * The console `switch' structure for the dummy console
  120. *
  121. * Most of the operations are dummies.
  122. */
  123. const struct consw dummy_con = {
  124. .owner = THIS_MODULE,
  125. .con_startup = dummycon_startup,
  126. .con_init = dummycon_init,
  127. .con_deinit = dummycon_deinit,
  128. .con_clear = dummycon_clear,
  129. .con_putc = dummycon_putc,
  130. .con_putcs = dummycon_putcs,
  131. .con_cursor = dummycon_cursor,
  132. .con_scroll = dummycon_scroll,
  133. .con_switch = dummycon_switch,
  134. .con_blank = dummycon_blank,
  135. };
  136. EXPORT_SYMBOL_GPL(dummy_con);