浏览代码

Recognise VirtIO devices.

Andrew Walbran 2 年之前
父节点
当前提交
8de7df2017
共有 2 个文件被更改,包括 67 次插入1 次删除
  1. 7 1
      examples/aarch64/src/main.rs
  2. 60 0
      src/transport/pci.rs

+ 7 - 1
examples/aarch64/src/main.rs

@@ -12,7 +12,10 @@ use hal::HalImpl;
 use log::{debug, error, info, trace, warn, LevelFilter};
 use psci::system_off;
 use virtio_drivers::{
-    pci::bus::{Cam, PciRoot},
+    pci::{
+        bus::{Cam, PciRoot},
+        virtio_device_type,
+    },
     DeviceType, MmioTransport, Transport, VirtIOBlk, VirtIOGpu, VirtIOHeader, VirtIONet,
 };
 
@@ -148,6 +151,9 @@ fn enumerate_pci(pci_node: FdtNode, cam: Cam) {
         let mut pci_root = unsafe { PciRoot::new(region.starting_address as *mut u8, cam) };
         for (device_function, info) in pci_root.enumerate_bus(0) {
             info!("Found {} at {}", info, device_function);
+            if let Some(virtio_type) = virtio_device_type(&info) {
+                info!("  VirtIO {:?}", virtio_type);
+            }
         }
     }
 }

+ 60 - 0
src/transport/pci.rs

@@ -2,6 +2,7 @@
 
 pub mod bus;
 
+use self::bus::DeviceFunctionInfo;
 use super::DeviceType;
 
 /// The PCI vendor ID for VirtIO devices.
@@ -32,6 +33,18 @@ fn device_type(pci_device_id: u16) -> DeviceType {
     }
 }
 
+/// Returns the type of VirtIO device to which the given PCI vendor and device ID corresponds, or
+/// `None` if it is not a recognised VirtIO device.
+pub fn virtio_device_type(device_function_info: &DeviceFunctionInfo) -> Option<DeviceType> {
+    if device_function_info.vendor_id == VIRTIO_VENDOR_ID {
+        let device_type = device_type(device_function_info.device_id);
+        if device_type != DeviceType::Invalid {
+            return Some(device_type);
+        }
+    }
+    None
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -51,4 +64,51 @@ mod tests {
         assert_eq!(device_type(0x1040), DeviceType::Invalid);
         assert_eq!(device_type(0x1059), DeviceType::Invalid);
     }
+
+    #[test]
+    fn virtio_device_type_valid() {
+        assert_eq!(
+            virtio_device_type(&DeviceFunctionInfo {
+                vendor_id: VIRTIO_VENDOR_ID,
+                device_id: TRANSITIONAL_BLOCK,
+                class: 0,
+                subclass: 0,
+                prog_if: 0,
+                revision: 0,
+                header_type: bus::HeaderType::Standard,
+            }),
+            Some(DeviceType::Block)
+        );
+    }
+
+    #[test]
+    fn virtio_device_type_invalid() {
+        // Non-VirtIO vendor ID.
+        assert_eq!(
+            virtio_device_type(&DeviceFunctionInfo {
+                vendor_id: 0x1234,
+                device_id: TRANSITIONAL_BLOCK,
+                class: 0,
+                subclass: 0,
+                prog_if: 0,
+                revision: 0,
+                header_type: bus::HeaderType::Standard,
+            }),
+            None
+        );
+
+        // Invalid device ID.
+        assert_eq!(
+            virtio_device_type(&DeviceFunctionInfo {
+                vendor_id: VIRTIO_VENDOR_ID,
+                device_id: 0x1040,
+                class: 0,
+                subclass: 0,
+                prog_if: 0,
+                revision: 0,
+                header_type: bus::HeaderType::Standard,
+            }),
+            None
+        );
+    }
 }