gfx_test: Set our own framebuffers up, update README
Use GMA.Setup_Default_FB() to allocate framebuffers in the stolen
memory. To help with setups where we can't unload the i915 driver,
back up and restore the current GTT setup and framebuffer contents.
Also add a wrapper script and update the README.
Change-Id: I10790d35d38b7b211f41b2452f6d2baf17372e31
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/20604
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
index ad396fd..d870401 100644
--- a/gfxtest/hw-gfx-gma-gfx_test.adb
+++ b/gfxtest/hw-gfx-gma-gfx_test.adb
@@ -2,10 +2,12 @@
with Ada.Command_Line;
with Interfaces.C;
+with HW.Time;
with HW.Debug;
with HW.PCI.Dev;
with HW.MMIO_Range;
with HW.GFX.GMA;
+with HW.GFX.GMA.Config;
with HW.GFX.GMA.Display_Probing;
package body HW.GFX.GMA.GFX_Test
@@ -14,6 +16,32 @@
package Dev is new PCI.Dev (PCI.Address'(0, 2, 0));
+ type GTT_PTE_Type is mod 2 ** (Config.GTT_PTE_Size * 8);
+ type GTT_Registers_Type is array (GTT_Range) of GTT_PTE_Type;
+ package GTT is new MMIO_Range
+ (Base_Addr => 0,
+ Element_T => GTT_PTE_Type,
+ Index_T => GTT_Range,
+ Array_T => GTT_Registers_Type);
+
+ GTT_Backup : GTT_Registers_Type;
+
+ procedure Backup_GTT
+ is
+ begin
+ for Idx in GTT_Range loop
+ GTT.Read (GTT_Backup (Idx), Idx);
+ end loop;
+ end Backup_GTT;
+
+ procedure Restore_GTT
+ is
+ begin
+ for Idx in GTT_Range loop
+ GTT.Write (Idx, GTT_Backup (Idx));
+ end loop;
+ end Restore_GTT;
+
type Pixel_Type is record
Red : Byte;
Green : Byte;
@@ -46,7 +74,27 @@
package Screen is new MMIO_Range (0, Word32, Screen_Index, Screen_Type);
- Pipes : GMA.Pipe_Configs;
+ Screen_Backup : Screen_Type;
+
+ procedure Backup_Screen (FB : Framebuffer_Type)
+ is
+ First : constant Screen_Index := Natural (FB.Offset) / 4;
+ Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1;
+ begin
+ for Idx in Screen_Index range First .. Last loop
+ Screen.Read (Screen_Backup (Idx), Idx);
+ end loop;
+ end Backup_Screen;
+
+ procedure Restore_Screen (FB : Framebuffer_Type)
+ is
+ First : constant Screen_Index := Natural (FB.Offset) / 4;
+ Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1;
+ begin
+ for Idx in Screen_Index range First .. Last loop
+ Screen.Write (Idx, Screen_Backup (Idx));
+ end loop;
+ end Restore_Screen;
function Fill
(X, Y : Natural;
@@ -113,11 +161,14 @@
Offset := Offset + Word32 (FB.Stride * FB.Height * 4);
end Calc_Framebuffer;
+ Pipes : GMA.Pipe_Configs;
+
procedure Prepare_Configs
is
use type HW.GFX.GMA.Port_Type;
Offset : Word32 := 0;
+ Success : Boolean;
begin
GMA.Display_Probing.Scan_Ports (Pipes);
@@ -127,12 +178,27 @@
(FB => Pipes (Pipe).Framebuffer,
Mode => Pipes (Pipe).Mode,
Offset => Offset);
+ GMA.Setup_Default_FB
+ (FB => Pipes (Pipe).Framebuffer,
+ Clear => False,
+ Success => Success);
+ if not Success then
+ Pipes (Pipe).Port := GMA.Disabled;
+ end if;
end if;
end loop;
GMA.Dump_Configs (Pipes);
end Prepare_Configs;
+ procedure Print_Usage
+ is
+ begin
+ Debug.Put_Line
+ ("Usage: " & Ada.Command_Line.Command_Name & " <delay seconds>");
+ Debug.New_Line;
+ end Print_Usage;
+
procedure Main
is
use type HW.GFX.GMA.Port_Type;
@@ -141,12 +207,21 @@
Res_Addr : Word64;
+ Delay_S : Natural;
+
Dev_Init,
Initialized : Boolean;
function iopl (level : Interfaces.C.int) return Interfaces.C.int;
pragma Import (C, iopl, "iopl");
begin
+ if Ada.Command_Line.Argument_Count /= 1 then
+ Print_Usage;
+ return;
+ end if;
+
+ Delay_S := Natural'Value (Ada.Command_Line.Argument (1));
+
if iopl (3) /= 0 then
Debug.Put_Line ("Failed to change i/o privilege level.");
return;
@@ -158,6 +233,13 @@
return;
end if;
+ Dev.Map (Res_Addr, PCI.Res0, Offset => Config.GTT_Offset);
+ if Res_Addr = 0 then
+ Debug.Put_Line ("Failed to map PCI resource0.");
+ return;
+ end if;
+ GTT.Set_Base_Address (Res_Addr);
+
Dev.Map (Res_Addr, PCI.Res2, WC => True);
if Res_Addr = 0 then
Debug.Put_Line ("Failed to map PCI resource2.");
@@ -170,17 +252,29 @@
Success => Initialized);
if Initialized then
+ Backup_GTT;
+
Prepare_Configs;
GMA.Update_Outputs (Pipes);
for Pipe in GMA.Pipe_Index loop
if Pipes (Pipe).Port /= GMA.Disabled then
+ Backup_Screen (Pipes (Pipe).Framebuffer);
Test_Screen
(Framebuffer => Pipes (Pipe).Framebuffer,
Pipe => Pipe);
end if;
end loop;
+
+ Time.M_Delay (Delay_S * 1_000);
+
+ for Pipe in GMA.Pipe_Index loop
+ if Pipes (Pipe).Port /= GMA.Disabled then
+ Restore_Screen (Pipes (Pipe).Framebuffer);
+ end if;
+ end loop;
+ Restore_GTT;
end if;
end Main;