ebdd2594fe212576bc5d1f34a3717bc6b49157f0
[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 BOOLEAN
876 NTAPI
877 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
878 IN PUSB2_REBALANCE Rebalance,
879 IN PULONG RebalanceListEntries,
880 IN ULONG MaxFrames)
881 {
882 PUSB2_TT Tt;
883 PUSB2_HC_EXTENSION HcExtension;
884 ULONG Speed;
885 ULONG StartMicroframe;
886 ULONG ix;
887
888 UCHAR frame;
889 UCHAR uframe;
890
891 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X\n",
892 TtEndpoint,
893 MaxFrames);
894
895 if (TtEndpoint->CalcBusTime == 0)
896 {
897 DPRINT("USB2_DeallocateEndpointBudget: endpoint not allocated\n");//error((int)"endpoint not allocated");
898 return FALSE;
899 }
900
901 Tt = TtEndpoint->Tt;
902 HcExtension = Tt->HcExtension;
903
904 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
905 DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
906
907 StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
908 TtEndpoint->StartMicroframe;
909
910 if (Speed == UsbHighSpeed)
911 {
912 for (ix = StartMicroframe;
913 ix < USB2_MAX_MICROFRAMES;
914 ix += TtEndpoint->ActualPeriod)
915 {
916 frame = ix / USB2_MICROFRAMES;
917 uframe = ix % (USB2_MICROFRAMES - 1);
918
919 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
920 }
921
922 TtEndpoint->CalcBusTime = 0;
923
924 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
925 return TRUE;
926 }
927
928 /* Speed != UsbHighSpeed (FS/LS) */
929
930 DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
931 ASSERT(FALSE);
932
933 TtEndpoint->CalcBusTime = 0;
934 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
935 return TRUE;
936 }
937
938 BOOLEAN
939 NTAPI
940 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
941 IN PUSB2_REBALANCE Rebalance,
942 IN PULONG RebalanceListEntries)
943 {
944 PUSB2_TT Tt;
945 PUSB2_HC_EXTENSION HcExtension;
946 ULONG Speed;
947 ULONG TimeUsed;
948 ULONG MinTimeUsed;
949 ULONG ix;
950 ULONG frame;
951 ULONG uframe;
952 ULONG Microframe;
953 ULONG TransferType;
954 ULONG Overhead;
955 ULONG LatestStart;
956 PUSB2_TT_ENDPOINT prevEndpoint;
957 PUSB2_TT_ENDPOINT nextEndpoint;
958 PUSB2_TT_ENDPOINT IntEndpoint;
959 ULONG StartTime;
960 ULONG calcBusTime;
961 BOOLEAN Result = TRUE;
962
963 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
964
965 Tt = TtEndpoint->Tt;
966 HcExtension = Tt->HcExtension;
967
968 TtEndpoint->Nums.NumStarts = 0;
969 TtEndpoint->Nums.NumCompletes = 0;
970
971 TtEndpoint->StartFrame = 0;
972 TtEndpoint->StartMicroframe = 0;
973
974 if (TtEndpoint->CalcBusTime)
975 {
976 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
977 return FALSE;
978 }
979
980 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
981
982 if (Speed == UsbHighSpeed)
983 {
984 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
985 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
986 else
987 TtEndpoint->ActualPeriod = TtEndpoint->Period;
988
989 MinTimeUsed = HcExtension->TimeUsed[0][0];
990
991 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
992 {
993 frame = ix / USB2_MICROFRAMES;
994 uframe = ix % (USB2_MICROFRAMES - 1);
995
996 TimeUsed = HcExtension->TimeUsed[frame][uframe];
997
998 if (TimeUsed < MinTimeUsed)
999 {
1000 MinTimeUsed = TimeUsed;
1001 TtEndpoint->StartFrame = frame;
1002 TtEndpoint->StartMicroframe = uframe;
1003 }
1004 }
1005
1006 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1007 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1008
1009 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1010 TtEndpoint->StartFrame,
1011 TtEndpoint->StartMicroframe,
1012 TtEndpoint->CalcBusTime);
1013
1014 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1015 TtEndpoint->StartMicroframe;
1016
1017 if (Microframe >= USB2_MAX_MICROFRAMES)
1018 {
1019 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1020 return TRUE;
1021 }
1022
1023 for (ix = Microframe;
1024 ix < USB2_MAX_MICROFRAMES;
1025 ix += TtEndpoint->ActualPeriod)
1026 {
1027 frame = ix / USB2_MICROFRAMES;
1028 uframe = ix % (USB2_MICROFRAMES - 1);
1029
1030 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1031 frame,
1032 uframe,
1033 HcExtension->TimeUsed[frame][uframe]);
1034
1035 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1036 TtEndpoint->CalcBusTime,
1037 USB2_MAX_MICROFRAME_ALLOCATION))
1038 {
1039 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1040 Result = FALSE;
1041 }
1042 }
1043
1044 if (!Result)
1045 {
1046 for (ix = Microframe;
1047 ix < USB2_MAX_MICROFRAMES;
1048 ix += TtEndpoint->ActualPeriod)
1049 {
1050 frame = ix / USB2_MICROFRAMES;
1051 uframe = ix % (USB2_MICROFRAMES - 1);
1052
1053 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1054 }
1055 }
1056
1057 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1058 return TRUE;
1059 }
1060
1061 /* Speed != UsbHighSpeed (FS/LS) */
1062
1063 if (TtEndpoint->Period > USB2_FRAMES)
1064 TtEndpoint->ActualPeriod = USB2_FRAMES;
1065 else
1066 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1067
1068 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1069
1070 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1071 {
1072 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1073 {
1074 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1075 TtEndpoint->StartFrame = ix;
1076 }
1077 }
1078
1079 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1080
1081 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1082 {
1083 if (Speed == UsbFullSpeed)
1084 {
1085 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1086 }
1087 else
1088 {
1089 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1090 return FALSE;
1091 }
1092 }
1093 else
1094 {
1095 if (Speed == UsbFullSpeed)
1096 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1097 else
1098 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1099 }
1100
1101 if (Speed == UsbLowSpeed)
1102 {
1103 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1104 }
1105 else
1106 {
1107 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1108 }
1109
1110 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1111
1112 for (ix = 0;
1113 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1114 ix += TtEndpoint->ActualPeriod)
1115 {
1116 frame = TtEndpoint->StartFrame + ix;
1117
1118 if (Tt->FrameBudget[frame].AltEndpoint &&
1119 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1120 {
1121 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1122 return FALSE;
1123 }
1124
1125 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1126 prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1127 else
1128 prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1129
1130 for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1131 nextEndpoint;
1132 nextEndpoint = nextEndpoint->NextTtEndpoint)
1133 {
1134 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1135 {
1136 break;
1137 }
1138
1139 prevEndpoint = nextEndpoint;
1140 }
1141
1142 StartTime = USB2_GetStartTime(nextEndpoint,
1143 TtEndpoint,
1144 prevEndpoint,
1145 frame);
1146
1147 if (StartTime > LatestStart)
1148 LatestStart = StartTime;
1149 }
1150
1151 TtEndpoint->StartTime = LatestStart;
1152
1153 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1154 {
1155 TtEndpoint->CalcBusTime = 0;
1156 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1157 return FALSE;
1158 }
1159
1160 for (ix = 0, frame = -TtEndpoint->StartFrame;
1161 ix < USB2_FRAMES;
1162 ix++, frame++)
1163 {
1164 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1165 ix,
1166 frame,
1167 TtEndpoint->StartFrame);
1168
1169 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1170 {
1171 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1172 ASSERT(FALSE);
1173 }
1174 else
1175 {
1176 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1177 nextEndpoint = IntEndpoint->NextTtEndpoint;
1178
1179 for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1180 nextEndpoint;
1181 nextEndpoint = nextEndpoint->NextTtEndpoint)
1182 {
1183 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1184 break;
1185 IntEndpoint = nextEndpoint;
1186 }
1187
1188 if ((frame % TtEndpoint->ActualPeriod) == 0)
1189 {
1190 calcBusTime = 0;
1191 }
1192 else
1193 {
1194 if (nextEndpoint)
1195 {
1196 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1197 nextEndpoint->StartTime;
1198 }
1199 else
1200 {
1201 calcBusTime = TtEndpoint->CalcBusTime;
1202 }
1203
1204 if (calcBusTime > 0)
1205 {
1206 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1207
1208 if (!USB2_AllocateCheck(&TimeUsed,
1209 calcBusTime,
1210 USB2_FS_MAX_PERIODIC_ALLOCATION))
1211 {
1212 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1213 Result = FALSE;
1214 }
1215 }
1216 }
1217
1218 if (nextEndpoint != TtEndpoint)
1219 {
1220 if ((frame % TtEndpoint->ActualPeriod) == 0)
1221 {
1222 if (frame == 0)
1223 {
1224 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1225 TtEndpoint->NextTtEndpoint = nextEndpoint;
1226 }
1227
1228 IntEndpoint->NextTtEndpoint = TtEndpoint;
1229
1230 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1231 TtEndpoint,
1232 nextEndpoint);
1233 }
1234
1235 if (calcBusTime > 0)
1236 {
1237 BOOLEAN IsMoved;
1238 BOOLEAN MoveResult;
1239
1240 DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1241 nextEndpoint,
1242 calcBusTime);
1243
1244 for (;
1245 nextEndpoint;
1246 nextEndpoint = nextEndpoint->NextTtEndpoint)
1247 {
1248 MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1249 calcBusTime,
1250 Rebalance,
1251 *RebalanceListEntries,
1252 &IsMoved);
1253
1254 if (!IsMoved)
1255 {
1256 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1257 Result = FALSE;
1258 }
1259
1260 if (!MoveResult)
1261 break;
1262 }
1263 }
1264 }
1265 }
1266
1267 if ((frame % TtEndpoint->ActualPeriod) == 0)
1268 {
1269 if (!USB2_AllocateHS(TtEndpoint, frame))
1270 {
1271 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1272 Result = FALSE;
1273 }
1274
1275 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1276 }
1277
1278 if (Result == FALSE)
1279 {
1280 USB2_DeallocateEndpointBudget(TtEndpoint,
1281 Rebalance,
1282 RebalanceListEntries,
1283 ix + 1);
1284
1285 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1286 return FALSE;
1287 }
1288 }
1289
1290 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1291 return Result;
1292 }
1293
1294 BOOLEAN
1295 NTAPI
1296 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1297 IN PUSB2_REBALANCE Rebalance,
1298 IN PULONG RebalanceListEntries)
1299 {
1300 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
1301 ASSERT(FALSE);
1302 return FALSE;
1303 }
1304
1305 VOID
1306 NTAPI
1307 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1308 {
1309 ULONG BusBandwidth;
1310 ULONG NewBusBandwidth;
1311 ULONG MaxBusBandwidth = 0;
1312 ULONG MinBusBandwidth;
1313 ULONG ix;
1314
1315 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1316
1317 BusBandwidth = TtExtension->BusBandwidth;
1318 MinBusBandwidth = BusBandwidth;
1319
1320 for (ix = 0; ix < USB2_FRAMES; ix++)
1321 {
1322 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1323
1324 if (NewBusBandwidth > MaxBusBandwidth)
1325 MaxBusBandwidth = NewBusBandwidth;
1326
1327 if (NewBusBandwidth < MinBusBandwidth)
1328 MinBusBandwidth = NewBusBandwidth;
1329 }
1330
1331 TtExtension->MaxBandwidth = MaxBusBandwidth;
1332
1333 if (MinBusBandwidth == BusBandwidth)
1334 TtExtension->MinBandwidth = 0;
1335 else
1336 TtExtension->MinBandwidth = MinBusBandwidth;
1337 }
1338
1339 BOOLEAN
1340 NTAPI
1341 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1342 IN PUSBPORT_ENDPOINT Endpoint)
1343 {
1344 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1345 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1346 PUSB2_TT_EXTENSION TtExtension;
1347 ULONG TransferType;
1348 PUSB2_REBALANCE Rebalance;
1349 LIST_ENTRY RebalanceList;
1350 ULONG RebalanceListEntries;
1351 PUSB2_TT_ENDPOINT TtEndpoint;
1352 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1353 PUSB2_TT Tt;
1354 USB_DEVICE_SPEED DeviceSpeed;
1355 ULONG Period;
1356 ULONG AllocedBusTime;
1357 ULONG EndpointBandwidth;
1358 ULONG ScheduleOffset;
1359 ULONG Factor;
1360 ULONG ix;
1361 ULONG n;
1362 BOOLEAN Direction;
1363 UCHAR SMask;
1364 UCHAR CMask;
1365 UCHAR ActualPeriod;
1366 BOOLEAN Result;
1367
1368 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1369 FdoDevice,
1370 Endpoint);
1371
1372 EndpointProperties = &Endpoint->EndpointProperties;
1373 EndpointProperties->ScheduleOffset = 0;
1374
1375 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1376 {
1377 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1378 return TRUE;
1379 }
1380
1381 FdoExtension = FdoDevice->DeviceExtension;
1382
1383 TransferType = EndpointProperties->TransferType;
1384 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1385
1386 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1387 TransferType == USBPORT_TRANSFER_TYPE_BULK)
1388 {
1389 return TRUE;
1390 }
1391
1392 if (Endpoint->TtExtension)
1393 TtExtension = Endpoint->TtExtension;
1394 else
1395 TtExtension = NULL;
1396
1397 InitializeListHead(&RebalanceList);
1398
1399 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1400 sizeof(USB2_REBALANCE),
1401 USB_PORT_TAG);
1402
1403 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1404 Rebalance,
1405 TtExtension);
1406
1407 if (Rebalance)
1408 {
1409 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1410
1411 TtEndpoint = Endpoint->TtEndpoint;
1412 TtEndpoint->Endpoint = Endpoint;
1413
1414 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1415 DeviceSpeed = EndpointProperties->DeviceSpeed;
1416
1417 switch (DeviceSpeed)
1418 {
1419 case UsbLowSpeed:
1420 case UsbFullSpeed:
1421 {
1422 Tt = &TtExtension->Tt;
1423
1424 Period = USB2_FRAMES;
1425
1426 while (Period > 0 && Period > EndpointProperties->Period)
1427 {
1428 Period >>= 1;
1429 }
1430
1431 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1432 break;
1433 }
1434
1435 case UsbHighSpeed:
1436 {
1437 Tt = &FdoExtension->Usb2Extension->HcTt;
1438
1439 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1440 Period = USB2_MAX_MICROFRAMES;
1441 else
1442 Period = EndpointProperties->Period;
1443
1444 break;
1445 }
1446
1447 default:
1448 {
1449 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1450 DeviceSpeed);
1451
1452 DbgBreakPoint();
1453
1454 Tt = &TtExtension->Tt;
1455 break;
1456 }
1457 }
1458
1459 USB2_InitTtEndpoint(TtEndpoint,
1460 TransferType,
1461 Direction,
1462 DeviceSpeed,
1463 Period,
1464 EndpointProperties->MaxPacketSize,
1465 Tt);
1466
1467 RebalanceListEntries = USB2_FRAMES - 2;
1468
1469 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1470 Rebalance,
1471 &RebalanceListEntries);
1472
1473 if (Result)
1474 {
1475 Result = USB2_PromotePeriods(TtEndpoint,
1476 Rebalance,
1477 &RebalanceListEntries);
1478 }
1479
1480 RebalanceListEntries = 0;
1481
1482 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1483 {
1484 RebalanceListEntries = ix + 1;
1485 }
1486 }
1487 else
1488 {
1489 RebalanceListEntries = 0;
1490 Result = FALSE;
1491 }
1492
1493 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1494 RebalanceListEntries,
1495 Result);
1496
1497 for (ix = 0; ix < RebalanceListEntries; ix++)
1498 {
1499 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1500
1501 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1502 ix,
1503 RebalanceTtEndpoint,
1504 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1505
1506 InsertTailList(&RebalanceList,
1507 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1508 }
1509
1510 if (Rebalance)
1511 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1512
1513 if (Result)
1514 {
1515 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1516 EndpointProperties->InterruptScheduleMask = SMask;
1517
1518 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1519 EndpointProperties->SplitCompletionMask = CMask;
1520
1521 AllocedBusTime = TtEndpoint->CalcBusTime;
1522
1523 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1524 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1525
1526 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1527 EndpointProperties->Period = ActualPeriod;
1528
1529 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1530 EndpointProperties->ScheduleOffset = ScheduleOffset;
1531
1532 Factor = USB2_FRAMES / ActualPeriod;
1533 ASSERT(Factor);
1534
1535 n = ScheduleOffset * Factor;
1536
1537 if (TtExtension)
1538 {
1539 for (ix = 0; ix < Factor; ix++)
1540 {
1541 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1542 }
1543 }
1544 else
1545 {
1546 for (ix = 1; ix < Factor; ix++)
1547 {
1548 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1549 }
1550 }
1551
1552 USBPORT_DumpingEndpointProperties(EndpointProperties);
1553 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
1554
1555 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1556 {
1557 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
1558 }
1559 }
1560
1561 //USB2_Rebalance(FdoDevice, &RebalanceList);
1562
1563 if (!TtExtension)
1564 {
1565 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1566 return Result;
1567 }
1568
1569 for (ix = 0; ix < USB2_FRAMES; ix++)
1570 {
1571 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1572 }
1573
1574 USBPORT_UpdateAllocatedBwTt(TtExtension);
1575
1576 for (ix = 0; ix < USB2_FRAMES; ix++)
1577 {
1578 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
1579 }
1580
1581 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1582
1583 return Result;
1584 }
1585
1586 VOID
1587 NTAPI
1588 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1589 IN PUSBPORT_ENDPOINT Endpoint)
1590 {
1591 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
1592 }
1593
1594 VOID
1595 NTAPI
1596 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
1597 IN PUSB2_TT Tt)
1598 {
1599 ULONG ix;
1600 ULONG jx;
1601
1602 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
1603
1604 Tt->HcExtension = HcExtension;
1605 Tt->DelayTime = 1;
1606 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
1607
1608 for (ix = 0; ix < USB2_FRAMES; ix++)
1609 {
1610 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
1611 Tt->FrameBudget[ix].AltEndpoint = NULL;
1612
1613 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1614 {
1615 Tt->TimeCS[ix][jx] = 0;
1616 Tt->NumStartSplits[ix][jx] = 0;
1617 }
1618
1619 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
1620
1621 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
1622 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
1623 USBPORT_TRANSFER_DIRECTION_OUT,
1624 UsbFullSpeed,
1625 USB2_FRAMES,
1626 0,
1627 Tt);
1628
1629 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
1630 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1631 Tt->IsoEndpoint[ix].StartFrame = ix;
1632 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
1633
1634 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
1635
1636 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
1637 USBPORT_TRANSFER_TYPE_INTERRUPT,
1638 USBPORT_TRANSFER_DIRECTION_OUT,
1639 UsbFullSpeed,
1640 USB2_FRAMES,
1641 0,
1642 Tt);
1643
1644 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
1645 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1646 Tt->IntEndpoint[ix].StartFrame = ix;
1647 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
1648 }
1649 }
1650
1651 VOID
1652 NTAPI
1653 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
1654 {
1655 ULONG ix;
1656 ULONG jx;
1657
1658 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
1659
1660 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
1661
1662 for (ix = 0; ix < USB2_FRAMES; ix++)
1663 {
1664 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1665 {
1666 HcExtension->TimeUsed[ix][jx] = 0;
1667 }
1668 }
1669
1670 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
1671
1672 USB2_InitTT(HcExtension, &HcExtension->HcTt);
1673 }