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