diff --git a/Base/usr/share/man/man7/boot_parameters.md b/Base/usr/share/man/man7/boot_parameters.md index 0f77ab50a30..6eed6be21bf 100644 --- a/Base/usr/share/man/man7/boot_parameters.md +++ b/Base/usr/share/man/man7/boot_parameters.md @@ -24,9 +24,6 @@ List of options: * **`boot_prof`** - If present on the command line, global system profiling will be enabled as soon as possible during the boot sequence. Allowing you to profile startup of all applications. -* **`disable_ide`** - If present on the command line, the IDE controller will not be initialized - during the boot sequence. Leaving only the AHCI and Ram Disk controllers. - * **`disable_physical_storage`** - If present on the command line, neither AHCI, or IDE controllers will be initialized on boot. * **`disable_ps2_mouse`** - If present on the command line, no PS2 mouse will be attached. @@ -50,8 +47,6 @@ List of options: * **`graphics_subsystem_mode`** - This parameter expects one of the following values. **`on`**- Boot into the graphical environment if possible (default). **`off`** - Boot into text mode, don't initialize any driver. **`limited`** - Boot into the pre-defined framebuffer that the bootloader has set up before booting the Kernel, don't initialize any driver. -* **`force_pio`** - If present on the command line, the IDE controllers will be force into PIO mode when initialized IDE Channels on boot. - * **`hpet`** - This parameter expects one of the following values. **`periodic`** - The High Precision Event Timer should be configured in a periodic mode. **`nonperiodic`** - The High Precision Event Timer should eb configure din non-periodic mode. diff --git a/Kernel/Arch/init.cpp b/Kernel/Arch/init.cpp index 756d91dfa31..6d98fe198b8 100644 --- a/Kernel/Arch/init.cpp +++ b/Kernel/Arch/init.cpp @@ -454,7 +454,7 @@ void init_stage2(void*) for (auto* init_function = driver_init_table_start; init_function != driver_init_table_end; init_function++) (*init_function)(); - StorageManagement::the().initialize(kernel_command_line().is_force_pio(), kernel_command_line().is_nvme_polling_enabled()); + StorageManagement::the().initialize(kernel_command_line().is_nvme_polling_enabled()); for (int i = 0; i < 5; ++i) { if (StorageManagement::the().determine_boot_device(kernel_command_line().root_device())) break; diff --git a/Kernel/Arch/x86_64/ISABus/IDEController.cpp b/Kernel/Arch/x86_64/ISABus/IDEController.cpp deleted file mode 100644 index e15b2a61c05..00000000000 --- a/Kernel/Arch/x86_64/ISABus/IDEController.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -UNMAP_AFTER_INIT ErrorOr> ISAIDEController::initialize() -{ - auto controller = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ISAIDEController())); - TRY(controller->initialize_channels()); - return controller; -} - -UNMAP_AFTER_INIT ISAIDEController::ISAIDEController() -{ -} - -UNMAP_AFTER_INIT ErrorOr ISAIDEController::initialize_channels() -{ - auto primary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x1F0), 8)); - auto primary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x3F6), 4)); - auto secondary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x170), 8)); - auto secondary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x376), 4)); - - auto initialize_and_enumerate = [](IDEChannel& channel) -> ErrorOr { - TRY(channel.allocate_resources_for_isa_ide_controller({})); - TRY(channel.detect_connected_devices()); - return {}; - }; - - auto primary_channel_io_window_group = IDEChannel::IOWindowGroup { move(primary_base_io_window), move(primary_control_io_window) }; - auto secondary_channel_io_window_group = IDEChannel::IOWindowGroup { move(secondary_base_io_window), move(secondary_control_io_window) }; - - m_channels[0] = TRY(IDEChannel::create(*this, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)); - TRY(initialize_and_enumerate(*m_channels[0])); - m_channels[0]->enable_irq(); - - m_channels[1] = TRY(IDEChannel::create(*this, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)); - TRY(initialize_and_enumerate(*m_channels[1])); - m_channels[1]->enable_irq(); - dbgln("ISA IDE controller detected and initialized"); - return {}; -} - -} diff --git a/Kernel/Arch/x86_64/ISABus/IDEController.h b/Kernel/Arch/x86_64/ISABus/IDEController.h deleted file mode 100644 index 7a3c9b4b5f9..00000000000 --- a/Kernel/Arch/x86_64/ISABus/IDEController.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; - -class ISAIDEController final : public IDEController { -public: - static ErrorOr> initialize(); - -private: - ISAIDEController(); - - ErrorOr initialize_channels(); -}; -} diff --git a/Kernel/Arch/x86_64/PCI/IDELegacyModeController.cpp b/Kernel/Arch/x86_64/PCI/IDELegacyModeController.cpp deleted file mode 100644 index c0445945753..00000000000 --- a/Kernel/Arch/x86_64/PCI/IDELegacyModeController.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2020-2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -UNMAP_AFTER_INIT ErrorOr> PCIIDELegacyModeController::initialize(PCI::DeviceIdentifier const& device_identifier, bool force_pio) -{ - auto controller = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) PCIIDELegacyModeController(device_identifier))); - PCI::enable_io_space(device_identifier); - PCI::enable_memory_space(device_identifier); - PCI::enable_bus_mastering(device_identifier); - ArmedScopeGuard disable_interrupts_on_failure([&] { - controller->disable_pin_based_interrupts(); - }); - controller->enable_pin_based_interrupts(); - TRY(controller->initialize_and_enumerate_channels(force_pio)); - disable_interrupts_on_failure.disarm(); - return controller; -} - -UNMAP_AFTER_INIT PCIIDELegacyModeController::PCIIDELegacyModeController(PCI::DeviceIdentifier const& device_identifier) - : PCI::Device(const_cast(device_identifier)) - , m_prog_if(device_identifier.prog_if()) - , m_interrupt_line(device_identifier.interrupt_line()) -{ -} - -bool PCIIDELegacyModeController::is_pci_native_mode_enabled() const -{ - return (m_prog_if.value() & 0x05) != 0; -} - -bool PCIIDELegacyModeController::is_pci_native_mode_enabled_on_primary_channel() const -{ - return (m_prog_if.value() & 0x1) == 0x1; -} - -bool PCIIDELegacyModeController::is_pci_native_mode_enabled_on_secondary_channel() const -{ - return (m_prog_if.value() & 0x4) == 0x4; -} - -bool PCIIDELegacyModeController::is_bus_master_capable() const -{ - return m_prog_if.value() & (1 << 7); -} - -static char const* detect_controller_type(u8 programming_value) -{ - switch (programming_value) { - case 0x00: - return "ISA Compatibility mode-only controller"; - case 0x05: - return "PCI native mode-only controller"; - case 0x0A: - return "ISA Compatibility mode controller, supports both channels switched to PCI native mode"; - case 0x0F: - return "PCI native mode controller, supports both channels switched to ISA compatibility mode"; - case 0x80: - return "ISA Compatibility mode-only controller, supports bus mastering"; - case 0x85: - return "PCI native mode-only controller, supports bus mastering"; - case 0x8A: - return "ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering"; - case 0x8F: - return "PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering"; - default: - VERIFY_NOT_REACHED(); - } - VERIFY_NOT_REACHED(); -} - -UNMAP_AFTER_INIT ErrorOr PCIIDELegacyModeController::initialize_and_enumerate_channels(bool force_pio) -{ - dbgln("IDE controller @ {}: interrupt line was set to {}", device_identifier().address(), m_interrupt_line.value()); - dbgln("IDE controller @ {}: {}", device_identifier().address(), detect_controller_type(m_prog_if.value())); - { - auto bus_master_base = IOAddress(PCI::get_BAR4(device_identifier()) & (~1)); - dbgln("IDE controller @ {}: bus master base was set to {}", device_identifier().address(), bus_master_base); - } - - auto initialize_and_enumerate = [&force_pio](IDEChannel& channel) -> ErrorOr { - TRY(channel.allocate_resources_for_pci_ide_controller({}, force_pio)); - TRY(channel.detect_connected_devices()); - return {}; - }; - - if (!is_bus_master_capable()) - force_pio = true; - - OwnPtr primary_base_io_window; - OwnPtr primary_control_io_window; - if (!is_pci_native_mode_enabled_on_primary_channel()) { - primary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x1F0), 8)); - primary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x3F6), 4)); - } else { - primary_base_io_window = TRY(IOWindow::create_for_pci_device_bar(device_identifier(), PCI::HeaderType0BaseRegister::BAR0)); - auto pci_primary_control_io_window = TRY(IOWindow::create_for_pci_device_bar(device_identifier(), PCI::HeaderType0BaseRegister::BAR1)); - // Note: the PCI IDE specification says we should access the IO address with an offset of 2 - // on native PCI IDE controllers. - primary_control_io_window = TRY(pci_primary_control_io_window->create_from_io_window_with_offset(2, 4)); - } - - VERIFY(primary_base_io_window); - VERIFY(primary_control_io_window); - - OwnPtr secondary_base_io_window; - OwnPtr secondary_control_io_window; - - if (!is_pci_native_mode_enabled_on_primary_channel()) { - secondary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x170), 8)); - secondary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x376), 4)); - } else { - secondary_base_io_window = TRY(IOWindow::create_for_pci_device_bar(device_identifier(), PCI::HeaderType0BaseRegister::BAR2)); - auto pci_secondary_control_io_window = TRY(IOWindow::create_for_pci_device_bar(device_identifier(), PCI::HeaderType0BaseRegister::BAR3)); - // Note: the PCI IDE specification says we should access the IO address with an offset of 2 - // on native PCI IDE controllers. - secondary_control_io_window = TRY(pci_secondary_control_io_window->create_from_io_window_with_offset(2, 4)); - } - VERIFY(secondary_base_io_window); - VERIFY(secondary_control_io_window); - - auto primary_bus_master_io = TRY(IOWindow::create_for_pci_device_bar(device_identifier(), PCI::HeaderType0BaseRegister::BAR4, 16)); - auto secondary_bus_master_io = TRY(primary_bus_master_io->create_from_io_window_with_offset(8)); - - // FIXME: On IOAPIC based system, this value might be completely wrong - // On QEMU for example, it should be "u8 irq_line = 22;" to actually work. - auto irq_line = m_interrupt_line.value(); - - if (is_pci_native_mode_enabled()) { - VERIFY(irq_line != 0); - } - - auto primary_channel_io_window_group = IDEChannel::IOWindowGroup { primary_base_io_window.release_nonnull(), primary_control_io_window.release_nonnull(), move(primary_bus_master_io) }; - auto secondary_channel_io_window_group = IDEChannel::IOWindowGroup { secondary_base_io_window.release_nonnull(), secondary_control_io_window.release_nonnull(), move(secondary_bus_master_io) }; - - if (is_pci_native_mode_enabled_on_primary_channel()) { - m_channels[0] = TRY(IDEChannel::create(*this, irq_line, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)); - } else { - m_channels[0] = TRY(IDEChannel::create(*this, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)); - } - TRY(initialize_and_enumerate(*m_channels[0])); - m_channels[0]->enable_irq(); - - if (is_pci_native_mode_enabled_on_secondary_channel()) { - m_channels[1] = TRY(IDEChannel::create(*this, irq_line, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)); - } else { - m_channels[1] = TRY(IDEChannel::create(*this, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)); - } - TRY(initialize_and_enumerate(*m_channels[1])); - m_channels[1]->enable_irq(); - return {}; -} - -} diff --git a/Kernel/Arch/x86_64/PCI/IDELegacyModeController.h b/Kernel/Arch/x86_64/PCI/IDELegacyModeController.h deleted file mode 100644 index 815e7f099e8..00000000000 --- a/Kernel/Arch/x86_64/PCI/IDELegacyModeController.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020-2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; - -class PCIIDELegacyModeController final : public IDEController - , public PCI::Device { -public: - static ErrorOr> initialize(PCI::DeviceIdentifier const&, bool force_pio); - - virtual StringView device_name() const override { return "PCIIDELegacyModeController"sv; } - - bool is_bus_master_capable() const; - bool is_pci_native_mode_enabled() const; - -private: - bool is_pci_native_mode_enabled_on_primary_channel() const; - bool is_pci_native_mode_enabled_on_secondary_channel() const; - explicit PCIIDELegacyModeController(PCI::DeviceIdentifier const&); - - ErrorOr initialize_and_enumerate_channels(bool force_pio); - - // FIXME: Find a better way to get the ProgrammingInterface - PCI::ProgrammingInterface m_prog_if; - PCI::InterruptLine m_interrupt_line; -}; -} diff --git a/Kernel/Boot/CommandLine.cpp b/Kernel/Boot/CommandLine.cpp index 4ae27403677..2782daca807 100644 --- a/Kernel/Boot/CommandLine.cpp +++ b/Kernel/Boot/CommandLine.cpp @@ -92,11 +92,6 @@ UNMAP_AFTER_INIT bool CommandLine::is_boot_profiling_enabled() const return contains("boot_prof"sv); } -UNMAP_AFTER_INIT bool CommandLine::is_ide_enabled() const -{ - return !contains("disable_ide"sv); -} - UNMAP_AFTER_INIT bool CommandLine::is_smp_enabled() const { // Note: We can't enable SMP mode without enabling the IOAPIC. @@ -195,11 +190,6 @@ bool CommandLine::is_pc_speaker_enabled() const PANIC("Unknown pcspeaker setting: {}", value); } -UNMAP_AFTER_INIT bool CommandLine::is_force_pio() const -{ - return contains("force_pio"sv); -} - UNMAP_AFTER_INIT StringView CommandLine::root_device() const { return lookup("root"sv).value_or("lun0:0:0"sv); diff --git a/Kernel/Boot/CommandLine.h b/Kernel/Boot/CommandLine.h index 35fd26e7d86..ac5920da191 100644 --- a/Kernel/Boot/CommandLine.h +++ b/Kernel/Boot/CommandLine.h @@ -72,7 +72,6 @@ public: [[nodiscard]] bool contains(StringView key) const; [[nodiscard]] bool is_boot_profiling_enabled() const; - [[nodiscard]] bool is_ide_enabled() const; [[nodiscard]] bool is_ioapic_enabled() const; [[nodiscard]] bool is_smp_enabled_without_ioapic_enabled() const; [[nodiscard]] bool is_smp_enabled() const; @@ -85,7 +84,6 @@ public: [[nodiscard]] bool i8042_enable_first_port_translation() const; [[nodiscard]] GraphicsSubsystemMode graphics_subsystem_mode() const; [[nodiscard]] I8042PresenceMode i8042_presence_mode() const; - [[nodiscard]] bool is_force_pio() const; [[nodiscard]] AcpiFeatureLevel acpi_feature_level() const; [[nodiscard]] StringView system_mode() const; [[nodiscard]] PanicMode panic_mode(Validate should_validate = Validate::No) const; diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d572e0dff12..6991f00fc4e 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -113,15 +113,11 @@ set(KERNEL_SOURCES Devices/GPU/VirtIO/GPU3DDevice.cpp Devices/GPU/VirtIO/GraphicsAdapter.cpp Devices/Loop/LoopDevice.cpp - Devices/Storage/ATA/AHCI/Controller.cpp - Devices/Storage/ATA/AHCI/Port.cpp - Devices/Storage/ATA/AHCI/InterruptHandler.cpp - Devices/Storage/ATA/GenericIDE/Controller.cpp - Devices/Storage/ATA/GenericIDE/Channel.cpp - Devices/Storage/ATA/ATAController.cpp - Devices/Storage/ATA/ATADevice.cpp - Devices/Storage/ATA/ATADiskDevice.cpp - Devices/Storage/ATA/ATAPort.cpp + Devices/Storage/AHCI/ATADevice.cpp + Devices/Storage/AHCI/ATADiskDevice.cpp + Devices/Storage/AHCI/Controller.cpp + Devices/Storage/AHCI/InterruptHandler.cpp + Devices/Storage/AHCI/Port.cpp Devices/Storage/NVMe/NVMeController.cpp Devices/Storage/NVMe/NVMeNameSpace.cpp Devices/Storage/NVMe/NVMeInterruptQueue.cpp @@ -419,10 +415,8 @@ if ("${SERENITY_ARCH}" STREQUAL "x86_64") Arch/x86_64/ISABus/HID/VMWareMouseDevice.cpp Arch/x86_64/ISABus/I8042Controller.cpp - Arch/x86_64/ISABus/IDEController.cpp Arch/x86_64/ISABus/SerialDevice.cpp Arch/x86_64/PCI/Controller/HostBridge.cpp - Arch/x86_64/PCI/IDELegacyModeController.cpp Arch/x86_64/PCI/Initializer.cpp Arch/x86_64/PCI/MSI.cpp diff --git a/Kernel/Devices/Storage/ATA/ATADevice.cpp b/Kernel/Devices/Storage/AHCI/ATADevice.cpp similarity index 66% rename from Kernel/Devices/Storage/ATA/ATADevice.cpp rename to Kernel/Devices/Storage/AHCI/ATADevice.cpp index e5c373b9c5a..fd1276b4db2 100644 --- a/Kernel/Devices/Storage/ATA/ATADevice.cpp +++ b/Kernel/Devices/Storage/AHCI/ATADevice.cpp @@ -5,18 +5,18 @@ */ #include -#include +#include #include #include namespace Kernel { -static StorageDevice::LUNAddress convert_ata_address_to_lun_address(ATAController const& controller, ATADevice::Address ata_address) +static StorageDevice::LUNAddress convert_ata_address_to_lun_address(AHCIController const& controller, ATA::Address ata_address) { return StorageDevice::LUNAddress { controller.controller_id(), ata_address.port, ata_address.subport }; } -ATADevice::ATADevice(ATAController const& controller, ATADevice::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) +ATADevice::ATADevice(AHCIController const& controller, ATA::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) : StorageDevice(convert_ata_address_to_lun_address(controller, ata_address), controller.hardware_relative_controller_id(), logical_sector_size, max_addressable_block) , m_controller(controller) , m_ata_address(ata_address) @@ -28,9 +28,8 @@ ATADevice::~ATADevice() = default; void ATADevice::start_request(AsyncBlockDeviceRequest& request) { - auto controller = m_controller.strong_ref(); - VERIFY(controller); - controller->start_request(*this, request); + VERIFY(m_controller); + m_controller->start_request(m_ata_address, request); } } diff --git a/Kernel/Devices/Storage/AHCI/ATADevice.h b/Kernel/Devices/Storage/AHCI/ATADevice.h new file mode 100644 index 00000000000..507a7b9279f --- /dev/null +++ b/Kernel/Devices/Storage/AHCI/ATADevice.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Kernel { + +class ATADevice : public StorageDevice { +public: + virtual ~ATADevice() override; + + // ^BlockDevice + virtual void start_request(AsyncBlockDeviceRequest&) override; + + u16 ata_capabilites() const { return m_capabilities; } + ATA::Address const& ata_address() const { return m_ata_address; } + +protected: + ATADevice(AHCIController const&, ATA::Address, u16, u16, u64); + + // FIXME: Add proper locking to ensure hotplug can work. + LockRefPtr m_controller; + ATA::Address const m_ata_address; + u16 const m_capabilities; +}; + +} diff --git a/Kernel/Devices/Storage/ATA/ATADiskDevice.cpp b/Kernel/Devices/Storage/AHCI/ATADiskDevice.cpp similarity index 66% rename from Kernel/Devices/Storage/ATA/ATADiskDevice.cpp rename to Kernel/Devices/Storage/AHCI/ATADiskDevice.cpp index ef0d3db0cf7..c81c518589f 100644 --- a/Kernel/Devices/Storage/ATA/ATADiskDevice.cpp +++ b/Kernel/Devices/Storage/AHCI/ATADiskDevice.cpp @@ -6,13 +6,13 @@ #include #include -#include +#include #include #include namespace Kernel { -NonnullLockRefPtr ATADiskDevice::create(ATAController const& controller, ATADevice::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) +NonnullLockRefPtr ATADiskDevice::create(AHCIController const& controller, ATA::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) { auto disk_device_or_error = DeviceManagement::try_create_device(controller, ata_address, capabilities, logical_sector_size, max_addressable_block); // FIXME: Find a way to propagate errors @@ -20,7 +20,7 @@ NonnullLockRefPtr ATADiskDevice::create(ATAController const& cont return disk_device_or_error.release_value(); } -ATADiskDevice::ATADiskDevice(ATAController const& controller, ATADevice::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) +ATADiskDevice::ATADiskDevice(AHCIController const& controller, ATA::Address ata_address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block) : ATADevice(controller, ata_address, capabilities, logical_sector_size, max_addressable_block) { } diff --git a/Kernel/Devices/Storage/ATA/ATADiskDevice.h b/Kernel/Devices/Storage/AHCI/ATADiskDevice.h similarity index 67% rename from Kernel/Devices/Storage/ATA/ATADiskDevice.h rename to Kernel/Devices/Storage/AHCI/ATADiskDevice.h index 9576a6eab13..3a656a48124 100644 --- a/Kernel/Devices/Storage/ATA/ATADiskDevice.h +++ b/Kernel/Devices/Storage/AHCI/ATADiskDevice.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include #include @@ -18,14 +18,14 @@ class ATADiskDevice final : public ATADevice { friend class DeviceManagement; public: - static NonnullLockRefPtr create(ATAController const&, ATADevice::Address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block); + static NonnullLockRefPtr create(AHCIController const&, ATA::Address, u16 capabilities, u16 logical_sector_size, u64 max_addressable_block); virtual ~ATADiskDevice() override; // ^StorageDevice virtual CommandSet command_set() const override { return CommandSet::ATA; } private: - ATADiskDevice(ATAController const&, Address, u16, u16, u64); + ATADiskDevice(AHCIController const&, ATA::Address, u16, u16, u64); // ^DiskDevice virtual StringView class_name() const override; diff --git a/Kernel/Devices/Storage/ATA/AHCI/Controller.cpp b/Kernel/Devices/Storage/AHCI/Controller.cpp similarity index 95% rename from Kernel/Devices/Storage/ATA/AHCI/Controller.cpp rename to Kernel/Devices/Storage/AHCI/Controller.cpp index 0b8a9719460..7876dbb8eca 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/Controller.cpp +++ b/Kernel/Devices/Storage/AHCI/Controller.cpp @@ -12,8 +12,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include @@ -87,9 +88,9 @@ size_t AHCIController::devices_count() const return count; } -void AHCIController::start_request(ATADevice const& device, AsyncBlockDeviceRequest& request) +void AHCIController::start_request(ATA::Address address, AsyncBlockDeviceRequest& request) { - auto port = m_ports[device.ata_address().port]; + auto port = m_ports[address.port]; VERIFY(port); port->start_request(request); } @@ -111,7 +112,7 @@ volatile AHCI::HBA& AHCIController::hba() const } UNMAP_AFTER_INIT AHCIController::AHCIController(PCI::DeviceIdentifier const& pci_device_identifier) - : ATAController() + : StorageController(StorageManagement::generate_relative_ahci_controller_id({})) , PCI::Device(const_cast(pci_device_identifier)) { } diff --git a/Kernel/Devices/Storage/ATA/AHCI/Controller.h b/Kernel/Devices/Storage/AHCI/Controller.h similarity index 90% rename from Kernel/Devices/Storage/ATA/AHCI/Controller.h rename to Kernel/Devices/Storage/AHCI/Controller.h index b9bb9df615b..3b8469e0555 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/Controller.h +++ b/Kernel/Devices/Storage/AHCI/Controller.h @@ -8,8 +8,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -20,7 +20,7 @@ namespace Kernel { class AsyncBlockDeviceRequest; class AHCIInterruptHandler; class AHCIPort; -class AHCIController final : public ATAController +class AHCIController final : public StorageController , public PCI::Device { friend class AHCIInterruptHandler; @@ -34,9 +34,10 @@ public: virtual ErrorOr reset() override; virtual ErrorOr shutdown() override; virtual size_t devices_count() const override; - virtual void start_request(ATADevice const&, AsyncBlockDeviceRequest&) override; virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; + void start_request(ATA::Address, AsyncBlockDeviceRequest&); + void handle_interrupt_for_port(Badge, u32 port_index) const; private: diff --git a/Kernel/Devices/Storage/ATA/AHCI/Definitions.h b/Kernel/Devices/Storage/AHCI/Definitions.h similarity index 71% rename from Kernel/Devices/Storage/ATA/AHCI/Definitions.h rename to Kernel/Devices/Storage/AHCI/Definitions.h index 17beea52f42..03c866f2c7a 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/Definitions.h +++ b/Kernel/Devices/Storage/AHCI/Definitions.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Liav A. * * SPDX-License-Identifier: BSD-2-Clause @@ -8,6 +9,7 @@ #include #include +#include namespace Kernel::FIS { @@ -445,3 +447,218 @@ struct [[gnu::packed]] CommandTable { static_assert(AssertSize()); } + +namespace Kernel::ATA { + +// NOTE: For SATA drives (AHCI driven HBAs), a port can be a number from 0 to 31, +// and subport can be a number from 0 to 14 (only 15 devices are allowed to +// be connected to one SATA port multiplier). +struct Address { + // FIXME: u32 for this value is wasteful, because even AHCI only support 32 ports + u32 port; + u8 subport; +}; + +enum DeviceSignature : u32 { + ATA = 0x00000101, + ATAPI = 0xEB140101, + EnclosureManagementBridge = 0xC33C0101, + PortMultiplier = 0x96690101, + Unconnected = 0xFFFFFFFF +}; + +} + +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 + +#define ATA_ER_BBK 0x80 +#define ATA_ER_UNC 0x40 +#define ATA_ER_MC 0x20 +#define ATA_ER_IDNF 0x10 +#define ATA_ER_MCR 0x08 +#define ATA_ER_ABRT 0x04 +#define ATA_ER_TK0NF 0x02 +#define ATA_ER_AMNF 0x01 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define ATA_USE_LBA_ADDRESSING (1 << 6) + +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 + +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_CTL_CONTROL 0x00 +#define ATA_CTL_ALTSTATUS 0x00 +#define ATA_CTL_DEVADDRESS 0x01 + +#define ATA_CAP_LBA 0x200 + +namespace Kernel { + +struct [[gnu::packed]] ATAIdentifyBlock { + u16 general_configuration; + u16 obsolete; + u16 specific_configuration; + + u16 obsolete2; + u16 retired[2]; + u16 obsolete3; + + u16 reserved_for_cfa[2]; + u16 retired2; + u16 serial_number[10]; + + u16 retired3[2]; + u16 obsolete4; + + u16 firmware_revision[4]; + u16 model_number[20]; + + u16 maximum_logical_sectors_per_drq; + u16 trusted_computing_features; + u16 capabilities[2]; + u16 obsolete5[2]; + u16 validity_flags; + u16 obsolete6[5]; + + u16 security_features; + + u32 max_28_bit_addressable_logical_sector; + u16 obsolete7; + u16 dma_modes; + u16 pio_modes; + + u16 minimum_multiword_dma_transfer_cycle; + u16 recommended_multiword_dma_transfer_cycle; + + u16 minimum_multiword_pio_transfer_cycle_without_flow_control; + u16 minimum_multiword_pio_transfer_cycle_with_flow_control; + + u16 additional_supported; + u16 reserved3[5]; + u16 queue_depth; + + u16 serial_ata_capabilities; + u16 serial_ata_additional_capabilities; + u16 serial_ata_features_supported; + u16 serial_ata_features_enabled; + u16 major_version_number; + u16 minor_version_number; + u16 commands_and_feature_sets_supported[3]; + u16 commands_and_feature_sets_supported_or_enabled[3]; + u16 ultra_dma_modes; + + u16 timing_for_security_features[2]; + u16 apm_level; + u16 master_password_id; + + u16 hardware_reset_results; + u16 obsolete8; + + u16 stream_minimum_request_time; + u16 streaming_transfer_time_for_dma; + u16 streaming_access_latency; + u16 streaming_performance_granularity[2]; + + u64 user_addressable_logical_sectors_count; + + u16 streaming_transfer_time_for_pio; + u16 max_512_byte_blocks_per_data_set_management_command; + u16 physical_sector_size_to_logical_sector_size; + u16 inter_seek_delay_for_acoustic_testing; + u16 world_wide_name[4]; + u16 reserved4[4]; + u16 obsolete9; + + u32 logical_sector_size; + + u16 commands_and_feature_sets_supported2; + u16 commands_and_feature_sets_supported_or_enabled2; + + u16 reserved_for_expanded_supported_and_enabled_settings[6]; + u16 obsolete10; + + u16 security_status; + u16 vendor_specific[31]; + u16 reserved_for_cfa2[8]; + u16 device_nominal_form_factor; + u16 data_set_management_command_support; + u16 additional_product_id[4]; + u16 reserved5[2]; + u16 current_media_serial_number[30]; + u16 sct_command_transport; + u16 reserved6[2]; + + u16 logical_sectors_alignment_within_physical_sector; + + u32 write_read_verify_sector_mode_3_count; + u32 write_read_verify_sector_mode_2_count; + + u16 obsolete11[3]; + u16 nominal_media_rotation_rate; + u16 reserved7; + u16 obsolete12; + u16 write_read_verify_feature_set_current_mode; + u16 reserved8; + u16 transport_major_version_number; + u16 transport_minor_version_number; + u16 reserved9[6]; + + u64 extended_user_addressable_logical_sectors_count; + + u16 minimum_512_byte_data_blocks_per_download_microcode_operation; + u16 max_512_byte_data_blocks_per_download_microcode_operation; + + u16 reserved10[19]; + u16 integrity; +}; + +}; diff --git a/Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.cpp b/Kernel/Devices/Storage/AHCI/InterruptHandler.cpp similarity index 96% rename from Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.cpp rename to Kernel/Devices/Storage/AHCI/InterruptHandler.cpp index f0fcfefbb95..1435a0dd59a 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.cpp +++ b/Kernel/Devices/Storage/AHCI/InterruptHandler.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include namespace Kernel { diff --git a/Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.h b/Kernel/Devices/Storage/AHCI/InterruptHandler.h similarity index 93% rename from Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.h rename to Kernel/Devices/Storage/AHCI/InterruptHandler.h index 459f5d827b5..200e7aa4fb4 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/InterruptHandler.h +++ b/Kernel/Devices/Storage/AHCI/InterruptHandler.h @@ -7,8 +7,8 @@ #pragma once #include -#include -#include +#include +#include #include #include #include diff --git a/Kernel/Devices/Storage/ATA/AHCI/Port.cpp b/Kernel/Devices/Storage/AHCI/Port.cpp similarity index 96% rename from Kernel/Devices/Storage/ATA/AHCI/Port.cpp rename to Kernel/Devices/Storage/AHCI/Port.cpp index 10e4120f5a5..e941c5ce095 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/Port.cpp +++ b/Kernel/Devices/Storage/AHCI/Port.cpp @@ -9,9 +9,8 @@ #include #include -#include -#include -#include +#include +#include #include #include #include @@ -181,14 +180,9 @@ void AHCIPort::recover_from_fatal_error() { MutexLocker locker(m_lock); SpinlockLocker lock(m_hard_lock); - LockRefPtr controller = m_parent_controller.strong_ref(); - if (!controller) { - dmesgln("AHCI Port {}: fatal error, controller not available", representative_port_index()); - return; - } - dmesgln("{}: AHCI Port {} fatal error, shutting down!", controller->device_identifier().address(), representative_port_index()); - dmesgln("{}: AHCI Port {} fatal error, SError {}", controller->device_identifier().address(), representative_port_index(), (u32)m_port_registers.serr); + dmesgln("{}: AHCI Port {} fatal error, shutting down!", m_parent_controller->device_identifier().address(), representative_port_index()); + dmesgln("{}: AHCI Port {} fatal error, SError {}", m_parent_controller->device_identifier().address(), representative_port_index(), (u32)m_port_registers.serr); stop_command_list_processing(); stop_fis_receiving(); m_interrupt_enable.clear(); @@ -283,12 +277,7 @@ bool AHCIPort::initialize() // FIXME: We don't support ATAPI devices yet, so for now we don't "create" them if (!is_atapi_attached()) { - LockRefPtr controller = m_parent_controller.strong_ref(); - if (!controller) { - dmesgln("AHCI Port {}: Device found, but parent controller is not available, abort.", representative_port_index()); - return false; - } - m_connected_device = ATADiskDevice::create(*controller, { m_port_index, 0 }, 0, logical_sector_size, max_addressable_sector); + m_connected_device = ATADiskDevice::create(*m_parent_controller, { m_port_index, 0 }, 0, logical_sector_size, max_addressable_sector); } else { dbgln("AHCI Port {}: Ignoring ATAPI devices as we don't support them.", representative_port_index()); } @@ -590,10 +579,6 @@ bool AHCIPort::identify_device() if (!spin_until_ready()) return false; - LockRefPtr controller = m_parent_controller.strong_ref(); - if (!controller) - return false; - auto unused_command_header = try_to_find_unused_command_header(); VERIFY(unused_command_header.has_value()); auto* command_list_entries = (volatile AHCI::CommandHeader*)m_command_list_region->vaddr().as_ptr(); diff --git a/Kernel/Devices/Storage/ATA/AHCI/Port.h b/Kernel/Devices/Storage/AHCI/Port.h similarity index 94% rename from Kernel/Devices/Storage/ATA/AHCI/Port.h rename to Kernel/Devices/Storage/AHCI/Port.h index 7024dfaac30..7bdfe624d70 100644 --- a/Kernel/Devices/Storage/ATA/AHCI/Port.h +++ b/Kernel/Devices/Storage/AHCI/Port.h @@ -9,10 +9,9 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -126,7 +125,7 @@ private: NonnullRefPtr const m_identify_buffer_page; volatile AHCI::PortRegisters& m_port_registers; - LockWeakPtr m_parent_controller; + NonnullRefPtr const m_parent_controller; AHCI::PortInterruptStatusBitField m_interrupt_status; AHCI::PortInterruptEnableBitField m_interrupt_enable; diff --git a/Kernel/Devices/Storage/ATA/ATAController.cpp b/Kernel/Devices/Storage/ATA/ATAController.cpp deleted file mode 100644 index 8631d911725..00000000000 --- a/Kernel/Devices/Storage/ATA/ATAController.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - -namespace Kernel { - -ATAController::ATAController() - : StorageController(StorageManagement::generate_relative_ata_controller_id({})) -{ -} - -} diff --git a/Kernel/Devices/Storage/ATA/ATAController.h b/Kernel/Devices/Storage/ATA/ATAController.h deleted file mode 100644 index 19fab7fe52f..00000000000 --- a/Kernel/Devices/Storage/ATA/ATAController.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; - -class ATADevice; -class ATAController - : public StorageController - , public LockWeakable { -public: - virtual void start_request(ATADevice const&, AsyncBlockDeviceRequest&) = 0; - -protected: - ATAController(); -}; -} diff --git a/Kernel/Devices/Storage/ATA/ATADevice.h b/Kernel/Devices/Storage/ATA/ATADevice.h deleted file mode 100644 index 1759e8eb95d..00000000000 --- a/Kernel/Devices/Storage/ATA/ATADevice.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace Kernel { - -class ATADevice : public StorageDevice { -public: - // Note: For IDE drives, port means Primary or Secondary (0 or 1), - // and subport means Master or Slave (0 or 1). - // For SATA drives (AHCI driven HBAs), a port can be a number from 0 to 31, - // and subport can be a number from 0 to 14 (only 15 devices are allowed to - // be connected to one SATA port multiplier). - struct Address { - // FIXME: u32 for this value is wasteful, because even AHCI only support 32 ports - u32 port; - u8 subport; - }; - -public: - virtual ~ATADevice() override; - - // ^BlockDevice - virtual void start_request(AsyncBlockDeviceRequest&) override; - - u16 ata_capabilites() const { return m_capabilities; } - Address const& ata_address() const { return m_ata_address; } - -protected: - ATADevice(ATAController const&, Address, u16, u16, u64); - - LockWeakPtr m_controller; - Address const m_ata_address; - u16 const m_capabilities; -}; - -} diff --git a/Kernel/Devices/Storage/ATA/ATAPort.cpp b/Kernel/Devices/Storage/ATA/ATAPort.cpp deleted file mode 100644 index 5f9bc3b09fd..00000000000 --- a/Kernel/Devices/Storage/ATA/ATAPort.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -class ATAPortInterruptDisabler { -public: - ATAPortInterruptDisabler(ATAPort& port) - : m_port(port) - { - (void)port.disable_interrupts(); - } - - ~ATAPortInterruptDisabler() - { - (void)m_port->enable_interrupts(); - } - -private: - LockRefPtr m_port; -}; - -class ATAPortInterruptCleaner { -public: - ATAPortInterruptCleaner(ATAPort& port) - : m_port(port) - { - } - - ~ATAPortInterruptCleaner() - { - (void)m_port->force_clear_interrupts(); - } - -private: - LockRefPtr m_port; -}; - -void ATAPort::fix_name_string_in_identify_device_block() -{ - VERIFY(m_lock.is_locked()); - auto* wbuf = (u16*)m_ata_identify_data_buffer->data(); - auto* bbuf = m_ata_identify_data_buffer->data() + 27 * 2; - for (size_t word_index = 27; word_index < 47; word_index++) { - u16 data = wbuf[word_index]; - *(bbuf++) = MSB(data); - *(bbuf++) = LSB(data); - } -} - -ErrorOr ATAPort::detect_connected_devices() -{ - MutexLocker locker(m_lock); - for (size_t device_index = 0; device_index < max_possible_devices_connected(); device_index++) { - TRY(device_select(device_index)); - auto device_presence = TRY(detect_presence_on_selected_device()); - if (!device_presence) - continue; - - TaskFile identify_taskfile; - memset(&identify_taskfile, 0, sizeof(TaskFile)); - identify_taskfile.command = ATA_CMD_IDENTIFY; - auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_ata_identify_data_buffer->data()); - { - auto result = execute_polled_command(TransactionDirection::Read, LBAMode::None, identify_taskfile, buffer, 0, 256, 100, 100); - if (result.is_error()) { - continue; - } - } - ATAIdentifyBlock volatile& identify_block = (ATAIdentifyBlock volatile&)(*m_ata_identify_data_buffer->data()); - u16 capabilities = identify_block.capabilities[0]; - - StringView device_name = StringView((char const*)const_cast(identify_block.model_number), 40); - fix_name_string_in_identify_device_block(); - - u64 max_addressable_block = identify_block.max_28_bit_addressable_logical_sector; - dbgln("ATAPort: device found: Name={}, Capacity={}, Capabilities={:#04x}", device_name.trim_whitespace(), max_addressable_block * 512, capabilities); - // If the drive is so old that it doesn't support LBA, ignore it. - if (!(capabilities & ATA_CAP_LBA)) { - dbgln("ATAPort: device found but without LBA support (what kind of dinosaur we see here?)"); - continue; - } - // if we support 48-bit LBA, use that value instead. - if (identify_block.commands_and_feature_sets_supported[1] & (1 << 10)) - max_addressable_block = identify_block.user_addressable_logical_sectors_count; - // FIXME: Don't assume all drives will have logical sector size of 512 bytes. - ATADevice::Address address = { m_port_index, static_cast(device_index) }; - m_ata_devices.append(ATADiskDevice::create(m_parent_ata_controller, address, capabilities, 512, max_addressable_block)); - } - return {}; -} - -LockRefPtr ATAPort::connected_device(size_t device_index) const -{ - MutexLocker locker(m_lock); - if (m_ata_devices.size() > device_index) - return m_ata_devices[device_index]; - return {}; -} - -ErrorOr ATAPort::start_request(ATADevice const& associated_device, AsyncBlockDeviceRequest& request) -{ - MutexLocker locker(m_lock); - VERIFY(m_current_request.is_null()); - VERIFY(pio_capable() || dma_capable()); - - dbgln_if(ATA_DEBUG, "ATAPort::start_request"); - - m_current_request = request; - m_current_request_block_index = 0; - m_current_request_flushing_cache = false; - - if (dma_capable()) { - TRY(prepare_and_initiate_dma_transaction(associated_device)); - return {}; - } - TRY(prepare_and_initiate_pio_transaction(associated_device)); - return {}; -} - -void ATAPort::complete_pio_transaction(AsyncDeviceRequest::RequestResult result) -{ - VERIFY(m_current_request); - - // Now schedule reading back the buffer as soon as we leave the irq handler. - // This is important so that we can safely write the buffer back, - // which could cause page faults. Note that this may be called immediately - // before Processor::deferred_call_queue returns! - auto work_item_creation_result = g_io_work->try_queue([this, result]() { - dbgln_if(ATA_DEBUG, "ATAPort::complete_pio_transaction result: {}", (int)result); - MutexLocker locker(m_lock); - VERIFY(m_current_request); - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(result); - }); - if (work_item_creation_result.is_error()) { - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(AsyncDeviceRequest::OutOfMemory); - } -} - -void ATAPort::complete_dma_transaction(AsyncDeviceRequest::RequestResult result) -{ - // NOTE: this may be called from the interrupt handler! - VERIFY(m_current_request); - VERIFY(m_lock.is_locked()); - - // Now schedule reading back the buffer as soon as we leave the irq handler. - // This is important so that we can safely write the buffer back, - // which could cause page faults. Note that this may be called immediately - // before Processor::deferred_call_queue returns! - auto work_item_creation_result = g_io_work->try_queue([this, result]() { - dbgln_if(ATA_DEBUG, "ATAPort::complete_dma_transaction result: {}", (int)result); - MutexLocker locker(m_lock); - if (!m_current_request) - return; - auto current_request = m_current_request; - m_current_request.clear(); - - if (result == AsyncDeviceRequest::Success) { - { - auto result = force_busmastering_status_clean(); - if (result.is_error()) { - locker.unlock(); - current_request->complete(AsyncDeviceRequest::Failure); - return; - } - } - - if (current_request->request_type() == AsyncBlockDeviceRequest::Read) { - if (auto result = current_request->write_to_buffer(current_request->buffer(), m_dma_buffer_region->vaddr().as_ptr(), 512 * current_request->block_count()); result.is_error()) { - locker.unlock(); - current_request->complete(AsyncDeviceRequest::MemoryFault); - return; - } - } - } - locker.unlock(); - current_request->complete(result); - }); - if (work_item_creation_result.is_error()) { - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(AsyncDeviceRequest::OutOfMemory); - } -} - -static void print_ata_status(u8 status) -{ - dbgln("ATAPort: print_status: DRQ={} BSY={}, DRDY={}, DSC={}, DF={}, CORR={}, IDX={}, ERR={}", - (status & ATA_SR_DRQ) != 0, - (status & ATA_SR_BSY) != 0, - (status & ATA_SR_DRDY) != 0, - (status & ATA_SR_DSC) != 0, - (status & ATA_SR_DF) != 0, - (status & ATA_SR_CORR) != 0, - (status & ATA_SR_IDX) != 0, - (status & ATA_SR_ERR) != 0); -} - -static void try_disambiguate_ata_error(u8 error) -{ - dbgln("ATAPort: Error cause:"); - - switch (error) { - case ATA_ER_BBK: - dbgln("ATAPort: - Bad block"); - break; - case ATA_ER_UNC: - dbgln("ATAPort: - Uncorrectable data"); - break; - case ATA_ER_MC: - dbgln("ATAPort: - Media changed"); - break; - case ATA_ER_IDNF: - dbgln("ATAPort: - ID mark not found"); - break; - case ATA_ER_MCR: - dbgln("ATAPort: - Media change request"); - break; - case ATA_ER_ABRT: - dbgln("ATAPort: - Command aborted"); - break; - case ATA_ER_TK0NF: - dbgln("ATAPort: - Track 0 not found"); - break; - case ATA_ER_AMNF: - dbgln("ATAPort: - No address mark"); - break; - default: - dbgln("ATAPort: - No one knows"); - break; - } -} - -ErrorOr ATAPort::handle_interrupt_after_dma_transaction() -{ - if (!dma_capable()) - return false; - u8 bstatus = TRY(busmastering_status()); - if (!(bstatus & 0x4)) { - // interrupt not from this device, ignore - dbgln_if(ATA_DEBUG, "ATAPort: ignore interrupt"); - return false; - } - auto work_item_creation_result = g_ata_work->try_queue([this]() -> void { - MutexLocker locker(m_lock); - u8 status = task_file_status().release_value(); - - m_entropy_source.add_random_event(status); - // clear bus master interrupt status - { - auto result = force_busmastering_status_clean(); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - SpinlockLocker lock(m_hard_lock); - dbgln_if(ATA_DEBUG, "ATAPort: interrupt: DRQ={}, BSY={}, DRDY={}", - (status & ATA_SR_DRQ) != 0, - (status & ATA_SR_BSY) != 0, - (status & ATA_SR_DRDY) != 0); - - if (!m_current_request) { - dbgln("ATAPort: IRQ but no pending request!"); - return; - } - - if (status & ATA_SR_ERR) { - print_ata_status(status); - auto device_error = task_file_error().release_value(); - dbgln("ATAPort: Error {:#02x}!", (u8)device_error); - try_disambiguate_ata_error(device_error); - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - complete_dma_transaction(AsyncDeviceRequest::Success); - return; - }); - if (work_item_creation_result.is_error()) { - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(AsyncDeviceRequest::OutOfMemory); - return Error::from_errno(ENOMEM); - } - return true; -} - -ErrorOr ATAPort::prepare_and_initiate_dma_transaction(ATADevice const& associated_device) -{ - VERIFY(m_lock.is_locked()); - VERIFY(!m_current_request.is_null()); - VERIFY(m_current_request->block_count() <= 256); - - // Note: We might be called here from an interrupt handler (like the page fault handler), so queue a read afterwards. - auto work_item_creation_result = g_ata_work->try_queue([this, &associated_device]() -> void { - MutexLocker locker(m_lock); - dbgln_if(ATA_DEBUG, "ATAPort::prepare_and_initiate_dma_transaction ({} x {})", m_current_request->block_index(), m_current_request->block_count()); - - VERIFY(!m_current_request.is_null()); - VERIFY(m_current_request->block_count() <= 256); - { - auto result = device_select(associated_device.ata_address().subport); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - if (m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write) { - if (auto result = m_current_request->read_from_buffer(m_current_request->buffer(), m_dma_buffer_region->vaddr().as_ptr(), 512 * m_current_request->block_count()); result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::MemoryFault); - return; - } - } - - prdt().offset = m_dma_buffer_page->paddr().get(); - prdt().size = 512 * m_current_request->block_count(); - - VERIFY(prdt().size <= PAGE_SIZE); - - SpinlockLocker hard_lock_locker(m_hard_lock); - - { - auto result = stop_busmastering(); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - if (m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write) { - auto result = prepare_transaction_with_busmastering(TransactionDirection::Write, m_prdt_page->paddr()); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } else { - auto result = prepare_transaction_with_busmastering(TransactionDirection::Read, m_prdt_page->paddr()); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - TaskFile taskfile; - LBAMode lba_mode = LBAMode::TwentyEightBit; - auto lba = m_current_request->block_index(); - if ((lba + m_current_request->block_count()) >= 0x10000000) { - lba_mode = LBAMode::FortyEightBit; - } - memset(&taskfile, 0, sizeof(TaskFile)); - taskfile.lba_low[0] = (lba & 0x000000FF) >> 0; - taskfile.lba_low[1] = (lba & 0x0000FF00) >> 8; - taskfile.lba_low[2] = (lba & 0x00FF0000) >> 16; - taskfile.lba_high[0] = (lba & 0xFF000000) >> 24; - taskfile.lba_high[1] = (lba & 0xFF00000000ull) >> 32; - taskfile.lba_high[2] = (lba & 0xFF0000000000ull) >> 40; - taskfile.count = m_current_request->block_count(); - if (lba_mode == LBAMode::TwentyEightBit) - taskfile.command = m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write ? ATA_CMD_WRITE_DMA : ATA_CMD_READ_DMA; - else - taskfile.command = m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_READ_DMA_EXT; - - { - auto result = load_taskfile_into_registers(taskfile, lba_mode, 1000); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - if (m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write) { - auto result = start_busmastering(TransactionDirection::Write); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - - else { - auto result = start_busmastering(TransactionDirection::Read); - if (result.is_error()) { - complete_dma_transaction(AsyncDeviceRequest::Failure); - return; - } - } - }); - if (work_item_creation_result.is_error()) { - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(AsyncDeviceRequest::OutOfMemory); - return Error::from_errno(ENOMEM); - } - return {}; -} - -ErrorOr ATAPort::prepare_and_initiate_pio_transaction(ATADevice const& associated_device) -{ - VERIFY(m_lock.is_locked()); - VERIFY(!m_current_request.is_null()); - VERIFY(m_current_request->block_count() <= 256); - dbgln_if(ATA_DEBUG, "ATAPort::prepare_and_initiate_pio_transaction ({} x {})", m_current_request->block_index(), m_current_request->block_count()); - // Note: We might be called here from an interrupt handler (like the page fault handler), so queue a read afterwards. - auto work_item_creation_result = g_ata_work->try_queue([this, &associated_device]() -> void { - MutexLocker locker(m_lock); - { - auto result = device_select(associated_device.ata_address().subport); - if (result.is_error()) { - complete_pio_transaction(AsyncDeviceRequest::Failure); - return; - } - } - for (size_t block_index = 0; block_index < m_current_request->block_count(); block_index++) { - TaskFile taskfile; - LBAMode lba_mode = LBAMode::TwentyEightBit; - auto lba = m_current_request->block_index() + block_index; - if (lba >= 0x10000000) { - lba_mode = LBAMode::FortyEightBit; - } - memset(&taskfile, 0, sizeof(TaskFile)); - taskfile.lba_low[0] = (lba & 0x000000FF) >> 0; - taskfile.lba_low[1] = (lba & 0x0000FF00) >> 8; - taskfile.lba_low[2] = (lba & 0x00FF0000) >> 16; - taskfile.lba_high[0] = (lba & 0xFF000000) >> 24; - taskfile.lba_high[1] = (lba & 0xFF00000000ull) >> 32; - taskfile.lba_high[2] = (lba & 0xFF0000000000ull) >> 40; - taskfile.count = 1; - if (lba_mode == LBAMode::TwentyEightBit) - taskfile.command = m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write ? ATA_CMD_WRITE_PIO : ATA_CMD_READ_PIO; - else - taskfile.command = m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Write ? ATA_CMD_WRITE_PIO_EXT : ATA_CMD_READ_PIO_EXT; - - if (m_current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Read) { - auto result = execute_polled_command(TransactionDirection::Read, lba_mode, taskfile, m_current_request->buffer(), block_index, 256, 100, 100); - if (result.is_error()) { - complete_pio_transaction(AsyncDeviceRequest::Failure); - return; - } - - } else { - auto result = execute_polled_command(TransactionDirection::Write, lba_mode, taskfile, m_current_request->buffer(), block_index, 256, 100, 100); - if (result.is_error()) { - complete_pio_transaction(AsyncDeviceRequest::Failure); - return; - } - } - } - complete_pio_transaction(AsyncDeviceRequest::Success); - }); - if (work_item_creation_result.is_error()) { - auto current_request = m_current_request; - m_current_request.clear(); - current_request->complete(AsyncDeviceRequest::OutOfMemory); - return Error::from_errno(ENOMEM); - } - return {}; -} - -ErrorOr ATAPort::execute_polled_command(TransactionDirection direction, LBAMode lba_mode, TaskFile const& taskfile, UserOrKernelBuffer& buffer, size_t block_offset, size_t words_count, size_t preparation_timeout_in_milliseconds, size_t completion_timeout_in_milliseconds) -{ - // Disable interrupts temporarily, just in case we have that enabled, - // remember the value to re-enable (and clean) later if needed. - ATAPortInterruptDisabler disabler(*this); - ATAPortInterruptCleaner cleaner(*this); - MutexLocker locker(m_lock); - { - SpinlockLocker hard_locker(m_hard_lock); - - // Wait for device to be not busy or timeout - TRY(wait_if_busy_until_timeout(preparation_timeout_in_milliseconds)); - - // Send command, wait for result or timeout - TRY(load_taskfile_into_registers(taskfile, lba_mode, preparation_timeout_in_milliseconds)); - - size_t milliseconds_elapsed = 0; - for (;;) { - if (milliseconds_elapsed > completion_timeout_in_milliseconds) - break; - u8 status = task_file_status().release_value(); - if (status & ATA_SR_ERR) { - return Error::from_errno(EINVAL); - } - - if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) { - break; - } - - microseconds_delay(1000); - milliseconds_elapsed++; - } - if (milliseconds_elapsed > completion_timeout_in_milliseconds) { - critical_dmesgln("ATAPort: device state unknown. Timeout exceeded."); - return Error::from_errno(EINVAL); - } - } - - VERIFY_INTERRUPTS_ENABLED(); - if (direction == TransactionDirection::Read) - TRY(read_pio_data_to_buffer(buffer, block_offset, words_count)); - else - TRY(write_pio_data_from_buffer(buffer, block_offset, words_count)); - return {}; -} - -} diff --git a/Kernel/Devices/Storage/ATA/ATAPort.h b/Kernel/Devices/Storage/ATA/ATAPort.h deleted file mode 100644 index b0747b33571..00000000000 --- a/Kernel/Devices/Storage/ATA/ATAPort.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; - -class ATAPort - : public AtomicRefCounted - , public LockWeakable { - - friend class ATAPortInterruptDisabler; - friend class ATAPortInterruptCleaner; - -public: - struct TaskFile { - u8 command; - u8 lba_low[3]; - u8 device; - u8 lba_high[3]; - u8 features_high; - u16 count; - u8 icc; - u8 control; - u32 reserved; - }; - - enum class TransactionDirection : u8 { - Read, - Write, - }; - - struct [[gnu::packed]] PhysicalRegionDescriptor { - u32 offset; - u16 size { 0 }; - u16 end_of_table { 0 }; - }; - - enum class LBAMode : u8 { - None, - TwentyEightBit, - FortyEightBit, - }; - -public: - LockRefPtr connected_device(size_t device_index) const; - - virtual ~ATAPort() = default; - - virtual ErrorOr disable() = 0; - virtual ErrorOr power_on() = 0; - ErrorOr detect_connected_devices(); - ErrorOr handle_interrupt_after_dma_transaction(); - - ErrorOr start_request(ATADevice const& associated_device, AsyncBlockDeviceRequest&); - - // Note: Generic (P)ATA IDE "ports" are tied to the IDE channel link (cable), and trying to - // reset the master port or slave port and vice versa requires to actually reset - // both at once... - // This is due to the fact that IDE devices can be connected together (master-slave) - // with one 80 pin cable which forms one (primary/secondary) "ATA bus". - // Intel AHCI controllers generally allow individual phy port reset. The caller - // of this method should know this in advance... - // Note: ATAPI devices are an exception to this, so even if we initiate a - // a port reset, there's no guarantee that ATAPI devices will reset anyway, - // so resetting them requires to actually send the ATA "DEVICE RESET" command. - virtual ErrorOr port_phy_reset() = 0; - - // Note: Software reset means individual reset to a selected device on the "bus" (port). - // This means that this will likely work for devices that indicate support for - // PACKET commands (ATAPI devices) that also support DEVICE RESET. For other devices - // there's no other method to reset them besides (full) PHY reset. - // For devices that don't support this feature, just return ENOTSUP. - virtual ErrorOr soft_reset() { return Error::from_errno(ENOTSUP); } - - ErrorOr execute_polled_command(TransactionDirection direction, LBAMode lba_mode, TaskFile const& taskfile, UserOrKernelBuffer&, size_t block_offset, size_t words_count, size_t preparation_timeout_in_milliseconds, size_t completion_timeout_in_milliseconds); - - virtual bool has_sata_capabilities() { return false; } - - virtual bool pio_capable() const = 0; - virtual bool dma_capable() const = 0; - - virtual size_t max_possible_devices_connected() const = 0; - -private: - ErrorOr prepare_and_initiate_dma_transaction(ATADevice const& associated_device); - ErrorOr prepare_and_initiate_pio_transaction(ATADevice const& associated_device); - - void complete_dma_transaction(AsyncDeviceRequest::RequestResult result); - void complete_pio_transaction(AsyncDeviceRequest::RequestResult result); - - void fix_name_string_in_identify_device_block(); - -protected: - virtual ErrorOr task_file_status() = 0; - virtual ErrorOr task_file_error() = 0; - - virtual ErrorOr wait_if_busy_until_timeout(size_t timeout_in_milliseconds) = 0; - - virtual ErrorOr device_select(size_t device_index) = 0; - virtual ErrorOr detect_presence_on_selected_device() = 0; - - virtual ErrorOr enable_interrupts() = 0; - virtual ErrorOr disable_interrupts() = 0; - - virtual ErrorOr stop_busmastering() = 0; - virtual ErrorOr start_busmastering(TransactionDirection) = 0; - virtual ErrorOr force_busmastering_status_clean() = 0; - virtual ErrorOr busmastering_status() = 0; - virtual ErrorOr prepare_transaction_with_busmastering(TransactionDirection, PhysicalAddress prdt_buffer) = 0; - virtual ErrorOr initiate_transaction(TransactionDirection) = 0; - - virtual ErrorOr force_clear_interrupts() = 0; - - // Note: This method assume we already selected the correct device! - virtual ErrorOr load_taskfile_into_registers(TaskFile const&, LBAMode lba_mode, size_t completion_timeout_in_milliseconds) = 0; - - virtual ErrorOr read_pio_data_to_buffer(UserOrKernelBuffer&, size_t block_offset, size_t words_count) = 0; - virtual ErrorOr write_pio_data_from_buffer(UserOrKernelBuffer const&, size_t block_offset, size_t words_count) = 0; - - PhysicalRegionDescriptor& prdt() { return *reinterpret_cast(m_prdt_region->vaddr().as_ptr()); } - - ATAPort(ATAController const& parent_controller, u8 port_index, NonnullOwnPtr ata_identify_data_buffer) - : m_port_index(port_index) - , m_ata_identify_data_buffer(move(ata_identify_data_buffer)) - , m_parent_ata_controller(parent_controller) - { - } - - mutable Mutex m_lock; - Spinlock m_hard_lock {}; - - EntropySource m_entropy_source; - - LockRefPtr m_current_request; - u64 m_current_request_block_index { 0 }; - bool m_current_request_flushing_cache { false }; - - OwnPtr m_prdt_region; - OwnPtr m_dma_buffer_region; - RefPtr m_prdt_page; - RefPtr m_dma_buffer_page; - - u8 const m_port_index; - Vector> m_ata_devices; - NonnullOwnPtr m_ata_identify_data_buffer; - NonnullLockRefPtr m_parent_ata_controller; -}; -} diff --git a/Kernel/Devices/Storage/ATA/Definitions.h b/Kernel/Devices/Storage/ATA/Definitions.h deleted file mode 100644 index 18eddcbf628..00000000000 --- a/Kernel/Devices/Storage/ATA/Definitions.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Kernel::ATA { - -enum DeviceSignature : u32 { - ATA = 0x00000101, - ATAPI = 0xEB140101, - EnclosureManagementBridge = 0xC33C0101, - PortMultiplier = 0x96690101, - Unconnected = 0xFFFFFFFF -}; -} - -#define ATA_SR_BSY 0x80 -#define ATA_SR_DRDY 0x40 -#define ATA_SR_DF 0x20 -#define ATA_SR_DSC 0x10 -#define ATA_SR_DRQ 0x08 -#define ATA_SR_CORR 0x04 -#define ATA_SR_IDX 0x02 -#define ATA_SR_ERR 0x01 - -#define ATA_ER_BBK 0x80 -#define ATA_ER_UNC 0x40 -#define ATA_ER_MC 0x20 -#define ATA_ER_IDNF 0x10 -#define ATA_ER_MCR 0x08 -#define ATA_ER_ABRT 0x04 -#define ATA_ER_TK0NF 0x02 -#define ATA_ER_AMNF 0x01 - -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - -#define ATAPI_CMD_READ 0xA8 -#define ATAPI_CMD_EJECT 0x1B - -#define ATA_IDENT_DEVICETYPE 0 -#define ATA_IDENT_CYLINDERS 2 -#define ATA_IDENT_HEADS 6 -#define ATA_IDENT_SECTORS 12 -#define ATA_IDENT_SERIAL 20 -#define ATA_IDENT_MODEL 54 -#define ATA_IDENT_CAPABILITIES 98 -#define ATA_IDENT_FIELDVALID 106 -#define ATA_IDENT_MAX_LBA 120 -#define ATA_IDENT_COMMANDSETS 164 -#define ATA_IDENT_MAX_LBA_EXT 200 - -#define ATA_USE_LBA_ADDRESSING (1 << 6) - -#define IDE_ATA 0x00 -#define IDE_ATAPI 0x01 - -#define ATA_REG_DATA 0x00 -#define ATA_REG_ERROR 0x01 -#define ATA_REG_FEATURES 0x01 -#define ATA_REG_SECCOUNT0 0x02 -#define ATA_REG_LBA0 0x03 -#define ATA_REG_LBA1 0x04 -#define ATA_REG_LBA2 0x05 -#define ATA_REG_HDDEVSEL 0x06 -#define ATA_REG_COMMAND 0x07 -#define ATA_REG_STATUS 0x07 -#define ATA_REG_SECCOUNT1 0x08 -#define ATA_REG_LBA3 0x09 -#define ATA_REG_LBA4 0x0A -#define ATA_REG_LBA5 0x0B -#define ATA_CTL_CONTROL 0x00 -#define ATA_CTL_ALTSTATUS 0x00 -#define ATA_CTL_DEVADDRESS 0x01 - -#define ATA_CAP_LBA 0x200 - -namespace Kernel { -struct [[gnu::packed]] ATAIdentifyBlock { - u16 general_configuration; - u16 obsolete; - u16 specific_configuration; - - u16 obsolete2; - u16 retired[2]; - u16 obsolete3; - - u16 reserved_for_cfa[2]; - u16 retired2; - u16 serial_number[10]; - - u16 retired3[2]; - u16 obsolete4; - - u16 firmware_revision[4]; - u16 model_number[20]; - - u16 maximum_logical_sectors_per_drq; - u16 trusted_computing_features; - u16 capabilities[2]; - u16 obsolete5[2]; - u16 validity_flags; - u16 obsolete6[5]; - - u16 security_features; - - u32 max_28_bit_addressable_logical_sector; - u16 obsolete7; - u16 dma_modes; - u16 pio_modes; - - u16 minimum_multiword_dma_transfer_cycle; - u16 recommended_multiword_dma_transfer_cycle; - - u16 minimum_multiword_pio_transfer_cycle_without_flow_control; - u16 minimum_multiword_pio_transfer_cycle_with_flow_control; - - u16 additional_supported; - u16 reserved3[5]; - u16 queue_depth; - - u16 serial_ata_capabilities; - u16 serial_ata_additional_capabilities; - u16 serial_ata_features_supported; - u16 serial_ata_features_enabled; - u16 major_version_number; - u16 minor_version_number; - u16 commands_and_feature_sets_supported[3]; - u16 commands_and_feature_sets_supported_or_enabled[3]; - u16 ultra_dma_modes; - - u16 timing_for_security_features[2]; - u16 apm_level; - u16 master_password_id; - - u16 hardware_reset_results; - u16 obsolete8; - - u16 stream_minimum_request_time; - u16 streaming_transfer_time_for_dma; - u16 streaming_access_latency; - u16 streaming_performance_granularity[2]; - - u64 user_addressable_logical_sectors_count; - - u16 streaming_transfer_time_for_pio; - u16 max_512_byte_blocks_per_data_set_management_command; - u16 physical_sector_size_to_logical_sector_size; - u16 inter_seek_delay_for_acoustic_testing; - u16 world_wide_name[4]; - u16 reserved4[4]; - u16 obsolete9; - - u32 logical_sector_size; - - u16 commands_and_feature_sets_supported2; - u16 commands_and_feature_sets_supported_or_enabled2; - - u16 reserved_for_expanded_supported_and_enabled_settings[6]; - u16 obsolete10; - - u16 security_status; - u16 vendor_specific[31]; - u16 reserved_for_cfa2[8]; - u16 device_nominal_form_factor; - u16 data_set_management_command_support; - u16 additional_product_id[4]; - u16 reserved5[2]; - u16 current_media_serial_number[30]; - u16 sct_command_transport; - u16 reserved6[2]; - - u16 logical_sectors_alignment_within_physical_sector; - - u32 write_read_verify_sector_mode_3_count; - u32 write_read_verify_sector_mode_2_count; - - u16 obsolete11[3]; - u16 nominal_media_rotation_rate; - u16 reserved7; - u16 obsolete12; - u16 write_read_verify_feature_set_current_mode; - u16 reserved8; - u16 transport_major_version_number; - u16 transport_minor_version_number; - u16 reserved9[6]; - - u64 extended_user_addressable_logical_sectors_count; - - u16 minimum_512_byte_data_blocks_per_download_microcode_operation; - u16 max_512_byte_data_blocks_per_download_microcode_operation; - - u16 reserved10[19]; - u16 integrity; -}; -}; diff --git a/Kernel/Devices/Storage/ATA/GenericIDE/Channel.cpp b/Kernel/Devices/Storage/ATA/GenericIDE/Channel.cpp deleted file mode 100644 index c82fb5054a0..00000000000 --- a/Kernel/Devices/Storage/ATA/GenericIDE/Channel.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2018-2021, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -#define PATA_PRIMARY_IRQ 14 -#define PATA_SECONDARY_IRQ 15 - -UNMAP_AFTER_INIT ErrorOr> IDEChannel::create(IDEController const& controller, IOWindowGroup io_window_group, ChannelType type) -{ - auto ata_identify_data_buffer = KBuffer::try_create_with_size("ATA Identify Page"sv, 4096, Memory::Region::Access::ReadWrite, AllocationStrategy::AllocateNow).release_value(); - return adopt_nonnull_ref_or_enomem(new (nothrow) IDEChannel(controller, move(io_window_group), type, move(ata_identify_data_buffer))); -} - -UNMAP_AFTER_INIT ErrorOr> IDEChannel::create(IDEController const& controller, u8 irq, IOWindowGroup io_window_group, ChannelType type) -{ - auto ata_identify_data_buffer = KBuffer::try_create_with_size("ATA Identify Page"sv, 4096, Memory::Region::Access::ReadWrite, AllocationStrategy::AllocateNow).release_value(); - return adopt_nonnull_ref_or_enomem(new (nothrow) IDEChannel(controller, irq, move(io_window_group), type, move(ata_identify_data_buffer))); -} - -StringView IDEChannel::channel_type_string() const -{ - if (m_channel_type == ChannelType::Primary) - return "Primary"sv; - return "Secondary"sv; -} - -bool IDEChannel::select_device_and_wait_until_not_busy(DeviceType device_type, size_t milliseconds_timeout) -{ - microseconds_delay(20); - u8 slave = device_type == DeviceType::Slave; - m_io_window_group.io_window().write8(ATA_REG_HDDEVSEL, 0xA0 | (slave << 4)); // First, we need to select the drive itself - microseconds_delay(20); - size_t time_elapsed = 0; - while (m_io_window_group.control_window().read8(0) & ATA_SR_BSY && time_elapsed <= milliseconds_timeout) { - microseconds_delay(1000); - time_elapsed++; - } - return time_elapsed <= milliseconds_timeout; -} - -ErrorOr IDEChannel::port_phy_reset() -{ - MutexLocker locker(m_lock); - SpinlockLocker hard_locker(m_hard_lock); - // reset the channel - u8 device_control = m_io_window_group.control_window().read8(0); - // Wait 30 milliseconds - microseconds_delay(30000); - m_io_window_group.control_window().write8(0, device_control | (1 << 2)); - // Wait 30 milliseconds - microseconds_delay(30000); - m_io_window_group.control_window().write8(0, device_control); - // Wait up to 30 seconds before failing - if (!select_device_and_wait_until_not_busy(DeviceType::Master, 30000)) { - dbgln("IDEChannel: reset failed, busy flag on master stuck"); - return Error::from_errno(EBUSY); - } - // Wait up to 30 seconds before failing - if (!select_device_and_wait_until_not_busy(DeviceType::Slave, 30000)) { - dbgln("IDEChannel: reset failed, busy flag on slave stuck"); - return Error::from_errno(EBUSY); - } - return {}; -} - -#if ARCH(X86_64) -ErrorOr IDEChannel::allocate_resources_for_pci_ide_controller(Badge, bool force_pio) -{ - return allocate_resources(force_pio); -} -ErrorOr IDEChannel::allocate_resources_for_isa_ide_controller(Badge) -{ - return allocate_resources(true); -} -#endif - -UNMAP_AFTER_INIT ErrorOr IDEChannel::allocate_resources(bool force_pio) -{ - dbgln_if(PATA_DEBUG, "IDEChannel: {} IO base: {}", channel_type_string(), m_io_window_group.io_window()); - dbgln_if(PATA_DEBUG, "IDEChannel: {} control base: {}", channel_type_string(), m_io_window_group.control_window()); - if (m_io_window_group.bus_master_window()) - dbgln_if(PATA_DEBUG, "IDEChannel: {} bus master base: {}", channel_type_string(), m_io_window_group.bus_master_window()); - else - dbgln_if(PATA_DEBUG, "IDEChannel: {} bus master base disabled", channel_type_string()); - - if (!force_pio) { - m_dma_enabled = true; - VERIFY(m_io_window_group.bus_master_window()); - // Let's try to set up DMA transfers. - - m_prdt_region = TRY(MM.allocate_dma_buffer_page("IDE PRDT"sv, Memory::Region::Access::ReadWrite, m_prdt_page)); - VERIFY(!m_prdt_page.is_null()); - m_dma_buffer_region = TRY(MM.allocate_dma_buffer_page("IDE DMA region"sv, Memory::Region::Access::ReadWrite, m_dma_buffer_page)); - VERIFY(!m_dma_buffer_page.is_null()); - - prdt().end_of_table = 0x8000; - - // clear bus master interrupt status - m_io_window_group.bus_master_window()->write8(2, m_io_window_group.bus_master_window()->read8(2) | 4); - } - return {}; -} - -UNMAP_AFTER_INIT IDEChannel::IDEChannel(IDEController const& controller, u8 irq, IOWindowGroup io_group, ChannelType type, NonnullOwnPtr ata_identify_data_buffer) - : ATAPort(controller, (type == ChannelType::Primary ? 0 : 1), move(ata_identify_data_buffer)) - , IRQHandler(irq) - , m_channel_type(type) - , m_io_window_group(move(io_group)) -{ -} - -UNMAP_AFTER_INIT IDEChannel::IDEChannel(IDEController const& controller, IOWindowGroup io_group, ChannelType type, NonnullOwnPtr ata_identify_data_buffer) - : ATAPort(controller, (type == ChannelType::Primary ? 0 : 1), move(ata_identify_data_buffer)) - , IRQHandler(type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ) - , m_channel_type(type) - , m_io_window_group(move(io_group)) -{ -} - -UNMAP_AFTER_INIT IDEChannel::~IDEChannel() = default; - -bool IDEChannel::handle_irq(RegisterState const&) -{ - auto result = handle_interrupt_after_dma_transaction(); - // FIXME: Propagate errors properly - VERIFY(!result.is_error()); - return result.release_value(); -} - -ErrorOr IDEChannel::stop_busmastering() -{ - VERIFY(m_lock.is_locked()); - VERIFY(m_io_window_group.bus_master_window()); - m_io_window_group.bus_master_window()->write8(0, 0); - return {}; -} -ErrorOr IDEChannel::start_busmastering(TransactionDirection direction) -{ - VERIFY(m_lock.is_locked()); - VERIFY(m_io_window_group.bus_master_window()); - m_io_window_group.bus_master_window()->write8(0, (direction != TransactionDirection::Write ? 0x9 : 0x1)); - return {}; -} -ErrorOr IDEChannel::force_busmastering_status_clean() -{ - VERIFY(m_lock.is_locked()); - VERIFY(m_io_window_group.bus_master_window()); - m_io_window_group.bus_master_window()->write8(2, m_io_window_group.bus_master_window()->read8(2) | 4); - return {}; -} -ErrorOr IDEChannel::busmastering_status() -{ - VERIFY(m_io_window_group.bus_master_window()); - return m_io_window_group.bus_master_window()->read8(2); -} -ErrorOr IDEChannel::prepare_transaction_with_busmastering(TransactionDirection direction, PhysicalAddress prdt_buffer) -{ - VERIFY(m_lock.is_locked()); - m_io_window_group.bus_master_window()->write32(4, prdt_buffer.get()); - m_io_window_group.bus_master_window()->write8(0, direction != TransactionDirection::Write ? 0x8 : 0); - - // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. - m_io_window_group.bus_master_window()->write8(2, m_io_window_group.bus_master_window()->read8(2) | 0x6); - return {}; -} -ErrorOr IDEChannel::initiate_transaction(TransactionDirection) -{ - VERIFY(m_lock.is_locked()); - return {}; -} - -ErrorOr IDEChannel::task_file_status() -{ - VERIFY(m_lock.is_locked()); - return m_io_window_group.control_window().read8(0); -} - -ErrorOr IDEChannel::task_file_error() -{ - VERIFY(m_lock.is_locked()); - return m_io_window_group.io_window().read8(ATA_REG_ERROR); -} - -ErrorOr IDEChannel::detect_presence_on_selected_device() -{ - VERIFY(m_lock.is_locked()); - m_io_window_group.io_window().write8(ATA_REG_SECCOUNT0, 0x55); - m_io_window_group.io_window().write8(ATA_REG_LBA0, 0xAA); - - m_io_window_group.io_window().write8(ATA_REG_SECCOUNT0, 0xAA); - m_io_window_group.io_window().write8(ATA_REG_LBA0, 0x55); - - m_io_window_group.io_window().write8(ATA_REG_SECCOUNT0, 0x55); - m_io_window_group.io_window().write8(ATA_REG_LBA0, 0xAA); - - auto nsectors_value = m_io_window_group.io_window().read8(ATA_REG_SECCOUNT0); - auto lba0 = m_io_window_group.io_window().read8(ATA_REG_LBA0); - - if (lba0 == 0xAA && nsectors_value == 0x55) - return true; - return false; -} - -ErrorOr IDEChannel::wait_if_busy_until_timeout(size_t timeout_in_milliseconds) -{ - size_t time_elapsed = 0; - while (m_io_window_group.control_window().read8(0) & ATA_SR_BSY && time_elapsed <= timeout_in_milliseconds) { - microseconds_delay(1000); - time_elapsed++; - } - if (time_elapsed <= timeout_in_milliseconds) - return {}; - return Error::from_errno(EBUSY); -} - -ErrorOr IDEChannel::force_clear_interrupts() -{ - VERIFY(m_lock.is_locked()); - m_io_window_group.io_window().read8(ATA_REG_STATUS); - return {}; -} - -ErrorOr IDEChannel::load_taskfile_into_registers(ATAPort::TaskFile const& task_file, LBAMode lba_mode, size_t completion_timeout_in_milliseconds) -{ - VERIFY(m_lock.is_locked()); - VERIFY(m_hard_lock.is_locked()); - u8 head = 0; - if (lba_mode == LBAMode::FortyEightBit) { - head = 0; - } else if (lba_mode == LBAMode::TwentyEightBit) { - head = (task_file.lba_high[0] & 0x0F); - } - - // Note: Preserve the selected drive, always use LBA addressing - auto driver_register = ((m_io_window_group.io_window().read8(ATA_REG_HDDEVSEL) & (1 << 4)) | (head | (1 << 5) | (1 << 6))); - m_io_window_group.io_window().write8(ATA_REG_HDDEVSEL, driver_register); - microseconds_delay(50); - - if (lba_mode == LBAMode::FortyEightBit) { - m_io_window_group.io_window().write8(ATA_REG_SECCOUNT1, (task_file.count >> 8) & 0xFF); - m_io_window_group.io_window().write8(ATA_REG_LBA3, task_file.lba_high[0]); - m_io_window_group.io_window().write8(ATA_REG_LBA4, task_file.lba_high[1]); - m_io_window_group.io_window().write8(ATA_REG_LBA5, task_file.lba_high[2]); - } - - m_io_window_group.io_window().write8(ATA_REG_SECCOUNT0, task_file.count & 0xFF); - m_io_window_group.io_window().write8(ATA_REG_LBA0, task_file.lba_low[0]); - m_io_window_group.io_window().write8(ATA_REG_LBA1, task_file.lba_low[1]); - m_io_window_group.io_window().write8(ATA_REG_LBA2, task_file.lba_low[2]); - - // FIXME: Set a timeout here? - size_t time_elapsed = 0; - for (;;) { - if (time_elapsed > completion_timeout_in_milliseconds) - return Error::from_errno(EBUSY); - // FIXME: Use task_file_status method - auto status = m_io_window_group.control_window().read8(0); - if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) - break; - microseconds_delay(1000); - time_elapsed++; - } - m_io_window_group.io_window().write8(ATA_REG_COMMAND, task_file.command); - return {}; -} - -ErrorOr IDEChannel::device_select(size_t device_index) -{ - VERIFY(m_lock.is_locked()); - if (device_index > 1) - return Error::from_errno(EINVAL); - microseconds_delay(20); - m_io_window_group.io_window().write8(ATA_REG_HDDEVSEL, (0xA0 | ((device_index) << 4))); - microseconds_delay(20); - return {}; -} - -ErrorOr IDEChannel::enable_interrupts() -{ - VERIFY(m_lock.is_locked()); - m_io_window_group.control_window().write8(0, 0); - m_interrupts_enabled = true; - return {}; -} -ErrorOr IDEChannel::disable_interrupts() -{ - VERIFY(m_lock.is_locked()); - m_io_window_group.control_window().write8(0, 1 << 1); - m_interrupts_enabled = false; - return {}; -} - -ErrorOr IDEChannel::read_pio_data_to_buffer(UserOrKernelBuffer& buffer, size_t block_offset, size_t words_count) -{ - VERIFY(m_lock.is_locked()); - VERIFY(words_count == 256); - for (u32 i = 0; i < 256; ++i) { - u16 data = m_io_window_group.io_window().read16(ATA_REG_DATA); - // FIXME: Don't assume 512 bytes sector - TRY(buffer.write(&data, block_offset * 512 + (i * 2), 2)); - } - return {}; -} -ErrorOr IDEChannel::write_pio_data_from_buffer(UserOrKernelBuffer const& buffer, size_t block_offset, size_t words_count) -{ - VERIFY(m_lock.is_locked()); - VERIFY(words_count == 256); - for (u32 i = 0; i < 256; ++i) { - u16 buf; - // FIXME: Don't assume 512 bytes sector - TRY(buffer.read(&buf, block_offset * 512 + (i * 2), 2)); - m_io_window_group.io_window().write16(ATA_REG_DATA, buf); - } - return {}; -} -} diff --git a/Kernel/Devices/Storage/ATA/GenericIDE/Channel.h b/Kernel/Devices/Storage/ATA/GenericIDE/Channel.h deleted file mode 100644 index d28a3b961b6..00000000000 --- a/Kernel/Devices/Storage/ATA/GenericIDE/Channel.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -// -// Parallel ATA (PATA) controller driver -// -// This driver describes a logical PATA Channel. Each channel can connect up to 2 -// IDE Hard Disk Drives. The drives themselves can be either the master drive (hd0) -// or the slave drive (hd1). -// -// More information about the ATA spec for PATA can be found here: -// ftp://ftp.seagate.com/acrobat/reference/111-1c.pdf -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; - -class IDEController; -#if ARCH(X86_64) -class PCIIDELegacyModeController; -class ISAIDEController; -#endif -class IDEChannel - : public ATAPort - , public IRQHandler { - friend class IDEController; - -public: - enum class ChannelType : u8 { - Primary, - Secondary - }; - - enum class DeviceType : u8 { - Master, - Slave, - }; - - struct IOWindowGroup { - IOWindowGroup(NonnullOwnPtr io_window, NonnullOwnPtr control_window, NonnullOwnPtr m_bus_master_window) - : m_io_window(move(io_window)) - , m_control_window(move(control_window)) - , m_bus_master_window(move(m_bus_master_window)) - { - } - - IOWindowGroup(NonnullOwnPtr io_window, NonnullOwnPtr control_window) - : m_io_window(move(io_window)) - , m_control_window(move(control_window)) - { - } - - // Disable default implementations that would use surprising integer promotion. - bool operator==(IOWindowGroup const&) const = delete; - bool operator<=(IOWindowGroup const&) const = delete; - bool operator>=(IOWindowGroup const&) const = delete; - bool operator<(IOWindowGroup const&) const = delete; - bool operator>(IOWindowGroup const&) const = delete; - - IOWindow& io_window() const { return *m_io_window; } - IOWindow& control_window() const { return *m_control_window; } - IOWindow* bus_master_window() const { return m_bus_master_window.ptr(); } - - private: - mutable NonnullOwnPtr m_io_window; - mutable NonnullOwnPtr m_control_window; - mutable OwnPtr m_bus_master_window; - }; - -public: - static ErrorOr> create(IDEController const&, IOWindowGroup, ChannelType type); - static ErrorOr> create(IDEController const&, u8 irq, IOWindowGroup, ChannelType type); - - virtual ~IDEChannel() override; - - virtual StringView purpose() const override { return "PATA Channel"sv; } - -#if ARCH(X86_64) - ErrorOr allocate_resources_for_pci_ide_controller(Badge, bool force_pio); - ErrorOr allocate_resources_for_isa_ide_controller(Badge); -#endif - -private: - static constexpr size_t m_logical_sector_size = 512; - ErrorOr allocate_resources(bool force_pio); - StringView channel_type_string() const; - - virtual ErrorOr disable() override { TODO(); } - virtual ErrorOr power_on() override { TODO(); } - - virtual ErrorOr port_phy_reset() override; - bool select_device_and_wait_until_not_busy(DeviceType, size_t milliseconds_timeout); - - virtual bool pio_capable() const override { return true; } - virtual bool dma_capable() const override { return m_dma_enabled; } - - virtual size_t max_possible_devices_connected() const override { return 2; } - - virtual ErrorOr stop_busmastering() override; - virtual ErrorOr start_busmastering(TransactionDirection) override; - virtual ErrorOr force_busmastering_status_clean() override; - virtual ErrorOr busmastering_status() override; - virtual ErrorOr prepare_transaction_with_busmastering(TransactionDirection, PhysicalAddress prdt_buffer) override; - virtual ErrorOr initiate_transaction(TransactionDirection) override; - - virtual ErrorOr task_file_status() override; - virtual ErrorOr task_file_error() override; - - virtual ErrorOr wait_if_busy_until_timeout(size_t timeout_in_milliseconds) override; - - virtual ErrorOr device_select(size_t device_index) override; - virtual ErrorOr detect_presence_on_selected_device() override; - - virtual ErrorOr enable_interrupts() override; - virtual ErrorOr disable_interrupts() override; - - virtual ErrorOr force_clear_interrupts() override; - virtual ErrorOr load_taskfile_into_registers(TaskFile const&, LBAMode lba_mode, size_t completion_timeout_in_milliseconds) override; - - virtual ErrorOr read_pio_data_to_buffer(UserOrKernelBuffer&, size_t block_offset, size_t words_count) override; - virtual ErrorOr write_pio_data_from_buffer(UserOrKernelBuffer const&, size_t block_offset, size_t words_count) override; - - IDEChannel(IDEController const&, IOWindowGroup, ChannelType type, NonnullOwnPtr ata_identify_data_buffer); - IDEChannel(IDEController const&, u8 irq, IOWindowGroup, ChannelType type, NonnullOwnPtr ata_identify_data_buffer); - //^ IRQHandler - virtual bool handle_irq(RegisterState const&) override; - - // Data members - ChannelType m_channel_type { ChannelType::Primary }; - - bool m_dma_enabled { false }; - bool m_interrupts_enabled { true }; - - IOWindowGroup m_io_window_group; -}; -} diff --git a/Kernel/Devices/Storage/ATA/GenericIDE/Controller.cpp b/Kernel/Devices/Storage/ATA/GenericIDE/Controller.cpp deleted file mode 100644 index 8a92f97f511..00000000000 --- a/Kernel/Devices/Storage/ATA/GenericIDE/Controller.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020-2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { - -ErrorOr IDEController::reset() -{ - return Error::from_errno(ENOTIMPL); -} - -ErrorOr IDEController::shutdown() -{ - return Error::from_errno(ENOTIMPL); -} - -size_t IDEController::devices_count() const -{ - size_t count = 0; - for (u32 index = 0; index < 4; index++) { - if (!device(index).is_null()) - count++; - } - return count; -} - -void IDEController::start_request(ATADevice const& device, AsyncBlockDeviceRequest& request) -{ - auto& address = device.ata_address(); - VERIFY(address.subport < 2); - switch (address.port) { - case 0: { - auto result = m_channels[0]->start_request(device, request); - // FIXME: Propagate errors properly - VERIFY(!result.is_error()); - return; - } - case 1: { - auto result = m_channels[1]->start_request(device, request); - // FIXME: Propagate errors properly - VERIFY(!result.is_error()); - return; - } - } - VERIFY_NOT_REACHED(); -} - -void IDEController::complete_current_request(AsyncDeviceRequest::RequestResult) -{ - VERIFY_NOT_REACHED(); -} - -UNMAP_AFTER_INIT IDEController::IDEController() = default; -UNMAP_AFTER_INIT IDEController::~IDEController() = default; - -LockRefPtr IDEController::device_by_channel_and_position(u32 index) const -{ - switch (index) { - case 0: - return m_channels[0]->connected_device(0); - case 1: - return m_channels[0]->connected_device(1); - case 2: - return m_channels[1]->connected_device(0); - case 3: - return m_channels[1]->connected_device(1); - } - VERIFY_NOT_REACHED(); -} - -LockRefPtr IDEController::device(u32 index) const -{ - Vector> connected_devices; - for (size_t index = 0; index < 4; index++) { - auto checked_device = device_by_channel_and_position(index); - if (checked_device.is_null()) - continue; - connected_devices.append(checked_device.release_nonnull()); - } - if (index >= connected_devices.size()) - return nullptr; - return connected_devices[index]; -} -} diff --git a/Kernel/Devices/Storage/ATA/GenericIDE/Controller.h b/Kernel/Devices/Storage/ATA/GenericIDE/Controller.h deleted file mode 100644 index b8af2bf83fe..00000000000 --- a/Kernel/Devices/Storage/ATA/GenericIDE/Controller.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020-2022, Liav A. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace Kernel { - -class AsyncBlockDeviceRequest; -class IDEChannel; -class IDEController : public ATAController { -public: - virtual ~IDEController() override; - - virtual LockRefPtr device(u32 index) const override final; - virtual ErrorOr reset() override final; - virtual ErrorOr shutdown() override final; - virtual size_t devices_count() const override final; - virtual void start_request(ATADevice const&, AsyncBlockDeviceRequest&) override final; - virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override final; - -protected: - IDEController(); - - LockRefPtr device_by_channel_and_position(u32 index) const; - Array, 2> m_channels; -}; -} diff --git a/Kernel/Devices/Storage/StorageManagement.cpp b/Kernel/Devices/Storage/StorageManagement.cpp index 10cfb313583..0cfbe1aa1b4 100644 --- a/Kernel/Devices/Storage/StorageManagement.cpp +++ b/Kernel/Devices/Storage/StorageManagement.cpp @@ -9,10 +9,6 @@ #include #include #include -#if ARCH(X86_64) -# include -# include -#endif #if ARCH(AARCH64) # include #endif @@ -22,8 +18,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -42,7 +37,7 @@ static Atomic s_storage_device_minor_number; static Atomic s_partition_device_minor_number; static Atomic s_controller_id; -static Atomic s_relative_ata_controller_id; +static Atomic s_relative_ahci_controller_id; static Atomic s_relative_nvme_controller_id; static Atomic s_relative_sd_controller_id; @@ -51,7 +46,7 @@ static constexpr StringView partition_uuid_prefix = "PARTUUID:"sv; static constexpr StringView partition_number_prefix = "part"sv; static constexpr StringView block_device_prefix = "block"sv; -static constexpr StringView ata_device_prefix = "ata"sv; +static constexpr StringView ahci_device_prefix = "ahci"sv; static constexpr StringView nvme_device_prefix = "nvme"sv; static constexpr StringView logical_unit_number_device_prefix = "lun"sv; static constexpr StringView sd_device_prefix = "sd"sv; @@ -67,10 +62,10 @@ u32 StorageManagement::generate_relative_nvme_controller_id(Badge) +u32 StorageManagement::generate_relative_ahci_controller_id(Badge) { - auto controller_id = s_relative_ata_controller_id.load(); - s_relative_ata_controller_id++; + auto controller_id = s_relative_ahci_controller_id.load(); + s_relative_ahci_controller_id++; return controller_id; } @@ -93,7 +88,7 @@ void StorageManagement::remove_device(StorageDevice& device) m_storage_devices.remove(device); } -UNMAP_AFTER_INIT void StorageManagement::enumerate_pci_controllers(bool force_pio, bool nvme_poll) +UNMAP_AFTER_INIT void StorageManagement::enumerate_pci_controllers(bool nvme_poll) { VERIFY(m_controllers.is_empty()); @@ -112,25 +107,6 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_pci_controllers(bool force_pi using SubclassID = PCI::MassStorage::SubclassID; auto subclass_code = static_cast(device_identifier.subclass_code().value()); -#if ARCH(X86_64) - if (subclass_code == SubclassID::IDEController && kernel_command_line().is_ide_enabled()) { - if (auto ide_controller_or_error = PCIIDELegacyModeController::initialize(device_identifier, force_pio); !ide_controller_or_error.is_error()) - m_controllers.append(ide_controller_or_error.release_value()); - else - dmesgln("Unable to initialize IDE controller: {}", ide_controller_or_error.error()); - } -#elif ARCH(AARCH64) - (void)force_pio; - TODO_AARCH64(); -#elif ARCH(RISCV64) - (void)force_pio; - if (subclass_code == SubclassID::IDEController && kernel_command_line().is_ide_enabled()) { - TODO_RISCV64(); - } -#else -# error Unknown architecture -#endif - if (subclass_code == SubclassID::SATAController && device_identifier.prog_if() == PCI::MassStorage::SATAProgIF::AHCI) { if (auto ahci_controller_or_error = AHCIController::initialize(device_identifier); !ahci_controller_or_error.is_error()) @@ -326,7 +302,7 @@ UNMAP_AFTER_INIT void StorageManagement::determine_hardware_relative_boot_device UNMAP_AFTER_INIT void StorageManagement::determine_ata_boot_device() { - determine_hardware_relative_boot_device(ata_device_prefix, [](StorageDevice const& device) -> bool { + determine_hardware_relative_boot_device(ahci_device_prefix, [](StorageDevice const& device) -> bool { return device.command_set() == StorageDevice::CommandSet::ATA; }); } @@ -400,7 +376,7 @@ UNMAP_AFTER_INIT bool StorageManagement::determine_boot_device(StringView boot_a return m_boot_block_device; } - if (m_boot_argument.starts_with(ata_device_prefix)) { + if (m_boot_argument.starts_with(ahci_device_prefix)) { determine_ata_boot_device(); return m_boot_block_device; } @@ -481,18 +457,11 @@ NonnullRefPtr StorageManagement::root_filesystem() const return file_system; } -UNMAP_AFTER_INIT void StorageManagement::initialize(bool force_pio, bool poll) +UNMAP_AFTER_INIT void StorageManagement::initialize(bool poll) { VERIFY(s_storage_device_minor_number == 0); - if (PCI::Access::is_disabled()) { -#if ARCH(X86_64) - // Note: If PCI is disabled, we assume that at least we have an ISA IDE controller - // to probe and use - auto isa_ide_controller = MUST(ISAIDEController::initialize()); - m_controllers.append(isa_ide_controller); -#endif - } else { - enumerate_pci_controllers(force_pio, poll); + if (!PCI::Access::is_disabled()) { + enumerate_pci_controllers(poll); } #if ARCH(AARCH64) diff --git a/Kernel/Devices/Storage/StorageManagement.h b/Kernel/Devices/Storage/StorageManagement.h index 2c664571a0d..665c76d5c71 100644 --- a/Kernel/Devices/Storage/StorageManagement.h +++ b/Kernel/Devices/Storage/StorageManagement.h @@ -18,13 +18,13 @@ namespace Kernel { -class ATAController; +class AHCIController; class NVMeController; class StorageManagement { public: StorageManagement(); - void initialize(bool force_pio, bool nvme_poll); + void initialize(bool nvme_poll); static StorageManagement& the(); bool determine_boot_device(StringView boot_argument); @@ -38,14 +38,14 @@ public: static u32 generate_controller_id(); static u32 generate_relative_nvme_controller_id(Badge); - static u32 generate_relative_ata_controller_id(Badge); + static u32 generate_relative_ahci_controller_id(Badge); static u32 generate_relative_sd_controller_id(Badge); void add_device(StorageDevice&); void remove_device(StorageDevice&); private: - void enumerate_pci_controllers(bool force_pio, bool nvme_poll); + void enumerate_pci_controllers(bool nvme_poll); void enumerate_storage_devices(); ErrorOr enumerate_device_partitions(StorageDevice&); void enumerate_disk_partitions(); diff --git a/Meta/gn/secondary/Kernel/BUILD.gn b/Meta/gn/secondary/Kernel/BUILD.gn index 11632d212e3..22a07b52756 100644 --- a/Meta/gn/secondary/Kernel/BUILD.gn +++ b/Meta/gn/secondary/Kernel/BUILD.gn @@ -319,7 +319,6 @@ source_set("arch_sources") { "Arch/x86_64/I8042Reboot.cpp", "Arch/x86_64/ISABus/HID/VMWareMouseDevice.cpp", "Arch/x86_64/ISABus/I8042Controller.cpp", - "Arch/x86_64/ISABus/IDEController.cpp", "Arch/x86_64/ISABus/SerialDevice.cpp", "Arch/x86_64/InterruptEntry.cpp", "Arch/x86_64/InterruptManagement.cpp", @@ -328,7 +327,6 @@ source_set("arch_sources") { "Arch/x86_64/Interrupts/IOAPIC.cpp", "Arch/x86_64/Interrupts/PIC.cpp", "Arch/x86_64/PCI/Controller/HostBridge.cpp", - "Arch/x86_64/PCI/IDELegacyModeController.cpp", "Arch/x86_64/PCI/Initializer.cpp", "Arch/x86_64/PCI/MSI.cpp", "Arch/x86_64/PCSpeaker.cpp", @@ -556,15 +554,12 @@ executable("Kernel_bin") { "Devices/KCOVInstance.cpp", "Devices/PCISerialDevice.cpp", "Devices/SerialDevice.cpp", - "Devices/Storage/ATA/AHCI/Controller.cpp", - "Devices/Storage/ATA/AHCI/InterruptHandler.cpp", - "Devices/Storage/ATA/AHCI/Port.cpp", - "Devices/Storage/ATA/ATAController.cpp", - "Devices/Storage/ATA/ATADevice.cpp", - "Devices/Storage/ATA/ATADiskDevice.cpp", - "Devices/Storage/ATA/ATAPort.cpp", - "Devices/Storage/ATA/GenericIDE/Channel.cpp", - "Devices/Storage/ATA/GenericIDE/Controller.cpp", + "Devices/Storage/AHCI/ATAController.cpp", + "Devices/Storage/AHCI/ATADevice.cpp", + "Devices/Storage/AHCI/ATADiskDevice.cpp", + "Devices/Storage/AHCI/Controller.cpp", + "Devices/Storage/AHCI/InterruptHandler.cpp", + "Devices/Storage/AHCI/Port.cpp", "Devices/Storage/DiskPartition.cpp", "Devices/Storage/NVMe/NVMeController.cpp", "Devices/Storage/NVMe/NVMeInterruptQueue.cpp",