summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Storage/BMIDEChannel.cpp27
-rw-r--r--Kernel/Storage/IDEChannel.cpp12
-rw-r--r--Kernel/Storage/IDEChannel.h11
-rw-r--r--Kernel/Storage/IDEController.cpp12
-rw-r--r--Kernel/Storage/IDEController.h2
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);