memcons.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
  3. *
  4. * Copyright (C) 2001,02 NEC Corporation
  5. * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file COPYING in the main directory of this
  9. * archive for more details.
  10. *
  11. * Written by Miles Bader <miles@gnu.org>
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/console.h>
  15. #include <linux/tty.h>
  16. #include <linux/tty_driver.h>
  17. #include <linux/init.h>
  18. /* If this device is enabled, the linker map should define start and
  19. end points for its buffer. */
  20. extern char memcons_output[], memcons_output_end;
  21. /* Current offset into the buffer. */
  22. static unsigned long memcons_offs = 0;
  23. /* Spinlock protecting memcons_offs. */
  24. static DEFINE_SPINLOCK(memcons_lock);
  25. static size_t write (const char *buf, size_t len)
  26. {
  27. int flags;
  28. char *point;
  29. spin_lock_irqsave (memcons_lock, flags);
  30. point = memcons_output + memcons_offs;
  31. if (point + len >= &memcons_output_end) {
  32. len = &memcons_output_end - point;
  33. memcons_offs = 0;
  34. } else
  35. memcons_offs += len;
  36. spin_unlock_irqrestore (memcons_lock, flags);
  37. memcpy (point, buf, len);
  38. return len;
  39. }
  40. /* Low-level console. */
  41. static void memcons_write (struct console *co, const char *buf, unsigned len)
  42. {
  43. while (len > 0)
  44. len -= write (buf, len);
  45. }
  46. static struct tty_driver *tty_driver;
  47. static struct tty_driver *memcons_device (struct console *co, int *index)
  48. {
  49. *index = co->index;
  50. return tty_driver;
  51. }
  52. static struct console memcons =
  53. {
  54. .name = "memcons",
  55. .write = memcons_write,
  56. .device = memcons_device,
  57. .flags = CON_PRINTBUFFER,
  58. .index = -1,
  59. };
  60. void memcons_setup (void)
  61. {
  62. register_console (&memcons);
  63. printk (KERN_INFO "Console: static memory buffer (memcons)\n");
  64. }
  65. /* Higher level TTY interface. */
  66. int memcons_tty_open (struct tty_struct *tty, struct file *filp)
  67. {
  68. return 0;
  69. }
  70. int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len)
  71. {
  72. return write (buf, len);
  73. }
  74. int memcons_tty_write_room (struct tty_struct *tty)
  75. {
  76. return &memcons_output_end - (memcons_output + memcons_offs);
  77. }
  78. int memcons_tty_chars_in_buffer (struct tty_struct *tty)
  79. {
  80. /* We have no buffer. */
  81. return 0;
  82. }
  83. static struct tty_operations ops = {
  84. .open = memcons_tty_open,
  85. .write = memcons_tty_write,
  86. .write_room = memcons_tty_write_room,
  87. .chars_in_buffer = memcons_tty_chars_in_buffer,
  88. };
  89. int __init memcons_tty_init (void)
  90. {
  91. int err;
  92. struct tty_driver *driver = alloc_tty_driver(1);
  93. if (!driver)
  94. return -ENOMEM;
  95. driver->name = "memcons";
  96. driver->major = TTY_MAJOR;
  97. driver->minor_start = 64;
  98. driver->type = TTY_DRIVER_TYPE_SYSCONS;
  99. driver->init_termios = tty_std_termios;
  100. tty_set_operations(driver, &ops);
  101. err = tty_register_driver(driver);
  102. if (err) {
  103. put_tty_driver(driver);
  104. return err;
  105. }
  106. tty_driver = driver;
  107. return 0;
  108. }
  109. __initcall (memcons_tty_init);