diff --git a/Kernel/Storage/BMIDEChannel.cpp b/Kernel/Storage/BMIDEChannel.cpp index e6214680c1..0a4c7ddd72 100644 --- a/Kernel/Storage/BMIDEChannel.cpp +++ b/Kernel/Storage/BMIDEChannel.cpp @@ -36,12 +36,23 @@ UNMAP_AFTER_INIT NonnullRefPtr BMIDEChannel::create(const IDEContr return adopt(*new BMIDEChannel(ide_controller, io_group, type)); } +UNMAP_AFTER_INIT NonnullRefPtr BMIDEChannel::create(const IDEController& ide_controller, u8 irq, IDEChannel::IOAddressGroup io_group, IDEChannel::ChannelType type) +{ + return adopt(*new BMIDEChannel(ide_controller, irq, io_group, type)); +} + UNMAP_AFTER_INIT BMIDEChannel::BMIDEChannel(const IDEController& controller, IDEChannel::IOAddressGroup io_group, IDEChannel::ChannelType type) : IDEChannel(controller, io_group, type) { initialize(); } +UNMAP_AFTER_INIT BMIDEChannel::BMIDEChannel(const IDEController& controller, u8 irq, IDEChannel::IOAddressGroup io_group, IDEChannel::ChannelType type) + : IDEChannel(controller, irq, io_group, type) +{ + initialize(); +} + UNMAP_AFTER_INIT void BMIDEChannel::initialize() { VERIFY(m_io_group.bus_master_base().has_value()); diff --git a/Kernel/Storage/BMIDEChannel.h b/Kernel/Storage/BMIDEChannel.h index 281048f1a0..855adf17ca 100644 --- a/Kernel/Storage/BMIDEChannel.h +++ b/Kernel/Storage/BMIDEChannel.h @@ -46,12 +46,14 @@ class BMIDEChannel final : public IDEChannel { public: static NonnullRefPtr create(const IDEController&, IDEChannel::IOAddressGroup, IDEChannel::ChannelType type); + static NonnullRefPtr create(const IDEController&, u8 irq, IDEChannel::IOAddressGroup, IDEChannel::ChannelType type); virtual ~BMIDEChannel() override {}; virtual bool is_dma_enabled() const override { return true; }; private: BMIDEChannel(const IDEController&, IDEChannel::IOAddressGroup, IDEChannel::ChannelType type); + BMIDEChannel(const IDEController&, u8 irq, IDEChannel::IOAddressGroup, IDEChannel::ChannelType type); void initialize(); void complete_current_request(AsyncDeviceRequest::RequestResult); diff --git a/Kernel/Storage/IDEChannel.cpp b/Kernel/Storage/IDEChannel.cpp index 52e324a8d3..f8b7418130 100644 --- a/Kernel/Storage/IDEChannel.cpp +++ b/Kernel/Storage/IDEChannel.cpp @@ -49,6 +49,11 @@ UNMAP_AFTER_INIT NonnullRefPtr IDEChannel::create(const IDEControlle return adopt(*new IDEChannel(controller, io_group, type)); } +UNMAP_AFTER_INIT NonnullRefPtr IDEChannel::create(const IDEController& controller, u8 irq, IOAddressGroup io_group, ChannelType type) +{ + return adopt(*new IDEChannel(controller, irq, io_group, type)); +} + RefPtr IDEChannel::master_device() const { return m_master; @@ -59,16 +64,9 @@ RefPtr IDEChannel::slave_device() const return m_slave; } -UNMAP_AFTER_INIT IDEChannel::IDEChannel(const IDEController& controller, IOAddressGroup io_group, ChannelType type) - : IRQHandler(type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ) - , m_channel_type(type) - , m_io_group(io_group) - , m_parent_controller(controller) +UNMAP_AFTER_INIT void IDEChannel::initialize() { disable_irq(); - - // FIXME: The device may not be capable of DMA. - dbgln_if(PATA_DEBUG, "IDEChannel: {} IO base: {}", channel_type_string(), m_io_group.io_base()); dbgln_if(PATA_DEBUG, "IDEChannel: {} control base: {}", channel_type_string(), m_io_group.control_base()); if (m_io_group.bus_master_base().has_value()) @@ -83,6 +81,24 @@ UNMAP_AFTER_INIT IDEChannel::IDEChannel(const IDEController& controller, IOAddre clear_pending_interrupts(); } +UNMAP_AFTER_INIT IDEChannel::IDEChannel(const IDEController& controller, u8 irq, IOAddressGroup io_group, ChannelType type) + : IRQHandler(irq) + , m_channel_type(type) + , m_io_group(io_group) + , m_parent_controller(controller) +{ + initialize(); +} + +UNMAP_AFTER_INIT IDEChannel::IDEChannel(const IDEController& controller, IOAddressGroup io_group, ChannelType type) + : IRQHandler(type == ChannelType::Primary ? PATA_PRIMARY_IRQ : PATA_SECONDARY_IRQ) + , m_channel_type(type) + , m_io_group(io_group) + , m_parent_controller(controller) +{ + initialize(); +} + void IDEChannel::clear_pending_interrupts() const { m_io_group.io_base().offset(ATA_REG_STATUS).in(); diff --git a/Kernel/Storage/IDEChannel.h b/Kernel/Storage/IDEChannel.h index c6b3598297..5fc1c2e80f 100644 --- a/Kernel/Storage/IDEChannel.h +++ b/Kernel/Storage/IDEChannel.h @@ -106,6 +106,7 @@ public: public: static NonnullRefPtr create(const IDEController&, IOAddressGroup, ChannelType type); + static NonnullRefPtr create(const IDEController&, u8 irq, IOAddressGroup, ChannelType type); virtual ~IDEChannel() override; RefPtr master_device() const; @@ -117,6 +118,7 @@ public: private: void complete_current_request(AsyncDeviceRequest::RequestResult); + void initialize(); protected: enum class LBAMode : u8 { @@ -131,6 +133,7 @@ protected: }; IDEChannel(const IDEController&, IOAddressGroup, ChannelType type); + IDEChannel(const IDEController&, u8 irq, IOAddressGroup, ChannelType type); //^ IRQHandler virtual void handle_irq(const RegisterState&) override; diff --git a/Kernel/Storage/IDEController.cpp b/Kernel/Storage/IDEController.cpp index 7d06d634cf..c55adf432c 100644 --- a/Kernel/Storage/IDEController.cpp +++ b/Kernel/Storage/IDEController.cpp @@ -80,6 +80,21 @@ UNMAP_AFTER_INIT IDEController::~IDEController() { } +bool IDEController::is_pci_native_mode_enabled() const +{ + return (PCI::get_programming_interface(pci_address()) & 0x05) != 0; +} + +bool IDEController::is_pci_native_mode_enabled_on_primary_channel() const +{ + return (PCI::get_programming_interface(pci_address()) & 0x1) == 0x1; +} + +bool IDEController::is_pci_native_mode_enabled_on_secondary_channel() const +{ + return (PCI::get_programming_interface(pci_address()) & 0x4) == 0x4; +} + bool IDEController::is_bus_master_capable() const { return PCI::get_programming_interface(pci_address()) & (1 << 7); @@ -119,28 +134,49 @@ UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio) dbgln("IDE controller @ {}: primary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2).in() >> 5) & 0b11)); dbgln("IDE controller @ {}: secondary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2 + 8).in() >> 5) & 0b11)); - auto bar0 = PCI::get_BAR0(pci_address()); - auto base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0); - auto bar1 = PCI::get_BAR1(pci_address()); - auto control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1); - if (!is_bus_master_capable()) force_pio = true; - if (force_pio) - m_channels.append(IDEChannel::create(*this, { base_io, control_io }, IDEChannel::ChannelType::Primary)); - else - m_channels.append(BMIDEChannel::create(*this, { base_io, control_io, bus_master_base }, IDEChannel::ChannelType::Primary)); + auto bar0 = PCI::get_BAR0(pci_address()); + auto primary_base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0 & (~1)); + auto bar1 = PCI::get_BAR1(pci_address()); + auto primary_control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1 & (~1)); + auto bar2 = PCI::get_BAR2(pci_address()); + auto secondary_base_io = (bar2 == 0x1 || bar2 == 0) ? IOAddress(0x170) : IOAddress(bar2 & (~1)); + auto bar3 = PCI::get_BAR3(pci_address()); + auto secondary_control_io = (bar3 == 0x1 || bar3 == 0) ? IOAddress(0x376) : IOAddress(bar3 & (~1)); + + auto irq_line = PCI::get_interrupt_line(pci_address()); + if (is_pci_native_mode_enabled()) { + VERIFY(irq_line != 0); + } + + if (is_pci_native_mode_enabled_on_primary_channel()) { + if (force_pio) + m_channels.append(IDEChannel::create(*this, irq_line, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary)); + else + m_channels.append(BMIDEChannel::create(*this, irq_line, { primary_control_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary)); + } else { + if (force_pio) + m_channels.append(IDEChannel::create(*this, { primary_base_io, primary_control_io }, IDEChannel::ChannelType::Primary)); + else + m_channels.append(BMIDEChannel::create(*this, { primary_base_io, primary_control_io, bus_master_base }, IDEChannel::ChannelType::Primary)); + } + m_channels[0].enable_irq(); - auto bar2 = PCI::get_BAR2(pci_address()); - base_io = (bar2 == 0x1 || bar2 == 0) ? IOAddress(0x170) : IOAddress(bar2); - auto bar3 = PCI::get_BAR3(pci_address()); - control_io = (bar3 == 0x1 || bar3 == 0) ? IOAddress(0x376) : IOAddress(bar3); - if (force_pio) - m_channels.append(IDEChannel::create(*this, { base_io, control_io }, IDEChannel::ChannelType::Secondary)); - else - m_channels.append(BMIDEChannel::create(*this, { base_io, control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary)); + if (is_pci_native_mode_enabled_on_secondary_channel()) { + if (force_pio) + m_channels.append(IDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary)); + else + m_channels.append(BMIDEChannel::create(*this, irq_line, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary)); + } else { + if (force_pio) + m_channels.append(IDEChannel::create(*this, { secondary_base_io, secondary_control_io }, IDEChannel::ChannelType::Secondary)); + else + m_channels.append(BMIDEChannel::create(*this, { secondary_base_io, secondary_control_io, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary)); + } + m_channels[1].enable_irq(); } diff --git a/Kernel/Storage/IDEController.h b/Kernel/Storage/IDEController.h index e51aca5201..6cd9ed1a6b 100644 --- a/Kernel/Storage/IDEController.h +++ b/Kernel/Storage/IDEController.h @@ -53,8 +53,11 @@ public: virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; 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; IDEController(PCI::Address address, bool force_pio); RefPtr device_by_channel_and_position(u32 index) const;