1pub use crate::common::*;
4
5#[derive(Clone, Copy, Default)]
7pub struct SD;
8
9use core::{fmt, str};
10
11#[non_exhaustive]
12#[derive(Debug, Copy, Clone, Eq, PartialEq)]
13pub enum SDSpecVersion {
14 V1_0,
16 V1_10,
18 V2,
20 V3,
22 V4,
24 V5,
26 V6,
28 V7,
30 Unknown,
32}
33
34#[derive(Clone, Copy, Default)]
36pub struct SCR(pub u64);
37impl From<[u32; 2]> for SCR {
39 fn from(words: [u32; 2]) -> Self {
40 Self(((words[1] as u64) << 32) | words[0] as u64)
41 }
42}
43impl SCR {
44 pub fn version(&self) -> SDSpecVersion {
46 let spec = (self.0 >> 56) & 0xF;
47 let spec3 = (self.0 >> 47) & 1;
48 let spec4 = (self.0 >> 42) & 1;
49 let specx = (self.0 >> 38) & 0xF;
50
51 match (spec, spec3, spec4, specx) {
53 (0, 0, 0, 0) => SDSpecVersion::V1_0,
54 (1, 0, 0, 0) => SDSpecVersion::V1_10,
55 (2, 0, 0, 0) => SDSpecVersion::V2,
56 (2, 1, 0, 0) => SDSpecVersion::V3,
57 (2, 1, 1, 0) => SDSpecVersion::V4,
58 (2, 1, _, 1) => SDSpecVersion::V5,
59 (2, 1, _, 2) => SDSpecVersion::V6,
60 (2, 1, _, 3) => SDSpecVersion::V7,
61 _ => SDSpecVersion::Unknown,
62 }
63 }
64 pub fn bus_widths(&self) -> u8 {
66 ((self.0 >> 48) as u8) & 0xF
68 }
69 pub fn bus_width_one(&self) -> bool {
71 (self.0 >> 48) & 1 != 0
72 }
73 pub fn bus_width_four(&self) -> bool {
75 (self.0 >> 50) & 1 != 0
76 }
77}
78impl core::fmt::Debug for SCR {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 f.debug_struct("SCR: SD CARD Configuration Register")
81 .field("Version", &self.version())
82 .field("1-bit width", &self.bus_width_one())
83 .field("4-bit width", &self.bus_width_four())
84 .finish()
85 }
86}
87
88impl OCR<SD> {
89 pub fn voltage_window_mv(&self) -> Option<(u16, u16)> {
95 let mut window = (self.0 >> 15) & 0x1FF;
96 let mut min = 2_700;
97
98 while window & 1 == 0 && window != 0 {
99 min += 100;
100 window >>= 1;
101 }
102 let mut max = min;
103 while window != 0 {
104 max += 100;
105 window >>= 1;
106 }
107
108 if max == min {
109 None
110 } else {
111 Some((min, max))
112 }
113 }
114 pub fn v18_allowed(&self) -> bool {
119 self.0 & 0x0100_0000 != 0
120 }
121 pub fn over_2tb(&self) -> bool {
126 self.0 & 0x0800_0000 != 0
127 }
128 pub fn uhs2_card_status(&self) -> bool {
133 self.0 & 0x2000_0000 != 0
134 }
135 pub fn high_capacity(&self) -> bool {
139 self.0 & 0x4000_0000 != 0
140 }
141}
142impl fmt::Debug for OCR<SD> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 f.debug_struct("OCR: Operation Conditions Register")
145 .field(
146 "Voltage Window (mV)",
147 &self.voltage_window_mv().unwrap_or((0, 0)),
148 )
149 .field("S18A (UHS-I only)", &self.v18_allowed())
150 .field("Over 2TB flag (SDUC only)", &self.over_2tb())
151 .field("UHS-II Card", &self.uhs2_card_status())
152 .field(
153 "Card Capacity Status (CSS)",
154 &if self.high_capacity() {
155 "SDHC/SDXC/SDUC"
156 } else {
157 "SDSC"
158 },
159 )
160 .field("Busy", &self.is_busy())
161 .finish()
162 }
163}
164
165impl CID<SD> {
166 pub fn oem_id(&self) -> &str {
168 str::from_utf8(&self.bytes[1..3]).unwrap_or(&"<ERR>")
169 }
170 pub fn product_name(&self) -> &str {
172 str::from_utf8(&self.bytes[3..8]).unwrap_or(&"<ERR>")
173 }
174 pub fn product_revision(&self) -> u8 {
176 self.bytes[8]
177 }
178 pub fn serial(&self) -> u32 {
180 (self.inner >> 24) as u32
181 }
182 pub fn manufacturing_date(&self) -> (u8, u16) {
184 (
185 (self.inner >> 8) as u8 & 0xF, ((self.inner >> 12) as u16 & 0xFF) + 2000, )
188 }
189}
190
191impl fmt::Debug for CID<SD> {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 f.debug_struct("CID: Card Identification")
194 .field("Manufacturer ID", &self.manufacturer_id())
195 .field("OEM ID", &self.oem_id())
196 .field("Product Name", &self.product_name())
197 .field("Product Revision", &self.product_revision())
198 .field("Product Serial Number", &self.serial())
199 .field("Manufacturing Date", &self.manufacturing_date())
200 .finish()
201 }
202}
203
204impl CSD<SD> {
205 pub fn block_count(&self) -> u64 {
207 match self.version() {
208 0 => {
209 let c_size: u16 = ((self.0 >> 62) as u16) & 0xFFF;
211 let c_size_mult: u8 = ((self.0 >> 47) as u8) & 7;
212
213 ((c_size + 1) as u64) * ((1 << (c_size_mult + 2)) as u64)
214 }
215 1 => {
216 (((self.0 >> 48) as u64 & 0x3F_FFFF) + 1) * 1024
218 }
219 2 => {
220 (((self.0 >> 48) as u64 & 0xFFF_FFFF) + 1) * 1024
222 }
223 _ => 0,
224 }
225 }
226 pub fn card_size(&self) -> u64 {
228 let block_size_bytes = 1 << self.block_length() as u64;
229
230 self.block_count() * block_size_bytes
231 }
232 pub fn erase_size_blocks(&self) -> u32 {
234 if (self.0 >> 46) & 1 == 1 {
235 1
237 } else {
238 let sector_size_tens = (self.0 >> 43) & 0x7;
239 let sector_size_units = (self.0 >> 39) & 0xF;
240
241 (sector_size_tens as u32 * 10) + (sector_size_units as u32)
242 }
243 }
244}
245
246impl fmt::Debug for CSD<SD> {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 f.debug_struct("CSD: Card Specific Data")
249 .field("Transfer Rate", &self.transfer_rate())
250 .field("Block Count", &self.block_count())
251 .field("Card Size (bytes)", &self.card_size())
252 .field("Read I (@min VDD)", &self.read_current_minimum_vdd())
253 .field("Write I (@min VDD)", &self.write_current_minimum_vdd())
254 .field("Read I (@max VDD)", &self.read_current_maximum_vdd())
255 .field("Write I (@max VDD)", &self.write_current_maximum_vdd())
256 .field("Erase Size (Blocks)", &self.erase_size_blocks())
257 .finish()
258 }
259}
260
261impl CardStatus<SD> {
262 pub fn ecc_disabled(&self) -> bool {
264 self.0 & 0x4000 != 0
265 }
266 pub fn fx_event(&self) -> bool {
268 self.0 & 0x40 != 0
269 }
270 pub fn ake_seq_error(&self) -> bool {
272 self.0 & 0x8 != 0
273 }
274}
275
276impl fmt::Debug for CardStatus<SD> {
277 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278 f.debug_struct("Card Status")
279 .field("Out of range error", &self.out_of_range())
280 .field("Address error", &self.address_error())
281 .field("Block len error", &self.block_len_error())
282 .field("Erase seq error", &self.erase_seq_error())
283 .field("Erase param error", &self.erase_param())
284 .field("Write protect error", &self.wp_violation())
285 .field("Card locked", &self.card_is_locked())
286 .field("Password lock unlock error", &self.lock_unlock_failed())
287 .field(
288 "Crc check for the previous command failed",
289 &self.com_crc_error(),
290 )
291 .field("Illegal command", &self.illegal_command())
292 .field("Card internal ecc failed", &self.card_ecc_failed())
293 .field("Internal card controller error", &self.cc_error())
294 .field("General Error", &self.error())
295 .field("Csd error", &self.csd_overwrite())
296 .field("Write protect error", &self.wp_erase_skip())
297 .field("Command ecc disabled", &self.ecc_disabled())
298 .field("Erase sequence cleared", &self.erase_reset())
299 .field("Card state", &self.state())
300 .field("Buffer empty", &self.ready_for_data())
301 .field("Extension event", &self.fx_event())
302 .field("Card expects app cmd", &self.app_cmd())
303 .field("Auth process error", &self.ake_seq_error())
304 .finish()
305 }
306}
307
308#[derive(Clone, Copy, Default)]
314pub struct SDStatus {
315 inner: [u32; 16],
316}
317impl From<[u32; 16]> for SDStatus {
319 fn from(inner: [u32; 16]) -> Self {
320 Self { inner }
321 }
322}
323impl SDStatus {
324 pub fn bus_width(&self) -> BusWidth {
326 match (self.inner[15] >> 30) & 3 {
327 0 => BusWidth::One,
328 2 => BusWidth::Four,
329 _ => BusWidth::Unknown,
330 }
331 }
332 pub fn secure_mode(&self) -> bool {
334 self.inner[15] & 0x2000_0000 != 0
335 }
336 pub fn sd_memory_card_type(&self) -> u16 {
338 self.inner[15] as u16
339 }
340 pub fn protected_area_size(&self) -> u32 {
342 self.inner[14]
343 }
344 pub fn speed_class(&self) -> u8 {
346 (self.inner[13] >> 24) as u8
347 }
348 pub fn move_performance(&self) -> u8 {
350 (self.inner[13] >> 16) as u8
351 }
352 pub fn allocation_unit_size(&self) -> u8 {
354 (self.inner[13] >> 12) as u8 & 0xF
355 }
356 pub fn erase_size(&self) -> u16 {
358 (self.inner[13] & 0xFF) as u16 | ((self.inner[12] >> 24) & 0xFF) as u16
359 }
360 pub fn erase_timeout(&self) -> u8 {
362 (self.inner[12] >> 18) as u8 & 0x3F
363 }
364 pub fn video_speed_class(&self) -> u8 {
366 (self.inner[11] & 0xFF) as u8
367 }
368 pub fn app_perf_class(&self) -> u8 {
370 (self.inner[9] >> 16) as u8 & 0xF
371 }
372 pub fn discard_support(&self) -> bool {
374 self.inner[8] & 0x0200_0000 != 0
375 }
376}
377impl fmt::Debug for SDStatus {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 f.debug_struct("SD Status")
380 .field("Bus Width", &self.bus_width())
381 .field("Secured Mode", &self.secure_mode())
382 .field("SD Memory Card Type", &self.sd_memory_card_type())
383 .field("Protected Area Size (B)", &self.protected_area_size())
384 .field("Speed Class", &self.speed_class())
385 .field("Video Speed Class", &self.video_speed_class())
386 .field("Application Performance Class", &self.app_perf_class())
387 .field("Move Performance (MB/s)", &self.move_performance())
388 .field("AU Size", &self.allocation_unit_size())
389 .field("Erase Size (units of AU)", &self.erase_size())
390 .field("Erase Timeout (s)", &self.erase_timeout())
391 .field("Discard Support", &self.discard_support())
392 .finish()
393 }
394}
395
396#[derive(Copy, Clone, Default)]
398pub struct CIC(u32);
399impl From<u32> for CIC {
400 fn from(word: u32) -> Self {
401 Self(word)
402 }
403}
404impl CIC {
405 pub fn voltage_accepted(&self) -> u8 {
407 (self.0 >> 8) as u8
408 }
409 pub fn pattern(&self) -> u8 {
411 self.0 as u8
412 }
413}
414
415impl RCA<SD> {
416 pub fn status(&self) -> u16 {
418 self.0 as u16
419 }
420}