xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
126d84a31SYJwu2023 use super::transport_pci::PciTransport;
226d84a31SYJwu2023 use super::virtio_impl::HalImpl;
3*e2841179SLoGin use crate::driver::base::device::DeviceId;
413776c11Slogin use crate::driver::net::virtio_net::virtio_net;
578bf93f0SYJwu2023 use crate::driver::pci::pci::{
68d94ea66SYJwu2023     get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
78d94ea66SYJwu2023     PCI_DEVICE_LINKEDLIST,
878bf93f0SYJwu2023 };
978bf93f0SYJwu2023 use crate::libs::rwlock::RwLockWriteGuard;
1026d84a31SYJwu2023 use crate::{kdebug, kerror, kwarn};
11*e2841179SLoGin use alloc::sync::Arc;
1226d84a31SYJwu2023 use alloc::{boxed::Box, collections::LinkedList};
1326d84a31SYJwu2023 use virtio_drivers::transport::{DeviceType, Transport};
1478bf93f0SYJwu2023 const NETWORK_CLASS: u8 = 0x2;
1578bf93f0SYJwu2023 const ETHERNET_SUBCLASS: u8 = 0x0;
1626d84a31SYJwu2023 
1726d84a31SYJwu2023 //Virtio设备寻找过程中出现的问题
1826d84a31SYJwu2023 enum VirtioError {
1926d84a31SYJwu2023     VirtioNetNotFound,
2078bf93f0SYJwu2023     NetDeviceNotFound,
2126d84a31SYJwu2023 }
2226d84a31SYJwu2023 
2326d84a31SYJwu2023 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
2478bf93f0SYJwu2023 pub fn virtio_probe() {
2578bf93f0SYJwu2023     let mut list = PCI_DEVICE_LINKEDLIST.write();
2678bf93f0SYJwu2023     if let Ok(virtio_list) = virtio_device_search(&mut list) {
2778bf93f0SYJwu2023         for virtio_device in virtio_list {
28*e2841179SLoGin             let dev_id = virtio_device.common_header.device_id;
29*e2841179SLoGin             let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap();
30*e2841179SLoGin             match PciTransport::new::<HalImpl>(virtio_device, dev_id.clone()) {
3126d84a31SYJwu2023                 Ok(mut transport) => {
3226d84a31SYJwu2023                     kdebug!(
3326d84a31SYJwu2023                         "Detected virtio PCI device with device type {:?}, features {:#018x}",
3426d84a31SYJwu2023                         transport.device_type(),
3526d84a31SYJwu2023                         transport.read_device_features(),
3626d84a31SYJwu2023                     );
37*e2841179SLoGin                     virtio_device_init(transport, dev_id);
3826d84a31SYJwu2023                 }
3926d84a31SYJwu2023                 Err(err) => {
4026d84a31SYJwu2023                     kerror!("Pci transport create failed because of error: {}", err);
4126d84a31SYJwu2023                 }
4226d84a31SYJwu2023             }
4326d84a31SYJwu2023         }
4426d84a31SYJwu2023     } else {
4526d84a31SYJwu2023         kerror!("Error occured when finding virtio device!");
4626d84a31SYJwu2023     }
4726d84a31SYJwu2023 }
4826d84a31SYJwu2023 
4926d84a31SYJwu2023 ///@brief 为virtio设备寻找对应的驱动进行初始化
50*e2841179SLoGin fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc<DeviceId>) {
5126d84a31SYJwu2023     match transport.device_type() {
5226d84a31SYJwu2023         DeviceType::Block => {
5326d84a31SYJwu2023             kwarn!("Not support virtio_block device for now");
5426d84a31SYJwu2023         }
5526d84a31SYJwu2023         DeviceType::GPU => {
5626d84a31SYJwu2023             kwarn!("Not support virtio_gpu device for now");
5726d84a31SYJwu2023         }
5826d84a31SYJwu2023         DeviceType::Input => {
5926d84a31SYJwu2023             kwarn!("Not support virtio_input device for now");
6026d84a31SYJwu2023         }
61*e2841179SLoGin         DeviceType::Network => virtio_net(transport, dev_id),
6226d84a31SYJwu2023         t => {
6326d84a31SYJwu2023             kwarn!("Unrecognized virtio device: {:?}", t);
6426d84a31SYJwu2023         }
6526d84a31SYJwu2023     }
6626d84a31SYJwu2023 }
6726d84a31SYJwu2023 
6826d84a31SYJwu2023 /// @brief 寻找所有的virtio设备
6978bf93f0SYJwu2023 /// @param list 链表的写锁
7078bf93f0SYJwu2023 /// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError>  成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
7126d84a31SYJwu2023 /// 该函数主要是为其他virtio设备预留支持
7278bf93f0SYJwu2023 fn virtio_device_search<'a>(
7378bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
7478bf93f0SYJwu2023 ) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
7578bf93f0SYJwu2023     let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
7678bf93f0SYJwu2023     let virtio_net_device = get_virtio_net_device(list)?;
7778bf93f0SYJwu2023     virtio_list.push_back(virtio_net_device);
7826d84a31SYJwu2023     Ok(virtio_list)
7926d84a31SYJwu2023 }
8078bf93f0SYJwu2023 
8178bf93f0SYJwu2023 /// @brief 寻找virtio-net设备
8278bf93f0SYJwu2023 /// @param list 链表的写锁
8378bf93f0SYJwu2023 /// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
8478bf93f0SYJwu2023 fn get_virtio_net_device<'a>(
8578bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
8678bf93f0SYJwu2023 ) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
8778bf93f0SYJwu2023     let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
8878bf93f0SYJwu2023     if result.is_empty() {
8978bf93f0SYJwu2023         return Err(VirtioError::NetDeviceNotFound);
9078bf93f0SYJwu2023     }
9178bf93f0SYJwu2023     for device in result {
9278bf93f0SYJwu2023         let standard_device = device.as_standard_device_mut().unwrap();
9378bf93f0SYJwu2023         let header = &standard_device.common_header;
9478bf93f0SYJwu2023         if header.vendor_id == 0x1AF4
9578bf93f0SYJwu2023             && header.device_id >= 0x1000
9678bf93f0SYJwu2023             && header.device_id <= 0x103F
9778bf93f0SYJwu2023             && standard_device.subsystem_id == 1
9878bf93f0SYJwu2023         {
9978bf93f0SYJwu2023             return Ok(standard_device);
10078bf93f0SYJwu2023         }
10178bf93f0SYJwu2023     }
10278bf93f0SYJwu2023     Err(VirtioError::VirtioNetNotFound)
10378bf93f0SYJwu2023 }
104