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.DMA_Buffers;
19 with HW.DbC.Transfer_Rings;
22 package body HW.DbC.Events
25 (State => (Next, CCS),
29 Debug_TD_Events : constant Boolean := False;
31 ----------------------------------------------------------------------------
33 Ring : TRBs.Transfer_Ring
38 Address => System'To_Address (DMA_Buffers.Event_Ring_Base);
40 Next : TRBs.Ring_Range;
43 ----------------------------------------------------------------------------
45 function Last_Physical return Word64
48 use type TRBs.Ring_Range;
50 return DMA_Buffers.Event_Ring_Base + Word64 (Next - 1) * TRBs.TRB_Size;
53 ----------------------------------------------------------------------------
58 TRBs.Clear_Ring (Ring, 1);
63 ----------------------------------------------------------------------------
65 function Ready return Boolean
69 TRBs.Get_Cycle (Data => Ring (Next),
70 Cycle => Current_Cycle);
71 return Current_Cycle = CCS;
74 procedure Update_Dequeue_Ptr
77 Phys : constant Word64 := Last_Physical;
79 Regs.Write (ER_Dequeue_Ptr_Lo, Phys and 16#ffff_ffff#);
80 Regs.Write (ER_Dequeue_Ptr_Hi, Shift_Right (Phys, 32));
81 end Update_Dequeue_Ptr;
83 -- advances to the next event
84 -- event ring has no link TRBs, it simply rolls over
87 use type TRBs.Ring_Range;
93 -- Update event dequeue pointer regularly.
98 ----------------------------------------------------------------------------
100 procedure Handle_Transfer_Event
103 CC : TRBs.Completion_Code;
104 Length, EP : Natural;
108 TRBs.Get_Slot_ID (Data => Ring (Next),
110 TRBs.Get_Endpoint_ID (Data => Ring (Next),
112 TRBs.Get_Parameter (Data => Ring (Next),
113 Parameter => Pointer);
114 TRBs.Get_Event_Length (Data => Ring (Next),
116 TRBs.Get_Completion_Code (Data => Ring (Next),
119 if ID = 1 and EP in Endpoint_Range then
120 pragma Debug (Debug_TD_Events, Debug.Put ("TD finished; Length: "));
121 pragma Debug (Debug_TD_Events, Debug.Put_Int32 (Int32 (Length)));
122 pragma Debug (Debug_TD_Events, Debug.Put ("; Status: "));
123 pragma Debug (Debug_TD_Events, Debug.Put_Int32 (Int32 (CC)));
124 pragma Debug (Debug_TD_Events, Debug.Put_Reg64 ("; Pointer", Pointer));
125 Transfer_Rings.Dequeue
128 Status => TRBs.CC_To_Usb_Error (CC),
129 Remaining_Length => Length);
131 pragma Debug (Debug.Put
132 ("WARNING: Spurious transfer event for ID "));
133 pragma Debug (Debug.Put_Int32 (Int32 (ID)));
134 pragma Debug (Debug.Put (", EP "));
135 pragma Debug (Debug.Put_Int32 (Int32 (EP)));
136 pragma Debug (Debug.Put_Line (":"));
137 pragma Debug (Debug.Put_Reg64 (" Pointer", Pointer));
138 pragma Debug (Debug.Put_Reg32 (" TL", Word32 (Length)));
139 pragma Debug (Debug.Put_Reg8 (" CC", Word8 (CC)));
143 end Handle_Transfer_Event;
145 procedure Handle_Host_Controller_Event
147 CC : TRBs.Completion_Code;
149 TRBs.Get_Completion_Code (Data => Ring (Next),
152 when TRBs.Event_Ring_Full_Error =>
153 pragma Debug (Debug.Put_Line ("Event ring full!"));
154 -- If we get here, we have processed the whole queue:
155 -- xHC pushes this event, when it sees the ring full,
156 -- full of other events.
157 -- IMO it's save and necessary to update the dequeue
162 pragma Debug (Debug.Put_Reg8
163 ("WARNING: Spurious host controller event", Word8 (CC)));
166 end Handle_Host_Controller_Event;
168 procedure Handle_Event
170 TRB_Type : TRBs.TRB_Types;
172 TRBs.Get_Type (Data => Ring (Next),
173 TRB_Type => TRB_Type);
175 when TRBs.Transfer_Event =>
176 Handle_Transfer_Event;
177 when TRBs.Port_Status_Change_Event =>
178 pragma Debug (Debug.Put_Line ("Port status change event."));
180 when TRBs.Host_Controller_Event =>
181 Handle_Host_Controller_Event;
183 pragma Debug (Debug.Put_Reg8
184 ("WARNING: Spurious event", Word8 (TRB_Type)));
189 procedure Handle_Events
191 Update_Ptr : Boolean;
204 -- vim: set ts=8 sts=3 sw=3 et: