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