diff --git a/Kernel/CommandLine.cpp b/Kernel/CommandLine.cpp index fdb09c4d41..4294b97c9c 100644 --- a/Kernel/CommandLine.cpp +++ b/Kernel/CommandLine.cpp @@ -148,6 +148,19 @@ UNMAP_AFTER_INIT HPETMode CommandLine::hpet_mode() const PANIC("Unknown HPETMode: {}", hpet_mode); } +UNMAP_AFTER_INIT AHCIResetMode CommandLine::ahci_reset_mode() const +{ + const auto ahci_reset_mode = lookup("ahci_reset_mode").value_or("controller"); + if (ahci_reset_mode == "controller") { + return AHCIResetMode::ControllerOnly; + } else if (ahci_reset_mode == "none") { + return AHCIResetMode::None; + } else if (ahci_reset_mode == "complete") { + return AHCIResetMode::Complete; + } + PANIC("Unknown AHCIResetMode: {}", ahci_reset_mode); +} + UNMAP_AFTER_INIT BootMode CommandLine::boot_mode() const { const auto boot_mode = lookup("boot_mode").value_or("graphical"); diff --git a/Kernel/CommandLine.h b/Kernel/CommandLine.h index 75a236bbcd..91e553026e 100644 --- a/Kernel/CommandLine.h +++ b/Kernel/CommandLine.h @@ -50,6 +50,12 @@ enum class AcpiFeatureLevel { Disabled, }; +enum class AHCIResetMode { + ControllerOnly, + Complete, + None +}; + class CommandLine { AK_MAKE_ETERNAL; @@ -72,6 +78,7 @@ public: [[nodiscard]] AcpiFeatureLevel acpi_feature_level() const; [[nodiscard]] BootMode boot_mode() const; [[nodiscard]] HPETMode hpet_mode() const; + [[nodiscard]] AHCIResetMode ahci_reset_mode() const; [[nodiscard]] String userspace_init() const; [[nodiscard]] Vector userspace_init_args() const; [[nodiscard]] String root_device() const; diff --git a/Kernel/Storage/AHCIController.cpp b/Kernel/Storage/AHCIController.cpp index 1068ea104a..d2b0570469 100644 --- a/Kernel/Storage/AHCIController.cpp +++ b/Kernel/Storage/AHCIController.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -144,11 +145,13 @@ AHCIController::~AHCIController() void AHCIController::initialize() { - if (!reset()) { - dmesgln("{}: AHCI controller reset failed", pci_address()); - return; + if (kernel_command_line().ahci_reset_mode() != AHCIResetMode::None) { + if (!reset()) { + dmesgln("{}: AHCI controller reset failed", pci_address()); + return; + } + dmesgln("{}: AHCI controller reset", pci_address()); } - dmesgln("{}: AHCI controller reset", pci_address()); dbgln("{}: AHCI command list entries count - {}", pci_address(), hba_capabilities().max_command_list_entries_count); hba().control_regs.ghc = 0x80000000; // Ensure that HBA knows we are AHCI aware. PCI::enable_interrupt_line(pci_address()); diff --git a/Kernel/Storage/AHCIPort.cpp b/Kernel/Storage/AHCIPort.cpp index 91d7241a04..b3f1f464bf 100644 --- a/Kernel/Storage/AHCIPort.cpp +++ b/Kernel/Storage/AHCIPort.cpp @@ -210,6 +210,22 @@ bool AHCIPort::reset() if (!initiate_sata_reset()) { return false; } + return initialize(); +} + +bool AHCIPort::initialize_without_reset() +{ + ScopedSpinLock lock(m_lock); + dmesgln("AHCI Port {}: {}", representative_port_index(), try_disambiguate_sata_status()); + return initialize(); +} + +bool AHCIPort::initialize() +{ + VERIFY(m_lock.is_locked()); + dbgln_if(AHCI_DEBUG, "AHCI Port {}: SIG {:x}", representative_port_index(), static_cast(m_port_registers.sig)); + if (!is_phy_enabled()) + return false; rebase(); power_on(); spin_up(); diff --git a/Kernel/Storage/AHCIPort.h b/Kernel/Storage/AHCIPort.h index 3f26f191ee..db7aaefc98 100644 --- a/Kernel/Storage/AHCIPort.h +++ b/Kernel/Storage/AHCIPort.h @@ -78,9 +78,13 @@ public: RefPtr connected_device() const { return m_connected_device; } bool reset(); + UNMAP_AFTER_INIT bool initialize_without_reset(); void handle_interrupt(); private: + bool is_phy_enabled() const { return (m_port_registers.ssts & 0xf) == 3; } + bool initialize(); + UNMAP_AFTER_INIT AHCIPort(const AHCIPortHandler&, volatile AHCI::PortRegisters&, u32 port_index); ALWAYS_INLINE void clear_sata_error_register() const; diff --git a/Kernel/Storage/AHCIPortHandler.cpp b/Kernel/Storage/AHCIPortHandler.cpp index 953078b19e..df5a0ac4dc 100644 --- a/Kernel/Storage/AHCIPortHandler.cpp +++ b/Kernel/Storage/AHCIPortHandler.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include namespace Kernel { @@ -46,10 +47,19 @@ AHCIPortHandler::AHCIPortHandler(AHCIController& controller, u8 irq, AHCI::Maske // Clear pending interrupts, if there are any! m_pending_ports_interrupts.set_all(); enable_irq(); + + if (kernel_command_line().ahci_reset_mode() == AHCIResetMode::Complete) { + for (auto index : taken_ports.to_vector()) { + auto port = AHCIPort::create(*this, static_cast(controller.hba().port_regs[index]), index); + m_handled_ports.set(index, port); + port->reset(); + } + return; + } for (auto index : taken_ports.to_vector()) { auto port = AHCIPort::create(*this, static_cast(controller.hba().port_regs[index]), index); m_handled_ports.set(index, port); - port->reset(); + port->initialize_without_reset(); } }