diff options
-rw-r--r-- | Kernel/Storage/BMIDEChannel.cpp | 27 | ||||
-rw-r--r-- | Kernel/Storage/IDEChannel.cpp | 12 | ||||
-rw-r--r-- | Kernel/Storage/IDEChannel.h | 11 | ||||
-rw-r--r-- | Kernel/Storage/IDEController.cpp | 12 | ||||
-rw-r--r-- | Kernel/Storage/IDEController.h | 2 |
5 files changed, 40 insertions, 24 deletions
diff --git a/Kernel/Storage/BMIDEChannel.cpp b/Kernel/Storage/BMIDEChannel.cpp index 0ee8c0d80e..0a74041e98 100644 --- a/Kernel/Storage/BMIDEChannel.cpp +++ b/Kernel/Storage/BMIDEChannel.cpp @@ -74,7 +74,8 @@ void BMIDEChannel::handle_irq(const RegisterState&) m_entropy_source.add_random_event(status); - u8 bstatus = m_io_group.bus_master_base().offset(2).in<u8>(); + VERIFY(m_io_group.bus_master_base().has_value()); + u8 bstatus = m_io_group.bus_master_base().value().offset(2).in<u8>(); if (!(bstatus & 0x4)) { // interrupt not from this device, ignore dbgln_if(PATA_DEBUG, "BMIDEChannel: ignore interrupt"); @@ -131,7 +132,8 @@ void BMIDEChannel::complete_current_request(AsyncDeviceRequest::RequestResult re } // I read somewhere that this may trigger a cache flush so let's do it. - m_io_group.bus_master_base().offset(2).out<u8>(m_io_group.bus_master_base().offset(2).in<u8>() | 0x6); + VERIFY(m_io_group.bus_master_base().has_value()); + m_io_group.bus_master_base().value().offset(2).out<u8>(m_io_group.bus_master_base().value().offset(2).in<u8>() | 0x6); } lock.unlock(); @@ -155,20 +157,20 @@ void BMIDEChannel::ata_write_sectors(bool slave_request, u16 capabilities) } VERIFY(prdt().size <= PAGE_SIZE); - + VERIFY(m_io_group.bus_master_base().has_value()); // Stop bus master - m_io_group.bus_master_base().out<u8>(0); + m_io_group.bus_master_base().value().out<u8>(0); // Write the PRDT location - m_io_group.bus_master_base().offset(4).out<u32>(m_prdt_page->paddr().get()); + m_io_group.bus_master_base().value().offset(4).out<u32>(m_prdt_page->paddr().get()); // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. - m_io_group.bus_master_base().offset(2).out<u8>(m_io_group.bus_master_base().offset(2).in<u8>() | 0x6); + m_io_group.bus_master_base().value().offset(2).out<u8>(m_io_group.bus_master_base().value().offset(2).in<u8>() | 0x6); ata_access(Direction::Write, slave_request, lba, request.block_count(), capabilities); // Start bus master - m_io_group.bus_master_base().out<u8>(0x1); + m_io_group.bus_master_base().value().out<u8>(0x1); } void BMIDEChannel::send_ata_io_command(LBAMode lba_mode, Direction direction) const @@ -192,22 +194,23 @@ void BMIDEChannel::ata_read_sectors(bool slave_request, u16 capabilities) VERIFY(prdt().size <= PAGE_SIZE); + VERIFY(m_io_group.bus_master_base().has_value()); // Stop bus master - m_io_group.bus_master_base().out<u8>(0); + m_io_group.bus_master_base().value().out<u8>(0); // Write the PRDT location - m_io_group.bus_master_base().offset(4).out(m_prdt_page->paddr().get()); + m_io_group.bus_master_base().value().offset(4).out(m_prdt_page->paddr().get()); // Turn on "Interrupt" and "Error" flag. The error flag should be cleared by hardware. - m_io_group.bus_master_base().offset(2).out<u8>(m_io_group.bus_master_base().offset(2).in<u8>() | 0x6); + m_io_group.bus_master_base().value().offset(2).out<u8>(m_io_group.bus_master_base().value().offset(2).in<u8>() | 0x6); // Set transfer direction - m_io_group.bus_master_base().out<u8>(0x8); + m_io_group.bus_master_base().value().out<u8>(0x8); ata_access(Direction::Read, slave_request, lba, request.block_count(), capabilities); // Start bus master - m_io_group.bus_master_base().out<u8>(0x9); + m_io_group.bus_master_base().value().out<u8>(0x9); } } diff --git a/Kernel/Storage/IDEChannel.cpp b/Kernel/Storage/IDEChannel.cpp index 1fc4b9e36c..0ddbb787ea 100644 --- a/Kernel/Storage/IDEChannel.cpp +++ b/Kernel/Storage/IDEChannel.cpp @@ -71,7 +71,10 @@ UNMAP_AFTER_INIT IDEChannel::IDEChannel(const IDEController& controller, IOAddre 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()); - dbgln_if(PATA_DEBUG, "IDEChannel: {} bus master base: {}", channel_type_string(), m_io_group.bus_master_base()); + if (m_io_group.bus_master_base().has_value()) + dbgln_if(PATA_DEBUG, "IDEChannel: {} bus master base: {}", channel_type_string(), m_io_group.bus_master_base().value()); + else + dbgln_if(PATA_DEBUG, "IDEChannel: {} bus master base disabled", channel_type_string()); m_parent_controller->enable_pin_based_interrupts(); detect_disks(); @@ -181,13 +184,6 @@ void IDEChannel::handle_irq(const RegisterState&) m_entropy_source.add_random_event(status); - u8 bstatus = m_io_group.bus_master_base().offset(2).in<u8>(); - if (!(bstatus & 0x4)) { - // interrupt not from this device, ignore - dbgln_if(PATA_DEBUG, "IDEChannel: ignore interrupt"); - return; - } - ScopedSpinLock lock(m_request_lock); dbgln_if(PATA_DEBUG, "IDEChannel: interrupt: DRQ={}, BSY={}, DRDY={}", (status & ATA_SR_DRQ) != 0, diff --git a/Kernel/Storage/IDEChannel.h b/Kernel/Storage/IDEChannel.h index 192c149a80..7651df4bba 100644 --- a/Kernel/Storage/IDEChannel.h +++ b/Kernel/Storage/IDEChannel.h @@ -72,6 +72,13 @@ public: { } + IOAddressGroup(IOAddress io_base, IOAddress control_base) + : m_io_base(io_base) + , m_control_base(control_base) + , m_bus_master_base() + { + } + // Disable default implementations that would use surprising integer promotion. bool operator==(const IOAddressGroup&) const = delete; bool operator<=(const IOAddressGroup&) const = delete; @@ -81,7 +88,7 @@ public: IOAddress io_base() const { return m_io_base; }; IOAddress control_base() const { return m_control_base; } - IOAddress bus_master_base() const { return m_bus_master_base; } + Optional<IOAddress> bus_master_base() const { return m_bus_master_base; } const IOAddressGroup& operator=(const IOAddressGroup& group) { @@ -94,7 +101,7 @@ public: private: IOAddress m_io_base; IOAddress m_control_base; - IOAddress m_bus_master_base; + Optional<IOAddress> m_bus_master_base; }; public: diff --git a/Kernel/Storage/IDEController.cpp b/Kernel/Storage/IDEController.cpp index 56a83b2f5c..ad81ae144b 100644 --- a/Kernel/Storage/IDEController.cpp +++ b/Kernel/Storage/IDEController.cpp @@ -80,6 +80,11 @@ UNMAP_AFTER_INIT IDEController::~IDEController() { } +bool IDEController::is_bus_master_capable() const +{ + return PCI::get_programming_interface(pci_address()) & (1 << 7); +} + UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio) { auto bus_master_base = IOAddress(PCI::get_BAR4(pci_address()) & (~1)); @@ -89,8 +94,11 @@ UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio) 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, bus_master_base }, IDEChannel::ChannelType::Primary)); + 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(); @@ -100,7 +108,7 @@ UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio) 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, bus_master_base.offset(8) }, IDEChannel::ChannelType::Secondary)); + 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)); m_channels[1].enable_irq(); diff --git a/Kernel/Storage/IDEController.h b/Kernel/Storage/IDEController.h index aff37f1bd9..3a2ac39bac 100644 --- a/Kernel/Storage/IDEController.h +++ b/Kernel/Storage/IDEController.h @@ -53,6 +53,8 @@ public: virtual void start_request(const StorageDevice&, AsyncBlockDeviceRequest&) override; virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; + bool is_bus_master_capable() const; + private: IDEController(PCI::Address address, bool force_pio); |