--
-- Copyright (C) 2017 Nico Huber <nico.h@gmx.de>
--
-- 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 Ada.Text_IO;
with Ada.Strings.Fixed;

with HW.File;
with HW.PCI.MMConf;

with HW.MMIO_Range;
pragma Elaborate_All (HW.MMIO_Range);

use Ada.Strings.Fixed;

package body HW.PCI.Dev
with
   Refined_State =>
     (Address_State  => MM.Address_State,
      PCI_State      => MM.PCI_State)
is

   -- We map each device's config space individually, hence Address'(0, 0, 0).
   package MM is new HW.PCI.MMConf (Address'(0, 0, 0));

   procedure Read8 (Value : out Word8; Offset : Index) renames MM.Read8;
   procedure Read16 (Value : out Word16; Offset : Index) renames MM.Read16;
   procedure Read32 (Value : out Word32; Offset : Index) renames MM.Read32;

   procedure Write8 (Offset : Index; Value : Word8) renames MM.Write8;
   procedure Write16 (Offset : Index; Value : Word16) renames MM.Write16;
   procedure Write32 (Offset : Index; Value : Word32) renames MM.Write32;

   -- No-op PCI config update to share contracts
   -- with implementations that do actual updates.
   procedure Dummy_PCI_Update
   with
      Global => (In_Out => MM.PCI_State);
   procedure Dummy_PCI_Update is null
   with
      SPARK_Mode => Off;

   function Hex (Val : Natural) return Character
   with
      Pre => Val < 16
   is
   begin
      if Val < 10 then
         return Character'Val (Character'Pos ('0') + Val);
      else
         return Character'Val (Character'Pos ('a') + Val - 10);
      end if;
   end Hex;

   subtype String2 is String (1 .. 2);
   function Hex2 (Val : Natural) return String2
   with
      Pre => Val < 256
   is
      Res : constant String (1 .. 2) := (Hex (Val / 16), Hex (Val mod 16));
   begin
      return Res;
   end Hex2;

   procedure Patch_Sysfs_Path (Path : in out String)
   with
      Pre => Path'Length >= 36
   is
   begin
      Path (Path'First + 21 .. Path'First + 22) := Hex2 (Natural (Dev.Bus));
      Path (Path'First + 29 .. Path'First + 30) := Hex2 (Natural (Dev.Bus));
      Path (Path'First + 32 .. Path'First + 33) := Hex2 (Natural (Dev.Slot));
      Path (Path'First + 35) := Hex (Natural (Dev.Func));
   end Patch_Sysfs_Path;

   procedure Map
     (Addr     :    out Word64;
      Res      : in     Resource;
      Length   : in     Natural := 0;
      Offset   : in     Natural := 0;
      WC       : in     Boolean := False)
   is
      Success  : Boolean;
      Path     : String (1 .. 49) :=
         "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex_wc";
   begin
      Dummy_PCI_Update;

      Patch_Sysfs_Path (Path);
      Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));
      if not WC then
         Path (47) := Character'Val (0);
      end if;

      File.Map
        (Addr     => Addr,
         Path     => Path,
         Len      => Length,
         Offset   => Offset,
         Readable => True,
         Writable => True,
         Success  => Success);

      if not Success and WC then -- try again without write-combining
         Path (47) := Character'Val (0);

         File.Map
           (Addr     => Addr,
            Path     => Path,
            Len      => Length,
            Offset   => Offset,
            Readable => True,
            Writable => True,
            Success  => Success);
      end if;

      if not Success then
         Addr := 0;
      end if;
   end Map;

   procedure Resource_Size (Length : out Natural; Res : Resource)
   is
      Path : String (1 .. 46) :=
         "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex";
   begin
      Dummy_PCI_Update;

      Patch_Sysfs_Path (Path);
      Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));

      File.Size (Length, Path);
   end Resource_Size;

   procedure Initialize (Success : out Boolean; MMConf_Base : Word64 := 0)
   is
      Addr  : Word64;
      Path  : String (1 .. 43) := "/sys/devices/pci0000:xx/0000:xx:xx.x/config";
   begin
      Patch_Sysfs_Path (Path);

      File.Map
        (Addr     => Addr,
         Path     => Path,
         Readable => True,
         Map_Copy => True,
         Success  => Success);
      MM.Set_Base_Address (Addr);
   end Initialize;

end HW.PCI.Dev;
