[USBPORT] Add USB2_AddDataBitStuff().
[reactos.git] / drivers / usb / usbport / usb2.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort USB 2.0 functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 //#define NDEBUG
11 #include <debug.h>
12
13 USHORT
14 NTAPI
15 USB2_AddDataBitStuff(IN USHORT DataTime)
16 {
17 return (DataTime + (DataTime / 16));
18 }
19
20 ULONG
21 NTAPI
22 USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
23 {
24 ULONG TransferType;
25 ULONG Direction;
26 ULONG DeviceSpeed;
27 ULONG Overhead;
28 ULONG HostDelay;
29
30 TransferType = TtEndpoint->TtEndpointParams.TransferType;
31 Direction = TtEndpoint->TtEndpointParams.Direction;
32 DeviceSpeed = TtEndpoint->TtEndpointParams.Direction;
33
34 HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
35
36 if (DeviceSpeed == UsbHighSpeed)
37 {
38 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
39 {
40 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
41 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
42 else
43 Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
44 }
45 else
46 {
47 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
48 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
49 else
50 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
51 }
52 }
53 else if (DeviceSpeed == UsbFullSpeed)
54 {
55 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
56 Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
57 else
58 Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
59 }
60 else
61 {
62 Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
63 }
64
65 return Overhead;
66 }
67
68 VOID
69 NTAPI
70 USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
71 IN UCHAR TransferType,
72 IN UCHAR Direction,
73 IN UCHAR DeviceSpeed,
74 IN USHORT Period,
75 IN USHORT MaxPacketSize,
76 IN PUSB2_TT Tt)
77 {
78 RtlZeroMemory(TtEndpoint, sizeof(USB2_TT_ENDPOINT));
79
80 TtEndpoint->TtEndpointParams.TransferType = TransferType;
81 TtEndpoint->TtEndpointParams.Direction = Direction;
82 TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
83
84 TtEndpoint->Period = Period;
85 TtEndpoint->MaxPacketSize = MaxPacketSize;
86 TtEndpoint->Tt = Tt;
87 }
88
89 BOOLEAN
90 NTAPI
91 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
92 IN PUSB2_REBALANCE Rebalance,
93 IN PULONG RebalanceListEntries)
94 {
95 DPRINT("USB2_AllocateTimeForEndpoint: UNIMPLEMENTED. FIXME\n");
96 ASSERT(FALSE);
97 return FALSE;
98 }
99
100 BOOLEAN
101 NTAPI
102 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
103 IN PUSB2_REBALANCE Rebalance,
104 IN PULONG RebalanceListEntries)
105 {
106 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
107 ASSERT(FALSE);
108 return FALSE;
109 }
110
111 VOID
112 NTAPI
113 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
114 {
115 ULONG BusBandwidth;
116 ULONG NewBusBandwidth;
117 ULONG MaxBusBandwidth = 0;
118 ULONG MinBusBandwidth;
119 ULONG ix;
120
121 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
122
123 BusBandwidth = TtExtension->BusBandwidth;
124 MinBusBandwidth = BusBandwidth;
125
126 for (ix = 0; ix < USB2_FRAMES; ix++)
127 {
128 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
129
130 if (NewBusBandwidth > MaxBusBandwidth)
131 MaxBusBandwidth = NewBusBandwidth;
132
133 if (NewBusBandwidth < MinBusBandwidth)
134 MinBusBandwidth = NewBusBandwidth;
135 }
136
137 TtExtension->MaxBandwidth = MaxBusBandwidth;
138
139 if (MinBusBandwidth == BusBandwidth)
140 TtExtension->MinBandwidth = 0;
141 else
142 TtExtension->MinBandwidth = MinBusBandwidth;
143 }
144
145 BOOLEAN
146 NTAPI
147 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
148 IN PUSBPORT_ENDPOINT Endpoint)
149 {
150 PUSBPORT_DEVICE_EXTENSION FdoExtension;
151 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
152 PUSB2_TT_EXTENSION TtExtension;
153 ULONG TransferType;
154 PUSB2_REBALANCE Rebalance;
155 LIST_ENTRY RebalanceList;
156 ULONG RebalanceListEntries;
157 PUSB2_TT_ENDPOINT TtEndpoint;
158 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
159
160 PUSB2_TT Tt;
161 USB_DEVICE_SPEED DeviceSpeed;
162 ULONG Period;
163
164 ULONG ix;
165 BOOLEAN Direction;
166 BOOLEAN Result;
167
168 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
169 FdoDevice,
170 Endpoint);
171
172 EndpointProperties = &Endpoint->EndpointProperties;
173 EndpointProperties->ScheduleOffset = 0;
174
175 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
176 {
177 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
178 return TRUE;
179 }
180
181 FdoExtension = FdoDevice->DeviceExtension;
182
183 TransferType = EndpointProperties->TransferType;
184 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
185
186 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
187 TransferType == USBPORT_TRANSFER_TYPE_BULK)
188 {
189 return TRUE;
190 }
191
192 if (Endpoint->TtExtension)
193 TtExtension = Endpoint->TtExtension;
194 else
195 TtExtension = NULL;
196
197 InitializeListHead(&RebalanceList);
198
199 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
200 sizeof(USB2_REBALANCE),
201 USB_PORT_TAG);
202
203 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
204 Rebalance,
205 TtExtension);
206
207 if (Rebalance)
208 {
209 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
210
211 TtEndpoint = Endpoint->TtEndpoint;
212 TtEndpoint->Endpoint = Endpoint;
213
214 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
215 DeviceSpeed = EndpointProperties->DeviceSpeed;
216
217 switch (DeviceSpeed)
218 {
219 case UsbLowSpeed:
220 case UsbFullSpeed:
221 {
222 Tt = &TtExtension->Tt;
223 Period = USB2_FRAMES;
224
225 while (Period && Period > EndpointProperties->Period);
226 {
227 Period >>= 1;
228 }
229
230 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
231 break;
232 }
233
234 case UsbHighSpeed:
235 {
236 Tt = &FdoExtension->Usb2Extension->HcTt;
237 Period = EndpointProperties->Period;
238
239 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
240 Period = USB2_MAX_MICROFRAMES;
241
242 break;
243 }
244
245 default:
246 {
247 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n", DeviceSpeed);
248 DbgBreakPoint();
249 Tt = &TtExtension->Tt;
250 break;
251 }
252 }
253
254 USB2_InitTtEndpoint(TtEndpoint,
255 TransferType,
256 Direction,
257 DeviceSpeed,
258 Period,
259 EndpointProperties->MaxPacketSize,
260 Tt);
261
262 RebalanceListEntries = USB2_FRAMES - 2;
263
264 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
265 Rebalance,
266 &RebalanceListEntries);
267
268 if (Result)
269 {
270 Result = USB2_PromotePeriods(TtEndpoint,
271 Rebalance,
272 &RebalanceListEntries);
273 }
274
275 RebalanceListEntries = 0;
276
277 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
278 {
279 RebalanceListEntries = ix + 1;
280 }
281 }
282 else
283 {
284 RebalanceListEntries = 0;
285 Result = FALSE;
286 }
287
288 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
289 RebalanceListEntries,
290 Result);
291
292 for (ix = 0; ix < RebalanceListEntries; ix++)
293 {
294 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceEndpoint[%X] - %X\n",
295 ix,
296 Rebalance->RebalanceEndpoint[ix]);
297
298 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
299
300 InsertTailList(&RebalanceList,
301 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
302 }
303
304 if (Rebalance)
305 ExFreePool(Rebalance);
306
307 if (Result)
308 {
309 DPRINT1("USBPORT_AllocateBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
310 ASSERT(FALSE);
311 }
312
313 //USB2_Rebalance(FdoDevice, &RebalanceList);
314
315 if (!TtExtension)
316 {
317 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
318 return Result;
319 }
320
321 for (ix = 0; ix < USB2_FRAMES; ix++)
322 {
323 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
324 }
325
326 USBPORT_UpdateAllocatedBwTt(TtExtension);
327
328 for (ix = 0; ix < USB2_FRAMES; ix++)
329 {
330 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
331 }
332
333 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
334
335 return Result;
336 }
337
338 VOID
339 NTAPI
340 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
341 IN PUSBPORT_ENDPOINT Endpoint)
342 {
343 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
344 }
345
346 VOID
347 NTAPI
348 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
349 IN PUSB2_TT Tt)
350 {
351 ULONG ix;
352 ULONG jx;
353
354 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
355
356 Tt->HcExtension = HcExtension;
357 Tt->DelayTime = 1;
358 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
359
360 for (ix = 0; ix < USB2_FRAMES; ix++)
361 {
362 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
363 Tt->FrameBudget[ix].AltEndpoint = NULL;
364
365 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
366 {
367 Tt->TimeCS[ix][jx] = 0;
368 Tt->NumStartSplits[ix][jx] = 0;
369 }
370
371 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
372
373 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
374 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
375 USBPORT_TRANSFER_DIRECTION_OUT,
376 UsbFullSpeed,
377 USB2_FRAMES,
378 0,
379 Tt);
380
381 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
382 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
383 Tt->IsoEndpoint[ix].StartFrame = ix;
384 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
385
386 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
387
388 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
389 USBPORT_TRANSFER_TYPE_INTERRUPT,
390 USBPORT_TRANSFER_DIRECTION_OUT,
391 UsbFullSpeed,
392 USB2_FRAMES,
393 0,
394 Tt);
395
396 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
397 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
398 Tt->IntEndpoint[ix].StartFrame = ix;
399 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
400 }
401 }
402
403 VOID
404 NTAPI
405 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
406 {
407 ULONG ix;
408 ULONG jx;
409
410 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
411
412 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
413
414 for (ix = 0; ix < USB2_FRAMES; ix++)
415 {
416 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
417 {
418 HcExtension->TimeUsed[ix][jx] = 0;
419 }
420 }
421
422 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
423
424 USB2_InitTT(HcExtension, &HcExtension->HcTt);
425 }