os/device/bus/
virtio_mmio.rs

1//! Virtio MMIO 设备驱动模块
2//!
3//! 提供对 Virtio MMIO 设备的探测和初始化功能
4//! 通过设备树节点信息创建 Virtio 传输对象,并根据设备类型调用相应的初始化函数
5//! 支持块设备、GPU、输入设备和网络设备的初始化
6use core::ptr::NonNull;
7
8use fdt::node::FdtNode;
9use virtio_drivers::transport::{
10    DeviceType, Transport,
11    mmio::{MmioTransport, VirtIOHeader},
12};
13
14use crate::{
15    device::{
16        block::virtio_blk, device_tree::DEVICE_TREE_REGISTRY, gpu::virtio_gpu, input::virtio_input,
17        net::virtio_net,
18    },
19    kernel::current_memory_space,
20    mm::address::{Paddr, UsizeConvert},
21    pr_info, pr_warn,
22};
23
24pub fn driver_init() {
25    DEVICE_TREE_REGISTRY
26        .write()
27        .insert("virtio,mmio", virtio_probe);
28}
29
30/// 探测并初始化 virtio 设备
31/// 分析设备树节点,创建对应的 virtio 传输对象,并调用设备初始化函数
32/// # 参数
33/// * `node` - 设备树节点
34fn virtio_probe(node: &FdtNode) {
35    // 分 析 reg 信 息
36    if let Some(reg) = node.reg().and_then(|mut reg| reg.next()) {
37        let paddr = reg.starting_address as usize;
38        let size = reg.size.unwrap_or(0);
39        if size == 0 {
40            pr_warn!(
41                "[Device] Virtio MMIO device tree node {} has no size",
42                node.name
43            );
44            return;
45        }
46        //判 断 virtio 设 备 类 型
47        let vaddr = current_memory_space()
48            .lock()
49            .map_mmio(Paddr::from_usize(paddr), size)
50            .ok()
51            .expect("Failed to map MMIO region");
52        let header = NonNull::new(vaddr.as_usize() as *mut VirtIOHeader).unwrap();
53        match unsafe { MmioTransport::new(header, size) } {
54            Err(e) => pr_warn!("Error creating VirtIO MMIO transport: {}", e),
55            Ok(transport) => {
56                virtio_device(transport);
57            }
58        }
59    }
60}
61
62/// 对不同的virtio设备进行进一步的初始化工作
63/// # 参数
64/// * `transport` - virtio 传输对象
65fn virtio_device(transport: MmioTransport<'static>) {
66    match transport.device_type() {
67        DeviceType::Block => virtio_blk::init(transport),
68        DeviceType::GPU => virtio_gpu::init(transport),
69        DeviceType::Input => virtio_input::init(transport),
70        DeviceType::Network => virtio_net::init(transport),
71        t => pr_warn!("Unrecognized virtio device: {:?}", t),
72    }
73}