blob: eb12b0dec2971f922bde4ed506ba1c3cb576f476 [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
Nico Huber0b2329a2018-06-09 21:14:27 +020048 type GTT_PTE_32 is mod 2 ** 32;
49 type GTT_Registers_32 is array (GTT_Range) of GTT_PTE_32
Nico Huber83693c82016-10-08 22:17:55 +020050 with
51 Volatile_Components,
Nico Huber0b2329a2018-06-09 21:14:27 +020052 Size => MMIO_GTT_32_Size * 8;
53 package GTT_32 is new MMIO_Range
54 (Base_Addr => Config.Default_MMIO_Base + MMIO_GTT_32_Offset,
55 Element_T => GTT_PTE_32,
Nico Huber83693c82016-10-08 22:17:55 +020056 Index_T => GTT_Range,
Nico Huber0b2329a2018-06-09 21:14:27 +020057 Array_T => GTT_Registers_32);
58
59 type GTT_PTE_64 is mod 2 ** 64;
60 type GTT_Registers_64 is array (GTT_Range) of GTT_PTE_64
61 with
62 Volatile_Components,
63 Size => MMIO_GTT_64_Size * 8;
64 package GTT_64 is new MMIO_Range
65 (Base_Addr => Config.Default_MMIO_Base + MMIO_GTT_64_Offset,
66 Element_T => GTT_PTE_64,
67 Index_T => GTT_Range,
68 Array_T => GTT_Registers_64);
Nico Huber83693c82016-10-08 22:17:55 +020069
Nico Huberceda17d2018-06-09 22:00:29 +020070 GTT_PTE_Valid : constant := 1;
Nico Huber83693c82016-10-08 22:17:55 +020071
72 ----------------------------------------------------------------------------
73
Nico Huberd0d8b792018-06-09 19:45:00 +020074 subtype Fence_Range is Natural range 0 .. 31;
Nico Huberb03c8f12017-08-25 13:29:08 +020075
76 FENCE_PAGE_SHIFT : constant := 12;
77 FENCE_PAGE_MASK : constant := 16#ffff_f000#;
Nico Huberb03c8f12017-08-25 13:29:08 +020078 FENCE_VALID : constant := 1 * 2 ** 0;
79
Arthur Heymans960e2392026-03-03 19:45:24 +010080 -- Gen4+ (i965/G45+): 64-bit fence pairs at Fence_Base + i*8
81 FENCE_TILE_WALK_YMAJOR : constant := 1 * 2 ** 1;
82
Nico Huberb03c8f12017-08-25 13:29:08 +020083 function Fence_Lower_Idx (Fence : Fence_Range) return Registers_Range is
Nico Huberd0d8b792018-06-09 19:45:00 +020084 (Registers_Range (Config.Fence_Base / Register_Width + 2 * Fence));
Nico Huberb03c8f12017-08-25 13:29:08 +020085 function Fence_Upper_Idx (Fence : Fence_Range) return Registers_Range is
86 (Fence_Lower_Idx (Fence) + 1);
87
Arthur Heymans960e2392026-03-03 19:45:24 +010088 -- Gen3 (i915/i945): 32-bit fences, split layout:
89 -- Fences 0-7: 0x2000 + i*4
90 -- Fences 8-15: 0x3000 + (i-8)*4
91 -- FENCE_REG(i) = 0x2000 + (((i) & 8) << 9) + ((i) & 7) * 4
92 GEN3_FENCE_TILING_Y_SHIFT : constant := 12;
93 GEN3_FENCE_SIZE_SHIFT : constant := 8;
94 GEN3_FENCE_PITCH_SHIFT : constant := 4;
95
96 function Gen3_Fence_Idx (Fence : Fence_Range) return Registers_Range is
97 (Registers_Range
98 ((16#2000# + (Fence / 8) * 16#1000# + (Fence mod 8) * 4) /
99 Register_Width));
100
101 -- Compute floor(log2(n)) for n >= 1 (fence size/pitch encoding).
102 function Floor_Log2 (N : Word32) return Natural
103 with
104 Pre => N >= 1
105 is
106 Result : Natural := 0;
107 Val : Word32 := N;
108 begin
109 for I in 0 .. 31 loop
110 exit when Val <= 1;
111 Val := Shift_Right (Val, 1);
112 Result := I + 1;
113 end loop;
114 return Result;
115 end Floor_Log2;
116
Nico Huber17d64b62017-07-15 20:51:25 +0200117 procedure Clear_Fences
118 is
Nico Huber17d64b62017-07-15 20:51:25 +0200119 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100120 if Config.Has_Gen3_Fences then
121 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
122 Regs.Write (Gen3_Fence_Idx (Fence), 0);
123 end loop;
124 else
125 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
126 Regs.Write (Fence_Lower_Idx (Fence), 0);
127 end loop;
128 end if;
Nico Huber17d64b62017-07-15 20:51:25 +0200129 end Clear_Fences;
130
Nico Huberb03c8f12017-08-25 13:29:08 +0200131 procedure Add_Fence
132 (First_Page : in GTT_Range;
133 Last_Page : in GTT_Range;
134 Tiling : in XY_Tiling;
135 Pitch : in Natural;
136 Success : out Boolean)
137 is
138 Y_Tiles : constant Boolean := Tiling = Y_Tiled;
139 Reg32 : Word32;
140 begin
141 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
142 pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (First_Page), 12)));
143 pragma Debug (Debug.Put (":"));
144 pragma Debug (Debug.Put_Word32 (Shift_Left (Word32 (Last_Page), 12)));
145 pragma Debug (not Y_Tiles, Debug.Put (" X tiled in "));
146 pragma Debug ( Y_Tiles, Debug.Put (" Y tiled in "));
147 pragma Debug (Debug.Put_Int32 (Int32 (Pitch)));
148 pragma Debug (Debug.Put_Line (" tiles per row."));
149
150 Success := False;
Arthur Heymans960e2392026-03-03 19:45:24 +0100151
152 if Config.Has_Gen3_Fences then
153 -- Gen3 i945: single 32-bit fence register per fence
154 -- Format: start[31:20] | tiling_y[12] | size_bits[11:8] |
155 -- pitch_log2[7:4] | valid[0]
156 -- stride: Y-tiled /128, X-tiled /512 (i945 has 128-byte Y tiling)
157 -- size_bits: log2(size_in_pages / 256) = log2(size_in_MB)
158 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
159 Regs.Read (Reg32, Gen3_Fence_Idx (Fence));
160 if (Reg32 and FENCE_VALID) = 0 then
161 declare
162 Start_Addr : constant Word32 :=
163 Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT);
164 Size_Pages : constant Word32 :=
165 Word32 (Last_Page - First_Page + 1);
166 -- Size in MB (pages / 256, since page = 4KB, 256*4KB = 1MB)
167 Size_MB : constant Word32 := Size_Pages / 256;
168 -- Pitch in tiles (X: 512B tiles, Y: 128B tiles for i945)
169 Stride : constant Word32 :=
170 Word32 (Pitch) / (if Y_Tiles then 128 else 512);
171 Size_Bits : constant Word32 :=
172 (if Size_MB >= 1
173 then Word32 (Floor_Log2 (Size_MB))
174 else 0);
175 begin
176 Regs.Write
177 (Index => Gen3_Fence_Idx (Fence),
178 Value => Start_Addr or
179 (if Y_Tiles
180 then Shift_Left (1, GEN3_FENCE_TILING_Y_SHIFT)
181 else 0) or
182 Shift_Left (Size_Bits, GEN3_FENCE_SIZE_SHIFT) or
183 Shift_Left
184 ((if Stride >= 1
185 then Word32 (Floor_Log2 (Stride))
186 else 0),
187 GEN3_FENCE_PITCH_SHIFT) or
188 FENCE_VALID);
189 end;
190 Success := True;
191 exit;
192 end if;
193 end loop;
194 else
195 -- Gen4+ (i965/G45+): 64-bit fence register pairs
196 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
197 Regs.Read (Reg32, Fence_Lower_Idx (Fence));
198 if (Reg32 and FENCE_VALID) = 0 then
199 Regs.Write
200 (Index => Fence_Lower_Idx (Fence),
201 Value => Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT) or
202 (if Y_Tiles then FENCE_TILE_WALK_YMAJOR else 0) or
203 FENCE_VALID);
204 Regs.Write
205 (Index => Fence_Upper_Idx (Fence),
206 Value => Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT) or
207 Word32 (Pitch) * (if Y_Tiles then 1 else 4) - 1);
208 Success := True;
209 exit;
210 end if;
211 end loop;
212 end if;
Nico Huberb03c8f12017-08-25 13:29:08 +0200213 end Add_Fence;
214
215 procedure Remove_Fence (First_Page, Last_Page : GTT_Range)
216 is
217 Page_Lower : constant Word32 :=
218 Shift_Left (Word32 (First_Page), FENCE_PAGE_SHIFT);
Arthur Heymans960e2392026-03-03 19:45:24 +0100219 Reg32 : Word32;
Nico Huberb03c8f12017-08-25 13:29:08 +0200220 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100221 if Config.Has_Gen3_Fences then
222 -- Gen3: match start address in single 32-bit register
223 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
224 Regs.Read (Reg32, Gen3_Fence_Idx (Fence));
225 if (Reg32 and FENCE_VALID) /= 0 and
226 (Reg32 and 16#fff0_0000#) = (Page_Lower and 16#fff0_0000#)
227 then
228 Regs.Write (Gen3_Fence_Idx (Fence), 0);
229 exit;
230 end if;
231 end loop;
232 else
233 -- Gen4+: match start in lower, end in upper register
234 declare
235 Page_Upper : constant Word32 :=
236 Shift_Left (Word32 (Last_Page), FENCE_PAGE_SHIFT);
237 Fence_Upper, Fence_Lower : Word32;
238 begin
239 for Fence in Fence_Range range 0 .. Config.Fence_Count - 1 loop
240 Regs.Read (Fence_Lower, Fence_Lower_Idx (Fence));
241 Regs.Read (Fence_Upper, Fence_Upper_Idx (Fence));
242 if (Fence_Lower and FENCE_PAGE_MASK) = Page_Lower and
243 (Fence_Upper and FENCE_PAGE_MASK) = Page_Upper
244 then
245 Regs.Write (Fence_Lower_Idx (Fence), 0);
246 exit;
247 end if;
248 end loop;
249 end;
250 end if;
Nico Huberb03c8f12017-08-25 13:29:08 +0200251 end Remove_Fence;
252
Nico Huber17d64b62017-07-15 20:51:25 +0200253 ----------------------------------------------------------------------------
254
Nico Huber83693c82016-10-08 22:17:55 +0200255 procedure Write_GTT
256 (GTT_Page : GTT_Range;
257 Device_Address : GTT_Address_Type;
258 Valid : Boolean)
259 is
260 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100261 if Config.Has_I945_Simple_GTT_PTE then
262 -- i945: simple 32-bit PTE, no high address bits
263 GTT_32.Write
264 (Index => GTT_Page,
265 Value => GTT_PTE_32 (Device_Address and 16#ffff_f000#) or
266 Boolean'Pos (Valid));
267 elsif not Config.Has_64bit_GTT then
Nico Huber0b2329a2018-06-09 21:14:27 +0200268 GTT_32.Write
Nico Huber83693c82016-10-08 22:17:55 +0200269 (Index => GTT_Page,
Nico Huber0b2329a2018-06-09 21:14:27 +0200270 Value => GTT_PTE_32 (Device_Address and 16#ffff_f000#) or
271 GTT_PTE_32 (Shift_Right (Word64 (Device_Address), 32 - 4)
Nico Huber83693c82016-10-08 22:17:55 +0200272 and 16#0000_07f0#) or
273 Boolean'Pos (Valid));
274 else
Nico Huber0b2329a2018-06-09 21:14:27 +0200275 GTT_64.Write
Nico Huber83693c82016-10-08 22:17:55 +0200276 (Index => GTT_Page,
Nico Huber0b2329a2018-06-09 21:14:27 +0200277 Value => GTT_PTE_64 (Device_Address and 16#7f_ffff_f000#) or
Nico Huber83693c82016-10-08 22:17:55 +0200278 Boolean'Pos (Valid));
279 end if;
280 end Write_GTT;
281
Nico Huberceda17d2018-06-09 22:00:29 +0200282 procedure Read_GTT
283 (Device_Address : out GTT_Address_Type;
284 Valid : out Boolean;
285 GTT_Page : in GTT_Range)
286 is
287 begin
Arthur Heymans960e2392026-03-03 19:45:24 +0100288 if Config.Has_I945_Simple_GTT_PTE then
289 declare
290 PTE : GTT_PTE_32;
291 begin
292 GTT_32.Read (PTE, GTT_Page);
293 Valid := (PTE and GTT_PTE_Valid) /= 0;
294 Device_Address := GTT_Address_Type (PTE and 16#ffff_f000#);
295 end;
296 elsif not Config.Has_64bit_GTT then
Nico Huberceda17d2018-06-09 22:00:29 +0200297 declare
298 PTE : GTT_PTE_32;
299 begin
300 GTT_32.Read (PTE, GTT_Page);
301 Valid := (PTE and GTT_PTE_Valid) /= 0;
302 Device_Address := GTT_Address_Type
303 (Shift_Left (Word64 (PTE and 16#07f0#), 32 - 4) or
304 Word64 (PTE and 16#ffff_f000#));
305 end;
306 else
307 declare
308 PTE : GTT_PTE_64;
309 begin
310 GTT_64.Read (PTE, GTT_Page);
311 Valid := (PTE and GTT_PTE_Valid) /= 0;
312 Device_Address := GTT_Address_Type (PTE and 16#7f_ffff_f000#);
313 end;
314 end if;
315 end Read_GTT;
316
Nico Huber83693c82016-10-08 22:17:55 +0200317 ----------------------------------------------------------------------------
318
319 package Rep is
320 function Index (Reg : Registers_Index) return Registers_Range;
321 end Rep;
322
323 package body Rep is
324 function Index (Reg : Registers_Index) return Registers_Range
325 with
326 SPARK_Mode => Off
327 is
328 begin
329 return Reg'Enum_Rep;
330 end Index;
331 end Rep;
332
333 -- Read a specific register
334 procedure Read
335 (Register : in Registers_Index;
336 Value : out Word32;
337 Verbose : in Boolean := True)
338 is
339 begin
340 Regs.Read (Value, Rep.Index (Register));
341
342 pragma Debug (Verbose, Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
343 pragma Debug (Verbose, Debug.Put_Word32 (Value));
344 pragma Debug (Verbose, Debug.Put (" <- "));
345 pragma Debug (Verbose, Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
346 pragma Debug (Verbose, Debug.Put (":"));
347 pragma Debug (Verbose, Debug.Put_Line (Registers_Index'Image (Register)));
348 end Read;
349
350 ----------------------------------------------------------------------------
351
352 -- Read a specific register to post a previous write
353 procedure Posting_Read (Register : Registers_Index)
354 is
355 Discard_Value : Word32;
356 begin
357 pragma Warnings
358 (Off, "unused assignment to ""Discard_Value""",
359 Reason => "Intentional dummy read to affect hardware.");
360
361 Read (Register, Discard_Value);
362
363 pragma Warnings
364 (On, "unused assignment to ""Discard_Value""");
365 end Posting_Read;
366
367 ----------------------------------------------------------------------------
368
369 -- Write a specific register
370 procedure Write (Register : Registers_Index; Value : Word32)
371 is
372 begin
373 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
374 pragma Debug (Debug.Put_Word32 (Value));
375 pragma Debug (Debug.Put (" -> "));
376 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
377 pragma Debug (Debug.Put (":"));
378 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
379
380 Regs.Write (Rep.Index (Register), Value);
381 pragma Debug (Debug.Register_Write_Wait);
382 end Write;
383
384 ----------------------------------------------------------------------------
385
386 -- Check whether all bits in @Register@ indicated by @Mask@ are set
387 procedure Is_Set_Mask
388 (Register : in Registers_Index;
389 Mask : in Word32;
390 Result : out Boolean)
391 is
392 Value : Word32;
393 begin
394 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
395 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
396
397 Read (Register, Value);
398 Result := (Value and Mask) = Mask;
399
400 end Is_Set_Mask;
401
402 ----------------------------------------------------------------------------
403
Nico Huber82ca09f2019-09-28 02:37:50 +0200404 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_Success""");
405
Nico Huberbcb2c472017-02-02 16:39:26 +0100406 -- Wait for the bits in @Register@ indicated by @Mask@ to be of @Value@
407 procedure Wait
Nico Huber82ca09f2019-09-28 02:37:50 +0200408 (Register : in Registers_Index;
409 Mask : in Word32;
410 Value : in Word32;
411 TOut_MS : in Natural := Default_Timeout_MS;
412 Verbose : in Boolean := False;
413 Success : out Boolean)
Nico Huberbcb2c472017-02-02 16:39:26 +0100414 is
415 Current : Word32;
416 Timeout : Time.T;
Nico Huber82ca09f2019-09-28 02:37:50 +0200417 Timed_Out : Boolean := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100418 begin
419 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
420 pragma Debug (Debug.Put_Word32 (Value));
421 pragma Debug (Debug.Put (" <- "));
422 pragma Debug (Debug.Put_Word32 (Mask));
423 pragma Debug (Debug.Put (" & "));
424 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
425 pragma Debug (Debug.Put (":"));
426 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
427
428 Timeout := Time.MS_From_Now (TOut_MS);
429 loop
Nico Huberbcb2c472017-02-02 16:39:26 +0100430 Read (Register, Current, Verbose);
431 if (Current and Mask) = Value then
Nico Huber82ca09f2019-09-28 02:37:50 +0200432 -- Ignore timeout if we succeeded anyway.
433 Timed_Out := False;
Nico Huberbcb2c472017-02-02 16:39:26 +0100434 exit;
435 end if;
436 pragma Debug (Timed_Out, Debug.Put (GNAT.Source_Info.Enclosing_Entity));
437 pragma Debug (Timed_Out, Debug.Put_Line (": Timed Out!"));
438 exit when Timed_Out;
Nico Huber82ca09f2019-09-28 02:37:50 +0200439
440 Timed_Out := Time.Timed_Out (Timeout);
Nico Huberbcb2c472017-02-02 16:39:26 +0100441 end loop;
Nico Huber82ca09f2019-09-28 02:37:50 +0200442
443 Success := not Timed_Out;
444 end Wait;
445
446 procedure Wait
447 (Register : Registers_Index;
448 Mask : Word32;
449 Value : Word32;
450 TOut_MS : Natural := Default_Timeout_MS;
451 Verbose : Boolean := False)
452 is
453 Ignored_Success : Boolean;
454 begin
455 Wait (Register, Mask, Value, TOut_MS, Verbose, Ignored_Success);
Nico Huberbcb2c472017-02-02 16:39:26 +0100456 end Wait;
457
458 ----------------------------------------------------------------------------
459
Nico Huber83693c82016-10-08 22:17:55 +0200460 -- Wait for all bits in @Register@ indicated by @Mask@ to be set
461 procedure Wait_Set_Mask
462 (Register : in Registers_Index;
463 Mask : in Word32;
464 TOut_MS : in Natural := Default_Timeout_MS;
Nico Huber82ca09f2019-09-28 02:37:50 +0200465 Verbose : in Boolean := False;
466 Success : out Boolean) is
Nico Huber83693c82016-10-08 22:17:55 +0200467 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200468 Wait (Register, Mask, Mask, TOut_MS, Verbose, Success);
469 end Wait_Set_Mask;
470
471 procedure Wait_Set_Mask
472 (Register : Registers_Index;
473 Mask : Word32;
474 TOut_MS : Natural := Default_Timeout_MS;
475 Verbose : Boolean := False)
476 is
477 Ignored_Success : Boolean;
478 begin
479 Wait (Register, Mask, Mask, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200480 end Wait_Set_Mask;
481
482 ----------------------------------------------------------------------------
483
Nico Huber83693c82016-10-08 22:17:55 +0200484 -- Wait for bits in @Register@ indicated by @Mask@ to be clear
485 procedure Wait_Unset_Mask
Nico Huber82ca09f2019-09-28 02:37:50 +0200486 (Register : in Registers_Index;
487 Mask : in Word32;
488 TOut_MS : in Natural := Default_Timeout_MS;
489 Verbose : in Boolean := False;
490 Success : out Boolean) is
491 begin
492 Wait (Register, Mask, 0, TOut_MS, Verbose, Success);
493 end;
494
495 procedure Wait_Unset_Mask
Nico Huber83693c82016-10-08 22:17:55 +0200496 (Register : Registers_Index;
497 Mask : Word32;
Nico Huber82ca09f2019-09-28 02:37:50 +0200498 TOut_MS : Natural := Default_Timeout_MS;
499 Verbose : Boolean := False)
Nico Huber83693c82016-10-08 22:17:55 +0200500 is
Nico Huber82ca09f2019-09-28 02:37:50 +0200501 Ignored_Success : Boolean;
Nico Huber83693c82016-10-08 22:17:55 +0200502 begin
Nico Huber82ca09f2019-09-28 02:37:50 +0200503 Wait (Register, Mask, 0, TOut_MS, Verbose, Ignored_Success);
Nico Huber83693c82016-10-08 22:17:55 +0200504 end Wait_Unset_Mask;
505
506 ----------------------------------------------------------------------------
507
508 -- Set bits from @Mask@ in @Register@
509 procedure Set_Mask
510 (Register : Registers_Index;
511 Mask : Word32)
512 is
513 Value : Word32;
514 begin
515 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
516 pragma Debug (Debug.Put_Word32 (Mask));
517 pragma Debug (Debug.Put (" .S "));
518 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
519
520 Read (Register, Value);
521 Value := Value or Mask;
522 Write (Register, Value);
523 end Set_Mask;
524
525 ----------------------------------------------------------------------------
526
527 -- Mask out @Mask@ in @Register@
528 procedure Unset_Mask
529 (Register : Registers_Index;
530 Mask : Word32)
531 is
532 Value : Word32;
533 begin
534 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
535 pragma Debug (Debug.Put_Word32 (Mask));
536 pragma Debug (Debug.Put (" !S "));
537 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
538
539 Read (Register, Value);
540 Value := Value and not Mask;
541 Write (Register, Value);
542 end Unset_Mask;
543
544 ----------------------------------------------------------------------------
545
546 -- Mask out @Unset_Mask@ and set @Set_Mask@ in @Register@
547 procedure Unset_And_Set_Mask
548 (Register : Registers_Index;
549 Mask_Unset : Word32;
550 Mask_Set : Word32)
551 is
552 Value : Word32;
553 begin
554 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
555 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
556
557 Read (Register, Value);
558 Value := (Value and not Mask_Unset) or Mask_Set;
559 Write (Register, Value);
560 end Unset_And_Set_Mask;
561
562 ----------------------------------------------------------------------------
563
Nico Huber2b6f6992017-07-09 18:11:34 +0200564 procedure Set_Register_Base (Base : Word64; GTT_Base : Word64 := 0)
Nico Huber83693c82016-10-08 22:17:55 +0200565 is
566 begin
567 Regs.Set_Base_Address (Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200568 if GTT_Base = 0 then
Nico Huber0b2329a2018-06-09 21:14:27 +0200569 GTT_32.Set_Base_Address (Base + MMIO_GTT_32_Offset);
570 GTT_64.Set_Base_Address (Base + MMIO_GTT_64_Offset);
Nico Huber2b6f6992017-07-09 18:11:34 +0200571 else
Nico Huber0b2329a2018-06-09 21:14:27 +0200572 GTT_32.Set_Base_Address (GTT_Base);
573 GTT_64.Set_Base_Address (GTT_Base);
Nico Huber2b6f6992017-07-09 18:11:34 +0200574 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200575 end Set_Register_Base;
576
577end HW.GFX.GMA.Registers;