virtio.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. use super::mmio::virtio_probe_mmio;
  2. use super::transport_pci::PciTransport;
  3. use super::virtio_impl::HalImpl;
  4. use crate::driver::base::device::bus::Bus;
  5. use crate::driver::base::device::{Device, DeviceId};
  6. use crate::driver::block::virtio_blk::virtio_blk;
  7. use crate::driver::net::virtio_net::virtio_net;
  8. use crate::driver::pci::pci::{
  9. get_pci_device_structures_mut_by_vendor_id, PciDeviceStructureGeneralDevice,
  10. PCI_DEVICE_LINKEDLIST,
  11. };
  12. use crate::driver::pci::subsys::pci_bus;
  13. use crate::driver::virtio::transport::VirtIOTransport;
  14. use alloc::string::String;
  15. use alloc::sync::Arc;
  16. use alloc::vec::Vec;
  17. use log::{debug, error, warn};
  18. use virtio_drivers::transport::{DeviceType, Transport};
  19. ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
  20. pub fn virtio_probe() {
  21. #[cfg(not(target_arch = "riscv64"))]
  22. virtio_probe_pci();
  23. virtio_probe_mmio();
  24. }
  25. #[allow(dead_code)]
  26. fn virtio_probe_pci() {
  27. let virtio_list = virtio_device_search();
  28. for virtio_device in virtio_list {
  29. let dev_id = virtio_device.common_header.device_id;
  30. let dev_id = DeviceId::new(None, Some(format!("{dev_id}"))).unwrap();
  31. match PciTransport::new::<HalImpl>(virtio_device.clone(), dev_id.clone()) {
  32. Ok(mut transport) => {
  33. debug!(
  34. "Detected virtio PCI device with device type {:?}, features {:#018x}",
  35. transport.device_type(),
  36. transport.read_device_features(),
  37. );
  38. let transport = VirtIOTransport::Pci(transport);
  39. // 这里暂时通过设备名称在sysfs中查找设备,但是我感觉用设备ID更好
  40. let bus = pci_bus() as Arc<dyn Bus>;
  41. let name: String = virtio_device.common_header.bus_device_function.into();
  42. let pci_raw_device = bus.find_device_by_name(name.as_str());
  43. virtio_device_init(transport, dev_id, pci_raw_device);
  44. }
  45. Err(err) => {
  46. error!("Pci transport create failed because of error: {}", err);
  47. }
  48. }
  49. }
  50. }
  51. ///@brief 为virtio设备寻找对应的驱动进行初始化
  52. pub(super) fn virtio_device_init(
  53. transport: VirtIOTransport,
  54. dev_id: Arc<DeviceId>,
  55. dev_parent: Option<Arc<dyn Device>>,
  56. ) {
  57. match transport.device_type() {
  58. DeviceType::Block => virtio_blk(transport, dev_id, dev_parent),
  59. DeviceType::GPU => {
  60. warn!("Not support virtio_gpu device for now");
  61. }
  62. DeviceType::Input => {
  63. warn!("Not support virtio_input device for now");
  64. }
  65. DeviceType::Network => virtio_net(transport, dev_id, dev_parent),
  66. t => {
  67. warn!("Unrecognized virtio device: {:?}", t);
  68. }
  69. }
  70. }
  71. /// # virtio_device_search - 在给定的PCI设备列表中搜索符合特定标准的virtio设备
  72. ///
  73. /// 该函数搜索一个PCI设备列表,找到所有由特定厂商ID(0x1AF4)和设备ID范围(0x1000至0x103F)定义的virtio设备。
  74. ///
  75. /// ## 参数
  76. ///
  77. /// - list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>> - 一个可写的PCI设备结构列表的互斥锁。
  78. ///
  79. /// ## 返回值
  80. ///
  81. /// 返回一个包含所有找到的virtio设备的数组
  82. fn virtio_device_search() -> Vec<Arc<PciDeviceStructureGeneralDevice>> {
  83. let list = &*PCI_DEVICE_LINKEDLIST;
  84. let mut virtio_list = Vec::new();
  85. let result = get_pci_device_structures_mut_by_vendor_id(list, 0x1AF4);
  86. for device in result {
  87. let standard_device = device.as_standard_device().unwrap();
  88. let header = &standard_device.common_header;
  89. if header.device_id >= 0x1000 && header.device_id <= 0x103F {
  90. virtio_list.push(standard_device);
  91. }
  92. }
  93. return virtio_list;
  94. }