134 lines
3.3 KiB
Rust
134 lines
3.3 KiB
Rust
|
use super::regs;
|
||
|
|
||
|
const APP_CMD_PREFIX: u8 = 0x80;
|
||
|
#[allow(unused)]
|
||
|
pub mod args {
|
||
|
pub const CMD8_VOL_PATTERN: u32 = 0x1AA;
|
||
|
pub const RESPOCR_READY: u32 = 0x80000000;
|
||
|
pub const ACMD41_HCS: u32 = 0x40000000;
|
||
|
pub const ACMD41_3V3: u32 = 0x00300000;
|
||
|
pub const CMD1_HIGH_VOL: u32 = 0x00FF8000;
|
||
|
pub const OCR_S18: u32 = 1 << 24;
|
||
|
}
|
||
|
|
||
|
#[allow(unused)]
|
||
|
#[repr(u8)]
|
||
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||
|
pub enum SdCmd {
|
||
|
CMD0 = 0x00,
|
||
|
CMD1 = 0x01,
|
||
|
CMD2 = 0x02,
|
||
|
CMD3 = 0x03,
|
||
|
CMD4 = 0x04,
|
||
|
CMD5 = 0x05,
|
||
|
CMD6 = 0x06,
|
||
|
ACMD6 = APP_CMD_PREFIX + 0x06,
|
||
|
CMD7 = 0x07,
|
||
|
CMD8 = 0x08,
|
||
|
CMD9 = 0x09,
|
||
|
CMD10 = 0x0A,
|
||
|
CMD11 = 0x0B,
|
||
|
CMD12 = 0x0C,
|
||
|
ACMD13 = APP_CMD_PREFIX + 0x0D,
|
||
|
CMD16 = 0x10,
|
||
|
CMD17 = 0x11,
|
||
|
CMD18 = 0x12,
|
||
|
CMD19 = 0x13,
|
||
|
CMD21 = 0x15,
|
||
|
CMD23 = 0x17,
|
||
|
ACMD23 = APP_CMD_PREFIX + 0x17,
|
||
|
CMD24 = 0x18,
|
||
|
CMD25 = 0x19,
|
||
|
CMD41 = 0x29,
|
||
|
ACMD41 = APP_CMD_PREFIX + 0x29,
|
||
|
ACMD42 = APP_CMD_PREFIX + 0x2A,
|
||
|
ACMD51 = APP_CMD_PREFIX + 0x33,
|
||
|
CMD52 = 0x34,
|
||
|
CMD55 = 0x37,
|
||
|
CMD58 = 0x3A,
|
||
|
}
|
||
|
|
||
|
pub fn require_dat(cmd: SdCmd, is_sd_card: bool) -> bool {
|
||
|
use SdCmd::*;
|
||
|
match cmd {
|
||
|
CMD6 => is_sd_card,
|
||
|
CMD8 => !is_sd_card,
|
||
|
ACMD13 | CMD17 | CMD18 | CMD19 | CMD21 | CMD23 | ACMD23 | CMD24 | CMD25 | ACMD51 => true,
|
||
|
_ => false,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type CmdReg = regs::transfer_mode_command::Write;
|
||
|
|
||
|
fn resp_r1(w: CmdReg) -> CmdReg {
|
||
|
w.response_type_select(regs::ResponseTypeSelect::Length48)
|
||
|
.crc_check_en(true)
|
||
|
.index_check_en(true)
|
||
|
}
|
||
|
|
||
|
fn resp_r1b(w: CmdReg) -> CmdReg {
|
||
|
w.response_type_select(regs::ResponseTypeSelect::Legnth48Check)
|
||
|
.crc_check_en(true)
|
||
|
.index_check_en(true)
|
||
|
}
|
||
|
|
||
|
fn resp_r2(w: CmdReg) -> CmdReg {
|
||
|
w.response_type_select(regs::ResponseTypeSelect::Length136)
|
||
|
.crc_check_en(true)
|
||
|
}
|
||
|
|
||
|
fn resp_r3(w: CmdReg) -> CmdReg {
|
||
|
w.response_type_select(regs::ResponseTypeSelect::Length48)
|
||
|
}
|
||
|
|
||
|
fn resp_r6(w: CmdReg) -> CmdReg {
|
||
|
w.response_type_select(regs::ResponseTypeSelect::Legnth48Check)
|
||
|
.crc_check_en(true)
|
||
|
.index_check_en(true)
|
||
|
}
|
||
|
|
||
|
pub fn set_cmd_reg(cmd: SdCmd, is_sd_card: bool, w: CmdReg) -> CmdReg {
|
||
|
use SdCmd::*;
|
||
|
let w = w.command_index(cmd as u8 & 0x3F);
|
||
|
match cmd {
|
||
|
CMD1 => resp_r3(w),
|
||
|
CMD2 => resp_r2(w),
|
||
|
CMD3 => {
|
||
|
if is_sd_card {
|
||
|
resp_r6(w)
|
||
|
} else {
|
||
|
resp_r1(w)
|
||
|
}
|
||
|
}
|
||
|
CMD5 => resp_r1b(w),
|
||
|
CMD6 => {
|
||
|
if is_sd_card {
|
||
|
resp_r1(w).data_present_select(true)
|
||
|
} else {
|
||
|
resp_r1b(w)
|
||
|
}
|
||
|
}
|
||
|
ACMD6 => resp_r1(w),
|
||
|
CMD7 => resp_r1(w),
|
||
|
CMD8 => {
|
||
|
if is_sd_card {
|
||
|
resp_r1(w)
|
||
|
} else {
|
||
|
resp_r1(w).data_present_select(true)
|
||
|
}
|
||
|
}
|
||
|
CMD9 => resp_r2(w),
|
||
|
CMD10 | CMD11 | CMD12 => resp_r1(w),
|
||
|
ACMD13 => resp_r1(w).data_present_select(true),
|
||
|
CMD16 => resp_r1(w),
|
||
|
CMD17 | CMD18 | CMD19 | CMD21 | CMD23 | ACMD23 | CMD24 | CMD25 => {
|
||
|
resp_r1(w).data_present_select(true)
|
||
|
}
|
||
|
ACMD41 => resp_r3(w),
|
||
|
ACMD42 => resp_r1(w),
|
||
|
ACMD51 => resp_r1(w).data_present_select(true),
|
||
|
CMD52 | CMD55 => resp_r1(w),
|
||
|
_ => w,
|
||
|
}
|
||
|
}
|