os/device/bus/
virtio_mmio.rs1use 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
30fn virtio_probe(node: &FdtNode) {
35 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 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
62fn 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}