blob: dd0fc6e89dbf665cb4ea2496006e9f035942a658 [file] [log] [blame]
Nico Huber312433c2019-09-28 03:15:48 +02001--
2-- Copyright (C) 2014-2016, 2019 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
6-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
8--
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
15with GNAT.Source_Info;
16
17with HW.Debug;
18with HW.GFX.GMA.Registers;
19
20use HW.GFX.GMA.Registers;
21
22package body HW.GFX.GMA.PCode is
23
24 GT_MAILBOX_READY : constant := 1 * 2 ** 31;
25
26 -- Send a command and optionally wait for and return the reply.
27 procedure Mailbox_Write_Read
28 (MBox : in Word32;
29 Command : in Word64;
30 Reply : out Word64;
31 Wait_Ready : in Boolean := False;
32 Wait_Ack : in Boolean := True;
33 Success : out Boolean)
34 with
35 Pre => Mailbox_Ready or Wait_Ready,
36 Post => (if Wait_Ack and Success then Mailbox_Ready)
37 is
38 use type HW.Word64;
39
40 Data : Word32;
41 begin
42 pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity));
43
44 Reply := 0;
45 Success := True;
46
47 if Wait_Ready then
48 Wait_Unset_Mask (GT_MAILBOX, GT_MAILBOX_READY, Success => Success);
49 if not Success then
50 return;
51 end if;
52 end if;
53
54 Write (GT_MAILBOX_DATA, Word32 (Command and 16#ffff_ffff#));
55 Write (GT_MAILBOX_DATA_1, Word32 (Shift_Right (Command, 32)));
56 Write (GT_MAILBOX, GT_MAILBOX_READY or MBox);
57 Mailbox_Ready := False;
58
59 if Wait_Ack then
60 Wait_Unset_Mask (GT_MAILBOX, GT_MAILBOX_READY, Success => Success);
61 Mailbox_Ready := Success;
62
63 Read (GT_MAILBOX_DATA, Data);
64 Reply := Word64 (Data);
65 Read (GT_MAILBOX_DATA_1, Data);
66 Reply := Shift_Left (Word64 (Data), 32) or Reply;
67
68 Write (GT_MAILBOX_DATA, 0);
69 Write (GT_MAILBOX_DATA_1, 0);
70 end if;
71 end Mailbox_Write_Read;
72
73 procedure Mailbox_Write
74 (MBox : in Word32;
75 Command : in Word64;
76 Wait_Ready : in Boolean := False;
77 Wait_Ack : in Boolean := True;
78 Success : out Boolean)
79 is
80 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_R""");
81 Ignored_R : Word64;
82 begin
83 Mailbox_Write_Read
84 (MBox, Command, Ignored_R, Wait_Ready, Wait_Ack, Success);
85 end Mailbox_Write;
86
87 procedure Mailbox_Request
88 (MBox : in Word32;
89 Command : in Word64;
90 Reply_Mask : in Word64;
91 Reply : in Word64 := 16#ffff_ffff_ffff_ffff#;
92 TOut_MS : in Natural := Registers.Default_Timeout_MS;
93 Wait_Ready : in Boolean := False;
94 Success : out Boolean)
95 is
96 use type HW.Word64;
97
98 Timeout : constant Time.T := Time.MS_From_Now (TOut_MS);
99 Timed_Out : Boolean := False;
100
101 Received_Reply : Word64;
102 begin
103 Success := False;
104 loop
105 pragma Loop_Invariant ((not Success and Wait_Ready) or Mailbox_Ready);
106 Mailbox_Write_Read
107 (MBox => MBox,
108 Command => Command,
109 Reply => Received_Reply,
110 Wait_Ready => not Success and Wait_Ready,
111 Success => Success);
112 exit when not Success;
113
114 if (Received_Reply and Reply_Mask) = (Reply and Reply_Mask) then
115 -- Ignore timeout if we succeeded anyway.
116 Timed_Out := False;
117 exit;
118 end if;
119 exit when Timed_Out;
120
121 Timed_Out := Time.Timed_Out (Timeout);
122 end loop;
123
124 Success := Success and then not Timed_Out;
125 end Mailbox_Request;
126
127 procedure Mailbox_Write
128 (MBox : Word32;
129 Command : Word64;
130 Wait_Ready : Boolean := False)
131 is
132 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_S""");
133 Ignored_S : Boolean;
134 begin
135 Mailbox_Write (MBox, Command, Wait_Ready, False, Ignored_S);
136 end Mailbox_Write;
137
138end HW.GFX.GMA.PCode;