1use alloc::{boxed::Box, sync::Arc, vec::Vec};
2
3use ax_kspin::SpinRaw as Mutex;
4
5use crate::{
6 BlkError, DeviceInfo, DriverGeneric, IrqHandler, IrqSourceList, OwnedRequest, PollError,
7 QueueInfo, QueueLimits, Request, RequestId, RequestPoll, RequestStatus, SubmitError,
8};
9
10pub type BInterface = Box<dyn Interface>;
11pub type BQueue = Box<dyn IQueue>;
12pub type BOwnedQueue = Box<dyn IQueueOwned>;
13pub type BIrqHandler = Box<dyn IrqHandler>;
14
15pub trait Interface: DriverGeneric {
16 fn device_info(&self) -> DeviceInfo;
17
18 fn queue_limits(&self) -> QueueLimits;
19
20 fn create_queue(&mut self) -> Option<BQueue>;
21
22 fn create_owned_queue(&mut self) -> Option<QueueHandle> {
23 None
24 }
25
26 fn enable_irq(&self) {}
27
28 fn disable_irq(&self) {}
29
30 fn is_irq_enabled(&self) -> bool {
31 false
32 }
33
34 fn irq_sources(&self) -> IrqSourceList {
35 Vec::new()
36 }
37
38 fn take_irq_handler(&mut self, _source_id: usize) -> Option<BIrqHandler> {
39 None
40 }
41}
42
43pub trait CompletionSink {
44 fn complete(&mut self, request: RequestId, result: Result<(), BlkError>);
45}
46
47pub trait IQueueOwned: Send + 'static {
49 fn id(&self) -> usize;
50
51 fn info(&self) -> QueueInfo;
52
53 fn submit_request(&mut self, request: OwnedRequest) -> Result<RequestId, SubmitError>;
54
55 fn poll_request(&mut self, request: RequestId) -> Result<RequestPoll, PollError>;
56
57 fn cancel_request(&mut self, request: RequestId) -> Result<RequestPoll, PollError>;
58
59 fn shutdown(&mut self) {}
60}
61
62pub struct QueueHandle {
63 queue: Option<BOwnedQueue>,
64}
65
66impl QueueHandle {
67 pub fn new(queue: BOwnedQueue) -> Self {
68 Self { queue: Some(queue) }
69 }
70
71 pub fn id(&self) -> usize {
72 self.queue
73 .as_ref()
74 .expect("owned queue handle must contain queue")
75 .id()
76 }
77
78 pub fn info(&self) -> QueueInfo {
79 self.queue
80 .as_ref()
81 .expect("owned queue handle must contain queue")
82 .info()
83 }
84
85 pub fn submit_request(&mut self, request: OwnedRequest) -> Result<RequestId, SubmitError> {
86 self.queue
87 .as_mut()
88 .expect("owned queue handle must contain queue")
89 .submit_request(request)
90 }
91
92 pub fn poll_request(&mut self, request: RequestId) -> Result<RequestPoll, PollError> {
93 self.queue
94 .as_mut()
95 .expect("owned queue handle must contain queue")
96 .poll_request(request)
97 }
98
99 pub fn cancel_request(&mut self, request: RequestId) -> Result<RequestPoll, PollError> {
100 self.queue
101 .as_mut()
102 .expect("owned queue handle must contain queue")
103 .cancel_request(request)
104 }
105
106 pub fn shutdown(&mut self) {
107 if let Some(queue) = self.queue.as_mut() {
108 queue.shutdown();
109 }
110 }
111}
112
113impl Drop for QueueHandle {
114 fn drop(&mut self) {
115 self.shutdown();
116 }
117}
118
119#[derive(Clone)]
120pub struct IrqHandlerSlot {
121 inner: Arc<Mutex<Option<BIrqHandler>>>,
122}
123
124impl IrqHandlerSlot {
125 pub fn new(handler: BIrqHandler) -> Self {
126 Self {
127 inner: Arc::new(Mutex::new(Some(handler))),
128 }
129 }
130
131 pub fn take(&self) -> Option<IrqHandlerHandle> {
132 let handler = self.inner.lock().take()?;
133 Some(IrqHandlerHandle {
134 slot: Self {
135 inner: Arc::clone(&self.inner),
136 },
137 handler: Some(handler),
138 })
139 }
140}
141
142pub struct IrqHandlerHandle {
143 slot: IrqHandlerSlot,
144 handler: Option<BIrqHandler>,
145}
146
147impl IrqHandler for IrqHandlerHandle {
148 fn handle_irq(&self) -> crate::Event {
149 self.handler
150 .as_ref()
151 .expect("IRQ handler handle must contain handler")
152 .handle_irq()
153 }
154}
155
156impl Drop for IrqHandlerHandle {
157 fn drop(&mut self) {
158 if let Some(handler) = self.handler.take() {
159 let mut slot = self.slot.inner.lock();
160 debug_assert!(slot.is_none());
161 *slot = Some(handler);
162 }
163 }
164}
165
166pub unsafe trait IQueue: Send + 'static {
176 fn id(&self) -> usize;
177
178 fn info(&self) -> QueueInfo;
179
180 fn submit_request(&mut self, request: Request<'_>) -> Result<RequestId, BlkError>;
181
182 fn poll_request(&mut self, request: RequestId) -> Result<RequestStatus, BlkError>;
183
184 fn poll_completions(
196 &mut self,
197 requests: &[RequestId],
198 sink: &mut dyn CompletionSink,
199 ) -> Result<(), BlkError> {
200 for &request in requests {
201 match self.poll_request(request) {
202 Ok(RequestStatus::Pending) => {}
203 Ok(RequestStatus::Complete) => sink.complete(request, Ok(())),
204 Err(err) => sink.complete(request, Err(err)),
205 }
206 }
207 Ok(())
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use alloc::vec::Vec;
214
215 use super::*;
216 use crate::{DeviceInfo, Event, QueueLimits, RequestOp};
217
218 struct NoopIrq;
219
220 impl IrqHandler for NoopIrq {
221 fn handle_irq(&self) -> Event {
222 let mut event = Event::none();
223 event.queues.insert(1);
224 event
225 }
226 }
227
228 struct Queue;
229
230 unsafe impl IQueue for Queue {
233 fn id(&self) -> usize {
234 1
235 }
236
237 fn info(&self) -> QueueInfo {
238 QueueInfo {
239 id: 1,
240 device: DeviceInfo::new(8, 512),
241 limits: QueueLimits::simple(512, u64::MAX),
242 }
243 }
244
245 fn submit_request(&mut self, request: Request<'_>) -> Result<RequestId, BlkError> {
246 assert!(matches!(request.op, RequestOp::Read | RequestOp::Write));
247 Ok(RequestId::new(1))
248 }
249
250 fn poll_request(&mut self, _request: RequestId) -> Result<RequestStatus, BlkError> {
251 Ok(RequestStatus::Complete)
252 }
253 }
254
255 #[test]
256 fn block_api_uses_unified_queue_and_irq_events() {
257 fn assert_queue<T: IQueue>() {}
258 fn assert_irq_handler<T: IrqHandler>() {}
259
260 assert_queue::<Queue>();
261 assert_irq_handler::<NoopIrq>();
262
263 let event = NoopIrq.handle_irq();
264 assert!(event.queues.contains(1));
265 }
266
267 #[derive(Default)]
268 struct RecordingSink {
269 completions: Vec<(RequestId, Result<(), BlkError>)>,
270 }
271
272 impl CompletionSink for RecordingSink {
273 fn complete(&mut self, request_id: RequestId, result: Result<(), BlkError>) {
274 self.completions.push((request_id, result));
275 }
276 }
277
278 struct BatchQueue;
279
280 unsafe impl IQueue for BatchQueue {
283 fn id(&self) -> usize {
284 0
285 }
286
287 fn info(&self) -> QueueInfo {
288 QueueInfo {
289 id: 0,
290 device: DeviceInfo::new(8, 512),
291 limits: QueueLimits::simple(512, u64::MAX),
292 }
293 }
294
295 fn submit_request(&mut self, _request: Request<'_>) -> Result<RequestId, BlkError> {
296 Ok(RequestId::new(0))
297 }
298
299 fn poll_request(&mut self, request: RequestId) -> Result<RequestStatus, BlkError> {
300 match usize::from(request) {
301 1 => Ok(RequestStatus::Complete),
302 2 => Ok(RequestStatus::Pending),
303 3 => Err(BlkError::Io),
304 _ => Err(BlkError::InvalidRequest),
305 }
306 }
307 }
308
309 #[test]
310 fn default_batch_completion_polls_pending_ids_and_reports_terminal_results() {
311 let mut queue = BatchQueue;
312 let mut sink = RecordingSink::default();
313 let ids = [RequestId::new(1), RequestId::new(2), RequestId::new(3)];
314
315 queue.poll_completions(&ids, &mut sink).unwrap();
316
317 assert_eq!(
318 sink.completions,
319 [
320 (RequestId::new(1), Ok(())),
321 (RequestId::new(3), Err(BlkError::Io)),
322 ]
323 );
324 }
325
326 #[test]
327 fn simple_queue_limits_are_single_inflight() {
328 let limits = QueueLimits::simple(512, u64::MAX);
329
330 assert_eq!(limits.max_inflight, 1);
331 }
332
333 #[test]
334 fn irq_handler_slot_returns_handler_on_drop() {
335 let slot = IrqHandlerSlot::new(Box::new(NoopIrq));
336 let handler = slot.take().unwrap();
337
338 assert!(slot.take().is_none());
339 assert!(handler.handle_irq().queues.contains(1));
340
341 drop(handler);
342 assert!(slot.take().is_some());
343 }
344
345 struct OwnedQueue;
346
347 impl IQueueOwned for OwnedQueue {
348 fn id(&self) -> usize {
349 2
350 }
351
352 fn info(&self) -> QueueInfo {
353 QueueInfo {
354 id: 2,
355 device: DeviceInfo::new(8, 512),
356 limits: QueueLimits::simple(512, u64::MAX),
357 }
358 }
359
360 fn submit_request(&mut self, request: OwnedRequest) -> Result<RequestId, SubmitError> {
361 Err(SubmitError::new(BlkError::Retry, request))
362 }
363
364 fn poll_request(&mut self, _request: RequestId) -> Result<RequestPoll, PollError> {
365 Ok(RequestPoll::Pending)
366 }
367
368 fn cancel_request(&mut self, _request: RequestId) -> Result<RequestPoll, PollError> {
369 Err(PollError::UnknownRequest)
370 }
371 }
372
373 #[test]
374 fn owned_queue_submit_error_returns_request_ownership() {
375 let mut handle = QueueHandle::new(Box::new(OwnedQueue));
376 let request = OwnedRequest {
377 op: RequestOp::Flush,
378 lba: 0,
379 block_count: 0,
380 data: None,
381 flags: Default::default(),
382 };
383
384 let err = handle.submit_request(request).unwrap_err();
385
386 assert_eq!(err.error, BlkError::Retry);
387 assert!(matches!(err.request().op, RequestOp::Flush));
388 }
389}