Skip to main content

rdif_eth/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use alloc::boxed::Box;
6
7pub use dma_api;
8pub use rdif_base::{DriverGeneric, KError, io};
9
10// ---------------------------------------------------------------------------
11// Error
12// ---------------------------------------------------------------------------
13
14/// Errors that can occur during network device operations.
15#[derive(thiserror::Error, Debug)]
16pub enum NetError {
17    /// The requested operation is not supported by the device.
18    #[error("Operation not supported")]
19    NotSupported,
20
21    /// The operation should be retried later (e.g. queue full).
22    #[error("Operation should be retried")]
23    Retry,
24
25    /// Insufficient memory to complete the operation.
26    #[error("Insufficient memory")]
27    NoMemory,
28
29    /// The network link is down.
30    #[error("Link down")]
31    LinkDown,
32
33    /// An unspecified error occurred.
34    #[error("Other error: {0}")]
35    Other(Box<dyn core::error::Error>),
36}
37
38impl From<NetError> for io::ErrorKind {
39    fn from(value: NetError) -> Self {
40        match value {
41            NetError::NotSupported => io::ErrorKind::Unsupported,
42            NetError::Retry => io::ErrorKind::Interrupted,
43            NetError::NoMemory => io::ErrorKind::OutOfMemory,
44            NetError::LinkDown => io::ErrorKind::NotAvailable,
45            NetError::Other(e) => io::ErrorKind::Other(e),
46        }
47    }
48}
49
50impl From<dma_api::DmaError> for NetError {
51    fn from(value: dma_api::DmaError) -> Self {
52        match value {
53            dma_api::DmaError::NoMemory => NetError::NoMemory,
54            e => NetError::Other(Box::new(e)),
55        }
56    }
57}
58
59// ---------------------------------------------------------------------------
60// DMA buffer helpers
61// ---------------------------------------------------------------------------
62
63/// Queue configuration needed by the upper layer DMA pool.
64#[derive(Debug, Clone, Copy)]
65pub struct QueueConfig {
66    /// DMA addressing mask for the device.
67    pub dma_mask: u64,
68
69    /// Required alignment for buffer addresses (in bytes).
70    pub align: usize,
71
72    /// DMA packet buffer size in bytes.
73    pub buf_size: usize,
74
75    /// Descriptor ring size.
76    pub ring_size: usize,
77}
78
79/// Bitmask tracking up to 64 queue identifiers.
80#[repr(transparent)]
81#[derive(Debug, Clone, Copy)]
82pub struct IdList(u64);
83
84impl IdList {
85    pub const fn none() -> Self {
86        Self(0)
87    }
88
89    pub fn contains(&self, id: usize) -> bool {
90        (self.0 & (1 << id)) != 0
91    }
92
93    pub fn insert(&mut self, id: usize) {
94        self.0 |= 1 << id;
95    }
96
97    pub fn remove(&mut self, id: usize) {
98        self.0 &= !(1 << id);
99    }
100
101    pub fn iter(&self) -> impl Iterator<Item = usize> {
102        let bits = self.0;
103        (0..64).filter(move |i| (bits & (1 << i)) != 0)
104    }
105}
106
107/// Event returned by [`Interface::handle_irq`] indicating which queues have
108/// completed operations.
109#[derive(Debug, Clone, Copy)]
110pub struct Event {
111    /// Bitmask of TX queue IDs that have completion events.
112    pub tx_queue: IdList,
113    /// Bitmask of RX queue IDs that have completion events.
114    pub rx_queue: IdList,
115}
116
117impl Event {
118    pub const fn none() -> Self {
119        Self {
120            tx_queue: IdList::none(),
121            rx_queue: IdList::none(),
122        }
123    }
124}
125
126/// Core interface that network device drivers must implement.
127///
128/// Provides device-level operations: queue creation, interrupt management,
129/// and MAC address retrieval. Individual packet I/O goes through the queue
130/// traits ([`ITxQueue`] / [`IRxQueue`]).
131pub trait Interface: DriverGeneric {
132    /// Returns the device's 6-byte MAC address.
133    fn mac_address(&self) -> [u8; 6];
134
135    /// Create a new transmit queue. Returns `None` if no more queues are
136    /// available.
137    fn create_tx_queue(&mut self) -> Option<Box<dyn ITxQueue>>;
138
139    /// Create a new receive queue. Returns `None` if no more queues are
140    /// available.
141    fn create_rx_queue(&mut self) -> Option<Box<dyn IRxQueue>>;
142
143    /// Enable device interrupts.
144    fn enable_irq(&mut self);
145
146    /// Disable device interrupts.
147    fn disable_irq(&mut self);
148
149    /// Check whether device interrupts are currently enabled.
150    fn is_irq_enabled(&self) -> bool;
151
152    /// Handle a device interrupt, returning which queues have events.
153    fn handle_irq(&mut self) -> Event;
154}
155
156// ---------------------------------------------------------------------------
157// Transmit queue
158// ---------------------------------------------------------------------------
159
160/// Transmit queue interface.
161///
162/// A driver creates one or more TX queues via [`Interface::create_tx_queue`]
163/// and exchanges DMA buffer bus addresses with the caller.
164pub trait ITxQueue: Send + 'static {
165    /// Queue identifier (unique within the device).
166    fn id(&self) -> usize;
167
168    /// DMA buffer configuration for this queue.
169    fn config(&self) -> QueueConfig;
170
171    /// Submit a DMA buffer for transmission.
172    ///
173    /// `bus_addr` must point to a DMA-capable buffer whose first `len` bytes
174    /// contain the packet to be transmitted.
175    fn submit(&mut self, bus_addr: u64, len: usize) -> Result<(), NetError>;
176
177    /// Reclaim the next completed transmit buffer.
178    ///
179    /// Returns the buffer bus address when the device has completed sending it.
180    fn reclaim(&mut self) -> Option<u64>;
181}
182
183// ---------------------------------------------------------------------------
184// Receive queue
185// ---------------------------------------------------------------------------
186
187/// Receive queue interface.
188///
189/// A driver creates one or more RX queues via [`Interface::create_rx_queue`]
190/// and exchanges DMA buffer bus addresses with the caller.
191pub trait IRxQueue: Send + 'static {
192    /// Queue identifier (unique within the device).
193    fn id(&self) -> usize;
194
195    /// DMA buffer configuration for this queue.
196    fn config(&self) -> QueueConfig;
197
198    /// Submit an empty DMA buffer to hardware.
199    ///
200    /// `bus_addr` must point to a DMA-capable buffer whose total size is `len`.
201    fn submit(&mut self, bus_addr: u64, len: usize) -> Result<(), NetError>;
202
203    /// Reclaim the next completed receive buffer.
204    ///
205    /// Returns the buffer bus address and the received byte count.
206    fn reclaim(&mut self) -> Option<(u64, usize)>;
207}