SpuriousInterruptHandler.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/Arch/x86/Interrupts.h>
  8. #include <Kernel/Interrupts/PIC.h>
  9. #include <Kernel/Interrupts/SpuriousInterruptHandler.h>
  10. #include <Kernel/Sections.h>
  11. namespace Kernel {
  12. UNMAP_AFTER_INIT void SpuriousInterruptHandler::initialize(u8 interrupt_number)
  13. {
  14. auto* handler = new SpuriousInterruptHandler(interrupt_number);
  15. handler->register_interrupt_handler();
  16. }
  17. void SpuriousInterruptHandler::initialize_for_disabled_master_pic()
  18. {
  19. auto* handler = new SpuriousInterruptHandler(7);
  20. register_disabled_interrupt_handler(7, *handler);
  21. handler->enable_interrupt_vector_for_disabled_pic();
  22. }
  23. void SpuriousInterruptHandler::initialize_for_disabled_slave_pic()
  24. {
  25. auto* handler = new SpuriousInterruptHandler(15);
  26. register_disabled_interrupt_handler(15, *handler);
  27. handler->enable_interrupt_vector_for_disabled_pic();
  28. }
  29. void SpuriousInterruptHandler::register_handler(GenericInterruptHandler& handler)
  30. {
  31. VERIFY(!m_real_handler);
  32. m_real_handler = adopt_own_if_nonnull(&handler);
  33. }
  34. void SpuriousInterruptHandler::unregister_handler(GenericInterruptHandler&)
  35. {
  36. TODO();
  37. }
  38. bool SpuriousInterruptHandler::eoi()
  39. {
  40. // Actually check if IRQ7 or IRQ15 are spurious, and if not, call EOI with the correct interrupt number.
  41. if (m_real_irq) {
  42. m_responsible_irq_controller->eoi(*this);
  43. m_real_irq = false; // return to default state!
  44. return true;
  45. }
  46. m_responsible_irq_controller->spurious_eoi(*this);
  47. return false;
  48. }
  49. StringView SpuriousInterruptHandler::purpose() const
  50. {
  51. if (!m_real_handler)
  52. return "Spurious Interrupt Handler"sv;
  53. return m_real_handler->purpose();
  54. }
  55. SpuriousInterruptHandler::SpuriousInterruptHandler(u8 irq)
  56. : GenericInterruptHandler(irq)
  57. , m_responsible_irq_controller(InterruptManagement::the().get_responsible_irq_controller(irq))
  58. {
  59. }
  60. SpuriousInterruptHandler::~SpuriousInterruptHandler() = default;
  61. bool SpuriousInterruptHandler::handle_interrupt(RegisterState const& state)
  62. {
  63. // Actually check if IRQ7 or IRQ15 are spurious, and if not, call the real handler to handle the IRQ.
  64. if (m_responsible_irq_controller->get_isr() & (1 << interrupt_number())) {
  65. m_real_irq = true; // remember that we had a real IRQ, when EOI later!
  66. if (m_real_handler->handle_interrupt(state)) {
  67. m_real_handler->increment_invoking_counter();
  68. return true;
  69. }
  70. return false;
  71. }
  72. dbgln("Spurious interrupt, vector {}", interrupt_number());
  73. return true;
  74. }
  75. void SpuriousInterruptHandler::enable_interrupt_vector_for_disabled_pic()
  76. {
  77. m_enabled = true;
  78. m_responsible_irq_controller = InterruptManagement::the().get_responsible_irq_controller(IRQControllerType::i8259, interrupt_number());
  79. }
  80. void SpuriousInterruptHandler::enable_interrupt_vector()
  81. {
  82. if (m_enabled)
  83. return;
  84. m_enabled = true;
  85. m_responsible_irq_controller->enable(*this);
  86. }
  87. void SpuriousInterruptHandler::disable_interrupt_vector()
  88. {
  89. VERIFY(!m_real_irq); // this flag should not be set when we call this method
  90. if (!m_enabled)
  91. return;
  92. m_enabled = false;
  93. m_responsible_irq_controller->disable(*this);
  94. }
  95. StringView SpuriousInterruptHandler::controller() const
  96. {
  97. if (m_responsible_irq_controller->type() == IRQControllerType::i82093AA)
  98. return "";
  99. return m_responsible_irq_controller->model();
  100. }
  101. }