AHCIPortHandler.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/CommandLine.h>
  7. #include <Kernel/Storage/AHCIPortHandler.h>
  8. namespace Kernel {
  9. NonnullRefPtr<AHCIPortHandler> AHCIPortHandler::create(AHCIController& controller, u8 irq, AHCI::MaskedBitField taken_ports)
  10. {
  11. return adopt_ref(*new AHCIPortHandler(controller, irq, taken_ports));
  12. }
  13. AHCIPortHandler::AHCIPortHandler(AHCIController& controller, u8 irq, AHCI::MaskedBitField taken_ports)
  14. : IRQHandler(irq)
  15. , m_parent_controller(controller)
  16. , m_taken_ports(taken_ports)
  17. , m_pending_ports_interrupts(create_pending_ports_interrupts_bitfield())
  18. {
  19. // FIXME: Use the number of taken ports to determine how many pages we should allocate.
  20. for (size_t index = 0; index < (((size_t)AHCI::Limits::MaxPorts * 512) / PAGE_SIZE); index++) {
  21. m_identify_metadata_pages.append(MM.allocate_supervisor_physical_page().release_nonnull());
  22. }
  23. dbgln_if(AHCI_DEBUG, "AHCI Port Handler: IRQ {}", irq);
  24. // Clear pending interrupts, if there are any!
  25. m_pending_ports_interrupts.set_all();
  26. enable_irq();
  27. if (kernel_command_line().ahci_reset_mode() == AHCIResetMode::Aggressive) {
  28. for (auto index : taken_ports.to_vector()) {
  29. auto port = AHCIPort::create(*this, static_cast<volatile AHCI::PortRegisters&>(controller.hba().port_regs[index]), index);
  30. m_handled_ports.set(index, port);
  31. port->reset();
  32. }
  33. return;
  34. }
  35. for (auto index : taken_ports.to_vector()) {
  36. auto port = AHCIPort::create(*this, static_cast<volatile AHCI::PortRegisters&>(controller.hba().port_regs[index]), index);
  37. m_handled_ports.set(index, port);
  38. port->initialize_without_reset();
  39. }
  40. }
  41. void AHCIPortHandler::enumerate_ports(Function<void(const AHCIPort&)> callback) const
  42. {
  43. for (auto& port : m_handled_ports) {
  44. callback(*port.value);
  45. }
  46. }
  47. RefPtr<AHCIPort> AHCIPortHandler::port_at_index(u32 port_index) const
  48. {
  49. VERIFY(m_taken_ports.is_set_at(port_index));
  50. auto it = m_handled_ports.find(port_index);
  51. if (it == m_handled_ports.end())
  52. return nullptr;
  53. return (*it).value;
  54. }
  55. PhysicalAddress AHCIPortHandler::get_identify_metadata_physical_region(u32 port_index) const
  56. {
  57. dbgln_if(AHCI_DEBUG, "AHCI Port Handler: Get identify metadata physical address of port {} - {}", port_index, (port_index * 512) / PAGE_SIZE);
  58. return m_identify_metadata_pages[(port_index * 512) / PAGE_SIZE].paddr().offset((port_index * 512) % PAGE_SIZE);
  59. }
  60. AHCI::MaskedBitField AHCIPortHandler::create_pending_ports_interrupts_bitfield() const
  61. {
  62. return AHCI::MaskedBitField((volatile u32&)m_parent_controller->hba().control_regs.is, m_taken_ports.bit_mask());
  63. }
  64. AHCI::HBADefinedCapabilities AHCIPortHandler::hba_capabilities() const
  65. {
  66. return m_parent_controller->hba_capabilities();
  67. }
  68. AHCIPortHandler::~AHCIPortHandler()
  69. {
  70. }
  71. bool AHCIPortHandler::handle_irq(const RegisterState&)
  72. {
  73. dbgln_if(AHCI_DEBUG, "AHCI Port Handler: IRQ received");
  74. if (m_pending_ports_interrupts.is_zeroed())
  75. return false;
  76. for (auto port_index : m_pending_ports_interrupts.to_vector()) {
  77. auto port = m_handled_ports.get(port_index);
  78. VERIFY(port.has_value());
  79. dbgln_if(AHCI_DEBUG, "AHCI Port Handler: Handling IRQ for port {}", port_index);
  80. port.value()->handle_interrupt();
  81. // We do this to clear the pending interrupt after we handled it.
  82. m_pending_ports_interrupts.set_at(port_index);
  83. }
  84. return true;
  85. }
  86. }