blob: e2401524e5f707625770ca0450dc180cfd4eb302 [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
Nico Huberb8ae6182017-07-15 20:03:56 +020019with HW.GFX.GMA.Config;
20
Nico Huber83693c82016-10-08 22:17:55 +020021with HW.Debug;
22with GNAT.Source_Info;
23
Nico Huber83693c82016-10-08 22:17:55 +020024use type HW.Word64;
25
26package body HW.GFX.GMA.Registers
27with
28 Refined_State =>
29 (Address_State => (Regs.Base_Address, GTT.Base_Address),
30 Register_State => Regs.State,
31 GTT_State => GTT.State)
32is
33 pragma Disable_Atomic_Synchronization;
34
35 type Registers_Range is
36 new Natural range 0 .. 16#0020_0000# / Register_Width - 1;
37 type Registers_Type is array (Registers_Range) of Word32
38 with
39 Atomic_Components,
40 Size => 16#20_0000# * 8;
41 package Regs is new MMIO_Range
42 (Base_Addr => Config.Default_MMIO_Base,
43 Element_T => Word32,
44 Index_T => Registers_Range,
45 Array_T => Registers_Type);
46
47 ----------------------------------------------------------------------------
48
Nico Huberb8ae6182017-07-15 20:03:56 +020049 type GTT_PTE_Type is mod 2 ** (Config.GTT_PTE_Size * 8);
Nico Huber83693c82016-10-08 22:17:55 +020050 type GTT_Registers_Type is array (GTT_Range) of GTT_PTE_Type
51 with
52 Volatile_Components,
Nico Huberb8ae6182017-07-15 20:03:56 +020053 Size => Config.GTT_Size * 8;
Nico Huber83693c82016-10-08 22:17:55 +020054 package GTT is new MMIO_Range
Nico Huberb8ae6182017-07-15 20:03:56 +020055 (Base_Addr => Config.Default_MMIO_Base + Config.GTT_Offset,
Nico Huber83693c82016-10-08 22:17:55 +020056 Element_T => GTT_PTE_Type,
57 Index_T => GTT_Range,
58 Array_T => GTT_Registers_Type);
59
60 GTT_PTE_Valid : constant Word32 := 1;
61
62 ----------------------------------------------------------------------------
63
64 procedure Write_GTT
65 (GTT_Page : GTT_Range;
66 Device_Address : GTT_Address_Type;
67 Valid : Boolean)
68 is
69 begin
70 if Config.Fold_39Bit_GTT_PTE then
71 GTT.Write
72 (Index => GTT_Page,
73 Value => GTT_PTE_Type (Device_Address and 16#ffff_f000#) or
74 GTT_PTE_Type (Shift_Right (Word64 (Device_Address), 32 - 4)
75 and 16#0000_07f0#) or
76 Boolean'Pos (Valid));
77 else
78 GTT.Write
79 (Index => GTT_Page,
80 Value => GTT_PTE_Type (Device_Address and 16#7f_ffff_f000#) or
81 Boolean'Pos (Valid));
82 end if;
83 end Write_GTT;
84
85 ----------------------------------------------------------------------------
86
87 package Rep is
88 function Index (Reg : Registers_Index) return Registers_Range;
89 end Rep;
90
91 package body Rep is
92 function Index (Reg : Registers_Index) return Registers_Range
93 with
94 SPARK_Mode => Off
95 is
96 begin
97 return Reg'Enum_Rep;
98 end Index;
99 end Rep;
100
101 -- Read a specific register
102 procedure Read
103 (Register : in Registers_Index;
104 Value : out Word32;
105 Verbose : in Boolean := True)
106 is
107 begin
108 Regs.Read (Value, Rep.Index (Register));
109
110 pragma Debug (Verbose, Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
111 pragma Debug (Verbose, Debug.Put_Word32 (Value));
112 pragma Debug (Verbose, Debug.Put (" <- "));
113 pragma Debug (Verbose, Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
114 pragma Debug (Verbose, Debug.Put (":"));
115 pragma Debug (Verbose, Debug.Put_Line (Registers_Index'Image (Register)));
116 end Read;
117
118 ----------------------------------------------------------------------------
119
120 -- Read a specific register to post a previous write
121 procedure Posting_Read (Register : Registers_Index)
122 is
123 Discard_Value : Word32;
124 begin
125 pragma Warnings
126 (Off, "unused assignment to ""Discard_Value""",
127 Reason => "Intentional dummy read to affect hardware.");
128
129 Read (Register, Discard_Value);
130
131 pragma Warnings
132 (On, "unused assignment to ""Discard_Value""");
133 end Posting_Read;
134
135 ----------------------------------------------------------------------------
136
137 -- Write a specific register
138 procedure Write (Register : Registers_Index; Value : Word32)
139 is
140 begin
141 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
142 pragma Debug (Debug.Put_Word32 (Value));
143 pragma Debug (Debug.Put (" -> "));
144 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
145 pragma Debug (Debug.Put (":"));
146 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
147
148 Regs.Write (Rep.Index (Register), Value);
149 pragma Debug (Debug.Register_Write_Wait);
150 end Write;
151
152 ----------------------------------------------------------------------------
153
154 -- Check whether all bits in @Register@ indicated by @Mask@ are set
155 procedure Is_Set_Mask
156 (Register : in Registers_Index;
157 Mask : in Word32;
158 Result : out Boolean)
159 is
160 Value : Word32;
161 begin
162 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
163 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
164
165 Read (Register, Value);
166 Result := (Value and Mask) = Mask;
167
168 end Is_Set_Mask;
169
170 ----------------------------------------------------------------------------
171
172 -- TODO: Should have Success parameter
Nico Huberbcb2c472017-02-02 16:39:26 +0100173 -- Wait for the bits in @Register@ indicated by @Mask@ to be of @Value@
174 procedure Wait
175 (Register : Registers_Index;
176 Mask : Word32;
177 Value : Word32;
178 TOut_MS : Natural := Default_Timeout_MS;
179 Verbose : Boolean := False)
180 is
181 Current : Word32;
182 Timeout : Time.T;
183 Timed_Out : Boolean;
184 begin
185 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
186 pragma Debug (Debug.Put_Word32 (Value));
187 pragma Debug (Debug.Put (" <- "));
188 pragma Debug (Debug.Put_Word32 (Mask));
189 pragma Debug (Debug.Put (" & "));
190 pragma Debug (Debug.Put_Word32 (Register'Enum_Rep * Register_Width));
191 pragma Debug (Debug.Put (":"));
192 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
193
194 Timeout := Time.MS_From_Now (TOut_MS);
195 loop
196 Timed_Out := Time.Timed_Out (Timeout);
197 Read (Register, Current, Verbose);
198 if (Current and Mask) = Value then
199 exit;
200 end if;
201 pragma Debug (Timed_Out, Debug.Put (GNAT.Source_Info.Enclosing_Entity));
202 pragma Debug (Timed_Out, Debug.Put_Line (": Timed Out!"));
203 exit when Timed_Out;
204 end loop;
205 end Wait;
206
207 ----------------------------------------------------------------------------
208
209 -- TODO: Should have Success parameter
Nico Huber83693c82016-10-08 22:17:55 +0200210 -- Wait for all bits in @Register@ indicated by @Mask@ to be set
211 procedure Wait_Set_Mask
212 (Register : in Registers_Index;
213 Mask : in Word32;
214 TOut_MS : in Natural := Default_Timeout_MS;
215 Verbose : in Boolean := False)
216 is
Nico Huber83693c82016-10-08 22:17:55 +0200217 begin
Nico Huberbcb2c472017-02-02 16:39:26 +0100218 Wait (Register, Mask, Mask, TOut_MS, Verbose);
Nico Huber83693c82016-10-08 22:17:55 +0200219 end Wait_Set_Mask;
220
221 ----------------------------------------------------------------------------
222
223 -- TODO: Should have Success parameter
224 -- Wait for bits in @Register@ indicated by @Mask@ to be clear
225 procedure Wait_Unset_Mask
226 (Register : Registers_Index;
227 Mask : Word32;
228 TOut_MS : in Natural := Default_Timeout_MS;
229 Verbose : in Boolean := False)
230 is
Nico Huber83693c82016-10-08 22:17:55 +0200231 begin
Nico Huberbcb2c472017-02-02 16:39:26 +0100232 Wait (Register, Mask, 0, TOut_MS, Verbose);
Nico Huber83693c82016-10-08 22:17:55 +0200233 end Wait_Unset_Mask;
234
235 ----------------------------------------------------------------------------
236
237 -- Set bits from @Mask@ in @Register@
238 procedure Set_Mask
239 (Register : Registers_Index;
240 Mask : Word32)
241 is
242 Value : Word32;
243 begin
244 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
245 pragma Debug (Debug.Put_Word32 (Mask));
246 pragma Debug (Debug.Put (" .S "));
247 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
248
249 Read (Register, Value);
250 Value := Value or Mask;
251 Write (Register, Value);
252 end Set_Mask;
253
254 ----------------------------------------------------------------------------
255
256 -- Mask out @Mask@ in @Register@
257 procedure Unset_Mask
258 (Register : Registers_Index;
259 Mask : Word32)
260 is
261 Value : Word32;
262 begin
263 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
264 pragma Debug (Debug.Put_Word32 (Mask));
265 pragma Debug (Debug.Put (" !S "));
266 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
267
268 Read (Register, Value);
269 Value := Value and not Mask;
270 Write (Register, Value);
271 end Unset_Mask;
272
273 ----------------------------------------------------------------------------
274
275 -- Mask out @Unset_Mask@ and set @Set_Mask@ in @Register@
276 procedure Unset_And_Set_Mask
277 (Register : Registers_Index;
278 Mask_Unset : Word32;
279 Mask_Set : Word32)
280 is
281 Value : Word32;
282 begin
283 pragma Debug (Debug.Put (GNAT.Source_Info.Enclosing_Entity & ": "));
284 pragma Debug (Debug.Put_Line (Registers_Index'Image (Register)));
285
286 Read (Register, Value);
287 Value := (Value and not Mask_Unset) or Mask_Set;
288 Write (Register, Value);
289 end Unset_And_Set_Mask;
290
291 ----------------------------------------------------------------------------
292
293 procedure Set_Register_Base (Base : Word64)
294 is
295 begin
296 Regs.Set_Base_Address (Base);
Nico Huberb8ae6182017-07-15 20:03:56 +0200297 GTT.Set_Base_Address (Base + Config.GTT_Offset);
Nico Huber83693c82016-10-08 22:17:55 +0200298 end Set_Register_Base;
299
300end HW.GFX.GMA.Registers;