Skip to main content

rdif_block/
interface.rs

1use alloc::{boxed::Box, vec::Vec};
2
3use crate::{
4    BlkError, DeviceInfo, DriverGeneric, IrqHandler, IrqSourceList, QueueInfo, QueueLimits,
5    Request, RequestId, RequestStatus,
6};
7
8pub trait Interface: DriverGeneric {
9    fn device_info(&self) -> DeviceInfo;
10
11    fn queue_limits(&self) -> QueueLimits;
12
13    fn create_queue(&mut self) -> Option<Box<dyn IQueue>>;
14
15    fn enable_irq(&self) {}
16
17    fn disable_irq(&self) {}
18
19    fn is_irq_enabled(&self) -> bool {
20        false
21    }
22
23    fn irq_sources(&self) -> IrqSourceList {
24        Vec::new()
25    }
26
27    fn take_irq_handler(&mut self, _source_id: usize) -> Option<Box<dyn IrqHandler>> {
28        None
29    }
30}
31
32/// A request queue for one block device hardware/software queue.
33///
34/// # Safety
35///
36/// Implementers may access `Request` segments after `submit_request` returns
37/// and until the matching `poll_request` returns `RequestStatus::Complete` or
38/// an error. They must not access any segment before `submit_request` is called
39/// or after completion/error has been reported, and request IDs must not alias
40/// two concurrently pending requests in a way that extends this lifetime.
41pub unsafe trait IQueue: Send + 'static {
42    fn id(&self) -> usize;
43
44    fn info(&self) -> QueueInfo;
45
46    fn submit_request(&mut self, request: Request<'_>) -> Result<RequestId, BlkError>;
47
48    fn poll_request(&mut self, request: RequestId) -> Result<RequestStatus, BlkError>;
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::{DeviceInfo, Event, QueueLimits, RequestOp};
55
56    struct NoopIrq;
57
58    impl IrqHandler for NoopIrq {
59        fn handle_irq(&self) -> Event {
60            let mut event = Event::none();
61            event.queues.insert(1);
62            event
63        }
64    }
65
66    struct Queue;
67
68    // SAFETY: This test queue never stores request segments beyond
69    // `submit_request` and reports completion immediately.
70    unsafe impl IQueue for Queue {
71        fn id(&self) -> usize {
72            1
73        }
74
75        fn info(&self) -> QueueInfo {
76            QueueInfo {
77                id: 1,
78                device: DeviceInfo::new(8, 512),
79                limits: QueueLimits::simple(512, u64::MAX),
80            }
81        }
82
83        fn submit_request(&mut self, request: Request<'_>) -> Result<RequestId, BlkError> {
84            assert!(matches!(request.op, RequestOp::Read | RequestOp::Write));
85            Ok(RequestId::new(1))
86        }
87
88        fn poll_request(&mut self, _request: RequestId) -> Result<RequestStatus, BlkError> {
89            Ok(RequestStatus::Complete)
90        }
91    }
92
93    #[test]
94    fn block_api_uses_unified_queue_and_irq_events() {
95        fn assert_queue<T: IQueue>() {}
96        fn assert_irq_handler<T: IrqHandler>() {}
97
98        assert_queue::<Queue>();
99        assert_irq_handler::<NoopIrq>();
100
101        let event = NoopIrq.handle_irq();
102        assert!(event.queues.contains(1));
103    }
104}