1 use super::transport_pci::PciTransport; 2 use super::virtio_impl::HalImpl; 3 use crate::driver::pci::pci::DeviceFunction; 4 use crate::include::bindings::bindings::get_virtio_net_device; 5 use crate::{kdebug, kerror, kwarn}; 6 use alloc::{boxed::Box, collections::LinkedList}; 7 use virtio_drivers::device::net::VirtIONet; 8 use virtio_drivers::transport::{DeviceType, Transport}; 9 10 //Virtio设备寻找过程中出现的问题 11 enum VirtioError { 12 VirtioNetNotFound, 13 } 14 15 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c) 16 #[no_mangle] 17 pub extern "C" fn c_virtio_probe() { 18 if let Ok(virtio_list) = virtio_device_search() { 19 for device_function in virtio_list { 20 match PciTransport::new::<HalImpl>(*device_function) { 21 Ok(mut transport) => { 22 kdebug!( 23 "Detected virtio PCI device with device type {:?}, features {:#018x}", 24 transport.device_type(), 25 transport.read_device_features(), 26 ); 27 virtio_device(transport); 28 } 29 Err(err) => { 30 kerror!("Pci transport create failed because of error: {}", err); 31 } 32 } 33 } 34 } else { 35 kerror!("Error occured when finding virtio device!"); 36 } 37 } 38 39 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加) 40 fn virtio_probe() { 41 if let Ok(virtio_list) = virtio_device_search() { 42 for device_function in virtio_list { 43 match PciTransport::new::<HalImpl>(*device_function) { 44 Ok(mut transport) => { 45 kdebug!( 46 "Detected virtio PCI device with device type {:?}, features {:#018x}", 47 transport.device_type(), 48 transport.read_device_features(), 49 ); 50 virtio_device(transport); 51 } 52 Err(err) => { 53 kerror!("Pci transport create failed because of error: {}", err); 54 } 55 } 56 } 57 } else { 58 kerror!("Error occured when finding virtio device!"); 59 } 60 } 61 62 ///@brief 为virtio设备寻找对应的驱动进行初始化 63 fn virtio_device(transport: impl Transport) { 64 match transport.device_type() { 65 DeviceType::Block => { 66 kwarn!("Not support virtio_block device for now"); 67 } 68 DeviceType::GPU => { 69 kwarn!("Not support virtio_gpu device for now"); 70 } 71 DeviceType::Input => { 72 kwarn!("Not support virtio_input device for now"); 73 } 74 DeviceType::Network => virtio_net(transport), 75 t => { 76 kwarn!("Unrecognized virtio device: {:?}", t); 77 } 78 } 79 } 80 81 ///@brief virtio-net 驱动的初始化与测试 82 fn virtio_net<T: Transport>(transport: T) { 83 let mut driver_net = match VirtIONet::<HalImpl, T>::new(transport) { 84 Ok(mut net) => { 85 kdebug!("Virtio-net driver init successfully."); 86 net 87 } 88 Err(_) => { 89 kerror!("VirtIONet init failed"); 90 return; 91 } 92 }; 93 // let mut buf = [0u8; 0x100]; 94 // let len = match driver_net.recv(&mut buf) 95 // { 96 // Ok(len) =>{len}, 97 // Err(_) =>{kerror!("virtio_net recv failed");return;} 98 // }; 99 // kdebug!("recv: {:?}", &buf[..len]); 100 // match driver_net.send(&buf[..len]) 101 // { 102 // Ok(_) =>{kdebug!("virtio_net send success");}, 103 // Err(_) =>{kerror!("virtio_net send failed");return;}, 104 // } 105 let mac = driver_net.mac(); 106 kdebug!("virtio_net MAC={:?}", mac); 107 kdebug!("virtio-net test finished"); 108 } 109 110 /// @brief 寻找所有的virtio设备 111 /// @return Result<LinkedList<Box<DeviceFunction>>,VirtioError> 成功则返回包含所有virtio设备的链表,失败则返回err 112 /// 该函数主要是为其他virtio设备预留支持 113 fn virtio_device_search() -> Result<LinkedList<Box<DeviceFunction>>, VirtioError> { 114 let mut virtio_list: LinkedList<Box<DeviceFunction>> = LinkedList::new(); 115 let (bus, device, function) = unsafe { 116 let mut bus: u8 = 0; 117 let mut device: u8 = 0; 118 let mut function: u8 = 0; 119 let bus_ptr = &mut bus as *mut u8; 120 let device_ptr = &mut device as *mut u8; 121 let function_ptr = &mut function as *mut u8; 122 get_virtio_net_device(bus_ptr, device_ptr, function_ptr); 123 (bus, device, function) 124 }; 125 if bus == 0 && device == 0 && function == 0 { 126 kdebug!("get_virtio_net_device failed"); 127 return Err(VirtioError::VirtioNetNotFound); 128 } 129 let device_function = DeviceFunction { 130 bus: bus, 131 device: device, 132 function: function, 133 }; 134 virtio_list.push_back(Box::new(device_function)); 135 Ok(virtio_list) 136 } 137