gfx_test: Update to use *libhwbase* new PCI interface

Thereby, move `gfx_test` into HW.GFX.GMA to make package dependencies
easier to handle.

Change-Id: Ie8a1251354b4fff57eef8c4bada8b49aa04ef382
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/20598
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/gfxtest/hw-gfx-gma-gfx_test.adb b/gfxtest/hw-gfx-gma-gfx_test.adb
new file mode 100644
index 0000000..b7060ec
--- /dev/null
+++ b/gfxtest/hw-gfx-gma-gfx_test.adb
@@ -0,0 +1,194 @@
+with Ada.Unchecked_Conversion;
+with Ada.Command_Line;
+with Interfaces.C;
+
+with HW.Debug;
+with HW.PCI.Dev;
+with HW.MMIO_Range;
+with HW.GFX.GMA;
+with HW.GFX.GMA.Display_Probing;
+
+package body HW.GFX.GMA.GFX_Test
+is
+   pragma Disable_Atomic_Synchronization;
+
+   package Dev is new PCI.Dev (PCI.Address'(0, 2, 0));
+
+   type Pixel_Type is record
+      Red   : Byte;
+      Green : Byte;
+      Blue  : Byte;
+      Alpha : Byte;
+   end record;
+
+   for Pixel_Type use record
+      Blue  at 0 range 0 .. 7;
+      Green at 1 range 0 .. 7;
+      Red   at 2 range 0 .. 7;
+      Alpha at 3 range 0 .. 7;
+   end record;
+
+   function Pixel_To_Word (P : Pixel_Type) return Word32
+   with
+      SPARK_Mode => Off
+   is
+      function To_Word is new Ada.Unchecked_Conversion (Pixel_Type, Word32);
+   begin
+      return To_Word (P);
+   end Pixel_To_Word;
+
+   Max_W    : constant := 4096;
+   Max_H    : constant := 2160;
+   FB_Align : constant := 16#0004_0000#;
+   subtype Screen_Index is Natural range
+      0 .. 3 * (Max_W * Max_H + FB_Align / 4) - 1;
+   type Screen_Type is array (Screen_Index) of Word32;
+
+   package Screen is new MMIO_Range (0, Word32, Screen_Index, Screen_Type);
+
+   Pipes : GMA.Pipe_Configs;
+
+   function Fill
+     (X, Y        : Natural;
+      Framebuffer : Framebuffer_Type;
+      Pipe        : GMA.Pipe_Index)
+      return Pixel_Type
+   is
+      use type HW.Byte;
+
+      Xp : constant Natural := X * 256 / Natural (Framebuffer.Width);
+      Yp : constant Natural := Y * 256 / Natural (Framebuffer.Height);
+      Xn : constant Natural := 255 - Xp;
+      Yn : constant Natural := 255 - Yp;
+
+      function Map (X, Y : Natural) return Byte is
+      begin
+         return Byte (X * Y / 255);
+      end Map;
+   begin
+      return
+        (case Pipe is
+         when GMA.Primary   => (Map (Xn, Yn), Map (Xp, Yn), Map (Xp, Yp), 255),
+         when GMA.Secondary => (Map (Xn, Yp), Map (Xn, Yn), Map (Xp, Yn), 255),
+         when GMA.Tertiary  => (Map (Xp, Yp), Map (Xn, Yp), Map (Xn, Yn), 255));
+   end Fill;
+
+   procedure Test_Screen
+     (Framebuffer : Framebuffer_Type;
+      Pipe        : GMA.Pipe_Index)
+   is
+      P        : Pixel_Type;
+      -- We have pixel offset wheras the framebuffer has a byte offset
+      Offset_Y : Natural := Natural (Framebuffer.Offset / 4);
+      Offset   : Natural;
+   begin
+      for Y in 0 .. Natural (Framebuffer.Height) - 1 loop
+         Offset := Offset_Y;
+         for X in 0 .. Natural (Framebuffer.Width) - 1 loop
+            if Y mod 16 = 0 or X mod 16 = 0 then
+               P := (0, 0, 0, 0);
+            else
+               P := Fill (X, Y, Framebuffer, Pipe);
+            end if;
+            Screen.Write (Offset, Pixel_To_Word (P));
+            Offset := Offset + 1;
+         end loop;
+         Offset_Y := Offset_Y + Natural (Framebuffer.Stride);
+      end loop;
+   end Test_Screen;
+
+   procedure Calc_Framebuffer
+     (FB       :    out Framebuffer_Type;
+      Mode     : in     Mode_Type;
+      Offset   : in out Word32)
+   is
+   begin
+      Offset := (Offset + FB_Align - 1) and not (FB_Align - 1);
+      FB :=
+        (Width    => Width_Type (Mode.H_Visible),
+         Height   => Height_Type (Mode.V_Visible),
+         BPC      => 8,
+         Stride   => Width_Type ((Word32 (Mode.H_Visible) + 15) and not 15),
+         Offset   => Offset);
+      Offset := Offset + Word32 (FB.Stride * FB.Height * 4);
+   end Calc_Framebuffer;
+
+   procedure Prepare_Configs
+   is
+      use type HW.GFX.GMA.Port_Type;
+
+      Offset : Word32 := 0;
+   begin
+      GMA.Display_Probing.Scan_Ports (Pipes);
+
+      for Pipe in GMA.Pipe_Index loop
+         if Pipes (Pipe).Port /= GMA.Disabled then
+            Calc_Framebuffer
+              (FB       => Pipes (Pipe).Framebuffer,
+               Mode     => Pipes (Pipe).Mode,
+               Offset   => Offset);
+         end if;
+      end loop;
+
+      GMA.Dump_Configs (Pipes);
+   end Prepare_Configs;
+
+   procedure Main
+   is
+      use type HW.GFX.GMA.Port_Type;
+      use type HW.Word64;
+      use type Interfaces.C.int;
+
+      Res_Addr : Word64;
+
+      Dev_Init,
+      Initialized : Boolean;
+
+      function iopl (level : Interfaces.C.int) return Interfaces.C.int;
+      pragma Import (C, iopl, "iopl");
+   begin
+      if iopl (3) /= 0 then
+         Debug.Put_Line ("Failed to change i/o privilege level.");
+         return;
+      end if;
+
+      Dev.Initialize (Dev_Init);
+      if not Dev_Init then
+         Debug.Put_Line ("Failed to map PCI config.");
+         return;
+      end if;
+
+      Dev.Map (Res_Addr, PCI.Res2, WC => True);
+      if Res_Addr = 0 then
+         Debug.Put_Line ("Failed to map PCI resource2.");
+         return;
+      end if;
+      Screen.Set_Base_Address (Res_Addr);
+
+      Dev.Map (Res_Addr, PCI.Res0);
+      if Res_Addr = 0 then
+         Debug.Put_Line ("Failed to map PCI resource0.");
+         return;
+      end if;
+
+      GMA.Initialize
+        (MMIO_Base   => Res_Addr,
+         Clean_State => True,
+         Success     => Initialized);
+
+      if Initialized then
+         Prepare_Configs;
+
+         GMA.Update_Outputs (Pipes);
+
+         for Pipe in GMA.Pipe_Index loop
+            if Pipes (Pipe).Port /= GMA.Disabled then
+               Test_Screen
+                 (Framebuffer => Pipes (Pipe).Framebuffer,
+                  Pipe        => Pipe);
+            end if;
+         end loop;
+      end if;
+   end Main;
+
+end HW.GFX.GMA.GFX_Test;