xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision 731bc2b32d7b37298883d7a15b6dca659b436ee4)
1 use super::mmio::virtio_probe_mmio;
2 use super::transport_pci::PciTransport;
3 use super::virtio_impl::HalImpl;
4 use crate::driver::base::device::DeviceId;
5 use crate::driver::block::virtio_blk::virtio_blk;
6 use crate::driver::net::virtio_net::virtio_net;
7 use crate::driver::pci::pci::{
8     get_pci_device_structures_mut_by_vendor_id, PciDeviceStructure,
9     PciDeviceStructureGeneralDevice, PCI_DEVICE_LINKEDLIST,
10 };
11 use crate::driver::virtio::transport::VirtIOTransport;
12 use crate::libs::rwlock::RwLockWriteGuard;
13 use crate::{kdebug, kerror, kwarn};
14 use alloc::sync::Arc;
15 use alloc::vec::Vec;
16 use alloc::{boxed::Box, collections::LinkedList};
17 use virtio_drivers::transport::{DeviceType, Transport};
18 
19 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
20 pub fn virtio_probe() {
21     #[cfg(not(target_arch = "riscv64"))]
22     virtio_probe_pci();
23     virtio_probe_mmio();
24 }
25 
26 #[allow(dead_code)]
27 fn virtio_probe_pci() {
28     let mut list = PCI_DEVICE_LINKEDLIST.write();
29     let virtio_list = virtio_device_search(&mut list);
30     for virtio_device in virtio_list {
31         let dev_id = virtio_device.common_header.device_id;
32         let dev_id = DeviceId::new(None, Some(format!("{dev_id}"))).unwrap();
33         match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
34             Ok(mut transport) => {
35                 kdebug!(
36                     "Detected virtio PCI device with device type {:?}, features {:#018x}",
37                     transport.device_type(),
38                     transport.read_device_features(),
39                 );
40                 let transport = VirtIOTransport::Pci(transport);
41                 virtio_device_init(transport, dev_id);
42             }
43             Err(err) => {
44                 kerror!("Pci transport create failed because of error: {}", err);
45             }
46         }
47     }
48 }
49 
50 ///@brief 为virtio设备寻找对应的驱动进行初始化
51 pub(super) fn virtio_device_init(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
52     match transport.device_type() {
53         DeviceType::Block => virtio_blk(transport, dev_id),
54         DeviceType::GPU => {
55             kwarn!("Not support virtio_gpu device for now");
56         }
57         DeviceType::Input => {
58             kwarn!("Not support virtio_input device for now");
59         }
60         DeviceType::Network => virtio_net(transport, dev_id),
61         t => {
62             kwarn!("Unrecognized virtio device: {:?}", t);
63         }
64     }
65 }
66 
67 /// # virtio_device_search - 在给定的PCI设备列表中搜索符合特定标准的virtio设备
68 ///
69 /// 该函数搜索一个PCI设备列表,找到所有由特定厂商ID(0x1AF4)和设备ID范围(0x1000至0x103F)定义的virtio设备。
70 ///
71 /// ## 参数
72 ///
73 /// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> - 一个可写的PCI设备结构列表的互斥锁。
74 ///
75 /// ## 返回值
76 ///
77 /// 返回一个包含所有找到的virtio设备的数组
78 fn virtio_device_search<'a>(
79     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
80 ) -> Vec<&'a mut PciDeviceStructureGeneralDevice> {
81     let mut virtio_list = Vec::new();
82     let result = get_pci_device_structures_mut_by_vendor_id(list, 0x1AF4);
83 
84     for device in result {
85         let standard_device = device.as_standard_device_mut().unwrap();
86         let header = &standard_device.common_header;
87         if header.device_id >= 0x1000 && header.device_id <= 0x103F {
88             virtio_list.push(standard_device);
89         }
90     }
91 
92     return virtio_list;
93 }
94