mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 01:52:43 +00:00 
			
		
		
		
	 500b7b08d6
			
		
	
	
		500b7b08d6
		
	
	
	
	
		
			
			The Storage subsystem, like the Audio and HID subsystems, exposes Unix device files (for example, in the /dev directory). To ensure consistency across the repository, we should make the Storage subsystem to reside in the Kernel/Devices directory like the two other mentioned subsystems.
		
			
				
	
	
		
			404 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			404 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2023, the SerenityOS developers.
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #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
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| }
 |