strat9_kernel/hardware/nic/
rtl8139_drv.rs1use crate::{
5 hardware::{
6 nic::NetworkDevice,
7 pci_client::{self as pci, Bar, ProbeCriteria},
8 },
9 memory::{allocate_zeroed_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 RX_BUFFER_SIZE: usize = 8192;
18const RX_BUFFER_PAD: usize = 16;
19const TX_BUFFER_SIZE: usize = 2048;
20const TX_BUFFERS_COUNT: usize = 4;
21const MTU: usize = 1536;
22
23const CR_RST: u8 = 1 << 4;
24const CR_RE: u8 = 1 << 3;
25const CR_TE: u8 = 1 << 2;
26const CR_BUFE: u8 = 1 << 0;
27
28const RCR_WRAP: u32 = 1 << 7;
29const RCR_AB: u32 = 1 << 3;
30const RCR_AM: u32 = 1 << 2;
31const RCR_APM: u32 = 1 << 1;
32const RCR_AAP: u32 = 1 << 0;
33const RCR_RBLEN: u32 = 0 << 11;
34
35const TCR_IFG: u32 = 3 << 24;
36const TCR_MXDMA: u32 = 7 << 8;
37
38const ISR_ROK: u16 = 1 << 0;
39const ISR_TOK: u16 = 1 << 2;
40
41#[allow(dead_code)]
42const TOK: u32 = 1 << 15;
43const OWN: u32 = 1 << 13;
44
45struct Ports {
46 io_base: u16,
47}
48
49impl Ports {
50 fn new(io_base: u16) -> Self {
52 Self { io_base }
53 }
54
55 #[inline]
57 fn read8(&self, offset: u16) -> u8 {
58 unsafe {
59 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).read()
60 }
61 }
62
63 #[inline]
65 fn write8(&mut self, offset: u16, value: u8) {
66 unsafe {
67 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).write(value)
68 }
69 }
70
71 #[inline]
73 #[allow(dead_code)]
74 fn read16(&self, offset: u16) -> u16 {
75 unsafe {
76 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).read()
77 }
78 }
79
80 #[inline]
82 fn write16(&mut self, offset: u16, value: u16) {
83 unsafe {
84 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).write(value)
85 }
86 }
87
88 #[inline]
90 fn read32(&self, offset: u16) -> u32 {
91 unsafe {
92 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).read()
93 }
94 }
95
96 #[inline]
98 fn write32(&mut self, offset: u16, value: u32) {
99 unsafe {
100 crate::x86_crate_shim::instructions::port::Port::new(self.io_base + offset).write(value)
101 }
102 }
103
104 fn mac(&mut self) -> [u8; 6] {
106 [
107 self.read8(0x00),
108 self.read8(0x01),
109 self.read8(0x02),
110 self.read8(0x03),
111 self.read8(0x04),
112 self.read8(0x05),
113 ]
114 }
115}
116
117pub struct Rtl8139Device {
118 ports: Mutex<Ports>,
119 rx_buffer: *mut u8,
120 rx_phys: u64,
121 rx_offset: AtomicUsize,
122 tx_buffers: [*mut u8; TX_BUFFERS_COUNT],
123 tx_phys: [u64; TX_BUFFERS_COUNT],
124 tx_id: AtomicUsize,
125 mac: [u8; 6],
126 name: String,
127}
128
129unsafe impl Send for Rtl8139Device {}
130unsafe impl Sync for Rtl8139Device {}
131
132impl Rtl8139Device {
133 pub unsafe fn new(pci_dev: pci::PciDevice) -> Result<Self, &'static str> {
135 let io_base = match pci_dev.read_bar(0) {
136 Some(Bar::Io { port }) => port as u16,
137 _ => return Err("Invalid BAR"),
138 };
139
140 let mut ports = Ports::new(io_base);
141 let mac = ports.mac();
142 let name = format!("rtl8139_{:02x}{:02x}{:02x}", mac[3], mac[4], mac[5]);
143
144 let rx_frame = allocate_zeroed_frame().ok_or("Failed to allocate RX buffer")?;
145 let rx_phys = rx_frame.start_address.as_u64();
146 let rx_buffer = phys_to_virt(rx_phys) as *mut u8;
147 core::ptr::write_bytes(rx_buffer, 0, RX_BUFFER_SIZE + RX_BUFFER_PAD + MTU);
148
149 let mut tx_buffers = [core::ptr::null_mut(); TX_BUFFERS_COUNT];
150 let mut tx_phys = [0u64; TX_BUFFERS_COUNT];
151 for i in 0..TX_BUFFERS_COUNT {
152 let frame = allocate_zeroed_frame().ok_or("Failed to allocate TX buffer")?;
153 tx_phys[i] = frame.start_address.as_u64();
154 tx_buffers[i] = phys_to_virt(tx_phys[i]) as *mut u8;
155 core::ptr::write_bytes(tx_buffers[i], 0, TX_BUFFER_SIZE);
156 }
157
158 let mut device = Self {
159 ports: Mutex::new(ports),
160 rx_buffer,
161 rx_phys,
162 rx_offset: AtomicUsize::new(0),
163 tx_buffers,
164 tx_phys,
165 tx_id: AtomicUsize::new(TX_BUFFERS_COUNT - 1),
166 mac,
167 name,
168 };
169
170 device.init();
171 Ok(device)
172 }
173
174 fn init(&mut self) {
176 let mut ports = self.ports.lock();
177
178 ports.write8(0x37, CR_RST);
179 core::hint::spin_loop();
180
181 for _ in 0..1000 {
182 if (ports.read8(0x37) & CR_RST) == 0 {
183 break;
184 }
185 core::hint::spin_loop();
186 }
187
188 ports.write32(
189 0x44,
190 RCR_WRAP | RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_RBLEN,
191 );
192 ports.write32(0x40, TCR_IFG | TCR_MXDMA);
193 ports.write32(0x30, self.rx_phys as u32);
194
195 for i in 0..TX_BUFFERS_COUNT {
196 ports.write32(0x20 + (i as u16) * 4, self.tx_phys[i] as u32);
197 }
198
199 ports.write16(0x3C, ISR_ROK | ISR_TOK);
200 ports.write8(0x37, CR_RE | CR_TE | CR_BUFE);
201
202 log::info!(
203 "RTL8139: MAC {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
204 self.mac[0],
205 self.mac[1],
206 self.mac[2],
207 self.mac[3],
208 self.mac[4],
209 self.mac[5]
210 );
211 }
212
213 #[allow(dead_code)]
215 fn receive_packet(&self) -> Option<Vec<u8>> {
216 self.receive_inner()
217 }
218
219 #[allow(dead_code)]
221 fn transmit_packet(&self, data: &[u8]) -> Result<(), NetError> {
222 self.transmit_inner(data)
223 }
224
225 fn receive_inner(&self) -> Option<Vec<u8>> {
227 let mut ports = self.ports.lock();
228 let rx_offset = self.rx_offset.load(Ordering::Relaxed);
229
230 let status = unsafe { (self.rx_buffer.add(rx_offset) as *const u32).read_volatile() };
231
232 if (status & OWN) != 0 {
233 return None;
234 }
235
236 if (status & 0x0001) != 0 {
237 let length = ((status >> 16) & 0x1FFF) as usize - 4;
238 if length <= MTU {
239 let packet_start = unsafe { self.rx_buffer.add(rx_offset + 4) };
240 let mut buf = Vec::with_capacity(length);
241 unsafe {
242 core::ptr::copy_nonoverlapping(packet_start, buf.as_mut_ptr(), length);
243 buf.set_len(length);
244 }
245
246 let new_offset = ((rx_offset + length + 4 + RX_BUFFER_PAD) & !(RX_BUFFER_PAD - 1))
247 % RX_BUFFER_SIZE;
248 self.rx_offset.store(new_offset, Ordering::Relaxed);
249 ports.write16(0x38, (new_offset - RX_BUFFER_PAD) as u16);
250
251 return Some(buf);
252 }
253 }
254
255 ports.write8(0x37, CR_RE | CR_TE);
256 self.rx_offset.store(0, Ordering::Relaxed);
257 None
258 }
259
260 fn transmit_inner(&self, data: &[u8]) -> Result<(), NetError> {
262 if data.len() > MTU {
263 return Err(NetError::BufferTooSmall);
264 }
265
266 let id = self.tx_id.fetch_add(1, Ordering::SeqCst) % TX_BUFFERS_COUNT;
267 let mut ports = self.ports.lock();
268
269 let tx_status = ports.read32(0x10 + (id as u16) * 4);
270 if (tx_status & OWN) == 0 {
271 let mut timeout = 10000;
272 while (ports.read32(0x10 + (id as u16) * 4) & OWN) == 0 {
273 core::hint::spin_loop();
274 timeout -= 1;
275 if timeout == 0 {
276 return Err(NetError::NotReady);
277 }
278 }
279 }
280
281 unsafe {
282 core::ptr::copy_nonoverlapping(data.as_ptr(), self.tx_buffers[id], data.len());
283 }
284
285 ports.write32(0x10 + (id as u16) * 4, data.len() as u32);
286
287 Ok(())
288 }
289}
290
291impl NetworkDevice for Rtl8139Device {
292 fn name(&self) -> &str {
294 &self.name
295 }
296
297 fn mac_address(&self) -> [u8; 6] {
299 self.mac
300 }
301
302 fn link_up(&self) -> bool {
304 let ports = self.ports.lock();
305 (ports.read8(0x58) & 0x80) != 0
306 }
307
308 fn receive(&self, buf: &mut [u8]) -> Result<usize, NetError> {
310 if let Some(packet) = self.receive_inner() {
311 let len = core::cmp::min(packet.len(), buf.len());
312 buf[..len].copy_from_slice(&packet[..len]);
313 Ok(len)
314 } else {
315 Err(NetError::NoPacket)
316 }
317 }
318
319 fn transmit(&self, data: &[u8]) -> Result<(), NetError> {
321 self.transmit_inner(data)
322 }
323}
324
325static RTL8139_DEVICES: Mutex<Vec<Arc<Rtl8139Device>>> = Mutex::new(Vec::new());
326
327pub fn init() {
329 log::info!("[RTL8139] Scanning for RTL8139 devices...");
330
331 let candidates = pci::probe_all(ProbeCriteria {
332 vendor_id: Some(0x10EC),
333 device_id: None,
334 class_code: Some(pci::class::NETWORK),
335 subclass: Some(pci::net_subclass::ETHERNET),
336 prog_if: None,
337 });
338
339 for pci_dev in candidates.into_iter() {
340 if pci_dev.device_id != 0x8139 {
341 continue;
342 }
343
344 log::info!(
345 "RTL8139: Found device at {:?} (VEN:{:04x} DEV:{:04x})",
346 pci_dev.address,
347 pci_dev.vendor_id,
348 pci_dev.device_id
349 );
350
351 pci_dev.enable_bus_master();
352
353 match unsafe { Rtl8139Device::new(pci_dev) } {
354 Ok(device) => {
355 let arc = Arc::new(device);
356 RTL8139_DEVICES.lock().push(arc.clone());
357 let _iface = crate::hardware::nic::register_device(arc);
358 }
359 Err(e) => {
360 log::warn!("RTL8139: Failed to initialize device: {}", e);
361 }
362 }
363 }
364
365 log::info!("[RTL8139] Found {} device(s)", RTL8139_DEVICES.lock().len());
366}