1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:57:35 +00:00

Kernel: Propagate properly errors from PCI IDE Controller initialization

This commit is contained in:
Liav A 2022-12-16 11:17:30 +02:00 committed by Andrew Kaster
parent 735aa01b58
commit cf3b75e2e6
3 changed files with 44 additions and 42 deletions

View file

@ -15,21 +15,26 @@
namespace Kernel { namespace Kernel {
UNMAP_AFTER_INIT NonnullLockRefPtr<PCIIDELegacyModeController> PCIIDELegacyModeController::initialize(PCI::DeviceIdentifier const& device_identifier, bool force_pio) UNMAP_AFTER_INIT ErrorOr<NonnullLockRefPtr<PCIIDELegacyModeController>> PCIIDELegacyModeController::initialize(PCI::DeviceIdentifier const& device_identifier, bool force_pio)
{ {
return adopt_lock_ref(*new PCIIDELegacyModeController(device_identifier, force_pio)); auto controller = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) PCIIDELegacyModeController(device_identifier)));
PCI::enable_io_space(device_identifier.address());
PCI::enable_memory_space(device_identifier.address());
PCI::enable_bus_mastering(device_identifier.address());
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, bool force_pio) UNMAP_AFTER_INIT PCIIDELegacyModeController::PCIIDELegacyModeController(PCI::DeviceIdentifier const& device_identifier)
: PCI::Device(device_identifier.address()) : PCI::Device(device_identifier.address())
, m_prog_if(device_identifier.prog_if()) , m_prog_if(device_identifier.prog_if())
, m_interrupt_line(device_identifier.interrupt_line()) , m_interrupt_line(device_identifier.interrupt_line())
{ {
PCI::enable_io_space(device_identifier.address());
PCI::enable_memory_space(device_identifier.address());
PCI::enable_bus_mastering(device_identifier.address());
enable_pin_based_interrupts();
initialize(force_pio);
} }
bool PCIIDELegacyModeController::is_pci_native_mode_enabled() const bool PCIIDELegacyModeController::is_pci_native_mode_enabled() const
@ -77,7 +82,7 @@ static char const* detect_controller_type(u8 programming_value)
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
UNMAP_AFTER_INIT void PCIIDELegacyModeController::initialize(bool force_pio) UNMAP_AFTER_INIT ErrorOr<void> PCIIDELegacyModeController::initialize_and_enumerate_channels(bool force_pio)
{ {
dbgln("IDE controller @ {}: interrupt line was set to {}", pci_address(), m_interrupt_line.value()); dbgln("IDE controller @ {}: interrupt line was set to {}", pci_address(), m_interrupt_line.value());
dbgln("IDE controller @ {}: {}", pci_address(), detect_controller_type(m_prog_if.value())); dbgln("IDE controller @ {}: {}", pci_address(), detect_controller_type(m_prog_if.value()));
@ -86,17 +91,10 @@ UNMAP_AFTER_INIT void PCIIDELegacyModeController::initialize(bool force_pio)
dbgln("IDE controller @ {}: bus master base was set to {}", pci_address(), bus_master_base); dbgln("IDE controller @ {}: bus master base was set to {}", pci_address(), bus_master_base);
} }
auto initialize_and_enumerate = [&force_pio](IDEChannel& channel) -> void { auto initialize_and_enumerate = [&force_pio](IDEChannel& channel) -> ErrorOr<void> {
{ TRY(channel.allocate_resources_for_pci_ide_controller({}, force_pio));
auto result = channel.allocate_resources_for_pci_ide_controller({}, force_pio); TRY(channel.detect_connected_devices());
// FIXME: Propagate errors properly return {};
VERIFY(!result.is_error());
}
{
auto result = channel.detect_connected_devices();
// FIXME: Propagate errors properly
VERIFY(!result.is_error());
}
}; };
if (!is_bus_master_capable()) if (!is_bus_master_capable())
@ -105,14 +103,14 @@ UNMAP_AFTER_INIT void PCIIDELegacyModeController::initialize(bool force_pio)
OwnPtr<IOWindow> primary_base_io_window; OwnPtr<IOWindow> primary_base_io_window;
OwnPtr<IOWindow> primary_control_io_window; OwnPtr<IOWindow> primary_control_io_window;
if (!is_pci_native_mode_enabled_on_primary_channel()) { if (!is_pci_native_mode_enabled_on_primary_channel()) {
primary_base_io_window = IOWindow::create_for_io_space(IOAddress(0x1F0), 8).release_value_but_fixme_should_propagate_errors(); primary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x1F0), 8));
primary_control_io_window = IOWindow::create_for_io_space(IOAddress(0x3F6), 4).release_value_but_fixme_should_propagate_errors(); primary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x3F6), 4));
} else { } else {
auto primary_base_io_window = IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR0).release_value_but_fixme_should_propagate_errors(); auto primary_base_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR0));
auto pci_primary_control_io_window = IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR1).release_value_but_fixme_should_propagate_errors(); auto pci_primary_control_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR1));
// Note: the PCI IDE specification says we should access the IO address with an offset of 2 // Note: the PCI IDE specification says we should access the IO address with an offset of 2
// on native PCI IDE controllers. // on native PCI IDE controllers.
primary_control_io_window = pci_primary_control_io_window->create_from_io_window_with_offset(2, 4).release_value_but_fixme_should_propagate_errors(); 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_base_io_window);
@ -122,20 +120,20 @@ UNMAP_AFTER_INIT void PCIIDELegacyModeController::initialize(bool force_pio)
OwnPtr<IOWindow> secondary_control_io_window; OwnPtr<IOWindow> secondary_control_io_window;
if (!is_pci_native_mode_enabled_on_primary_channel()) { if (!is_pci_native_mode_enabled_on_primary_channel()) {
secondary_base_io_window = IOWindow::create_for_io_space(IOAddress(0x170), 8).release_value_but_fixme_should_propagate_errors(); secondary_base_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x170), 8));
secondary_control_io_window = IOWindow::create_for_io_space(IOAddress(0x376), 4).release_value_but_fixme_should_propagate_errors(); secondary_control_io_window = TRY(IOWindow::create_for_io_space(IOAddress(0x376), 4));
} else { } else {
secondary_base_io_window = IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR2).release_value_but_fixme_should_propagate_errors(); secondary_base_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR2));
auto pci_secondary_control_io_window = IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR3).release_value_but_fixme_should_propagate_errors(); auto pci_secondary_control_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR3));
// Note: the PCI IDE specification says we should access the IO address with an offset of 2 // Note: the PCI IDE specification says we should access the IO address with an offset of 2
// on native PCI IDE controllers. // on native PCI IDE controllers.
secondary_control_io_window = pci_secondary_control_io_window->create_from_io_window_with_offset(2, 4).release_value_but_fixme_should_propagate_errors(); 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_base_io_window);
VERIFY(secondary_control_io_window); VERIFY(secondary_control_io_window);
auto primary_bus_master_io = IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR4, 16).release_value_but_fixme_should_propagate_errors(); auto primary_bus_master_io = TRY(IOWindow::create_for_pci_device_bar(pci_address(), PCI::HeaderType0BaseRegister::BAR4, 16));
auto secondary_bus_master_io = primary_bus_master_io->create_from_io_window_with_offset(8).release_value_but_fixme_should_propagate_errors(); 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 // 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. // On QEMU for example, it should be "u8 irq_line = 22;" to actually work.
@ -149,20 +147,21 @@ UNMAP_AFTER_INIT void PCIIDELegacyModeController::initialize(bool force_pio)
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) }; 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()) { if (is_pci_native_mode_enabled_on_primary_channel()) {
m_channels.append(IDEChannel::create(*this, irq_line, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)); TRY(m_channels.try_append(IDEChannel::create(*this, irq_line, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)));
} else { } else {
m_channels.append(IDEChannel::create(*this, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)); TRY(m_channels.try_append(IDEChannel::create(*this, move(primary_channel_io_window_group), IDEChannel::ChannelType::Primary)));
} }
initialize_and_enumerate(m_channels[0]); TRY(initialize_and_enumerate(m_channels[0]));
m_channels[0].enable_irq(); m_channels[0].enable_irq();
if (is_pci_native_mode_enabled_on_secondary_channel()) { if (is_pci_native_mode_enabled_on_secondary_channel()) {
m_channels.append(IDEChannel::create(*this, irq_line, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)); TRY(m_channels.try_append(IDEChannel::create(*this, irq_line, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)));
} else { } else {
m_channels.append(IDEChannel::create(*this, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)); TRY(m_channels.try_append(IDEChannel::create(*this, move(secondary_channel_io_window_group), IDEChannel::ChannelType::Secondary)));
} }
initialize_and_enumerate(m_channels[1]); TRY(initialize_and_enumerate(m_channels[1]));
m_channels[1].enable_irq(); m_channels[1].enable_irq();
return {};
} }
} }

View file

@ -19,7 +19,7 @@ class AsyncBlockDeviceRequest;
class PCIIDELegacyModeController final : public IDEController class PCIIDELegacyModeController final : public IDEController
, public PCI::Device { , public PCI::Device {
public: public:
static NonnullLockRefPtr<PCIIDELegacyModeController> initialize(PCI::DeviceIdentifier const&, bool force_pio); static ErrorOr<NonnullLockRefPtr<PCIIDELegacyModeController>> initialize(PCI::DeviceIdentifier const&, bool force_pio);
bool is_bus_master_capable() const; bool is_bus_master_capable() const;
bool is_pci_native_mode_enabled() const; bool is_pci_native_mode_enabled() const;
@ -27,10 +27,10 @@ public:
private: private:
bool is_pci_native_mode_enabled_on_primary_channel() const; bool is_pci_native_mode_enabled_on_primary_channel() const;
bool is_pci_native_mode_enabled_on_secondary_channel() const; bool is_pci_native_mode_enabled_on_secondary_channel() const;
PCIIDELegacyModeController(PCI::DeviceIdentifier const&, bool force_pio); explicit PCIIDELegacyModeController(PCI::DeviceIdentifier const&);
LockRefPtr<StorageDevice> device_by_channel_and_position(u32 index) const; LockRefPtr<StorageDevice> device_by_channel_and_position(u32 index) const;
void initialize(bool force_pio); ErrorOr<void> initialize_and_enumerate_channels(bool force_pio);
// FIXME: Find a better way to get the ProgrammingInterface // FIXME: Find a better way to get the ProgrammingInterface
PCI::ProgrammingInterface m_prog_if; PCI::ProgrammingInterface m_prog_if;

View file

@ -105,7 +105,10 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_pci_controllers(bool force_pi
auto subclass_code = static_cast<SubclassID>(device_identifier.subclass_code().value()); auto subclass_code = static_cast<SubclassID>(device_identifier.subclass_code().value());
#if ARCH(X86_64) #if ARCH(X86_64)
if (subclass_code == SubclassID::IDEController && kernel_command_line().is_ide_enabled()) { if (subclass_code == SubclassID::IDEController && kernel_command_line().is_ide_enabled()) {
m_controllers.append(PCIIDELegacyModeController::initialize(device_identifier, force_pio)); 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) #elif ARCH(AARCH64)
(void)force_pio; (void)force_pio;