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