strat9_kernel/hardware/nic/
e1000_drv.rs1use super::{
7 common::{probe_e1000_pci, KernelDma, KernelE1000Adapter},
8 register_device, set_nic_device,
9};
10use crate::{
11 arch::x86_64::{ioapic, msi},
12 hardware::pci_client as pci,
13 serial_println,
14};
15use e1000::E1000Nic;
16
17const LEGACY_E1000_IDS: &[u16] = &[pci::intel_eth::E1000_82540EM, pci::intel_eth::E1000_82545EM];
18
19pub fn init() {
20 let Some(probe) = probe_e1000_pci(LEGACY_E1000_IDS) else {
21 serial_println!("[E1000] no compatible device found");
22 return;
23 };
24
25 log::info!(
26 "E1000: PCI {:04x}:{:04x} at {:?}",
27 probe.pci_dev.vendor_id,
28 probe.pci_dev.device_id,
29 probe.pci_dev.address
30 );
31
32 let mut init_ok = None;
33 for attempt in 0..2 {
34 log::info!(
35 "E1000: init attempt {} mmio_phys={:#x} mmio_virt={:#x}",
36 attempt + 1,
37 probe.mmio_phys,
38 probe.mmio_virt
39 );
40 match E1000Nic::init(probe.mmio_virt, &KernelDma) {
41 Ok(nic) => {
42 log::info!("E1000: core init ok on attempt {}", attempt + 1);
43 init_ok = Some(nic);
44 break;
45 }
46 Err(e) => {
47 log::warn!("E1000: core init attempt {} failed: {}", attempt + 1, e);
48 if attempt == 0 {
49 let mut cmd_retry = probe.pci_dev.read_config_u16(pci::config::COMMAND);
50 cmd_retry |= pci::command::BUS_MASTER | pci::command::MEMORY_SPACE;
51 cmd_retry &= !pci::command::INTERRUPT_DISABLE;
52 probe
53 .pci_dev
54 .write_config_u16(pci::config::COMMAND, cmd_retry);
55 continue;
56 }
57 log::error!("E1000: init failed: {}", e);
58 }
59 }
60 }
61
62 if let Some(nic) = init_ok {
63 let mac = nic.mac_address();
64 serial_println!(
65 "[E1000] Device initialized: MAC {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
66 mac[0],
67 mac[1],
68 mac[2],
69 mac[3],
70 mac[4],
71 mac[5]
72 );
73 let dev = KernelE1000Adapter::new(nic, "e1000");
74 let iface = register_device(dev.clone());
75
76 let (irq, vector) = msi::probe_and_enable(&probe.pci_dev, false);
80
81 if irq == 0 || irq == 0xFF {
82 log::warn!(
83 "[E1000] {}: no valid IRQ line, running in polling mode",
84 iface
85 );
86 } else {
87 let cmd = probe.pci_dev.read_config_u16(pci::config::COMMAND);
90 let msi_active = (cmd & pci::command::INTERRUPT_DISABLE) != 0;
91
92 if !msi_active {
93 ioapic::route_nic_irq(irq, vector);
95 log::info!("[E1000] {}: INTx IRQ {} → vector {:#x}", iface, irq, vector);
96 } else {
97 log::info!("[E1000] {}: MSI active on vector {:#x}", iface, vector);
98 }
99
100 crate::arch::x86_64::idt::register_nic_irq(irq);
101 set_nic_device(dev, irq);
102 }
103 }
104}