⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/drivers/
e1000.rs

1//! Intel E1000 (82540EM) Network Driver
2//!
3//! This driver supports the Intel E1000 Gigabit Ethernet controller,
4//! commonly found in QEMU and VirtualBox virtual machines.
5
6// Intel E1000 driver
7
8use crate::{
9    error::KernelError,
10    net::{
11        device::{DeviceCapabilities, DeviceState, DeviceStatistics, NetworkDevice},
12        MacAddress, Packet,
13    },
14};
15
16/// E1000 PCI vendor and device IDs
17pub const E1000_VENDOR_ID: u16 = 0x8086;
18pub const E1000_DEVICE_ID: u16 = 0x100E;
19
20/// E1000 register offsets
21const REG_CTRL: usize = 0x0000; // Device Control
22#[allow(dead_code)] // E1000 hardware register per Intel spec
23const REG_STATUS: usize = 0x0008; // Device Status
24const REG_EEPROM: usize = 0x0014; // EEPROM Read
25#[allow(dead_code)] // E1000 hardware register per Intel spec
26const REG_CTRL_EXT: usize = 0x0018; // Extended Device Control
27const REG_ICR: usize = 0x00C0; // Interrupt Cause Read
28const REG_IMS: usize = 0x00D0; // Interrupt Mask Set
29const REG_RCTL: usize = 0x0100; // Receive Control
30const REG_TCTL: usize = 0x0400; // Transmit Control
31const REG_RDBAL: usize = 0x2800; // RX Descriptor Base Low
32const REG_RDBAH: usize = 0x2804; // RX Descriptor Base High
33const REG_RDLEN: usize = 0x2808; // RX Descriptor Length
34const REG_RDH: usize = 0x2810; // RX Descriptor Head
35const REG_RDT: usize = 0x2818; // RX Descriptor Tail
36const REG_TDBAL: usize = 0x3800; // TX Descriptor Base Low
37const REG_TDBAH: usize = 0x3804; // TX Descriptor Base High
38const REG_TDLEN: usize = 0x3808; // TX Descriptor Length
39const REG_TDH: usize = 0x3810; // TX Descriptor Head
40const REG_TDT: usize = 0x3818; // TX Descriptor Tail
41const REG_MTA: usize = 0x5200; // Multicast Table Array
42
43/// Number of RX/TX descriptors
44const NUM_RX_DESC: usize = 32;
45const NUM_TX_DESC: usize = 8;
46
47/// Receive Descriptor
48#[repr(C)]
49#[derive(Debug, Clone, Copy)]
50struct RxDescriptor {
51    addr: u64,
52    length: u16,
53    checksum: u16,
54    status: u8,
55    errors: u8,
56    special: u16,
57}
58
59/// Transmit Descriptor
60#[repr(C)]
61#[derive(Debug, Clone, Copy)]
62struct TxDescriptor {
63    addr: u64,
64    length: u16,
65    cso: u8,
66    cmd: u8,
67    status: u8,
68    css: u8,
69    special: u16,
70}
71
72/// E1000 Driver State
73pub struct E1000Driver {
74    mmio_base: usize,
75    mac_address: MacAddress,
76    rx_descriptors: [RxDescriptor; NUM_RX_DESC],
77    tx_descriptors: [TxDescriptor; NUM_TX_DESC],
78    rx_buffers: [[u8; 2048]; NUM_RX_DESC],
79    tx_buffers: [[u8; 2048]; NUM_TX_DESC],
80    rx_current: usize,
81    tx_current: usize,
82    state: DeviceState,
83    stats: DeviceStatistics,
84}
85
86impl E1000Driver {
87    /// Create a new E1000 driver instance
88    pub fn new(mmio_base: usize) -> Result<Self, KernelError> {
89        let mut driver = Self {
90            mmio_base,
91            mac_address: MacAddress::ZERO,
92            rx_descriptors: [RxDescriptor {
93                addr: 0,
94                length: 0,
95                checksum: 0,
96                status: 0,
97                errors: 0,
98                special: 0,
99            }; NUM_RX_DESC],
100            tx_descriptors: [TxDescriptor {
101                addr: 0,
102                length: 0,
103                cso: 0,
104                cmd: 0,
105                status: 0,
106                css: 0,
107                special: 0,
108            }; NUM_TX_DESC],
109            rx_buffers: [[0u8; 2048]; NUM_RX_DESC],
110            tx_buffers: [[0u8; 2048]; NUM_TX_DESC],
111            rx_current: 0,
112            tx_current: 0,
113            state: DeviceState::Down,
114            stats: DeviceStatistics::default(),
115        };
116
117        driver.initialize()?;
118        Ok(driver)
119    }
120
121    /// Read from MMIO register
122    fn read_reg(&self, offset: usize) -> u32 {
123        // SAFETY: Reading an E1000 MMIO register at mmio_base + offset. The mmio_base
124        // is the controller's BAR0 address from PCI configuration. read_volatile
125        // prevents the compiler from eliding or reordering this hardware register
126        // access.
127        unsafe { core::ptr::read_volatile((self.mmio_base + offset) as *const u32) }
128    }
129
130    /// Write to MMIO register
131    fn write_reg(&self, offset: usize, value: u32) {
132        // SAFETY: Writing an E1000 MMIO register. Same invariants as read_reg.
133        unsafe {
134            core::ptr::write_volatile((self.mmio_base + offset) as *mut u32, value);
135        }
136    }
137
138    /// Read MAC address from EEPROM
139    fn read_mac_address(&mut self) -> MacAddress {
140        let mut mac = [0u8; 6];
141
142        // Read from EEPROM words 0-2
143        for i in 0usize..3 {
144            let word = self.eeprom_read(i as u8);
145            mac[i * 2] = (word & 0xFF) as u8;
146            mac[i * 2 + 1] = (word >> 8) as u8;
147        }
148
149        MacAddress(mac)
150    }
151
152    /// Read from EEPROM
153    fn eeprom_read(&self, addr: u8) -> u16 {
154        self.write_reg(REG_EEPROM, 1 | ((addr as u32) << 8));
155
156        // Wait for read to complete
157        let mut result: u32;
158        loop {
159            result = self.read_reg(REG_EEPROM);
160            if (result & (1 << 4)) != 0 {
161                break;
162            }
163        }
164
165        ((result >> 16) & 0xFFFF) as u16
166    }
167
168    /// Initialize the E1000 device
169    fn initialize(&mut self) -> Result<(), KernelError> {
170        // Read MAC address
171        self.mac_address = self.read_mac_address();
172
173        // Enable bus mastering and memory access
174        // (Would normally be done via PCI configuration space)
175
176        // Reset the device
177        self.write_reg(REG_CTRL, self.read_reg(REG_CTRL) | 0x04000000);
178
179        // Wait for reset
180        for _ in 0..1000 {
181            if (self.read_reg(REG_CTRL) & 0x04000000) == 0 {
182                break;
183            }
184        }
185
186        // Disable interrupts
187        self.write_reg(REG_IMS, 0);
188        self.read_reg(REG_ICR); // Clear pending interrupts
189
190        // Initialize RX descriptors
191        for i in 0..NUM_RX_DESC {
192            self.rx_descriptors[i].addr = &self.rx_buffers[i] as *const _ as u64;
193            self.rx_descriptors[i].status = 0;
194        }
195
196        // Initialize TX descriptors
197        for i in 0..NUM_TX_DESC {
198            self.tx_descriptors[i].addr = &self.tx_buffers[i] as *const _ as u64;
199            self.tx_descriptors[i].status = 1; // DD bit set
200            self.tx_descriptors[i].cmd = 0;
201        }
202
203        // Set up RX ring
204        let rx_desc_addr = &self.rx_descriptors as *const _ as u64;
205        self.write_reg(REG_RDBAL, (rx_desc_addr & 0xFFFFFFFF) as u32);
206        self.write_reg(REG_RDBAH, (rx_desc_addr >> 32) as u32);
207        self.write_reg(REG_RDLEN, (NUM_RX_DESC * 16) as u32);
208        self.write_reg(REG_RDH, 0);
209        self.write_reg(REG_RDT, (NUM_RX_DESC - 1) as u32);
210
211        // Set up TX ring
212        let tx_desc_addr = &self.tx_descriptors as *const _ as u64;
213        self.write_reg(REG_TDBAL, (tx_desc_addr & 0xFFFFFFFF) as u32);
214        self.write_reg(REG_TDBAH, (tx_desc_addr >> 32) as u32);
215        self.write_reg(REG_TDLEN, (NUM_TX_DESC * 16) as u32);
216        self.write_reg(REG_TDH, 0);
217        self.write_reg(REG_TDT, 0);
218
219        // Enable receiver
220        self.write_reg(REG_RCTL, (1 << 1) | (1 << 2) | (1 << 15));
221
222        // Enable transmitter
223        self.write_reg(REG_TCTL, (1 << 1) | (1 << 3) | (0x10 << 4));
224
225        // Clear multicast table
226        for i in 0..128 {
227            self.write_reg(REG_MTA + i * 4, 0);
228        }
229
230        println!(
231            "[E1000] Initialized with MAC: {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
232            self.mac_address.0[0],
233            self.mac_address.0[1],
234            self.mac_address.0[2],
235            self.mac_address.0[3],
236            self.mac_address.0[4],
237            self.mac_address.0[5]
238        );
239
240        // Device is now up
241        self.state = DeviceState::Up;
242
243        Ok(())
244    }
245
246    /// Transmit a packet (raw implementation)
247    fn transmit_raw(&mut self, packet: &[u8]) -> Result<(), KernelError> {
248        if packet.len() > 2048 {
249            return Err(KernelError::InvalidArgument {
250                name: "packet_size",
251                value: "too_large",
252            });
253        }
254
255        let idx = self.tx_current;
256        let desc = &mut self.tx_descriptors[idx];
257
258        // Wait for descriptor to be available
259        if (desc.status & 1) == 0 {
260            self.stats.tx_dropped += 1;
261            return Err(KernelError::WouldBlock);
262        }
263
264        // Copy packet to TX buffer
265        self.tx_buffers[idx][..packet.len()].copy_from_slice(packet);
266
267        // Set up descriptor
268        desc.length = packet.len() as u16;
269        desc.cmd = (1 << 0) | (1 << 1) | (1 << 3); // EOP | IFCS | RS
270        desc.status = 0;
271
272        // Update tail pointer
273        self.tx_current = (self.tx_current + 1) % NUM_TX_DESC;
274        self.write_reg(REG_TDT, self.tx_current as u32);
275
276        // Update statistics
277        self.stats.tx_packets += 1;
278        self.stats.tx_bytes += packet.len() as u64;
279
280        Ok(())
281    }
282
283    /// Receive a packet (raw implementation)
284    fn receive_raw(&mut self) -> Result<Option<Packet>, KernelError> {
285        let idx = self.rx_current;
286        let desc = &mut self.rx_descriptors[idx];
287
288        // Check if packet is available
289        if (desc.status & 1) == 0 {
290            return Ok(None);
291        }
292
293        // Check for errors
294        if desc.errors != 0 {
295            self.stats.rx_errors += 1;
296            // Reset descriptor
297            desc.status = 0;
298            self.rx_current = (self.rx_current + 1) % NUM_RX_DESC;
299            self.write_reg(REG_RDT, self.rx_current as u32);
300            return Ok(None);
301        }
302
303        // Get packet data
304        let len = desc.length as usize;
305        let data = self.rx_buffers[idx][..len].to_vec();
306        let packet = Packet::from_bytes(&data);
307
308        // Update statistics
309        self.stats.rx_packets += 1;
310        self.stats.rx_bytes += len as u64;
311
312        // Reset descriptor
313        desc.status = 0;
314
315        // Update tail pointer
316        self.rx_current = (self.rx_current + 1) % NUM_RX_DESC;
317        self.write_reg(REG_RDT, self.rx_current as u32);
318
319        Ok(Some(packet))
320    }
321
322    /// Get MAC address
323    pub fn mac_address(&self) -> MacAddress {
324        self.mac_address
325    }
326}
327
328// DeviceDriver trait implementation removed - using NetworkDevice trait instead
329
330impl NetworkDevice for E1000Driver {
331    fn name(&self) -> &str {
332        "eth0"
333    }
334
335    fn mac_address(&self) -> MacAddress {
336        self.mac_address
337    }
338
339    fn capabilities(&self) -> DeviceCapabilities {
340        DeviceCapabilities {
341            max_transmission_unit: 1500,
342            supports_vlan: false,
343            supports_checksum_offload: true,
344            supports_tso: false,
345            supports_lro: false,
346        }
347    }
348
349    fn state(&self) -> DeviceState {
350        self.state
351    }
352
353    fn set_state(&mut self, state: DeviceState) -> Result<(), KernelError> {
354        match state {
355            DeviceState::Up => {
356                if self.state == DeviceState::Down {
357                    // Re-enable RX and TX
358                    self.write_reg(REG_RCTL, (1 << 1) | (1 << 2) | (1 << 15));
359                    self.write_reg(REG_TCTL, (1 << 1) | (1 << 3) | (0x10 << 4));
360                }
361                self.state = DeviceState::Up;
362            }
363            DeviceState::Down => {
364                // Disable RX and TX
365                self.write_reg(REG_RCTL, 0);
366                self.write_reg(REG_TCTL, 0);
367                self.state = DeviceState::Down;
368            }
369            _ => {
370                self.state = state;
371            }
372        }
373        Ok(())
374    }
375
376    fn statistics(&self) -> DeviceStatistics {
377        self.stats
378    }
379
380    fn transmit(&mut self, packet: &Packet) -> Result<(), KernelError> {
381        if self.state != DeviceState::Up {
382            self.stats.tx_dropped += 1;
383            return Err(KernelError::InvalidState {
384                expected: "up",
385                actual: "not_up",
386            });
387        }
388
389        self.transmit_raw(packet.data())
390    }
391
392    fn receive(&mut self) -> Result<Option<Packet>, KernelError> {
393        if self.state != DeviceState::Up {
394            return Ok(None);
395        }
396
397        self.receive_raw()
398    }
399}
400
401/// Initialize E1000 driver
402pub fn init() -> Result<(), KernelError> {
403    println!("[E1000] Intel E1000 network driver module loaded");
404    Ok(())
405}
406
407#[cfg(test)]
408mod tests {
409    use super::*;
410
411    #[test]
412    fn test_e1000_constants() {
413        assert_eq!(E1000_VENDOR_ID, 0x8086);
414        assert_eq!(E1000_DEVICE_ID, 0x100E);
415        assert_eq!(NUM_RX_DESC, 32);
416        assert_eq!(NUM_TX_DESC, 8);
417    }
418}