ConsoleDevice.cpp 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Singleton.h>
  7. #include <Kernel/Devices/ConsoleDevice.h>
  8. #include <Kernel/IO.h>
  9. #include <Kernel/Locking/Spinlock.h>
  10. #include <Kernel/Sections.h>
  11. #include <Kernel/kstdio.h>
  12. // Output bytes to kernel debug port 0xE9 (Bochs console). It's very handy.
  13. #define CONSOLE_OUT_TO_BOCHS_DEBUG_PORT
  14. static Singleton<ConsoleDevice> s_the;
  15. static Kernel::Spinlock g_console_lock;
  16. UNMAP_AFTER_INIT void ConsoleDevice::initialize()
  17. {
  18. s_the.ensure_instance();
  19. s_the->after_inserting();
  20. }
  21. ConsoleDevice& ConsoleDevice::the()
  22. {
  23. return *s_the;
  24. }
  25. bool ConsoleDevice::is_initialized()
  26. {
  27. return s_the.is_initialized();
  28. }
  29. UNMAP_AFTER_INIT ConsoleDevice::ConsoleDevice()
  30. : CharacterDevice(5, 1)
  31. {
  32. }
  33. UNMAP_AFTER_INIT ConsoleDevice::~ConsoleDevice()
  34. {
  35. }
  36. bool ConsoleDevice::can_read(const Kernel::OpenFileDescription&, size_t) const
  37. {
  38. return false;
  39. }
  40. Kernel::KResultOr<size_t> ConsoleDevice::read(OpenFileDescription&, u64, Kernel::UserOrKernelBuffer&, size_t)
  41. {
  42. // FIXME: Implement reading from the console.
  43. // Maybe we could use a ring buffer for this device?
  44. return 0;
  45. }
  46. Kernel::KResultOr<size_t> ConsoleDevice::write(OpenFileDescription&, u64, const Kernel::UserOrKernelBuffer& data, size_t size)
  47. {
  48. if (!size)
  49. return 0;
  50. return data.read_buffered<256>(size, [&](ReadonlyBytes readonly_bytes) {
  51. for (const auto& byte : readonly_bytes)
  52. put_char(byte);
  53. return readonly_bytes.size();
  54. });
  55. }
  56. void ConsoleDevice::put_char(char ch)
  57. {
  58. Kernel::SpinlockLocker lock(g_console_lock);
  59. #ifdef CONSOLE_OUT_TO_BOCHS_DEBUG_PORT
  60. IO::out8(IO::BOCHS_DEBUG_PORT, ch);
  61. #endif
  62. m_logbuffer.enqueue(ch);
  63. }