/* * Copyright (c) 2023, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Kernel { class SDHostController : public StorageController { public: SDHostController(); ErrorOr initialize(); virtual ~SDHostController() = default; virtual LockRefPtr device(u32 index) const override { return index == 0 ? m_card : nullptr; } virtual ErrorOr reset() override; virtual ErrorOr shutdown() override; virtual size_t devices_count() const override { return m_card ? 1 : 0; } virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; ErrorOr read_block(Badge, u32 block_address, u32 block_count, UserOrKernelBuffer out); ErrorOr write_block(Badge, u32 block_address, u32 block_count, UserOrKernelBuffer in); void try_enable_dma(); protected: virtual SD::HostControlRegisterMap volatile* get_register_map_base_address() = 0; private: ErrorOr> try_initialize_inserted_card(); bool is_card_inserted() const { return m_registers->present_state.card_inserted; } SD::HostVersion host_version() { return m_registers->slot_interrupt_status_and_version.specification_version_number; } ErrorOr reset_host_controller(); SD::Command last_sent_command() { SD::Command command {}; command.raw = m_registers->transfer_mode_and_command; return command; } bool currently_active_command_uses_transfer_complete_interrupt(); ErrorOr calculate_sd_clock_divisor(u32 sd_clock_frequency, u32 frequency); bool is_sd_clock_enabled(); ErrorOr sd_clock_supply(u32 frequency); ErrorOr sd_clock_stop(); ErrorOr sd_clock_frequency_change(u32 frequency); ErrorOr retrieve_sd_clock_frequency(); struct Response { u32 response[4]; }; ErrorOr issue_command(SD::Command const&, u32 argument); ErrorOr wait_for_response(); bool card_status_contains_errors(SD::Command const&, u32); bool retry_with_timeout(Function, i64 delay_between_tries = 100); enum class DataTransferType { Read, Write }; enum class OperatingMode { PIO, ADMA2_32, ADMA2_64 }; ErrorOr transaction_control_with_data_transfer_using_the_dat_line_without_dma(SD::Command const&, u32 argument, u32 block_count, u32 block_size, UserOrKernelBuffer, DataTransferType data_transfer_type); ErrorOr transfer_blocks_adma2(u32 block_address, u32 block_count, UserOrKernelBuffer, SD::DataTransferDirection); ErrorOr retrieve_sd_configuration_register(u32 relative_card_address); u32 make_adma_descriptor_table(u32 block_count); volatile SD::HostControlRegisterMap* m_registers; LockRefPtr m_card { nullptr }; u32 m_hardware_relative_controller_id { 0 }; OperatingMode m_mode { OperatingMode::PIO }; Mutex m_lock { "SDHostController"sv }; // For ADMA2 // One page of descriptor tables with 16 bit lengths can address writes of // Up to 4 MiB ADMA2_32 // Up to 2 MiB ADMA2_64 // To not over allocate we use a buffer of just 16 pages // FIXME: Investigate the average usage and adjust this constexpr static size_t dma_rw_buffer_size = 16 * PAGE_SIZE; constexpr static size_t dma_region_size = PAGE_SIZE + dma_rw_buffer_size; OwnPtr m_dma_region; }; }