blob: 41aae0a3d2f88d9f11501ea56ac0f0d53b3eaf1b [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
2-- Copyright (C) 2015-2016 secunet Security Networks AG
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
Nico Huber125a29e2016-10-18 00:23:54 +02006-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02008--
9-- This program is distributed in the hope that it will be useful,
10-- but WITHOUT ANY WARRANTY; without even the implied warranty of
11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-- GNU General Public License for more details.
13--
14
Nico Huber83693c82016-10-08 22:17:55 +020015with HW.Time;
16with HW.MMIO_Range;
17pragma Elaborate_All (HW.MMIO_Range);
18
19with HW.Debug;
20with GNAT.Source_Info;
21
Nico Huber83693c82016-10-08 22:17:55 +020022use type HW.Word64;
23
24package body HW.GFX.GMA.Registers
25with
26 Refined_State =>
Nico Huber0b2329a2018-06-09 21:14:27 +020027 (Address_State =>
28 (Regs.Base_Address, GTT_32.Base_Address, GTT_64.Base_Address),
Nico Huber83693c82016-10-08 22:17:55 +020029 Register_State => Regs.State,
Nico Huber0b2329a2018-06-09 21:14:27 +020030 GTT_State => (GTT_32.State, GTT_64.State))
Nico Huber83693c82016-10-08 22:17:55 +020031is
32 pragma Disable_Atomic_Synchronization;
33
34 type Registers_Range is
35 new Natural range 0 .. 16#0020_0000# / Register_Width - 1;
36 type Registers_Type is array (Registers_Range) of Word32
37 with
38 Atomic_Components,
39 Size => 16#20_0000# * 8;
40 package Regs is new MMIO_Range
41 (Base_Addr => Config.Default_MMIO_Base,
42 Element_T => Word32,
43 Index_T => Registers_Range,
44 Array_T => Registers_Type);
45
46 ----------------------------------------------------------------------------
47
Arthur Heymans3f37cce2026-03-03 18:52:12 +010048 MMIO_GTT_32_Size : constant := 16#20_0000#;
49 -- Limit Broadwell+ to 4MiB to have a stable
50 -- interface (i.e. same number of entries):
51 MMIO_GTT_64_Size : constant := 16#40_0000#;
52
Nico Huber0b2329a2018-06-09 21:14:27 +020053 type GTT_PTE_32 is mod 2 ** 32;
54 type GTT_Registers_32 is array (GTT_Range) of GTT_PTE_32
Nico Huber83693c82016-10-08 22:17:55 +020055 with
56 Volatile_Components,
Nico Huber0b2329a2018-06-09 21:14:27 +020057 Size => MMIO_GTT_32_Size * 8;
58 package GTT_32 is new MMIO_Range
Arthur Heymans3f37cce2026-03-03 18:52:12 +010059 (Base_Addr =>
60 Config.Default_MMIO_Base + Word64 (Config.Default_MMIO_GTT_32_Offset),
Nico Huber0b2329a2018-06-09 21:14:27 +020061 Element_T => GTT_PTE_32,
Nico Huber83693c82016-10-08 22:17:55 +020062 Index_T => GTT_Range,
Nico Huber0b2329a2018-06-09 21:14:27 +020063 Array_T => GTT_Registers_32);
64
65 type GTT_PTE_64 is mod 2 ** 64;
66 type GTT_Registers_64 is array (GTT_Range) of GTT_PTE_64
67 with
68 Volatile_Components,
69 Size => MMIO_GTT_64_Size * 8;
70 package GTT_64 is new MMIO_Range
Arthur Heymans3f37cce2026-03-03 18:52:12 +010071 (Base_Addr => Config.Default_MMIO_Base + Word64 (Config.MMIO_GTT_64_Offset),
Nico Huber0b2329a2018-06-09 21:14:27 +020072 Element_T => GTT_PTE_64,
73 Index_T => GTT_Range,
74 Array_T => GTT_Registers_64);
Nico Huber83693c82016-10-08 22:17:55 +020075
Nico Huberceda17d2018-06-09 22:00:29 +020076 GTT_PTE_Valid : constant := 1;
Nico Huber83693c82016-10-08 22:17:55 +020077
78 ----------------------------------------------------------------------------
79
Nico Huberd0d8b792018-06-09 19:45:00 +020080 subtype Fence_Range is Natural range 0 .. 31;
Nico Huberb03c8f12017-08-25 13:29:08 +020081
82 FENCE_PAGE_SHIFT : constant := 12;
83 FENCE_PAGE_MASK : constant := 16#ffff_f000#;
Nico Huberb03c8f12017-08-25 13:29:08 +020084 FENCE_VALID : constant := 1 * 2 ** 0;
85
Arthur Heymans960e2392026-03-03 19:45:24 +010086 -- Gen4+ (i965/G45+): 64-bit fence pairs at Fence_Base + i*8
87 FENCE_TILE_WALK_YMAJOR : constant := 1 * 2 ** 1;
88
Nico Huberb03c8f12017-08-25 13:29:08 +020089 function Fence_Lower_Idx (Fence : Fence_Range) return Registers_Range is
Nico Huberd0d8b792018-06-09 19:45:00 +020090 (Registers_Range (Config.Fence_Base / Register_Width + 2 * Fence));
Nico Huberb03c8f12017-08-25 13:29:08 +020091 function Fence_Upper_Idx (Fence : Fence_Range) return Registers_Range is
92 (Fence_Lower_Idx (Fence) + 1);
93
Arthur Heymans960e2392026-03-03 19:45:24 +010094 -- Gen3 (i915/i945): 32-bit fences, split layout:
95 -- Fences 0-7: 0x2000 + i*4
96 -- Fences 8-15: 0x3000 + (i-8)*4
97 -- FENCE_REG(i) = 0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4
98 GEN3_FENCE_TILING_Y_SHIFT : constant := 12;
99 GEN3_FENCE_SIZE_SHIFT : constant := 8;
100 GEN3_FENCE_PITCH_SHIFT : constant := 4;
101
102 function Gen3_Fence_Idx (Fence : Fence_Range) return Registers_Range is
103 (Registers_Range
104 ((16#2000# + (Fence / 8) * 16#1000# + (Fence mod 8) * 4) /
105 Register_Width));
106
107 -- Compute floor(log2(n)) for n >= 1 (fence size/pitch encoding).
108 function Floor_Log2 (N : Word32) return Natural
109 with
110 Pre => N >= 1
111 is
112 Result : Natural := 0;
113 Val : Word32 := N;
114 begin
115 for I in 0 .. 31 loop
116 exit when Val <= 1;
117 Val := Shift_Right (Val, 1);
118 Result := I + 1;
119 end loop;
120 return Result;
121 end Floor_Log2;
122
Nico Huber17d64b62017-07-15 20:51:25 +0200123 procedure Clear_Fences
124 is
Nico Huber17d64b62017-07-15 20:51:25 +0200125 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100126 if Config.Has_Gen3_Fences then
127 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
128 Regs.Write (Gen3_Fence_Idx (Fence), 0);
129 end loop;
130 else
131 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
132 Regs.Write (Fence_Lower_Idx (Fence), 0);
133 end loop;
134 end if;
Nico Huber17d64b62017-07-15 20:51:25 +0200135 end Clear_Fences;
136
Nico Huberb03c8f12017-08-25 13:29:08 +0200137 procedure Add_Fence
138 (First_Page : in GTT_Range;
139 Last_Page : in GTT_Range;
140 Tiling : in XY_Tiling;
141 Pitch : in Natural;
142 Success : out Boolean)
143 is
144 Y_Tiles : constant Boolean := Tiling = Y_Tiled;
145 Reg32 : Word32;
146 begin
147 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
148 pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (First_Page), 12)));
149 pragma Debug (Debug.Put (":"));
150 pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (Last_Page), 12)));
151 pragma Debug (not Y_Tiles, Debug.Put (" X tiled in "));
152 pragma Debug ( Y_Tiles, Debug.Put (" Y tiled in "));
153 pragma Debug (Debug.Put_Int32 (Int32 (Pitch)));
154 pragma Debug (Debug.Put_Line (" tiles per row."));
155
156 Success := False;
Arthur Heymans960e2392026-03-03 19:45:24 +0100157
158 if Config.Has_Gen3_Fences then
159 -- Gen3 i945: single 32-bit fence register per fence
160 -- Format: start[31:20] | tiling_y[12] | size_bits[11:8] |
161 -- pitch_log2[7:4] | valid[0]
162 -- stride: Y-tiled /128, X-tiled /512 (i945 has 128-byte Y tiling)
163 -- size_bits: log2(size_in_pages / 256) = log2(size_in_MB)
164 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
165 Regs.Read (Reg32, Gen3_Fence_Idx (Fence));
166 if (Reg32 and FENCE_VALID) = 0 then
167 declare
168 Start_Addr : constant Word32 :=
169 Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT);
170 Size_Pages : constant Word32 :=
171 Word32 (Last_Page - First_Page + 1);
172 -- Size in MB (pages / 256, since page = 4KB, 256*4KB = 1MB)
173 Size_MB : constant Word32 := Size_Pages / 256;
174 -- Pitch in tiles (X: 512B tiles, Y: 128B tiles for i945)
175 Stride : constant Word32 :=
176 Word32 (Pitch) / (if Y_Tiles then 128 else 512);
177 Size_Bits : constant Word32 :=
178 (if Size_MB >= 1
179 then Word32 (Floor_Log2 (Size_MB))
180 else 0);
181 begin
182 Regs.Write
183 (Index => Gen3_Fence_Idx (Fence),
184 Value => Start_Addr or
185 (if Y_Tiles
186 then Shift_Left (1, GEN3_FENCE_TILING_Y_SHIFT)
187 else 0) or
188 Shift_Left (Size_Bits, GEN3_FENCE_SIZE_SHIFT) or
189 Shift_Left
190 ((if Stride >= 1
191 then Word32 (Floor_Log2 (Stride))
192 else 0),
193 GEN3_FENCE_PITCH_SHIFT) or
194 FENCE_VALID);
195 end;
196 Success := True;
197 exit;
198 end if;
199 end loop;
200 else
201 -- Gen4+ (i965/G45+): 64-bit fence register pairs
202 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
203 Regs.Read (Reg32, Fence_Lower_Idx (Fence));
204 if (Reg32 and FENCE_VALID) = 0 then
205 Regs.Write
206 (Index => Fence_Lower_Idx (Fence),
207 Value => Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT) or
208 (if Y_Tiles then FENCE_TILE_WALK_YMAJOR else 0) or
209 FENCE_VALID);
210 Regs.Write
211 (Index => Fence_Upper_Idx (Fence),
212 Value => Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT) or
213 Word32 (Pitch) * (if Y_Tiles then 1 else 4) - 1);
214 Success := True;
215 exit;
216 end if;
217 end loop;
218 end if;
Nico Huberb03c8f12017-08-25 13:29:08 +0200219 end Add_Fence;
220
221 procedure Remove_Fence (First_Page, Last_Page : GTT_Range)
222 is
223 Page_Lower : constant Word32 :=
224 Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT);
Arthur Heymans960e2392026-03-03 19:45:24 +0100225 Reg32 : Word32;
Nico Huberb03c8f12017-08-25 13:29:08 +0200226 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100227 if Config.Has_Gen3_Fences then
228 -- Gen3: match start address in single 32-bit register
229 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
230 Regs.Read (Reg32, Gen3_Fence_Idx (Fence));
231 if (Reg32 and FENCE_VALID) /= 0 and
232 (Reg32 and 16#fff0_0000#) = (Page_Lower and 16#fff0_0000#)
233 then
234 Regs.Write (Gen3_Fence_Idx (Fence), 0);
235 exit;
236 end if;
237 end loop;
238 else
239 -- Gen4+: match start in lower, end in upper register
240 declare
241 Page_Upper : constant Word32 :=
242 Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT);
243 Fence_Upper, Fence_Lower : Word32;
244 begin
245 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
246 Regs.Read (Fence_Lower, Fence_Lower_Idx (Fence));
247 Regs.Read (Fence_Upper, Fence_Upper_Idx (Fence));
248 if (Fence_Lower and FENCE_PAGE_MASK) = Page_Lower and
249 (Fence_Upper and FENCE_PAGE_MASK) = Page_Upper
250 then
251 Regs.Write (Fence_Lower_Idx (Fence), 0);
252 exit;
253 end if;
254 end loop;
255 end;
256 end if;
Nico Huberb03c8f12017-08-25 13:29:08 +0200257 end Remove_Fence;
258
Nico Huber17d64b62017-07-15 20:51:25 +0200259 ----------------------------------------------------------------------------
260
Nico Huber83693c82016-10-08 22:17:55 +0200261 procedure Write_GTT
262 (GTT_Page : GTT_Range;
263 Device_Address : GTT_Address_Type;
264 Valid : Boolean)
265 is
266 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100267 if Config.Has_I945_Simple_GTT_PTE then
268 -- i945: simple 32-bit PTE, no high address bits
269 GTT_32.Write
270 (Index => GTT_Page,
271 Value => GTT_PTE_32 (Device_Address and 16#ffff_f000#) or
272 Boolean'Pos (Valid));
273 elsif not Config.Has_64bit_GTT then
Nico Huber0b2329a2018-06-09 21:14:27 +0200274 GTT_32.Write
Nico Huber83693c82016-10-08 22:17:55 +0200275 (Index => GTT_Page,
Nico Huber0b2329a2018-06-09 21:14:27 +0200276 Value => GTT_PTE_32 (Device_Address and 16#ffff_f000#) or
277 GTT_PTE_32 (Shift_Right (Word64 (Device_Address), 32 - 4)
Nico Huber83693c82016-10-08 22:17:55 +0200278 and 16#0000_07f0#) or
279 Boolean'Pos (Valid));
280 else
Nico Huber0b2329a2018-06-09 21:14:27 +0200281 GTT_64.Write
Nico Huber83693c82016-10-08 22:17:55 +0200282 (Index => GTT_Page,
Nico Huber0b2329a2018-06-09 21:14:27 +0200283 Value => GTT_PTE_64 (Device_Address and 16#7f_ffff_f000#) or
Nico Huber83693c82016-10-08 22:17:55 +0200284 Boolean'Pos (Valid));
285 end if;
286 end Write_GTT;
287
Nico Huberceda17d2018-06-09 22:00:29 +0200288 procedure Read_GTT
289 (Device_Address : out GTT_Address_Type;
290 Valid : out Boolean;
291 GTT_Page : in GTT_Range)
292 is
293 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100294 if Config.Has_I945_Simple_GTT_PTE then
295 declare
296 PTE : GTT_PTE_32;
297 begin
298 GTT_32.Read (PTE, GTT_Page);
299 Valid := (PTE and GTT_PTE_Valid) /= 0;
300 Device_Address := GTT_Address_Type (PTE and 16#ffff_f000#);
301 end;
302 elsif not Config.Has_64bit_GTT then
Nico Huberceda17d2018-06-09 22:00:29 +0200303 declare
304 PTE : GTT_PTE_32;
305 begin
306 GTT_32.Read (PTE, GTT_Page);
307 Valid := (PTE and GTT_PTE_Valid) /= 0;
308 Device_Address := GTT_Address_Type
309 (Shift_Left (Word64 (PTE and 16#07f0#), 32 - 4) or
310 Word64 (PTE and 16#ffff_f000#));
311 end;
312 else
313 declare
314 PTE : GTT_PTE_64;
315 begin
316 GTT_64.Read (PTE, GTT_Page);
317 Valid := (PTE and GTT_PTE_Valid) /= 0;
318 Device_Address := GTT_Address_Type (PTE and 16#7f_ffff_f000#);
319 end;
320 end if;
321 end Read_GTT;
322
Nico Huber83693c82016-10-08 22:17:55 +0200323 ----------------------------------------------------------------------------
324
325 package Rep is
326 function Index (Reg : Registers_Index) return Registers_Range;
327 end Rep;
328
329 package body Rep is
330 function Index (Reg : Registers_Index) return Registers_Range
331 with
332 SPARK_Mode => Off
333 is
334 begin
335 return Reg'Enum_Rep;
336 end Index;
337 end Rep;
338
339 -- Read a specific register
340 procedure Read
341 (Register : in Registers_Index;
342 Value : out Word32;
343 Verbose : in Boolean := True)
344 is
345 begin
346 Regs.Read (Value, Rep.Index (Register));
347
348 pragma Debug (Verbose, Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
349 pragma Debug (Verbose, Debug.Put_Word32 (Value));
350 pragma Debug (Verbose, Debug.Put (" <- "));
351 pragma Debug (Verbose, Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
352 pragma Debug (Verbose, Debug.Put (":"));
353 pragma Debug (Verbose, Debug.Put_Line (Registers_Index'Image (Register)));
354 end Read;
355
Arthur Heymans3f37cce2026-03-03 18:52:12 +0100356 procedure Read_AUD_VID_DID (Value : out Word32)
357 is
358 begin
359 Regs.Read
360 (Value,
361 Registers_Range (Config.AUD_VID_DID_Offset / Register_Width));
362 end Read_AUD_VID_DID;
363
Nico Huber83693c82016-10-08 22:17:55 +0200364 ----------------------------------------------------------------------------
365
366 -- Read a specific register to post a previous write
367 procedure Posting_Read (Register : Registers_Index)
368 is
369 Discard_Value : Word32;
370 begin
371 pragma Warnings
372 (Off, "unused assignment to ""Discard_Value""",
373 Reason => "Intentional dummy read to affect hardware.");
374
375 Read (Register, Discard_Value);
376
377 pragma Warnings
378 (On, "unused assignment to ""Discard_Value""");
379 end Posting_Read;
380
381 ----------------------------------------------------------------------------
382
383 -- Write a specific register
Nico Huberaae8a352020-06-15 13:09:29 +0200384 procedure Write
385 (Register : Registers_Index;
386 Value : Word32;
387 Verbose : Boolean := True)
Nico Huber83693c82016-10-08 22:17:55 +0200388 is
389 begin
Nico Huberaae8a352020-06-15 13:09:29 +0200390 pragma Debug (Verbose, Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
391 pragma Debug (Verbose, Debug.Put_Word32 (Value));
392 pragma Debug (Verbose, Debug.Put (" -> "));
393 pragma Debug (Verbose, Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
394 pragma Debug (Verbose, Debug.Put (":"));
395 pragma Debug (Verbose, Debug.Put_Line (Registers_Index'Image (Register)));
Nico Huber83693c82016-10-08 22:17:55 +0200396
397 Regs.Write (Rep.Index (Register), Value);
398 pragma Debug (Debug.Register_Write_Wait);
399 end Write;
400
401 ----------------------------------------------------------------------------
402
403 -- Check whether all bits in @Register@ indicated by @Mask@ are set
404 procedure Is_Set_Mask
405 (Register : in Registers_Index;
406 Mask : in Word32;
407 Result : out Boolean)
408 is
409 Value : Word32;
410 begin
411 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
412 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
413
414 Read (Register, Value);
415 Result := (Value and Mask) = Mask;
416
417 end Is_Set_Mask;
418
419 ----------------------------------------------------------------------------
420
Nico Huber82ca09f2019-09-28 02:37:50 +0200421 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_Success""");
422
Nico Huberbcb2c472017-02-02 16:39:26 +0100423 -- Wait for the bits in @Register@ indicated by @Mask@ to be of @Value@
424 procedure Wait
Nico Huber82ca09f2019-09-28 02:37:50 +0200425 (Register : in Registers_Index;
426 Mask : in Word32;
427 Value : in Word32;
428 TOut_MS : in Natural := Default_Timeout_MS;
429 Verbose : in Boolean := False;
430 Success : out Boolean)
Nico Huberbcb2c472017-02-02 16:39:26 +0100431 is
432 Current : Word32;
433 Timeout : Time.T;
Nico Huber82ca09f2019-09-28 02:37:50 +0200434 Timed_Out : Boolean := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100435 begin
436 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
437 pragma Debug (Debug.Put_Word32 (Value));
438 pragma Debug (Debug.Put (" <- "));
439 pragma Debug (Debug.Put_Word32 (Mask));
440 pragma Debug (Debug.Put (" & "));
441 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
442 pragma Debug (Debug.Put (":"));
443 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
444
445 Timeout := Time.MS_From_Now (TOut_MS);
446 loop
Nico Huberbcb2c472017-02-02 16:39:26 +0100447 Read (Register, Current, Verbose);
448 if (Current and Mask) = Value then
Nico Huber82ca09f2019-09-28 02:37:50 +0200449 -- Ignore timeout if we succeeded anyway.
450 Timed_Out := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100451 exit;
452 end if;
453 pragma Debug (Timed_Out, Debug.Put (GNAT.Source_Info.Enclosing_Entity));
454 pragma Debug (Timed_Out, Debug.Put_Line (": Timed Out!"));
455 exit when Timed_Out;
Nico Huber82ca09f2019-09-28 02:37:50 +0200456
457 Timed_Out := Time.Timed_Out (Timeout);
Nico Huberbcb2c472017-02-02 16:39:26 +0100458 end loop;
Nico Huber82ca09f2019-09-28 02:37:50 +0200459
460 Success := not Timed_Out;
461 end Wait;
462
463 procedure Wait
464 (Register : Registers_Index;
465 Mask : Word32;
466 Value : Word32;
467 TOut_MS : Natural := Default_Timeout_MS;
468 Verbose : Boolean := False)
469 is
470 Ignored_Success : Boolean;
471 begin
472 Wait (Register, Mask, Value, TOut_MS, Verbose, Ignored_Success);
Nico Huberbcb2c472017-02-02 16:39:26 +0100473 end Wait;
474
475 ----------------------------------------------------------------------------
476
Nico Huber83693c82016-10-08 22:17:55 +0200477 -- Wait for all bits in @Register@ indicated by @Mask@ to be set
478 procedure Wait_Set_Mask
479 (Register : in Registers_Index;
480 Mask : in Word32;
481 TOut_MS : in Natural := Default_Timeout_MS;
Nico Huber82ca09f2019-09-28 02:37:50 +0200482 Verbose : in Boolean := False;
483 Success : out Boolean) is
Nico Huber83693c82016-10-08 22:17:55 +0200484 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200485 Wait (Register, Mask, Mask, TOut_MS, Verbose, Success);
486 end Wait_Set_Mask;
487
488 procedure Wait_Set_Mask
489 (Register : Registers_Index;
490 Mask : Word32;
491 TOut_MS : Natural := Default_Timeout_MS;
492 Verbose : Boolean := False)
493 is
494 Ignored_Success : Boolean;
495 begin
496 Wait (Register, Mask, Mask, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200497 end Wait_Set_Mask;
498
499 ----------------------------------------------------------------------------
500
Nico Huber83693c82016-10-08 22:17:55 +0200501 -- Wait for bits in @Register@ indicated by @Mask@ to be clear
502 procedure Wait_Unset_Mask
Nico Huber82ca09f2019-09-28 02:37:50 +0200503 (Register : in Registers_Index;
504 Mask : in Word32;
505 TOut_MS : in Natural := Default_Timeout_MS;
506 Verbose : in Boolean := False;
507 Success : out Boolean) is
508 begin
509 Wait (Register, Mask, 0, TOut_MS, Verbose, Success);
Nico Huberac2a1412026-07-02 10:41:59 +0200510 end Wait_Unset_Mask;
Nico Huber82ca09f2019-09-28 02:37:50 +0200511
512 procedure Wait_Unset_Mask
Nico Huber83693c82016-10-08 22:17:55 +0200513 (Register : Registers_Index;
514 Mask : Word32;
Nico Huber82ca09f2019-09-28 02:37:50 +0200515 TOut_MS : Natural := Default_Timeout_MS;
516 Verbose : Boolean := False)
Nico Huber83693c82016-10-08 22:17:55 +0200517 is
Nico Huber82ca09f2019-09-28 02:37:50 +0200518 Ignored_Success : Boolean;
Nico Huber83693c82016-10-08 22:17:55 +0200519 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200520 Wait (Register, Mask, 0, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200521 end Wait_Unset_Mask;
522
523 ----------------------------------------------------------------------------
524
525 -- Set bits from @Mask@ in @Register@
526 procedure Set_Mask
527 (Register : Registers_Index;
528 Mask : Word32)
529 is
530 Value : Word32;
531 begin
532 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
533 pragma Debug (Debug.Put_Word32 (Mask));
534 pragma Debug (Debug.Put (" .S "));
535 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
536
537 Read (Register, Value);
538 Value := Value or Mask;
539 Write (Register, Value);
540 end Set_Mask;
541
542 ----------------------------------------------------------------------------
543
544 -- Mask out @Mask@ in @Register@
545 procedure Unset_Mask
546 (Register : Registers_Index;
547 Mask : Word32)
548 is
549 Value : Word32;
550 begin
551 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
552 pragma Debug (Debug.Put_Word32 (Mask));
553 pragma Debug (Debug.Put (" !S "));
554 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
555
556 Read (Register, Value);
557 Value := Value and not Mask;
558 Write (Register, Value);
559 end Unset_Mask;
560
561 ----------------------------------------------------------------------------
562
563 -- Mask out @Unset_Mask@ and set @Set_Mask@ in @Register@
564 procedure Unset_And_Set_Mask
565 (Register : Registers_Index;
566 Mask_Unset : Word32;
567 Mask_Set : Word32)
568 is
569 Value : Word32;
570 begin
571 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
572 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
573
574 Read (Register, Value);
575 Value := (Value and not Mask_Unset) or Mask_Set;
576 Write (Register, Value);
577 end Unset_And_Set_Mask;
578
579 ----------------------------------------------------------------------------
580
Nico Huber2b6f6992017-07-09 18:11:34 +0200581 procedure Set_Register_Base (Base : Word64; GTT_Base : Word64 := 0)
Nico Huber83693c82016-10-08 22:17:55 +0200582 is
583 begin
584 Regs.Set_Base_Address (Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200585 if GTT_Base = 0 then
Arthur Heymans3f37cce2026-03-03 18:52:12 +0100586 GTT_32.Set_Base_Address
587 (Base + Word64 (Config.Default_MMIO_GTT_32_Offset));
588 GTT_64.Set_Base_Address (Base + Word64 (Config.MMIO_GTT_64_Offset));
Nico Huber2b6f6992017-07-09 18:11:34 +0200589 else
Nico Huber0b2329a2018-06-09 21:14:27 +0200590 GTT_32.Set_Base_Address (GTT_Base);
591 GTT_64.Set_Base_Address (GTT_Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200592 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200593 end Set_Register_Base;
594
595end HW.GFX.GMA.Registers;