|
5 | 5 |
|
6 | 6 | use core::sync::atomic::{AtomicBool, Ordering}; |
7 | 7 | use morpheus_display::console::TextConsole; |
8 | | -use morpheus_network::device::{NetworkDevice, UnifiedNetDevice}; |
9 | | -use morpheus_network::boot::{probe_and_create_driver, ProbeError, ProbeResult}; |
| 8 | + |
| 9 | +use crate::baremetal_ops::network; |
10 | 10 |
|
11 | 11 | // TYPES THAT CROSS THE BORDER |
12 | 12 |
|
@@ -51,199 +51,6 @@ static BAREMETAL_MODE: AtomicBool = AtomicBool::new(false); |
51 | 51 |
|
52 | 52 | static mut LIVE_CONSOLE: Option<TextConsole> = None; |
53 | 53 |
|
54 | | -// userspace-activated networking state. offline by default until requested. |
55 | | -static mut USER_NET_DRIVER: Option<UnifiedNetDevice> = None; |
56 | | -static mut USER_NET_DMA: Option<morpheus_network::dma::DmaRegion> = None; |
57 | | -static mut USER_NET_TSC_FREQ: u64 = 0; |
58 | | - |
59 | | -unsafe fn log_pci_network_candidates() { |
60 | | - let mut found = 0u32; |
61 | | - for bus in 0..=255u8 { |
62 | | - for dev in 0..32u8 { |
63 | | - for func in 0..8u8 { |
64 | | - let addr = morpheus_hwinit::PciAddr::new(bus, dev, func); |
65 | | - let vendor = morpheus_hwinit::pci_cfg_read16(addr, 0x00); |
66 | | - if vendor == 0xFFFF { |
67 | | - if func == 0 { |
68 | | - break; |
69 | | - } |
70 | | - continue; |
71 | | - } |
72 | | - |
73 | | - let class = morpheus_hwinit::pci_cfg_read8(addr, 0x0B); |
74 | | - let subclass = morpheus_hwinit::pci_cfg_read8(addr, 0x0A); |
75 | | - if class != 0x02 { |
76 | | - if func == 0 { |
77 | | - let header = morpheus_hwinit::pci_cfg_read8(addr, 0x0E); |
78 | | - if (header & 0x80) == 0 { |
79 | | - break; |
80 | | - } |
81 | | - } |
82 | | - continue; |
83 | | - } |
84 | | - |
85 | | - let device = morpheus_hwinit::pci_cfg_read16(addr, 0x02); |
86 | | - found = found.wrapping_add(1); |
87 | | - morpheus_hwinit::serial::puts("[INFO] [NET] pci net candidate bdf="); |
88 | | - morpheus_hwinit::serial::put_hex64(((bus as u64) << 16) | ((dev as u64) << 8) | func as u64); |
89 | | - morpheus_hwinit::serial::puts(" ven="); |
90 | | - morpheus_hwinit::serial::put_hex64(vendor as u64); |
91 | | - morpheus_hwinit::serial::puts(" dev="); |
92 | | - morpheus_hwinit::serial::put_hex64(device as u64); |
93 | | - morpheus_hwinit::serial::puts(" sub="); |
94 | | - morpheus_hwinit::serial::put_hex64(subclass as u64); |
95 | | - morpheus_hwinit::serial::puts("\n"); |
96 | | - |
97 | | - if func == 0 { |
98 | | - let header = morpheus_hwinit::pci_cfg_read8(addr, 0x0E); |
99 | | - if (header & 0x80) == 0 { |
100 | | - break; |
101 | | - } |
102 | | - } |
103 | | - } |
104 | | - } |
105 | | - } |
106 | | - |
107 | | - if found == 0 { |
108 | | - morpheus_hwinit::serial::log_warn("NET", 953, "pci scan found zero class-0x02 devices"); |
109 | | - } else { |
110 | | - morpheus_hwinit::serial::log_info("NET", 954, "pci net candidates logged"); |
111 | | - } |
112 | | -} |
113 | | - |
114 | | -#[inline] |
115 | | -unsafe fn user_net_driver_mut() -> Option<&'static mut UnifiedNetDevice> { |
116 | | - USER_NET_DRIVER.as_mut() |
117 | | -} |
118 | | - |
119 | | -unsafe fn user_net_tx(frame: *const u8, len: usize) -> i64 { |
120 | | - let Some(driver) = user_net_driver_mut() else { |
121 | | - return -1; |
122 | | - }; |
123 | | - let frame = core::slice::from_raw_parts(frame, len); |
124 | | - if driver.transmit(frame).is_ok() { |
125 | | - 0 |
126 | | - } else { |
127 | | - -1 |
128 | | - } |
129 | | -} |
130 | | - |
131 | | -unsafe fn user_net_rx(buf: *mut u8, buf_len: usize) -> i64 { |
132 | | - let Some(driver) = user_net_driver_mut() else { |
133 | | - return -1; |
134 | | - }; |
135 | | - let buf = core::slice::from_raw_parts_mut(buf, buf_len); |
136 | | - match driver.receive(buf) { |
137 | | - Ok(Some(n)) => n as i64, |
138 | | - Ok(None) => 0, |
139 | | - Err(_) => -1, |
140 | | - } |
141 | | -} |
142 | | - |
143 | | -unsafe fn user_net_link_up() -> i64 { |
144 | | - let Some(driver) = user_net_driver_mut() else { |
145 | | - return 0; |
146 | | - }; |
147 | | - driver.link_up() as i64 |
148 | | -} |
149 | | - |
150 | | -unsafe fn user_net_mac(out: *mut u8) -> i64 { |
151 | | - let Some(driver) = user_net_driver_mut() else { |
152 | | - return -1; |
153 | | - }; |
154 | | - let mac = driver.mac_address(); |
155 | | - core::ptr::copy_nonoverlapping(mac.as_ptr(), out, 6); |
156 | | - 0 |
157 | | -} |
158 | | - |
159 | | -unsafe fn user_net_refill() -> i64 { |
160 | | - let Some(driver) = user_net_driver_mut() else { |
161 | | - return -1; |
162 | | - }; |
163 | | - driver.refill_rx_queue(); |
164 | | - driver.collect_tx_completions(); |
165 | | - 0 |
166 | | -} |
167 | | - |
168 | | -unsafe fn user_net_ctrl(_cmd: u32, _arg: u64) -> i64 { |
169 | | - // full NIC control routing can be added later per-driver. |
170 | | - -1 |
171 | | -} |
172 | | - |
173 | | -unsafe fn activate_network_from_userspace() -> i64 { |
174 | | - morpheus_hwinit::serial::log_info("NET", 940, "userspace activation requested"); |
175 | | - |
176 | | - if USER_NET_DRIVER.is_some() { |
177 | | - morpheus_hwinit::serial::log_info("NET", 941, "already active"); |
178 | | - return 1; |
179 | | - } |
180 | | - |
181 | | - let Some(dma) = USER_NET_DMA.as_ref() else { |
182 | | - morpheus_hwinit::serial::log_error("NET", 942, "activation failed: dma unavailable"); |
183 | | - return -1; |
184 | | - }; |
185 | | - let tsc_freq = USER_NET_TSC_FREQ; |
186 | | - |
187 | | - morpheus_hwinit::serial::log_info("NET", 943, "probing NIC via network::probe_and_create_driver"); |
188 | | - let driver = match probe_and_create_driver(dma, tsc_freq) { |
189 | | - Ok(ProbeResult::VirtIO(v)) => { |
190 | | - morpheus_hwinit::serial::log_info("NET", 949, "probe selected virtio NIC"); |
191 | | - UnifiedNetDevice::VirtIO(v) |
192 | | - } |
193 | | - Ok(ProbeResult::Intel(i)) => { |
194 | | - morpheus_hwinit::serial::log_info("NET", 951, "probe selected intel NIC"); |
195 | | - UnifiedNetDevice::Intel(i) |
196 | | - } |
197 | | - Err(ProbeError::NoDevice) => { |
198 | | - morpheus_hwinit::serial::log_error("NET", 944, "probe failed: no supported NIC detected"); |
199 | | - log_pci_network_candidates(); |
200 | | - return -2; |
201 | | - } |
202 | | - Err(ProbeError::VirtioInitFailed) => { |
203 | | - morpheus_hwinit::serial::log_error("NET", 950, "virtio init failed"); |
204 | | - return -3; |
205 | | - } |
206 | | - Err(ProbeError::IntelInitFailed) => { |
207 | | - morpheus_hwinit::serial::log_error("NET", 952, "intel init failed"); |
208 | | - return -3; |
209 | | - } |
210 | | - Err(ProbeError::DeviceNotResponding) => { |
211 | | - morpheus_hwinit::serial::log_error("NET", 955, "nic mmio not responding"); |
212 | | - return -4; |
213 | | - } |
214 | | - Err(ProbeError::BarMappingFailed) => { |
215 | | - morpheus_hwinit::serial::log_error("NET", 956, "nic bar mapping failure"); |
216 | | - return -5; |
217 | | - } |
218 | | - }; |
219 | | - |
220 | | - morpheus_hwinit::serial::log_ok("NET", 945, "driver initialized"); |
221 | | - |
222 | | - USER_NET_DRIVER = Some(driver); |
223 | | - |
224 | | - morpheus_hwinit::serial::log_info("NET", 946, "registering NIC ops"); |
225 | | - morpheus_hwinit::register_nic(morpheus_hwinit::NicOps { |
226 | | - tx: Some(user_net_tx), |
227 | | - rx: Some(user_net_rx), |
228 | | - link_up: Some(user_net_link_up), |
229 | | - mac: Some(user_net_mac), |
230 | | - refill: Some(user_net_refill), |
231 | | - ctrl: Some(user_net_ctrl), |
232 | | - }); |
233 | | - |
234 | | - // prime descriptor maintenance immediately. |
235 | | - let _ = user_net_refill(); |
236 | | - |
237 | | - let link_now = user_net_link_up(); |
238 | | - if link_now != 0 { |
239 | | - morpheus_hwinit::serial::log_ok("NET", 947, "activation complete: link up"); |
240 | | - } else { |
241 | | - morpheus_hwinit::serial::log_info("NET", 948, "activation complete: link down"); |
242 | | - } |
243 | | - |
244 | | - 0 |
245 | | -} |
246 | | - |
247 | 54 | /// Called by the hwinit serial hook for every byte emitted via `puts()`. |
248 | 55 | /// Writes directly to the TextConsole backed by the GOP framebuffer. |
249 | 56 | pub unsafe fn live_console_putc(b: u8) { |
@@ -483,13 +290,11 @@ pub unsafe fn enter_baremetal(config: BaremetalEntryConfig) -> ! { |
483 | 290 | }; |
484 | 291 |
|
485 | 292 | // userspace network activation hook. we stay offline by default. |
486 | | - USER_NET_DMA = Some(morpheus_network::dma::DmaRegion::new( |
| 293 | + network::init_userspace_network_activation(morpheus_network::dma::DmaRegion::new( |
487 | 294 | platform.dma().cpu_base(), |
488 | 295 | platform.dma().bus_base(), |
489 | 296 | platform.dma().size(), |
490 | | - )); |
491 | | - USER_NET_TSC_FREQ = platform.tsc_freq(); |
492 | | - morpheus_hwinit::register_net_activation(activate_network_from_userspace); |
| 297 | + ), platform.tsc_freq()); |
493 | 298 |
|
494 | 299 | // persistent storage — try to mount a real block device |
495 | 300 | crate::storage::init_persistent_storage(platform.dma(), platform.tsc_freq()); |
|
0 commit comments