blob: 0017abffa6e1c24e9228d2d23173d759ae0efc29 [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
Nico Huber66859712017-08-25 20:04:30 +020044 -- No-op PCI config update to share contracts
45 -- with implementations that do actual updates.
46 procedure Dummy_PCI_Update
47 with
48 Global => (In_Out => MM.PCI_State);
49 procedure Dummy_PCI_Update is null
50 with
51 SPARK_Mode => Off;
52
Nico Huberff3240b2017-07-09 16:23:04 +020053 function Hex (Val : Natural) return Character
54 with
55 Pre => Val < 16
56 is
57 begin
58 if Val < 10 then
59 return Character'Val (Character'Pos ('0') + Val);
60 else
61 return Character'Val (Character'Pos ('a') + Val - 10);
62 end if;
63 end Hex;
64
65 subtype String2 is String (1 .. 2);
66 function Hex2 (Val : Natural) return String2
67 with
68 Pre => Val < 256
69 is
70 Res : constant String (1 .. 2) := (Hex (Val / 16), Hex (Val mod 16));
71 begin
72 return Res;
73 end Hex2;
74
75 procedure Patch_Sysfs_Path (Path : in out String)
76 with
77 Pre => Path'Length >= 36
78 is
79 begin
80 Path (Path'First + 21 .. Path'First + 22) := Hex2 (Natural (Dev.Bus));
81 Path (Path'First + 29 .. Path'First + 30) := Hex2 (Natural (Dev.Bus));
82 Path (Path'First + 32 .. Path'First + 33) := Hex2 (Natural (Dev.Slot));
83 Path (Path'First + 35) := Hex (Natural (Dev.Func));
84 end Patch_Sysfs_Path;
85
86 procedure Map
87 (Addr : out Word64;
88 Res : in Resource;
89 Length : in Natural := 0;
90 Offset : in Natural := 0;
91 WC : in Boolean := False)
92 is
93 Success : Boolean;
94 Path : String (1 .. 49) :=
95 "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex_wc";
96 begin
Nico Huber66859712017-08-25 20:04:30 +020097 Dummy_PCI_Update;
98
Nico Huberff3240b2017-07-09 16:23:04 +020099 Patch_Sysfs_Path (Path);
100 Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));
101 if not WC then
102 Path (47) := Character'Val (0);
103 end if;
104
105 File.Map
106 (Addr => Addr,
107 Path => Path,
108 Len => Length,
109 Offset => Offset,
110 Readable => True,
111 Writable => True,
112 Success => Success);
113
114 if not Success and WC then -- try again without write-combining
115 Path (47) := Character'Val (0);
116
117 File.Map
118 (Addr => Addr,
119 Path => Path,
120 Len => Length,
121 Offset => Offset,
122 Readable => True,
123 Writable => True,
124 Success => Success);
125 end if;
126
127 if not Success then
128 Addr := 0;
129 end if;
130 end Map;
131
132 procedure Resource_Size (Length : out Natural; Res : Resource)
133 is
134 Path : String (1 .. 46) :=
135 "/sys/devices/pci0000:xx/0000:xx:xx.x/resourcex";
136 begin
Nico Huber66859712017-08-25 20:04:30 +0200137 Dummy_PCI_Update;
138
Nico Huberff3240b2017-07-09 16:23:04 +0200139 Patch_Sysfs_Path (Path);
140 Path (46) := Character'Val (Character'Pos ('0') + Resource'Pos (Res));
141
142 File.Size (Length, Path);
143 end Resource_Size;
144
145 procedure Initialize (Success : out Boolean; MMConf_Base : Word64 := 0)
146 is
147 Addr : Word64;
148 Path : String (1 .. 43) := "/sys/devices/pci0000:xx/0000:xx:xx.x/config";
149 begin
150 Patch_Sysfs_Path (Path);
151
152 File.Map
153 (Addr => Addr,
154 Path => Path,
155 Readable => True,
156 Map_Copy => True,
157 Success => Success);
158 MM.Set_Base_Address (Addr);
159 end Initialize;
160
161end HW.PCI.Dev;