-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
294 lines (262 loc) · 11.3 KB
/
mod.rs
File metadata and controls
294 lines (262 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
//! Device drivers subsystem
//!
//! This module provides the driver infrastructure for Breenix, including
//! PCI enumeration and device-specific drivers.
#[cfg(target_arch = "aarch64")]
pub mod ahci;
pub mod e1000;
pub mod fw_cfg;
pub mod pci;
#[cfg(target_arch = "aarch64")]
pub mod usb;
pub mod virtio; // Now available on both x86_64 and aarch64
#[cfg(target_arch = "aarch64")]
pub mod vmware;
/// Initialize the driver subsystem
///
/// This enumerates devices and initializes any detected devices
/// that have drivers available.
///
/// Returns the number of devices found.
#[cfg(target_arch = "x86_64")]
pub fn init() -> usize {
log::info!("Initializing driver subsystem...");
// Enumerate PCI bus and detect devices
let device_count = pci::enumerate();
// Initialize VirtIO block driver if device was found
match virtio::block::init() {
Ok(()) => {
log::info!("VirtIO block driver initialized successfully");
// Enable VirtIO IRQ now that driver is initialized
// IMPORTANT: Must be done AFTER driver init, not during PIC init
crate::interrupts::enable_virtio_irq();
// Run a quick test
if let Err(e) = virtio::block::test_read() {
log::warn!("VirtIO block test failed: {}", e);
}
}
Err(e) => {
log::warn!("VirtIO block driver initialization failed: {}", e);
}
}
// Initialize E1000 network driver if device was found
match e1000::init() {
Ok(()) => {
log::info!("E1000 network driver initialized successfully");
// Enable E1000 IRQ now that driver is initialized
// E1000 uses IRQ 10 in QEMU's PCI configuration
crate::interrupts::enable_irq10();
}
Err(e) => {
log::warn!("E1000 network driver initialization failed: {}", e);
}
}
// Initialize VirtIO sound driver
match virtio::sound::init() {
Ok(()) => {
log::info!("VirtIO sound driver initialized successfully");
}
Err(e) => {
log::warn!("VirtIO sound driver initialization failed: {}", e);
}
}
log::info!("Driver subsystem initialized");
device_count
}
/// Initialize the driver subsystem (ARM64 version)
///
/// Detects the platform at runtime:
/// - If PCI ECAM is configured (Parallels/UEFI boot): enumerate PCI bus
/// - Otherwise (QEMU virt): enumerate VirtIO MMIO devices
#[cfg(target_arch = "aarch64")]
pub fn init() -> usize {
use crate::serial_println;
serial_println!("[drivers] Initializing driver subsystem...");
let ecam_base = crate::platform_config::pci_ecam_base();
if ecam_base != 0 {
// PCI-based platform (Parallels): enumerate PCI bus
serial_println!("[drivers] PCI ECAM at {:#x}, enumerating PCI bus...", ecam_base);
let device_count = pci::enumerate();
serial_println!("[drivers] Found {} PCI devices", device_count);
// Dump all PCI devices to serial for platform discovery
if let Some(devices) = pci::get_devices() {
for dev in &devices {
serial_println!("[pci] {:02x}:{:02x}.{} [{:04x}:{:04x}] class={:02x}/{:02x}",
dev.bus, dev.device, dev.function,
dev.vendor_id, dev.device_id,
dev.class as u8, dev.subclass);
for (i, bar) in dev.bars.iter().enumerate() {
if bar.is_valid() {
serial_println!("[pci] BAR{}: {:#x} ({})",
i, bar.address, bar.size);
}
}
}
}
// Enumerate VirtIO PCI devices with modern transport
let virtio_devices = virtio::pci_transport::enumerate_virtio_pci_devices();
serial_println!("[drivers] Found {} VirtIO PCI devices", virtio_devices.len());
match virtio::gpu_pci::init() {
Ok(()) => {
serial_println!("[drivers] VirtIO GPU (PCI) initialized");
// Attempt to initialize VirGL 3D acceleration if the device supports it
match virtio::gpu_pci::virgl_init() {
Ok(()) => {
serial_println!("[drivers] VirGL 3D acceleration active");
crate::graphics::set_compositor_backend(crate::graphics::CompositorBackend::VirGL);
serial_println!("[drivers] Compositor backend: VirGL");
// Enable yielding during GPU command waits now that init is complete.
// During runtime, GPU poll loops yield to the scheduler instead of
// spinning, letting other tasks run during ~3.4ms GPU processing.
virtio::gpu_pci::enable_gpu_yield();
}
Err(e) => serial_println!("[drivers] VirGL init skipped: {}", e),
}
}
Err(e) => serial_println!("[drivers] VirtIO GPU (PCI) init failed: {}", e),
}
// Initialize VirtIO network driver (PCI transport) — Parallels
match virtio::net_pci::init() {
Ok(()) => serial_println!("[drivers] VirtIO network (PCI) initialized"),
Err(e) => {
serial_println!("[drivers] VirtIO network (PCI) init failed: {}", e);
// No VirtIO net — try Intel e1000/e1000e (VMware Fusion)
match e1000::init() {
Ok(()) => serial_println!("[drivers] Intel e1000 network driver initialized"),
Err(e2) => serial_println!("[drivers] e1000 init also failed: {}", e2),
}
}
}
// Initialize VMware SVGA3 GPU if present (VMware Fusion on ARM64)
match vmware::svga3::init() {
Ok(()) => {
serial_println!("[drivers] VMware SVGA3 GPU initialized");
// SVGA3 with VRAM traces provides GPU-level compositing:
// BWM writes pixels to VRAM, device monitors and updates display.
crate::graphics::set_compositor_backend(crate::graphics::CompositorBackend::Svga3Stdu);
serial_println!("[drivers] Compositor backend: SVGA3 (VRAM traces)");
}
Err(e) => serial_println!("[drivers] SVGA3 init skipped: {}", e),
}
// EHCI USB 2.0 controller — initialization is handled inside xhci::init()
// as a prerequisite for Parallels USB device routing (companion controller model).
// Intel 82801FB EHCI: vendor 0x8086, device 0x265c at PCI 00:02.0
// Initialize XHCI USB host controller (keyboard + mouse)
// Find by class code (0x0C/0x03/0x30 = USB XHCI), then fall back to known device IDs.
// Parallels NEC uPD720200: 0x1033:0x0194, VMware: 0x15ad:0x077a
if let Some(xhci_dev) = pci::find_by_class(pci::DeviceClass::SerialBus, 0x03, 0x30)
.or_else(|| pci::find_device(0x1033, 0x0194))
.or_else(|| pci::find_device(0x15ad, 0x077a))
{
serial_println!("[drivers] Found XHCI at {:02x}:{:02x}.{} [{:04x}:{:04x}]",
xhci_dev.bus, xhci_dev.device, xhci_dev.function,
xhci_dev.vendor_id, xhci_dev.device_id);
#[cfg(feature = "xhci_linux_harness")]
let xhci_result = usb::xhci_linux::init(&xhci_dev);
#[cfg(not(feature = "xhci_linux_harness"))]
let xhci_result = usb::xhci::init(&xhci_dev);
match xhci_result {
Ok(()) => {
serial_println!("[drivers] XHCI USB controller initialized");
}
Err(e) => {
serial_println!("[drivers] XHCI USB init failed: {}", e);
}
}
} else {
serial_println!("[drivers] No XHCI USB controller found");
}
// Initialize AHCI storage driver.
// First try PCI (standard AHCI), then platform MMIO (Parallels Desktop).
match ahci::init() {
Ok(count) => {
serial_println!("[drivers] AHCI initialized (PCI): {} SATA device(s)", count);
}
Err(_) => {
// No PCI AHCI controller found. On Parallels Desktop, the SATA
// controller is an ACPI platform device at 0x0214_0000, not on PCI.
const PARALLELS_AHCI_BASE: u64 = 0x0214_0000;
match ahci::init_platform(PARALLELS_AHCI_BASE) {
Ok(count) => {
serial_println!("[drivers] AHCI initialized (platform MMIO): {} SATA device(s)", count);
}
Err(e) => {
serial_println!("[drivers] AHCI init skipped: {}", e);
}
}
}
}
serial_println!("[drivers] Driver subsystem initialized (PCI)");
device_count
} else {
// MMIO-based platform (QEMU virt): enumerate VirtIO MMIO
init_virtio_mmio()
}
}
/// Initialize VirtIO MMIO devices (QEMU virt platform).
#[cfg(target_arch = "aarch64")]
fn init_virtio_mmio() -> usize {
use crate::serial_println;
// Enumerate VirtIO MMIO devices
let mut device_count = 0;
for device in virtio::mmio::enumerate_devices() {
let type_name = virtio::mmio::device_type_name(device.device_id());
serial_println!(
"[drivers] Found VirtIO MMIO device: {} (ID={}, version={})",
type_name,
device.device_id(),
device.version()
);
device_count += 1;
}
serial_println!("[drivers] Found {} VirtIO MMIO devices", device_count);
// Initialize VirtIO block driver
match virtio::block_mmio::init() {
Ok(()) => {
serial_println!("[drivers] VirtIO block driver initialized");
// Run a quick read test
if let Err(e) = virtio::block_mmio::test_read() {
serial_println!("[drivers] VirtIO block test failed: {}", e);
}
}
Err(e) => {
serial_println!("[drivers] VirtIO block driver init failed: {}", e);
}
}
// Initialize VirtIO network driver
match virtio::net_mmio::init() {
Ok(()) => {
serial_println!("[drivers] VirtIO network driver initialized");
// Run a quick test
if let Err(e) = virtio::net_mmio::test_device() {
serial_println!("[drivers] VirtIO network test failed: {}", e);
}
}
Err(e) => {
serial_println!("[drivers] VirtIO network driver init failed: {}", e);
}
}
// Initialize VirtIO GPU driver
match virtio::gpu_mmio::init() {
Ok(()) => {
serial_println!("[drivers] VirtIO GPU driver initialized");
if let Err(e) = virtio::gpu_mmio::test_device() {
serial_println!("[drivers] VirtIO GPU test failed: {}", e);
}
}
Err(e) => {
serial_println!("[drivers] VirtIO GPU driver init failed: {}", e);
}
}
// Initialize VirtIO sound driver
match virtio::sound_mmio::init() {
Ok(()) => {
serial_println!("[drivers] VirtIO sound driver initialized");
}
Err(e) => {
serial_println!("[drivers] VirtIO sound driver init failed: {}", e);
}
}
serial_println!("[drivers] Driver subsystem initialized (MMIO)");
device_count
}