1extern crate alloc;
2
3use alloc::boxed::Box;
4use core::mem::size_of;
5
6use dma_api::{CoherentArray, DeviceDma, DmaOp};
7use mmio_api::{Mmio, MmioAddr, MmioOp};
8use rdif_eth::{DmaBuffer, Event, IRxQueue, ITxQueue, Interface, NetError, QueueConfig};
9
10use crate::err::{Error, Result};
11
12mod descriptor;
13mod registers;
14
15use descriptor::{RxDesc, TxDesc};
16use registers::*;
17
18const QUEUE_SIZE: usize = 256;
19const QUEUE_ID0: usize = 0;
20const MAX_PACKET: usize = 2048;
21
22pub struct E1000 {
23 regs: Regs,
24 _mmio: Mmio,
25 dma: DeviceDma,
26 mac: [u8; 6],
27 irq_enabled: bool,
28 tx_created: bool,
29 rx_created: bool,
30}
31
32impl E1000 {
33 pub fn check_vid_did(vid: u16, did: u16) -> bool {
34 vid == 0x8086 && [0x100e, 0x100f].contains(&did)
35 }
36
37 pub fn new(
38 bar_addr: impl Into<MmioAddr>,
39 bar_size: usize,
40 dma_mask: u64,
41 dma_op: &'static dyn DmaOp,
42 mmio_op: &'static dyn MmioOp,
43 ) -> Result<Self> {
44 mmio_api::init(mmio_op);
45 let mmio = mmio_api::ioremap(bar_addr.into(), bar_size)?;
46 let regs = Regs::new(mmio.as_nonnull_ptr());
47 let dma = DeviceDma::new_legacy(dma_mask, dma_op);
48
49 regs.reset();
50 regs.disable_all_irq();
51
52 regs.write(CTRL, regs.read(CTRL) | (1 << 6));
54
55 let mac = regs.mac_addr();
56
57 Ok(Self {
58 regs,
59 _mmio: mmio,
60 dma,
61 mac,
62 irq_enabled: false,
63 tx_created: false,
64 rx_created: false,
65 })
66 }
67}
68
69impl rdif_eth::DriverGeneric for E1000 {
70 fn name(&self) -> &str {
71 "eth-intel-e1000"
72 }
73}
74
75impl Interface for E1000 {
76 fn mac_address(&self) -> [u8; 6] {
77 self.mac
78 }
79
80 fn create_tx_queue(&mut self) -> Option<Box<dyn ITxQueue>> {
81 if self.tx_created {
82 return None;
83 }
84
85 let desc = self
86 .dma
87 .coherent_array_zero_with_align::<TxDesc>(QUEUE_SIZE, 16)
88 .ok()?;
89
90 let desc_base = desc.dma_addr().as_u64();
91
92 self.regs.write(TDBAL, desc_base as u32);
93 self.regs.write(TDBAH, (desc_base >> 32) as u32);
94 self.regs
95 .write(TDLEN, (QUEUE_SIZE * size_of::<TxDesc>()) as u32);
96 self.regs.write(TDH, 0);
97 self.regs.write(TDT, 0);
98
99 self.regs
101 .write(TCTL, (1 << 1) | (1 << 3) | (0x10 << 4) | (0x40 << 12));
102 self.regs.write(TIPG, 10 | (8 << 10) | (6 << 20));
103
104 let queue = E1000TxQueue {
105 regs: self.regs,
106 desc,
107 dma_mask: self.dma.dma_mask(),
108 bus_addrs: [None; QUEUE_SIZE],
109 next_submit: 0,
110 next_reclaim: 0,
111 };
112
113 self.tx_created = true;
114 Some(Box::new(queue))
115 }
116
117 fn create_rx_queue(&mut self) -> Option<Box<dyn IRxQueue>> {
118 if self.rx_created {
119 return None;
120 }
121
122 let desc = self
123 .dma
124 .coherent_array_zero_with_align::<RxDesc>(QUEUE_SIZE, 16)
125 .ok()?;
126
127 let desc_base = desc.dma_addr().as_u64();
128
129 self.regs.write(RDBAL, desc_base as u32);
130 self.regs.write(RDBAH, (desc_base >> 32) as u32);
131 self.regs
132 .write(RDLEN, (QUEUE_SIZE * size_of::<RxDesc>()) as u32);
133 self.regs.write(RDH, 0);
134 self.regs.write(RDT, 0);
135
136 self.regs.write(RCTL, (1 << 1) | (1 << 15) | (1 << 26));
138
139 let queue = E1000RxQueue {
140 regs: self.regs,
141 desc,
142 dma_mask: self.dma.dma_mask(),
143 bus_addrs: [None; QUEUE_SIZE],
144 next_submit: 0,
145 next_reclaim: 0,
146 };
147
148 self.rx_created = true;
149 Some(Box::new(queue))
150 }
151
152 fn enable_irq(&mut self) {
153 self.regs.enable_default_irq();
154 self.irq_enabled = true;
155 }
156
157 fn disable_irq(&mut self) {
158 self.regs.disable_all_irq();
159 self.irq_enabled = false;
160 }
161
162 fn is_irq_enabled(&self) -> bool {
163 self.irq_enabled
164 }
165
166 fn handle_irq(&mut self) -> Event {
167 e1000_irq_event(self.regs.read(ICR))
168 }
169
170 fn take_irq_handler(&mut self) -> Option<rdif_eth::BIrqHandler> {
171 Some(Box::new(E1000IrqHandler { regs: self.regs }))
172 }
173}
174
175struct E1000IrqHandler {
176 regs: Regs,
177}
178
179impl rdif_eth::IrqHandler for E1000IrqHandler {
180 fn handle_irq(&mut self) -> Event {
181 e1000_irq_event(self.regs.read(ICR))
182 }
183}
184
185fn e1000_irq_event(icr: u32) -> Event {
186 let mut ev = Event::none();
187
188 if icr & (1 << 0) != 0 {
189 ev.tx_queue.insert(QUEUE_ID0);
190 }
191 if icr & (1 << 7) != 0 {
192 ev.rx_queue.insert(QUEUE_ID0);
193 }
194
195 ev
196}
197
198struct E1000TxQueue {
199 regs: Regs,
200 desc: CoherentArray<TxDesc>,
201 dma_mask: u64,
202 bus_addrs: [Option<u64>; QUEUE_SIZE],
203 next_submit: usize,
204 next_reclaim: usize,
205}
206
207impl ITxQueue for E1000TxQueue {
208 fn id(&self) -> usize {
209 QUEUE_ID0
210 }
211
212 fn config(&self) -> QueueConfig {
213 QueueConfig {
214 dma_mask: self.dma_mask,
215 align: 16,
216 buf_size: MAX_PACKET,
217 ring_size: QUEUE_SIZE,
218 }
219 }
220
221 fn submit(&mut self, buffer: DmaBuffer) -> core::result::Result<(), NetError> {
222 if buffer.len > MAX_PACKET {
223 return Err(NetError::Other(Box::new(Error::InvalidArgument(
224 "tx packet too large",
225 ))));
226 }
227
228 let idx = self.next_submit;
229 let next = (idx + 1) % QUEUE_SIZE;
230 let hw_head = self.regs.read(TDH) as usize;
231
232 if next == hw_head {
233 return Err(NetError::Retry);
234 }
235
236 self.desc
237 .set_cpu(idx, TxDesc::new(buffer.bus_addr, buffer.len as u16));
238 self.bus_addrs[idx] = Some(buffer.bus_addr);
239 self.next_submit = next;
240 self.regs.write(TDT, next as u32);
241
242 Ok(())
243 }
244
245 fn reclaim(&mut self) -> Option<u64> {
246 let idx = self.next_reclaim;
247 let desc = self.desc.read_cpu(idx)?;
248 if !desc.is_done() {
249 return None;
250 }
251
252 self.next_reclaim = (idx + 1) % QUEUE_SIZE;
253 self.bus_addrs[idx].take()
254 }
255}
256
257struct E1000RxQueue {
258 regs: Regs,
259 desc: CoherentArray<RxDesc>,
260 dma_mask: u64,
261 bus_addrs: [Option<u64>; QUEUE_SIZE],
262 next_submit: usize,
263 next_reclaim: usize,
264}
265
266impl IRxQueue for E1000RxQueue {
267 fn id(&self) -> usize {
268 QUEUE_ID0
269 }
270
271 fn config(&self) -> QueueConfig {
272 QueueConfig {
273 dma_mask: self.dma_mask,
274 align: 16,
275 buf_size: MAX_PACKET,
276 ring_size: QUEUE_SIZE,
277 }
278 }
279
280 fn submit(&mut self, buffer: DmaBuffer) -> core::result::Result<(), NetError> {
281 if buffer.len > MAX_PACKET {
282 return Err(NetError::Other(Box::new(Error::InvalidArgument(
283 "rx buffer too large",
284 ))));
285 }
286
287 let idx = self.next_submit;
288 let next = (idx + 1) % QUEUE_SIZE;
289 let hw_head = self.regs.read(RDH) as usize;
290
291 if next == hw_head {
292 return Err(NetError::Retry);
293 }
294
295 self.desc.set_cpu(idx, RxDesc::new(buffer.bus_addr));
296 self.bus_addrs[idx] = Some(buffer.bus_addr);
297 self.next_submit = next;
298 self.regs.write(RDT, next as u32);
299
300 Ok(())
301 }
302
303 fn reclaim(&mut self) -> Option<(u64, usize)> {
304 let idx = self.next_reclaim;
305 let desc = self.desc.read_cpu(idx)?;
306 if !desc.is_done() {
307 return None;
308 }
309
310 self.next_reclaim = (idx + 1) % QUEUE_SIZE;
311 self.bus_addrs[idx]
312 .take()
313 .map(|bus_addr| (bus_addr, desc.length as usize))
314 }
315}