e7a51caa895c22d38dffe9f04542b314bb6caff8
[libxhcidbg.git] / src / hw-dbc.ads
1 --
2 -- Copyright (C) 2016-2017 secunet Security Networks AG
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
15 with HW.Sub_Regs;
16 with HW.MMIO_Regs;
17 pragma Elaborate_All (HW.MMIO_Regs);
18 with HW.MMIO_Range;
19 pragma Elaborate_All (HW.MMIO_Range);
20 with HW.DbC_Config;
21
22 package HW.DbC
23 with
24    Abstract_State => (State, (DMA with External))
25 is
26
27    procedure Init;
28
29    procedure Poll (Now : Boolean := False);
30
31    procedure Receive
32      (Buf : in out Buffer;
33       Len : in out Natural)
34    with
35       Post => Len <= Len'Old;
36
37    procedure Send
38      (Buf      : in     Buffer;
39       Len      : in out Natural;
40       Success  :    out Boolean)
41    with
42       Post => Len <= Len'Old;
43
44    ----------------------------------------------------------------------------
45
46 private
47
48    type Word2  is mod 2 **  2;
49    type Word3  is mod 2 **  3;
50    type Word4  is mod 2 **  4;
51    type Word5  is mod 2 **  5;
52    type Word10 is mod 2 ** 10;
53    type Word19 is mod 2 ** 19;
54    type Word20 is mod 2 ** 20;
55    type Word28 is mod 2 ** 28;
56
57    type Error is (
58       Success,
59       Communication_Error,
60       Driver_Error,
61       Stall_Error,
62       Data_Residue,
63       Bad_Descriptor,
64       Not_Enough_Bandwidth,
65       Unsupported_Size,
66       Unsupported_Count,
67       No_Space_Left,
68       Unknown_Device_Class,
69       Invalid_Data,
70       Invalid_Request,
71       Timeout,
72       Class_Prohibited,
73       Initialization_Error,
74       Controller_Error,
75       No_USB2_Address,
76       Device_Not_Supported,
77       Unknown_Error);
78
79    ----------------------------------------------------------------------------
80
81    Max_DMA_Xfers : constant   := 64;
82    Max_Bulk_Size : constant   := 4096;
83    Highest_Address : constant := 16#0000_ffff_ffff_ffff#;
84
85    Endpoint_Count : constant  := 3;
86    -- Endpoint 1 (the control endpoint) is handled by hardware
87    -- Endpoint 2 is the bulk out endpoint
88    -- Endpoint 3 is the bulk in endpoint
89    subtype Endpoint_Range is Positive range 2 .. Endpoint_Count;
90
91    type Global_Transfer_Id is range 0 .. Max_DMA_Xfers - 1;
92    -- DMA space for the last transfer is reserved for the kernel.
93    subtype Transfer_Id is
94       Global_Transfer_Id range 0 .. Global_Transfer_Id'Last - 1;
95
96    ----------------------------------------------------------------------------
97
98    MMIO_Size : constant := DbC_Config.XHCI_SIZE;
99    type MMIO_Index is range 0 .. MMIO_Size / 4 - 1;
100    type MMIO_Array is array (MMIO_Index) of Word32
101    with
102       Atomic_Components,
103       Size => MMIO_Size * 8;
104    pragma Warnings (Off, "atomic synchronization set");
105    package MMIO is new MMIO_Range
106      (Base_Addr   => DbC_Config.XHCI_BASE,
107       Element_T   => Word32,
108       Index_T     => MMIO_Index,
109       Array_T     => MMIO_Array);
110    pragma Warnings (On, "atomic synchronization set");
111
112    type Cap_Registers is
113      (Capability_Registers_Length,
114       XHCI_Extended_Caps);
115    package Cap_S_Regs is new Sub_Regs (Cap_Registers);
116    Cap_Reg_Descs : constant Cap_S_Regs.Array_T :=
117      (Capability_Registers_Length      => (16#00#,  7,  0),
118       XHCI_Extended_Caps               => (16#10#, 31, 16));
119    package Cap_Regs is new MMIO_Regs (MMIO, 0, Cap_S_Regs, Cap_Reg_Descs);
120
121    type Op_Registers is
122      (Run_Stop,
123       Host_Controller_Reset,
124       HC_Halted,
125       Controller_Not_Ready);
126    package Op_S_Regs is new Sub_Regs (Op_Registers);
127    Op_Reg_Descs : constant Op_S_Regs.Array_T :=
128      (Run_Stop                         => (16#00#,  0,  0),
129       Host_Controller_Reset            => (16#00#,  1,  1),
130       HC_Halted                        => (16#04#,  0,  0),
131       Controller_Not_Ready             => (16#04#, 11, 11));
132    package Op_Regs is new MMIO_Regs (MMIO, 0, Op_S_Regs, Op_Reg_Descs);
133
134    type xCap_Registers is
135      (Capability_ID,
136       Next_xCap);
137    package xCap_S_Regs is new Sub_Regs (xCap_Registers);
138    xCap_Reg_Descs : constant xCap_S_Regs.Array_T :=
139      (Capability_ID                    => (16#00#,  7,  0),
140       Next_xCap                        => (16#00#, 15,  8));
141    package xCap_Regs is new MMIO_Regs (MMIO, 0, xCap_S_Regs, xCap_Reg_Descs);
142    procedure Find_Next_xCap (Cap_Id : in Word8; Success : out Boolean);
143
144    type Legacy_Support_Registers is
145      (HC_BIOS_Owned_Semaphore,
146       HC_OS_Owned_Semaphore);
147    package Legacy_Support_S_Regs is new Sub_Regs (Legacy_Support_Registers);
148    Legacy_Support_Reg_Descs : constant Legacy_Support_S_Regs.Array_T :=
149      (HC_BIOS_Owned_Semaphore => (16#00#, 16, 16),
150       HC_OS_Owned_Semaphore   => (16#00#, 24, 24));
151    package Legacy_Support_Regs is new MMIO_Regs
152      (DbC.MMIO, 0, Legacy_Support_S_Regs, Legacy_Support_Reg_Descs);
153
154    type Registers is
155      (Doorbell_Target,
156       ERST_Size,
157       ERST_Base_Lo,
158       ERST_Base_Hi,
159       ER_Dequeue_Ptr_Lo,
160       ER_Dequeue_Ptr_Hi,
161       DBC_CONTROL,
162       DbC_Run,
163       Link_Status_Event_Enable,
164       Halt_OUT_TR,
165       Halt_IN_TR,
166       DbC_Run_Change,
167       Debug_Max_Burst_Size,
168       Device_Address,
169       DbC_Enable,
170       DBC_STATUS,
171       Event_Ring_Not_Empty,
172       DbC_System_Bus_Reset,
173       Debug_Port_Number,
174       DBC_PORTSC,
175       Current_Connect_Status,
176       Port_Enable_Disable,
177       Port_Reset,
178       Port_Link_State,
179       Port_Speed,
180       Connect_Status_Change,
181       Port_Reset_Change,
182       Port_Link_Status_Change,
183       Port_Config_Error_Change,
184       Context_Pointer_Lo,
185       Context_Pointer_Hi,
186       DbC_Protocol,
187       Vendor_ID,
188       Product_ID,
189       Device_Revision);
190    package S_Regs is new Sub_Regs (Registers);
191    Reg_Descs : constant S_Regs.Array_T :=
192      (Doorbell_Target                  => (16#04#, 15,  8),
193       ERST_Size                        => (16#08#, 15,  0),
194       ERST_Base_Lo                     => (16#10#, 31,  0),
195       ERST_Base_Hi                     => (16#14#, 31,  0),
196       ER_Dequeue_Ptr_Lo                => (16#18#, 31,  0),
197       ER_Dequeue_Ptr_Hi                => (16#1c#, 31,  0),
198       DBC_CONTROL                      => (16#20#, 31,  0),
199       DbC_Run                          => (16#20#,  0,  0),
200       Link_Status_Event_Enable         => (16#20#,  1,  1),
201       Halt_OUT_TR                      => (16#20#,  2,  2),
202       Halt_IN_TR                       => (16#20#,  3,  3),
203       DbC_Run_Change                   => (16#20#,  4,  4),
204       Debug_Max_Burst_Size             => (16#20#, 23, 16),
205       Device_Address                   => (16#20#, 30, 24),
206       DbC_Enable                       => (16#20#, 31, 31),
207       DBC_STATUS                       => (16#24#, 31,  0),
208       Event_Ring_Not_Empty             => (16#24#,  0,  0),
209       DbC_System_Bus_Reset             => (16#24#,  1,  1),
210       Debug_Port_Number                => (16#24#, 31, 24),
211       DBC_PORTSC                       => (16#28#, 31,  0),
212       Current_Connect_Status           => (16#28#,  0,  0),
213       Port_Enable_Disable              => (16#28#,  1,  1),
214       Port_Reset                       => (16#28#,  4,  4),
215       Port_Link_State                  => (16#28#,  8,  5),
216       Port_Speed                       => (16#28#, 13, 10),
217       Connect_Status_Change            => (16#28#, 17, 17),
218       Port_Reset_Change                => (16#28#, 21, 21),
219       Port_Link_Status_Change          => (16#28#, 22, 22),
220       Port_Config_Error_Change         => (16#28#, 23, 23),
221       Context_Pointer_Lo               => (16#30#, 31,  0),
222       Context_Pointer_Hi               => (16#34#, 31,  0),
223       DbC_Protocol                     => (16#38#,  7,  0),
224       Vendor_ID                        => (16#38#, 31, 16),
225       Product_ID                       => (16#3c#, 15,  0),
226       Device_Revision                  => (16#3c#, 31, 16));
227    package Regs is new MMIO_Regs (MMIO, 0, S_Regs, Reg_Descs);
228
229    procedure Ring_Doorbell (EP : Endpoint_Range)
230    with
231       Pre => Regs.Byte_Offset /= 0;
232
233 end HW.DbC;
234
235 --  vim: set ts=8 sts=3 sw=3 et: