SpuriousInterruptHandler.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Interrupts/InterruptManagement.h>
  7. #include <Kernel/Interrupts/SpuriousInterruptHandler.h>
  8. #include <Kernel/Sections.h>
  9. namespace Kernel {
  10. UNMAP_AFTER_INIT void SpuriousInterruptHandler::initialize(u8 interrupt_number)
  11. {
  12. auto* handler = new SpuriousInterruptHandler(interrupt_number);
  13. handler->register_interrupt_handler();
  14. }
  15. void SpuriousInterruptHandler::register_handler(GenericInterruptHandler& handler)
  16. {
  17. VERIFY(!m_real_handler);
  18. m_real_handler = adopt_own_if_nonnull(&handler);
  19. }
  20. void SpuriousInterruptHandler::unregister_handler(GenericInterruptHandler&)
  21. {
  22. TODO();
  23. }
  24. bool SpuriousInterruptHandler::eoi()
  25. {
  26. // Actually check if IRQ7 or IRQ15 are spurious, and if not, call EOI with the correct interrupt number.
  27. if (m_real_irq) {
  28. m_responsible_irq_controller->eoi(*this);
  29. m_real_irq = false; // return to default state!
  30. return true;
  31. }
  32. m_responsible_irq_controller->spurious_eoi(*this);
  33. return false;
  34. }
  35. StringView SpuriousInterruptHandler::purpose() const
  36. {
  37. if (!m_real_handler)
  38. return "Spurious Interrupt Handler";
  39. return m_real_handler->purpose();
  40. }
  41. SpuriousInterruptHandler::SpuriousInterruptHandler(u8 irq)
  42. : GenericInterruptHandler(irq)
  43. , m_responsible_irq_controller(InterruptManagement::the().get_responsible_irq_controller(irq))
  44. {
  45. }
  46. SpuriousInterruptHandler::~SpuriousInterruptHandler()
  47. {
  48. }
  49. bool SpuriousInterruptHandler::handle_interrupt(const RegisterState& state)
  50. {
  51. // Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ.
  52. if (m_responsible_irq_controller->get_isr() & (1 << interrupt_number())) {
  53. m_real_irq = true; // remember that we had a real IRQ, when EOI later!
  54. if (m_real_handler->handle_interrupt(state)) {
  55. m_real_handler->increment_invoking_counter();
  56. return true;
  57. }
  58. return false;
  59. }
  60. dbgln("Spurious interrupt, vector {}", interrupt_number());
  61. return true;
  62. }
  63. void SpuriousInterruptHandler::enable_interrupt_vector()
  64. {
  65. if (m_enabled)
  66. return;
  67. m_enabled = true;
  68. m_responsible_irq_controller->enable(*this);
  69. }
  70. void SpuriousInterruptHandler::disable_interrupt_vector()
  71. {
  72. VERIFY(!m_real_irq); // this flag should not be set when we call this method
  73. if (!m_enabled)
  74. return;
  75. m_enabled = false;
  76. m_responsible_irq_controller->disable(*this);
  77. }
  78. StringView SpuriousInterruptHandler::controller() const
  79. {
  80. if (m_responsible_irq_controller->type() == IRQControllerType::i82093AA)
  81. return "";
  82. return m_responsible_irq_controller->model();
  83. }
  84. }