[USBPORT] Use min(), max() macro.
[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 TransferType;
1061 ULONG Frame;
1062 ULONG StartMicroframe;
1063 ULONG ix;
1064 PUSB2_TT_ENDPOINT endpoint;
1065 PUSB2_TT_ENDPOINT nextEndpoint;
1066 PUSB2_TT_ENDPOINT lastEndpoint;
1067 PUSB2_TT_ENDPOINT tmpEndpoint;
1068 ULONG endTime;
1069 ULONG maxEndTime;
1070 ULONG lastEndTime;
1071 ULONG Factor;
1072 ULONG jx;
1073 UCHAR frame;
1074 UCHAR uframe;
1075 USHORT Period;
1076 BOOLEAN IsMoved = FALSE;
1077
1078 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
1079 TtEndpoint,
1080 MaxFrames,
1081 TtEndpoint->CalcBusTime);
1082
1083 if (TtEndpoint->CalcBusTime == 0)
1084 {
1085 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
1086 return FALSE;
1087 }
1088
1089 Tt = TtEndpoint->Tt;
1090 HcExtension = Tt->HcExtension;
1091
1092 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1093 DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
1094
1095 StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1096 TtEndpoint->StartMicroframe;
1097
1098 if (Speed == UsbHighSpeed)
1099 {
1100 for (ix = StartMicroframe;
1101 ix < USB2_MAX_MICROFRAMES;
1102 ix += TtEndpoint->ActualPeriod)
1103 {
1104 frame = ix / USB2_MICROFRAMES;
1105 uframe = ix % (USB2_MICROFRAMES - 1);
1106
1107 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1108 }
1109
1110 TtEndpoint->CalcBusTime = 0;
1111
1112 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1113 return TRUE;
1114 }
1115
1116 /* Speed != UsbHighSpeed (FS/LS) */
1117
1118 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1119
1120 for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
1121 ix > 0;
1122 ix--, Frame--)
1123 {
1124 frame = TtEndpoint->StartFrame + Frame;
1125
1126 DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
1127 frame,
1128 Frame,
1129 TtEndpoint->StartFrame);
1130
1131 if ((Frame % TtEndpoint->ActualPeriod) == 0)
1132 {
1133 USB2_DeallocateHS(TtEndpoint, Frame);
1134 Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
1135 }
1136
1137 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1138 {
1139 endpoint = Tt->FrameBudget[frame].IntEndpoint;
1140 }
1141 else
1142 {
1143 endpoint = Tt->FrameBudget[frame].IsoEndpoint;
1144 }
1145
1146 nextEndpoint = endpoint->NextTtEndpoint;
1147
1148 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
1149 TtEndpoint,
1150 nextEndpoint);
1151
1152 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1153 {
1154 while (nextEndpoint)
1155 {
1156 endpoint = nextEndpoint;
1157 nextEndpoint = nextEndpoint->NextTtEndpoint;
1158 }
1159
1160 nextEndpoint = TtEndpoint;
1161
1162 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1163 endpoint,
1164 nextEndpoint);
1165 }
1166 else
1167 {
1168 while (nextEndpoint &&
1169 !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1170 {
1171 endpoint = nextEndpoint;
1172 nextEndpoint = nextEndpoint->NextTtEndpoint;
1173 }
1174
1175 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
1176 nextEndpoint)
1177 {
1178 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1179 ASSERT(FALSE);
1180 }
1181
1182 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1183 endpoint,
1184 nextEndpoint);
1185 }
1186
1187 if ((Frame % TtEndpoint->ActualPeriod) == 0)
1188 {
1189 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1190 {
1191 Tt->FrameBudget[frame].AltEndpoint = NULL;
1192 }
1193 else if (nextEndpoint)
1194 {
1195 nextEndpoint = nextEndpoint->NextTtEndpoint;
1196 endpoint->NextTtEndpoint = nextEndpoint;
1197
1198 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1199 endpoint,
1200 nextEndpoint);
1201 }
1202 }
1203
1204 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1205 {
1206 if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
1207 {
1208 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1209 {
1210 endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1211 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
1212 }
1213 else if (Tt->FrameBudget[frame].AltEndpoint)
1214 {
1215 endpoint = Tt->FrameBudget[frame].AltEndpoint;
1216 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
1217 }
1218 }
1219 }
1220 else
1221 {
1222 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1223 ASSERT(FALSE);
1224 }
1225
1226 Period = TtEndpoint->ActualPeriod;
1227
1228 for (;
1229 nextEndpoint;
1230 endpoint = nextEndpoint,
1231 nextEndpoint = nextEndpoint->NextTtEndpoint)
1232 {
1233 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1234 endpoint,
1235 nextEndpoint);
1236
1237 endTime = endpoint->StartTime + endpoint->CalcBusTime;
1238 maxEndTime = endTime;
1239
1240 if (Period > nextEndpoint->ActualPeriod ||
1241 TtEndpoint->StartFrame != nextEndpoint->StartFrame)
1242 {
1243 if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
1244 Factor = Period / nextEndpoint->ActualPeriod;
1245 else
1246 Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
1247
1248 maxEndTime = endTime;
1249
1250 for (jx = 0, frame = nextEndpoint->StartFrame;
1251 jx < Factor;
1252 jx++, frame += nextEndpoint->ActualPeriod)
1253 {
1254 if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
1255 {
1256 lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1257
1258 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1259 {
1260 lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1261 }
1262 else if (Tt->FrameBudget[frame].AltEndpoint)
1263 {
1264 lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
1265 }
1266
1267 for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
1268 tmpEndpoint && tmpEndpoint != nextEndpoint;
1269 tmpEndpoint = tmpEndpoint->NextTtEndpoint)
1270 {
1271 lastEndpoint = tmpEndpoint;
1272 }
1273
1274 lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
1275
1276 if (endTime < (lastEndTime - 1))
1277 {
1278 maxEndTime = lastEndTime;
1279 endTime = maxEndTime;
1280
1281 if (nextEndpoint->StartTime == maxEndTime)
1282 break;
1283 }
1284 else
1285 {
1286 maxEndTime = endTime;
1287 }
1288 }
1289 }
1290 }
1291
1292 if (maxEndTime >= nextEndpoint->StartTime)
1293 break;
1294
1295 if (!USB2_MoveTtEndpoint(nextEndpoint,
1296 maxEndTime - nextEndpoint->StartTime,
1297 Rebalance,
1298 *RebalanceListEntries,
1299 &IsMoved))
1300 {
1301 if (!IsMoved)
1302 {
1303 DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
1304 }
1305
1306 break;
1307 }
1308
1309 if (Period > nextEndpoint->ActualPeriod)
1310 Period = nextEndpoint->ActualPeriod;
1311 }
1312 }
1313
1314 TtEndpoint->CalcBusTime = 0;
1315
1316 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1317 return TRUE;
1318 }
1319
1320 BOOLEAN
1321 NTAPI
1322 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
1323 IN PUSB2_REBALANCE Rebalance,
1324 IN PULONG RebalanceListEntries)
1325 {
1326 PUSB2_TT Tt;
1327 PUSB2_HC_EXTENSION HcExtension;
1328 ULONG Speed;
1329 ULONG TimeUsed;
1330 ULONG MinTimeUsed;
1331 ULONG ix;
1332 ULONG frame;
1333 ULONG uframe;
1334 ULONG Microframe;
1335 ULONG TransferType;
1336 ULONG Overhead;
1337 ULONG LatestStart;
1338 PUSB2_TT_ENDPOINT prevEndpoint;
1339 PUSB2_TT_ENDPOINT nextEndpoint;
1340 PUSB2_TT_ENDPOINT IntEndpoint;
1341 ULONG StartTime;
1342 ULONG calcBusTime;
1343 BOOLEAN Result = TRUE;
1344
1345 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
1346
1347 Tt = TtEndpoint->Tt;
1348 HcExtension = Tt->HcExtension;
1349
1350 TtEndpoint->Nums.NumStarts = 0;
1351 TtEndpoint->Nums.NumCompletes = 0;
1352
1353 TtEndpoint->StartFrame = 0;
1354 TtEndpoint->StartMicroframe = 0;
1355
1356 if (TtEndpoint->CalcBusTime)
1357 {
1358 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
1359 return FALSE;
1360 }
1361
1362 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1363
1364 if (Speed == UsbHighSpeed)
1365 {
1366 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
1367 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
1368 else
1369 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1370
1371 MinTimeUsed = HcExtension->TimeUsed[0][0];
1372
1373 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1374 {
1375 frame = ix / USB2_MICROFRAMES;
1376 uframe = ix % (USB2_MICROFRAMES - 1);
1377
1378 TimeUsed = HcExtension->TimeUsed[frame][uframe];
1379
1380 if (TimeUsed < MinTimeUsed)
1381 {
1382 MinTimeUsed = TimeUsed;
1383 TtEndpoint->StartFrame = frame;
1384 TtEndpoint->StartMicroframe = uframe;
1385 }
1386 }
1387
1388 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1389 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1390
1391 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1392 TtEndpoint->StartFrame,
1393 TtEndpoint->StartMicroframe,
1394 TtEndpoint->CalcBusTime);
1395
1396 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1397 TtEndpoint->StartMicroframe;
1398
1399 if (Microframe >= USB2_MAX_MICROFRAMES)
1400 {
1401 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1402 return TRUE;
1403 }
1404
1405 for (ix = Microframe;
1406 ix < USB2_MAX_MICROFRAMES;
1407 ix += TtEndpoint->ActualPeriod)
1408 {
1409 frame = ix / USB2_MICROFRAMES;
1410 uframe = ix % (USB2_MICROFRAMES - 1);
1411
1412 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1413 frame,
1414 uframe,
1415 HcExtension->TimeUsed[frame][uframe]);
1416
1417 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1418 TtEndpoint->CalcBusTime,
1419 USB2_MAX_MICROFRAME_ALLOCATION))
1420 {
1421 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1422 Result = FALSE;
1423 }
1424 }
1425
1426 if (!Result)
1427 {
1428 for (ix = Microframe;
1429 ix < USB2_MAX_MICROFRAMES;
1430 ix += TtEndpoint->ActualPeriod)
1431 {
1432 frame = ix / USB2_MICROFRAMES;
1433 uframe = ix % (USB2_MICROFRAMES - 1);
1434
1435 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1436 }
1437 }
1438
1439 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1440 return TRUE;
1441 }
1442
1443 /* Speed != UsbHighSpeed (FS/LS) */
1444
1445 if (TtEndpoint->Period > USB2_FRAMES)
1446 TtEndpoint->ActualPeriod = USB2_FRAMES;
1447 else
1448 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1449
1450 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1451
1452 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1453 {
1454 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1455 {
1456 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1457 TtEndpoint->StartFrame = ix;
1458 }
1459 }
1460
1461 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1462
1463 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1464 {
1465 if (Speed == UsbFullSpeed)
1466 {
1467 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1468 }
1469 else
1470 {
1471 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1472 return FALSE;
1473 }
1474 }
1475 else
1476 {
1477 if (Speed == UsbFullSpeed)
1478 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1479 else
1480 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1481 }
1482
1483 if (Speed == UsbLowSpeed)
1484 {
1485 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1486 }
1487 else
1488 {
1489 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1490 }
1491
1492 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1493
1494 for (ix = 0;
1495 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1496 ix += TtEndpoint->ActualPeriod)
1497 {
1498 frame = TtEndpoint->StartFrame + ix;
1499
1500 if (Tt->FrameBudget[frame].AltEndpoint &&
1501 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1502 {
1503 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1504 return FALSE;
1505 }
1506
1507 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1508 prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1509 else
1510 prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1511
1512 for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1513 nextEndpoint;
1514 nextEndpoint = nextEndpoint->NextTtEndpoint)
1515 {
1516 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1517 {
1518 break;
1519 }
1520
1521 prevEndpoint = nextEndpoint;
1522 }
1523
1524 StartTime = USB2_GetStartTime(nextEndpoint,
1525 TtEndpoint,
1526 prevEndpoint,
1527 frame);
1528
1529 if (StartTime > LatestStart)
1530 LatestStart = StartTime;
1531 }
1532
1533 TtEndpoint->StartTime = LatestStart;
1534
1535 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1536 {
1537 TtEndpoint->CalcBusTime = 0;
1538 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1539 return FALSE;
1540 }
1541
1542 for (ix = 0, frame = -TtEndpoint->StartFrame;
1543 ix < USB2_FRAMES;
1544 ix++, frame++)
1545 {
1546 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1547 ix,
1548 frame,
1549 TtEndpoint->StartFrame);
1550
1551 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1552 {
1553 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1554 ASSERT(FALSE);
1555 }
1556 else
1557 {
1558 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1559 nextEndpoint = IntEndpoint->NextTtEndpoint;
1560
1561 for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1562 nextEndpoint;
1563 nextEndpoint = nextEndpoint->NextTtEndpoint)
1564 {
1565 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1566 break;
1567 IntEndpoint = nextEndpoint;
1568 }
1569
1570 if ((frame % TtEndpoint->ActualPeriod) == 0)
1571 {
1572 calcBusTime = 0;
1573 }
1574 else
1575 {
1576 if (nextEndpoint)
1577 {
1578 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1579 nextEndpoint->StartTime;
1580 }
1581 else
1582 {
1583 calcBusTime = TtEndpoint->CalcBusTime;
1584 }
1585
1586 if (calcBusTime > 0)
1587 {
1588 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1589
1590 if (!USB2_AllocateCheck(&TimeUsed,
1591 calcBusTime,
1592 USB2_FS_MAX_PERIODIC_ALLOCATION))
1593 {
1594 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1595 Result = FALSE;
1596 }
1597 }
1598 }
1599
1600 if (nextEndpoint != TtEndpoint)
1601 {
1602 if ((frame % TtEndpoint->ActualPeriod) == 0)
1603 {
1604 if (frame == 0)
1605 {
1606 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1607 TtEndpoint->NextTtEndpoint = nextEndpoint;
1608 }
1609
1610 IntEndpoint->NextTtEndpoint = TtEndpoint;
1611
1612 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1613 TtEndpoint,
1614 nextEndpoint);
1615 }
1616
1617 if (calcBusTime > 0)
1618 {
1619 BOOLEAN IsMoved;
1620 BOOLEAN MoveResult;
1621
1622 DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1623 nextEndpoint,
1624 calcBusTime);
1625
1626 for (;
1627 nextEndpoint;
1628 nextEndpoint = nextEndpoint->NextTtEndpoint)
1629 {
1630 MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1631 calcBusTime,
1632 Rebalance,
1633 *RebalanceListEntries,
1634 &IsMoved);
1635
1636 if (!IsMoved)
1637 {
1638 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1639 Result = FALSE;
1640 }
1641
1642 if (!MoveResult)
1643 break;
1644 }
1645 }
1646 }
1647 }
1648
1649 if ((frame % TtEndpoint->ActualPeriod) == 0)
1650 {
1651 if (!USB2_AllocateHS(TtEndpoint, frame))
1652 {
1653 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1654 Result = FALSE;
1655 }
1656
1657 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1658 }
1659
1660 if (Result == FALSE)
1661 {
1662 USB2_DeallocateEndpointBudget(TtEndpoint,
1663 Rebalance,
1664 RebalanceListEntries,
1665 ix + 1);
1666
1667 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1668 return FALSE;
1669 }
1670 }
1671
1672 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1673 return Result;
1674 }
1675
1676 BOOLEAN
1677 NTAPI
1678 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
1679 IN PUSB2_REBALANCE Rebalance,
1680 IN PULONG RebalanceListEntries)
1681 {
1682 BOOLEAN Result;
1683
1684 DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
1685 *RebalanceListEntries);
1686
1687 USB2_DeallocateEndpointBudget(TtEndpoint,
1688 Rebalance,
1689 RebalanceListEntries,
1690 USB2_FRAMES);
1691
1692 TtEndpoint->PreviosPeriod = TtEndpoint->Period;
1693 TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1694
1695 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1696 Rebalance,
1697 RebalanceListEntries);
1698
1699 return Result;
1700 }
1701
1702 BOOLEAN
1703 NTAPI
1704 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1705 IN PUSB2_REBALANCE Rebalance,
1706 IN PULONG RebalanceListEntries)
1707 {
1708 PUSB2_TT_ENDPOINT ttEndpoint;
1709 ULONG TransferType;
1710 ULONG ix;
1711
1712 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1713
1714 if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1715 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1716 (CHAR)TtEndpoint->StartMicroframe > 2 &&
1717 !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
1718 {
1719 DPRINT("USB2_PromotePeriods: return FALSE\n");
1720 return FALSE;
1721 }
1722
1723 if (Rebalance->RebalanceEndpoint[0] == NULL)
1724 {
1725 DPRINT("USB2_PromotePeriods: return TRUE\n");
1726 return TRUE;
1727 }
1728
1729 DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
1730 *RebalanceListEntries);
1731
1732 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1733 {
1734 Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
1735 }
1736
1737 for (ix = 0; ; ix++)
1738 {
1739 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1740 TransferType = ttEndpoint->TtEndpointParams.TransferType;
1741
1742 if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1743 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1744 ttEndpoint->StartMicroframe > 2)
1745 {
1746 USB2_DeallocateEndpointBudget(ttEndpoint,
1747 Rebalance,
1748 RebalanceListEntries,
1749 USB2_FRAMES);
1750
1751 ttEndpoint->IsPromoted = TRUE;
1752 ttEndpoint->PreviosPeriod = ttEndpoint->Period;
1753 ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1754
1755 if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
1756 Rebalance,
1757 RebalanceListEntries))
1758 {
1759 break;
1760 }
1761 }
1762
1763 if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
1764 {
1765 DPRINT("USB2_PromotePeriods: return TRUE\n");
1766 return TRUE;
1767 }
1768 }
1769
1770 USB2_DeallocateEndpointBudget(TtEndpoint,
1771 Rebalance,
1772 RebalanceListEntries,
1773 USB2_FRAMES);
1774
1775 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1776 TtEndpoint->PreviosPeriod = 0;
1777
1778 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1779 {
1780 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1781
1782 if (ttEndpoint->IsPromoted)
1783 {
1784 if (ttEndpoint->CalcBusTime)
1785 {
1786 USB2_DeallocateEndpointBudget(ttEndpoint,
1787 Rebalance,
1788 RebalanceListEntries,
1789 USB2_FRAMES);
1790 }
1791
1792 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1793 TtEndpoint->PreviosPeriod = 0;
1794
1795 USB2_AllocateTimeForEndpoint(ttEndpoint,
1796 Rebalance,
1797 RebalanceListEntries);
1798 }
1799 }
1800
1801 DPRINT("USB2_PromotePeriods: return FALSE\n");
1802 return FALSE;
1803 }
1804
1805 VOID
1806 NTAPI
1807 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1808 {
1809 ULONG BusBandwidth;
1810 ULONG NewBusBandwidth;
1811 ULONG MaxBusBandwidth = 0;
1812 ULONG MinBusBandwidth;
1813 ULONG ix;
1814
1815 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1816
1817 BusBandwidth = TtExtension->BusBandwidth;
1818 MinBusBandwidth = BusBandwidth;
1819
1820 for (ix = 0; ix < USB2_FRAMES; ix++)
1821 {
1822 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1823
1824 MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
1825 MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
1826 }
1827
1828 TtExtension->MaxBandwidth = MaxBusBandwidth;
1829
1830 if (MinBusBandwidth == BusBandwidth)
1831 TtExtension->MinBandwidth = 0;
1832 else
1833 TtExtension->MinBandwidth = MinBusBandwidth;
1834 }
1835
1836 BOOLEAN
1837 NTAPI
1838 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1839 IN PUSBPORT_ENDPOINT Endpoint)
1840 {
1841 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1842 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1843 PUSB2_TT_EXTENSION TtExtension;
1844 ULONG TransferType;
1845 PUSB2_REBALANCE Rebalance;
1846 LIST_ENTRY RebalanceList;
1847 ULONG RebalanceListEntries;
1848 PUSB2_TT_ENDPOINT TtEndpoint;
1849 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1850 PUSB2_TT Tt;
1851 USB_DEVICE_SPEED DeviceSpeed;
1852 ULONG Period;
1853 ULONG AllocedBusTime;
1854 ULONG EndpointBandwidth;
1855 ULONG ScheduleOffset;
1856 ULONG Factor;
1857 ULONG ix;
1858 ULONG n;
1859 BOOLEAN Direction;
1860 UCHAR SMask;
1861 UCHAR CMask;
1862 UCHAR ActualPeriod;
1863 BOOLEAN Result;
1864
1865 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1866 FdoDevice,
1867 Endpoint);
1868
1869 EndpointProperties = &Endpoint->EndpointProperties;
1870 EndpointProperties->ScheduleOffset = 0;
1871
1872 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1873 {
1874 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1875 return TRUE;
1876 }
1877
1878 FdoExtension = FdoDevice->DeviceExtension;
1879
1880 TransferType = EndpointProperties->TransferType;
1881 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1882
1883 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1884 TransferType == USBPORT_TRANSFER_TYPE_BULK)
1885 {
1886 return TRUE;
1887 }
1888
1889 if (Endpoint->TtExtension)
1890 TtExtension = Endpoint->TtExtension;
1891 else
1892 TtExtension = NULL;
1893
1894 InitializeListHead(&RebalanceList);
1895
1896 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1897 sizeof(USB2_REBALANCE),
1898 USB_PORT_TAG);
1899
1900 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1901 Rebalance,
1902 TtExtension);
1903
1904 if (Rebalance)
1905 {
1906 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1907
1908 TtEndpoint = Endpoint->TtEndpoint;
1909 TtEndpoint->Endpoint = Endpoint;
1910
1911 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1912 DeviceSpeed = EndpointProperties->DeviceSpeed;
1913
1914 switch (DeviceSpeed)
1915 {
1916 case UsbLowSpeed:
1917 case UsbFullSpeed:
1918 {
1919 Tt = &TtExtension->Tt;
1920
1921 Period = USB2_FRAMES;
1922
1923 while (Period > 0 && Period > EndpointProperties->Period)
1924 {
1925 Period >>= 1;
1926 }
1927
1928 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1929 break;
1930 }
1931
1932 case UsbHighSpeed:
1933 {
1934 Tt = &FdoExtension->Usb2Extension->HcTt;
1935
1936 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1937 Period = USB2_MAX_MICROFRAMES;
1938 else
1939 Period = EndpointProperties->Period;
1940
1941 break;
1942 }
1943
1944 default:
1945 {
1946 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1947 DeviceSpeed);
1948
1949 DbgBreakPoint();
1950
1951 Tt = &TtExtension->Tt;
1952 break;
1953 }
1954 }
1955
1956 USB2_InitTtEndpoint(TtEndpoint,
1957 TransferType,
1958 Direction,
1959 DeviceSpeed,
1960 Period,
1961 EndpointProperties->MaxPacketSize,
1962 Tt);
1963
1964 RebalanceListEntries = USB2_FRAMES - 2;
1965
1966 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1967 Rebalance,
1968 &RebalanceListEntries);
1969
1970 if (Result)
1971 {
1972 Result = USB2_PromotePeriods(TtEndpoint,
1973 Rebalance,
1974 &RebalanceListEntries);
1975 }
1976
1977 RebalanceListEntries = 0;
1978
1979 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1980 {
1981 RebalanceListEntries = ix + 1;
1982 }
1983 }
1984 else
1985 {
1986 RebalanceListEntries = 0;
1987 Result = FALSE;
1988 }
1989
1990 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1991 RebalanceListEntries,
1992 Result);
1993
1994 for (ix = 0; ix < RebalanceListEntries; ix++)
1995 {
1996 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1997
1998 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1999 ix,
2000 RebalanceTtEndpoint,
2001 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2002
2003 InsertTailList(&RebalanceList,
2004 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2005 }
2006
2007 if (Rebalance)
2008 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2009
2010 if (Result)
2011 {
2012 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
2013 EndpointProperties->InterruptScheduleMask = SMask;
2014
2015 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
2016 EndpointProperties->SplitCompletionMask = CMask;
2017
2018 AllocedBusTime = TtEndpoint->CalcBusTime;
2019
2020 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
2021 EndpointProperties->UsbBandwidth = EndpointBandwidth;
2022
2023 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
2024 EndpointProperties->Period = ActualPeriod;
2025
2026 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
2027 EndpointProperties->ScheduleOffset = ScheduleOffset;
2028
2029 Factor = USB2_FRAMES / ActualPeriod;
2030 ASSERT(Factor);
2031
2032 n = ScheduleOffset * Factor;
2033
2034 if (TtExtension)
2035 {
2036 for (ix = 0; ix < Factor; ix++)
2037 {
2038 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2039 }
2040 }
2041 else
2042 {
2043 for (ix = 1; ix < Factor; ix++)
2044 {
2045 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2046 }
2047 }
2048
2049 USBPORT_DumpingEndpointProperties(EndpointProperties);
2050 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
2051
2052 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
2053 {
2054 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
2055 }
2056 }
2057
2058 USB2_Rebalance(FdoDevice, &RebalanceList);
2059
2060 if (!TtExtension)
2061 {
2062 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2063 return Result;
2064 }
2065
2066 for (ix = 0; ix < USB2_FRAMES; ix++)
2067 {
2068 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2069 }
2070
2071 USBPORT_UpdateAllocatedBwTt(TtExtension);
2072
2073 for (ix = 0; ix < USB2_FRAMES; ix++)
2074 {
2075 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2076 }
2077
2078 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2079
2080 return Result;
2081 }
2082
2083 VOID
2084 NTAPI
2085 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
2086 IN PUSBPORT_ENDPOINT Endpoint)
2087 {
2088 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2089 ULONG Period;
2090 ULONG ScheduleOffset;
2091 ULONG EndpointBandwidth;
2092 LIST_ENTRY RebalanceList;
2093 ULONG TransferType;
2094 PUSB2_REBALANCE Rebalance;
2095 ULONG RebalanceListEntries;
2096 ULONG Factor;
2097 ULONG ix;
2098 ULONG n;
2099 PUSB2_TT_EXTENSION TtExtension;
2100 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
2101
2102 DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
2103
2104 FdoExtension = FdoDevice->DeviceExtension;
2105
2106 Period = Endpoint->EndpointProperties.Period;
2107 ASSERT(Period != 0);
2108
2109 ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
2110 EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
2111
2112 InitializeListHead(&RebalanceList);
2113
2114 TransferType = Endpoint->EndpointProperties.TransferType;
2115
2116 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2117 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2118 (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
2119 {
2120 return;
2121 }
2122
2123 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
2124 sizeof(USB2_REBALANCE),
2125 USB_PORT_TAG);
2126
2127 if (!Rebalance)
2128 {
2129 DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
2130 return;
2131 }
2132
2133 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
2134
2135 Factor = USB2_FRAMES / Period;
2136 n = ScheduleOffset * Factor;
2137
2138 TtExtension = Endpoint->TtExtension;
2139
2140 if (TtExtension)
2141 {
2142 for (ix = 0; ix < Factor; ix++)
2143 {
2144 TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
2145 }
2146 }
2147 else
2148 {
2149 for (ix = 1; ix < Factor; ix++)
2150 {
2151 FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
2152 }
2153 }
2154
2155 RebalanceListEntries = USB2_FRAMES - 2;
2156
2157 USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
2158 Rebalance,
2159 &RebalanceListEntries,
2160 USB2_FRAMES);
2161
2162 RebalanceListEntries = 0;
2163
2164 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
2165 {
2166 RebalanceListEntries = ix + 1;
2167 }
2168
2169 for (ix = 0; ix < RebalanceListEntries; ix++)
2170 {
2171 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
2172
2173 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
2174 ix,
2175 RebalanceTtEndpoint,
2176 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2177
2178 InsertTailList(&RebalanceList,
2179 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2180 }
2181
2182 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2183
2184 USB2_Rebalance(FdoDevice, &RebalanceList);
2185
2186 if (!TtExtension)
2187 {
2188 return;
2189 }
2190
2191 for (ix = 0; ix < USB2_FRAMES; ix++)
2192 {
2193 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2194 }
2195
2196 USBPORT_UpdateAllocatedBwTt(TtExtension);
2197
2198 for (ix = 0; ix < USB2_FRAMES; ix++)
2199 {
2200 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2201 }
2202
2203 DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
2204 }
2205
2206 VOID
2207 NTAPI
2208 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
2209 IN PUSB2_TT Tt)
2210 {
2211 ULONG ix;
2212 ULONG jx;
2213
2214 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
2215
2216 Tt->HcExtension = HcExtension;
2217 Tt->DelayTime = 1;
2218 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
2219
2220 for (ix = 0; ix < USB2_FRAMES; ix++)
2221 {
2222 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
2223 Tt->FrameBudget[ix].AltEndpoint = NULL;
2224
2225 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2226 {
2227 Tt->TimeCS[ix][jx] = 0;
2228 Tt->NumStartSplits[ix][jx] = 0;
2229 }
2230
2231 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
2232
2233 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
2234 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
2235 USBPORT_TRANSFER_DIRECTION_OUT,
2236 UsbFullSpeed,
2237 USB2_FRAMES,
2238 0,
2239 Tt);
2240
2241 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
2242 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2243 Tt->IsoEndpoint[ix].StartFrame = ix;
2244 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
2245
2246 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
2247
2248 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
2249 USBPORT_TRANSFER_TYPE_INTERRUPT,
2250 USBPORT_TRANSFER_DIRECTION_OUT,
2251 UsbFullSpeed,
2252 USB2_FRAMES,
2253 0,
2254 Tt);
2255
2256 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
2257 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2258 Tt->IntEndpoint[ix].StartFrame = ix;
2259 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
2260 }
2261 }
2262
2263 VOID
2264 NTAPI
2265 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
2266 {
2267 ULONG ix;
2268 ULONG jx;
2269
2270 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
2271
2272 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
2273
2274 for (ix = 0; ix < USB2_FRAMES; ix++)
2275 {
2276 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2277 {
2278 HcExtension->TimeUsed[ix][jx] = 0;
2279 }
2280 }
2281
2282 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
2283
2284 USB2_InitTT(HcExtension, &HcExtension->HcTt);
2285 }