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