blob: a76800212ad49bc33daea9272697d30ed8367242 [file] [log] [blame]
Nico Huberff3240b2017-07-09 16:23:04 +02001--
2-- Copyright (C) 2017 Nico Huber <nico.h@gmx.de>
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 Ada.Text_IO;
16with Ada.Strings.Fixed;
17
18with HW.File;
19with HW.PCI.MMConf;
20
21with HW.MMIO_Range;
22pragma Elaborate_All (HW.MMIO_Range);
23
24use Ada.Strings.Fixed;
25
26package body HW.PCI.Dev
27with
28 Refined_State =>
29 (Address_State => MM.Address_State,
30 PCI_State => MM.PCI_State)
31is
32
33 -- We map each device's config space individually, hence Address'(0, 0, 0).
34 package MM is new HW.PCI.MMConf (Address'(0, 0, 0));
35
36 procedure Read8 (Value : out Word8; Offset : Index) renames MM.Read8;
37 procedure Read16 (Value : out Word16; Offset : Index) renames MM.Read16;
38 procedure Read32 (Value : out Word32; Offset : Index) renames MM.Read32;
39
40 procedure Write8 (Offset : Index; Value : Word8) renames MM.Write8;
41 procedure Write16 (Offset : Index; Value : Word16) renames MM.Write16;
42 procedure Write32 (Offset : Index; Value : Word32) renames MM.Write32;
43
44 function Hex (Val : Natural) return Character
45 with
46 Pre => Val < 16
47 is
48 begin
49 if Val < 10 then
50 return Character'Val (Character'Pos ('0') + Val);
51 else
52 return Character'Val (Character'Pos ('a') + Val - 10);
53 end if;
54 end Hex;
55
56 subtype String2 is String (1 .. 2);
57 function Hex2 (Val : Natural) return String2
58 with
59 Pre => Val < 256
60 is
61 Res : constant String (1 .. 2) := (Hex (Val / 16), Hex (Val mod 16));
62 begin
63 return Res;
64 end Hex2;
65
66 procedure Patch_Sysfs_Path (Path : in out String)
67 with
68 Pre => Path'Length >= 36
69 is
70 begin
71 Path (Path'First + 21 .. Path'First + 22) := Hex2 (Natural (Dev.Bus));
72 Path (Path'First + 29 .. Path'First + 30) := Hex2 (Natural (Dev.Bus));
73 Path (Path'First + 32 .. Path'First + 33) := Hex2 (Natural (Dev.Slot));
74 Path (Path'First + 35) := Hex (Natural (Dev.Func));
75 end Patch_Sysfs_Path;
76
77 procedure Map
78 (Addr : out Word64;
79 Res : in Resource;
80 Length : in Natural := 0;
81 Offset : in Natural := 0;
82 WC : in Boolean := False)
83 is
84 Success : Boolean;
85 Path : String (1 .. 49) :=
86 "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex_wc";
87 begin
88 Patch_Sysfs_Path (Path);
89 Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));
90 if not WC then
91 Path (47) := Character'Val (0);
92 end if;
93
94 File.Map
95 (Addr => Addr,
96 Path => Path,
97 Len => Length,
98 Offset => Offset,
99 Readable => True,
100 Writable => True,
101 Success => Success);
102
103 if not Success and WC then -- try again without write-combining
104 Path (47) := Character'Val (0);
105
106 File.Map
107 (Addr => Addr,
108 Path => Path,
109 Len => Length,
110 Offset => Offset,
111 Readable => True,
112 Writable => True,
113 Success => Success);
114 end if;
115
116 if not Success then
117 Addr := 0;
118 end if;
119 end Map;
120
121 procedure Resource_Size (Length : out Natural; Res : Resource)
122 is
123 Path : String (1 .. 46) :=
124 "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex";
125 begin
126 Patch_Sysfs_Path (Path);
127 Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));
128
129 File.Size (Length, Path);
130 end Resource_Size;
131
132 procedure Initialize (Success : out Boolean; MMConf_Base : Word64 := 0)
133 is
134 Addr : Word64;
135 Path : String (1 .. 43) := "/sys/devices/pci0000:xx/0000:xx:xx.x/config";
136 begin
137 Patch_Sysfs_Path (Path);
138
139 File.Map
140 (Addr => Addr,
141 Path => Path,
142 Readable => True,
143 Map_Copy => True,
144 Success => Success);
145 MM.Set_Base_Address (Addr);
146 end Initialize;
147
148end HW.PCI.Dev;