b3d7f4d80c1a4edff5c478890af51b573c1e47e1
[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 BOOLEAN
14 NTAPI
15 USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,
16 IN ULONG CalcBusTime,
17 IN ULONG LimitAllocation)
18 {
19 ULONG BusTime;
20 BOOLEAN Result = TRUE;
21
22 BusTime = *OutTimeUsed + CalcBusTime;
23 *OutTimeUsed += CalcBusTime;
24
25 if (BusTime > LimitAllocation)
26 {
27 DPRINT("USB2_AllocateCheck: BusTime > LimitAllocation\n");
28 Result = FALSE;
29 }
30
31 return Result;
32 }
33
34 USHORT
35 NTAPI
36 USB2_AddDataBitStuff(IN USHORT DataTime)
37 {
38 return (DataTime + (DataTime / 16));
39 }
40
41 VOID
42 NTAPI
43 USB2_IncMicroFrame(OUT PUCHAR frame,
44 OUT PUCHAR uframe)
45 {
46 ++*uframe;
47
48 if (*uframe > (USB2_MICROFRAMES - 1))
49 {
50 *uframe = 0;
51 *frame = (*frame + 1) & (USB2_FRAMES - 1);
52 }
53 }
54
55 VOID
56 NTAPI
57 USB2_GetPrevMicroFrame(OUT PUCHAR frame,
58 OUT PUCHAR uframe)
59 {
60 *uframe = USB2_MICROFRAMES - 1;
61
62 if (*frame)
63 --*frame;
64 else
65 *frame = USB2_FRAMES - 1;
66 }
67
68 BOOLEAN
69 NTAPI
70 USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
71 IN PUSB2_TT_ENDPOINT TtEndpoint)
72 {
73 ULONG TransferType;
74
75 DPRINT("USB2_CheckTtEndpointInsert: nextTtEndpoint - %p, TtEndpoint - %p\n",
76 nextTtEndpoint,
77 TtEndpoint);
78
79 ASSERT(TtEndpoint);
80
81 if (TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
82 {
83 DPRINT1("USB2_CheckTtEndpointInsert: Result - FALSE\n");
84 return FALSE;
85 }
86
87 if (!nextTtEndpoint)
88 {
89 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
90 return TRUE;
91 }
92
93 TransferType = TtEndpoint->TtEndpointParams.TransferType;
94
95 if (nextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod &&
96 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
97 {
98 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
99 return TRUE;
100 }
101
102 if ((nextTtEndpoint->ActualPeriod <= TtEndpoint->ActualPeriod &&
103 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) ||
104 nextTtEndpoint == TtEndpoint)
105 {
106 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
107 return TRUE;
108 }
109
110 DPRINT("USB2_CheckTtEndpointInsert: Result - FALSE\n");
111 return FALSE;
112 }
113
114 ULONG
115 NTAPI
116 USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
117 {
118 ULONG TransferType;
119 ULONG Direction;
120 ULONG DeviceSpeed;
121 ULONG Overhead;
122 ULONG HostDelay;
123
124 TransferType = TtEndpoint->TtEndpointParams.TransferType;
125 Direction = TtEndpoint->TtEndpointParams.Direction;
126 DeviceSpeed = TtEndpoint->TtEndpointParams.Direction;
127
128 HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
129
130 if (DeviceSpeed == UsbHighSpeed)
131 {
132 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
133 {
134 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
135 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
136 else
137 Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
138 }
139 else
140 {
141 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
142 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
143 else
144 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
145 }
146 }
147 else if (DeviceSpeed == UsbFullSpeed)
148 {
149 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
150 Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
151 else
152 Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
153 }
154 else
155 {
156 Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
157 }
158
159 return Overhead;
160 }
161
162 VOID
163 NTAPI
164 USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,
165 IN PULONG OverheadSS,
166 IN PULONG OverheadCS)
167 {
168 ULONG TransferType;
169 ULONG Direction;
170 ULONG HostDelay;
171
172 TransferType = TtEndpoint->TtEndpointParams.TransferType;
173 Direction = TtEndpoint->TtEndpointParams.Direction;
174
175 HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
176
177 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
178 {
179 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
180 {
181 *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD;
182 *OverheadCS = 0;
183 }
184 else
185 {
186 *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_OUT_OVERHEAD;
187 *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_OUT_OVERHEAD;
188 }
189 }
190 else
191 {
192 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
193 {
194 *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD;
195 *OverheadCS = HostDelay + USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD;
196 }
197 else
198 {
199 *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_IN_OVERHEAD;
200 *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_IN_OVERHEAD;
201 }
202
203 DPRINT("USB2_GetHsOverhead: *OverheadSS - %X, *OverheadCS - %X\n",
204 *OverheadSS,
205 *OverheadCS);
206 }
207 }
208
209 ULONG
210 NTAPI
211 USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,
212 IN ULONG Frame)
213 {
214 PUSB2_TT_ENDPOINT nextTtEndpoint;
215 ULONG Result;
216
217 DPRINT("USB2_GetLastIsoTime: TtEndpoint - %p, Frame - %X\n",
218 TtEndpoint,
219 Frame);
220
221 nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].IsoEndpoint->NextTtEndpoint;
222
223 if (nextTtEndpoint ||
224 (nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint) != NULL)
225 {
226 Result = nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
227 }
228 else
229 {
230 Result = USB2_FS_SOF_TIME;
231 }
232
233 return Result;
234 }
235
236 ULONG
237 NTAPI
238 USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
239 IN PUSB2_TT_ENDPOINT TtEndpoint,
240 IN PUSB2_TT_ENDPOINT prevTtEndpoint,
241 IN ULONG Frame)
242 {
243 PUSB2_TT_ENDPOINT ttEndpoint;
244 ULONG TransferType;
245
246 DPRINT("USB2_GetStartTime: nextTtEndpoint - %p, TtEndpoint - %p, prevTtEndpoint - %p, Frame - %X\n",
247 nextTtEndpoint,
248 TtEndpoint,
249 prevTtEndpoint,
250 Frame);
251
252 TransferType = TtEndpoint->TtEndpointParams.TransferType;
253
254 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
255 {
256 if (nextTtEndpoint)
257 return nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
258
259 ttEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint;
260
261 if (ttEndpoint)
262 return ttEndpoint->StartTime + ttEndpoint->CalcBusTime;
263 else
264 return USB2_FS_SOF_TIME;
265 }
266 else
267 {
268 ttEndpoint = prevTtEndpoint;
269
270 if (ttEndpoint == TtEndpoint->Tt->FrameBudget[Frame].IntEndpoint)
271 return USB2_GetLastIsoTime(TtEndpoint, Frame);
272 else
273 return ttEndpoint->StartTime + ttEndpoint->CalcBusTime;
274 }
275 }
276
277 VOID
278 NTAPI
279 USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
280 IN UCHAR TransferType,
281 IN UCHAR Direction,
282 IN UCHAR DeviceSpeed,
283 IN USHORT Period,
284 IN USHORT MaxPacketSize,
285 IN PUSB2_TT Tt)
286 {
287 TtEndpoint->TtEndpointParams.TransferType = TransferType;
288 TtEndpoint->TtEndpointParams.Direction = Direction;
289 TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
290
291 TtEndpoint->Period = Period;
292 TtEndpoint->MaxPacketSize = MaxPacketSize;
293 TtEndpoint->Tt = Tt;
294
295 TtEndpoint->CalcBusTime = 0;
296 TtEndpoint->StartTime = 0;
297 TtEndpoint->ActualPeriod = 0;
298 TtEndpoint->StartFrame = 0;
299 TtEndpoint->StartMicroframe = 0;
300
301 TtEndpoint->Nums.AsULONG = 0;
302 TtEndpoint->NextTtEndpoint = NULL;
303 TtEndpoint->Reserved2 = 0;
304 TtEndpoint->PreviosPeriod = 0;
305 TtEndpoint->IsPromoted = FALSE;
306 }
307
308 BOOLEAN
309 NTAPI
310 USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
311 IN LONG Frame)
312 {
313 PUSB2_HC_EXTENSION HcExtension;
314 PUSB2_TT Tt;
315 ULONG TransferType;
316 ULONG Direction;
317 ULONG DataTime;
318 ULONG RemainDataTime;
319 ULONG OverheadCS;
320 ULONG OverheadSS;
321 ULONG ix;
322 USHORT PktSize;
323 UCHAR frame;
324 UCHAR uframe;
325 BOOL Result = TRUE;
326
327 DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, TtEndpoint->StartFrame - %X\n",
328 TtEndpoint,
329 Frame,
330 TtEndpoint->StartFrame);
331
332 Tt = TtEndpoint->Tt;
333 HcExtension = Tt->HcExtension;
334
335 TransferType = TtEndpoint->TtEndpointParams.TransferType;
336 Direction = TtEndpoint->TtEndpointParams.Direction;
337
338 if (Frame == 0)
339 {
340 TtEndpoint->StartMicroframe =
341 TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1;
342
343 DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n",
344 TtEndpoint->StartMicroframe);
345 }
346
347 USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
348
349 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
350 {
351 if (Frame == 0)
352 {
353 TtEndpoint->Nums.NumStarts = 1;
354
355 if ((CHAR)TtEndpoint->StartMicroframe < 5)
356 {
357 TtEndpoint->Nums.NumCompletes = 3;
358 }
359 else
360 {
361 TtEndpoint->Nums.NumCompletes = 2;
362 }
363 }
364 }
365 else
366 {
367 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
368 {
369 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
370 ASSERT(FALSE);
371 }
372 else
373 {
374 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
375 ASSERT(FALSE);
376 }
377 }
378
379 frame = TtEndpoint->StartFrame + Frame;
380 uframe = TtEndpoint->StartMicroframe;
381
382 if (TtEndpoint->StartMicroframe == 0xFF)
383 USB2_GetPrevMicroFrame(&frame, &uframe);
384
385 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
386 {
387 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
388 OverheadSS,
389 USB2_MAX_MICROFRAME_ALLOCATION))
390 {
391 Result = FALSE;
392 }
393
394 if (Tt->NumStartSplits[frame][uframe] > (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
395 {
396 DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
397 Tt->NumStartSplits[frame][uframe] + 1);
398
399 ASSERT(FALSE);
400 Result = FALSE;
401 }
402
403 ++Tt->NumStartSplits[frame][uframe];
404 USB2_IncMicroFrame(&frame, &uframe);
405 }
406
407 frame = TtEndpoint->StartFrame + Frame;
408 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
409
410 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
411 {
412 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
413 OverheadCS,
414 USB2_MAX_MICROFRAME_ALLOCATION))
415 {
416 Result = FALSE;
417 }
418
419 USB2_IncMicroFrame(&frame, &uframe);
420 }
421
422 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
423 {
424 DPRINT("USB2_AllocateHS: DIRECTION OUT UNIMPLEMENTED\n");
425 ASSERT(FALSE);
426 }
427 else
428 {
429 frame = TtEndpoint->StartFrame + Frame;
430 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
431
432 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
433 {
434 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
435 {
436 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
437 {
438 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
439 Tt->TimeCS[frame][uframe];
440 }
441 else
442 {
443 RemainDataTime = 0;
444 }
445
446 PktSize = TtEndpoint->MaxPacketSize;
447
448 if (RemainDataTime >= USB2_AddDataBitStuff(PktSize))
449 {
450 DataTime = USB2_AddDataBitStuff(PktSize);
451 }
452 else
453 {
454 DataTime = RemainDataTime;
455 }
456
457 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
458 DataTime,
459 USB2_MAX_MICROFRAME_ALLOCATION))
460 {
461 Result = FALSE;
462 }
463 }
464
465 PktSize = TtEndpoint->MaxPacketSize;
466
467 if (USB2_AddDataBitStuff(PktSize) < USB2_FS_RAW_BYTES_IN_MICROFRAME)
468 {
469 Tt->TimeCS[frame][uframe] += USB2_AddDataBitStuff(PktSize);
470 }
471 else
472 {
473 Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
474 }
475
476 USB2_IncMicroFrame(&frame, &uframe);
477 }
478 }
479
480 DPRINT("USB2_AllocateHS: Result - %X\n", Result);
481 return Result;
482 }
483
484 BOOLEAN
485 NTAPI
486 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
487 IN PUSB2_REBALANCE Rebalance,
488 IN PULONG RebalanceListEntries,
489 IN ULONG MaxFrames)
490 {
491 DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
492 ASSERT(FALSE);
493 return FALSE;
494 }
495
496 BOOLEAN
497 NTAPI
498 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
499 IN PUSB2_REBALANCE Rebalance,
500 IN PULONG RebalanceListEntries)
501 {
502 PUSB2_TT Tt;
503 PUSB2_HC_EXTENSION HcExtension;
504 ULONG Speed;
505 ULONG TimeUsed;
506 ULONG MinTimeUsed;
507 ULONG ix;
508 ULONG frame;
509 ULONG uframe;
510 ULONG Microframe;
511 ULONG TransferType;
512 ULONG Overhead;
513 ULONG LatestStart;
514 PUSB2_TT_ENDPOINT prevTtEndpoint;
515 PUSB2_TT_ENDPOINT nextTtEndpoint;
516 PUSB2_TT_ENDPOINT IntEndpoint;
517 ULONG StartTime;
518 ULONG calcBusTime;
519 BOOLEAN Result = TRUE;
520
521 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
522
523 Tt = TtEndpoint->Tt;
524 HcExtension = Tt->HcExtension;
525
526 TtEndpoint->Nums.NumStarts = 0;
527 TtEndpoint->Nums.NumCompletes = 0;
528
529 TtEndpoint->StartFrame = 0;
530 TtEndpoint->StartMicroframe = 0;
531
532 if (TtEndpoint->CalcBusTime)
533 {
534 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
535 return FALSE;
536 }
537
538 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
539
540 if (Speed == UsbHighSpeed)
541 {
542 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
543 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
544 else
545 TtEndpoint->ActualPeriod = TtEndpoint->Period;
546
547 MinTimeUsed = HcExtension->TimeUsed[0][0];
548
549 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
550 {
551 frame = ix / USB2_MICROFRAMES;
552 uframe = ix % (USB2_MICROFRAMES - 1);
553
554 TimeUsed = HcExtension->TimeUsed[frame][uframe];
555
556 if (TimeUsed < MinTimeUsed)
557 {
558 MinTimeUsed = TimeUsed;
559 TtEndpoint->StartFrame = frame;
560 TtEndpoint->StartMicroframe = uframe;
561 }
562 }
563
564 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
565 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
566
567 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
568 TtEndpoint->StartFrame,
569 TtEndpoint->StartMicroframe,
570 TtEndpoint->CalcBusTime);
571
572 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
573 TtEndpoint->StartMicroframe;
574
575 if (Microframe >= USB2_MAX_MICROFRAMES)
576 {
577 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
578 return TRUE;
579 }
580
581 for (ix = Microframe;
582 ix < USB2_MAX_MICROFRAMES;
583 ix += TtEndpoint->ActualPeriod)
584 {
585 frame = ix / USB2_MICROFRAMES;
586 uframe = ix % (USB2_MICROFRAMES - 1);
587
588 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
589 frame,
590 uframe,
591 HcExtension->TimeUsed[frame][uframe]);
592
593 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
594 TtEndpoint->CalcBusTime,
595 USB2_MAX_MICROFRAME_ALLOCATION))
596 {
597 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
598 Result = FALSE;
599 }
600 }
601
602 if (!Result)
603 {
604 for (ix = Microframe;
605 ix < USB2_MAX_MICROFRAMES;
606 ix += TtEndpoint->ActualPeriod)
607 {
608 frame = ix / USB2_MICROFRAMES;
609 uframe = ix % (USB2_MICROFRAMES - 1);
610
611 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
612 }
613 }
614
615 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
616 return TRUE;
617 }
618
619 /* Speed != UsbHighSpeed (FS/LS) */
620
621 if (TtEndpoint->Period > USB2_FRAMES)
622 TtEndpoint->ActualPeriod = USB2_FRAMES;
623 else
624 TtEndpoint->ActualPeriod = TtEndpoint->Period;
625
626 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
627
628 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
629 {
630 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
631 {
632 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
633 TtEndpoint->StartFrame = ix;
634 }
635 }
636
637 TransferType = TtEndpoint->TtEndpointParams.TransferType;
638
639 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
640 {
641 if (Speed == UsbFullSpeed)
642 {
643 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
644 }
645 else
646 {
647 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
648 return FALSE;
649 }
650 }
651 else
652 {
653 if (Speed == UsbFullSpeed)
654 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
655 else
656 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
657 }
658
659 if (Speed == UsbLowSpeed)
660 {
661 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
662 }
663 else
664 {
665 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
666 }
667
668 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
669
670 for (ix = 0;
671 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
672 ix += TtEndpoint->ActualPeriod)
673 {
674 frame = TtEndpoint->StartFrame + ix;
675
676 if (Tt->FrameBudget[frame].AltEndpoint &&
677 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
678 {
679 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
680 return FALSE;
681 }
682
683 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
684 prevTtEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
685 else
686 prevTtEndpoint = Tt->FrameBudget[frame].IntEndpoint;
687
688 for (nextTtEndpoint = prevTtEndpoint->NextTtEndpoint;
689 nextTtEndpoint;
690 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
691 {
692 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
693 {
694 break;
695 }
696
697 prevTtEndpoint = nextTtEndpoint;
698 }
699
700 StartTime = USB2_GetStartTime(nextTtEndpoint,
701 TtEndpoint,
702 prevTtEndpoint,
703 frame);
704
705 if (StartTime > LatestStart)
706 LatestStart = StartTime;
707 }
708
709 TtEndpoint->StartTime = LatestStart;
710
711 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
712 {
713 TtEndpoint->CalcBusTime = 0;
714 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
715 return FALSE;
716 }
717
718 for (ix = 0, frame = -TtEndpoint->StartFrame;
719 ix < USB2_FRAMES;
720 ix++, frame++)
721 {
722 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
723 ix,
724 frame,
725 TtEndpoint->StartFrame);
726
727 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
728 {
729 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
730 ASSERT(FALSE);
731 }
732 else
733 {
734 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
735 nextTtEndpoint = IntEndpoint->NextTtEndpoint;
736
737 for (nextTtEndpoint = IntEndpoint->NextTtEndpoint;
738 nextTtEndpoint;
739 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
740 {
741 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
742 break;
743 IntEndpoint = nextTtEndpoint;
744 }
745
746 if ((frame % TtEndpoint->ActualPeriod) == 0)
747 {
748 calcBusTime = 0;
749 }
750 else
751 {
752 if (nextTtEndpoint)
753 {
754 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
755 nextTtEndpoint->StartTime;
756 }
757 else
758 {
759 calcBusTime = TtEndpoint->CalcBusTime;
760 }
761
762 if (calcBusTime > 0)
763 {
764 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
765
766 if (!USB2_AllocateCheck(&TimeUsed,
767 calcBusTime,
768 USB2_FS_MAX_PERIODIC_ALLOCATION))
769 {
770 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
771 Result = FALSE;
772 }
773 }
774 }
775
776 if (nextTtEndpoint != TtEndpoint)
777 {
778 if ((frame % TtEndpoint->ActualPeriod) == 0)
779 {
780 if (frame == 0)
781 {
782 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
783 TtEndpoint->NextTtEndpoint = nextTtEndpoint;
784 }
785
786 IntEndpoint->NextTtEndpoint = TtEndpoint;
787
788 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextTtEndpoint - %p\n",
789 TtEndpoint,
790 nextTtEndpoint);
791 }
792
793 if (calcBusTime > 0)
794 {
795 BOOLEAN IsMoved;
796 BOOLEAN MoveResult;
797
798 DPRINT("USB2_AllocateTimeForEndpoint: nextTtEndpoint - %p, calcBusTime - %X\n",
799 nextTtEndpoint,
800 calcBusTime);
801
802 for (;
803 nextTtEndpoint;
804 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
805 {
806 MoveResult = USB2_MoveTtEndpoint(nextTtEndpoint,
807 calcBusTime,
808 Rebalance,
809 *RebalanceListEntries,
810 &IsMoved);
811
812 if (!IsMoved)
813 {
814 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
815 Result = FALSE;
816 }
817
818 if (!MoveResult)
819 break;
820 }
821 }
822 }
823 }
824
825 if ((frame % TtEndpoint->ActualPeriod) == 0)
826 {
827 if (!USB2_AllocateHS(TtEndpoint, frame))
828 {
829 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
830 Result = FALSE;
831 }
832
833 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
834 }
835
836 if (Result == FALSE)
837 {
838 USB2_DeallocateEndpointBudget(TtEndpoint,
839 Rebalance,
840 RebalanceListEntries,
841 ix + 1);
842
843 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
844 return FALSE;
845 }
846 }
847
848 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
849 return Result;
850 }
851
852 BOOLEAN
853 NTAPI
854 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
855 IN PUSB2_REBALANCE Rebalance,
856 IN PULONG RebalanceListEntries)
857 {
858 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
859 ASSERT(FALSE);
860 return FALSE;
861 }
862
863 VOID
864 NTAPI
865 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
866 {
867 ULONG BusBandwidth;
868 ULONG NewBusBandwidth;
869 ULONG MaxBusBandwidth = 0;
870 ULONG MinBusBandwidth;
871 ULONG ix;
872
873 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
874
875 BusBandwidth = TtExtension->BusBandwidth;
876 MinBusBandwidth = BusBandwidth;
877
878 for (ix = 0; ix < USB2_FRAMES; ix++)
879 {
880 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
881
882 if (NewBusBandwidth > MaxBusBandwidth)
883 MaxBusBandwidth = NewBusBandwidth;
884
885 if (NewBusBandwidth < MinBusBandwidth)
886 MinBusBandwidth = NewBusBandwidth;
887 }
888
889 TtExtension->MaxBandwidth = MaxBusBandwidth;
890
891 if (MinBusBandwidth == BusBandwidth)
892 TtExtension->MinBandwidth = 0;
893 else
894 TtExtension->MinBandwidth = MinBusBandwidth;
895 }
896
897 BOOLEAN
898 NTAPI
899 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
900 IN PUSBPORT_ENDPOINT Endpoint)
901 {
902 PUSBPORT_DEVICE_EXTENSION FdoExtension;
903 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
904 PUSB2_TT_EXTENSION TtExtension;
905 ULONG TransferType;
906 PUSB2_REBALANCE Rebalance;
907 LIST_ENTRY RebalanceList;
908 ULONG RebalanceListEntries;
909 PUSB2_TT_ENDPOINT TtEndpoint;
910 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
911 PUSB2_TT Tt;
912 USB_DEVICE_SPEED DeviceSpeed;
913 ULONG Period;
914 ULONG AllocedBusTime;
915 ULONG EndpointBandwidth;
916 ULONG ScheduleOffset;
917 ULONG Factor;
918 ULONG ix;
919 ULONG n;
920 BOOLEAN Direction;
921 UCHAR SMask;
922 UCHAR CMask;
923 UCHAR ActualPeriod;
924 BOOLEAN Result;
925
926 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
927 FdoDevice,
928 Endpoint);
929
930 EndpointProperties = &Endpoint->EndpointProperties;
931 EndpointProperties->ScheduleOffset = 0;
932
933 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
934 {
935 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
936 return TRUE;
937 }
938
939 FdoExtension = FdoDevice->DeviceExtension;
940
941 TransferType = EndpointProperties->TransferType;
942 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
943
944 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
945 TransferType == USBPORT_TRANSFER_TYPE_BULK)
946 {
947 return TRUE;
948 }
949
950 if (Endpoint->TtExtension)
951 TtExtension = Endpoint->TtExtension;
952 else
953 TtExtension = NULL;
954
955 InitializeListHead(&RebalanceList);
956
957 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
958 sizeof(USB2_REBALANCE),
959 USB_PORT_TAG);
960
961 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
962 Rebalance,
963 TtExtension);
964
965 if (Rebalance)
966 {
967 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
968
969 TtEndpoint = Endpoint->TtEndpoint;
970 TtEndpoint->Endpoint = Endpoint;
971
972 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
973 DeviceSpeed = EndpointProperties->DeviceSpeed;
974
975 switch (DeviceSpeed)
976 {
977 case UsbLowSpeed:
978 case UsbFullSpeed:
979 {
980 Tt = &TtExtension->Tt;
981
982 Period = USB2_FRAMES;
983
984 while (Period > 0 && Period > EndpointProperties->Period)
985 {
986 Period >>= 1;
987 }
988
989 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
990 break;
991 }
992
993 case UsbHighSpeed:
994 {
995 Tt = &FdoExtension->Usb2Extension->HcTt;
996
997 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
998 Period = USB2_MAX_MICROFRAMES;
999 else
1000 Period = EndpointProperties->Period;
1001
1002 break;
1003 }
1004
1005 default:
1006 {
1007 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1008 DeviceSpeed);
1009
1010 DbgBreakPoint();
1011
1012 Tt = &TtExtension->Tt;
1013 break;
1014 }
1015 }
1016
1017 USB2_InitTtEndpoint(TtEndpoint,
1018 TransferType,
1019 Direction,
1020 DeviceSpeed,
1021 Period,
1022 EndpointProperties->MaxPacketSize,
1023 Tt);
1024
1025 RebalanceListEntries = USB2_FRAMES - 2;
1026
1027 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1028 Rebalance,
1029 &RebalanceListEntries);
1030
1031 if (Result)
1032 {
1033 Result = USB2_PromotePeriods(TtEndpoint,
1034 Rebalance,
1035 &RebalanceListEntries);
1036 }
1037
1038 RebalanceListEntries = 0;
1039
1040 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1041 {
1042 RebalanceListEntries = ix + 1;
1043 }
1044 }
1045 else
1046 {
1047 RebalanceListEntries = 0;
1048 Result = FALSE;
1049 }
1050
1051 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1052 RebalanceListEntries,
1053 Result);
1054
1055 for (ix = 0; ix < RebalanceListEntries; ix++)
1056 {
1057 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1058
1059 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1060 ix,
1061 RebalanceTtEndpoint,
1062 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1063
1064 InsertTailList(&RebalanceList,
1065 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1066 }
1067
1068 if (Rebalance)
1069 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1070
1071 if (Result)
1072 {
1073 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1074 EndpointProperties->InterruptScheduleMask = SMask;
1075
1076 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1077 EndpointProperties->SplitCompletionMask = CMask;
1078
1079 AllocedBusTime = TtEndpoint->CalcBusTime;
1080
1081 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1082 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1083
1084 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1085 EndpointProperties->Period = ActualPeriod;
1086
1087 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1088 EndpointProperties->ScheduleOffset = ScheduleOffset;
1089
1090 Factor = USB2_FRAMES / ActualPeriod;
1091 ASSERT(Factor);
1092
1093 n = ScheduleOffset * Factor;
1094
1095 if (TtExtension)
1096 {
1097 for (ix = 0; ix < Factor; ix++)
1098 {
1099 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1100 }
1101 }
1102 else
1103 {
1104 for (ix = 1; ix < Factor; ix++)
1105 {
1106 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1107 }
1108 }
1109
1110 USBPORT_DumpingEndpointProperties(EndpointProperties);
1111 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
1112
1113 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1114 {
1115 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
1116 }
1117 }
1118
1119 //USB2_Rebalance(FdoDevice, &RebalanceList);
1120
1121 if (!TtExtension)
1122 {
1123 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1124 return Result;
1125 }
1126
1127 for (ix = 0; ix < USB2_FRAMES; ix++)
1128 {
1129 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1130 }
1131
1132 USBPORT_UpdateAllocatedBwTt(TtExtension);
1133
1134 for (ix = 0; ix < USB2_FRAMES; ix++)
1135 {
1136 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
1137 }
1138
1139 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1140
1141 return Result;
1142 }
1143
1144 VOID
1145 NTAPI
1146 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1147 IN PUSBPORT_ENDPOINT Endpoint)
1148 {
1149 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
1150 }
1151
1152 VOID
1153 NTAPI
1154 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
1155 IN PUSB2_TT Tt)
1156 {
1157 ULONG ix;
1158 ULONG jx;
1159
1160 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
1161
1162 Tt->HcExtension = HcExtension;
1163 Tt->DelayTime = 1;
1164 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
1165
1166 for (ix = 0; ix < USB2_FRAMES; ix++)
1167 {
1168 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
1169 Tt->FrameBudget[ix].AltEndpoint = NULL;
1170
1171 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1172 {
1173 Tt->TimeCS[ix][jx] = 0;
1174 Tt->NumStartSplits[ix][jx] = 0;
1175 }
1176
1177 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
1178
1179 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
1180 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
1181 USBPORT_TRANSFER_DIRECTION_OUT,
1182 UsbFullSpeed,
1183 USB2_FRAMES,
1184 0,
1185 Tt);
1186
1187 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
1188 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1189 Tt->IsoEndpoint[ix].StartFrame = ix;
1190 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
1191
1192 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
1193
1194 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
1195 USBPORT_TRANSFER_TYPE_INTERRUPT,
1196 USBPORT_TRANSFER_DIRECTION_OUT,
1197 UsbFullSpeed,
1198 USB2_FRAMES,
1199 0,
1200 Tt);
1201
1202 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
1203 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1204 Tt->IntEndpoint[ix].StartFrame = ix;
1205 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
1206 }
1207 }
1208
1209 VOID
1210 NTAPI
1211 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
1212 {
1213 ULONG ix;
1214 ULONG jx;
1215
1216 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
1217
1218 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
1219
1220 for (ix = 0; ix < USB2_FRAMES; ix++)
1221 {
1222 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1223 {
1224 HcExtension->TimeUsed[ix][jx] = 0;
1225 }
1226 }
1227
1228 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
1229
1230 USB2_InitTT(HcExtension, &HcExtension->HcTt);
1231 }