77cbd57b4b8cc39bdcc4e2eafa2afb205874a84e
[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.DeviceSpeed;
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_INTERRUPT_IN_OVERHEAD;
149 }
150 }
151 else if (DeviceSpeed == UsbFullSpeed)
152 {
153 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
154 Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
155 else
156 Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
157 }
158 else
159 {
160 Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
161 }
162
163 return Overhead;
164 }
165
166 VOID
167 NTAPI
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 == USB2_PREV_MICROFRAME)
381 USB2_GetPrevMicroFrame(&frame, &uframe);
382
383 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
384 {
385 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
386 OverheadSS,
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 == USB2_PREV_MICROFRAME)
430 USB2_GetPrevMicroFrame(&frame, &uframe);
431
432 DataTime = 0;
433
434 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
435 {
436 DataSize = PktSizeBitStuff - DataTime;
437
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 == USB2_PREV_MICROFRAME)
539 USB2_GetPrevMicroFrame(&frame, &uframe);
540
541 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
542 {
543 HcExtension->TimeUsed[frame][uframe] -= OverheadSS;
544 --Tt->NumStartSplits[frame][uframe];
545 USB2_IncMicroFrame(&frame, &uframe);
546 }
547
548 frame = TtEndpoint->StartFrame + Frame;
549 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
550
551 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
552 {
553 HcExtension->TimeUsed[frame][uframe] -= OverheadCS;
554 USB2_IncMicroFrame(&frame, &uframe);
555 }
556
557 Direction = TtEndpoint->TtEndpointParams.Direction;
558 PktSize = TtEndpoint->MaxPacketSize;
559 PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
560
561 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
562 {
563 frame = TtEndpoint->StartFrame + Frame;
564 uframe = TtEndpoint->StartMicroframe;
565
566 if (TtEndpoint->StartMicroframe == USB2_PREV_MICROFRAME)
567 USB2_GetPrevMicroFrame(&frame, &uframe);
568
569 DataTime = 0;
570
571 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
572 {
573 DataSize = PktSizeBitStuff - DataTime;
574
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 LONG BusTime,
621 IN PUSB2_REBALANCE Rebalance,
622 IN ULONG RebalanceListEntries,
623 OUT BOOLEAN * OutResult)
624 {
625 ULONG EndBusTime;
626 ULONG TransferType;
627 ULONG Num;
628 UCHAR ix;
629
630 DPRINT("USB2_MoveTtEndpoint: TtEndpoint - %p, BusTime - %X\n",
631 TtEndpoint,
632 BusTime);
633
634 *OutResult = TRUE;
635
636 for (Num = 0; Rebalance->RebalanceEndpoint[Num]; Num++)
637 {
638 if (Rebalance->RebalanceEndpoint[Num] == TtEndpoint)
639 break;
640 }
641
642 DPRINT("USB2_MoveTtEndpoint: Num - %X\n", Num);
643
644 TransferType = TtEndpoint->TtEndpointParams.TransferType;
645
646 if (Rebalance->RebalanceEndpoint[Num] &&
647 TtEndpoint->TtEndpointParams.EndpointMoved == TRUE &&
648 ((TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT) || BusTime >= 0))
649 {
650 DPRINT("USB2_MoveTtEndpoint: result - FALSE\n");
651 return FALSE;
652 }
653
654 for (ix = 0;
655 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
656 ix += TtEndpoint->ActualPeriod)
657 {
658 USB2_DeallocateHS(TtEndpoint, ix);
659 }
660
661 TtEndpoint->StartTime += BusTime;
662
663 EndBusTime = TtEndpoint->StartTime + TtEndpoint->CalcBusTime;
664
665 if (EndBusTime > USB2_FS_MAX_PERIODIC_ALLOCATION)
666 {
667 DPRINT("USB2_MoveTtEndpoint: EndBusTime is too large!\n");
668 *OutResult = FALSE;
669 }
670
671 TtEndpoint->TtEndpointParams.EndpointMoved = TRUE;
672
673 if (Rebalance->RebalanceEndpoint[Num] == NULL)
674 {
675 if (Num >= RebalanceListEntries)
676 {
677 DPRINT("USB2_MoveTtEndpoint: Too many changes!\n");
678 *OutResult = FALSE;
679 }
680 else
681 {
682 Rebalance->RebalanceEndpoint[Num] = TtEndpoint;
683 Rebalance->RebalanceEndpoint[Num + 1] = NULL;
684 }
685 }
686
687 for (ix = 0;
688 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
689 ix += TtEndpoint->ActualPeriod)
690 {
691 if (!USB2_AllocateHS(TtEndpoint, ix))
692 {
693 DPRINT("USB2_MoveTtEndpoint: OutResult - FALSE\n");
694 OutResult = FALSE;
695 }
696 }
697
698 DPRINT("USB2_MoveTtEndpoint: result - TRUE\n");
699 return TRUE;
700 }
701
702 BOOLEAN
703 NTAPI
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 == USB2_PREV_MICROFRAME)
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 }
1183 else if (Tt->FrameBudget[frame].AltEndpoint)
1184 {
1185 endpoint = Tt->FrameBudget[frame].AltEndpoint;
1186 }
1187 }
1188 }
1189 else
1190 {
1191 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1192 ASSERT(FALSE);
1193 }
1194
1195 Period = TtEndpoint->ActualPeriod;
1196
1197 for (;
1198 nextEndpoint;
1199 endpoint = nextEndpoint,
1200 nextEndpoint = nextEndpoint->NextTtEndpoint)
1201 {
1202 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1203 endpoint,
1204 nextEndpoint);
1205
1206 endTime = endpoint->StartTime + endpoint->CalcBusTime;
1207 maxEndTime = endTime;
1208
1209 if (Period > nextEndpoint->ActualPeriod ||
1210 TtEndpoint->StartFrame != nextEndpoint->StartFrame)
1211 {
1212 if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
1213 Factor = Period / nextEndpoint->ActualPeriod;
1214 else
1215 Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
1216
1217 maxEndTime = endTime;
1218
1219 for (jx = 0, frame = nextEndpoint->StartFrame;
1220 jx < Factor;
1221 jx++, frame += nextEndpoint->ActualPeriod)
1222 {
1223 if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
1224 {
1225 lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1226
1227 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1228 {
1229 lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1230 }
1231 else if (Tt->FrameBudget[frame].AltEndpoint)
1232 {
1233 lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
1234 }
1235
1236 for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
1237 tmpEndpoint && tmpEndpoint != nextEndpoint;
1238 tmpEndpoint = tmpEndpoint->NextTtEndpoint)
1239 {
1240 lastEndpoint = tmpEndpoint;
1241 }
1242
1243 lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
1244
1245 if (endTime < (lastEndTime - 1))
1246 {
1247 maxEndTime = lastEndTime;
1248 endTime = maxEndTime;
1249
1250 if (nextEndpoint->StartTime == maxEndTime)
1251 break;
1252 }
1253 else
1254 {
1255 maxEndTime = endTime;
1256 }
1257 }
1258 }
1259 }
1260
1261 if (maxEndTime >= nextEndpoint->StartTime)
1262 break;
1263
1264 if (!USB2_MoveTtEndpoint(nextEndpoint,
1265 maxEndTime - nextEndpoint->StartTime,
1266 Rebalance,
1267 *RebalanceListEntries,
1268 &IsMoved))
1269 {
1270 if (!IsMoved)
1271 {
1272 DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
1273 }
1274
1275 break;
1276 }
1277
1278 if (Period > nextEndpoint->ActualPeriod)
1279 Period = nextEndpoint->ActualPeriod;
1280 }
1281 }
1282
1283 TtEndpoint->CalcBusTime = 0;
1284
1285 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1286 return TRUE;
1287 }
1288
1289 BOOLEAN
1290 NTAPI
1291 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
1292 IN PUSB2_REBALANCE Rebalance,
1293 IN PULONG RebalanceListEntries)
1294 {
1295 PUSB2_TT Tt;
1296 PUSB2_HC_EXTENSION HcExtension;
1297 ULONG Speed;
1298 ULONG TimeUsed;
1299 ULONG MinTimeUsed;
1300 ULONG ix;
1301 ULONG frame;
1302 ULONG uframe;
1303 ULONG Microframe;
1304 ULONG TransferType;
1305 ULONG Overhead;
1306 ULONG LatestStart;
1307 PUSB2_TT_ENDPOINT prevEndpoint;
1308 PUSB2_TT_ENDPOINT nextEndpoint;
1309 PUSB2_TT_ENDPOINT IntEndpoint;
1310 ULONG StartTime;
1311 ULONG calcBusTime;
1312 BOOLEAN Result = TRUE;
1313
1314 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
1315
1316 Tt = TtEndpoint->Tt;
1317 HcExtension = Tt->HcExtension;
1318
1319 TtEndpoint->Nums.NumStarts = 0;
1320 TtEndpoint->Nums.NumCompletes = 0;
1321
1322 TtEndpoint->StartFrame = 0;
1323 TtEndpoint->StartMicroframe = 0;
1324
1325 if (TtEndpoint->CalcBusTime)
1326 {
1327 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
1328 return FALSE;
1329 }
1330
1331 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1332
1333 if (Speed == UsbHighSpeed)
1334 {
1335 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
1336 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
1337 else
1338 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1339
1340 MinTimeUsed = HcExtension->TimeUsed[0][0];
1341
1342 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1343 {
1344 frame = ix / USB2_MICROFRAMES;
1345 uframe = ix % (USB2_MICROFRAMES - 1);
1346
1347 TimeUsed = HcExtension->TimeUsed[frame][uframe];
1348
1349 if (TimeUsed < MinTimeUsed)
1350 {
1351 MinTimeUsed = TimeUsed;
1352 TtEndpoint->StartFrame = frame;
1353 TtEndpoint->StartMicroframe = uframe;
1354 }
1355 }
1356
1357 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1358 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1359
1360 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1361 TtEndpoint->StartFrame,
1362 TtEndpoint->StartMicroframe,
1363 TtEndpoint->CalcBusTime);
1364
1365 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1366 TtEndpoint->StartMicroframe;
1367
1368 if (Microframe >= USB2_MAX_MICROFRAMES)
1369 {
1370 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1371 return TRUE;
1372 }
1373
1374 for (ix = Microframe;
1375 ix < USB2_MAX_MICROFRAMES;
1376 ix += TtEndpoint->ActualPeriod)
1377 {
1378 frame = ix / USB2_MICROFRAMES;
1379 uframe = ix % (USB2_MICROFRAMES - 1);
1380
1381 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1382 frame,
1383 uframe,
1384 HcExtension->TimeUsed[frame][uframe]);
1385
1386 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1387 TtEndpoint->CalcBusTime,
1388 USB2_MAX_MICROFRAME_ALLOCATION))
1389 {
1390 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1391 Result = FALSE;
1392 }
1393 }
1394
1395 if (!Result)
1396 {
1397 for (ix = Microframe;
1398 ix < USB2_MAX_MICROFRAMES;
1399 ix += TtEndpoint->ActualPeriod)
1400 {
1401 frame = ix / USB2_MICROFRAMES;
1402 uframe = ix % (USB2_MICROFRAMES - 1);
1403
1404 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1405 }
1406 }
1407
1408 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1409 return TRUE;
1410 }
1411
1412 /* Speed != UsbHighSpeed (FS/LS) */
1413
1414 if (TtEndpoint->Period > USB2_FRAMES)
1415 TtEndpoint->ActualPeriod = USB2_FRAMES;
1416 else
1417 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1418
1419 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1420
1421 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1422 {
1423 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1424 {
1425 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1426 TtEndpoint->StartFrame = ix;
1427 }
1428 }
1429
1430 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1431
1432 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1433 {
1434 if (Speed == UsbFullSpeed)
1435 {
1436 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1437 }
1438 else
1439 {
1440 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1441 return FALSE;
1442 }
1443 }
1444 else
1445 {
1446 if (Speed == UsbFullSpeed)
1447 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1448 else
1449 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1450 }
1451
1452 if (Speed == UsbLowSpeed)
1453 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1454 else
1455 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1456
1457 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1458
1459 for (ix = 0;
1460 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1461 ix += TtEndpoint->ActualPeriod)
1462 {
1463 frame = TtEndpoint->StartFrame + ix;
1464
1465 if (Tt->FrameBudget[frame].AltEndpoint &&
1466 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1467 {
1468 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1469 return FALSE;
1470 }
1471
1472 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1473 prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1474 else
1475 prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1476
1477 for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1478 nextEndpoint;
1479 nextEndpoint = nextEndpoint->NextTtEndpoint)
1480 {
1481 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1482 break;
1483
1484 prevEndpoint = nextEndpoint;
1485 }
1486
1487 StartTime = USB2_GetStartTime(nextEndpoint,
1488 TtEndpoint,
1489 prevEndpoint,
1490 frame);
1491
1492 LatestStart = max(LatestStart, StartTime);
1493 }
1494
1495 TtEndpoint->StartTime = LatestStart;
1496
1497 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1498 {
1499 TtEndpoint->CalcBusTime = 0;
1500 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1501 return FALSE;
1502 }
1503
1504 for (ix = 0, frame = -TtEndpoint->StartFrame;
1505 ix < USB2_FRAMES;
1506 ix++, frame++)
1507 {
1508 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1509 ix,
1510 frame,
1511 TtEndpoint->StartFrame);
1512
1513 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1514 {
1515 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1516 ASSERT(FALSE);
1517 }
1518 else
1519 {
1520 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1521 nextEndpoint = IntEndpoint->NextTtEndpoint;
1522
1523 for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1524 nextEndpoint;
1525 nextEndpoint = nextEndpoint->NextTtEndpoint)
1526 {
1527 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1528 break;
1529 IntEndpoint = nextEndpoint;
1530 }
1531
1532 if ((frame % TtEndpoint->ActualPeriod) == 0)
1533 {
1534 calcBusTime = 0;
1535 }
1536 else
1537 {
1538 if (nextEndpoint)
1539 {
1540 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1541 nextEndpoint->StartTime;
1542 }
1543 else
1544 {
1545 calcBusTime = TtEndpoint->CalcBusTime;
1546 }
1547
1548 if (calcBusTime > 0)
1549 {
1550 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1551
1552 if (!USB2_AllocateCheck(&TimeUsed,
1553 calcBusTime,
1554 USB2_FS_MAX_PERIODIC_ALLOCATION))
1555 {
1556 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1557 Result = FALSE;
1558 }
1559 }
1560 }
1561
1562 if (nextEndpoint != TtEndpoint)
1563 {
1564 if ((frame % TtEndpoint->ActualPeriod) == 0)
1565 {
1566 if (frame == 0)
1567 {
1568 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1569 TtEndpoint->NextTtEndpoint = nextEndpoint;
1570 }
1571
1572 IntEndpoint->NextTtEndpoint = TtEndpoint;
1573
1574 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1575 TtEndpoint,
1576 nextEndpoint);
1577 }
1578
1579 if (calcBusTime > 0)
1580 {
1581 BOOLEAN IsMoved;
1582 BOOLEAN MoveResult;
1583
1584 DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1585 nextEndpoint,
1586 calcBusTime);
1587
1588 for (;
1589 nextEndpoint;
1590 nextEndpoint = nextEndpoint->NextTtEndpoint)
1591 {
1592 MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1593 calcBusTime,
1594 Rebalance,
1595 *RebalanceListEntries,
1596 &IsMoved);
1597
1598 if (!IsMoved)
1599 {
1600 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1601 Result = FALSE;
1602 }
1603
1604 if (!MoveResult)
1605 break;
1606 }
1607 }
1608 }
1609 }
1610
1611 if ((frame % TtEndpoint->ActualPeriod) == 0)
1612 {
1613 if (!USB2_AllocateHS(TtEndpoint, frame))
1614 {
1615 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1616 Result = FALSE;
1617 }
1618
1619 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1620 }
1621
1622 if (Result == FALSE)
1623 {
1624 USB2_DeallocateEndpointBudget(TtEndpoint,
1625 Rebalance,
1626 RebalanceListEntries,
1627 ix + 1);
1628
1629 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1630 return FALSE;
1631 }
1632 }
1633
1634 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1635 return Result;
1636 }
1637
1638 BOOLEAN
1639 NTAPI
1640 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
1641 IN PUSB2_REBALANCE Rebalance,
1642 IN PULONG RebalanceListEntries)
1643 {
1644 BOOLEAN Result;
1645
1646 DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
1647 *RebalanceListEntries);
1648
1649 USB2_DeallocateEndpointBudget(TtEndpoint,
1650 Rebalance,
1651 RebalanceListEntries,
1652 USB2_FRAMES);
1653
1654 TtEndpoint->PreviosPeriod = TtEndpoint->Period;
1655 TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1656
1657 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1658 Rebalance,
1659 RebalanceListEntries);
1660
1661 return Result;
1662 }
1663
1664 BOOLEAN
1665 NTAPI
1666 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1667 IN PUSB2_REBALANCE Rebalance,
1668 IN PULONG RebalanceListEntries)
1669 {
1670 PUSB2_TT_ENDPOINT ttEndpoint;
1671 ULONG TransferType;
1672 ULONG ix;
1673
1674 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1675
1676 if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1677 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1678 (CHAR)TtEndpoint->StartMicroframe > 2 &&
1679 !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
1680 {
1681 DPRINT("USB2_PromotePeriods: return FALSE\n");
1682 return FALSE;
1683 }
1684
1685 if (Rebalance->RebalanceEndpoint[0] == NULL)
1686 {
1687 DPRINT("USB2_PromotePeriods: return TRUE\n");
1688 return TRUE;
1689 }
1690
1691 DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
1692 *RebalanceListEntries);
1693
1694 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1695 {
1696 Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
1697 }
1698
1699 for (ix = 0; ; ix++)
1700 {
1701 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1702 TransferType = ttEndpoint->TtEndpointParams.TransferType;
1703
1704 if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1705 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1706 (CHAR)ttEndpoint->StartMicroframe > 2)
1707 {
1708 USB2_DeallocateEndpointBudget(ttEndpoint,
1709 Rebalance,
1710 RebalanceListEntries,
1711 USB2_FRAMES);
1712
1713 ttEndpoint->IsPromoted = TRUE;
1714 ttEndpoint->PreviosPeriod = ttEndpoint->Period;
1715 ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1716
1717 if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
1718 Rebalance,
1719 RebalanceListEntries))
1720 {
1721 break;
1722 }
1723 }
1724
1725 if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
1726 {
1727 DPRINT("USB2_PromotePeriods: return TRUE\n");
1728 return TRUE;
1729 }
1730 }
1731
1732 USB2_DeallocateEndpointBudget(TtEndpoint,
1733 Rebalance,
1734 RebalanceListEntries,
1735 USB2_FRAMES);
1736
1737 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1738 TtEndpoint->PreviosPeriod = 0;
1739
1740 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1741 {
1742 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1743
1744 if (ttEndpoint->IsPromoted)
1745 {
1746 if (ttEndpoint->CalcBusTime)
1747 {
1748 USB2_DeallocateEndpointBudget(ttEndpoint,
1749 Rebalance,
1750 RebalanceListEntries,
1751 USB2_FRAMES);
1752 }
1753
1754 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1755 TtEndpoint->PreviosPeriod = 0;
1756
1757 USB2_AllocateTimeForEndpoint(ttEndpoint,
1758 Rebalance,
1759 RebalanceListEntries);
1760 }
1761 }
1762
1763 DPRINT("USB2_PromotePeriods: return FALSE\n");
1764 return FALSE;
1765 }
1766
1767 VOID
1768 NTAPI
1769 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1770 {
1771 ULONG BusBandwidth;
1772 ULONG NewBusBandwidth;
1773 ULONG MaxBusBandwidth = 0;
1774 ULONG MinBusBandwidth;
1775 ULONG ix;
1776
1777 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1778
1779 BusBandwidth = TtExtension->BusBandwidth;
1780 MinBusBandwidth = BusBandwidth;
1781
1782 for (ix = 0; ix < USB2_FRAMES; ix++)
1783 {
1784 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1785
1786 MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
1787 MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
1788 }
1789
1790 TtExtension->MaxBandwidth = MaxBusBandwidth;
1791
1792 if (MinBusBandwidth == BusBandwidth)
1793 TtExtension->MinBandwidth = 0;
1794 else
1795 TtExtension->MinBandwidth = MinBusBandwidth;
1796 }
1797
1798 BOOLEAN
1799 NTAPI
1800 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1801 IN PUSBPORT_ENDPOINT Endpoint)
1802 {
1803 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1804 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1805 PUSB2_TT_EXTENSION TtExtension;
1806 ULONG TransferType;
1807 PUSB2_REBALANCE Rebalance;
1808 LIST_ENTRY RebalanceList;
1809 ULONG RebalanceListEntries;
1810 PUSB2_TT_ENDPOINT TtEndpoint;
1811 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1812 PUSB2_TT Tt;
1813 USB_DEVICE_SPEED DeviceSpeed;
1814 ULONG Period;
1815 ULONG AllocedBusTime;
1816 ULONG EndpointBandwidth;
1817 ULONG ScheduleOffset;
1818 ULONG Factor;
1819 ULONG ix;
1820 ULONG n;
1821 BOOLEAN Direction;
1822 UCHAR SMask;
1823 UCHAR CMask;
1824 UCHAR ActualPeriod;
1825 BOOLEAN Result;
1826
1827 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1828 FdoDevice,
1829 Endpoint);
1830
1831 EndpointProperties = &Endpoint->EndpointProperties;
1832 EndpointProperties->ScheduleOffset = 0;
1833
1834 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1835 {
1836 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1837 return TRUE;
1838 }
1839
1840 FdoExtension = FdoDevice->DeviceExtension;
1841
1842 TransferType = EndpointProperties->TransferType;
1843 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1844
1845 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1846 TransferType == USBPORT_TRANSFER_TYPE_BULK)
1847 {
1848 return TRUE;
1849 }
1850
1851 if (Endpoint->TtExtension)
1852 TtExtension = Endpoint->TtExtension;
1853 else
1854 TtExtension = NULL;
1855
1856 InitializeListHead(&RebalanceList);
1857
1858 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1859 sizeof(USB2_REBALANCE),
1860 USB_PORT_TAG);
1861
1862 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1863 Rebalance,
1864 TtExtension);
1865
1866 if (Rebalance)
1867 {
1868 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1869
1870 TtEndpoint = Endpoint->TtEndpoint;
1871 TtEndpoint->Endpoint = Endpoint;
1872
1873 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1874 DeviceSpeed = EndpointProperties->DeviceSpeed;
1875
1876 switch (DeviceSpeed)
1877 {
1878 case UsbLowSpeed:
1879 case UsbFullSpeed:
1880 {
1881 Tt = &TtExtension->Tt;
1882 Period = USB2_FRAMES;
1883
1884 while (Period > 0 && Period > EndpointProperties->Period)
1885 {
1886 Period >>= 1;
1887 }
1888
1889 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1890 break;
1891 }
1892
1893 case UsbHighSpeed:
1894 {
1895 Tt = &FdoExtension->Usb2Extension->HcTt;
1896
1897 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1898 Period = USB2_MAX_MICROFRAMES;
1899 else
1900 Period = EndpointProperties->Period;
1901
1902 break;
1903 }
1904
1905 default:
1906 {
1907 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1908 DeviceSpeed);
1909
1910 DbgBreakPoint();
1911
1912 Tt = &TtExtension->Tt;
1913 break;
1914 }
1915 }
1916
1917 USB2_InitTtEndpoint(TtEndpoint,
1918 TransferType,
1919 Direction,
1920 DeviceSpeed,
1921 Period,
1922 EndpointProperties->MaxPacketSize,
1923 Tt);
1924
1925 RebalanceListEntries = USB2_FRAMES - 2;
1926
1927 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1928 Rebalance,
1929 &RebalanceListEntries);
1930
1931 if (Result)
1932 {
1933 Result = USB2_PromotePeriods(TtEndpoint,
1934 Rebalance,
1935 &RebalanceListEntries);
1936 }
1937
1938 RebalanceListEntries = 0;
1939
1940 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1941 {
1942 RebalanceListEntries = ix + 1;
1943 }
1944 }
1945 else
1946 {
1947 RebalanceListEntries = 0;
1948 Result = FALSE;
1949 }
1950
1951 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1952 RebalanceListEntries,
1953 Result);
1954
1955 for (ix = 0; ix < RebalanceListEntries; ix++)
1956 {
1957 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1958
1959 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1960 ix,
1961 RebalanceTtEndpoint,
1962 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1963
1964 InsertTailList(&RebalanceList,
1965 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1966 }
1967
1968 if (Rebalance)
1969 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1970
1971 if (Result)
1972 {
1973 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1974 EndpointProperties->InterruptScheduleMask = SMask;
1975
1976 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1977 EndpointProperties->SplitCompletionMask = CMask;
1978
1979 AllocedBusTime = TtEndpoint->CalcBusTime;
1980
1981 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1982 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1983
1984 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1985 EndpointProperties->Period = ActualPeriod;
1986
1987 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1988 EndpointProperties->ScheduleOffset = ScheduleOffset;
1989
1990 ASSERT(ActualPeriod);
1991 Factor = USB2_FRAMES / ActualPeriod;
1992 n = ScheduleOffset * Factor;
1993
1994 if (TtExtension)
1995 {
1996 for (ix = 0; ix < Factor; ix++)
1997 {
1998 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1999 }
2000 }
2001 else
2002 {
2003 for (ix = 1; ix < Factor; ix++)
2004 {
2005 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2006 }
2007 }
2008
2009 USBPORT_DumpingEndpointProperties(EndpointProperties);
2010 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
2011
2012 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
2013 {
2014 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
2015 }
2016 }
2017
2018 USB2_Rebalance(FdoDevice, &RebalanceList);
2019
2020 if (!TtExtension)
2021 {
2022 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2023 return Result;
2024 }
2025
2026 for (ix = 0; ix < USB2_FRAMES; ix++)
2027 {
2028 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2029 }
2030
2031 USBPORT_UpdateAllocatedBwTt(TtExtension);
2032
2033 for (ix = 0; ix < USB2_FRAMES; ix++)
2034 {
2035 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2036 }
2037
2038 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2039
2040 return Result;
2041 }
2042
2043 VOID
2044 NTAPI
2045 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
2046 IN PUSBPORT_ENDPOINT Endpoint)
2047 {
2048 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2049 ULONG Period;
2050 ULONG ScheduleOffset;
2051 ULONG EndpointBandwidth;
2052 LIST_ENTRY RebalanceList;
2053 ULONG TransferType;
2054 PUSB2_REBALANCE Rebalance;
2055 ULONG RebalanceListEntries;
2056 ULONG Factor;
2057 ULONG ix;
2058 ULONG n;
2059 PUSB2_TT_EXTENSION TtExtension;
2060 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
2061
2062 DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
2063
2064 FdoExtension = FdoDevice->DeviceExtension;
2065
2066 Period = Endpoint->EndpointProperties.Period;
2067 ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
2068 EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
2069
2070 InitializeListHead(&RebalanceList);
2071
2072 TransferType = Endpoint->EndpointProperties.TransferType;
2073
2074 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2075 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2076 (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
2077 {
2078 return;
2079 }
2080
2081 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
2082 sizeof(USB2_REBALANCE),
2083 USB_PORT_TAG);
2084
2085 if (!Rebalance)
2086 {
2087 DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
2088 return;
2089 }
2090
2091 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
2092
2093 ASSERT(Period != 0);
2094 Factor = USB2_FRAMES / Period;
2095 n = ScheduleOffset * Factor;
2096
2097 TtExtension = Endpoint->TtExtension;
2098
2099 if (TtExtension)
2100 {
2101 for (ix = 0; ix < Factor; ix++)
2102 {
2103 TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
2104 }
2105 }
2106 else
2107 {
2108 for (ix = 1; ix < Factor; ix++)
2109 {
2110 FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
2111 }
2112 }
2113
2114 RebalanceListEntries = USB2_FRAMES - 2;
2115
2116 USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
2117 Rebalance,
2118 &RebalanceListEntries,
2119 USB2_FRAMES);
2120
2121 RebalanceListEntries = 0;
2122
2123 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
2124 {
2125 RebalanceListEntries = ix + 1;
2126 }
2127
2128 for (ix = 0; ix < RebalanceListEntries; ix++)
2129 {
2130 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
2131
2132 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
2133 ix,
2134 RebalanceTtEndpoint,
2135 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2136
2137 InsertTailList(&RebalanceList,
2138 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2139 }
2140
2141 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2142
2143 USB2_Rebalance(FdoDevice, &RebalanceList);
2144
2145 if (!TtExtension)
2146 return;
2147
2148 for (ix = 0; ix < USB2_FRAMES; ix++)
2149 {
2150 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2151 }
2152
2153 USBPORT_UpdateAllocatedBwTt(TtExtension);
2154
2155 for (ix = 0; ix < USB2_FRAMES; ix++)
2156 {
2157 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2158 }
2159
2160 DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
2161 }
2162
2163 VOID
2164 NTAPI
2165 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
2166 IN PUSB2_TT Tt)
2167 {
2168 ULONG ix;
2169 ULONG jx;
2170
2171 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
2172
2173 Tt->HcExtension = HcExtension;
2174 Tt->DelayTime = 1;
2175 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
2176
2177 for (ix = 0; ix < USB2_FRAMES; ix++)
2178 {
2179 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
2180 Tt->FrameBudget[ix].AltEndpoint = NULL;
2181
2182 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2183 {
2184 Tt->TimeCS[ix][jx] = 0;
2185 Tt->NumStartSplits[ix][jx] = 0;
2186 }
2187
2188 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
2189
2190 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
2191 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
2192 USBPORT_TRANSFER_DIRECTION_OUT,
2193 UsbFullSpeed,
2194 USB2_FRAMES,
2195 0,
2196 Tt);
2197
2198 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
2199 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2200 Tt->IsoEndpoint[ix].StartFrame = ix;
2201 Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2202
2203 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
2204
2205 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
2206 USBPORT_TRANSFER_TYPE_INTERRUPT,
2207 USBPORT_TRANSFER_DIRECTION_OUT,
2208 UsbFullSpeed,
2209 USB2_FRAMES,
2210 0,
2211 Tt);
2212
2213 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
2214 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2215 Tt->IntEndpoint[ix].StartFrame = ix;
2216 Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2217 }
2218 }
2219
2220 VOID
2221 NTAPI
2222 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
2223 {
2224 ULONG ix;
2225 ULONG jx;
2226
2227 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
2228
2229 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
2230
2231 for (ix = 0; ix < USB2_FRAMES; ix++)
2232 {
2233 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2234 {
2235 HcExtension->TimeUsed[ix][jx] = 0;
2236 }
2237 }
2238
2239 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
2240
2241 USB2_InitTT(HcExtension, &HcExtension->HcTt);
2242 }