| -- |
| -- Copyright (C) 2014-2016, 2019 secunet Security Networks AG |
| -- |
| -- This program is free software; you can redistribute it and/or modify |
| -- it under the terms of the GNU General Public License as published by |
| -- the Free Software Foundation; either version 2 of the License, or |
| -- (at your option) any later version. |
| -- |
| -- This program is distributed in the hope that it will be useful, |
| -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
| -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| -- GNU General Public License for more details. |
| -- |
| |
| with GNAT.Source_Info; |
| |
| with HW.Debug; |
| with HW.GFX.GMA.Registers; |
| |
| use HW.GFX.GMA.Registers; |
| |
| package body HW.GFX.GMA.PCode is |
| |
| GT_MAILBOX_READY : constant := 1 * 2 ** 31; |
| |
| -- Send a command and optionally wait for and return the reply. |
| procedure Mailbox_Write_Read |
| (MBox : in Word32; |
| Command : in Word64; |
| Reply : out Word64; |
| Wait_Ready : in Boolean := False; |
| Wait_Ack : in Boolean := True; |
| Success : out Boolean) |
| with |
| Pre => Mailbox_Ready or Wait_Ready, |
| Post => (if Wait_Ack and Success then Mailbox_Ready) |
| is |
| use type HW.Word64; |
| |
| Data : Word32; |
| begin |
| pragma Debug (Debug.Put_Line (GNAT.Source_Info.Enclosing_Entity)); |
| |
| Reply := 0; |
| Success := True; |
| |
| if Wait_Ready then |
| Wait_Unset_Mask (GT_MAILBOX, GT_MAILBOX_READY, Success => Success); |
| if not Success then |
| return; |
| end if; |
| end if; |
| |
| Write (GT_MAILBOX_DATA, Word32 (Command and 16#ffff_ffff#)); |
| Write (GT_MAILBOX_DATA_1, Word32 (Shift_Right (Command, 32))); |
| Write (GT_MAILBOX, GT_MAILBOX_READY or MBox); |
| Mailbox_Ready := False; |
| |
| if Wait_Ack then |
| Wait_Unset_Mask (GT_MAILBOX, GT_MAILBOX_READY, Success => Success); |
| Mailbox_Ready := Success; |
| |
| Read (GT_MAILBOX_DATA, Data); |
| Reply := Word64 (Data); |
| Read (GT_MAILBOX_DATA_1, Data); |
| Reply := Shift_Left (Word64 (Data), 32) or Reply; |
| |
| Write (GT_MAILBOX_DATA, 0); |
| Write (GT_MAILBOX_DATA_1, 0); |
| end if; |
| end Mailbox_Write_Read; |
| |
| procedure Mailbox_Write |
| (MBox : in Word32; |
| Command : in Word64; |
| Wait_Ready : in Boolean := False; |
| Wait_Ack : in Boolean := True; |
| Success : out Boolean) |
| is |
| pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_R"""); |
| Ignored_R : Word64; |
| begin |
| Mailbox_Write_Read |
| (MBox, Command, Ignored_R, Wait_Ready, Wait_Ack, Success); |
| end Mailbox_Write; |
| |
| procedure Mailbox_Read |
| (MBox : in Word32; |
| Command : in Word64 := 0; |
| Wait_Ready : in Boolean := False; |
| Reply : out Word64; |
| Success : out Boolean) |
| is |
| begin |
| Mailbox_Write_Read (MBox, Command, Reply, Wait_Ready, True, Success); |
| end Mailbox_Read; |
| |
| procedure Mailbox_Request |
| (MBox : in Word32; |
| Command : in Word64; |
| Reply_Mask : in Word64; |
| Reply : in Word64 := 16#ffff_ffff_ffff_ffff#; |
| TOut_MS : in Natural := Registers.Default_Timeout_MS; |
| Wait_Ready : in Boolean := False; |
| Success : out Boolean) |
| is |
| use type HW.Word64; |
| |
| Timeout : constant Time.T := Time.MS_From_Now (TOut_MS); |
| Timed_Out : Boolean := False; |
| |
| Received_Reply : Word64; |
| begin |
| Success := False; |
| loop |
| pragma Loop_Invariant ((not Success and Wait_Ready) or Mailbox_Ready); |
| Mailbox_Write_Read |
| (MBox => MBox, |
| Command => Command, |
| Reply => Received_Reply, |
| Wait_Ready => not Success and Wait_Ready, |
| Success => Success); |
| exit when not Success; |
| |
| if (Received_Reply and Reply_Mask) = (Reply and Reply_Mask) then |
| -- Ignore timeout if we succeeded anyway. |
| Timed_Out := False; |
| exit; |
| end if; |
| exit when Timed_Out; |
| |
| Timed_Out := Time.Timed_Out (Timeout); |
| end loop; |
| |
| Success := Success and then not Timed_Out; |
| end Mailbox_Request; |
| |
| procedure Mailbox_Write |
| (MBox : Word32; |
| Command : Word64; |
| Wait_Ready : Boolean := False) |
| is |
| pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_S"""); |
| Ignored_S : Boolean; |
| begin |
| Mailbox_Write (MBox, Command, Wait_Ready, False, Ignored_S); |
| end Mailbox_Write; |
| |
| end HW.GFX.GMA.PCode; |