SharedIRQHandler.cpp 3.0 KB

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