[USBPORT] Add USB2_GetSMASK()and USB2_ConvertFrame().
[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 RemainDataTime;
319 ULONG OverheadCS;
320 ULONG OverheadSS;
321 ULONG ix;
322 USHORT PktSize;
323 UCHAR frame;
324 UCHAR uframe;
325 BOOL Result = TRUE;
326
327 DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, TtEndpoint->StartFrame - %X\n",
328 TtEndpoint,
329 Frame,
330 TtEndpoint->StartFrame);
331
332 Tt = TtEndpoint->Tt;
333 HcExtension = Tt->HcExtension;
334
335 TransferType = TtEndpoint->TtEndpointParams.TransferType;
336 Direction = TtEndpoint->TtEndpointParams.Direction;
337
338 if (Frame == 0)
339 {
340 TtEndpoint->StartMicroframe =
341 TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1;
342
343 DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n",
344 TtEndpoint->StartMicroframe);
345 }
346
347 USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
348
349 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
350 {
351 if (Frame == 0)
352 {
353 TtEndpoint->Nums.NumStarts = 1;
354
355 if ((CHAR)TtEndpoint->StartMicroframe < 5)
356 {
357 TtEndpoint->Nums.NumCompletes = 3;
358 }
359 else
360 {
361 TtEndpoint->Nums.NumCompletes = 2;
362 }
363 }
364 }
365 else
366 {
367 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
368 {
369 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
370 ASSERT(FALSE);
371 }
372 else
373 {
374 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
375 ASSERT(FALSE);
376 }
377 }
378
379 frame = TtEndpoint->StartFrame + Frame;
380 uframe = TtEndpoint->StartMicroframe;
381
382 if (TtEndpoint->StartMicroframe == 0xFF)
383 USB2_GetPrevMicroFrame(&frame, &uframe);
384
385 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
386 {
387 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
388 OverheadSS,
389 USB2_MAX_MICROFRAME_ALLOCATION))
390 {
391 Result = FALSE;
392 }
393
394 if (Tt->NumStartSplits[frame][uframe] > (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
395 {
396 DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
397 Tt->NumStartSplits[frame][uframe] + 1);
398
399 ASSERT(FALSE);
400 Result = FALSE;
401 }
402
403 ++Tt->NumStartSplits[frame][uframe];
404 USB2_IncMicroFrame(&frame, &uframe);
405 }
406
407 frame = TtEndpoint->StartFrame + Frame;
408 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
409
410 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
411 {
412 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
413 OverheadCS,
414 USB2_MAX_MICROFRAME_ALLOCATION))
415 {
416 Result = FALSE;
417 }
418
419 USB2_IncMicroFrame(&frame, &uframe);
420 }
421
422 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
423 {
424 DPRINT("USB2_AllocateHS: DIRECTION OUT UNIMPLEMENTED\n");
425 ASSERT(FALSE);
426 }
427 else
428 {
429 frame = TtEndpoint->StartFrame + Frame;
430 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
431
432 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
433 {
434 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
435 {
436 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
437 {
438 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
439 Tt->TimeCS[frame][uframe];
440 }
441 else
442 {
443 RemainDataTime = 0;
444 }
445
446 PktSize = TtEndpoint->MaxPacketSize;
447
448 if (RemainDataTime >= USB2_AddDataBitStuff(PktSize))
449 {
450 DataTime = USB2_AddDataBitStuff(PktSize);
451 }
452 else
453 {
454 DataTime = RemainDataTime;
455 }
456
457 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
458 DataTime,
459 USB2_MAX_MICROFRAME_ALLOCATION))
460 {
461 Result = FALSE;
462 }
463 }
464
465 PktSize = TtEndpoint->MaxPacketSize;
466
467 if (USB2_AddDataBitStuff(PktSize) < USB2_FS_RAW_BYTES_IN_MICROFRAME)
468 {
469 Tt->TimeCS[frame][uframe] += USB2_AddDataBitStuff(PktSize);
470 }
471 else
472 {
473 Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
474 }
475
476 USB2_IncMicroFrame(&frame, &uframe);
477 }
478 }
479
480 DPRINT("USB2_AllocateHS: Result - %X\n", Result);
481 return Result;
482 }
483
484 VOID
485 NTAPI
486 USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
487 IN ULONG Frame)
488 {
489 DPRINT("USB2_DeallocateHS: UNIMPLEMENTED FIXME\n");
490 ASSERT(FALSE);
491 }
492
493 BOOLEAN
494 NTAPI
495 USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
496 IN USHORT BusTime,
497 IN PUSB2_REBALANCE Rebalance,
498 IN ULONG RebalanceListEntries,
499 OUT BOOLEAN * OutResult)
500 {
501 DPRINT("USB2_MoveTtEndpoint: UNIMPLEMENTED FIXME\n");
502 ASSERT(FALSE);
503 return FALSE;
504 }
505
506 VOID
507 NTAPI
508 USB2_ConvertFrame(IN UCHAR Frame,
509 IN UCHAR Microframe,
510 OUT PUCHAR HcFrame,
511 OUT PUCHAR HcMicroframe)
512 {
513 DPRINT("USB2_ConvertFrame: Frame - %x, Microframe - %x\n",
514 Frame,
515 Microframe);
516
517 if (Microframe == 0xFF)
518 {
519 *HcFrame = Frame;
520 *HcMicroframe = 0;
521 }
522
523 if (Microframe >= 0 &&
524 Microframe <= (USB2_MICROFRAMES - 2))
525 {
526 *HcFrame = Frame;
527 *HcMicroframe = Microframe + 1;
528 }
529
530 if (Microframe == (USB2_MICROFRAMES - 1))
531 {
532 *HcFrame = Frame + 1;
533 *HcMicroframe = 0;
534 }
535 }
536
537 UCHAR
538 NTAPI
539 USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
540 {
541 ULONG ix;
542 UCHAR SMask = 0;
543 UCHAR HcFrame;
544 UCHAR HcMicroFrame;
545
546 if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
547 {
548 SMask = (1 << TtEndpoint->StartMicroframe);
549 }
550 else
551 {
552 USB2_ConvertFrame(TtEndpoint->StartFrame,
553 TtEndpoint->StartMicroframe,
554 &HcFrame,
555 &HcMicroFrame);
556
557 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
558 {
559 SMask |= (1 << HcMicroFrame);
560 HcMicroFrame++;
561 }
562 }
563
564 return SMask;
565 }
566
567 BOOLEAN
568 NTAPI
569 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
570 IN PUSB2_REBALANCE Rebalance,
571 IN PULONG RebalanceListEntries,
572 IN ULONG MaxFrames)
573 {
574 DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
575 ASSERT(FALSE);
576 return FALSE;
577 }
578
579 BOOLEAN
580 NTAPI
581 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
582 IN PUSB2_REBALANCE Rebalance,
583 IN PULONG RebalanceListEntries)
584 {
585 PUSB2_TT Tt;
586 PUSB2_HC_EXTENSION HcExtension;
587 ULONG Speed;
588 ULONG TimeUsed;
589 ULONG MinTimeUsed;
590 ULONG ix;
591 ULONG frame;
592 ULONG uframe;
593 ULONG Microframe;
594 ULONG TransferType;
595 ULONG Overhead;
596 ULONG LatestStart;
597 PUSB2_TT_ENDPOINT prevTtEndpoint;
598 PUSB2_TT_ENDPOINT nextTtEndpoint;
599 PUSB2_TT_ENDPOINT IntEndpoint;
600 ULONG StartTime;
601 ULONG calcBusTime;
602 BOOLEAN Result = TRUE;
603
604 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
605
606 Tt = TtEndpoint->Tt;
607 HcExtension = Tt->HcExtension;
608
609 TtEndpoint->Nums.NumStarts = 0;
610 TtEndpoint->Nums.NumCompletes = 0;
611
612 TtEndpoint->StartFrame = 0;
613 TtEndpoint->StartMicroframe = 0;
614
615 if (TtEndpoint->CalcBusTime)
616 {
617 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
618 return FALSE;
619 }
620
621 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
622
623 if (Speed == UsbHighSpeed)
624 {
625 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
626 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
627 else
628 TtEndpoint->ActualPeriod = TtEndpoint->Period;
629
630 MinTimeUsed = HcExtension->TimeUsed[0][0];
631
632 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
633 {
634 frame = ix / USB2_MICROFRAMES;
635 uframe = ix % (USB2_MICROFRAMES - 1);
636
637 TimeUsed = HcExtension->TimeUsed[frame][uframe];
638
639 if (TimeUsed < MinTimeUsed)
640 {
641 MinTimeUsed = TimeUsed;
642 TtEndpoint->StartFrame = frame;
643 TtEndpoint->StartMicroframe = uframe;
644 }
645 }
646
647 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
648 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
649
650 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
651 TtEndpoint->StartFrame,
652 TtEndpoint->StartMicroframe,
653 TtEndpoint->CalcBusTime);
654
655 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
656 TtEndpoint->StartMicroframe;
657
658 if (Microframe >= USB2_MAX_MICROFRAMES)
659 {
660 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
661 return TRUE;
662 }
663
664 for (ix = Microframe;
665 ix < USB2_MAX_MICROFRAMES;
666 ix += TtEndpoint->ActualPeriod)
667 {
668 frame = ix / USB2_MICROFRAMES;
669 uframe = ix % (USB2_MICROFRAMES - 1);
670
671 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
672 frame,
673 uframe,
674 HcExtension->TimeUsed[frame][uframe]);
675
676 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
677 TtEndpoint->CalcBusTime,
678 USB2_MAX_MICROFRAME_ALLOCATION))
679 {
680 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
681 Result = FALSE;
682 }
683 }
684
685 if (!Result)
686 {
687 for (ix = Microframe;
688 ix < USB2_MAX_MICROFRAMES;
689 ix += TtEndpoint->ActualPeriod)
690 {
691 frame = ix / USB2_MICROFRAMES;
692 uframe = ix % (USB2_MICROFRAMES - 1);
693
694 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
695 }
696 }
697
698 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
699 return TRUE;
700 }
701
702 /* Speed != UsbHighSpeed (FS/LS) */
703
704 if (TtEndpoint->Period > USB2_FRAMES)
705 TtEndpoint->ActualPeriod = USB2_FRAMES;
706 else
707 TtEndpoint->ActualPeriod = TtEndpoint->Period;
708
709 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
710
711 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
712 {
713 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
714 {
715 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
716 TtEndpoint->StartFrame = ix;
717 }
718 }
719
720 TransferType = TtEndpoint->TtEndpointParams.TransferType;
721
722 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
723 {
724 if (Speed == UsbFullSpeed)
725 {
726 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
727 }
728 else
729 {
730 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
731 return FALSE;
732 }
733 }
734 else
735 {
736 if (Speed == UsbFullSpeed)
737 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
738 else
739 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
740 }
741
742 if (Speed == UsbLowSpeed)
743 {
744 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
745 }
746 else
747 {
748 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
749 }
750
751 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
752
753 for (ix = 0;
754 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
755 ix += TtEndpoint->ActualPeriod)
756 {
757 frame = TtEndpoint->StartFrame + ix;
758
759 if (Tt->FrameBudget[frame].AltEndpoint &&
760 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
761 {
762 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
763 return FALSE;
764 }
765
766 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
767 prevTtEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
768 else
769 prevTtEndpoint = Tt->FrameBudget[frame].IntEndpoint;
770
771 for (nextTtEndpoint = prevTtEndpoint->NextTtEndpoint;
772 nextTtEndpoint;
773 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
774 {
775 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
776 {
777 break;
778 }
779
780 prevTtEndpoint = nextTtEndpoint;
781 }
782
783 StartTime = USB2_GetStartTime(nextTtEndpoint,
784 TtEndpoint,
785 prevTtEndpoint,
786 frame);
787
788 if (StartTime > LatestStart)
789 LatestStart = StartTime;
790 }
791
792 TtEndpoint->StartTime = LatestStart;
793
794 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
795 {
796 TtEndpoint->CalcBusTime = 0;
797 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
798 return FALSE;
799 }
800
801 for (ix = 0, frame = -TtEndpoint->StartFrame;
802 ix < USB2_FRAMES;
803 ix++, frame++)
804 {
805 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
806 ix,
807 frame,
808 TtEndpoint->StartFrame);
809
810 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
811 {
812 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
813 ASSERT(FALSE);
814 }
815 else
816 {
817 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
818 nextTtEndpoint = IntEndpoint->NextTtEndpoint;
819
820 for (nextTtEndpoint = IntEndpoint->NextTtEndpoint;
821 nextTtEndpoint;
822 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
823 {
824 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
825 break;
826 IntEndpoint = nextTtEndpoint;
827 }
828
829 if ((frame % TtEndpoint->ActualPeriod) == 0)
830 {
831 calcBusTime = 0;
832 }
833 else
834 {
835 if (nextTtEndpoint)
836 {
837 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
838 nextTtEndpoint->StartTime;
839 }
840 else
841 {
842 calcBusTime = TtEndpoint->CalcBusTime;
843 }
844
845 if (calcBusTime > 0)
846 {
847 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
848
849 if (!USB2_AllocateCheck(&TimeUsed,
850 calcBusTime,
851 USB2_FS_MAX_PERIODIC_ALLOCATION))
852 {
853 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
854 Result = FALSE;
855 }
856 }
857 }
858
859 if (nextTtEndpoint != TtEndpoint)
860 {
861 if ((frame % TtEndpoint->ActualPeriod) == 0)
862 {
863 if (frame == 0)
864 {
865 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
866 TtEndpoint->NextTtEndpoint = nextTtEndpoint;
867 }
868
869 IntEndpoint->NextTtEndpoint = TtEndpoint;
870
871 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextTtEndpoint - %p\n",
872 TtEndpoint,
873 nextTtEndpoint);
874 }
875
876 if (calcBusTime > 0)
877 {
878 BOOLEAN IsMoved;
879 BOOLEAN MoveResult;
880
881 DPRINT("USB2_AllocateTimeForEndpoint: nextTtEndpoint - %p, calcBusTime - %X\n",
882 nextTtEndpoint,
883 calcBusTime);
884
885 for (;
886 nextTtEndpoint;
887 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
888 {
889 MoveResult = USB2_MoveTtEndpoint(nextTtEndpoint,
890 calcBusTime,
891 Rebalance,
892 *RebalanceListEntries,
893 &IsMoved);
894
895 if (!IsMoved)
896 {
897 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
898 Result = FALSE;
899 }
900
901 if (!MoveResult)
902 break;
903 }
904 }
905 }
906 }
907
908 if ((frame % TtEndpoint->ActualPeriod) == 0)
909 {
910 if (!USB2_AllocateHS(TtEndpoint, frame))
911 {
912 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
913 Result = FALSE;
914 }
915
916 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
917 }
918
919 if (Result == FALSE)
920 {
921 USB2_DeallocateEndpointBudget(TtEndpoint,
922 Rebalance,
923 RebalanceListEntries,
924 ix + 1);
925
926 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
927 return FALSE;
928 }
929 }
930
931 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
932 return Result;
933 }
934
935 BOOLEAN
936 NTAPI
937 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
938 IN PUSB2_REBALANCE Rebalance,
939 IN PULONG RebalanceListEntries)
940 {
941 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
942 ASSERT(FALSE);
943 return FALSE;
944 }
945
946 VOID
947 NTAPI
948 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
949 {
950 ULONG BusBandwidth;
951 ULONG NewBusBandwidth;
952 ULONG MaxBusBandwidth = 0;
953 ULONG MinBusBandwidth;
954 ULONG ix;
955
956 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
957
958 BusBandwidth = TtExtension->BusBandwidth;
959 MinBusBandwidth = BusBandwidth;
960
961 for (ix = 0; ix < USB2_FRAMES; ix++)
962 {
963 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
964
965 if (NewBusBandwidth > MaxBusBandwidth)
966 MaxBusBandwidth = NewBusBandwidth;
967
968 if (NewBusBandwidth < MinBusBandwidth)
969 MinBusBandwidth = NewBusBandwidth;
970 }
971
972 TtExtension->MaxBandwidth = MaxBusBandwidth;
973
974 if (MinBusBandwidth == BusBandwidth)
975 TtExtension->MinBandwidth = 0;
976 else
977 TtExtension->MinBandwidth = MinBusBandwidth;
978 }
979
980 BOOLEAN
981 NTAPI
982 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
983 IN PUSBPORT_ENDPOINT Endpoint)
984 {
985 PUSBPORT_DEVICE_EXTENSION FdoExtension;
986 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
987 PUSB2_TT_EXTENSION TtExtension;
988 ULONG TransferType;
989 PUSB2_REBALANCE Rebalance;
990 LIST_ENTRY RebalanceList;
991 ULONG RebalanceListEntries;
992 PUSB2_TT_ENDPOINT TtEndpoint;
993 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
994 PUSB2_TT Tt;
995 USB_DEVICE_SPEED DeviceSpeed;
996 ULONG Period;
997 ULONG AllocedBusTime;
998 ULONG EndpointBandwidth;
999 ULONG ScheduleOffset;
1000 ULONG Factor;
1001 ULONG ix;
1002 ULONG n;
1003 BOOLEAN Direction;
1004 UCHAR SMask;
1005 UCHAR CMask;
1006 UCHAR ActualPeriod;
1007 BOOLEAN Result;
1008
1009 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1010 FdoDevice,
1011 Endpoint);
1012
1013 EndpointProperties = &Endpoint->EndpointProperties;
1014 EndpointProperties->ScheduleOffset = 0;
1015
1016 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1017 {
1018 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1019 return TRUE;
1020 }
1021
1022 FdoExtension = FdoDevice->DeviceExtension;
1023
1024 TransferType = EndpointProperties->TransferType;
1025 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1026
1027 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1028 TransferType == USBPORT_TRANSFER_TYPE_BULK)
1029 {
1030 return TRUE;
1031 }
1032
1033 if (Endpoint->TtExtension)
1034 TtExtension = Endpoint->TtExtension;
1035 else
1036 TtExtension = NULL;
1037
1038 InitializeListHead(&RebalanceList);
1039
1040 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1041 sizeof(USB2_REBALANCE),
1042 USB_PORT_TAG);
1043
1044 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1045 Rebalance,
1046 TtExtension);
1047
1048 if (Rebalance)
1049 {
1050 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1051
1052 TtEndpoint = Endpoint->TtEndpoint;
1053 TtEndpoint->Endpoint = Endpoint;
1054
1055 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1056 DeviceSpeed = EndpointProperties->DeviceSpeed;
1057
1058 switch (DeviceSpeed)
1059 {
1060 case UsbLowSpeed:
1061 case UsbFullSpeed:
1062 {
1063 Tt = &TtExtension->Tt;
1064
1065 Period = USB2_FRAMES;
1066
1067 while (Period > 0 && Period > EndpointProperties->Period)
1068 {
1069 Period >>= 1;
1070 }
1071
1072 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1073 break;
1074 }
1075
1076 case UsbHighSpeed:
1077 {
1078 Tt = &FdoExtension->Usb2Extension->HcTt;
1079
1080 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1081 Period = USB2_MAX_MICROFRAMES;
1082 else
1083 Period = EndpointProperties->Period;
1084
1085 break;
1086 }
1087
1088 default:
1089 {
1090 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1091 DeviceSpeed);
1092
1093 DbgBreakPoint();
1094
1095 Tt = &TtExtension->Tt;
1096 break;
1097 }
1098 }
1099
1100 USB2_InitTtEndpoint(TtEndpoint,
1101 TransferType,
1102 Direction,
1103 DeviceSpeed,
1104 Period,
1105 EndpointProperties->MaxPacketSize,
1106 Tt);
1107
1108 RebalanceListEntries = USB2_FRAMES - 2;
1109
1110 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1111 Rebalance,
1112 &RebalanceListEntries);
1113
1114 if (Result)
1115 {
1116 Result = USB2_PromotePeriods(TtEndpoint,
1117 Rebalance,
1118 &RebalanceListEntries);
1119 }
1120
1121 RebalanceListEntries = 0;
1122
1123 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1124 {
1125 RebalanceListEntries = ix + 1;
1126 }
1127 }
1128 else
1129 {
1130 RebalanceListEntries = 0;
1131 Result = FALSE;
1132 }
1133
1134 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1135 RebalanceListEntries,
1136 Result);
1137
1138 for (ix = 0; ix < RebalanceListEntries; ix++)
1139 {
1140 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1141
1142 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1143 ix,
1144 RebalanceTtEndpoint,
1145 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1146
1147 InsertTailList(&RebalanceList,
1148 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1149 }
1150
1151 if (Rebalance)
1152 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1153
1154 if (Result)
1155 {
1156 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1157 EndpointProperties->InterruptScheduleMask = SMask;
1158
1159 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1160 EndpointProperties->SplitCompletionMask = CMask;
1161
1162 AllocedBusTime = TtEndpoint->CalcBusTime;
1163
1164 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1165 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1166
1167 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1168 EndpointProperties->Period = ActualPeriod;
1169
1170 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1171 EndpointProperties->ScheduleOffset = ScheduleOffset;
1172
1173 Factor = USB2_FRAMES / ActualPeriod;
1174 ASSERT(Factor);
1175
1176 n = ScheduleOffset * Factor;
1177
1178 if (TtExtension)
1179 {
1180 for (ix = 0; ix < Factor; ix++)
1181 {
1182 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1183 }
1184 }
1185 else
1186 {
1187 for (ix = 1; ix < Factor; ix++)
1188 {
1189 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1190 }
1191 }
1192
1193 USBPORT_DumpingEndpointProperties(EndpointProperties);
1194 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
1195
1196 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1197 {
1198 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
1199 }
1200 }
1201
1202 //USB2_Rebalance(FdoDevice, &RebalanceList);
1203
1204 if (!TtExtension)
1205 {
1206 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1207 return Result;
1208 }
1209
1210 for (ix = 0; ix < USB2_FRAMES; ix++)
1211 {
1212 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1213 }
1214
1215 USBPORT_UpdateAllocatedBwTt(TtExtension);
1216
1217 for (ix = 0; ix < USB2_FRAMES; ix++)
1218 {
1219 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
1220 }
1221
1222 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1223
1224 return Result;
1225 }
1226
1227 VOID
1228 NTAPI
1229 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1230 IN PUSBPORT_ENDPOINT Endpoint)
1231 {
1232 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
1233 }
1234
1235 VOID
1236 NTAPI
1237 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
1238 IN PUSB2_TT Tt)
1239 {
1240 ULONG ix;
1241 ULONG jx;
1242
1243 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
1244
1245 Tt->HcExtension = HcExtension;
1246 Tt->DelayTime = 1;
1247 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
1248
1249 for (ix = 0; ix < USB2_FRAMES; ix++)
1250 {
1251 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
1252 Tt->FrameBudget[ix].AltEndpoint = NULL;
1253
1254 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1255 {
1256 Tt->TimeCS[ix][jx] = 0;
1257 Tt->NumStartSplits[ix][jx] = 0;
1258 }
1259
1260 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
1261
1262 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
1263 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
1264 USBPORT_TRANSFER_DIRECTION_OUT,
1265 UsbFullSpeed,
1266 USB2_FRAMES,
1267 0,
1268 Tt);
1269
1270 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
1271 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1272 Tt->IsoEndpoint[ix].StartFrame = ix;
1273 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
1274
1275 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
1276
1277 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
1278 USBPORT_TRANSFER_TYPE_INTERRUPT,
1279 USBPORT_TRANSFER_DIRECTION_OUT,
1280 UsbFullSpeed,
1281 USB2_FRAMES,
1282 0,
1283 Tt);
1284
1285 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
1286 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1287 Tt->IntEndpoint[ix].StartFrame = ix;
1288 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
1289 }
1290 }
1291
1292 VOID
1293 NTAPI
1294 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
1295 {
1296 ULONG ix;
1297 ULONG jx;
1298
1299 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
1300
1301 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
1302
1303 for (ix = 0; ix < USB2_FRAMES; ix++)
1304 {
1305 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1306 {
1307 HcExtension->TimeUsed[ix][jx] = 0;
1308 }
1309 }
1310
1311 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
1312
1313 USB2_InitTT(HcExtension, &HcExtension->HcTt);
1314 }