100 lines · 2.9 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 use kernel::{    auxiliary,    device::Core,    pci,    pci::{        Class,        ClassMask,        Vendor, //    },    prelude::*,    sizes::SZ_16M,    sync::atomic::{        Atomic,        Relaxed, //    },    types::CovariantForLt,}; use crate::gpu::Gpu; /// Counter for generating unique auxiliary device IDs.static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0); #[pin_data]pub(crate) struct NovaCore<'bound> {    #[pin]    pub(crate) gpu: Gpu<'bound>,    bar: pci::Bar<'bound, BAR0_SIZE>,    #[allow(clippy::type_complexity)]    _reg: auxiliary::Registration<'bound, CovariantForLt!(())>,} pub(crate) struct NovaCoreDriver; const BAR0_SIZE: usize = SZ_16M; pub(crate) type Bar0<'a> = &'a pci::Bar<'a, BAR0_SIZE>; kernel::pci_device_table!(    PCI_TABLE,    <NovaCoreDriver as pci::Driver>::IdInfo,    [        // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.        (            pci::DeviceId::from_class_and_vendor(                Class::DISPLAY_VGA,                ClassMask::ClassSubclass,                Vendor::NVIDIA            ),            ()        ),        (            pci::DeviceId::from_class_and_vendor(                Class::DISPLAY_3D,                ClassMask::ClassSubclass,                Vendor::NVIDIA            ),            ()        ),    ]); impl pci::Driver for NovaCoreDriver {    type IdInfo = ();    type Data<'bound> = NovaCore<'bound>;    const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;     fn probe<'bound>(        pdev: &'bound pci::Device<Core<'_>>,        _info: Option<&'bound Self::IdInfo>,    ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {        pin_init::pin_init_scope(move || {            dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");             pdev.enable_device_mem()?;            pdev.set_master();             Ok(try_pin_init!(NovaCore {                bar: pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?,                // TODO: Use `&bar` self-referential pin-init syntax once available.                //                // SAFETY: `bar` is initialized before this expression is evaluated                // (`try_pin_init!()` initializes fields in declaration order), lives at a pinned                // stable address, and is dropped after `gpu` (struct field drop order).                gpu <- Gpu::new(pdev, unsafe { &*core::ptr::from_ref(bar) }),                _reg: auxiliary::Registration::new(                    pdev.as_ref(),                    c"nova-drm",                    // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For                    // now, use a simple atomic counter that never recycles IDs.                    AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed),                    crate::MODULE_NAME,                    (),                )?,            }))        })    }}