1pub use crate::common::*;
4
5use core::{fmt, str};
6
7#[derive(Clone, Copy, Default, Debug)]
9pub struct EMMC;
10
11impl OCR<EMMC> {
12 pub fn is_dual_voltage_card(&self) -> bool {
14 self.0 & 0x0000_0080 != 0
15 }
16 pub fn access_mode(&self) -> u8 {
21 (self.0 & 0x6000_0000 >> 29) as u8
22 }
23}
24impl fmt::Debug for OCR<EMMC> {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 f.debug_struct("OCR: Operation Conditions Register")
27 .field(
28 "Dual Voltage",
29 &if self.is_dual_voltage_card() {
30 "yes"
31 } else {
32 "no"
33 },
34 )
35 .field(
36 "Access mode",
37 &match self.access_mode() {
38 0b00 => "byte",
39 0b10 => "sector",
40 _ => "unknown",
41 },
42 )
43 .field("Busy", &self.is_busy())
44 .finish()
45 }
46}
47
48#[derive(Debug, Copy, Clone, Eq, PartialEq)]
50pub enum DeviceType {
51 RemovableDevice = 0b00,
52 BGA = 0b01,
53 POP = 0b10,
54 Unknown = 0b11,
55}
56
57impl CID<EMMC> {
58 pub fn device_type(&self) -> DeviceType {
60 match self.bytes[1] & 0x3 {
61 0b00 => DeviceType::RemovableDevice,
62 0b01 => DeviceType::BGA,
63 0b10 => DeviceType::POP,
64 _ => DeviceType::POP,
65 }
66 }
67
68 pub fn oem_application_id(&self) -> u8 {
72 self.bytes[2]
73 }
74
75 pub fn product_name(&self) -> &str {
77 str::from_utf8(&self.bytes[3..9]).unwrap_or(&"<ERR>")
78 }
79
80 pub fn product_revision(&self) -> (u8, u8) {
84 let major = (self.bytes[9] & 0xF0) >> 4;
85 let minor = self.bytes[9] & 0x0F;
86 (major, minor)
87 }
88
89 pub fn serial(&self) -> u32 {
91 (self.inner >> 16) as u32
92 }
93
94 pub fn manufacturing_date(&self) -> (u8, u8) {
99 let month = (self.inner >> 12) as u8 & 0xF;
100 let year = (self.inner >> 8) as u8 & 0xF;
101 (month, year)
102 }
103}
104impl fmt::Debug for CID<EMMC> {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.debug_struct("CID: Card Identification")
107 .field("Manufacturer ID", &self.manufacturer_id())
108 .field("Device Type", &self.device_type())
109 .field("OEM ID", &self.oem_application_id())
110 .field("Product Name", &self.product_name())
111 .field("Product Revision", &self.product_revision())
112 .field("Product Serial Number", &self.serial())
113 .field("Manufacturing Date", &self.manufacturing_date())
114 .finish()
115 }
116}
117
118impl CSD<EMMC> {
119 pub fn erase_size_blocks(&self) -> u32 {
124 let erase_grp_size = (self.0 >> 42) & 0x1F;
125 let erase_grp_mult = (self.0 >> 37) & 0x1F;
126
127 (erase_grp_size as u32 + 1) + (erase_grp_mult as u32 + 1)
128 }
129}
130impl fmt::Debug for CSD<EMMC> {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.debug_struct("CSD: Card Specific Data")
133 .field("Transfer Rate", &self.transfer_rate())
134 .field("Read I (@min VDD)", &self.read_current_minimum_vdd())
135 .field("Write I (@min VDD)", &self.write_current_minimum_vdd())
136 .field("Read I (@max VDD)", &self.read_current_maximum_vdd())
137 .field("Write I (@max VDD)", &self.write_current_maximum_vdd())
138 .field("Erase Size (Blocks)", &self.erase_size_blocks())
139 .finish()
140 }
141}
142
143impl CardStatus<EMMC> {
144 pub fn switch_error(&self) -> bool {
146 self.0 & 0x80 != 0
147 }
148 pub fn exception_event(&self) -> bool {
152 self.0 & 0x40 != 0
153 }
154}
155impl fmt::Debug for CardStatus<EMMC> {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 f.debug_struct("Card Status")
158 .field("Out of range error", &self.out_of_range())
159 .field("Address error", &self.address_error())
160 .field("Block len error", &self.block_len_error())
161 .field("Erase seq error", &self.erase_seq_error())
162 .field("Erase param error", &self.erase_param())
163 .field("Write protect error", &self.wp_violation())
164 .field("Card locked", &self.card_is_locked())
165 .field("Password lock unlock error", &self.lock_unlock_failed())
166 .field(
167 "Crc check for the previous command failed",
168 &self.com_crc_error(),
169 )
170 .field("Illegal command", &self.illegal_command())
171 .field("Card internal ecc failed", &self.card_ecc_failed())
172 .field("Internal card controller error", &self.cc_error())
173 .field("General Error", &self.error())
174 .field("Csd error", &self.csd_overwrite())
175 .field("Write protect error", &self.wp_erase_skip())
176 .field("Erase sequence cleared", &self.erase_reset())
177 .field("Card state", &self.state())
178 .field("Buffer empty", &self.ready_for_data())
179 .field("Switch error", &self.switch_error())
180 .field("Exception event", &self.exception_event())
181 .field("Card expects app cmd", &self.app_cmd())
182 .finish()
183 }
184}
185
186#[derive(Clone, Copy)]
190pub struct ExtCSD {
191 pub inner: [u32; 128],
192}
193impl Default for ExtCSD {
194 fn default() -> ExtCSD {
195 ExtCSD { inner: [0; 128] }
196 }
197}
198impl From<[u32; 128]> for ExtCSD {
200 fn from(inner: [u32; 128]) -> Self {
201 Self { inner }
202 }
203}
204impl ExtCSD {
205 pub fn boot_info(&self) -> u8 {
206 (self.inner[57] >> 24) as u8
208 }
209 pub fn sleep_awake_timeout(&self) -> u8 {
210 (self.inner[54] >> 16) as u8
212 }
213 pub fn sleep_notification_time(&self) -> u8 {
214 (self.inner[54] >> 24) as u8
216 }
217 pub fn sector_count(&self) -> u32 {
218 self.inner[53]
220 }
221 pub fn driver_strength(&self) -> u8 {
222 (self.inner[49] >> 16) as u8
224 }
225 pub fn card_type(&self) -> u8 {
226 (self.inner[49] >> 24) as u8
228 }
229 pub fn csd_structure_version(&self) -> u8 {
230 (self.inner[48] >> 8) as u8
232 }
233 pub fn extended_csd_revision(&self) -> u8 {
234 (self.inner[48] >> 24) as u8
236 }
237 pub fn data_sector_size(&self) -> u8 {
238 (self.inner[15] >> 16) as u8
240 }
241 pub fn secure_removal_type(&self) -> u8 {
242 (self.inner[4] >> 24) as u8
244 }
245}
246impl fmt::Debug for ExtCSD {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 f.debug_struct("Extended CSD")
249 .field("Boot Info", &self.boot_info())
250 .field("Sleep/Awake Timeout", &self.sleep_awake_timeout())
251 .field("Sleep Notification Time", &self.sleep_notification_time())
252 .field("Sector Count", &self.sector_count())
253 .field("Driver Strength", &self.driver_strength())
254 .field("Card Type", &self.card_type())
255 .field("CSD Structure Version", &self.csd_structure_version())
256 .field("Extended CSD Revision", &self.extended_csd_revision())
257 .field("Sector Size", &self.data_sector_size())
258 .field("Secure removal type", &self.secure_removal_type())
259 .finish()
260 }
261}
262
263impl From<u16> for RCA<EMMC> {
266 fn from(address: u16) -> Self {
267 Self::from((address as u32) << 16)
268 }
269}