On Thu, Dec 5, 2024 at 3:16 PM Danilo Krummrich <dakr@xxxxxxxxxx> wrote: > > Implement the basic PCI abstractions required to write a basic PCI > driver. This includes the following data structures: > > The `pci::Driver` trait represents the interface to the driver and > provides `pci::Driver::probe` for the driver to implement. > > The `pci::Device` abstraction represents a `struct pci_dev` and provides > abstractions for common functions, such as `pci::Device::set_master`. > > In order to provide the PCI specific parts to a generic > `driver::Registration` the `driver::RegistrationOps` trait is implemented > by `pci::Adapter`. > > `pci::DeviceId` implements PCI device IDs based on the generic > `device_id::RawDevceId` abstraction. > > Co-developed-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxx> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxx> > Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx> > +/// The PCI device representation. > +/// > +/// A PCI device is based on an always reference counted `device:Device` instance. Cloning a PCI > +/// device, hence, also increments the base device' reference count. > +#[derive(Clone)] > +pub struct Device(ARef<device::Device>); It seems more natural for this to be a wrapper around `Opaque<bindings::pci_dev>`. Then you can have both &Device and ARef<Device> depending on whether you want to hold a refcount or not. Alice > +impl Device { > + /// Create a PCI Device instance from an existing `device::Device`. > + /// > + /// # Safety > + /// > + /// `dev` must be an `ARef<device::Device>` whose underlying `bindings::device` is a member of > + /// a `bindings::pci_dev`. > + pub unsafe fn from_dev(dev: ARef<device::Device>) -> Self { > + Self(dev) > + } > + > + fn as_raw(&self) -> *mut bindings::pci_dev { > + // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device` > + // embedded in `struct pci_dev`. > + unsafe { container_of!(self.0.as_raw(), bindings::pci_dev, dev) as _ } > + } > + > + /// Enable memory resources for this device. > + pub fn enable_device_mem(&self) -> Result { > + // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. > + let ret = unsafe { bindings::pci_enable_device_mem(self.as_raw()) }; > + if ret != 0 { > + Err(Error::from_errno(ret)) > + } else { > + Ok(()) > + } > + } > + > + /// Enable bus-mastering for this device. > + pub fn set_master(&self) { > + // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. > + unsafe { bindings::pci_set_master(self.as_raw()) }; > + } > +} > + > +impl AsRef<device::Device> for Device { > + fn as_ref(&self) -> &device::Device { > + &self.0 > + } > +} > -- > 2.47.0 >