xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision 17041e0e307eaf9e8d8ddbddfa186cd1f10f1bc0)
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