ReactOS  0.4.14-dev-297-g23e575c
usb2.c
Go to the documentation of this file.
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
20  IN ULONG CalcBusTime,
21  IN ULONG LimitAllocation)
22 {
23  ULONG BusTime;
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
41 {
42  return (DataTime + (DataTime / 16));
43 }
44 
45 VOID
46 NTAPI
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
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
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
121 {
122  ULONG TransferType;
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  {
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
169  IN PULONG OverheadSS,
170  IN PULONG OverheadCS)
171 {
172  ULONG TransferType;
174  ULONG HostDelay;
175 
176  TransferType = TtEndpoint->TtEndpointParams.TransferType;
177  Direction = TtEndpoint->TtEndpointParams.Direction;
178 
179  HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
180 
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
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  {
231  }
232 
233  return Result;
234 }
235 
236 ULONG
237 NTAPI
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
280  IN UCHAR TransferType,
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
311  IN LONG Frame)
312 {
313  PUSB2_HC_EXTENSION HcExtension;
314  PUSB2_TT Tt;
315  ULONG TransferType;
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  {
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,
388  {
389  Result = FALSE;
390  }
391 
392  if (Tt->NumStartSplits[frame][uframe] >
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,
414  {
415  Result = FALSE;
416  }
417 
418  USB2_IncMicroFrame(&frame, &uframe);
419  }
420 
421  PktSize = TtEndpoint->MaxPacketSize;
422  PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
423 
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 
439  DataTime = DataSize;
440  else
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,
452  {
453  Result = FALSE;
454  }
455 
456  USB2_IncMicroFrame(&frame, &uframe);
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,
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
509  IN ULONG Frame)
510 {
511  PUSB2_TT Tt;
512  PUSB2_HC_EXTENSION HcExtension;
513  ULONG OverheadCS;
514  ULONG OverheadSS;
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 
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 
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);
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
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 == 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
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
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
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
788 {
789  ULONG NumCompletes;
790  ULONG TransferType;
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  {
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
853 {
856  PUSBPORT_ENDPOINT Endpoint;
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  {
876 
877  Endpoint = CONTAINING_RECORD(Entry,
879  RebalanceLink.Flink);
880 
881  DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
882 
883  Endpoint->RebalanceLink.Flink = NULL;
884  Endpoint->RebalanceLink.Blink = NULL;
885 
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 
936  Endpoint->EndpointOldIrql);
937  }
938 }
939 
940 VOID
941 NTAPI
943  IN PLIST_ENTRY RebalanceList)
944 {
945  PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
946  PUSBPORT_ENDPOINT Endpoint;
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,
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  {
991  DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
992  ASSERT(FALSE);
993  break;
994 
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
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;
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  {
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
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,
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,
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
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
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
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
1800  IN PUSBPORT_ENDPOINT Endpoint)
1801 {
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;
1813  ULONG Period;
1814  ULONG AllocedBusTime;
1815  ULONG EndpointBandwidth;
1816  ULONG ScheduleOffset;
1817  ULONG Factor;
1818  ULONG ix;
1819  ULONG n;
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
2041  IN PUSBPORT_ENDPOINT Endpoint)
2042 {
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
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],
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],
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
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 }
#define USB2_MICROFRAMES
Definition: usbport.h:452
USB2_FRAME_BUDGET FrameBudget[USB2_FRAMES]
Definition: usbport.h:540
#define USB2_PREV_MICROFRAME
Definition: usbport.h:454
#define USBPORT_TRANSFER_TYPE_BULK
Definition: usbmport.h:9
#define IN
Definition: typedefs.h:38
PUSB2_TT_ENDPOINT TtEndpoint
Definition: usbport.h:209
#define max(a, b)
Definition: svc.c:63
#define USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD
Definition: usbport.h:479
#define TRUE
Definition: types.h:120
VOID NTAPI USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice, IN PUSBPORT_ENDPOINT Endpoint)
Definition: usb2.c:2040
#define USB2_FS_RAW_BYTES_IN_MICROFRAME
Definition: usbport.h:462
#define ENDPOINT_INTERRUPT_1ms
Definition: usbmport.h:25
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
struct _Entry Entry
Definition: kefuncs.h:640
#define USBPORT_TRANSFER_DIRECTION_OUT
Definition: usbmport.h:649
#define USB2_HS_ISOCHRONOUS_OUT_OVERHEAD
Definition: usbport.h:470
ULONG TimeUsed[USB2_FRAMES][USB2_MICROFRAMES]
Definition: usbport.h:564
VOID NTAPI USB2_IncMicroFrame(OUT PUCHAR frame, OUT PUCHAR uframe)
Definition: usb2.c:47
USHORT StartTime
Definition: usbport.h:520
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PUSB2_HC_EXTENSION HcExtension
Definition: usbport.h:535
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
VOID NTAPI USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint, IN ULONG Frame)
Definition: usb2.c:508
GLdouble n
Definition: glext.h:7729
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1268
ULONG MaxBandwidth
Definition: usbport.h:552
#define USB2_FS_INTERRUPT_OVERHEAD
Definition: usbport.h:466
#define USBPORT_TRANSFER_TYPE_CONTROL
Definition: usbmport.h:8
BOOLEAN NTAPI USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint, IN PUSB2_REBALANCE Rebalance, IN PULONG RebalanceListEntries)
Definition: usb2.c:1639
#define ENDPOINT_FLAG_ROOTHUB_EP0
Definition: usbport.h:111
#define InsertTailList(ListHead, Entry)
USB_DEVICE_SPEED DeviceSpeed
Definition: usbmport.h:73
USHORT NTAPI USB2_AddDataBitStuff(IN USHORT DataTime)
Definition: usb2.c:40
void DbgBreakPoint()
Definition: mach.c:553
static LARGE_INTEGER StartTime
Definition: sys_arch.c:18
ULONG NumStartSplits[USB2_FRAMES][USB2_MICROFRAMES]
Definition: usbport.h:541
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PUSB2_TT_EXTENSION TtExtension
Definition: usbport.h:208
uint32_t ULONG_PTR
Definition: typedefs.h:63
BOOLEAN NTAPI USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint, IN LONG BusTime, IN PUSB2_REBALANCE Rebalance, IN ULONG RebalanceListEntries, OUT BOOLEAN *OutResult)
Definition: usb2.c:619
#define USB_PORT_TAG
Definition: usbport.h:44
UCHAR KIRQL
Definition: env_spec_w32.h:591
USHORT ActualPeriod
Definition: usbport.h:518
VOID NTAPI USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice, IN PLIST_ENTRY RebalanceList)
Definition: usb2.c:942
UCHAR StartFrame
Definition: usbport.h:522
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define USB2_HS_SS_INTERRUPT_OUT_OVERHEAD
Definition: usbport.h:473
USB2_TT_ENDPOINT_PARAMS TtEndpointParams
Definition: usbport.h:512
#define USB2_FS_ISOCHRONOUS_OVERHEAD
Definition: usbport.h:469
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
KIRQL EndpointOldIrql
Definition: usbport.h:215
ULONG NTAPI USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint, IN ULONG Frame)
Definition: usb2.c:211
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define USB2_LS_INTERRUPT_OVERHEAD
Definition: usbport.h:465
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
UCHAR NTAPI USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: usb2.c:757
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
BOOLEAN NTAPI USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint, IN PUSB2_REBALANCE Rebalance, IN PULONG RebalanceListEntries)
Definition: usb2.c:1665
#define USB2_HUB_DELAY
Definition: usbport.h:460
ULONG Bandwidth[USB2_FRAMES]
Definition: usbport.h:551
PUSB2_TT_ENDPOINT IsoEndpoint
Definition: usbport.h:527
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
UCHAR NTAPI USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: usb2.c:787
PUSBPORT_ENDPOINT Endpoint
Definition: usbport.h:510
struct _USB2_TT_ENDPOINT * NextTtEndpoint
Definition: usbport.h:511
#define USB2_HS_SS_INTERRUPT_IN_OVERHEAD
Definition: usbport.h:475
VOID NTAPI USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension, IN PUSB2_TT Tt)
Definition: usb2.c:2160
#define USB2_CONTROLLER_DELAY
Definition: usbport.h:457
LIST_ENTRY List
Definition: psmgr.c:57
_Inout_ PSIZE_T _In_opt_ PMDLX _In_ MM_ROTATE_DIRECTION Direction
Definition: mmfuncs.h:773
#define USB2_HS_ISOCHRONOUS_IN_OVERHEAD
Definition: usbport.h:471
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct endpoint endpoint
Definition: nis.h:15
UCHAR StartMicroframe
Definition: usbport.h:523
#define USB2_HS_INTERRUPT_OUT_OVERHEAD
Definition: usbport.h:467
ULONG DelayTime
Definition: usbport.h:536
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define USB2_HS_CS_INTERRUPT_IN_OVERHEAD
Definition: usbport.h:476
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT PreviosPeriod
Definition: usbport.h:516
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN NTAPI USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint, IN PUSB2_REBALANCE Rebalance, IN PULONG RebalanceListEntries)
Definition: usb2.c:1290
#define USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME
Definition: usbport.h:461
#define USBPORT_TRANSFER_TYPE_INTERRUPT
Definition: usbmport.h:10
#define USB2_HS_CS_INTERRUPT_OUT_OVERHEAD
Definition: usbport.h:474
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
USHORT CalcBusTime
Definition: usbport.h:519
PUSB2_TT Tt
Definition: usbport.h:509
BOOLEAN NTAPI USB2_AllocateCheck(IN OUT PULONG OutTimeUsed, IN ULONG CalcBusTime, IN ULONG LimitAllocation)
Definition: usb2.c:19
BOOLEAN NTAPI USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint, IN LONG Frame)
Definition: usb2.c:310
VOID NTAPI USBPORT_DumpingEndpointProperties(IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties)
Definition: debug.c:281
Definition: typedefs.h:117
BOOLEAN NTAPI USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint, IN PUSB2_REBALANCE Rebalance, IN PULONG RebalanceListEntries, IN ULONG MaxFrames)
Definition: usb2.c:1026
#define USBPORT_TRANSFER_TYPE_ISOCHRONOUS
Definition: usbmport.h:7
PUSB2_TT_ENDPOINT AltEndpoint
Definition: usbport.h:529
#define USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD
Definition: usbport.h:478
VOID NTAPI USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice, IN PLIST_ENTRY List)
Definition: usb2.c:851
USBPORT_ENDPOINT_PROPERTIES EndpointProperties
Definition: usbport.h:210
VOID 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)
Definition: usb2.c:279
VOID NTAPI USB2_ConvertFrame(IN UCHAR Frame, IN UCHAR Microframe, OUT PUCHAR HcFrame, OUT PUCHAR HcMicroframe)
Definition: usb2.c:727
Definition: nis.h:10
PUSB2_TT_ENDPOINT RebalanceEndpoint[USB2_FRAMES - 2]
Definition: usbport.h:569
#define USB2_FS_SOF_TIME
Definition: usbport.h:459
LIST_ENTRY RebalanceLink
Definition: usbport.h:239
VOID NTAPI USBPORT_DumpingTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: debug.c:301
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
BOOLEAN NTAPI USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint, IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: usb2.c:704
ULONG NTAPI USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: usb2.c:120
#define USB2_MAX_MICROFRAMES
Definition: usbport.h:453
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define USB2_MAX_MICROFRAME_ALLOCATION
Definition: usbport.h:456
#define USB2_HS_INTERRUPT_IN_OVERHEAD
Definition: usbport.h:468
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
static const UCHAR CMASKS[USB2_MICROFRAMES]
Definition: usb2.c:13
VOID NTAPI USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
Definition: usb2.c:1768
#define DPRINT1
Definition: precomp.h:8
#define USB2_FRAMES
Definition: usbport.h:451
#define USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD
Definition: usbport.h:480
#define OUT
Definition: typedefs.h:39
VOID NTAPI USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
Definition: usb2.c:2217
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ULONG TimeCS[USB2_FRAMES][USB2_MICROFRAMES]
Definition: usbport.h:542
VOID NTAPI USB2_GetPrevMicroFrame(OUT PUCHAR frame, OUT PUCHAR uframe)
Definition: usb2.c:61
VOID NTAPI USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint, IN PULONG OverheadSS, IN PULONG OverheadCS)
Definition: usb2.c:168
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define USB2_FS_MAX_PERIODIC_ALLOCATION
Definition: usbport.h:458
BOOLEAN NTAPI USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint, IN PUSB2_TT_ENDPOINT TtEndpoint)
Definition: usb2.c:74
KSPIN_LOCK EndpointSpinLock
Definition: usbport.h:214
ULONG NTAPI USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint, IN PUSB2_TT_ENDPOINT TtEndpoint, IN PUSB2_TT_ENDPOINT prevTtEndpoint, IN ULONG Frame)
Definition: usb2.c:238
_In_ PUSBD_PIPE_INFORMATION _In_ USB_DEVICE_SPEED DeviceSpeed
Definition: hubbusif.h:294
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
base of all file and directory entries
Definition: entries.h:82
PUSB2_TT_ENDPOINT IntEndpoint
Definition: usbport.h:528
BOOLEAN NTAPI USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice, IN PUSBPORT_ENDPOINT Endpoint)
Definition: usb2.c:1799