diff options
author | Liav A <liavalb@gmail.com> | 2021-03-27 21:44:25 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-03 11:57:23 +0200 |
commit | 2718d7c74cc7a3c5b125fe1ec89ab189547b1dd8 (patch) | |
tree | a54189ad2a63e3df708cb34d975245170248d194 | |
parent | 627cfe017c34ccd08a4a047a5548703b66d447cd (diff) | |
download | serenity-2718d7c74cc7a3c5b125fe1ec89ab189547b1dd8.zip |
Kernel/Storage: Add support for IDE controllers in PCI native mode
Also handle native and compatibility channel modes together, so if only
one IDE channel was set to work on PCI native mode, we need to handle it
separately, so the other channel continue to operate with the legacy IO
ports and interrupt line.
-rw-r--r-- | Kernel/Storage/BMIDEChannel.cpp | 11 | ||||
-rw-r--r-- | Kernel/Storage/BMIDEChannel.h | 2 | ||||
-rw-r--r-- | Kernel/Storage/IDEChannel.cpp | 32 | ||||
-rw-r--r-- | Kernel/Storage/IDEChannel.h | 3 | ||||
-rw-r--r-- | Kernel/Storage/IDEController.cpp | 68 | ||||
-rw-r--r-- | Kernel/Storage/IDEController.h | 3 |
6 files changed, 95 insertions, 24 deletions
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> BMIDEChannel::create(const IDEContr return adopt(*new BMIDEChannel(ide_controller, io_group, type)); } +UNMAP_AFTER_INIT NonnullRefPtr<BMIDEChannel> 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<BMIDEChannel> create(const IDEController&, IDEChannel::IOAddressGroup, IDEChannel::ChannelType type); + static NonnullRefPtr<BMIDEChannel> 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> IDEChannel::create(const IDEControlle return adopt(*new IDEChannel(controller, io_group, type)); } +UNMAP_AFTER_INIT NonnullRefPtr<IDEChannel> IDEChannel::create(const IDEController& controller, u8 irq, IOAddressGroup io_group, ChannelType type) +{ + return adopt(*new IDEChannel(controller, irq, io_group, type)); +} + RefPtr<StorageDevice> IDEChannel::master_device() const { return m_master; @@ -59,16 +64,9 @@ RefPtr<StorageDevice> 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<u8>(); 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<IDEChannel> create(const IDEController&, IOAddressGroup, ChannelType type); + static NonnullRefPtr<IDEChannel> create(const IDEController&, u8 irq, IOAddressGroup, ChannelType type); virtual ~IDEChannel() override; RefPtr<StorageDevice> 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<u8>() >> 5) & 0b11)); dbgln("IDE controller @ {}: secondary channel DMA capable? {}", pci_address(), ((bus_master_base.offset(2 + 8).in<u8>() >> 5) & 0b11)); + if (!is_bus_master_capable()) + force_pio = true; + auto bar0 = PCI::get_BAR0(pci_address()); - auto base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0); + auto primary_base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0 & (~1)); auto bar1 = PCI::get_BAR1(pci_address()); - auto control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1); + 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)); - if (!is_bus_master_capable()) - force_pio = true; + 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)); + } - 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)); 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<StorageDevice> device_by_channel_and_position(u32 index) const; |