strat9_kernel/hardware/nic/
pcnet_drv.rs1use crate::{
5 hardware::{
6 nic::NetworkDevice,
7 pci_client::{self as pci, Bar, ProbeCriteria},
8 },
9 memory::{allocate_dma_frame, phys_to_virt},
10};
11use alloc::{format, string::String, sync::Arc, vec::Vec};
12use core::sync::atomic::{AtomicUsize, Ordering};
13use spin::Mutex;
14
15use crate::hardware::nic::NetError;
16
17const MTU: usize = 1536;
18const RX_BUFFERS_COUNT: usize = 32;
19const TX_BUFFERS_COUNT: usize = 8;
20const DESC_LEN: usize = 16;
21
22const CSR0_INIT: u32 = 0;
23const CSR0_STRT: u32 = 1;
24const CSR0_TDMD: u32 = 3;
25
26const DE_ENP: usize = 0;
27const DE_STP: usize = 1;
28const DE_OWN: usize = 7;
29
30fn log2(x: u8) -> u8 {
32 8 - 1 - x.leading_zeros() as u8
33}
34
35pub struct PcnetDevice {
36 ports: Mutex<Ports>,
37 rx_buffers: [*mut u8; RX_BUFFERS_COUNT],
38 rx_phys: [u64; RX_BUFFERS_COUNT],
39 tx_buffers: [*mut u8; TX_BUFFERS_COUNT],
40 tx_phys: [u64; TX_BUFFERS_COUNT],
41 rx_des: *mut u8,
42 rx_des_phys: u64,
43 tx_des: *mut u8,
44 tx_des_phys: u64,
45 rx_id: AtomicUsize,
46 tx_id: AtomicUsize,
47 mac: [u8; 6],
48 name: String,
49}
50
51unsafe impl Send for PcnetDevice {}
52unsafe impl Sync for PcnetDevice {}
53
54struct Ports {
55 io_base: u16,
56}
57
58impl Ports {
59 fn new(io_base: u16) -> Self {
61 Self { io_base }
62 }
63
64 #[inline]
66 fn read8(&self, offset: u16) -> u8 {
67 unsafe { x86_64::instructions::port::Port::new(self.io_base + offset).read() }
68 }
69
70 #[inline]
72 #[allow(dead_code)]
73 fn write8(&mut self, offset: u16, value: u8) {
74 unsafe { x86_64::instructions::port::Port::new(self.io_base + offset).write(value) }
75 }
76
77 #[inline]
79 fn read32(&self, offset: u16) -> u32 {
80 unsafe { x86_64::instructions::port::Port::new(self.io_base + offset).read() }
81 }
82
83 #[inline]
85 #[allow(dead_code)]
86 fn write32(&mut self, offset: u16, value: u32) {
87 unsafe { x86_64::instructions::port::Port::new(self.io_base + offset).write(value) }
88 }
89
90 fn write_rap(&mut self, val: u32) {
92 unsafe { x86_64::instructions::port::Port::new(self.io_base + 0x14).write(val) }
93 }
94
95 fn read_rdp(&self) -> u32 {
97 unsafe { x86_64::instructions::port::Port::new(self.io_base + 0x10).read() }
98 }
99
100 fn write_rdp(&mut self, val: u32) {
102 unsafe { x86_64::instructions::port::Port::new(self.io_base + 0x10).write(val) }
103 }
104
105 fn read_bdp(&self) -> u32 {
107 unsafe { x86_64::instructions::port::Port::new(self.io_base + 0x1C).read() }
108 }
109
110 fn write_bdp(&mut self, val: u32) {
112 unsafe { x86_64::instructions::port::Port::new(self.io_base + 0x1C).write(val) }
113 }
114
115 fn read_csr(&mut self, csr: u32) -> u32 {
117 self.write_rap(csr);
118 self.read_rdp()
119 }
120
121 fn write_csr(&mut self, csr: u32, val: u32) {
123 self.write_rap(csr);
124 self.write_rdp(val);
125 }
126
127 fn read_bcr(&mut self, bcr: u32) -> u32 {
129 self.write_rap(bcr);
130 self.read_bdp()
131 }
132
133 fn write_bcr(&mut self, bcr: u32, val: u32) {
135 self.write_rap(bcr);
136 self.write_bdp(val);
137 }
138
139 fn mac(&mut self) -> [u8; 6] {
141 [
142 self.read8(0x00),
143 self.read8(0x01),
144 self.read8(0x02),
145 self.read8(0x03),
146 self.read8(0x04),
147 self.read8(0x05),
148 ]
149 }
150}
151
152impl PcnetDevice {
153 pub unsafe fn new(pci_dev: pci::PciDevice) -> Result<Self, &'static str> {
155 let io_base = match pci_dev.read_bar(0) {
156 Some(Bar::Io { port }) => port as u16,
157 _ => return Err("Invalid BAR"),
158 };
159
160 let mut ports = Ports::new(io_base);
161 let mac = ports.mac();
162 let name = format!("pcnet_{:02x}{:02x}{:02x}", mac[3], mac[4], mac[5]);
163
164 let mut rx_buffers = [core::ptr::null_mut(); RX_BUFFERS_COUNT];
165 let mut rx_phys = [0u64; RX_BUFFERS_COUNT];
166 for i in 0..RX_BUFFERS_COUNT {
167 let frame = allocate_dma_frame().ok_or("Failed to allocate RX buffer")?;
168 rx_phys[i] = frame.start_address.as_u64();
169 rx_buffers[i] = phys_to_virt(rx_phys[i]) as *mut u8;
170 }
171
172 let mut tx_buffers = [core::ptr::null_mut(); TX_BUFFERS_COUNT];
173 let mut tx_phys = [0u64; TX_BUFFERS_COUNT];
174 for i in 0..TX_BUFFERS_COUNT {
175 let frame = allocate_dma_frame().ok_or("Failed to allocate TX buffer")?;
176 tx_phys[i] = frame.start_address.as_u64();
177 tx_buffers[i] = phys_to_virt(tx_phys[i]) as *mut u8;
178 }
179
180 let rx_des_frame = allocate_dma_frame().ok_or("Failed to allocate RX descriptors")?;
181 let rx_des_phys = rx_des_frame.start_address.as_u64();
182 let rx_des = phys_to_virt(rx_des_phys) as *mut u8;
183 unsafe {
184 core::ptr::write_bytes(rx_des, 0, RX_BUFFERS_COUNT * DESC_LEN);
185 }
186
187 let tx_des_frame = allocate_dma_frame().ok_or("Failed to allocate TX descriptors")?;
188 let tx_des_phys = tx_des_frame.start_address.as_u64();
189 let tx_des = phys_to_virt(tx_des_phys) as *mut u8;
190 unsafe {
191 core::ptr::write_bytes(tx_des, 0, TX_BUFFERS_COUNT * DESC_LEN);
192 }
193
194 let mut device = Self {
195 ports: Mutex::new(ports),
196 rx_buffers,
197 rx_phys,
198 tx_buffers,
199 tx_phys,
200 rx_des,
201 rx_des_phys,
202 tx_des,
203 tx_des_phys,
204 rx_id: AtomicUsize::new(0),
205 tx_id: AtomicUsize::new(0),
206 mac,
207 name,
208 };
209
210 device.init();
211 Ok(device)
212 }
213
214 fn init(&mut self) {
216 let mut ports = self.ports.lock();
217
218 ports.read8(0x18);
219 let _ = ports.read32(0x18);
220
221 let mut csr_58 = ports.read_csr(58);
222 csr_58 &= 0xFF00;
223 csr_58 |= 2;
224 ports.write_csr(58, csr_58);
225
226 let mut bcr_2 = ports.read_bcr(2);
227 bcr_2 |= 2;
228 ports.write_bcr(2, bcr_2);
229
230 for i in 0..RX_BUFFERS_COUNT {
231 self.init_rx_descriptor(i);
232 }
233 for i in 0..TX_BUFFERS_COUNT {
234 self.init_tx_descriptor(i);
235 }
236
237 let init_struct_frame = allocate_dma_frame().unwrap();
238 let init_phys = init_struct_frame.start_address.as_u64();
239 let init_virt = phys_to_virt(init_phys) as *mut u8;
240 unsafe {
241 core::ptr::write_bytes(init_virt, 0, 28);
242 }
243
244 unsafe {
245 init_virt.write(0);
246 init_virt.add(1).write(0);
247 init_virt
248 .add(2)
249 .write((log2(RX_BUFFERS_COUNT as u8) as u8) << 4);
250 init_virt
251 .add(3)
252 .write((log2(TX_BUFFERS_COUNT as u8) as u8) << 4);
253
254 init_virt.add(4).write(self.mac[0]);
255 init_virt.add(5).write(self.mac[1]);
256 init_virt.add(6).write(self.mac[2]);
257 init_virt.add(7).write(self.mac[3]);
258 init_virt.add(8).write(self.mac[4]);
259 init_virt.add(9).write(self.mac[5]);
260
261 init_virt.add(20).write((self.rx_des_phys & 0xFF) as u8);
262 init_virt
263 .add(21)
264 .write(((self.rx_des_phys >> 8) & 0xFF) as u8);
265 init_virt
266 .add(22)
267 .write(((self.rx_des_phys >> 16) & 0xFF) as u8);
268 init_virt
269 .add(23)
270 .write(((self.rx_des_phys >> 24) & 0xFF) as u8);
271
272 init_virt.add(24).write((self.tx_des_phys & 0xFFFF) as u8);
273 init_virt
274 .add(25)
275 .write(((self.tx_des_phys >> 8) & 0xFF) as u8);
276 init_virt
277 .add(26)
278 .write(((self.tx_des_phys >> 16) & 0xFF) as u8);
279 init_virt
280 .add(27)
281 .write(((self.tx_des_phys >> 24) & 0xFF) as u8);
282 }
283
284 ports.write_csr(1, (init_phys & 0xFFFF) as u32);
285 ports.write_csr(2, ((init_phys >> 16) & 0xFFFF) as u32);
286
287 let mut csr_0 = ports.read_csr(0);
288 csr_0 |= 1 << CSR0_INIT;
289 ports.write_csr(0, csr_0);
290
291 core::hint::spin_loop();
292
293 let mut csr_0 = ports.read_csr(0);
294 csr_0 |= 1 << CSR0_STRT;
295 ports.write_csr(0, csr_0);
296
297 log::info!(
298 "PCnet: MAC {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
299 self.mac[0],
300 self.mac[1],
301 self.mac[2],
302 self.mac[3],
303 self.mac[4],
304 self.mac[5]
305 );
306 }
307
308 fn init_rx_descriptor(&self, i: usize) {
310 unsafe {
311 let desc = self.rx_des.add(i * DESC_LEN);
312 desc.write_bytes(0, DESC_LEN);
313
314 let buf_addr = self.rx_phys[i];
315 desc.add(0).write((buf_addr & 0xFF) as u8);
316 desc.add(1).write(((buf_addr >> 8) & 0xFF) as u8);
317 desc.add(2).write(((buf_addr >> 16) & 0xFF) as u8);
318 desc.add(3).write(((buf_addr >> 24) & 0xFF) as u8);
319 let bcnt = (!(MTU as u16)).wrapping_add(1) & 0x0FFF;
320 desc.add(4).write((bcnt & 0xFF) as u8);
321 desc.add(5).write(((bcnt >> 8) as u8) | 0xF0);
322 desc.add(7).write(0x80);
323 }
324 }
325
326 fn init_tx_descriptor(&self, i: usize) {
328 unsafe {
329 let desc = self.tx_des.add(i * DESC_LEN);
330 desc.write_bytes(0, DESC_LEN);
331
332 let buf_addr = self.tx_phys[i];
333 desc.add(0).write((buf_addr & 0xFF) as u8);
334 desc.add(1).write(((buf_addr >> 8) & 0xFF) as u8);
335 desc.add(2).write(((buf_addr >> 16) & 0xFF) as u8);
336 desc.add(3).write(((buf_addr >> 24) & 0xFF) as u8);
337 }
338 }
339
340 fn receive_inner(&self) -> Option<Vec<u8>> {
342 let rx_id = self.rx_id.load(Ordering::Relaxed);
343
344 unsafe {
345 let desc = self.rx_des.add(rx_id * DESC_LEN + 7);
346 let status = desc.read_volatile();
347
348 if (status & (1 << DE_OWN)) != 0 {
349 return None;
350 }
351
352 let stp = (status & (1 << DE_STP)) != 0;
353 let enp = (status & (1 << DE_ENP)) != 0;
354
355 if stp && enp {
356 let len_offset = rx_id * DESC_LEN + 8;
357 let len_lo = self.rx_des.add(len_offset).read() as usize;
358 let len_hi = self.rx_des.add(len_offset + 1).read() as usize & 0xF;
359 let len = ((len_hi << 8) | len_lo) & 0xFFF;
360
361 if len <= MTU {
362 let mut buf = Vec::with_capacity(len);
363 core::ptr::copy_nonoverlapping(self.rx_buffers[rx_id], buf.as_mut_ptr(), len);
364 buf.set_len(len);
365
366 let desc = self.rx_des.add(rx_id * DESC_LEN + 7);
367 desc.write_volatile(0x80);
368
369 self.rx_id
370 .store((rx_id + 1) % RX_BUFFERS_COUNT, Ordering::Relaxed);
371 return Some(buf);
372 }
373 }
374
375 let desc = self.rx_des.add(rx_id * DESC_LEN + 7);
376 desc.write_volatile(0x80);
377 self.rx_id
378 .store((rx_id + 1) % RX_BUFFERS_COUNT, Ordering::Relaxed);
379 }
380
381 None
382 }
383
384 fn transmit_inner(&self, data: &[u8]) -> Result<(), NetError> {
386 if data.len() > MTU {
387 return Err(NetError::BufferTooSmall);
388 }
389
390 let tx_id = self.tx_id.load(Ordering::Relaxed);
391
392 unsafe {
393 let desc = self.tx_des.add(tx_id * DESC_LEN + 7);
394 let status = desc.read_volatile();
395
396 if (status & (1 << DE_OWN)) != 0 {
397 let mut timeout = 10000;
398 while (self.tx_des.add(tx_id * DESC_LEN + 7).read_volatile() & (1 << DE_OWN)) != 0 {
399 core::hint::spin_loop();
400 timeout -= 1;
401 if timeout == 0 {
402 return Err(NetError::NotReady);
403 }
404 }
405 }
406
407 core::ptr::copy_nonoverlapping(data.as_ptr(), self.tx_buffers[tx_id], data.len());
408
409 let desc = self.tx_des.add(tx_id * DESC_LEN);
410 let bcnt = (!(data.len() as u16)).wrapping_add(1) & 0x0FFF;
411 desc.add(4).write((bcnt & 0xFF) as u8);
412 desc.add(5).write(((bcnt >> 8) as u8) | 0xF0);
413 desc.add(6).write(0);
414 desc.add(7).write(0x83);
415
416 self.tx_id
417 .store((tx_id + 1) % TX_BUFFERS_COUNT, Ordering::Relaxed);
418
419 let mut ports = self.ports.lock();
420 let mut csr_0 = ports.read_csr(0);
421 csr_0 |= 1 << CSR0_TDMD;
422 ports.write_csr(0, csr_0);
423 }
424
425 Ok(())
426 }
427}
428
429impl NetworkDevice for PcnetDevice {
430 fn name(&self) -> &str {
432 &self.name
433 }
434
435 fn mac_address(&self) -> [u8; 6] {
437 self.mac
438 }
439
440 fn link_up(&self) -> bool {
442 let mut ports = self.ports.lock();
443 let csr_4 = ports.read_csr(4);
444 (csr_4 & 0x20) != 0
445 }
446
447 fn receive(&self, buf: &mut [u8]) -> Result<usize, NetError> {
449 if let Some(packet) = self.receive_inner() {
450 let len = core::cmp::min(packet.len(), buf.len());
451 buf[..len].copy_from_slice(&packet[..len]);
452 Ok(len)
453 } else {
454 Err(NetError::NoPacket)
455 }
456 }
457
458 fn transmit(&self, data: &[u8]) -> Result<(), NetError> {
460 self.transmit_inner(data)
461 }
462}
463
464static PCNET_DEVICES: Mutex<Vec<Arc<PcnetDevice>>> = Mutex::new(Vec::new());
465
466pub fn init() {
468 log::info!("[PCnet] Scanning for PCnet devices...");
469
470 let candidates = pci::probe_all(ProbeCriteria {
471 vendor_id: Some(0x1022),
472 device_id: None,
473 class_code: Some(pci::class::NETWORK),
474 subclass: Some(pci::net_subclass::ETHERNET),
475 prog_if: None,
476 });
477
478 for pci_dev in candidates.into_iter() {
479 if pci_dev.device_id != 0x2000 && pci_dev.device_id != 0x2001 {
480 continue;
481 }
482
483 log::info!(
484 "PCnet: Found device at {:?} (VEN:{:04x} DEV:{:04x})",
485 pci_dev.address,
486 pci_dev.vendor_id,
487 pci_dev.device_id
488 );
489
490 pci_dev.enable_bus_master();
491
492 match unsafe { PcnetDevice::new(pci_dev) } {
493 Ok(device) => {
494 let arc = Arc::new(device);
495 PCNET_DEVICES.lock().push(arc.clone());
496 let _iface = crate::hardware::nic::register_device(arc);
497 }
498 Err(e) => {
499 log::warn!("PCnet: Failed to initialize device: {}", e);
500 }
501 }
502 }
503
504 log::info!("[PCnet] Found {} device(s)", PCNET_DEVICES.lock().len());
505}