SharedIRQHandler.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Arch/InterruptManagement.h>
  7. #include <Kernel/Assertions.h>
  8. #include <Kernel/Debug.h>
  9. #include <Kernel/Interrupts/IRQHandler.h>
  10. #include <Kernel/Interrupts/SharedIRQHandler.h>
  11. #include <Kernel/Sections.h>
  12. namespace Kernel {
  13. UNMAP_AFTER_INIT void SharedIRQHandler::initialize(u8 interrupt_number)
  14. {
  15. auto* handler = new SharedIRQHandler(interrupt_number);
  16. handler->register_interrupt_handler();
  17. handler->disable_interrupt_vector();
  18. }
  19. void SharedIRQHandler::register_handler(GenericInterruptHandler& handler)
  20. {
  21. dbgln_if(INTERRUPT_DEBUG, "Interrupt Handler registered @ Shared Interrupt Handler {}", interrupt_number());
  22. m_handlers.append(handler);
  23. enable_interrupt_vector();
  24. }
  25. void SharedIRQHandler::unregister_handler(GenericInterruptHandler& handler)
  26. {
  27. dbgln_if(INTERRUPT_DEBUG, "Interrupt Handler unregistered @ Shared Interrupt Handler {}", interrupt_number());
  28. m_handlers.remove(handler);
  29. if (m_handlers.is_empty())
  30. disable_interrupt_vector();
  31. }
  32. bool SharedIRQHandler::eoi()
  33. {
  34. dbgln_if(INTERRUPT_DEBUG, "EOI IRQ {}", interrupt_number());
  35. m_responsible_irq_controller->eoi(*this);
  36. return true;
  37. }
  38. void SharedIRQHandler::enumerate_handlers(Function<void(GenericInterruptHandler&)>& callback)
  39. {
  40. for (auto& handler : m_handlers) {
  41. callback(handler);
  42. }
  43. }
  44. SharedIRQHandler::SharedIRQHandler(u8 irq)
  45. : GenericInterruptHandler(irq)
  46. , m_responsible_irq_controller(InterruptManagement::the().get_responsible_irq_controller(irq))
  47. {
  48. dbgln_if(INTERRUPT_DEBUG, "Shared Interrupt Handler registered @ {}", interrupt_number());
  49. }
  50. SharedIRQHandler::~SharedIRQHandler()
  51. {
  52. dbgln_if(INTERRUPT_DEBUG, "Shared Interrupt Handler unregistered @ {}", interrupt_number());
  53. disable_interrupt_vector();
  54. }
  55. bool SharedIRQHandler::handle_interrupt(RegisterState const& regs)
  56. {
  57. VERIFY_INTERRUPTS_DISABLED();
  58. if constexpr (INTERRUPT_DEBUG) {
  59. dbgln("Interrupt @ {}", interrupt_number());
  60. dbgln("Interrupt Handlers registered - {}", m_handlers.size_slow());
  61. }
  62. int i = 0;
  63. bool was_handled = false;
  64. for (auto& handler : m_handlers) {
  65. dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {}", i, interrupt_number());
  66. if (handler.handle_interrupt(regs)) {
  67. handler.increment_invoking_counter();
  68. was_handled = true;
  69. }
  70. dbgln_if(INTERRUPT_DEBUG, "Going for Interrupt Handling @ {}, Shared Interrupt {} - End", i, interrupt_number());
  71. i++;
  72. }
  73. return was_handled;
  74. }
  75. void SharedIRQHandler::enable_interrupt_vector()
  76. {
  77. if (m_enabled)
  78. return;
  79. m_enabled = true;
  80. m_responsible_irq_controller->enable(*this);
  81. }
  82. void SharedIRQHandler::disable_interrupt_vector()
  83. {
  84. if (!m_enabled)
  85. return;
  86. m_enabled = false;
  87. m_responsible_irq_controller->disable(*this);
  88. }
  89. }