xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision c566df451ce6dbf2af684333e68b39fdfff86498)
1 use super::transport_pci::PciTransport;
2 use super::virtio_impl::HalImpl;
3 use crate::driver::net::virtio_net::virtio_net;
4 use crate::driver::pci::pci::{
5     get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
6     PCI_DEVICE_LINKEDLIST,
7 };
8 use crate::libs::rwlock::RwLockWriteGuard;
9 use crate::{kdebug, kerror, kwarn};
10 use alloc::{boxed::Box, collections::LinkedList};
11 use virtio_drivers::transport::{DeviceType, Transport};
12 const NETWORK_CLASS: u8 = 0x2;
13 const ETHERNET_SUBCLASS: u8 = 0x0;
14 
15 //Virtio设备寻找过程中出现的问题
16 enum VirtioError {
17     VirtioNetNotFound,
18     NetDeviceNotFound,
19 }
20 
21 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
22 pub fn virtio_probe() {
23     let mut list = PCI_DEVICE_LINKEDLIST.write();
24     if let Ok(virtio_list) = virtio_device_search(&mut list) {
25         for virtio_device in virtio_list {
26             match PciTransport::new::<HalImpl>(virtio_device) {
27                 Ok(mut transport) => {
28                     kdebug!(
29                         "Detected virtio PCI device with device type {:?}, features {:#018x}",
30                         transport.device_type(),
31                         transport.read_device_features(),
32                     );
33                     virtio_device_init(transport);
34                 }
35                 Err(err) => {
36                     kerror!("Pci transport create failed because of error: {}", err);
37                 }
38             }
39         }
40     } else {
41         kerror!("Error occured when finding virtio device!");
42     }
43 }
44 
45 ///@brief 为virtio设备寻找对应的驱动进行初始化
46 fn virtio_device_init(transport: impl Transport + 'static) {
47     match transport.device_type() {
48         DeviceType::Block => {
49             kwarn!("Not support virtio_block device for now");
50         }
51         DeviceType::GPU => {
52             kwarn!("Not support virtio_gpu device for now");
53         }
54         DeviceType::Input => {
55             kwarn!("Not support virtio_input device for now");
56         }
57         DeviceType::Network => virtio_net(transport),
58         t => {
59             kwarn!("Unrecognized virtio device: {:?}", t);
60         }
61     }
62 }
63 
64 /// @brief 寻找所有的virtio设备
65 /// @param list 链表的写锁
66 /// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError>  成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
67 /// 该函数主要是为其他virtio设备预留支持
68 fn virtio_device_search<'a>(
69     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
70 ) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
71     let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
72     let virtio_net_device = get_virtio_net_device(list)?;
73     virtio_list.push_back(virtio_net_device);
74     Ok(virtio_list)
75 }
76 
77 /// @brief 寻找virtio-net设备
78 /// @param list 链表的写锁
79 /// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
80 fn get_virtio_net_device<'a>(
81     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
82 ) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
83     let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
84     if result.is_empty() {
85         return Err(VirtioError::NetDeviceNotFound);
86     }
87     for device in result {
88         let standard_device = device.as_standard_device_mut().unwrap();
89         let header = &standard_device.common_header;
90         if header.vendor_id == 0x1AF4
91             && header.device_id >= 0x1000
92             && header.device_id <= 0x103F
93             && standard_device.subsystem_id == 1
94         {
95             return Ok(standard_device);
96         }
97     }
98     Err(VirtioError::VirtioNetNotFound)
99 }
100