strat9_kernel/hardware/nic/
common.rs1use crate::{
8 arch::xshim::VirtAddr,
9 hardware::pci_client::{self as pci, Bar, PciDevice},
10 memory::{self},
11 sync::SpinLock,
12};
13use alloc::sync::Arc;
14use e1000::E1000Nic;
15use net_core::{NetError, NetworkDevice};
16use nic_buffers::{DmaAllocator, DmaRegion};
17
18pub struct KernelDma;
20
21impl DmaAllocator for KernelDma {
22 fn alloc_dma(&self, size: usize) -> Result<DmaRegion, nic_buffers::DmaAllocError> {
24 let pages = (size + 4095) / 4096;
25 let order = pages.next_power_of_two().trailing_zeros() as u8;
26 let frame = crate::sync::with_irqs_disabled(|token| {
27 crate::memory::allocate_phys_contiguous(token, order)
28 })
29 .map_err(|_| nic_buffers::DmaAllocError)?;
30 let phys = frame.start_address.as_u64();
31 let virt = memory::phys_to_virt(phys) as *mut u8;
32 Ok(DmaRegion {
33 phys,
34 virt,
35 size: pages * 4096,
36 })
37 }
38
39 unsafe fn free_dma(&self, region: DmaRegion) {
46 let pages = (region.size + 4095) / 4096;
47 let order = pages.next_power_of_two().trailing_zeros() as u8;
48 let frame = crate::memory::PhysFrame::containing_address(
49 crate::arch::xshim::PhysAddr::new(region.phys),
50 );
51 crate::sync::with_irqs_disabled(|token| {
52 crate::memory::free_phys_contiguous(token, frame, order);
53 });
54 }
55}
56
57pub struct ProbeResult {
59 pub pci_dev: PciDevice,
61 pub mmio_virt: u64,
63 pub mmio_phys: u64,
65}
66
67pub fn probe_e1000_pci(device_ids: &[u16]) -> Option<ProbeResult> {
76 if !memory::paging::is_initialized() {
77 log::warn!("e1000-family: paging not initialized, deferring probe");
78 return None;
79 }
80
81 let candidates = pci::probe_all(pci::ProbeCriteria {
82 vendor_id: Some(pci::vendor::INTEL),
83 device_id: None,
84 class_code: Some(pci::class::NETWORK),
85 subclass: None,
86 prog_if: None,
87 });
88
89 for pci_dev in candidates.into_iter() {
90 if pci_dev.subclass != pci::net_subclass::ETHERNET
91 && pci_dev.subclass != pci::net_subclass::OTHER
92 {
93 continue;
94 }
95 if !device_ids.contains(&pci_dev.device_id) {
96 continue;
97 }
98
99 log::info!(
100 "e1000-family: PCI {:04x}:{:04x} at {:?}",
101 pci_dev.vendor_id,
102 pci_dev.device_id,
103 pci_dev.address
104 );
105
106 pci_dev.enable_bus_master();
107 pci_dev.enable_memory_space();
108 let mut cmd = pci_dev.read_config_u16(pci::config::COMMAND);
109 cmd &= !pci::command::INTERRUPT_DISABLE;
110 pci_dev.write_config_u16(pci::config::COMMAND, cmd);
111
112 let mmio_phys = match pci_dev.read_bar(0).or_else(|| pci_dev.read_bar(1)) {
113 Some(Bar::Memory32 { addr, .. }) => addr as u64,
114 Some(Bar::Memory64 { addr, .. }) => addr,
115 _ => {
116 log::error!(
117 "e1000-family: no MMIO BAR (BAR0/BAR1) for {:04x}:{:04x}",
118 pci_dev.vendor_id,
119 pci_dev.device_id
120 );
121 continue;
122 }
123 };
124
125 memory::paging::ensure_identity_map_range(mmio_phys, 0x2_0000);
126 let mmio_virt = memory::phys_to_virt(mmio_phys);
127 let mmio_page_phys = mmio_phys & !0xFFF;
128 let mmio_page_virt = mmio_virt & !0xFFF;
129 let mapped = memory::paging::translate(VirtAddr::new(mmio_page_virt))
130 .map(|p| p.as_u64())
131 .unwrap_or(0);
132 if mapped != mmio_page_phys {
133 log::error!(
134 "e1000-family: MMIO not mapped for {:04x}:{:04x} phys={:#x} virt={:#x} mapped={:#x}",
135 pci_dev.vendor_id,
136 pci_dev.device_id,
137 mmio_phys,
138 mmio_virt,
139 mapped
140 );
141 continue;
142 }
143
144 return Some(ProbeResult {
145 pci_dev,
146 mmio_virt,
147 mmio_phys,
148 });
149 }
150
151 None
152}
153
154pub struct KernelE1000Adapter {
164 inner: SpinLock<E1000Nic>,
165 mac: [u8; 6],
166 name: &'static str,
167}
168
169impl KernelE1000Adapter {
170 pub fn new(nic: E1000Nic, driver_name: &'static str) -> Arc<Self> {
172 let mac = nic.mac_address();
173 Arc::new(Self {
174 inner: SpinLock::new(nic),
175 mac,
176 name: driver_name,
177 })
178 }
179}
180
181impl NetworkDevice for KernelE1000Adapter {
182 fn name(&self) -> &str {
183 self.name
184 }
185
186 fn mac_address(&self) -> [u8; 6] {
187 self.mac
188 }
189
190 fn link_up(&self) -> bool {
191 self.inner.lock().link_up()
192 }
193
194 fn receive(&self, buf: &mut [u8]) -> Result<usize, NetError> {
195 self.inner.lock().receive(buf)
196 }
197
198 fn transmit(&self, buf: &[u8]) -> Result<(), NetError> {
199 self.inner.lock().transmit(buf)
200 }
201
202 fn handle_interrupt(&self) {
203 let _icr = self.inner.lock().handle_interrupt();
204 }
205
206 fn poll(&self) {
207 let mut nic = self.inner.lock();
208 nic.watchdog_tick(&KernelDma);
209 }
210}