⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/drivers/
gpu_i915.rs

1//! Intel i915/Xe GPU Driver Framework
2//!
3//! Provides PCI device detection and structured types for Intel integrated
4//! and discrete GPUs. Actual register programming requires hardware access
5//! not available in QEMU's virtio-gpu environment.
6
7#![allow(dead_code)]
8
9#[cfg(target_arch = "x86_64")]
10use alloc::format;
11use alloc::{string::String, vec::Vec};
12
13use crate::error::KernelError;
14
15// ---------------------------------------------------------------------------
16// PCI Device IDs
17// ---------------------------------------------------------------------------
18
19/// Intel GPU PCI device IDs (subset of common devices)
20pub mod device_ids {
21    // Intel HD Graphics / UHD Graphics / Iris
22    /// Tiger Lake LP GT2 (11th gen mobile)
23    pub const TIGERLAKE_LP_GT2: u16 = 0x9A49;
24    /// Alder Lake S GT1 (12th gen desktop)
25    pub const ALDERLAKE_S_GT1: u16 = 0x4680;
26    /// Raptor Lake S GT1 (13th gen desktop)
27    pub const RAPTORLAKE_S_GT1: u16 = 0xA780;
28    /// Meteor Lake GT2 (14th gen mobile)
29    pub const METEORLAKE_GT2: u16 = 0x7D55;
30
31    // Intel Arc (Xe/DG2)
32    /// Arc A770 (DG2-512EU)
33    pub const ARC_A770: u16 = 0x56A0;
34    /// Arc A750 (DG2-448EU)
35    pub const ARC_A750: u16 = 0x56A1;
36    /// Arc A380 (DG2-128EU)
37    pub const ARC_A380: u16 = 0x56A5;
38}
39
40// ---------------------------------------------------------------------------
41// GPU Generation Classification
42// ---------------------------------------------------------------------------
43
44/// Intel GPU generation
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum IntelGeneration {
47    /// Skylake / Kaby Lake / Coffee Lake
48    Gen9,
49    /// Ice Lake
50    Gen11,
51    /// Tiger Lake
52    Gen12,
53    /// Alder Lake / Raptor Lake
54    Gen12p5,
55    /// Meteor Lake
56    Gen12p7,
57    /// Arc discrete GPUs (DG2)
58    XeHpg,
59    /// Unrecognised device ID
60    Unknown,
61}
62
63impl core::fmt::Display for IntelGeneration {
64    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65        match self {
66            Self::Gen9 => write!(f, "Gen9"),
67            Self::Gen11 => write!(f, "Gen11"),
68            Self::Gen12 => write!(f, "Gen12"),
69            Self::Gen12p5 => write!(f, "Gen12.5"),
70            Self::Gen12p7 => write!(f, "Gen12.7"),
71            Self::XeHpg => write!(f, "Xe-HPG"),
72            Self::Unknown => write!(f, "Unknown"),
73        }
74    }
75}
76
77// ---------------------------------------------------------------------------
78// MMIO Register Offsets
79// ---------------------------------------------------------------------------
80
81/// MMIO register block offsets (per i915 driver documentation)
82pub mod regs {
83    /// Render ring base
84    pub const RENDER_RING_BASE: u64 = 0x02000;
85    /// Blitter ring base
86    pub const BLITTER_RING_BASE: u64 = 0x22000;
87    /// Video decode ring base
88    pub const VIDEO_RING_BASE: u64 = 0x12000;
89    /// Display pipe A registers
90    pub const DISPLAY_PIPE_A: u64 = 0x60000;
91    /// Display pipe B registers
92    pub const DISPLAY_PIPE_B: u64 = 0x61000;
93    /// Graphics Translation Table base
94    pub const GTT_BASE: u64 = 0x100000;
95    /// Fence register base (tiling)
96    pub const FENCE_REG_BASE: u64 = 0x02000;
97    /// Instruction parser mode
98    pub const INSTPM: u64 = 0x020C0;
99    /// Forcewake register
100    pub const FORCEWAKE: u64 = 0x0A188;
101    /// Hardware status page address
102    pub const HWS_PGA: u64 = 0x04080;
103    /// Ring buffer control
104    pub const RING_CTL: u64 = 0x0203C;
105}
106
107// ---------------------------------------------------------------------------
108// Display Types
109// ---------------------------------------------------------------------------
110
111/// Display pipe configuration
112#[derive(Debug, Clone)]
113pub struct DisplayPipe {
114    /// Pipe index (0 = A, 1 = B, etc.)
115    pub pipe_id: u8,
116    /// Horizontal resolution
117    pub width: u32,
118    /// Vertical resolution
119    pub height: u32,
120    /// Refresh rate in Hz
121    pub refresh_rate: u32,
122    /// Whether the pipe is currently active
123    pub enabled: bool,
124    /// Framebuffer pixel format
125    pub pixel_format: DisplayPixelFormat,
126}
127
128/// Display framebuffer pixel format
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub enum DisplayPixelFormat {
131    /// 32-bit XRGB (8:8:8:8, X ignored)
132    Xrgb8888,
133    /// 32-bit ARGB (8:8:8:8, alpha blended)
134    Argb8888,
135    /// 30-bit deep colour (10:10:10:2)
136    Xrgb2101010,
137    /// 32-bit XBGR (reversed channel order)
138    Xbgr8888,
139}
140
141// ---------------------------------------------------------------------------
142// Memory Types
143// ---------------------------------------------------------------------------
144
145/// Graphics Translation Table (GTT) entry
146#[derive(Debug, Clone, Copy)]
147pub struct GttEntry {
148    /// Physical address of the page
149    pub physical_addr: u64,
150    /// Entry is valid / present
151    pub valid: bool,
152    /// Page is writeable
153    pub writeable: bool,
154    /// Cache level for the mapping
155    pub cache_level: CacheLevel,
156}
157
158/// Cache level for GTT mappings
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160pub enum CacheLevel {
161    /// Uncached (UC) -- MMIO regions
162    Uncached,
163    /// Write-combining (WC) -- framebuffer
164    WriteCombining,
165    /// Cached (LLC) -- general GPU memory
166    Cached,
167}
168
169// ---------------------------------------------------------------------------
170// Device Representation
171// ---------------------------------------------------------------------------
172
173/// Intel GPU device instance
174pub struct I915Device {
175    /// PCI vendor ID (always 0x8086 for Intel)
176    pub vendor_id: u16,
177    /// PCI device ID
178    pub device_id: u16,
179    /// Classified GPU generation
180    pub generation: IntelGeneration,
181    /// BAR0 MMIO base address
182    pub mmio_base: u64,
183    /// BAR0 MMIO region size
184    pub mmio_size: u64,
185    /// GTT aperture size (detected during init)
186    pub gtt_size: u64,
187    /// Dedicated VRAM size (0 for integrated)
188    pub vram_size: u64,
189    /// Configured display pipes
190    pub display_pipes: Vec<DisplayPipe>,
191    /// Human-readable device name
192    pub name: String,
193}
194
195impl I915Device {
196    /// Classify GPU generation from PCI device ID.
197    ///
198    /// Device ID ranges are derived from the upstream i915 and xe driver
199    /// source tables.
200    pub fn classify_generation(device_id: u16) -> IntelGeneration {
201        match device_id {
202            // Skylake / Kaby Lake / Coffee Lake
203            0x1900..=0x19FF | 0x5900..=0x59FF | 0x3E90..=0x3EFF => IntelGeneration::Gen9,
204            // Ice Lake
205            0x8A50..=0x8AFF => IntelGeneration::Gen11,
206            // Tiger Lake
207            0x9A40..=0x9A7F => IntelGeneration::Gen12,
208            // Alder Lake / Raptor Lake
209            0x4680..=0x46FF | 0xA780..=0xA7FF => IntelGeneration::Gen12p5,
210            // Meteor Lake
211            0x7D40..=0x7DFF => IntelGeneration::Gen12p7,
212            // Arc DG2 discrete
213            0x56A0..=0x56BF => IntelGeneration::XeHpg,
214            _ => IntelGeneration::Unknown,
215        }
216    }
217
218    /// Return `true` if this is a discrete GPU (Arc).
219    pub fn is_discrete(&self) -> bool {
220        self.generation == IntelGeneration::XeHpg
221    }
222}
223
224// ---------------------------------------------------------------------------
225// PCI Probing
226// ---------------------------------------------------------------------------
227
228/// Probe the PCI bus for Intel GPU devices (x86_64 only).
229///
230/// Returns a list of detected Intel display-class devices with generation
231/// classification and BAR0 information. No register programming is performed.
232#[cfg(target_arch = "x86_64")]
233pub fn probe() -> Vec<I915Device> {
234    let mut devices = Vec::new();
235
236    if !crate::drivers::pci::is_pci_initialized() {
237        return devices;
238    }
239
240    let bus = crate::drivers::pci::get_pci_bus().lock();
241    let pci_devices = bus.find_devices_by_class(crate::drivers::pci::class_codes::DISPLAY);
242
243    for pci_dev in &pci_devices {
244        if pci_dev.vendor_id != 0x8086 {
245            continue;
246        }
247
248        let gen = I915Device::classify_generation(pci_dev.device_id);
249
250        let (mmio_base, mmio_size) = pci_dev
251            .bars
252            .first()
253            .map(|bar| match bar {
254                crate::drivers::pci::PciBar::Memory { address, size, .. } => (*address, *size),
255                _ => (0, 0),
256            })
257            .unwrap_or((0, 0));
258
259        devices.push(I915Device {
260            vendor_id: pci_dev.vendor_id,
261            device_id: pci_dev.device_id,
262            generation: gen,
263            mmio_base,
264            mmio_size,
265            gtt_size: 0,
266            vram_size: 0,
267            display_pipes: Vec::new(),
268            name: format!("Intel GPU {:04x} ({})", pci_dev.device_id, gen),
269        });
270    }
271
272    devices
273}
274
275/// Stub probe for non-x86_64 architectures (Intel GPUs are x86-only).
276#[cfg(not(target_arch = "x86_64"))]
277pub fn probe() -> Vec<I915Device> {
278    Vec::new()
279}
280
281// ---------------------------------------------------------------------------
282// Initialization
283// ---------------------------------------------------------------------------
284
285/// Initialize the Intel i915 GPU driver (detection only).
286///
287/// Scans the PCI bus for Intel display-class devices and logs any found.
288/// No register programming or mode setting is performed.
289pub fn init() -> Result<(), KernelError> {
290    let devices = probe();
291
292    if devices.is_empty() {
293        crate::println!("[i915] No Intel GPU devices found");
294    } else {
295        for dev in &devices {
296            crate::println!(
297                "[i915] Found: {} (BAR0: {:#x}, size: {:#x})",
298                dev.name,
299                dev.mmio_base,
300                dev.mmio_size
301            );
302        }
303    }
304
305    Ok(())
306}