Skip to main content

rdif_eth/
lib.rs

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