Skip to main content

sdmmc_protocol/
block.rs

1//! Block request state shared by SD/MMC host controller backends.
2//!
3//! The protocol crate intentionally does not know about `rd-block` or any
4//! executor. These types describe the portable queue contract that host
5//! drivers expose upward: submit one block transfer, advance it by polling or
6//! IRQ wakeups, and keep the concrete FIFO/DMA engine visible.
7
8use core::num::NonZeroUsize;
9
10/// Stable identifier returned by a host block queue after submission.
11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct BlockRequestId(usize);
13
14impl BlockRequestId {
15    pub const fn new(id: usize) -> Self {
16        Self(id)
17    }
18}
19
20impl From<BlockRequestId> for usize {
21    fn from(value: BlockRequestId) -> Self {
22        value.0
23    }
24}
25
26/// Data engine used by an in-flight block request.
27///
28/// Marked `#[non_exhaustive]`: new engines (e.g. SDMA, ADMA3) may be added
29/// before 1.0.
30#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31#[non_exhaustive]
32pub enum BlockTransferMode {
33    /// Controller FIFO/data-port engine.
34    Fifo,
35    /// Host-controller DMA engine (SDHCI ADMA2, DW_mshc IDMAC, etc.).
36    Dma,
37}
38
39/// Buffer and address constraints exposed by a host block queue.
40#[derive(Clone, Copy, Debug, PartialEq, Eq)]
41pub struct BlockBufferConfig {
42    /// Logical block size accepted by the queue.
43    pub block_size: NonZeroUsize,
44    /// Required CPU-buffer alignment in bytes.
45    pub align: usize,
46    /// Device-visible DMA address mask, when the queue uses DMA.
47    pub dma_mask: Option<u64>,
48}
49
50impl BlockBufferConfig {
51    pub const fn new(block_size: NonZeroUsize, align: usize, dma_mask: Option<u64>) -> Self {
52        Self {
53            block_size,
54            align,
55            dma_mask,
56        }
57    }
58}
59
60/// Direction of a block request.
61///
62/// Marked `#[non_exhaustive]` for forward compatibility (future variants like
63/// `Erase` may join the queue contract).
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
65#[non_exhaustive]
66pub enum BlockTransferDirection {
67    Read,
68    Write,
69}
70
71/// Observable state of one host block-transfer state machine.
72///
73/// Marked `#[non_exhaustive]`: queue-level intermediate states (e.g. tuning,
74/// drain) may be added before 1.0; downstream match sites must keep a
75/// `_ => ...` arm.
76#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
77#[non_exhaustive]
78pub enum BlockTransferState {
79    #[default]
80    Idle,
81    Submitted {
82        id: BlockRequestId,
83        mode: BlockTransferMode,
84        direction: BlockTransferDirection,
85    },
86    Complete {
87        id: BlockRequestId,
88        mode: BlockTransferMode,
89        direction: BlockTransferDirection,
90    },
91    Failed {
92        id: BlockRequestId,
93        mode: BlockTransferMode,
94        direction: BlockTransferDirection,
95    },
96}
97
98impl BlockTransferState {
99    pub const fn id(self) -> Option<BlockRequestId> {
100        match self {
101            Self::Idle => None,
102            Self::Submitted { id, .. } | Self::Complete { id, .. } | Self::Failed { id, .. } => {
103                Some(id)
104            }
105        }
106    }
107
108    pub const fn mode(self) -> Option<BlockTransferMode> {
109        match self {
110            Self::Idle => None,
111            Self::Submitted { mode, .. }
112            | Self::Complete { mode, .. }
113            | Self::Failed { mode, .. } => Some(mode),
114        }
115    }
116
117    pub const fn direction(self) -> Option<BlockTransferDirection> {
118        match self {
119            Self::Idle => None,
120            Self::Submitted { direction, .. }
121            | Self::Complete { direction, .. }
122            | Self::Failed { direction, .. } => Some(direction),
123        }
124    }
125}
126
127/// Result of advancing a submitted transfer without blocking.
128///
129/// Marked `#[non_exhaustive]`: intermediate states such as `Aborted` or
130/// per-block progress may be added before 1.0.
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132#[non_exhaustive]
133pub enum BlockPoll {
134    Pending,
135    Complete,
136}
137
138/// Direction of a generic SD/MMC data command.
139///
140/// Marked `#[non_exhaustive]` for forward compatibility.
141#[derive(Clone, Copy, Debug, PartialEq, Eq)]
142#[non_exhaustive]
143pub enum DataCommandDirection {
144    Read,
145    Write,
146}
147
148/// Observable state of one protocol data command.
149///
150/// Marked `#[non_exhaustive]` for forward compatibility.
151#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
152#[non_exhaustive]
153pub enum DataCommandState {
154    #[default]
155    Idle,
156    Submitted {
157        direction: DataCommandDirection,
158        cmd_index: u8,
159        block_size: u32,
160        block_count: u32,
161    },
162}
163
164/// Result of advancing a generic data command without blocking.
165///
166/// Marked `#[non_exhaustive]` for forward compatibility.
167#[derive(Clone, Copy, Debug)]
168#[non_exhaustive]
169pub enum DataCommandPoll {
170    Pending,
171    Complete(crate::response::Response),
172}
173
174/// Result of advancing a submitted command without blocking.
175///
176/// Marked `#[non_exhaustive]` for forward compatibility.
177#[derive(Clone, Copy, Debug, PartialEq, Eq)]
178#[non_exhaustive]
179pub enum CommandPoll {
180    Pending,
181    Complete,
182}
183
184/// Result of advancing a submitted command and harvesting its response when
185/// available.
186///
187/// Marked `#[non_exhaustive]` for forward compatibility.
188#[derive(Clone, Copy, Debug)]
189#[non_exhaustive]
190pub enum CommandResponsePoll {
191    Pending,
192    Complete(crate::response::Response),
193}
194
195/// Generic result of advancing an operation without blocking.
196///
197/// Marked `#[non_exhaustive]` for forward compatibility.
198#[derive(Clone, Copy, Debug)]
199#[non_exhaustive]
200pub enum OperationPoll<T> {
201    Pending,
202    Complete(T),
203}
204
205impl From<CommandResponsePoll> for OperationPoll<crate::response::Response> {
206    fn from(value: CommandResponsePoll) -> Self {
207        match value {
208            CommandResponsePoll::Pending => Self::Pending,
209            CommandResponsePoll::Complete(response) => Self::Complete(response),
210        }
211    }
212}
213
214impl From<DataCommandPoll> for OperationPoll<crate::response::Response> {
215    fn from(value: DataCommandPoll) -> Self {
216        match value {
217            DataCommandPoll::Pending => Self::Pending,
218            DataCommandPoll::Complete(response) => Self::Complete(response),
219        }
220    }
221}
222
223impl From<BlockPoll> for OperationPoll<()> {
224    fn from(value: BlockPoll) -> Self {
225        match value {
226            BlockPoll::Pending => Self::Pending,
227            BlockPoll::Complete => Self::Complete(()),
228        }
229    }
230}