2 -- Copyright (C) 2016-2017 secunet Security Networks AG
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.
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.
18 with HW.DbC.Transfer_Info;
19 with HW.DbC.Transfer_Rings;
21 package body HW.DbC.Transfers
24 Debug_TDs : constant Boolean := False;
26 Num_Receive_TDs : constant := 2;
28 ----------------------------------------------------------------------------
30 procedure Start_Bulk (Id : DbC.Transfer_Id; Start_Now : Boolean)
32 EP : constant Endpoint_Range := Transfer_Info.Get_Endpoint (Id);
33 Len : constant Natural := Transfer_Info.Get_Length (Id);
34 Pointer : constant Word64 := Transfer_Info.Physical (Id);
37 Transfer_Rings.Enqueue_Data_TRB
41 Toggle_CS => Start_Now);
47 pragma Debug (Debug_TDs, Debug.Put ("TD started; Length: "));
48 pragma Debug (Debug_TDs, Debug.Put_Int32 (Int32 (Len)));
49 pragma Debug (Debug_TDs, Debug.Put ("; Transfer: "));
50 pragma Debug (Debug_TDs, Debug.Put_Word16 (Word16 (Id)));
51 pragma Debug (Debug_TDs, Debug.Put_Reg64 ("; Pointer", Pointer));
54 ----------------------------------------------------------------------------
56 procedure Reset (Initial_Reset : Boolean)
62 Transfer_Rings.Initialize (2);
63 Transfer_Rings.Initialize (3);
66 for I in 1 .. Num_Receive_TDs loop
69 Length => Max_Bulk_Size,
72 exit when not Success;
73 Start_Bulk (Id, False);
78 Transfer_Info.Walk_Started (Ctr, Id, Success);
79 exit when not Success;
80 Start_Bulk (Id, False);
88 for EP in Endpoint_Range loop
89 Transfer_Rings.Toggle_CS (EP);
94 ----------------------------------------------------------------------------
96 subtype DMA_Range is Natural range 0 .. Max_Bulk_Size - 1;
97 subtype DMA_Buffer is Buffer (DMA_Range);
100 (Id : in Transfer_Id;
103 DMA_Off : in Natural)
107 with Address => System'To_Address (Transfer_Info.Physical (Id));
108 DMA_Len : constant Natural := Natural'Min (Max_Bulk_Size - DMA_Off, Len);
110 Buf (Buf'First .. Buf'First + DMA_Len - 1) :=
111 DMA_Buf (DMA_Off .. DMA_Off + DMA_Len - 1);
114 procedure Copy_DMA_Out
119 DMA_Off : Natural := 0)
123 with Address => System'To_Address (Transfer_Info.Physical (Id));
124 DMA_Len : constant Natural := Natural'Min (Max_Bulk_Size - DMA_Off, Len);
126 DMA_Buf (DMA_Off .. DMA_Off + DMA_Len - 1) :=
127 Buf (Off .. Off + DMA_Len - 1);
130 ----------------------------------------------------------------------------
133 (Buf : in out Buffer;
134 Len : in out Natural)
142 Transfer_Info.Walk_Finished (3, Ctr, Id, Success);
145 (Transfer_Info.Get_Status (Id) = DbC.Success or
146 Transfer_Info.Get_Status (Id) = DbC.Data_Residue);
147 Transfer_Info.Restart (Id, Max_Bulk_Size); -- ignore failed transfers
148 Start_Bulk (Id, True);
153 Transfer_Info.Get_Length (Id) - Transfer_Info.Get_Offset (Id));
158 DMA_Off => Transfer_Info.Get_Offset (Id));
159 Transfer_Info.Set_Offset (Id, Transfer_Info.Get_Offset (Id) + Len);
160 if Transfer_Info.Get_Offset (Id) = Transfer_Info.Get_Length (Id) then
161 Transfer_Info.Restart (Id, Max_Bulk_Size);
162 Start_Bulk (Id, True);
169 ----------------------------------------------------------------------------
171 procedure Process_Finished_Sends
179 Transfer_Info.Walk_Finished (2, Ctr, Id, Success);
180 exit when not Success;
181 Transfer_Info.Reset (Id);
183 end Process_Finished_Sends;
185 ----------------------------------------------------------------------------
189 Len : in out Natural;
190 Start_Now : in Boolean;
191 Success : out Boolean)
195 Appended : Natural := 0;
197 if not Transfer_Rings.Last_Started (2) then
199 Transfer_Info.Append (2, Appended, Offset, Id);
207 Transfer_Rings.Requeue_Data_TRB
209 Length => Transfer_Info.Get_Length (Id),
210 Buf_Addr => Transfer_Info.Physical (Id));
215 if Len > Appended then
216 Len := Natural'Min (Len - Appended, Max_Bulk_Size);
218 Process_Finished_Sends;
226 if Success and not Transfer_Rings.Full (2) then
230 Off => Buf'First + Appended,
233 Start_Bulk (Id, Start_Now);
239 Len := Len + Appended;
246 end HW.DbC.Transfers;
248 -- vim: set ts=8 sts=3 sw=3 et: