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 for I in Natural range 0 .. DMA_Len - 1 loop
111 Buf (Buf'First + I) := DMA_Buf (DMA_Off + I);
115 procedure Copy_DMA_Out
120 DMA_Off : Natural := 0)
124 with Address => System'To_Address (Transfer_Info.Physical (Id));
125 DMA_Len : constant Natural := Natural'Min (Max_Bulk_Size - DMA_Off, Len);
127 for I in Natural range 0 .. DMA_Len - 1 loop
128 DMA_Buf (DMA_Off + I) := Buf (Off + I);
132 ----------------------------------------------------------------------------
135 (Buf : in out Buffer;
136 Len : in out Natural)
144 Transfer_Info.Walk_Finished (3, Ctr, Id, Success);
147 (Transfer_Info.Get_Status (Id) = DbC.Success or
148 Transfer_Info.Get_Status (Id) = DbC.Data_Residue);
149 Transfer_Info.Restart (Id, Max_Bulk_Size); -- ignore failed transfers
150 Start_Bulk (Id, True);
155 Transfer_Info.Get_Length (Id) - Transfer_Info.Get_Offset (Id));
160 DMA_Off => Transfer_Info.Get_Offset (Id));
161 Transfer_Info.Set_Offset (Id, Transfer_Info.Get_Offset (Id) + Len);
162 if Transfer_Info.Get_Offset (Id) = Transfer_Info.Get_Length (Id) then
163 Transfer_Info.Restart (Id, Max_Bulk_Size);
164 Start_Bulk (Id, True);
171 ----------------------------------------------------------------------------
173 procedure Process_Finished_Sends
181 Transfer_Info.Walk_Finished (2, Ctr, Id, Success);
182 exit when not Success;
183 Transfer_Info.Reset (Id);
185 end Process_Finished_Sends;
187 ----------------------------------------------------------------------------
191 Len : in out Natural;
192 Start_Now : in Boolean;
193 Success : out Boolean)
197 Appended : Natural := 0;
199 if not Transfer_Rings.Last_Started (2) then
201 Transfer_Info.Append (2, Appended, Offset, Id);
209 Transfer_Rings.Requeue_Data_TRB
211 Length => Transfer_Info.Get_Length (Id),
212 Buf_Addr => Transfer_Info.Physical (Id));
217 if Len > Appended then
218 Len := Natural'Min (Len - Appended, Max_Bulk_Size);
220 Process_Finished_Sends;
228 if Success and not Transfer_Rings.Full (2) then
232 Off => Buf'First + Appended,
235 Start_Bulk (Id, Start_Now);
241 Len := Len + Appended;
248 end HW.DbC.Transfers;
250 -- vim: set ts=8 sts=3 sw=3 et: