blob: a59a4f7b117ccf5855dd4c4a51cc27140246f865 [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
384 procedure Write (Register : Registers_Index; Value : Word32)
385 is
386 begin
387 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
388 pragma Debug (Debug.Put_Word32 (Value));
389 pragma Debug (Debug.Put (" -> "));
390 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
391 pragma Debug (Debug.Put (":"));
392 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
393
394 Regs.Write (Rep.Index (Register), Value);
395 pragma Debug (Debug.Register_Write_Wait);
396 end Write;
397
398 ----------------------------------------------------------------------------
399
400 -- Check whether all bits in @Register@ indicated by @Mask@ are set
401 procedure Is_Set_Mask
402 (Register : in Registers_Index;
403 Mask : in Word32;
404 Result : out Boolean)
405 is
406 Value : Word32;
407 begin
408 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
409 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
410
411 Read (Register, Value);
412 Result := (Value and Mask) = Mask;
413
414 end Is_Set_Mask;
415
416 ----------------------------------------------------------------------------
417
Nico Huber82ca09f2019-09-28 02:37:50 +0200418 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_Success""");
419
Nico Huberbcb2c472017-02-02 16:39:26 +0100420 -- Wait for the bits in @Register@ indicated by @Mask@ to be of @Value@
421 procedure Wait
Nico Huber82ca09f2019-09-28 02:37:50 +0200422 (Register : in Registers_Index;
423 Mask : in Word32;
424 Value : in Word32;
425 TOut_MS : in Natural := Default_Timeout_MS;
426 Verbose : in Boolean := False;
427 Success : out Boolean)
Nico Huberbcb2c472017-02-02 16:39:26 +0100428 is
429 Current : Word32;
430 Timeout : Time.T;
Nico Huber82ca09f2019-09-28 02:37:50 +0200431 Timed_Out : Boolean := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100432 begin
433 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
434 pragma Debug (Debug.Put_Word32 (Value));
435 pragma Debug (Debug.Put (" <- "));
436 pragma Debug (Debug.Put_Word32 (Mask));
437 pragma Debug (Debug.Put (" & "));
438 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
439 pragma Debug (Debug.Put (":"));
440 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
441
442 Timeout := Time.MS_From_Now (TOut_MS);
443 loop
Nico Huberbcb2c472017-02-02 16:39:26 +0100444 Read (Register, Current, Verbose);
445 if (Current and Mask) = Value then
Nico Huber82ca09f2019-09-28 02:37:50 +0200446 -- Ignore timeout if we succeeded anyway.
447 Timed_Out := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100448 exit;
449 end if;
450 pragma Debug (Timed_Out, Debug.Put (GNAT.Source_Info.Enclosing_Entity));
451 pragma Debug (Timed_Out, Debug.Put_Line (": Timed Out!"));
452 exit when Timed_Out;
Nico Huber82ca09f2019-09-28 02:37:50 +0200453
454 Timed_Out := Time.Timed_Out (Timeout);
Nico Huberbcb2c472017-02-02 16:39:26 +0100455 end loop;
Nico Huber82ca09f2019-09-28 02:37:50 +0200456
457 Success := not Timed_Out;
458 end Wait;
459
460 procedure Wait
461 (Register : Registers_Index;
462 Mask : Word32;
463 Value : Word32;
464 TOut_MS : Natural := Default_Timeout_MS;
465 Verbose : Boolean := False)
466 is
467 Ignored_Success : Boolean;
468 begin
469 Wait (Register, Mask, Value, TOut_MS, Verbose, Ignored_Success);
Nico Huberbcb2c472017-02-02 16:39:26 +0100470 end Wait;
471
472 ----------------------------------------------------------------------------
473
Nico Huber83693c82016-10-08 22:17:55 +0200474 -- Wait for all bits in @Register@ indicated by @Mask@ to be set
475 procedure Wait_Set_Mask
476 (Register : in Registers_Index;
477 Mask : in Word32;
478 TOut_MS : in Natural := Default_Timeout_MS;
Nico Huber82ca09f2019-09-28 02:37:50 +0200479 Verbose : in Boolean := False;
480 Success : out Boolean) is
Nico Huber83693c82016-10-08 22:17:55 +0200481 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200482 Wait (Register, Mask, Mask, TOut_MS, Verbose, Success);
483 end Wait_Set_Mask;
484
485 procedure Wait_Set_Mask
486 (Register : Registers_Index;
487 Mask : Word32;
488 TOut_MS : Natural := Default_Timeout_MS;
489 Verbose : Boolean := False)
490 is
491 Ignored_Success : Boolean;
492 begin
493 Wait (Register, Mask, Mask, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200494 end Wait_Set_Mask;
495
496 ----------------------------------------------------------------------------
497
Nico Huber83693c82016-10-08 22:17:55 +0200498 -- Wait for bits in @Register@ indicated by @Mask@ to be clear
499 procedure Wait_Unset_Mask
Nico Huber82ca09f2019-09-28 02:37:50 +0200500 (Register : in Registers_Index;
501 Mask : in Word32;
502 TOut_MS : in Natural := Default_Timeout_MS;
503 Verbose : in Boolean := False;
504 Success : out Boolean) is
505 begin
506 Wait (Register, Mask, 0, TOut_MS, Verbose, Success);
507 end;
508
509 procedure Wait_Unset_Mask
Nico Huber83693c82016-10-08 22:17:55 +0200510 (Register : Registers_Index;
511 Mask : Word32;
Nico Huber82ca09f2019-09-28 02:37:50 +0200512 TOut_MS : Natural := Default_Timeout_MS;
513 Verbose : Boolean := False)
Nico Huber83693c82016-10-08 22:17:55 +0200514 is
Nico Huber82ca09f2019-09-28 02:37:50 +0200515 Ignored_Success : Boolean;
Nico Huber83693c82016-10-08 22:17:55 +0200516 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200517 Wait (Register, Mask, 0, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200518 end Wait_Unset_Mask;
519
520 ----------------------------------------------------------------------------
521
522 -- Set bits from @Mask@ in @Register@
523 procedure Set_Mask
524 (Register : Registers_Index;
525 Mask : Word32)
526 is
527 Value : Word32;
528 begin
529 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
530 pragma Debug (Debug.Put_Word32 (Mask));
531 pragma Debug (Debug.Put (" .S "));
532 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
533
534 Read (Register, Value);
535 Value := Value or Mask;
536 Write (Register, Value);
537 end Set_Mask;
538
539 ----------------------------------------------------------------------------
540
541 -- Mask out @Mask@ in @Register@
542 procedure Unset_Mask
543 (Register : Registers_Index;
544 Mask : Word32)
545 is
546 Value : Word32;
547 begin
548 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
549 pragma Debug (Debug.Put_Word32 (Mask));
550 pragma Debug (Debug.Put (" !S "));
551 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
552
553 Read (Register, Value);
554 Value := Value and not Mask;
555 Write (Register, Value);
556 end Unset_Mask;
557
558 ----------------------------------------------------------------------------
559
560 -- Mask out @Unset_Mask@ and set @Set_Mask@ in @Register@
561 procedure Unset_And_Set_Mask
562 (Register : Registers_Index;
563 Mask_Unset : Word32;
564 Mask_Set : Word32)
565 is
566 Value : Word32;
567 begin
568 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
569 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
570
571 Read (Register, Value);
572 Value := (Value and not Mask_Unset) or Mask_Set;
573 Write (Register, Value);
574 end Unset_And_Set_Mask;
575
576 ----------------------------------------------------------------------------
577
Nico Huber2b6f6992017-07-09 18:11:34 +0200578 procedure Set_Register_Base (Base : Word64; GTT_Base : Word64 := 0)
Nico Huber83693c82016-10-08 22:17:55 +0200579 is
580 begin
581 Regs.Set_Base_Address (Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200582 if GTT_Base = 0 then
Arthur Heymans3f37cce2026-03-03 18:52:12 +0100583 GTT_32.Set_Base_Address
584 (Base + Word64 (Config.Default_MMIO_GTT_32_Offset));
585 GTT_64.Set_Base_Address (Base + Word64 (Config.MMIO_GTT_64_Offset));
Nico Huber2b6f6992017-07-09 18:11:34 +0200586 else
Nico Huber0b2329a2018-06-09 21:14:27 +0200587 GTT_32.Set_Base_Address (GTT_Base);
588 GTT_64.Set_Base_Address (GTT_Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200589 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200590 end Set_Register_Base;
591
592end HW.GFX.GMA.Registers;