1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:54:58 +00:00
serenity/Kernel/Devices/Storage/SD/Commands.h
Nico Weber 4409b33145 AK: Make IndexSequence use size_t
This makes it possible to use MakeIndexSequqnce in functions like:

    template<typename T, size_t N>
    constexpr auto foo(T (&a)[N])

This means AK/StdLibExtraDetails.h must now include AK/Types.h
for size_t, which means AK/Types.h can no longer include
AK/StdLibExtras.h (which arguably it shouldn't do anyways),
which requires rejiggering some things.

(IMHO Types.h shouldn't use AK::Details metaprogramming at all.
FlatPtr doesn't necessarily have to use Conditional<> and ssize_t could
maybe be in its own header or something. But since it's tangential to
this PR, going with the tried and true "lift things that cause the
cycle up to the top" approach.)
2024-02-11 18:53:00 +01:00

405 lines
10 KiB
C++

/*
* Copyright (c) 2023, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/StdLibExtras.h>
#include <AK/Types.h>
namespace Kernel::SD {
// Relevant Specifications:
// * (SDHC): SD Host Controller Simplified Specification (https://www.sdcard.org/downloads/pls/)
// * (PLSS) Physical Layer Simplified Specification (https://www.sdcard.org/downloads/pls/)
// PLSS 4.7.4: "Detailed Command Description"
enum class CommandIndex : u8 {
GoIdleState = 0,
AllSendCid = 2,
SendRelativeAddr = 3,
AppSetBusWidth = 6,
SelectCard = 7,
SendIfCond = 8,
SendCsd = 9,
GoInactiveState = 15,
SetBlockLen = 16,
ReadSingleBlock = 17,
ReadMultipleBlock = 18,
WriteSingleBlock = 24,
WriteMultipleBlock = 25,
AppSendOpCond = 41,
AppSendScr = 51,
AppCmd = 55,
};
enum class CommandType : u8 {
Normal,
Suspend,
Resume,
Abort
};
enum class ResponseType : u8 {
NoResponse,
ResponseOf136Bits,
ResponseOf48Bits,
ResponseOf48BitsWithBusy
};
enum class DataTransferDirection : u8 {
HostToCard,
CardToHost
};
enum class SendAutoCommand : u8 {
Disabled,
Command12,
Command23
};
// SDHC 2.2.5 & 2.2.6: "Transfer Mode Register" & "Command Register"
union Command {
u32 raw;
struct {
u32 dma_enable : 1;
u32 block_counter : 1;
SendAutoCommand auto_command : 2;
DataTransferDirection direction : 1;
u32 multiblock : 1;
u32 response_type_r1r5 : 1; // v4.10
u32 response_error_check : 1; // v4.10
u32 response_interrupt_disable : 1; // v4.10
u32 reserved1 : 7;
ResponseType response_type : 2;
u32 sub_command_flag : 1; // v4.10
u32 crc_enable : 1;
u32 idx_enable : 1;
u32 is_data : 1;
CommandType type : 2;
CommandIndex index : 6;
u32 reserved3 : 2;
};
bool requires_dat_line() const
{
return is_data;
}
bool uses_transfer_complete_interrupt() const
{
// FIXME: I don't know how to determine this.
return false;
}
};
static_assert(AssertSize<Command, 4>());
namespace Commands {
constexpr Command go_idle_state = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::NoResponse,
.sub_command_flag = 0,
.crc_enable = 0,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::GoIdleState,
.reserved3 = 0
};
constexpr Command all_send_cid = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf136Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::AllSendCid,
.reserved3 = 0
};
constexpr Command send_relative_addr = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::SendRelativeAddr,
.reserved3 = 0
};
constexpr Command app_set_bus_width = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::AppSetBusWidth,
.reserved3 = 0
};
constexpr Command select_card = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48BitsWithBusy,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::SelectCard,
.reserved3 = 0
};
constexpr Command send_if_cond = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::SendIfCond,
.reserved3 = 0
};
constexpr Command send_csd = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf136Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::SendCsd,
.reserved3 = 0
};
constexpr Command set_block_len = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 0,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::SetBlockLen,
.reserved3 = 0
};
constexpr Command read_single_block = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::CardToHost,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 1,
.type = CommandType::Normal,
.index = CommandIndex::ReadSingleBlock,
.reserved3 = 0
};
constexpr Command read_multiple_block = {
.dma_enable = 0,
.block_counter = 1,
.auto_command = SendAutoCommand::Command12,
.direction = DataTransferDirection::CardToHost,
.multiblock = 1,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 1,
.type = CommandType::Normal,
.index = CommandIndex::ReadMultipleBlock,
.reserved3 = 0
};
constexpr Command write_single_block = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 1,
.type = CommandType::Normal,
.index = CommandIndex::WriteSingleBlock,
.reserved3 = 0
};
constexpr Command write_multiple_block = {
.dma_enable = 0,
.block_counter = 1,
.auto_command = SendAutoCommand::Command12,
.direction = DataTransferDirection::HostToCard,
.multiblock = 1,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 1,
.type = CommandType::Normal,
.index = CommandIndex::WriteMultipleBlock,
.reserved3 = 0
};
constexpr Command app_send_op_cond = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 0,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::AppSendOpCond,
.reserved3 = 0
};
constexpr Command app_send_scr = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::CardToHost,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 0,
.idx_enable = 0,
.is_data = 1,
.type = CommandType::Normal,
.index = CommandIndex::AppSendScr,
.reserved3 = 0
};
constexpr Command app_cmd = {
.dma_enable = 0,
.block_counter = 0,
.auto_command = SendAutoCommand::Disabled,
.direction = DataTransferDirection::HostToCard,
.multiblock = 0,
.response_type_r1r5 = 0,
.response_error_check = 0,
.response_interrupt_disable = 0,
.reserved1 = 0,
.response_type = ResponseType::ResponseOf48Bits,
.sub_command_flag = 0,
.crc_enable = 1,
.idx_enable = 0,
.is_data = 0,
.type = CommandType::Normal,
.index = CommandIndex::AppCmd,
.reserved3 = 0
};
}
}