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 driver_net = match VirtIONet::<HalImpl, T>::new(transport) { 84 Ok(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 // match driver_net.can_send() { 100 // true => { 101 // kdebug!("Virtio-net can send"); 102 // } 103 // false => { 104 // kdebug!("Virtio-net can not send"); 105 // } 106 // } 107 // // match driver_net.can_recv() { 108 // // true => { 109 // // kdebug!("can recv") 110 // // } 111 // // false => { 112 // // kdebug!("can not recv"); 113 // // } 114 // // } 115 116 // let len = 100; 117 // //kdebug!("recv: {:?}", &buf[..len]); 118 // match driver_net.send(&buf[..len]) { 119 // Ok(_) => { 120 // kdebug!("virtio_net send success"); 121 // } 122 // Err(_) => { 123 // kerror!("virtio_net send failed"); 124 // return; 125 // } 126 // } 127 128 let mac = driver_net.mac(); 129 kdebug!("virtio_net MAC={:?}", mac); 130 kdebug!("virtio-net test finished"); 131 } 132 133 /// @brief 寻找所有的virtio设备 134 /// @return Result<LinkedList<Box<DeviceFunction>>,VirtioError> 成功则返回包含所有virtio设备的链表,失败则返回err 135 /// 该函数主要是为其他virtio设备预留支持 136 fn virtio_device_search() -> Result<LinkedList<Box<DeviceFunction>>, VirtioError> { 137 let mut virtio_list: LinkedList<Box<DeviceFunction>> = LinkedList::new(); 138 let (bus, device, function) = unsafe { 139 let mut bus: u8 = 0; 140 let mut device: u8 = 0; 141 let mut function: u8 = 0; 142 let bus_ptr = &mut bus as *mut u8; 143 let device_ptr = &mut device as *mut u8; 144 let function_ptr = &mut function as *mut u8; 145 get_virtio_net_device(bus_ptr, device_ptr, function_ptr); 146 (bus, device, function) 147 }; 148 if bus == 0 && device == 0 && function == 0 { 149 kdebug!("get_virtio_net_device failed"); 150 return Err(VirtioError::VirtioNetNotFound); 151 } 152 let device_function = DeviceFunction { 153 bus: bus, 154 device: device, 155 function: function, 156 }; 157 virtio_list.push_back(Box::new(device_function)); 158 Ok(virtio_list) 159 } 160