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