diff options
Diffstat (limited to 'devices/src/virtio/controller.rs')
-rw-r--r-- | devices/src/virtio/controller.rs | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/devices/src/virtio/controller.rs b/devices/src/virtio/controller.rs index 33dbdd4..c5d2ef4 100644 --- a/devices/src/virtio/controller.rs +++ b/devices/src/virtio/controller.rs @@ -37,7 +37,7 @@ use std::thread; use super::resource_bridge::*; use super::{Interrupt, InterruptProxyEvent, Queue, VirtioDevice, TYPE_WL, VIRTIO_F_VERSION_1}; use crate::{ - pci::{PciAddress, PciBarConfiguration}, + pci::{PciAddress, PciBarConfiguration, PciCapability, PciCapabilityID}, MemoryParams, }; use vm_control::{MaybeOwnedFd, VmMemoryControlRequestSocket}; @@ -47,6 +47,33 @@ use serde::{Deserialize, Serialize}; use sys_util::net::UnixSeqpacket; use sys_util::{error, EventFd, GuestMemory, PollContext, PollToken, SharedMemory}; +// As far as I can tell, these never change on the other side, so it's +// fine to just copy them over. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct RemotePciCapability { + bytes: Vec<u8>, + id: PciCapabilityID, +} + +impl RemotePciCapability { + pub fn from(capability: &dyn PciCapability) -> Self { + Self { + bytes: capability.bytes().to_vec(), + id: capability.id(), + } + } +} + +impl PciCapability for RemotePciCapability { + fn bytes(&self) -> &[u8] { + &self.bytes + } + + fn id(&self) -> PciCapabilityID { + self.id + } +} + #[derive(Debug, MsgOnSocket)] pub enum MsgOnSocketRequest { Create { @@ -79,6 +106,7 @@ pub enum BincodeRequest { WriteConfig { offset: u64, data: Vec<u8> }, GetDeviceBars(PciAddress), + GetDeviceCaps, } pub type Request = poly_msg_socket::Value<MsgOnSocketRequest, BincodeRequest>; @@ -106,6 +134,7 @@ pub enum BincodeResponse { ReadConfig(Vec<u8>), GetDeviceBars(Vec<PciBarConfiguration>), + GetDeviceCaps(Vec<RemotePciCapability>), } pub type Response = poly_msg_socket::Value<MsgOnSocketResponse, BincodeResponse>; @@ -406,4 +435,20 @@ impl VirtioDevice for Controller { } } } + + fn get_device_caps(&self) -> Vec<Box<dyn PciCapability>> { + if let Err(e) = self.socket.send(BincodeRequest::GetDeviceCaps) { + panic!("failed to send GetDeviceCaps: {}", e); + } + + match self.socket.recv_bincode() { + Ok(BincodeResponse::GetDeviceCaps(caps)) => caps + .into_iter() + .map(|cap| Box::new(cap) as Box<dyn PciCapability>) + .collect(), + response => { + panic!("bad response to GetDeviceCaps: {:?}", response); + } + } + } } |