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