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}