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