hermit/drivers/fs/
virtio_pci.rs

1use alloc::vec::Vec;
2
3use volatile::VolatileRef;
4
5use crate::arch::pci::PciConfigRegion;
6use crate::drivers::fs::virtio_fs::{FsDevCfg, VirtioFsDriver};
7use crate::drivers::pci::PciDevice;
8use crate::drivers::virtio::error::{self, VirtioError};
9use crate::drivers::virtio::transport::pci;
10use crate::drivers::virtio::transport::pci::{PciCap, UniCapsColl};
11
12impl VirtioFsDriver {
13	fn map_cfg(cap: &PciCap) -> Option<FsDevCfg> {
14		let dev_cfg = pci::map_dev_cfg::<virtio::fs::Config>(cap)?;
15
16		let dev_cfg = VolatileRef::from_ref(dev_cfg);
17
18		Some(FsDevCfg {
19			raw: dev_cfg,
20			dev_id: cap.dev_id(),
21			features: virtio::fs::F::empty(),
22		})
23	}
24
25	/// Instantiates a new (VirtioFsDriver)[VirtioFsDriver] struct, by checking the available
26	/// configuration structures and moving them into the struct.
27	pub fn new(
28		caps_coll: UniCapsColl,
29		device: &PciDevice<PciConfigRegion>,
30	) -> Result<Self, error::VirtioFsError> {
31		let device_id = device.device_id();
32
33		let UniCapsColl {
34			com_cfg,
35			notif_cfg,
36			isr_cfg,
37			dev_cfg_list,
38			..
39		} = caps_coll;
40
41		let Some(dev_cfg) = dev_cfg_list.iter().find_map(VirtioFsDriver::map_cfg) else {
42			error!("No dev config. Aborting!");
43			return Err(error::VirtioFsError::NoDevCfg(device_id));
44		};
45
46		Ok(VirtioFsDriver {
47			dev_cfg,
48			com_cfg,
49			isr_stat: isr_cfg,
50			notif_cfg,
51			vqueues: Vec::new(),
52			irq: device.get_irq().unwrap(),
53		})
54	}
55
56	/// Initializes virtio filesystem device
57	pub fn init(device: &PciDevice<PciConfigRegion>) -> Result<VirtioFsDriver, VirtioError> {
58		let mut drv = match pci::map_caps(device) {
59			Ok(caps) => match VirtioFsDriver::new(caps, device) {
60				Ok(driver) => driver,
61				Err(fs_err) => {
62					error!("Initializing new network driver failed. Aborting!");
63					return Err(VirtioError::FsDriver(fs_err));
64				}
65			},
66			Err(err) => {
67				error!("Mapping capabilities failed. Aborting!");
68				return Err(err);
69			}
70		};
71
72		match drv.init_dev() {
73			Ok(()) => info!(
74				"Filesystem device with id {:x}, has been initialized by driver!",
75				drv.get_dev_id()
76			),
77			Err(fs_err) => {
78				drv.set_failed();
79				return Err(VirtioError::FsDriver(fs_err));
80			}
81		}
82
83		Ok(drv)
84	}
85}