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