/* * Copyright (c) 2018-2020, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ // // Parallel ATA (PATA) controller driver // // This driver describes a logical PATA Channel. Each channel can connect up to 2 // IDE Hard Disk Drives. The drives themselves can be either the master drive (hd0) // or the slave drive (hd1). // // More information about the ATA spec for PATA can be found here: // ftp://ftp.seagate.com/acrobat/reference/111-1c.pdf // #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { class AsyncBlockDeviceRequest; class IDEController; class PCIIDEController; class ISAIDEController; class IDEChannel : public ATAPort , public IRQHandler { friend class IDEController; public: enum class ChannelType : u8 { Primary, Secondary }; enum class DeviceType : u8 { Master, Slave, }; struct IOAddressGroup { IOAddressGroup(IOAddress io_base, IOAddress control_base, IOAddress bus_master_base) : m_io_base(io_base) , m_control_base(control_base) , m_bus_master_base(bus_master_base) { } IOAddressGroup(IOAddress io_base, IOAddress control_base, Optional bus_master_base) : m_io_base(io_base) , m_control_base(control_base) , m_bus_master_base(bus_master_base) { } IOAddressGroup(IOAddress io_base, IOAddress control_base) : m_io_base(io_base) , m_control_base(control_base) , m_bus_master_base() { } IOAddressGroup(IOAddressGroup const& other, IOAddress bus_master_base) : m_io_base(other.io_base()) , m_control_base(other.control_base()) , m_bus_master_base(bus_master_base) { } IOAddressGroup(IOAddressGroup const&) = default; // Disable default implementations that would use surprising integer promotion. bool operator==(IOAddressGroup const&) const = delete; bool operator<=(IOAddressGroup const&) const = delete; bool operator>=(IOAddressGroup const&) const = delete; bool operator<(IOAddressGroup const&) const = delete; bool operator>(IOAddressGroup const&) const = delete; IOAddress io_base() const { return m_io_base; }; IOAddress control_base() const { return m_control_base; } Optional bus_master_base() const { return m_bus_master_base; } private: IOAddress m_io_base; IOAddress m_control_base; Optional m_bus_master_base; }; public: static NonnullRefPtr create(IDEController const&, IOAddressGroup, ChannelType type); static NonnullRefPtr create(IDEController const&, u8 irq, IOAddressGroup, ChannelType type); virtual ~IDEChannel() override; virtual StringView purpose() const override { return "PATA Channel"sv; } ErrorOr allocate_resources_for_pci_ide_controller(Badge, bool force_pio); ErrorOr allocate_resources_for_isa_ide_controller(Badge); private: static constexpr size_t m_logical_sector_size = 512; ErrorOr allocate_resources(bool force_pio); StringView channel_type_string() const; virtual ErrorOr disable() override { TODO(); } virtual ErrorOr power_on() override { TODO(); } virtual ErrorOr port_phy_reset() override; bool select_device_and_wait_until_not_busy(DeviceType, size_t milliseconds_timeout); virtual bool pio_capable() const override { return true; } virtual bool dma_capable() const override { return m_dma_enabled; } virtual size_t max_possible_devices_connected() const override { return 2; } virtual ErrorOr stop_busmastering() override; virtual ErrorOr start_busmastering(TransactionDirection) override; virtual ErrorOr force_busmastering_status_clean() override; virtual ErrorOr busmastering_status() override; virtual ErrorOr prepare_transaction_with_busmastering(TransactionDirection, PhysicalAddress prdt_buffer) override; virtual ErrorOr initiate_transaction(TransactionDirection) override; virtual ErrorOr task_file_status() override; virtual ErrorOr task_file_error() override; virtual ErrorOr wait_if_busy_until_timeout(size_t timeout_in_milliseconds) override; virtual ErrorOr device_select(size_t device_index) override; virtual ErrorOr detect_presence_on_selected_device() override; virtual ErrorOr enable_interrupts() override; virtual ErrorOr disable_interrupts() override; virtual ErrorOr force_clear_interrupts() override; virtual ErrorOr load_taskfile_into_registers(TaskFile const&, LBAMode lba_mode, size_t completion_timeout_in_milliseconds) override; virtual ErrorOr read_pio_data_to_buffer(UserOrKernelBuffer&, size_t block_offset, size_t words_count) override; virtual ErrorOr write_pio_data_from_buffer(UserOrKernelBuffer const&, size_t block_offset, size_t words_count) override; IDEChannel(IDEController const&, IOAddressGroup, ChannelType type, NonnullOwnPtr ata_identify_data_buffer); IDEChannel(IDEController const&, u8 irq, IOAddressGroup, ChannelType type, NonnullOwnPtr ata_identify_data_buffer); //^ IRQHandler virtual bool handle_irq(RegisterState const&) override; // Data members ChannelType m_channel_type { ChannelType::Primary }; bool m_dma_enabled { false }; bool m_interrupts_enabled { true }; IOAddressGroup m_io_group; }; }