1use bitfield::bitfield;
6use bitflags::bitflags;
7use std::num::NonZeroU16;
8
9pub const MMC_BLOCK_SIZE: u64 = 512;
11
12pub const EXT_CSD_SIZE: usize = 512;
15
16pub const EXT_CSD_BARRIER_EN: usize = 31;
17pub const EXT_CSD_BARRIER_ENABLED: u8 = 1;
18
19pub const EXT_CSD_FLUSH_CACHE: usize = 32;
20pub const EXT_CSD_FLUSH_CACHE_FLUSH: u8 = 0x1;
21pub const EXT_CSD_FLUSH_CACHE_BARRIER: u8 = 0x2;
22
23pub const EXT_CSD_CACHE_CTRL: usize = 33;
24pub const EXT_CSD_CACHE_EN_MASK: u8 = 1;
25
26pub const EXT_CSD_PARTITION_CONFIG: usize = 179;
27pub const EXT_CSD_PARTITION_ACCESS_MASK: u8 = 0xf8;
28
29pub const EXT_CSD_PARTITON_SWITCH_TIME: usize = 199;
30
31pub const EXT_CSD_SEC_FEATURE_SUPPORT: usize = 231;
32pub const EXT_CSD_SEC_FEATURE_SUPPORT_SEC_GB_CL_EN: u8 = 1 << 4;
33
34pub const EXT_CSD_CACHE_FLUSH_POLICY: usize = 240;
35pub const EXT_CSD_CACHE_FLUSH_POLICY_FIFO: u8 = 1;
36
37pub const EXT_CSD_GENERIC_CMD6_TIME: usize = 248;
38
39pub const EXT_CSD_BARRIER_SUPPORT: usize = 486;
40pub const EXT_CSD_BARRIER_SUPPORT_MASK: u8 = 0x1;
41
42#[derive(Clone, Copy, Debug, PartialEq, enumn::N)]
43#[repr(u8)]
44pub enum MmcCommand {
48 Switch = 6,
49 SendStatus = 13,
50 QueuedTaskParams = 44,
51 QueuedTaskAddress = 45,
52 CommandQueueTaskManagement = 48,
53}
54
55impl MmcCommand {
56 fn response_type(&self) -> DcmdResponseType {
57 match self {
58 Self::Switch => DcmdResponseType::R1B,
59 Self::SendStatus => DcmdResponseType::R1,
60 Self::QueuedTaskParams => DcmdResponseType::R1,
61 Self::QueuedTaskAddress => DcmdResponseType::R1,
62 Self::CommandQueueTaskManagement => DcmdResponseType::R1B,
63 }
64 }
65}
66
67impl From<MmcCommand> for u8 {
69 fn from(value: MmcCommand) -> Self {
70 value as u8
71 }
72}
73
74const DEVICE_MANAGEMENT_SEQUENCE: u8 = 0b10;
75
76#[derive(Clone, Copy, Debug, PartialEq, Eq, enumn::N)]
78#[repr(u8)]
79pub enum EmmcPartitionIndex {
80 UserDataPartition = 0,
81 BootPartition1 = 1,
82 BootPartition2 = 2,
83}
84
85impl From<EmmcPartitionIndex> for u8 {
87 fn from(value: EmmcPartitionIndex) -> Self {
88 value as u8
89 }
90}
91
92bitfield! {
93 #[derive(
94 Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
95 )]
96 pub struct DeviceManagementOpDiscardCmd44Args(u32);
98 impl Debug;
99 u16, num_blocks, set_num_blocks: 15, 0;
100 u8, task_id, set_task_id: 20, 16;
101 u8, dms, set_dms: 22, 21;
102 u8, from into EmmcPartitionIndex, _, set_partition: 28, 25;
104 }
106
107impl DeviceManagementOpDiscardCmd44Args {
108 pub fn new(num_blocks: u16, task_id: u8, partition: EmmcPartitionIndex) -> Self {
109 let mut this = Self(0);
110 this.set_num_blocks(num_blocks);
111 this.set_task_id(task_id);
112 this.set_dms(DEVICE_MANAGEMENT_SEQUENCE);
113 this.set_partition(partition);
114 this
115 }
116
117 pub fn raw(&self) -> u32 {
118 self.0
119 }
120}
121
122#[repr(u8)]
123#[derive(Clone, Copy, Debug, PartialEq, Eq, enumn::N)]
124pub enum DeviceManagementOpcode {
125 Discard = 8,
126}
127
128impl From<DeviceManagementOpcode> for u8 {
130 fn from(value: DeviceManagementOpcode) -> Self {
131 value as u8
132 }
133}
134
135const TM_OPCODE_DEVICE_MANAGEMENT_SEQUENCE: u8 = 2;
136
137bitfield! {
138 #[derive(
139 Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
140 )]
141 pub struct CommandQueueTaskManagementArgs(u32);
143 impl Debug;
144 u8, tm_opcode, set_tm_opcode: 4, 0;
146 u8, task_id, set_task_id: 20, 16;
147 u8, from into DeviceManagementOpcode, _, set_dm_opcode: 24, 21;
148 }
150
151impl CommandQueueTaskManagementArgs {
152 pub fn new(task_id: u8, operation: DeviceManagementOpcode) -> Self {
153 let mut this = Self(0);
154 this.set_tm_opcode(TM_OPCODE_DEVICE_MANAGEMENT_SEQUENCE);
155 this.set_task_id(task_id);
156 this.set_dm_opcode(operation);
157 this
158 }
159
160 pub fn raw(&self) -> u32 {
161 self.0
162 }
163}
164
165bitflags! {
166 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
167 pub struct MmcSendStatusResponse: u32 {
169 const STATUS_ERR = 1 << 19;
170 const CURRENT_STATE_STDBY = 0x3 << 9;
171 const CURRENT_STATE_TRAN = 0x4 << 9;
172 const CURRENT_STATE_DATA = 0x5 << 9;
173 const CURRENT_STATE_RECV = 0x6 << 9;
174 const CURRENT_STATE_SLP = 0xa << 9;
175 const READY_FOR_DATA = 1 << 8;
176 const SWITCH_ERR = 1 << 7;
177 const EXCEPTION_EVENT = 1 << 6;
178 const APP_CMD = 1 << 5;
179 }
180}
181
182#[derive(Clone, Copy, Debug, PartialEq, Eq)]
183pub enum Direction {
185 Read,
186 Write,
187}
188
189impl Direction {
190 pub const fn as_str(&self) -> &'static str {
191 match self {
192 Self::Read => "read",
193 Self::Write => "write",
194 }
195 }
196}
197
198const TASK_DESCRIPTOR_ACT: u8 = 0b101;
200
201bitfield! {
202 #[derive(
203 Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
204 )]
205 pub struct CommandQueueTaskDescriptor(u128);
207 impl Debug;
208 bool, valid, set_valid: 0;
209 bool, end, set_end: 1;
210 bool, int, set_int: 2;
211 u8, act, set_act: 5, 3;
212 bool, forced_programming, set_forced_programming: 6;
213 u8, context_id, set_context_id: 10, 7;
214 bool, tag_request, set_tag_request: 11;
215 bool, data_direction, set_data_direction: 12;
216 bool, priority, set_priority: 13;
217 bool, qbr, set_qbr: 14;
218 bool, reliable_write, set_reliable_write: 15;
219 u16, block_count, set_block_count: 31, 16;
220 u64, block_offset, set_block_offset: 95, 32;
221 }
223
224impl CommandQueueTaskDescriptor {
225 fn new(
226 direction: Direction,
227 block_offset: u64,
228 block_count: NonZeroU16,
229 queue_barrier: bool,
230 ) -> Self {
231 let mut this = Self(0);
232 this.set_valid(true);
233 this.set_end(true);
234 this.set_int(true);
235 this.set_act(TASK_DESCRIPTOR_ACT);
236 this.set_data_direction(direction == Direction::Read);
237 this.set_block_count(block_count.get());
238 this.set_block_offset(block_offset);
239 this.set_qbr(queue_barrier);
240 this
241 }
242}
243
244#[derive(Clone, Copy, Debug, PartialEq, Eq)]
245#[repr(u8)]
246pub enum DcmdResponseType {
247 NoResponse = 0b00,
249 R1 = 0b10,
251 R1B = 0b11,
253}
254
255impl From<DcmdResponseType> for u8 {
257 fn from(value: DcmdResponseType) -> Self {
258 value as u8
259 }
260}
261
262bitfield! {
263 #[derive(
264 Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
265 )]
266 pub struct CommandQueueDirectCmdTaskDescriptor(u128);
268 impl Debug;
269 pub bool, valid, set_valid: 0;
270 pub bool, end, set_end: 1;
271 pub bool, int, set_int: 2;
272 pub u8, act, set_act: 5, 3;
273 pub bool, qbr, set_qbr: 14;
274 pub u8, from into MmcCommand, _, set_cmd_index: 21, 16;
275 pub bool, cmd_timing, set_cmd_timing: 22;
276 pub u8, from into DcmdResponseType, _, set_response_type: 24, 23;
277 pub u32, cmd_arg, set_cmd_arg: 63, 32;
278}
279
280impl CommandQueueDirectCmdTaskDescriptor {
281 fn new(command: MmcCommand, command_arg: u32) -> Self {
282 let mut this = Self(0);
283 this.set_valid(true);
284 this.set_end(true);
285 this.set_act(TASK_DESCRIPTOR_ACT);
286 this.set_qbr(true);
287 this.set_int(true);
288 this.set_cmd_index(command);
289 let response_type = command.response_type();
290 this.set_response_type(response_type);
291 this.set_cmd_timing(response_type != DcmdResponseType::R1B);
294 this.set_cmd_arg(command_arg);
295 this
296 }
297}
298
299#[derive(Clone, Copy, Debug, PartialEq, Eq)]
300#[repr(transparent)]
301pub struct TransferBytes(u16);
305
306impl TransferBytes {
307 pub const MAX_BYTES: usize = u16::MAX as usize + 1;
309
310 pub const MAX_BLOCKS: u64 = Self::MAX_BYTES as u64 / MMC_BLOCK_SIZE;
312
313 pub const MAX: Self = Self(0);
314}
315
316impl From<TransferBytes> for u32 {
317 fn from(length: TransferBytes) -> u32 {
318 if length == TransferBytes::MAX { TransferBytes::MAX_BYTES as u32 } else { length.0 as u32 }
319 }
320}
321
322impl TryFrom<usize> for TransferBytes {
323 type Error = usize;
324
325 fn try_from(size: usize) -> Result<Self, Self::Error> {
326 if size == 0 {
327 Err(size)
328 } else if size < Self::MAX_BYTES {
329 debug_assert!(size <= u16::MAX as usize);
330 Ok(Self(size as u16))
331 } else if size == Self::MAX_BYTES {
332 Ok(Self::MAX)
333 } else {
334 Err(size)
335 }
336 }
337}
338
339#[derive(Clone, Copy, Debug, Eq, PartialEq)]
340#[repr(u8)]
341enum TransferAct {
342 Tran = 0b100,
344 Link = 0b110,
346}
347
348impl From<TransferAct> for u8 {
350 fn from(value: TransferAct) -> Self {
351 value as u8
352 }
353}
354
355bitfield! {
356 #[derive(
357 Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
358 )]
359 pub struct CommandQueueTransferDescriptor(u128);
361 impl Debug;
362 bool, valid, set_valid: 0;
363 bool, end, set_end: 1;
364 bool, int, set_int: 2;
365 u8, from into TransferAct, _, set_act: 5, 3;
366 u16, length, set_length: 31, 16;
368 u64, address, set_address: 95, 32;
369 }
371
372impl CommandQueueTransferDescriptor {
373 pub fn transfer(address: u64, length: TransferBytes, end: bool) -> Self {
375 let mut this = Self(0);
376 this.set_valid(true);
377 this.set_end(end);
378 this.set_int(false);
379 this.set_act(TransferAct::Tran);
380 this.set_length(length.0);
381 this.set_address(address);
382 this
383 }
384
385 pub fn link(address: u64) -> Self {
387 let mut this = Self(0);
388 this.set_valid(true);
389 this.set_end(false);
390 this.set_int(false);
391 this.set_act(TransferAct::Link);
392 this.set_address(address);
393 this
394 }
395}
396
397#[repr(C)]
398#[derive(
399 Debug, Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
400)]
401pub struct CommandQueueTDLEntry {
405 task: CommandQueueTaskDescriptor,
406 transfer: CommandQueueTransferDescriptor,
407}
408
409impl CommandQueueTDLEntry {
410 pub fn single_buffer(
416 direction: Direction,
417 block_offset: u64,
418 block_count: NonZeroU16,
419 phys_address: u64,
420 queue_barrier: bool,
421 ) -> Result<Self, ()> {
422 let length = TransferBytes::try_from(block_count.get() as usize * MMC_BLOCK_SIZE as usize)
425 .map_err(|_| ())?;
426 Ok(Self {
427 task: CommandQueueTaskDescriptor::new(
428 direction,
429 block_offset,
430 block_count,
431 queue_barrier,
432 ),
433 transfer: CommandQueueTransferDescriptor::transfer(phys_address, length, true),
434 })
435 }
436
437 pub fn scatter_gather_buffers(
442 direction: Direction,
443 block_offset: u64,
444 block_count: NonZeroU16,
445 descriptors_phys_address: u64,
446 queue_barrier: bool,
447 ) -> Self {
448 debug_assert!(
449 descriptors_phys_address
450 .is_multiple_of(std::mem::align_of::<CommandQueueTransferDescriptor>() as u64)
451 );
452 Self {
453 task: CommandQueueTaskDescriptor::new(
454 direction,
455 block_offset,
456 block_count,
457 queue_barrier,
458 ),
459 transfer: CommandQueueTransferDescriptor::link(descriptors_phys_address),
460 }
461 }
462}
463
464#[repr(C)]
465#[derive(
466 Debug, Clone, Copy, Eq, PartialEq, zerocopy::FromBytes, zerocopy::IntoBytes, zerocopy::Immutable,
467)]
468pub struct CommandQueueTDLDirectCmdEntry {
475 task: CommandQueueDirectCmdTaskDescriptor,
476 _transfer: u128,
477}
478
479impl CommandQueueTDLDirectCmdEntry {
480 pub fn new(command: MmcCommand, command_arg: u32) -> Self {
481 Self { task: CommandQueueDirectCmdTaskDescriptor::new(command, command_arg), _transfer: 0 }
482 }
483}
484
485pub const CQHCI_TASK_DESCRIPTOR_LIST_NUM_SLOTS: usize = 32;
486pub const CQHCI_TASK_DESCRIPTOR_LIST_DCMD_SLOT: u8 = 31;
487pub const CQHCI_TASK_DESCRIPTOR_LIST_SIZE: usize =
488 CQHCI_TASK_DESCRIPTOR_LIST_NUM_SLOTS * size_of::<CommandQueueTDLEntry>();
489
490pub const CQHCI_CQ_VER_OFFSET: usize = 0x0;
493pub const CQHCI_CQ_CAP_OFFSET: usize = 0x4;
494pub const CQHCI_CQ_CFG_OFFSET: usize = 0x8;
495pub const CQHCI_CQ_CTL_OFFSET: usize = 0xC;
496pub const CQHCI_CQ_IS_OFFSET: usize = 0x10;
497pub const CQHCI_CQ_ISTE_OFFSET: usize = 0x14;
498pub const CQHCI_CQ_ISGE_OFFSET: usize = 0x18;
499pub const CQHCI_CQ_IC_OFFSET: usize = 0x1c;
500pub const CQHCI_CQ_TDLBA_OFFSET: usize = 0x20;
501pub const CQHCI_CQ_TDLBAU_OFFSET: usize = 0x24;
502pub const CQHCI_CQ_TDBR_OFFSET: usize = 0x28;
503pub const CQHCI_CQ_TCN_OFFSET: usize = 0x2C;
504pub const CQHCI_CQ_DQS_OFFSET: usize = 0x30;
505pub const CQHCI_CQ_DPT_OFFSET: usize = 0x34;
506pub const CQHCI_CQ_TDPE_OFFSET: usize = 0x3C;
507pub const CQHCI_CQ_SSC1_OFFSET: usize = 0x40;
508pub const CQHCI_CQ_SSC2_OFFSET: usize = 0x44;
509pub const CQHCI_CQ_CRDCT_OFFSET: usize = 0x48;
510pub const CQHCI_CQ_RMEM_OFFSET: usize = 0x50;
511pub const CQHCI_CQ_TERRI_OFFSET: usize = 0x54;
512pub const CQHCI_CQ_CRI_OFFSET: usize = 0x58;
513pub const CQHCI_CQ_CRA_OFFSET: usize = 0x5C;
514pub const CQHCI_CQ_HCCAP_OFFSET: usize = 0x60;
515pub const CQHCI_CQ_HCCFG_OFFSET: usize = 0x64;
516pub const CQHCI_CQ_CRYPTO_NQP_OFFSET: usize = 0x70;
518pub const CQHCI_CQ_CRYPTO_NQDUN_OFFSET: usize = 0x74;
519pub const CQHCI_CQ_CRYPTO_NQIS_OFFSET: usize = 0x78;
520pub const CQHCI_CQ_CRYPTO_NQIE_OFFSET: usize = 0x7C;
521pub const CQHCI_CQ_CRYPTO_CAP_OFFSET: usize = 0x100;
522
523bitfield! {
524 #[derive(Clone, Copy)]
525 pub struct CqhciCqCapsRegister(u32);
526 impl Debug;
527 pub u16, timer_clock_freq, set_timer_clock_freq: 9, 0;
528 pub u8, timer_clock_freq_multiplier, set_timer_clock_freq_multiplier: 15, 12;
529 pub bool, crypto_support, set_crypto_support: 28;
530}
531
532bitflags! {
533 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
534 pub struct CqhciCqCfgRegister: u32 {
535 const DCMD_ENABLE = 1 << 12;
536 const TASK_DESC_128 = 1 << 8; const CRYPTO_ENABLE = 1 << 1;
538 const CQE_ENABLE = 1;
539 }
540}
541
542bitflags! {
543 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
544 pub struct CqhciCqCtlRegister: u32 {
545 const HALT = 1;
546 const HALT_ON_EMPTY_QUEUE = 1 << 1;
547 const CLEAR_ALL_TASKS = 1 << 8;
548 }
549}
550
551bitfield! {
552 #[derive(Clone, Copy)]
553 pub struct CqhciCqSendStatusConfiguration1Register(u32);
554 impl Debug;
555 pub u16, ssc_idle_timer, set_ssc_idle_timer: 15, 0;
556 pub u8, ssc_block_counter, set_ssc_block_counter: 19, 16;
557}
558
559bitfield! {
560 #[derive(Clone, Copy)]
561 pub struct CqhciCqSendStatusConfiguration2Register(u32);
562 impl Debug;
563 pub u16, rca, set_rca: 15, 0;
564}
565
566impl CqhciCqSendStatusConfiguration2Register {
567 pub fn from_rca(rca: u16) -> Self {
568 let mut this = Self(0);
569 this.set_rca(rca);
570 this
571 }
572
573 pub fn raw(&self) -> u32 {
574 self.0
575 }
576}
577
578bitfield! {
580 #[derive(Clone, Copy)]
581 pub struct CqhciCqInterruptStatusRegister(u32);
582 impl Debug;
583 pub bool, halt_complete, set_halt_complete: 0;
584 pub bool, task_complete, set_task_complete: 1;
585 pub bool, response_error_detected, set_response_error_detected: 2;
586 pub bool, task_cleared, set_task_cleared: 3;
587 pub bool, general_crypto_error, set_general_crypto_error: 4;
588 pub bool, invalid_crypto_config_error, set_invalid_crypto_config_error: 5;
589 pub bool, device_exception_event, set_device_exception_event: 6;
590 pub bool, host_controller_fatal_error, _: 7;
591}
592
593impl CqhciCqInterruptStatusRegister {
594 pub fn is_error(&self) -> bool {
595 self.response_error_detected()
596 || self.general_crypto_error()
597 || self.invalid_crypto_config_error()
598 || self.device_exception_event()
599 || self.host_controller_fatal_error()
600 }
601 pub fn raw(&self) -> u32 {
602 self.0
603 }
604 pub fn from_raw(value: u32) -> Self {
605 Self(value)
606 }
607}
608
609bitfield! {
610 #[derive(Clone, Copy)]
611 pub struct CqhciCqInterruptStatusEnableRegister(u32);
612 impl Debug;
613 pub bool, halt_complete, set_halt_complete: 0;
614 pub bool, task_complete, set_task_complete: 1;
615 pub bool, response_error_detected, set_response_error_detected: 2;
616 pub bool, task_cleared, set_task_cleared: 3;
617 pub bool, general_crypto_error, set_general_crypto_error: 4;
618 pub bool, invalid_crypto_config_error, set_invalid_crypto_config_error: 5;
619 pub bool, device_exception_event, set_device_exception_event: 6;
620 pub bool, host_controller_fatal_error, set_host_controller_fatal_error: 7;
621}
622
623impl CqhciCqInterruptStatusEnableRegister {
624 pub fn disabled() -> Self {
625 Self(0)
626 }
627 pub fn enabled() -> Self {
628 Self(0xff)
629 }
630 pub fn raw(&self) -> u32 {
631 self.0
632 }
633 pub fn from_raw(value: u32) -> Self {
634 Self(value)
635 }
636}
637
638bitfield! {
639 #[derive(Clone, Copy)]
640 pub struct CqhciCqInterruptSignalEnableRegister(u32);
641 impl Debug;
642 pub bool, halt_complete, set_halt_complete: 0;
643 pub bool, task_complete, set_task_complete: 1;
644 pub bool, response_error_detected, set_response_error_detected: 2;
645 pub bool, task_cleared, set_task_cleared: 3;
646 pub bool, general_crypto_error, set_general_crypto_error: 4;
647 pub bool, invalid_crypto_config_error, set_invalid_crypto_config_error: 5;
648 pub bool, device_exception_event, set_device_exception_event: 6;
649 pub bool, host_controller_fatal_error, set_host_controller_fatal_error: 7;
650}
651
652impl CqhciCqInterruptSignalEnableRegister {
653 pub fn disabled() -> Self {
654 Self(0)
655 }
656 pub fn enabled() -> Self {
657 Self(0xff)
658 }
659 pub fn raw(&self) -> u32 {
660 self.0
661 }
662 pub fn from_raw(value: u32) -> Self {
663 Self(value)
664 }
665}
666
667bitfield! {
668 #[derive(Clone, Copy)]
669 pub struct CqhciCqInterruptCoalescingRegister(u32);
670 impl Debug;
671 pub u8, ic_timeout_value, set_ic_timeout_value: 6, 0;
672 pub bool, ic_timeout_value_write_enable, set_ic_timeout_value_write_enable: 7;
673 pub u8, ic_counter_threshold, set_ic_counter_threshold: 12, 8;
674 pub bool, ic_counter_threshold_write_enable, set_ic_counter_threshold_write_enable: 15;
675 pub bool, ic_counter_timer_reset, set_ic_counter_timer_reset: 16;
676 pub bool, ic_status_bit, set_ic_status_bit: 20;
677 pub bool, ic_enable, set_ic_enable: 31;
678}
679
680impl CqhciCqInterruptCoalescingRegister {
681 pub fn disabled() -> Self {
682 let mut this = Self(0);
683 this.set_ic_enable(false);
684 this
685 }
686 pub fn raw(&self) -> u32 {
687 self.0
688 }
689}
690
691bitfield! {
692 #[derive(Clone, Copy)]
693 pub struct CqhciCqTaskErrorRegister(u32);
694 impl Debug;
695 pub u8, response_mode_error_command_index, set_response_mode_error_command_index: 5, 0;
696 pub u8, response_mode_error_task_id, set_response_mode_error_task_id: 12, 8;
697 pub bool, response_mode_error_fields_valid, set_response_mode_error_fields_valid: 15;
698 pub u8, data_transfer_error_command_index, set_data_transfer_error_command_index: 21, 16;
699 pub u8, data_transfer_error_task_id, set_data_transfer_error_task_id: 28, 24;
700 pub bool, data_transfer_error_fields_valid, set_data_transfer_error_fields_valid: 31;
701}
702
703pub const SDHCI_IS_OFFSET: usize = 0x30;
707pub const SDHCI_ISTE_OFFSET: usize = 0x34;
708pub const SDHCI_ISGE_OFFSET: usize = 0x38;
709
710bitfield! {
711 #[derive(Clone, Copy)]
712 pub struct SdhciInterruptStatusRegister(u32);
713 impl Debug;
714 pub bool, tuning_error, set_tuning_error: 26;
715 pub bool, adma_error, set_adma_error: 25;
716 pub bool, auto_cmd_error, set_auto_cmd_error: 24;
717 pub bool, current_limit_error, set_current_limit_error: 23;
718 pub bool, data_end_bit_error, set_data_end_bit_error: 22;
719 pub bool, data_crc_error, set_data_crc_error: 21;
720 pub bool, data_timeout_error, set_data_timeout_error: 20;
721 pub bool, command_index_error, set_command_index_error: 19;
722 pub bool, command_end_bit_error, set_command_end_bit_error: 18;
723 pub bool, command_crc_error, set_command_crc_error: 17;
724 pub bool, command_timeout_error, set_command_timeout_error: 16;
725 pub bool, error, set_error: 15;
726 pub bool, cqhci_interrupt, set_cqhci_interrupt: 14;
728 pub bool, card_interrupt, set_card_interrupt: 8;
729 pub bool, buffer_read_ready, set_buffer_read_ready: 5;
730 pub bool, buffer_write_ready, set_buffer_write_ready: 4;
731 pub bool, transfer_complete, set_transfer_complete: 1;
732 pub bool, command_complete, set_command_complete: 0;
733}
734
735impl SdhciInterruptStatusRegister {
736 pub fn take_cqhci_interrupt(&mut self) -> Self {
737 let mut cqhci = Self(0);
738 if self.cqhci_interrupt() {
739 cqhci.set_cqhci_interrupt(true);
740 self.set_cqhci_interrupt(false);
741 }
742 cqhci
743 }
744
745 pub fn is_empty(&self) -> bool {
746 self.raw() == 0
747 }
748
749 pub fn is_error(&self) -> bool {
750 self.tuning_error()
751 || self.adma_error()
752 || self.auto_cmd_error()
753 || self.current_limit_error()
754 || self.data_end_bit_error()
755 || self.data_crc_error()
756 || self.data_timeout_error()
757 || self.command_index_error()
758 || self.command_end_bit_error()
759 || self.command_crc_error()
760 || self.command_timeout_error()
761 || self.error()
762 }
763 pub fn from_raw(value: u32) -> Self {
764 Self(value)
765 }
766 pub fn raw(&self) -> u32 {
767 self.0
768 }
769}
770
771bitfield! {
772 #[derive(Clone, Copy)]
773 pub struct SdhciInterruptStatusEnableRegister(u32);
774 impl Debug;
775 pub bool, tuning_error, set_tuning_error: 26;
776 pub bool, adma_error, set_adma_error: 25;
777 pub bool, auto_cmd_error, set_auto_cmd_error: 24;
778 pub bool, current_limit_error, set_current_limit_error: 23;
779 pub bool, data_end_bit_error, set_data_end_bit_error: 22;
780 pub bool, data_crc_error, set_data_crc_error: 21;
781 pub bool, data_timeout_error, set_data_timeout_error: 20;
782 pub bool, command_index_error, set_command_index_error: 19;
783 pub bool, command_end_bit_error, set_command_end_bit_error: 18;
784 pub bool, command_crc_error, set_command_crc_error: 17;
785 pub bool, command_timeout_error, set_command_timeout_error: 16;
786 pub bool, error, set_error: 15;
787 pub bool, cqhci_interrupt, set_cqhci_interrupt: 14;
788 pub bool, card_interrupt, set_card_interrupt: 8;
789 pub bool, buffer_read_ready, set_buffer_read_ready: 5;
790 pub bool, buffer_write_ready, set_buffer_write_ready: 4;
791 pub bool, transfer_complete, set_transfer_complete: 1;
792 pub bool, command_complete, set_command_complete: 0;
793}
794
795impl SdhciInterruptStatusEnableRegister {
796 pub fn disabled() -> Self {
797 Self(0)
798 }
799 pub fn enabled() -> Self {
801 let mut this = Self::disabled();
802 this.enable_errors();
803 this.set_cqhci_interrupt(true);
804 this
805 }
806 pub fn errors_enabled() -> Self {
808 let mut this = Self::disabled();
809 this.enable_errors();
810 this
811 }
812 pub fn enable_errors(&mut self) {
813 self.set_tuning_error(true);
814 self.set_adma_error(true);
815 self.set_auto_cmd_error(true);
816 self.set_current_limit_error(true);
817 self.set_data_end_bit_error(true);
818 self.set_data_crc_error(true);
819 self.set_data_timeout_error(true);
820 self.set_command_index_error(true);
821 self.set_command_end_bit_error(true);
822 self.set_command_crc_error(true);
823 self.set_command_timeout_error(true);
824 self.set_error(true)
825 }
826 pub fn raw(&self) -> u32 {
827 self.0
828 }
829}
830
831bitfield! {
832 #[derive(Clone, Copy)]
833 pub struct SdhciInterruptSignalEnableRegister(u32);
834 impl Debug;
835 pub bool, tuning_error, set_tuning_error: 26;
836 pub bool, adma_error, set_adma_error: 25;
837 pub bool, auto_cmd_error, set_auto_cmd_error: 24;
838 pub bool, current_limit_error, set_current_limit_error: 23;
839 pub bool, data_end_bit_error, set_data_end_bit_error: 22;
840 pub bool, data_crc_error, set_data_crc_error: 21;
841 pub bool, data_timeout_error, set_data_timeout_error: 20;
842 pub bool, command_index_error, set_command_index_error: 19;
843 pub bool, command_end_bit_error, set_command_end_bit_error: 18;
844 pub bool, command_crc_error, set_command_crc_error: 17;
845 pub bool, command_timeout_error, set_command_timeout_error: 16;
846 pub bool, error, set_error: 15;
847 pub bool, cqhci_interrupt, set_cqhci_interrupt: 14;
848 pub bool, card_interrupt, set_card_interrupt: 8;
849 pub bool, buffer_read_ready, set_buffer_read_ready: 5;
850 pub bool, buffer_write_ready, set_buffer_write_ready: 4;
851 pub bool, transfer_complete, set_transfer_complete: 1;
852 pub bool, command_complete, set_command_complete: 0;
853}
854
855impl SdhciInterruptSignalEnableRegister {
856 pub fn disabled() -> Self {
857 Self(0)
858 }
859 pub fn enabled() -> Self {
861 let mut this = Self::disabled();
862 this.enable_errors();
863 this.set_cqhci_interrupt(true);
864 this
865 }
866 pub fn errors_enabled() -> Self {
868 let mut this = Self::disabled();
869 this.enable_errors();
870 this
871 }
872 pub fn enable_errors(&mut self) {
873 self.set_tuning_error(true);
874 self.set_adma_error(true);
875 self.set_auto_cmd_error(true);
876 self.set_current_limit_error(true);
877 self.set_data_end_bit_error(true);
878 self.set_data_crc_error(true);
879 self.set_data_timeout_error(true);
880 self.set_command_index_error(true);
881 self.set_command_end_bit_error(true);
882 self.set_command_crc_error(true);
883 self.set_command_timeout_error(true);
884 self.set_error(true)
885 }
886 pub fn raw(&self) -> u32 {
887 self.0
888 }
889}
890
891pub struct CqhciCryptoRegisterSnapshot {
893 pub crnqp: u32,
894 pub crnqdun: u32,
895 pub crnqis: u32,
896 pub crnqie: u32,
897 pub crcap: u32,
898}
899
900pub struct CqhciRegisterSnapshot {
902 pub ver: u32,
903 pub caps: u32,
904 pub cfg: u32,
905 pub ctl: u32,
906 pub is: u32,
907 pub iste: u32,
908 pub isge: u32,
909 pub tdlba: u32,
910 pub tdlbau: u32,
911 pub dbr: u32,
912 pub tcn: u32,
913 pub dqs: u32,
914 pub dpt: u32,
915 pub tdpe: u32,
916 pub ssc1: u32,
917 pub ssc2: u32,
918 pub rmem: u32,
919 pub terri: u32,
920 pub cri: u32,
921 pub cra: u32,
922 pub hccap: u32,
923 pub hccfg: u32,
924 pub crypto: Option<CqhciCryptoRegisterSnapshot>,
925}
926
927impl std::fmt::Debug for CqhciRegisterSnapshot {
928 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
929 writeln!(f, "CQHCI Registers: ")?;
930 writeln!(
931 f,
932 " ver {:08x} caps {:08x} cfg {:08x} ctl {:08x}",
933 self.ver, self.caps, self.cfg, self.ctl
934 )?;
935 writeln!(
936 f,
937 " is {:08x} iste {:08x} isge {:08x} tdlba {:08x}",
938 self.is, self.iste, self.isge, self.tdlba
939 )?;
940 writeln!(
941 f,
942 "tdlbau {:08x} dbr {:08x} tcn {:08x} dqs {:08x}",
943 self.tdlbau, self.dbr, self.tcn, self.dqs
944 )?;
945 writeln!(
946 f,
947 " dpt {:08x} tdpe {:08x} ssc1 {:08x} ssc2 {:08x}",
948 self.dpt, self.tdpe, self.ssc1, self.ssc2
949 )?;
950 writeln!(
951 f,
952 " rmem {:08x} terri {:08x} cri {:08x} cra {:08x}",
953 self.rmem, self.terri, self.cri, self.cra
954 )?;
955 write!(f, " hccap {:08x} hccfg {:08x}", self.hccap, self.hccfg)?;
956 if let Some(crypto) = &self.crypto {
957 writeln!(f)?;
958 writeln!(f, "CQHCI Crypto Registers: ")?;
959 writeln!(
960 f,
961 " crnqp {:08x}crnqdun {:08x}crnqis {:08x}crnqie {:08x}",
962 crypto.crnqp, crypto.crnqdun, crypto.crnqis, crypto.crnqie
963 )?;
964 write!(f, " crcap {:08x}", crypto.crcap)?;
965 }
966 Ok(())
967 }
968}