xref: /DragonOS/kernel/src/driver/virtio/virtio.rs (revision 78bf93f02f84bf5e024ddfb559f040e68ce39ccf)
126d84a31SYJwu2023 use super::transport_pci::PciTransport;
226d84a31SYJwu2023 use super::virtio_impl::HalImpl;
3*78bf93f0SYJwu2023 use crate::driver::pci::pci::PciDeviceStructureGeneralDevice;
4*78bf93f0SYJwu2023 use crate::driver::pci::pci::{
5*78bf93f0SYJwu2023     get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
6*78bf93f0SYJwu2023 };
7*78bf93f0SYJwu2023 use crate::libs::rwlock::RwLockWriteGuard;
826d84a31SYJwu2023 use crate::{kdebug, kerror, kwarn};
926d84a31SYJwu2023 use alloc::{boxed::Box, collections::LinkedList};
1026d84a31SYJwu2023 use virtio_drivers::device::net::VirtIONet;
1126d84a31SYJwu2023 use virtio_drivers::transport::{DeviceType, Transport};
12*78bf93f0SYJwu2023 const NETWORK_CLASS: u8 = 0x2;
13*78bf93f0SYJwu2023 const ETHERNET_SUBCLASS: u8 = 0x0;
1426d84a31SYJwu2023 
1526d84a31SYJwu2023 //Virtio设备寻找过程中出现的问题
1626d84a31SYJwu2023 enum VirtioError {
1726d84a31SYJwu2023     VirtioNetNotFound,
18*78bf93f0SYJwu2023     NetDeviceNotFound,
1926d84a31SYJwu2023 }
2026d84a31SYJwu2023 
2126d84a31SYJwu2023 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c)
2226d84a31SYJwu2023 #[no_mangle]
2326d84a31SYJwu2023 pub extern "C" fn c_virtio_probe() {
24*78bf93f0SYJwu2023     virtio_probe();
2526d84a31SYJwu2023 }
2626d84a31SYJwu2023 
2726d84a31SYJwu2023 ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
28*78bf93f0SYJwu2023 pub fn virtio_probe() {
29*78bf93f0SYJwu2023     let mut list = PCI_DEVICE_LINKEDLIST.write();
30*78bf93f0SYJwu2023     if let Ok(virtio_list) = virtio_device_search(&mut list) {
31*78bf93f0SYJwu2023         for virtio_device in virtio_list {
32*78bf93f0SYJwu2023             match PciTransport::new::<HalImpl>(virtio_device) {
3326d84a31SYJwu2023                 Ok(mut transport) => {
3426d84a31SYJwu2023                     kdebug!(
3526d84a31SYJwu2023                         "Detected virtio PCI device with device type {:?}, features {:#018x}",
3626d84a31SYJwu2023                         transport.device_type(),
3726d84a31SYJwu2023                         transport.read_device_features(),
3826d84a31SYJwu2023                     );
39*78bf93f0SYJwu2023                     virtio_device_init(transport);
4026d84a31SYJwu2023                 }
4126d84a31SYJwu2023                 Err(err) => {
4226d84a31SYJwu2023                     kerror!("Pci transport create failed because of error: {}", err);
4326d84a31SYJwu2023                 }
4426d84a31SYJwu2023             }
4526d84a31SYJwu2023         }
4626d84a31SYJwu2023     } else {
4726d84a31SYJwu2023         kerror!("Error occured when finding virtio device!");
4826d84a31SYJwu2023     }
4926d84a31SYJwu2023 }
5026d84a31SYJwu2023 
5126d84a31SYJwu2023 ///@brief 为virtio设备寻找对应的驱动进行初始化
52*78bf93f0SYJwu2023 fn virtio_device_init(transport: impl Transport) {
5326d84a31SYJwu2023     match transport.device_type() {
5426d84a31SYJwu2023         DeviceType::Block => {
5526d84a31SYJwu2023             kwarn!("Not support virtio_block device for now");
5626d84a31SYJwu2023         }
5726d84a31SYJwu2023         DeviceType::GPU => {
5826d84a31SYJwu2023             kwarn!("Not support virtio_gpu device for now");
5926d84a31SYJwu2023         }
6026d84a31SYJwu2023         DeviceType::Input => {
6126d84a31SYJwu2023             kwarn!("Not support virtio_input device for now");
6226d84a31SYJwu2023         }
6326d84a31SYJwu2023         DeviceType::Network => virtio_net(transport),
6426d84a31SYJwu2023         t => {
6526d84a31SYJwu2023             kwarn!("Unrecognized virtio device: {:?}", t);
6626d84a31SYJwu2023         }
6726d84a31SYJwu2023     }
6826d84a31SYJwu2023 }
6926d84a31SYJwu2023 
7026d84a31SYJwu2023 ///@brief virtio-net 驱动的初始化与测试
7126d84a31SYJwu2023 fn virtio_net<T: Transport>(transport: T) {
72bacd691cSlogin     let driver_net = match VirtIONet::<HalImpl, T>::new(transport) {
73676b8ef6SMork         Ok(net) => {
7426d84a31SYJwu2023             kdebug!("Virtio-net driver init successfully.");
7526d84a31SYJwu2023             net
7626d84a31SYJwu2023         }
7726d84a31SYJwu2023         Err(_) => {
7826d84a31SYJwu2023             kerror!("VirtIONet init failed");
7926d84a31SYJwu2023             return;
8026d84a31SYJwu2023         }
8126d84a31SYJwu2023     };
82bacd691cSlogin     // let mut buf = [0u8; 0x100];
83bacd691cSlogin     // // let len = match driver_net.recv(&mut buf)
84bacd691cSlogin     // // {
85bacd691cSlogin     // //     Ok(len) =>{len},
86bacd691cSlogin     // //     Err(_) =>{kerror!("virtio_net recv failed");return;}
87bacd691cSlogin     // // };
88bacd691cSlogin     // match driver_net.can_send() {
8973c607aaSYJwu2023     //     true => {
90bacd691cSlogin     //         kdebug!("Virtio-net can send");
9126d84a31SYJwu2023     //     }
9273c607aaSYJwu2023     //     false => {
93bacd691cSlogin     //         kdebug!("Virtio-net can not send");
9473c607aaSYJwu2023     //     }
9573c607aaSYJwu2023     // }
96bacd691cSlogin     // // match driver_net.can_recv() {
97bacd691cSlogin     // //     true => {
98bacd691cSlogin     // //         kdebug!("can recv")
99bacd691cSlogin     // //     }
100bacd691cSlogin     // //     false => {
101bacd691cSlogin     // //         kdebug!("can not recv");
102bacd691cSlogin     // //     }
103bacd691cSlogin     // // }
10473c607aaSYJwu2023 
105bacd691cSlogin     // let len = 100;
106bacd691cSlogin     // //kdebug!("recv: {:?}", &buf[..len]);
107bacd691cSlogin     // match driver_net.send(&buf[..len]) {
108bacd691cSlogin     //     Ok(_) => {
109bacd691cSlogin     //         kdebug!("virtio_net send success");
110bacd691cSlogin     //     }
111bacd691cSlogin     //     Err(_) => {
112bacd691cSlogin     //         kerror!("virtio_net send failed");
113bacd691cSlogin     //         return;
114bacd691cSlogin     //     }
115bacd691cSlogin     // }
11673c607aaSYJwu2023 
11726d84a31SYJwu2023     let mac = driver_net.mac();
11826d84a31SYJwu2023     kdebug!("virtio_net MAC={:?}", mac);
11926d84a31SYJwu2023     kdebug!("virtio-net test finished");
12026d84a31SYJwu2023 }
12126d84a31SYJwu2023 
12226d84a31SYJwu2023 /// @brief 寻找所有的virtio设备
123*78bf93f0SYJwu2023 /// @param list 链表的写锁
124*78bf93f0SYJwu2023 /// @return Result<LinkedList<&'a mut Pci_Device_Structure_General_Device>, VirtioError>  成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err
12526d84a31SYJwu2023 /// 该函数主要是为其他virtio设备预留支持
126*78bf93f0SYJwu2023 fn virtio_device_search<'a>(
127*78bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
128*78bf93f0SYJwu2023 ) -> Result<LinkedList<&'a mut PciDeviceStructureGeneralDevice>, VirtioError> {
129*78bf93f0SYJwu2023     let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new();
130*78bf93f0SYJwu2023     let virtio_net_device = get_virtio_net_device(list)?;
131*78bf93f0SYJwu2023     virtio_list.push_back(virtio_net_device);
13226d84a31SYJwu2023     Ok(virtio_list)
13326d84a31SYJwu2023 }
134*78bf93f0SYJwu2023 
135*78bf93f0SYJwu2023 /// @brief 寻找virtio-net设备
136*78bf93f0SYJwu2023 /// @param list 链表的写锁
137*78bf93f0SYJwu2023 /// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err
138*78bf93f0SYJwu2023 fn get_virtio_net_device<'a>(
139*78bf93f0SYJwu2023     list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
140*78bf93f0SYJwu2023 ) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> {
141*78bf93f0SYJwu2023     let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS);
142*78bf93f0SYJwu2023     if result.is_empty() {
143*78bf93f0SYJwu2023         return Err(VirtioError::NetDeviceNotFound);
144*78bf93f0SYJwu2023     }
145*78bf93f0SYJwu2023     for device in result {
146*78bf93f0SYJwu2023         let standard_device = device.as_standard_device_mut().unwrap();
147*78bf93f0SYJwu2023         let header = &standard_device.common_header;
148*78bf93f0SYJwu2023         if header.vendor_id == 0x1AF4
149*78bf93f0SYJwu2023             && header.device_id >= 0x1000
150*78bf93f0SYJwu2023             && header.device_id <= 0x103F
151*78bf93f0SYJwu2023             && standard_device.subsystem_id == 1
152*78bf93f0SYJwu2023         {
153*78bf93f0SYJwu2023             return Ok(standard_device);
154*78bf93f0SYJwu2023         }
155*78bf93f0SYJwu2023     }
156*78bf93f0SYJwu2023     Err(VirtioError::VirtioNetNotFound)
157*78bf93f0SYJwu2023 }
158