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