xref: /reactos/drivers/usb/usbport/usb2.c (revision f5c54269)
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
USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,IN ULONG CalcBusTime,IN ULONG LimitAllocation)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
USB2_AddDataBitStuff(IN USHORT DataTime)40 USB2_AddDataBitStuff(IN USHORT DataTime)
41 {
42     return (DataTime + (DataTime / 16));
43 }
44 
45 VOID
46 NTAPI
USB2_IncMicroFrame(OUT PUCHAR frame,OUT PUCHAR uframe)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
USB2_GetPrevMicroFrame(OUT PUCHAR frame,OUT PUCHAR uframe)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
USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint)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
USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)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
USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PULONG OverheadSS,IN PULONG OverheadCS)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
USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,IN ULONG Frame)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
USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_TT_ENDPOINT prevTtEndpoint,IN ULONG Frame)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
USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN UCHAR TransferType,IN UCHAR Direction,IN UCHAR DeviceSpeed,IN USHORT Period,IN USHORT MaxPacketSize,IN PUSB2_TT Tt)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
USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,IN LONG Frame)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
USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,IN ULONG Frame)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
USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN LONG BusTime,IN PUSB2_REBALANCE Rebalance,IN ULONG RebalanceListEntries,OUT BOOLEAN * OutResult)619 USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
620                     IN LONG 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 &&
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 = 1;
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
USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint)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
USB2_ConvertFrame(IN UCHAR Frame,IN UCHAR Microframe,OUT PUCHAR HcFrame,OUT PUCHAR HcMicroframe)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 <= (USB2_MICROFRAMES - 2))
743     {
744         *HcFrame = Frame;
745         *HcMicroframe = Microframe + 1;
746     }
747 
748     if (Microframe == (USB2_MICROFRAMES - 1))
749     {
750         *HcFrame = Frame + 1;
751         *HcMicroframe = 0;
752     }
753 }
754 
755 UCHAR
756 NTAPI
USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)757 USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
758 {
759     ULONG ix;
760     UCHAR SMask = 0;
761     UCHAR HcFrame;
762     UCHAR HcMicroFrame;
763 
764     if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
765     {
766         SMask = (1 << TtEndpoint->StartMicroframe);
767     }
768     else
769     {
770         USB2_ConvertFrame(TtEndpoint->StartFrame,
771                           TtEndpoint->StartMicroframe,
772                           &HcFrame,
773                           &HcMicroFrame);
774 
775         for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
776         {
777             SMask |= (1 << HcMicroFrame);
778             HcMicroFrame++;
779         }
780     }
781 
782     return SMask;
783 }
784 
785 UCHAR
786 NTAPI
USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)787 USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
788 {
789     ULONG NumCompletes;
790     ULONG TransferType;
791     ULONG DeviceSpeed;
792     ULONG Direction;
793     UCHAR Result;
794     UCHAR MicroFrameCS;
795     UCHAR HcFrame;
796     UCHAR HcMicroFrame;
797     UCHAR MaskCS = 0;
798 
799     TransferType = TtEndpoint->TtEndpointParams.TransferType;
800     DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
801     Direction = TtEndpoint->TtEndpointParams.Direction;
802 
803     if (DeviceSpeed == UsbHighSpeed)
804         return 0;
805 
806     if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
807     {
808         USB2_ConvertFrame(TtEndpoint->StartFrame,
809                           TtEndpoint->StartMicroframe,
810                           &HcFrame,
811                           &HcMicroFrame);
812 
813         Result = CMASKS[HcMicroFrame];
814     }
815     else
816     {
817         if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
818             return 0;
819 
820         USB2_ConvertFrame(TtEndpoint->StartFrame,
821                           TtEndpoint->StartMicroframe,
822                           &HcFrame,
823                           &HcMicroFrame);
824 
825         NumCompletes = TtEndpoint->Nums.NumCompletes;
826 
827         for (MicroFrameCS = HcMicroFrame + 2;
828              MicroFrameCS < USB2_MICROFRAMES;
829              MicroFrameCS++)
830         {
831             MaskCS |= (1 << MicroFrameCS);
832             NumCompletes--;
833 
834             if (!NumCompletes)
835                 return MaskCS;
836         }
837 
838         for (; NumCompletes; NumCompletes--)
839         {
840             MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES));
841         }
842 
843         Result = MaskCS;
844     }
845 
846     return Result;
847 }
848 
849 VOID
850 NTAPI
USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,IN PLIST_ENTRY List)851 USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
852                        IN PLIST_ENTRY List)
853 {
854     PUSBPORT_DEVICE_EXTENSION FdoExtension;
855     PUSBPORT_REGISTRATION_PACKET Packet;
856     PUSBPORT_ENDPOINT Endpoint;
857     PLIST_ENTRY Entry;
858     ULONG AllocedBusTime;
859     ULONG EndpointBandwidth;
860     ULONG Factor;
861     ULONG ScheduleOffset;
862     ULONG Bandwidth;
863     ULONG n;
864     ULONG ix;
865     KIRQL OldIrql;
866     UCHAR NewPeriod;
867     UCHAR SMask;
868     UCHAR CMask;
869 
870     FdoExtension = FdoDevice->DeviceExtension;
871     Packet = &FdoExtension->MiniPortInterface->Packet;
872 
873     while (!IsListEmpty(List))
874     {
875         Entry = RemoveHeadList(List);
876 
877         Endpoint = CONTAINING_RECORD(Entry,
878                                      USBPORT_ENDPOINT,
879                                      RebalanceLink.Flink);
880 
881         DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
882 
883         Endpoint->RebalanceLink.Flink = NULL;
884         Endpoint->RebalanceLink.Blink = NULL;
885 
886         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
887                           &Endpoint->EndpointOldIrql);
888 
889         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
890         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
891 
892         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
893         NewPeriod = Endpoint->TtEndpoint->ActualPeriod;
894 
895         AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime;
896         EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
897 
898         Endpoint->EndpointProperties.InterruptScheduleMask = SMask;
899         Endpoint->EndpointProperties.SplitCompletionMask = CMask;
900 
901         if (Endpoint->EndpointProperties.Period != NewPeriod)
902         {
903             ASSERT(Endpoint->EndpointProperties.Period);
904             Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
905 
906             for (ix = 0; ix < Factor; ix++)
907             {
908                 Bandwidth = Endpoint->EndpointProperties.UsbBandwidth;
909                 n = Factor * Endpoint->EndpointProperties.ScheduleOffset;
910                 Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth;
911             }
912 
913             Endpoint->EndpointProperties.Period = NewPeriod;
914             Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset;
915             Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth;
916 
917             ASSERT(NewPeriod);
918             Factor = USB2_FRAMES / NewPeriod;
919 
920             for (ix = 0; ix < Factor; ix++)
921             {
922                 n = Factor * ScheduleOffset;
923                 Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
924             }
925         }
926 
927         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
928 
929         Packet->RebalanceEndpoint(FdoExtension->MiniPortExt,
930                                   &Endpoint->EndpointProperties,
931                                   (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT)));
932 
933         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
934 
935         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
936                           Endpoint->EndpointOldIrql);
937     }
938 }
939 
940 VOID
941 NTAPI
USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,IN PLIST_ENTRY RebalanceList)942 USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,
943                IN PLIST_ENTRY RebalanceList)
944 {
945     PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
946     PUSBPORT_ENDPOINT Endpoint;
947     PLIST_ENTRY Entry;
948     LIST_ENTRY BalanceListInt1;
949     LIST_ENTRY BalanceListInt2;
950     ULONG TransferType;
951     ULONG ScheduleOffset;
952     UCHAR SMask;
953     UCHAR CMask;
954     UCHAR ActualPeriod;
955 
956     DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n",
957            FdoDevice,
958            RebalanceList);
959 
960     InitializeListHead(&BalanceListInt1);
961     InitializeListHead(&BalanceListInt2);
962 
963     while (!IsListEmpty(RebalanceList))
964     {
965         Entry = RebalanceList->Flink;
966 
967         Endpoint = CONTAINING_RECORD(Entry,
968                                      USBPORT_ENDPOINT,
969                                      RebalanceLink.Flink);
970 
971         DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n",
972                Entry,
973                Endpoint);
974 
975         RemoveHeadList(RebalanceList);
976         Entry->Flink = NULL;
977         Entry->Blink = NULL;
978 
979         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
980         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
981 
982         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
983         ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
984 
985         EndpointProperties = &Endpoint->EndpointProperties;
986         TransferType = EndpointProperties->TransferType;
987 
988         switch (TransferType)
989         {
990             case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
991                 DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
992                 ASSERT(FALSE);
993                 break;
994 
995             case USBPORT_TRANSFER_TYPE_INTERRUPT:
996                 if (SMask != EndpointProperties->InterruptScheduleMask ||
997                     CMask != EndpointProperties->SplitCompletionMask ||
998                     ScheduleOffset != EndpointProperties->ScheduleOffset ||
999                     ActualPeriod != EndpointProperties->Period)
1000                 {
1001                     if (ActualPeriod == EndpointProperties->Period &&
1002                         ScheduleOffset == EndpointProperties->ScheduleOffset)
1003                     {
1004                         InsertTailList(&BalanceListInt1, Entry);
1005                     }
1006                     else
1007                     {
1008                         InsertTailList(&BalanceListInt2, Entry);
1009                     }
1010                 }
1011                 break;
1012 
1013             default:
1014                 ASSERT(FALSE);
1015                 break;
1016         }
1017     }
1018 
1019     USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2);
1020     USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1);
1021     //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso);
1022 }
1023 
1024 BOOLEAN
1025 NTAPI
USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries,IN ULONG MaxFrames)1026 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
1027                               IN PUSB2_REBALANCE Rebalance,
1028                               IN PULONG RebalanceListEntries,
1029                               IN ULONG MaxFrames)
1030 {
1031     PUSB2_TT Tt;
1032     PUSB2_HC_EXTENSION HcExtension;
1033     ULONG Speed;
1034     ULONG TransferType;
1035     ULONG Frame;
1036     ULONG StartMicroframe;
1037     ULONG ix;
1038     PUSB2_TT_ENDPOINT endpoint;
1039     PUSB2_TT_ENDPOINT nextEndpoint;
1040     PUSB2_TT_ENDPOINT lastEndpoint;
1041     PUSB2_TT_ENDPOINT tmpEndpoint;
1042     ULONG endTime;
1043     ULONG maxEndTime;
1044     ULONG lastEndTime;
1045     ULONG Factor;
1046     ULONG jx;
1047     UCHAR frame;
1048     UCHAR uframe;
1049     USHORT Period;
1050     BOOLEAN IsMoved = FALSE;
1051 
1052     DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
1053            TtEndpoint,
1054            MaxFrames,
1055            TtEndpoint->CalcBusTime);
1056 
1057     if (TtEndpoint->CalcBusTime == 0)
1058     {
1059         DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
1060         return FALSE;
1061     }
1062 
1063     Tt = TtEndpoint->Tt;
1064     HcExtension = Tt->HcExtension;
1065 
1066     Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1067     DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
1068 
1069     StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1070                       TtEndpoint->StartMicroframe;
1071 
1072     if (Speed == UsbHighSpeed)
1073     {
1074         for (ix = StartMicroframe;
1075              ix < USB2_MAX_MICROFRAMES;
1076              ix += TtEndpoint->ActualPeriod)
1077         {
1078             frame = ix / USB2_MICROFRAMES;
1079             uframe = ix % (USB2_MICROFRAMES - 1);
1080 
1081             HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1082         }
1083 
1084         TtEndpoint->CalcBusTime = 0;
1085 
1086         DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1087         return TRUE;
1088     }
1089 
1090     /* Speed != UsbHighSpeed (FS/LS) */
1091 
1092     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1093 
1094     for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
1095          ix > 0;
1096          ix--, Frame--)
1097     {
1098         frame = TtEndpoint->StartFrame + Frame;
1099 
1100         DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
1101                frame,
1102                Frame,
1103                TtEndpoint->StartFrame);
1104 
1105         if ((Frame % TtEndpoint->ActualPeriod) == 0)
1106         {
1107             USB2_DeallocateHS(TtEndpoint, Frame);
1108             Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
1109         }
1110 
1111         if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1112             endpoint = Tt->FrameBudget[frame].IntEndpoint;
1113         else
1114             endpoint = Tt->FrameBudget[frame].IsoEndpoint;
1115 
1116         nextEndpoint = endpoint->NextTtEndpoint;
1117 
1118         DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
1119                TtEndpoint,
1120                nextEndpoint);
1121 
1122         if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1123         {
1124             while (nextEndpoint)
1125             {
1126                 endpoint = nextEndpoint;
1127                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1128             }
1129 
1130             nextEndpoint = TtEndpoint;
1131 
1132             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1133                    endpoint,
1134                    nextEndpoint);
1135         }
1136         else
1137         {
1138             while (nextEndpoint &&
1139                    !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1140             {
1141                 endpoint = nextEndpoint;
1142                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1143             }
1144 
1145             if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
1146                 nextEndpoint)
1147             {
1148                 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1149                 ASSERT(FALSE);
1150             }
1151 
1152             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1153                    endpoint,
1154                    nextEndpoint);
1155         }
1156 
1157         if ((Frame % TtEndpoint->ActualPeriod) == 0)
1158         {
1159             if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1160             {
1161                 Tt->FrameBudget[frame].AltEndpoint = NULL;
1162             }
1163             else if (nextEndpoint)
1164             {
1165                 nextEndpoint = nextEndpoint->NextTtEndpoint;
1166                 endpoint->NextTtEndpoint = nextEndpoint;
1167 
1168                 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1169                        endpoint,
1170                        nextEndpoint);
1171             }
1172         }
1173 
1174         if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1175         {
1176             if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
1177             {
1178                 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1179                 {
1180                     endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1181                 }
1182                 else if (Tt->FrameBudget[frame].AltEndpoint)
1183                 {
1184                     endpoint = Tt->FrameBudget[frame].AltEndpoint;
1185                 }
1186             }
1187         }
1188         else
1189         {
1190             DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1191             ASSERT(FALSE);
1192         }
1193 
1194         Period = TtEndpoint->ActualPeriod;
1195 
1196         for (;
1197              nextEndpoint;
1198              endpoint = nextEndpoint,
1199              nextEndpoint = nextEndpoint->NextTtEndpoint)
1200         {
1201             DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1202                    endpoint,
1203                    nextEndpoint);
1204 
1205             endTime = endpoint->StartTime + endpoint->CalcBusTime;
1206             maxEndTime = endTime;
1207 
1208             if (Period > nextEndpoint->ActualPeriod ||
1209                 TtEndpoint->StartFrame != nextEndpoint->StartFrame)
1210             {
1211                 if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
1212                     Factor = Period / nextEndpoint->ActualPeriod;
1213                 else
1214                     Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
1215 
1216                 maxEndTime = endTime;
1217 
1218                 for (jx = 0, frame = nextEndpoint->StartFrame;
1219                      jx < Factor;
1220                      jx++, frame += nextEndpoint->ActualPeriod)
1221                 {
1222                     if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
1223                     {
1224                         lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1225 
1226                         if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1227                         {
1228                             lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1229                         }
1230                         else if (Tt->FrameBudget[frame].AltEndpoint)
1231                         {
1232                             lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
1233                         }
1234 
1235                         for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
1236                              tmpEndpoint && tmpEndpoint != nextEndpoint;
1237                              tmpEndpoint = tmpEndpoint->NextTtEndpoint)
1238                         {
1239                             lastEndpoint = tmpEndpoint;
1240                         }
1241 
1242                         lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
1243 
1244                         if (endTime < (lastEndTime - 1))
1245                         {
1246                             maxEndTime = lastEndTime;
1247                             endTime = maxEndTime;
1248 
1249                             if (nextEndpoint->StartTime == maxEndTime)
1250                                 break;
1251                         }
1252                         else
1253                         {
1254                             maxEndTime = endTime;
1255                         }
1256                     }
1257                 }
1258             }
1259 
1260             if (maxEndTime >= nextEndpoint->StartTime)
1261                 break;
1262 
1263             if (!USB2_MoveTtEndpoint(nextEndpoint,
1264                                      maxEndTime - nextEndpoint->StartTime,
1265                                      Rebalance,
1266                                      *RebalanceListEntries,
1267                                      &IsMoved))
1268             {
1269                 if (!IsMoved)
1270                 {
1271                     DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
1272                 }
1273 
1274                 break;
1275             }
1276 
1277             if (Period > nextEndpoint->ActualPeriod)
1278                 Period = nextEndpoint->ActualPeriod;
1279         }
1280     }
1281 
1282     TtEndpoint->CalcBusTime = 0;
1283 
1284     DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1285     return TRUE;
1286 }
1287 
1288 BOOLEAN
1289 NTAPI
USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1290 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
1291                              IN PUSB2_REBALANCE Rebalance,
1292                              IN PULONG RebalanceListEntries)
1293 {
1294     PUSB2_TT Tt;
1295     PUSB2_HC_EXTENSION HcExtension;
1296     ULONG Speed;
1297     ULONG TimeUsed;
1298     ULONG MinTimeUsed;
1299     ULONG ix;
1300     ULONG frame;
1301     ULONG uframe;
1302     ULONG Microframe;
1303     ULONG TransferType;
1304     ULONG Overhead;
1305     ULONG LatestStart;
1306     PUSB2_TT_ENDPOINT prevEndpoint;
1307     PUSB2_TT_ENDPOINT nextEndpoint;
1308     PUSB2_TT_ENDPOINT IntEndpoint;
1309     ULONG StartTime;
1310     ULONG calcBusTime;
1311     BOOLEAN Result = TRUE;
1312 
1313     DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
1314 
1315     Tt = TtEndpoint->Tt;
1316     HcExtension = Tt->HcExtension;
1317 
1318     TtEndpoint->Nums.NumStarts = 0;
1319     TtEndpoint->Nums.NumCompletes = 0;
1320 
1321     TtEndpoint->StartFrame = 0;
1322     TtEndpoint->StartMicroframe = 0;
1323 
1324     if (TtEndpoint->CalcBusTime)
1325     {
1326         DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
1327         return FALSE;
1328     }
1329 
1330     Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1331 
1332     if (Speed == UsbHighSpeed)
1333     {
1334         if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
1335             TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
1336         else
1337             TtEndpoint->ActualPeriod = TtEndpoint->Period;
1338 
1339         MinTimeUsed = HcExtension->TimeUsed[0][0];
1340 
1341         for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1342         {
1343             frame = ix / USB2_MICROFRAMES;
1344             uframe = ix % (USB2_MICROFRAMES - 1);
1345 
1346             TimeUsed = HcExtension->TimeUsed[frame][uframe];
1347 
1348             if (TimeUsed < MinTimeUsed)
1349             {
1350                 MinTimeUsed = TimeUsed;
1351                 TtEndpoint->StartFrame = frame;
1352                 TtEndpoint->StartMicroframe = uframe;
1353             }
1354         }
1355 
1356         TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1357                                   USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1358 
1359         DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1360                TtEndpoint->StartFrame,
1361                TtEndpoint->StartMicroframe,
1362                TtEndpoint->CalcBusTime);
1363 
1364         Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1365                      TtEndpoint->StartMicroframe;
1366 
1367         if (Microframe >= USB2_MAX_MICROFRAMES)
1368         {
1369             DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1370             return TRUE;
1371         }
1372 
1373         for (ix = Microframe;
1374              ix < USB2_MAX_MICROFRAMES;
1375              ix += TtEndpoint->ActualPeriod)
1376         {
1377             frame = ix / USB2_MICROFRAMES;
1378             uframe = ix % (USB2_MICROFRAMES - 1);
1379 
1380             DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1381                    frame,
1382                    uframe,
1383                    HcExtension->TimeUsed[frame][uframe]);
1384 
1385             if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1386                                     TtEndpoint->CalcBusTime,
1387                                     USB2_MAX_MICROFRAME_ALLOCATION))
1388             {
1389                 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1390                 Result = FALSE;
1391             }
1392         }
1393 
1394         if (!Result)
1395         {
1396             for (ix = Microframe;
1397                  ix < USB2_MAX_MICROFRAMES;
1398                  ix += TtEndpoint->ActualPeriod)
1399             {
1400                 frame = ix / USB2_MICROFRAMES;
1401                 uframe = ix % (USB2_MICROFRAMES - 1);
1402 
1403                 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1404             }
1405         }
1406 
1407         DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1408         return TRUE;
1409     }
1410 
1411     /* Speed != UsbHighSpeed (FS/LS) */
1412 
1413     if (TtEndpoint->Period > USB2_FRAMES)
1414         TtEndpoint->ActualPeriod = USB2_FRAMES;
1415     else
1416         TtEndpoint->ActualPeriod = TtEndpoint->Period;
1417 
1418     MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1419 
1420     for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1421     {
1422         if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1423         {
1424             MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1425             TtEndpoint->StartFrame = ix;
1426         }
1427     }
1428 
1429     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1430 
1431     if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1432     {
1433         if (Speed == UsbFullSpeed)
1434         {
1435             Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1436         }
1437         else
1438         {
1439             DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1440             return FALSE;
1441         }
1442     }
1443     else
1444     {
1445         if (Speed == UsbFullSpeed)
1446             Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1447         else
1448             Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1449     }
1450 
1451     if (Speed == UsbLowSpeed)
1452         TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1453     else
1454         TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1455 
1456     LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1457 
1458     for (ix = 0;
1459          (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1460          ix += TtEndpoint->ActualPeriod)
1461     {
1462         frame = TtEndpoint->StartFrame + ix;
1463 
1464         if (Tt->FrameBudget[frame].AltEndpoint &&
1465             TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1466         {
1467             DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1468             return FALSE;
1469         }
1470 
1471         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1472             prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1473         else
1474             prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1475 
1476         for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1477              nextEndpoint;
1478              nextEndpoint = nextEndpoint->NextTtEndpoint)
1479         {
1480             if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1481                 break;
1482 
1483             prevEndpoint = nextEndpoint;
1484         }
1485 
1486         StartTime = USB2_GetStartTime(nextEndpoint,
1487                                       TtEndpoint,
1488                                       prevEndpoint,
1489                                       frame);
1490 
1491         LatestStart = max(LatestStart, StartTime);
1492     }
1493 
1494     TtEndpoint->StartTime = LatestStart;
1495 
1496     if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1497     {
1498         TtEndpoint->CalcBusTime = 0;
1499         DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1500         return FALSE;
1501     }
1502 
1503     for (ix = 0, frame = -TtEndpoint->StartFrame;
1504          ix < USB2_FRAMES;
1505          ix++, frame++)
1506     {
1507         DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1508                ix,
1509                frame,
1510                TtEndpoint->StartFrame);
1511 
1512         if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1513         {
1514             DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1515             ASSERT(FALSE);
1516         }
1517         else
1518         {
1519             IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1520             nextEndpoint = IntEndpoint->NextTtEndpoint;
1521 
1522             for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1523                  nextEndpoint;
1524                  nextEndpoint = nextEndpoint->NextTtEndpoint)
1525             {
1526                 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1527                     break;
1528                 IntEndpoint = nextEndpoint;
1529             }
1530 
1531             if ((frame % TtEndpoint->ActualPeriod) == 0)
1532             {
1533                 calcBusTime = 0;
1534             }
1535             else
1536             {
1537                 if (nextEndpoint)
1538                 {
1539                     calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1540                                   nextEndpoint->StartTime;
1541                 }
1542                 else
1543                 {
1544                     calcBusTime = TtEndpoint->CalcBusTime;
1545                 }
1546 
1547                 if (calcBusTime > 0)
1548                 {
1549                     TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1550 
1551                     if (!USB2_AllocateCheck(&TimeUsed,
1552                                             calcBusTime,
1553                                             USB2_FS_MAX_PERIODIC_ALLOCATION))
1554                     {
1555                         DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1556                         Result = FALSE;
1557                     }
1558                 }
1559             }
1560 
1561             if (nextEndpoint != TtEndpoint)
1562             {
1563                 if ((frame % TtEndpoint->ActualPeriod) == 0)
1564                 {
1565                     if (frame == 0)
1566                     {
1567                         DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1568                         TtEndpoint->NextTtEndpoint = nextEndpoint;
1569                     }
1570 
1571                     IntEndpoint->NextTtEndpoint = TtEndpoint;
1572 
1573                     DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1574                            TtEndpoint,
1575                            nextEndpoint);
1576                 }
1577 
1578                 if (calcBusTime > 0)
1579                 {
1580                     BOOLEAN IsMoved;
1581                     BOOLEAN MoveResult;
1582 
1583                     DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1584                            nextEndpoint,
1585                            calcBusTime);
1586 
1587                     for (;
1588                          nextEndpoint;
1589                          nextEndpoint = nextEndpoint->NextTtEndpoint)
1590                     {
1591                         MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1592                                                          calcBusTime,
1593                                                          Rebalance,
1594                                                          *RebalanceListEntries,
1595                                                          &IsMoved);
1596 
1597                         if (!IsMoved)
1598                         {
1599                             DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1600                             Result = FALSE;
1601                         }
1602 
1603                         if (!MoveResult)
1604                             break;
1605                     }
1606                 }
1607             }
1608         }
1609 
1610         if ((frame % TtEndpoint->ActualPeriod) == 0)
1611         {
1612             if (!USB2_AllocateHS(TtEndpoint, frame))
1613             {
1614                 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1615                 Result = FALSE;
1616             }
1617 
1618             Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1619         }
1620 
1621         if (Result == FALSE)
1622         {
1623             USB2_DeallocateEndpointBudget(TtEndpoint,
1624                                           Rebalance,
1625                                           RebalanceListEntries,
1626                                           ix + 1);
1627 
1628             DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1629             return FALSE;
1630         }
1631     }
1632 
1633     DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1634     return Result;
1635 }
1636 
1637 BOOLEAN
1638 NTAPI
USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1639 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
1640                   IN PUSB2_REBALANCE Rebalance,
1641                   IN PULONG RebalanceListEntries)
1642 {
1643     BOOLEAN Result;
1644 
1645     DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
1646            *RebalanceListEntries);
1647 
1648     USB2_DeallocateEndpointBudget(TtEndpoint,
1649                                   Rebalance,
1650                                   RebalanceListEntries,
1651                                   USB2_FRAMES);
1652 
1653     TtEndpoint->PreviosPeriod = TtEndpoint->Period;
1654     TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1655 
1656     Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1657                                           Rebalance,
1658                                           RebalanceListEntries);
1659 
1660     return Result;
1661 }
1662 
1663 BOOLEAN
1664 NTAPI
USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1665 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1666                     IN PUSB2_REBALANCE Rebalance,
1667                     IN PULONG RebalanceListEntries)
1668 {
1669     PUSB2_TT_ENDPOINT ttEndpoint;
1670     ULONG TransferType;
1671     ULONG ix;
1672 
1673     TransferType = TtEndpoint->TtEndpointParams.TransferType;
1674 
1675     if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1676         TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1677         (CHAR)TtEndpoint->StartMicroframe > 2 &&
1678         !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
1679     {
1680         DPRINT("USB2_PromotePeriods: return FALSE\n");
1681         return FALSE;
1682     }
1683 
1684     if (Rebalance->RebalanceEndpoint[0] == NULL)
1685     {
1686         DPRINT("USB2_PromotePeriods: return TRUE\n");
1687         return TRUE;
1688     }
1689 
1690     DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
1691            *RebalanceListEntries);
1692 
1693     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1694     {
1695         Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
1696     }
1697 
1698     for (ix = 0; ; ix++)
1699     {
1700         ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1701         TransferType = ttEndpoint->TtEndpointParams.TransferType;
1702 
1703         if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1704             TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1705             (CHAR)ttEndpoint->StartMicroframe > 2)
1706         {
1707             USB2_DeallocateEndpointBudget(ttEndpoint,
1708                                           Rebalance,
1709                                           RebalanceListEntries,
1710                                           USB2_FRAMES);
1711 
1712             ttEndpoint->IsPromoted = TRUE;
1713             ttEndpoint->PreviosPeriod = ttEndpoint->Period;
1714             ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1715 
1716             if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
1717                                               Rebalance,
1718                                               RebalanceListEntries))
1719             {
1720                 break;
1721             }
1722         }
1723 
1724         if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
1725         {
1726             DPRINT("USB2_PromotePeriods: return TRUE\n");
1727             return TRUE;
1728         }
1729     }
1730 
1731     USB2_DeallocateEndpointBudget(TtEndpoint,
1732                                   Rebalance,
1733                                   RebalanceListEntries,
1734                                   USB2_FRAMES);
1735 
1736     TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1737     TtEndpoint->PreviosPeriod = 0;
1738 
1739     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1740     {
1741         ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1742 
1743         if (ttEndpoint->IsPromoted)
1744         {
1745             if (ttEndpoint->CalcBusTime)
1746             {
1747                 USB2_DeallocateEndpointBudget(ttEndpoint,
1748                                               Rebalance,
1749                                               RebalanceListEntries,
1750                                               USB2_FRAMES);
1751             }
1752 
1753             TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1754             TtEndpoint->PreviosPeriod = 0;
1755 
1756             USB2_AllocateTimeForEndpoint(ttEndpoint,
1757                                          Rebalance,
1758                                          RebalanceListEntries);
1759         }
1760     }
1761 
1762     DPRINT("USB2_PromotePeriods: return FALSE\n");
1763     return FALSE;
1764 }
1765 
1766 VOID
1767 NTAPI
USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)1768 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1769 {
1770     ULONG BusBandwidth;
1771     ULONG NewBusBandwidth;
1772     ULONG MaxBusBandwidth = 0;
1773     ULONG MinBusBandwidth;
1774     ULONG ix;
1775 
1776     DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1777 
1778     BusBandwidth = TtExtension->BusBandwidth;
1779     MinBusBandwidth = BusBandwidth;
1780 
1781     for (ix = 0; ix < USB2_FRAMES; ix++)
1782     {
1783         NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1784 
1785         MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
1786         MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
1787     }
1788 
1789     TtExtension->MaxBandwidth = MaxBusBandwidth;
1790 
1791     if (MinBusBandwidth == BusBandwidth)
1792         TtExtension->MinBandwidth = 0;
1793     else
1794         TtExtension->MinBandwidth = MinBusBandwidth;
1795 }
1796 
1797 BOOLEAN
1798 NTAPI
USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint)1799 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1800                               IN PUSBPORT_ENDPOINT Endpoint)
1801 {
1802     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1803     PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1804     PUSB2_TT_EXTENSION TtExtension;
1805     ULONG TransferType;
1806     PUSB2_REBALANCE Rebalance;
1807     LIST_ENTRY RebalanceList;
1808     ULONG RebalanceListEntries;
1809     PUSB2_TT_ENDPOINT TtEndpoint;
1810     PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1811     PUSB2_TT Tt;
1812     USB_DEVICE_SPEED DeviceSpeed;
1813     ULONG Period;
1814     ULONG AllocedBusTime;
1815     ULONG EndpointBandwidth;
1816     ULONG ScheduleOffset;
1817     ULONG Factor;
1818     ULONG ix;
1819     ULONG n;
1820     BOOLEAN Direction;
1821     UCHAR SMask;
1822     UCHAR CMask;
1823     UCHAR ActualPeriod;
1824     BOOLEAN Result;
1825 
1826     DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1827            FdoDevice,
1828            Endpoint);
1829 
1830     EndpointProperties = &Endpoint->EndpointProperties;
1831     EndpointProperties->ScheduleOffset = 0;
1832 
1833     if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1834     {
1835         DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1836         return TRUE;
1837     }
1838 
1839     FdoExtension = FdoDevice->DeviceExtension;
1840 
1841     TransferType = EndpointProperties->TransferType;
1842     DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1843 
1844     if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1845         TransferType == USBPORT_TRANSFER_TYPE_BULK)
1846     {
1847         return TRUE;
1848     }
1849 
1850     if (Endpoint->TtExtension)
1851         TtExtension = Endpoint->TtExtension;
1852     else
1853         TtExtension = NULL;
1854 
1855     InitializeListHead(&RebalanceList);
1856 
1857     Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1858                                       sizeof(USB2_REBALANCE),
1859                                       USB_PORT_TAG);
1860 
1861     DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1862            Rebalance,
1863            TtExtension);
1864 
1865     if (Rebalance)
1866     {
1867         RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1868 
1869         TtEndpoint = Endpoint->TtEndpoint;
1870         TtEndpoint->Endpoint = Endpoint;
1871 
1872         Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1873         DeviceSpeed = EndpointProperties->DeviceSpeed;
1874 
1875         switch (DeviceSpeed)
1876         {
1877             case UsbLowSpeed:
1878             case UsbFullSpeed:
1879             {
1880                 Tt = &TtExtension->Tt;
1881                 Period = USB2_FRAMES;
1882 
1883                 while (Period > 0 && Period > EndpointProperties->Period)
1884                 {
1885                     Period >>= 1;
1886                 }
1887 
1888                 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1889                 break;
1890             }
1891 
1892             case UsbHighSpeed:
1893             {
1894                 Tt = &FdoExtension->Usb2Extension->HcTt;
1895                 Period = EndpointProperties->Period;
1896 
1897                 break;
1898             }
1899 
1900             default:
1901             {
1902                 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1903                         DeviceSpeed);
1904 
1905                 DbgBreakPoint();
1906 
1907                 Tt = &TtExtension->Tt;
1908                 break;
1909             }
1910         }
1911 
1912         USB2_InitTtEndpoint(TtEndpoint,
1913                             TransferType,
1914                             Direction,
1915                             DeviceSpeed,
1916                             Period,
1917                             EndpointProperties->MaxPacketSize,
1918                             Tt);
1919 
1920         RebalanceListEntries = USB2_FRAMES - 2;
1921 
1922         Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1923                                               Rebalance,
1924                                               &RebalanceListEntries);
1925 
1926         if (Result)
1927         {
1928             Result = USB2_PromotePeriods(TtEndpoint,
1929                                          Rebalance,
1930                                          &RebalanceListEntries);
1931         }
1932 
1933         RebalanceListEntries = 0;
1934 
1935         for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1936         {
1937             RebalanceListEntries = ix + 1;
1938         }
1939     }
1940     else
1941     {
1942         RebalanceListEntries = 0;
1943         Result = FALSE;
1944     }
1945 
1946     DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1947            RebalanceListEntries,
1948            Result);
1949 
1950     for (ix = 0; ix < RebalanceListEntries; ix++)
1951     {
1952         RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1953 
1954         DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1955                ix,
1956                RebalanceTtEndpoint,
1957                &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1958 
1959         InsertTailList(&RebalanceList,
1960                        &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1961     }
1962 
1963     if (Rebalance)
1964         ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1965 
1966     if (Result)
1967     {
1968         SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1969         EndpointProperties->InterruptScheduleMask = SMask;
1970 
1971         CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1972         EndpointProperties->SplitCompletionMask = CMask;
1973 
1974         AllocedBusTime = TtEndpoint->CalcBusTime;
1975 
1976         EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1977         EndpointProperties->UsbBandwidth = EndpointBandwidth;
1978 
1979         ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1980         EndpointProperties->Period = ActualPeriod;
1981 
1982         ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1983         EndpointProperties->ScheduleOffset = ScheduleOffset;
1984 
1985         ASSERT(ActualPeriod);
1986         Factor = USB2_FRAMES / ActualPeriod;
1987         n = ScheduleOffset * Factor;
1988 
1989         if (TtExtension)
1990         {
1991             for (ix = 0; ix < Factor; ix++)
1992             {
1993                 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1994             }
1995         }
1996         else
1997         {
1998             for (ix = 1; ix < Factor; ix++)
1999             {
2000                 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2001             }
2002         }
2003 
2004         USBPORT_DumpingEndpointProperties(EndpointProperties);
2005         USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
2006 
2007         if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
2008         {
2009             DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
2010         }
2011     }
2012 
2013     USB2_Rebalance(FdoDevice, &RebalanceList);
2014 
2015     if (!TtExtension)
2016     {
2017         DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2018         return Result;
2019     }
2020 
2021     for (ix = 0; ix < USB2_FRAMES; ix++)
2022     {
2023         FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2024     }
2025 
2026     USBPORT_UpdateAllocatedBwTt(TtExtension);
2027 
2028     for (ix = 0; ix < USB2_FRAMES; ix++)
2029     {
2030         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2031     }
2032 
2033     DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2034 
2035     return Result;
2036 }
2037 
2038 VOID
2039 NTAPI
USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint)2040 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
2041                           IN PUSBPORT_ENDPOINT Endpoint)
2042 {
2043     PUSBPORT_DEVICE_EXTENSION FdoExtension;
2044     ULONG Period;
2045     ULONG ScheduleOffset;
2046     ULONG EndpointBandwidth;
2047     LIST_ENTRY RebalanceList;
2048     ULONG TransferType;
2049     PUSB2_REBALANCE Rebalance;
2050     ULONG RebalanceListEntries;
2051     ULONG Factor;
2052     ULONG ix;
2053     ULONG n;
2054     PUSB2_TT_EXTENSION TtExtension;
2055     PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
2056 
2057     DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
2058 
2059     FdoExtension = FdoDevice->DeviceExtension;
2060 
2061     Period = Endpoint->EndpointProperties.Period;
2062     ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
2063     EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
2064 
2065     InitializeListHead(&RebalanceList);
2066 
2067     TransferType = Endpoint->EndpointProperties.TransferType;
2068 
2069     if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2070         TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2071         (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
2072     {
2073         return;
2074     }
2075 
2076     Rebalance = ExAllocatePoolWithTag(NonPagedPool,
2077                                       sizeof(USB2_REBALANCE),
2078                                       USB_PORT_TAG);
2079 
2080     if (!Rebalance)
2081     {
2082         DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
2083         return;
2084     }
2085 
2086     RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
2087 
2088     ASSERT(Period != 0);
2089     Factor = USB2_FRAMES / Period;
2090     n = ScheduleOffset * Factor;
2091 
2092     TtExtension = Endpoint->TtExtension;
2093 
2094     if (TtExtension)
2095     {
2096         for (ix = 0; ix < Factor; ix++)
2097         {
2098             TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
2099         }
2100     }
2101     else
2102     {
2103         for (ix = 1; ix < Factor; ix++)
2104         {
2105             FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
2106         }
2107     }
2108 
2109     RebalanceListEntries = USB2_FRAMES - 2;
2110 
2111     USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
2112                                   Rebalance,
2113                                   &RebalanceListEntries,
2114                                   USB2_FRAMES);
2115 
2116     RebalanceListEntries = 0;
2117 
2118     for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
2119     {
2120         RebalanceListEntries = ix + 1;
2121     }
2122 
2123     for (ix = 0; ix < RebalanceListEntries; ix++)
2124     {
2125         RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
2126 
2127         DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
2128                ix,
2129                RebalanceTtEndpoint,
2130                &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2131 
2132         InsertTailList(&RebalanceList,
2133                        &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2134     }
2135 
2136     ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2137 
2138     USB2_Rebalance(FdoDevice, &RebalanceList);
2139 
2140     if (!TtExtension)
2141         return;
2142 
2143     for (ix = 0; ix < USB2_FRAMES; ix++)
2144     {
2145         FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2146     }
2147 
2148     USBPORT_UpdateAllocatedBwTt(TtExtension);
2149 
2150     for (ix = 0; ix < USB2_FRAMES; ix++)
2151     {
2152         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2153     }
2154 
2155     DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
2156 }
2157 
2158 VOID
2159 NTAPI
USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,IN PUSB2_TT Tt)2160 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
2161             IN PUSB2_TT Tt)
2162 {
2163     ULONG ix;
2164     ULONG jx;
2165 
2166     DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
2167 
2168     Tt->HcExtension = HcExtension;
2169     Tt->DelayTime = 1;
2170     Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
2171 
2172     for (ix = 0; ix < USB2_FRAMES; ix++)
2173     {
2174         Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
2175         Tt->FrameBudget[ix].AltEndpoint = NULL;
2176 
2177         for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2178         {
2179             Tt->TimeCS[ix][jx] = 0;
2180             Tt->NumStartSplits[ix][jx] = 0;
2181         }
2182 
2183         Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
2184 
2185         USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
2186                             USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
2187                             USBPORT_TRANSFER_DIRECTION_OUT,
2188                             UsbFullSpeed,
2189                             USB2_FRAMES,
2190                             0,
2191                             Tt);
2192 
2193         Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
2194         Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2195         Tt->IsoEndpoint[ix].StartFrame = ix;
2196         Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2197 
2198         Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
2199 
2200         USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
2201                             USBPORT_TRANSFER_TYPE_INTERRUPT,
2202                             USBPORT_TRANSFER_DIRECTION_OUT,
2203                             UsbFullSpeed,
2204                             USB2_FRAMES,
2205                             0,
2206                             Tt);
2207 
2208         Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
2209         Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2210         Tt->IntEndpoint[ix].StartFrame = ix;
2211         Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2212     }
2213 }
2214 
2215 VOID
2216 NTAPI
USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)2217 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
2218 {
2219     ULONG ix;
2220     ULONG jx;
2221 
2222     DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
2223 
2224     HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
2225 
2226     for (ix = 0; ix < USB2_FRAMES; ix++)
2227     {
2228         for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2229         {
2230             HcExtension->TimeUsed[ix][jx] = 0;
2231         }
2232     }
2233 
2234     HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
2235 
2236     USB2_InitTT(HcExtension, &HcExtension->HcTt);
2237 }
2238