xref: /reactos/drivers/usb/usbport/usb2.c (revision aad80191)
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 static const UCHAR CMASKS[USB2_MICROFRAMES] = {
14   0x1C, 0x38, 0x70, 0xE0, 0xC1, 0x83, 0x07, 0x0E
15 };
16 
17 BOOLEAN
18 NTAPI
19 USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,
20                    IN ULONG CalcBusTime,
21                    IN ULONG LimitAllocation)
22 {
23     ULONG BusTime;
24     BOOLEAN Result = TRUE;
25 
26     BusTime = *OutTimeUsed + CalcBusTime;
27     *OutTimeUsed += CalcBusTime;
28 
29     if (BusTime > LimitAllocation)
30     {
31         DPRINT("USB2_AllocateCheck: BusTime > LimitAllocation\n");
32         Result = FALSE;
33     }
34 
35     return Result;
36 }
37 
38 USHORT
39 NTAPI
40 USB2_AddDataBitStuff(IN USHORT DataTime)
41 {
42     return (DataTime + (DataTime / 16));
43 }
44 
45 VOID
46 NTAPI
47 USB2_IncMicroFrame(OUT PUCHAR frame,
48                    OUT PUCHAR uframe)
49 {
50     ++*uframe;
51 
52     if (*uframe > (USB2_MICROFRAMES - 1))
53     {
54         *uframe = 0;
55         *frame = (*frame + 1) & (USB2_FRAMES - 1);
56     }
57 }
58 
59 VOID
60 NTAPI
61 USB2_GetPrevMicroFrame(OUT PUCHAR frame,
62                        OUT PUCHAR uframe)
63 {
64     *uframe = USB2_MICROFRAMES - 1;
65 
66     if (*frame)
67         --*frame;
68     else
69         *frame = USB2_FRAMES - 1;
70 }
71 
72 BOOLEAN
73 NTAPI
74 USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
75                            IN PUSB2_TT_ENDPOINT TtEndpoint)
76 {
77     ULONG TransferType;
78 
79     DPRINT("USB2_CheckTtEndpointInsert: nextTtEndpoint - %p, TtEndpoint - %p\n",
80            nextTtEndpoint,
81            TtEndpoint);
82 
83     ASSERT(TtEndpoint);
84 
85     if (TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
86     {
87         DPRINT1("USB2_CheckTtEndpointInsert: Result - FALSE\n");
88         return FALSE;
89     }
90 
91     if (!nextTtEndpoint)
92     {
93         DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
94         return TRUE;
95     }
96 
97     TransferType = TtEndpoint->TtEndpointParams.TransferType;
98 
99     if (nextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod &&
100         TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
101     {
102         DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
103         return TRUE;
104     }
105 
106     if ((nextTtEndpoint->ActualPeriod <= TtEndpoint->ActualPeriod &&
107         TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) ||
108         nextTtEndpoint == TtEndpoint)
109     {
110         DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
111         return TRUE;
112     }
113 
114     DPRINT("USB2_CheckTtEndpointInsert: Result - FALSE\n");
115     return FALSE;
116 }
117 
118 ULONG
119 NTAPI
120 USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
121 {
122     ULONG TransferType;
123     ULONG Direction;
124     ULONG DeviceSpeed;
125     ULONG Overhead;
126     ULONG HostDelay;
127 
128     TransferType = TtEndpoint->TtEndpointParams.TransferType;
129     Direction = TtEndpoint->TtEndpointParams.Direction;
130     DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
131 
132     HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
133 
134     if (DeviceSpeed == UsbHighSpeed)
135     {
136         if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
137         {
138             if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
139                 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
140             else
141                 Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
142         }
143         else
144         {
145             if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
146                 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
147             else
148                 Overhead = HostDelay + USB2_HS_INTERRUPT_IN_OVERHEAD;
149         }
150     }
151     else if (DeviceSpeed == UsbFullSpeed)
152     {
153         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
154             Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
155         else
156             Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
157     }
158     else
159     {
160         Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
161     }
162 
163     return Overhead;
164 }
165 
166 VOID
167 NTAPI
168 USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,
169                    IN PULONG OverheadSS,
170                    IN PULONG OverheadCS)
171 {
172     ULONG TransferType;
173     ULONG Direction;
174     ULONG HostDelay;
175 
176     TransferType = TtEndpoint->TtEndpointParams.TransferType;
177     Direction = TtEndpoint->TtEndpointParams.Direction;
178 
179     HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
180 
181     if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
182     {
183         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
184         {
185             *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD;
186             *OverheadCS = 0;
187         }
188         else
189         {
190             *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_OUT_OVERHEAD;
191             *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_OUT_OVERHEAD;
192         }
193     }
194     else
195     {
196         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
197         {
198             *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD;
199             *OverheadCS = HostDelay + USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD;
200         }
201         else
202         {
203             *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_IN_OVERHEAD;
204             *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_IN_OVERHEAD;
205         }
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 DataSize;
319     ULONG RemainDataTime;
320     ULONG OverheadCS;
321     ULONG OverheadSS;
322     ULONG ix;
323     USHORT PktSize;
324     USHORT PktSizeBitStuff;
325     UCHAR frame;
326     UCHAR uframe;
327     BOOL Result = TRUE;
328 
329     DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, StartFrame - %X\n",
330            TtEndpoint,
331            Frame,
332            TtEndpoint->StartFrame);
333 
334     Tt = TtEndpoint->Tt;
335     HcExtension = Tt->HcExtension;
336 
337     TransferType = TtEndpoint->TtEndpointParams.TransferType;
338     Direction = TtEndpoint->TtEndpointParams.Direction;
339 
340     if (Frame == 0)
341     {
342         TtEndpoint->StartMicroframe =
343         TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1;
344 
345         DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n",
346                TtEndpoint->StartMicroframe);
347     }
348 
349     USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
350 
351     if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
352     {
353         if (Frame == 0)
354         {
355             TtEndpoint->Nums.NumStarts = 1;
356 
357             if ((CHAR)TtEndpoint->StartMicroframe < (USB2_MICROFRAMES - 3))
358                 TtEndpoint->Nums.NumCompletes = 3;
359             else
360                 TtEndpoint->Nums.NumCompletes = 2;
361         }
362     }
363     else
364     {
365         if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
366         {
367             DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
368             ASSERT(FALSE);
369         }
370         else
371         {
372             DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
373             ASSERT(FALSE);
374         }
375     }
376 
377     frame = TtEndpoint->StartFrame + Frame;
378     uframe = TtEndpoint->StartMicroframe;
379 
380     if (TtEndpoint->StartMicroframe == USB2_PREV_MICROFRAME)
381         USB2_GetPrevMicroFrame(&frame, &uframe);
382 
383     for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
384     {
385         if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
386                                 OverheadSS,
387                                 USB2_MAX_MICROFRAME_ALLOCATION))
388         {
389             Result = FALSE;
390         }
391 
392         if (Tt->NumStartSplits[frame][uframe] >
393             (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
394         {
395             DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
396                     Tt->NumStartSplits[frame][uframe] + 1);
397 
398             ASSERT(FALSE);
399             Result = FALSE;
400         }
401 
402         ++Tt->NumStartSplits[frame][uframe];
403         USB2_IncMicroFrame(&frame, &uframe);
404     }
405 
406     frame = TtEndpoint->StartFrame + Frame;
407     uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
408 
409     for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
410     {
411         if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
412                                 OverheadCS,
413                                 USB2_MAX_MICROFRAME_ALLOCATION))
414         {
415             Result = FALSE;
416         }
417 
418         USB2_IncMicroFrame(&frame, &uframe);
419     }
420 
421     PktSize = TtEndpoint->MaxPacketSize;
422     PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
423 
424     if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
425     {
426         frame = TtEndpoint->StartFrame + Frame;
427         uframe = TtEndpoint->StartMicroframe;
428 
429         if (uframe == USB2_PREV_MICROFRAME)
430             USB2_GetPrevMicroFrame(&frame, &uframe);
431 
432         DataTime = 0;
433 
434         for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
435         {
436             DataSize = PktSizeBitStuff - DataTime;
437 
438             if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
439                 DataTime = DataSize;
440             else
441                 DataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
442 
443             DPRINT("USB2_AllocateHS: ix - %X, frame - %X, uframe - %X, TimeUsed - %X\n",
444                    ix,
445                    frame,
446                    uframe,
447                    HcExtension->TimeUsed[frame][uframe]);
448 
449             if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
450                                     DataTime,
451                                     USB2_MAX_MICROFRAME_ALLOCATION))
452             {
453                 Result = FALSE;
454             }
455 
456             USB2_IncMicroFrame(&frame, &uframe);
457             DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
458         }
459     }
460     else
461     {
462         frame = TtEndpoint->StartFrame + Frame;
463         uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
464 
465         for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
466         {
467             if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
468             {
469                 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
470                                  Tt->TimeCS[frame][uframe];
471 
472                 if (RemainDataTime >= PktSizeBitStuff)
473                 {
474                     DataTime = PktSizeBitStuff;
475                 }
476                 else if (RemainDataTime > 0)
477                 {
478                     DataTime = RemainDataTime;
479                 }
480                 else
481                 {
482                     DataTime = 0;
483                 }
484 
485                 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
486                                         DataTime,
487                                         USB2_MAX_MICROFRAME_ALLOCATION))
488                 {
489                     Result = FALSE;
490                 }
491             }
492 
493             if (PktSizeBitStuff < USB2_FS_RAW_BYTES_IN_MICROFRAME)
494                 Tt->TimeCS[frame][uframe] += PktSizeBitStuff;
495             else
496                 Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
497 
498             USB2_IncMicroFrame(&frame, &uframe);
499         }
500     }
501 
502     DPRINT("USB2_AllocateHS: Result - %X\n", Result);
503     return Result;
504 }
505 
506 VOID
507 NTAPI
508 USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
509                   IN ULONG Frame)
510 {
511     PUSB2_TT Tt;
512     PUSB2_HC_EXTENSION HcExtension;
513     ULONG OverheadCS;
514     ULONG OverheadSS;
515     ULONG Direction;
516     ULONG ix;
517     ULONG CurrentDataTime;
518     ULONG RemainDataTime;
519     ULONG DataTime;
520     ULONG DataSize;
521     USHORT PktSize;
522     USHORT PktSizeBitStuff;
523     UCHAR uframe;
524     UCHAR frame;
525 
526     DPRINT("USB2_DeallocateHS: TtEndpoint - %p, Frame - %X\n",
527            TtEndpoint,
528            Frame);
529 
530     Tt = TtEndpoint->Tt;
531     HcExtension = Tt->HcExtension;
532 
533     USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
534 
535     frame = TtEndpoint->StartFrame + Frame;
536     uframe = TtEndpoint->StartMicroframe;
537 
538     if (TtEndpoint->StartMicroframe == USB2_PREV_MICROFRAME)
539         USB2_GetPrevMicroFrame(&frame, &uframe);
540 
541     for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
542     {
543         HcExtension->TimeUsed[frame][uframe] -= OverheadSS;
544         --Tt->NumStartSplits[frame][uframe];
545         USB2_IncMicroFrame(&frame, &uframe);
546     }
547 
548     frame = TtEndpoint->StartFrame + Frame;
549     uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
550 
551     for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
552     {
553         HcExtension->TimeUsed[frame][uframe] -= OverheadCS;
554         USB2_IncMicroFrame(&frame, &uframe);
555     }
556 
557     Direction = TtEndpoint->TtEndpointParams.Direction;
558     PktSize = TtEndpoint->MaxPacketSize;
559     PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
560 
561     if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
562     {
563         frame = TtEndpoint->StartFrame + Frame;
564         uframe = TtEndpoint->StartMicroframe;
565 
566         if (TtEndpoint->StartMicroframe == USB2_PREV_MICROFRAME)
567             USB2_GetPrevMicroFrame(&frame, &uframe);
568 
569         DataTime = 0;
570 
571         for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
572         {
573             DataSize = PktSizeBitStuff - DataTime;
574 
575             if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
576                 CurrentDataTime = PktSizeBitStuff - DataTime;
577             else
578                 CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
579 
580             HcExtension->TimeUsed[frame][uframe] -= CurrentDataTime;
581             USB2_IncMicroFrame(&frame, &uframe);
582             DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
583         }
584     }
585     else
586     {
587         frame = TtEndpoint->StartFrame + Frame;
588         uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
589 
590         for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
591         {
592             if (PktSizeBitStuff >= USB2_FS_RAW_BYTES_IN_MICROFRAME)
593                 CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
594             else
595                 CurrentDataTime = PktSizeBitStuff;
596 
597             Tt->TimeCS[frame][uframe] -= CurrentDataTime;
598 
599             if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
600             {
601                 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
602                                  Tt->TimeCS[frame][uframe];
603 
604                 if (RemainDataTime >= PktSizeBitStuff)
605                     RemainDataTime = PktSizeBitStuff;
606 
607                 HcExtension->TimeUsed[frame][uframe] -= RemainDataTime;
608             }
609 
610             USB2_IncMicroFrame(&frame, &uframe);
611         }
612     }
613 
614     return;
615 }
616 
617 BOOLEAN
618 NTAPI
619 USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
620                     IN USHORT BusTime,
621                     IN PUSB2_REBALANCE Rebalance,
622                     IN ULONG RebalanceListEntries,
623                     OUT BOOLEAN * OutResult)
624 {
625     ULONG EndBusTime;
626     ULONG TransferType;
627     ULONG Num;
628     UCHAR ix;
629 
630     DPRINT("USB2_MoveTtEndpoint: TtEndpoint - %p, BusTime - %X\n",
631            TtEndpoint,
632            BusTime);
633 
634     *OutResult = TRUE;
635 
636     for (Num = 0; Rebalance->RebalanceEndpoint[Num]; Num++)
637     {
638         if (Rebalance->RebalanceEndpoint[Num] == TtEndpoint)
639             break;
640     }
641 
642     DPRINT("USB2_MoveTtEndpoint: Num - %X\n", Num);
643 
644     TransferType = TtEndpoint->TtEndpointParams.TransferType;
645 
646     if (Rebalance->RebalanceEndpoint[Num] &&
647         TtEndpoint->TtEndpointParams.EndpointMoved == TRUE &&
648         ((TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT) || BusTime >= 0))
649     {
650         DPRINT("USB2_MoveTtEndpoint: result - FALSE\n");
651         return FALSE;
652     }
653 
654     for (ix = 0;
655          (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
656          ix += TtEndpoint->ActualPeriod)
657     {
658         USB2_DeallocateHS(TtEndpoint, ix);
659     }
660 
661     TtEndpoint->StartTime += BusTime;
662 
663     EndBusTime = TtEndpoint->StartTime + TtEndpoint->CalcBusTime;
664 
665     if (EndBusTime > USB2_FS_MAX_PERIODIC_ALLOCATION)
666     {
667         DPRINT("USB2_MoveTtEndpoint: EndBusTime is too large!\n");
668         *OutResult = FALSE;
669     }
670 
671     TtEndpoint->TtEndpointParams.EndpointMoved = TRUE;
672 
673     if (Rebalance->RebalanceEndpoint[Num] == NULL)
674     {
675         if (Num >= RebalanceListEntries)
676         {
677             DPRINT("USB2_MoveTtEndpoint: Too many changes!\n");
678             *OutResult = FALSE;
679         }
680         else
681         {
682             Rebalance->RebalanceEndpoint[Num] = TtEndpoint;
683             Rebalance->RebalanceEndpoint[Num + 1] = NULL;
684         }
685     }
686 
687     for (ix = 0;
688          (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
689          ix += TtEndpoint->ActualPeriod)
690     {
691         if (!USB2_AllocateHS(TtEndpoint, ix))
692         {
693             DPRINT("USB2_MoveTtEndpoint: OutResult - FALSE\n");
694             OutResult = FALSE;
695         }
696     }
697 
698     DPRINT("USB2_MoveTtEndpoint: result - TRUE\n");
699     return TRUE;
700 }
701 
702 BOOLEAN
703 NTAPI
704 USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,
705                   IN PUSB2_TT_ENDPOINT TtEndpoint)
706 {
707     UCHAR Frame;
708 
709     DPRINT("USB2_CommonFrames: \n");
710 
711     if (NextTtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms ||
712         TtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms)
713     {
714         return TRUE;
715     }
716 
717     if (NextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod)
718         Frame = TtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
719     else
720         Frame = NextTtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
721 
722     return (Frame == TtEndpoint->StartFrame);
723 }
724 
725 VOID
726 NTAPI
727 USB2_ConvertFrame(IN UCHAR Frame,
728                   IN UCHAR Microframe,
729                   OUT PUCHAR HcFrame,
730                   OUT PUCHAR HcMicroframe)
731 {
732     DPRINT("USB2_ConvertFrame: Frame - %x, Microframe - %x\n",
733            Frame,
734            Microframe);
735 
736     if (Microframe == USB2_PREV_MICROFRAME)
737     {
738         *HcFrame = Frame;
739         *HcMicroframe = 0;
740     }
741 
742     if (Microframe >= 0 &&
743         Microframe <= (USB2_MICROFRAMES - 2))
744     {
745         *HcFrame = Frame;
746         *HcMicroframe = Microframe + 1;
747     }
748 
749     if (Microframe == (USB2_MICROFRAMES - 1))
750     {
751         *HcFrame = Frame + 1;
752         *HcMicroframe = 0;
753     }
754 }
755 
756 UCHAR
757 NTAPI
758 USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
759 {
760     ULONG ix;
761     UCHAR SMask = 0;
762     UCHAR HcFrame;
763     UCHAR HcMicroFrame;
764 
765     if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
766     {
767         SMask = (1 << TtEndpoint->StartMicroframe);
768     }
769     else
770     {
771         USB2_ConvertFrame(TtEndpoint->StartFrame,
772                           TtEndpoint->StartMicroframe,
773                           &HcFrame,
774                           &HcMicroFrame);
775 
776         for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
777         {
778             SMask |= (1 << HcMicroFrame);
779             HcMicroFrame++;
780         }
781     }
782 
783     return SMask;
784 }
785 
786 UCHAR
787 NTAPI
788 USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
789 {
790     ULONG NumCompletes;
791     ULONG TransferType;
792     ULONG DeviceSpeed;
793     ULONG Direction;
794     UCHAR Result;
795     UCHAR MicroFrameCS;
796     UCHAR HcFrame;
797     UCHAR HcMicroFrame;
798     UCHAR MaskCS = 0;
799 
800     TransferType = TtEndpoint->TtEndpointParams.TransferType;
801     DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
802     Direction = TtEndpoint->TtEndpointParams.Direction;
803 
804     if (DeviceSpeed == UsbHighSpeed)
805         return 0;
806 
807     if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
808     {
809         USB2_ConvertFrame(TtEndpoint->StartFrame,
810                           TtEndpoint->StartMicroframe,
811                           &HcFrame,
812                           &HcMicroFrame);
813 
814         Result = CMASKS[HcMicroFrame];
815     }
816     else
817     {
818         if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
819             return 0;
820 
821         USB2_ConvertFrame(TtEndpoint->StartFrame,
822                           TtEndpoint->StartMicroframe,
823                           &HcFrame,
824                           &HcMicroFrame);
825 
826         NumCompletes = TtEndpoint->Nums.NumCompletes;
827 
828         for (MicroFrameCS = HcMicroFrame + 2;
829              MicroFrameCS < USB2_MICROFRAMES;
830              MicroFrameCS++)
831         {
832             MaskCS |= (1 << MicroFrameCS);
833             NumCompletes--;
834 
835             if (!NumCompletes)
836                 return MaskCS;
837         }
838 
839         for (; NumCompletes; NumCompletes--)
840         {
841             MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES));
842         }
843 
844         Result = MaskCS;
845     }
846 
847     return Result;
848 }
849 
850 VOID
851 NTAPI
852 USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
853                        IN PLIST_ENTRY List)
854 {
855     PUSBPORT_DEVICE_EXTENSION FdoExtension;
856     PUSBPORT_REGISTRATION_PACKET Packet;
857     PUSBPORT_ENDPOINT Endpoint;
858     PLIST_ENTRY Entry;
859     ULONG AllocedBusTime;
860     ULONG EndpointBandwidth;
861     ULONG Factor;
862     ULONG ScheduleOffset;
863     ULONG Bandwidth;
864     ULONG n;
865     ULONG ix;
866     KIRQL OldIrql;
867     UCHAR NewPeriod;
868     UCHAR SMask;
869     UCHAR CMask;
870 
871     FdoExtension = FdoDevice->DeviceExtension;
872     Packet = &FdoExtension->MiniPortInterface->Packet;
873 
874     while (!IsListEmpty(List))
875     {
876         Entry = RemoveHeadList(List);
877 
878         Endpoint = CONTAINING_RECORD(Entry,
879                                      USBPORT_ENDPOINT,
880                                      RebalanceLink.Flink);
881 
882         DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
883 
884         Endpoint->RebalanceLink.Flink = NULL;
885         Endpoint->RebalanceLink.Blink = NULL;
886 
887         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
888                           &Endpoint->EndpointOldIrql);
889 
890         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
891         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
892 
893         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
894         NewPeriod = Endpoint->TtEndpoint->ActualPeriod;
895 
896         AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime;
897         EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
898 
899         Endpoint->EndpointProperties.InterruptScheduleMask = SMask;
900         Endpoint->EndpointProperties.SplitCompletionMask = CMask;
901 
902         if (Endpoint->EndpointProperties.Period != NewPeriod)
903         {
904             ASSERT(Endpoint->EndpointProperties.Period);
905             Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
906 
907             for (ix = 0; ix < Factor; ix++)
908             {
909                 Bandwidth = Endpoint->EndpointProperties.UsbBandwidth;
910                 n = Factor * Endpoint->EndpointProperties.ScheduleOffset;
911                 Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth;
912             }
913 
914             Endpoint->EndpointProperties.Period = NewPeriod;
915             Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset;
916             Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth;
917 
918             ASSERT(NewPeriod);
919             Factor = USB2_FRAMES / NewPeriod;
920 
921             for (ix = 0; ix < Factor; ix++)
922             {
923                 n = Factor * ScheduleOffset;
924                 Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
925             }
926         }
927 
928         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
929 
930         Packet->RebalanceEndpoint(FdoExtension->MiniPortExt,
931                                   &Endpoint->EndpointProperties,
932                                   (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT)));
933 
934         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
935 
936         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
937                           Endpoint->EndpointOldIrql);
938     }
939 }
940 
941 VOID
942 NTAPI
943 USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,
944                IN PLIST_ENTRY RebalanceList)
945 {
946     PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
947     PUSBPORT_ENDPOINT Endpoint;
948     PLIST_ENTRY Entry;
949     LIST_ENTRY BalanceListInt1;
950     LIST_ENTRY BalanceListInt2;
951     ULONG TransferType;
952     ULONG ScheduleOffset;
953     UCHAR SMask;
954     UCHAR CMask;
955     UCHAR ActualPeriod;
956 
957     DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n",
958            FdoDevice,
959            RebalanceList);
960 
961     InitializeListHead(&BalanceListInt1);
962     InitializeListHead(&BalanceListInt2);
963 
964     while (!IsListEmpty(RebalanceList))
965     {
966         Entry = RebalanceList->Flink;
967 
968         Endpoint = CONTAINING_RECORD(Entry,
969                                      USBPORT_ENDPOINT,
970                                      RebalanceLink.Flink);
971 
972         DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n",
973                Entry,
974                Endpoint);
975 
976         RemoveHeadList(RebalanceList);
977         Entry->Flink = NULL;
978         Entry->Blink = NULL;
979 
980         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
981         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
982 
983         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
984         ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
985 
986         EndpointProperties = &Endpoint->EndpointProperties;
987         TransferType = EndpointProperties->TransferType;
988 
989         switch (TransferType)
990         {
991             case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
992                 DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
993                 ASSERT(FALSE);
994                 break;
995 
996             case USBPORT_TRANSFER_TYPE_INTERRUPT:
997                 if (SMask != EndpointProperties->InterruptScheduleMask ||
998                     CMask != EndpointProperties->SplitCompletionMask ||
999                     ScheduleOffset != EndpointProperties->ScheduleOffset ||
1000                     ActualPeriod != EndpointProperties->Period)
1001                 {
1002                     if (ActualPeriod == EndpointProperties->Period &&
1003                         ScheduleOffset == EndpointProperties->ScheduleOffset)
1004                     {
1005                         InsertTailList(&BalanceListInt1, Entry);
1006                     }
1007                     else
1008                     {
1009                         InsertTailList(&BalanceListInt2, Entry);
1010                     }
1011                 }
1012                 break;
1013 
1014             default:
1015                 ASSERT(FALSE);
1016                 break;
1017         }
1018     }
1019 
1020     USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2);
1021     USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1);
1022     //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso);
1023 }
1024 
1025 BOOLEAN
1026 NTAPI
1027 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
1028                               IN PUSB2_REBALANCE Rebalance,
1029                               IN PULONG RebalanceListEntries,
1030                               IN ULONG MaxFrames)
1031 {
1032     PUSB2_TT Tt;
1033     PUSB2_HC_EXTENSION HcExtension;
1034     ULONG Speed;
1035     ULONG TransferType;
1036     ULONG Frame;
1037     ULONG StartMicroframe;
1038     ULONG ix;
1039     PUSB2_TT_ENDPOINT endpoint;
1040     PUSB2_TT_ENDPOINT nextEndpoint;
1041     PUSB2_TT_ENDPOINT lastEndpoint;
1042     PUSB2_TT_ENDPOINT tmpEndpoint;
1043     ULONG endTime;
1044     ULONG maxEndTime;
1045     ULONG lastEndTime;
1046     ULONG Factor;
1047     ULONG jx;
1048     UCHAR frame;
1049     UCHAR uframe;
1050     USHORT Period;
1051     BOOLEAN IsMoved = FALSE;
1052 
1053     DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
1054            TtEndpoint,
1055            MaxFrames,
1056            TtEndpoint->CalcBusTime);
1057 
1058     if (TtEndpoint->CalcBusTime == 0)
1059     {
1060         DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
1061         return FALSE;
1062     }
1063 
1064     Tt = TtEndpoint->Tt;
1065     HcExtension = Tt->HcExtension;
1066 
1067     Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1068     DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
1069 
1070     StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1071                       TtEndpoint->StartMicroframe;
1072 
1073     if (Speed == UsbHighSpeed)
1074     {
1075         for (ix = StartMicroframe;
1076              ix < USB2_MAX_MICROFRAMES;
1077              ix += TtEndpoint->ActualPeriod)
1078         {
1079             frame = ix / USB2_MICROFRAMES;
1080             uframe = ix % (USB2_MICROFRAMES - 1);
1081 
1082             HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1083         }
1084 
1085         TtEndpoint->CalcBusTime = 0;
1086 
1087         DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1088         return TRUE;
1089     }
1090 
1091     /* Speed != UsbHighSpeed (FS/LS) */
1092 
1093     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1094 
1095     for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
1096          ix > 0;
1097          ix--, Frame--)
1098     {
1099         frame = TtEndpoint->StartFrame + Frame;
1100 
1101         DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
1102                frame,
1103                Frame,
1104                TtEndpoint->StartFrame);
1105 
1106         if ((Frame % TtEndpoint->ActualPeriod) == 0)
1107         {
1108             USB2_DeallocateHS(TtEndpoint, Frame);
1109             Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
1110         }
1111 
1112         if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1113             endpoint = Tt->FrameBudget[frame].IntEndpoint;
1114         else
1115             endpoint = Tt->FrameBudget[frame].IsoEndpoint;
1116 
1117         nextEndpoint = endpoint->NextTtEndpoint;
1118 
1119         DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
1120                TtEndpoint,
1121                nextEndpoint);
1122 
1123         if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1124         {
1125             while (nextEndpoint)
1126             {
1127                 endpoint = nextEndpoint;
1128                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1129             }
1130 
1131             nextEndpoint = TtEndpoint;
1132 
1133             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1134                    endpoint,
1135                    nextEndpoint);
1136         }
1137         else
1138         {
1139             while (nextEndpoint &&
1140                    !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1141             {
1142                 endpoint = nextEndpoint;
1143                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1144             }
1145 
1146             if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
1147                 nextEndpoint)
1148             {
1149                 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1150                 ASSERT(FALSE);
1151             }
1152 
1153             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1154                    endpoint,
1155                    nextEndpoint);
1156         }
1157 
1158         if ((Frame % TtEndpoint->ActualPeriod) == 0)
1159         {
1160             if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1161             {
1162                 Tt->FrameBudget[frame].AltEndpoint = NULL;
1163             }
1164             else if (nextEndpoint)
1165             {
1166                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1167                 endpoint->NextTtEndpoint = nextEndpoint;
1168 
1169                 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1170                        endpoint,
1171                        nextEndpoint);
1172             }
1173         }
1174 
1175         if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1176         {
1177             if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
1178             {
1179                 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1180                 {
1181                     endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1182                 }
1183                 else if (Tt->FrameBudget[frame].AltEndpoint)
1184                 {
1185                     endpoint = Tt->FrameBudget[frame].AltEndpoint;
1186                 }
1187             }
1188         }
1189         else
1190         {
1191             DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1192             ASSERT(FALSE);
1193         }
1194 
1195         Period = TtEndpoint->ActualPeriod;
1196 
1197         for (;
1198              nextEndpoint;
1199              endpoint = nextEndpoint,
1200              nextEndpoint = nextEndpoint->NextTtEndpoint)
1201         {
1202             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1203                    endpoint,
1204                    nextEndpoint);
1205 
1206             endTime = endpoint->StartTime + endpoint->CalcBusTime;
1207             maxEndTime = endTime;
1208 
1209             if (Period > nextEndpoint->ActualPeriod ||
1210                 TtEndpoint->StartFrame != nextEndpoint->StartFrame)
1211             {
1212                 if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
1213                     Factor = Period / nextEndpoint->ActualPeriod;
1214                 else
1215                     Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
1216 
1217                 maxEndTime = endTime;
1218 
1219                 for (jx = 0, frame = nextEndpoint->StartFrame;
1220                      jx < Factor;
1221                      jx++, frame += nextEndpoint->ActualPeriod)
1222                 {
1223                     if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
1224                     {
1225                         lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1226 
1227                         if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1228                         {
1229                             lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1230                         }
1231                         else if (Tt->FrameBudget[frame].AltEndpoint)
1232                         {
1233                             lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
1234                         }
1235 
1236                         for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
1237                              tmpEndpoint && tmpEndpoint != nextEndpoint;
1238                              tmpEndpoint = tmpEndpoint->NextTtEndpoint)
1239                         {
1240                             lastEndpoint = tmpEndpoint;
1241                         }
1242 
1243                         lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
1244 
1245                         if (endTime < (lastEndTime - 1))
1246                         {
1247                             maxEndTime = lastEndTime;
1248                             endTime = maxEndTime;
1249 
1250                             if (nextEndpoint->StartTime == maxEndTime)
1251                                 break;
1252                         }
1253                         else
1254                         {
1255                             maxEndTime = endTime;
1256                         }
1257                     }
1258                 }
1259             }
1260 
1261             if (maxEndTime >= nextEndpoint->StartTime)
1262                 break;
1263 
1264             if (!USB2_MoveTtEndpoint(nextEndpoint,
1265                                      maxEndTime - nextEndpoint->StartTime,
1266                                      Rebalance,
1267                                      *RebalanceListEntries,
1268                                      &IsMoved))
1269             {
1270                 if (!IsMoved)
1271                 {
1272                     DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
1273                 }
1274 
1275                 break;
1276             }
1277 
1278             if (Period > nextEndpoint->ActualPeriod)
1279                 Period = nextEndpoint->ActualPeriod;
1280         }
1281     }
1282 
1283     TtEndpoint->CalcBusTime = 0;
1284 
1285     DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1286     return TRUE;
1287 }
1288 
1289 BOOLEAN
1290 NTAPI
1291 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
1292                              IN PUSB2_REBALANCE Rebalance,
1293                              IN PULONG RebalanceListEntries)
1294 {
1295     PUSB2_TT Tt;
1296     PUSB2_HC_EXTENSION HcExtension;
1297     ULONG Speed;
1298     ULONG TimeUsed;
1299     ULONG MinTimeUsed;
1300     ULONG ix;
1301     ULONG frame;
1302     ULONG uframe;
1303     ULONG Microframe;
1304     ULONG TransferType;
1305     ULONG Overhead;
1306     ULONG LatestStart;
1307     PUSB2_TT_ENDPOINT prevEndpoint;
1308     PUSB2_TT_ENDPOINT nextEndpoint;
1309     PUSB2_TT_ENDPOINT IntEndpoint;
1310     ULONG StartTime;
1311     ULONG calcBusTime;
1312     BOOLEAN Result = TRUE;
1313 
1314     DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
1315 
1316     Tt = TtEndpoint->Tt;
1317     HcExtension = Tt->HcExtension;
1318 
1319     TtEndpoint->Nums.NumStarts = 0;
1320     TtEndpoint->Nums.NumCompletes = 0;
1321 
1322     TtEndpoint->StartFrame = 0;
1323     TtEndpoint->StartMicroframe = 0;
1324 
1325     if (TtEndpoint->CalcBusTime)
1326     {
1327         DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
1328         return FALSE;
1329     }
1330 
1331     Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1332 
1333     if (Speed == UsbHighSpeed)
1334     {
1335         if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
1336             TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
1337         else
1338             TtEndpoint->ActualPeriod = TtEndpoint->Period;
1339 
1340         MinTimeUsed = HcExtension->TimeUsed[0][0];
1341 
1342         for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1343         {
1344             frame = ix / USB2_MICROFRAMES;
1345             uframe = ix % (USB2_MICROFRAMES - 1);
1346 
1347             TimeUsed = HcExtension->TimeUsed[frame][uframe];
1348 
1349             if (TimeUsed < MinTimeUsed)
1350             {
1351                 MinTimeUsed = TimeUsed;
1352                 TtEndpoint->StartFrame = frame;
1353                 TtEndpoint->StartMicroframe = uframe;
1354             }
1355         }
1356 
1357         TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1358                                   USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1359 
1360         DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1361                TtEndpoint->StartFrame,
1362                TtEndpoint->StartMicroframe,
1363                TtEndpoint->CalcBusTime);
1364 
1365         Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1366                      TtEndpoint->StartMicroframe;
1367 
1368         if (Microframe >= USB2_MAX_MICROFRAMES)
1369         {
1370             DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1371             return TRUE;
1372         }
1373 
1374         for (ix = Microframe;
1375              ix < USB2_MAX_MICROFRAMES;
1376              ix += TtEndpoint->ActualPeriod)
1377         {
1378             frame = ix / USB2_MICROFRAMES;
1379             uframe = ix % (USB2_MICROFRAMES - 1);
1380 
1381             DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1382                    frame,
1383                    uframe,
1384                    HcExtension->TimeUsed[frame][uframe]);
1385 
1386             if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1387                                     TtEndpoint->CalcBusTime,
1388                                     USB2_MAX_MICROFRAME_ALLOCATION))
1389             {
1390                 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1391                 Result = FALSE;
1392             }
1393         }
1394 
1395         if (!Result)
1396         {
1397             for (ix = Microframe;
1398                  ix < USB2_MAX_MICROFRAMES;
1399                  ix += TtEndpoint->ActualPeriod)
1400             {
1401                 frame = ix / USB2_MICROFRAMES;
1402                 uframe = ix % (USB2_MICROFRAMES - 1);
1403 
1404                 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1405             }
1406         }
1407 
1408         DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1409         return TRUE;
1410     }
1411 
1412     /* Speed != UsbHighSpeed (FS/LS) */
1413 
1414     if (TtEndpoint->Period > USB2_FRAMES)
1415         TtEndpoint->ActualPeriod = USB2_FRAMES;
1416     else
1417         TtEndpoint->ActualPeriod = TtEndpoint->Period;
1418 
1419     MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1420 
1421     for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1422     {
1423         if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1424         {
1425             MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1426             TtEndpoint->StartFrame = ix;
1427         }
1428     }
1429 
1430     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1431 
1432     if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1433     {
1434         if (Speed == UsbFullSpeed)
1435         {
1436             Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1437         }
1438         else
1439         {
1440             DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1441             return FALSE;
1442         }
1443     }
1444     else
1445     {
1446         if (Speed == UsbFullSpeed)
1447             Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1448         else
1449             Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1450     }
1451 
1452     if (Speed == UsbLowSpeed)
1453         TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1454     else
1455         TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1456 
1457     LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1458 
1459     for (ix = 0;
1460          (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1461          ix += TtEndpoint->ActualPeriod)
1462     {
1463         frame = TtEndpoint->StartFrame + ix;
1464 
1465         if (Tt->FrameBudget[frame].AltEndpoint &&
1466             TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1467         {
1468             DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1469             return FALSE;
1470         }
1471 
1472         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1473             prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1474         else
1475             prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1476 
1477         for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1478              nextEndpoint;
1479              nextEndpoint = nextEndpoint->NextTtEndpoint)
1480         {
1481             if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1482                 break;
1483 
1484             prevEndpoint = nextEndpoint;
1485         }
1486 
1487         StartTime = USB2_GetStartTime(nextEndpoint,
1488                                       TtEndpoint,
1489                                       prevEndpoint,
1490                                       frame);
1491 
1492         LatestStart = max(LatestStart, StartTime);
1493     }
1494 
1495     TtEndpoint->StartTime = LatestStart;
1496 
1497     if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1498     {
1499         TtEndpoint->CalcBusTime = 0;
1500         DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1501         return FALSE;
1502     }
1503 
1504     for (ix = 0, frame = -TtEndpoint->StartFrame;
1505          ix < USB2_FRAMES;
1506          ix++, frame++)
1507     {
1508         DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1509                ix,
1510                frame,
1511                TtEndpoint->StartFrame);
1512 
1513         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1514         {
1515             DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1516             ASSERT(FALSE);
1517         }
1518         else
1519         {
1520             IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1521             nextEndpoint = IntEndpoint->NextTtEndpoint;
1522 
1523             for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1524                  nextEndpoint;
1525                  nextEndpoint = nextEndpoint->NextTtEndpoint)
1526             {
1527                 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1528                     break;
1529                 IntEndpoint = nextEndpoint;
1530             }
1531 
1532             if ((frame % TtEndpoint->ActualPeriod) == 0)
1533             {
1534                 calcBusTime = 0;
1535             }
1536             else
1537             {
1538                 if (nextEndpoint)
1539                 {
1540                     calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1541                                   nextEndpoint->StartTime;
1542                 }
1543                 else
1544                 {
1545                     calcBusTime = TtEndpoint->CalcBusTime;
1546                 }
1547 
1548                 if (calcBusTime > 0)
1549                 {
1550                     TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1551 
1552                     if (!USB2_AllocateCheck(&TimeUsed,
1553                                             calcBusTime,
1554                                             USB2_FS_MAX_PERIODIC_ALLOCATION))
1555                     {
1556                         DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1557                         Result = FALSE;
1558                     }
1559                 }
1560             }
1561 
1562             if (nextEndpoint != TtEndpoint)
1563             {
1564                 if ((frame % TtEndpoint->ActualPeriod) == 0)
1565                 {
1566                     if (frame == 0)
1567                     {
1568                         DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1569                         TtEndpoint->NextTtEndpoint = nextEndpoint;
1570                     }
1571 
1572                     IntEndpoint->NextTtEndpoint = TtEndpoint;
1573 
1574                     DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1575                            TtEndpoint,
1576                            nextEndpoint);
1577                 }
1578 
1579                 if (calcBusTime > 0)
1580                 {
1581                     BOOLEAN IsMoved;
1582                     BOOLEAN MoveResult;
1583 
1584                     DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1585                            nextEndpoint,
1586                            calcBusTime);
1587 
1588                     for (;
1589                          nextEndpoint;
1590                          nextEndpoint = nextEndpoint->NextTtEndpoint)
1591                     {
1592                         MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1593                                                          calcBusTime,
1594                                                          Rebalance,
1595                                                          *RebalanceListEntries,
1596                                                          &IsMoved);
1597 
1598                         if (!IsMoved)
1599                         {
1600                             DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1601                             Result = FALSE;
1602                         }
1603 
1604                         if (!MoveResult)
1605                             break;
1606                     }
1607                 }
1608             }
1609         }
1610 
1611         if ((frame % TtEndpoint->ActualPeriod) == 0)
1612         {
1613             if (!USB2_AllocateHS(TtEndpoint, frame))
1614             {
1615                 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1616                 Result = FALSE;
1617             }
1618 
1619             Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1620         }
1621 
1622         if (Result == FALSE)
1623         {
1624             USB2_DeallocateEndpointBudget(TtEndpoint,
1625                                           Rebalance,
1626                                           RebalanceListEntries,
1627                                           ix + 1);
1628 
1629             DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1630             return FALSE;
1631         }
1632     }
1633 
1634     DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1635     return Result;
1636 }
1637 
1638 BOOLEAN
1639 NTAPI
1640 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
1641                   IN PUSB2_REBALANCE Rebalance,
1642                   IN PULONG RebalanceListEntries)
1643 {
1644     BOOLEAN Result;
1645 
1646     DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
1647            *RebalanceListEntries);
1648 
1649     USB2_DeallocateEndpointBudget(TtEndpoint,
1650                                   Rebalance,
1651                                   RebalanceListEntries,
1652                                   USB2_FRAMES);
1653 
1654     TtEndpoint->PreviosPeriod = TtEndpoint->Period;
1655     TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1656 
1657     Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1658                                           Rebalance,
1659                                           RebalanceListEntries);
1660 
1661     return Result;
1662 }
1663 
1664 BOOLEAN
1665 NTAPI
1666 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1667                     IN PUSB2_REBALANCE Rebalance,
1668                     IN PULONG RebalanceListEntries)
1669 {
1670     PUSB2_TT_ENDPOINT ttEndpoint;
1671     ULONG TransferType;
1672     ULONG ix;
1673 
1674     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1675 
1676     if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1677         TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1678         (CHAR)TtEndpoint->StartMicroframe > 2 &&
1679         !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
1680     {
1681         DPRINT("USB2_PromotePeriods: return FALSE\n");
1682         return FALSE;
1683     }
1684 
1685     if (Rebalance->RebalanceEndpoint[0] == NULL)
1686     {
1687         DPRINT("USB2_PromotePeriods: return TRUE\n");
1688         return TRUE;
1689     }
1690 
1691     DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
1692            *RebalanceListEntries);
1693 
1694     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1695     {
1696         Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
1697     }
1698 
1699     for (ix = 0; ; ix++)
1700     {
1701         ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1702         TransferType = ttEndpoint->TtEndpointParams.TransferType;
1703 
1704         if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1705             TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1706             (CHAR)ttEndpoint->StartMicroframe > 2)
1707         {
1708             USB2_DeallocateEndpointBudget(ttEndpoint,
1709                                           Rebalance,
1710                                           RebalanceListEntries,
1711                                           USB2_FRAMES);
1712 
1713             ttEndpoint->IsPromoted = TRUE;
1714             ttEndpoint->PreviosPeriod = ttEndpoint->Period;
1715             ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1716 
1717             if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
1718                                               Rebalance,
1719                                               RebalanceListEntries))
1720             {
1721                 break;
1722             }
1723         }
1724 
1725         if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
1726         {
1727             DPRINT("USB2_PromotePeriods: return TRUE\n");
1728             return TRUE;
1729         }
1730     }
1731 
1732     USB2_DeallocateEndpointBudget(TtEndpoint,
1733                                   Rebalance,
1734                                   RebalanceListEntries,
1735                                   USB2_FRAMES);
1736 
1737     TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1738     TtEndpoint->PreviosPeriod = 0;
1739 
1740     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1741     {
1742         ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1743 
1744         if (ttEndpoint->IsPromoted)
1745         {
1746             if (ttEndpoint->CalcBusTime)
1747             {
1748                 USB2_DeallocateEndpointBudget(ttEndpoint,
1749                                               Rebalance,
1750                                               RebalanceListEntries,
1751                                               USB2_FRAMES);
1752             }
1753 
1754             TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1755             TtEndpoint->PreviosPeriod = 0;
1756 
1757             USB2_AllocateTimeForEndpoint(ttEndpoint,
1758                                          Rebalance,
1759                                          RebalanceListEntries);
1760         }
1761     }
1762 
1763     DPRINT("USB2_PromotePeriods: return FALSE\n");
1764     return FALSE;
1765 }
1766 
1767 VOID
1768 NTAPI
1769 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1770 {
1771     ULONG BusBandwidth;
1772     ULONG NewBusBandwidth;
1773     ULONG MaxBusBandwidth = 0;
1774     ULONG MinBusBandwidth;
1775     ULONG ix;
1776 
1777     DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1778 
1779     BusBandwidth = TtExtension->BusBandwidth;
1780     MinBusBandwidth = BusBandwidth;
1781 
1782     for (ix = 0; ix < USB2_FRAMES; ix++)
1783     {
1784         NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1785 
1786         MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
1787         MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
1788     }
1789 
1790     TtExtension->MaxBandwidth = MaxBusBandwidth;
1791 
1792     if (MinBusBandwidth == BusBandwidth)
1793         TtExtension->MinBandwidth = 0;
1794     else
1795         TtExtension->MinBandwidth = MinBusBandwidth;
1796 }
1797 
1798 BOOLEAN
1799 NTAPI
1800 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1801                               IN PUSBPORT_ENDPOINT Endpoint)
1802 {
1803     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1804     PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1805     PUSB2_TT_EXTENSION TtExtension;
1806     ULONG TransferType;
1807     PUSB2_REBALANCE Rebalance;
1808     LIST_ENTRY RebalanceList;
1809     ULONG RebalanceListEntries;
1810     PUSB2_TT_ENDPOINT TtEndpoint;
1811     PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1812     PUSB2_TT Tt;
1813     USB_DEVICE_SPEED DeviceSpeed;
1814     ULONG Period;
1815     ULONG AllocedBusTime;
1816     ULONG EndpointBandwidth;
1817     ULONG ScheduleOffset;
1818     ULONG Factor;
1819     ULONG ix;
1820     ULONG n;
1821     BOOLEAN Direction;
1822     UCHAR SMask;
1823     UCHAR CMask;
1824     UCHAR ActualPeriod;
1825     BOOLEAN Result;
1826 
1827     DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1828            FdoDevice,
1829            Endpoint);
1830 
1831     EndpointProperties = &Endpoint->EndpointProperties;
1832     EndpointProperties->ScheduleOffset = 0;
1833 
1834     if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1835     {
1836         DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1837         return TRUE;
1838     }
1839 
1840     FdoExtension = FdoDevice->DeviceExtension;
1841 
1842     TransferType = EndpointProperties->TransferType;
1843     DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1844 
1845     if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1846         TransferType == USBPORT_TRANSFER_TYPE_BULK)
1847     {
1848         return TRUE;
1849     }
1850 
1851     if (Endpoint->TtExtension)
1852         TtExtension = Endpoint->TtExtension;
1853     else
1854         TtExtension = NULL;
1855 
1856     InitializeListHead(&RebalanceList);
1857 
1858     Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1859                                       sizeof(USB2_REBALANCE),
1860                                       USB_PORT_TAG);
1861 
1862     DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1863            Rebalance,
1864            TtExtension);
1865 
1866     if (Rebalance)
1867     {
1868         RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1869 
1870         TtEndpoint = Endpoint->TtEndpoint;
1871         TtEndpoint->Endpoint = Endpoint;
1872 
1873         Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1874         DeviceSpeed = EndpointProperties->DeviceSpeed;
1875 
1876         switch (DeviceSpeed)
1877         {
1878             case UsbLowSpeed:
1879             case UsbFullSpeed:
1880             {
1881                 Tt = &TtExtension->Tt;
1882                 Period = USB2_FRAMES;
1883 
1884                 while (Period > 0 && Period > EndpointProperties->Period)
1885                 {
1886                     Period >>= 1;
1887                 }
1888 
1889                 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1890                 break;
1891             }
1892 
1893             case UsbHighSpeed:
1894             {
1895                 Tt = &FdoExtension->Usb2Extension->HcTt;
1896 
1897                 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1898                     Period = USB2_MAX_MICROFRAMES;
1899                 else
1900                     Period = EndpointProperties->Period;
1901 
1902                 break;
1903             }
1904 
1905             default:
1906             {
1907                 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1908                         DeviceSpeed);
1909 
1910                 DbgBreakPoint();
1911 
1912                 Tt = &TtExtension->Tt;
1913                 break;
1914             }
1915         }
1916 
1917         USB2_InitTtEndpoint(TtEndpoint,
1918                             TransferType,
1919                             Direction,
1920                             DeviceSpeed,
1921                             Period,
1922                             EndpointProperties->MaxPacketSize,
1923                             Tt);
1924 
1925         RebalanceListEntries = USB2_FRAMES - 2;
1926 
1927         Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1928                                               Rebalance,
1929                                               &RebalanceListEntries);
1930 
1931         if (Result)
1932         {
1933             Result = USB2_PromotePeriods(TtEndpoint,
1934                                          Rebalance,
1935                                          &RebalanceListEntries);
1936         }
1937 
1938         RebalanceListEntries = 0;
1939 
1940         for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1941         {
1942             RebalanceListEntries = ix + 1;
1943         }
1944     }
1945     else
1946     {
1947         RebalanceListEntries = 0;
1948         Result = FALSE;
1949     }
1950 
1951     DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1952            RebalanceListEntries,
1953            Result);
1954 
1955     for (ix = 0; ix < RebalanceListEntries; ix++)
1956     {
1957         RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1958 
1959         DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1960                ix,
1961                RebalanceTtEndpoint,
1962                &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1963 
1964         InsertTailList(&RebalanceList,
1965                        &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1966     }
1967 
1968     if (Rebalance)
1969         ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1970 
1971     if (Result)
1972     {
1973         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1974         EndpointProperties->InterruptScheduleMask = SMask;
1975 
1976         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1977         EndpointProperties->SplitCompletionMask = CMask;
1978 
1979         AllocedBusTime = TtEndpoint->CalcBusTime;
1980 
1981         EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1982         EndpointProperties->UsbBandwidth = EndpointBandwidth;
1983 
1984         ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1985         EndpointProperties->Period = ActualPeriod;
1986 
1987         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1988         EndpointProperties->ScheduleOffset = ScheduleOffset;
1989 
1990         ASSERT(ActualPeriod);
1991         Factor = USB2_FRAMES / ActualPeriod;
1992         n = ScheduleOffset * Factor;
1993 
1994         if (TtExtension)
1995         {
1996             for (ix = 0; ix < Factor; ix++)
1997             {
1998                 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1999             }
2000         }
2001         else
2002         {
2003             for (ix = 1; ix < Factor; ix++)
2004             {
2005                 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2006             }
2007         }
2008 
2009         USBPORT_DumpingEndpointProperties(EndpointProperties);
2010         USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
2011 
2012         if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
2013         {
2014             DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
2015         }
2016     }
2017 
2018     USB2_Rebalance(FdoDevice, &RebalanceList);
2019 
2020     if (!TtExtension)
2021     {
2022         DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2023         return Result;
2024     }
2025 
2026     for (ix = 0; ix < USB2_FRAMES; ix++)
2027     {
2028         FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2029     }
2030 
2031     USBPORT_UpdateAllocatedBwTt(TtExtension);
2032 
2033     for (ix = 0; ix < USB2_FRAMES; ix++)
2034     {
2035         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2036     }
2037 
2038     DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2039 
2040     return Result;
2041 }
2042 
2043 VOID
2044 NTAPI
2045 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
2046                           IN PUSBPORT_ENDPOINT Endpoint)
2047 {
2048     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2049     ULONG Period;
2050     ULONG ScheduleOffset;
2051     ULONG EndpointBandwidth;
2052     LIST_ENTRY RebalanceList;
2053     ULONG TransferType;
2054     PUSB2_REBALANCE Rebalance;
2055     ULONG RebalanceListEntries;
2056     ULONG Factor;
2057     ULONG ix;
2058     ULONG n;
2059     PUSB2_TT_EXTENSION TtExtension;
2060     PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
2061 
2062     DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
2063 
2064     FdoExtension = FdoDevice->DeviceExtension;
2065 
2066     Period = Endpoint->EndpointProperties.Period;
2067     ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
2068     EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
2069 
2070     InitializeListHead(&RebalanceList);
2071 
2072     TransferType = Endpoint->EndpointProperties.TransferType;
2073 
2074     if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2075         TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2076         (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
2077     {
2078         return;
2079     }
2080 
2081     Rebalance = ExAllocatePoolWithTag(NonPagedPool,
2082                                       sizeof(USB2_REBALANCE),
2083                                       USB_PORT_TAG);
2084 
2085     if (!Rebalance)
2086     {
2087         DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
2088         return;
2089     }
2090 
2091     RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
2092 
2093     ASSERT(Period != 0);
2094     Factor = USB2_FRAMES / Period;
2095     n = ScheduleOffset * Factor;
2096 
2097     TtExtension = Endpoint->TtExtension;
2098 
2099     if (TtExtension)
2100     {
2101         for (ix = 0; ix < Factor; ix++)
2102         {
2103             TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
2104         }
2105     }
2106     else
2107     {
2108         for (ix = 1; ix < Factor; ix++)
2109         {
2110             FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
2111         }
2112     }
2113 
2114     RebalanceListEntries = USB2_FRAMES - 2;
2115 
2116     USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
2117                                   Rebalance,
2118                                   &RebalanceListEntries,
2119                                   USB2_FRAMES);
2120 
2121     RebalanceListEntries = 0;
2122 
2123     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
2124     {
2125         RebalanceListEntries = ix + 1;
2126     }
2127 
2128     for (ix = 0; ix < RebalanceListEntries; ix++)
2129     {
2130         RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
2131 
2132         DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
2133                ix,
2134                RebalanceTtEndpoint,
2135                &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2136 
2137         InsertTailList(&RebalanceList,
2138                        &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2139     }
2140 
2141     ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2142 
2143     USB2_Rebalance(FdoDevice, &RebalanceList);
2144 
2145     if (!TtExtension)
2146         return;
2147 
2148     for (ix = 0; ix < USB2_FRAMES; ix++)
2149     {
2150         FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2151     }
2152 
2153     USBPORT_UpdateAllocatedBwTt(TtExtension);
2154 
2155     for (ix = 0; ix < USB2_FRAMES; ix++)
2156     {
2157         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2158     }
2159 
2160     DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
2161 }
2162 
2163 VOID
2164 NTAPI
2165 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
2166             IN PUSB2_TT Tt)
2167 {
2168     ULONG ix;
2169     ULONG jx;
2170 
2171     DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
2172 
2173     Tt->HcExtension = HcExtension;
2174     Tt->DelayTime = 1;
2175     Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
2176 
2177     for (ix = 0; ix < USB2_FRAMES; ix++)
2178     {
2179         Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
2180         Tt->FrameBudget[ix].AltEndpoint = NULL;
2181 
2182         for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2183         {
2184             Tt->TimeCS[ix][jx] = 0;
2185             Tt->NumStartSplits[ix][jx] = 0;
2186         }
2187 
2188         Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
2189 
2190         USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
2191                             USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
2192                             USBPORT_TRANSFER_DIRECTION_OUT,
2193                             UsbFullSpeed,
2194                             USB2_FRAMES,
2195                             0,
2196                             Tt);
2197 
2198         Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
2199         Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2200         Tt->IsoEndpoint[ix].StartFrame = ix;
2201         Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2202 
2203         Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
2204 
2205         USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
2206                             USBPORT_TRANSFER_TYPE_INTERRUPT,
2207                             USBPORT_TRANSFER_DIRECTION_OUT,
2208                             UsbFullSpeed,
2209                             USB2_FRAMES,
2210                             0,
2211                             Tt);
2212 
2213         Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
2214         Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2215         Tt->IntEndpoint[ix].StartFrame = ix;
2216         Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2217     }
2218 }
2219 
2220 VOID
2221 NTAPI
2222 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
2223 {
2224     ULONG ix;
2225     ULONG jx;
2226 
2227     DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
2228 
2229     HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
2230 
2231     for (ix = 0; ix < USB2_FRAMES; ix++)
2232     {
2233         for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2234         {
2235             HcExtension->TimeUsed[ix][jx] = 0;
2236         }
2237     }
2238 
2239     HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
2240 
2241     USB2_InitTT(HcExtension, &HcExtension->HcTt);
2242 }
2243