edc91c1d7013285d92fb756a657ab021b1a0b06a
[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 RtlZeroMemory(TtEndpoint, sizeof(USB2_TT_ENDPOINT));
288
289 TtEndpoint->TtEndpointParams.TransferType = TransferType;
290 TtEndpoint->TtEndpointParams.Direction = Direction;
291 TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
292
293 TtEndpoint->Period = Period;
294 TtEndpoint->MaxPacketSize = MaxPacketSize;
295 TtEndpoint->Tt = Tt;
296 }
297
298 BOOLEAN
299 NTAPI
300 USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
301 IN LONG Frame)
302 {
303 PUSB2_HC_EXTENSION HcExtension;
304 PUSB2_TT Tt;
305 ULONG TransferType;
306 ULONG Direction;
307 ULONG DataTime;
308 ULONG RemainDataTime;
309 ULONG OverheadCS;
310 ULONG OverheadSS;
311 ULONG ix;
312 USHORT PktSize;
313 UCHAR frame;
314 UCHAR uframe;
315 BOOL Result = TRUE;
316
317 DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, TtEndpoint->StartFrame - %X\n",
318 TtEndpoint,
319 Frame,
320 TtEndpoint->StartFrame);
321
322 Tt = TtEndpoint->Tt;
323 HcExtension = Tt->HcExtension;
324
325 TransferType = TtEndpoint->TtEndpointParams.TransferType;
326 Direction = TtEndpoint->TtEndpointParams.Direction;
327
328 if (Frame == 0)
329 {
330 TtEndpoint->StartMicroframe =
331 TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1;
332
333 DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n",
334 TtEndpoint->StartMicroframe);
335 }
336
337 USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
338
339 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
340 {
341 if (Frame == 0)
342 {
343 TtEndpoint->Nums.NumStarts = 1;
344
345 if ((CHAR)TtEndpoint->StartMicroframe < 5)
346 {
347 TtEndpoint->Nums.NumCompletes = 3;
348 }
349 else
350 {
351 TtEndpoint->Nums.NumCompletes = 2;
352 }
353 }
354 }
355 else
356 {
357 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
358 {
359 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
360 ASSERT(FALSE);
361 }
362 else
363 {
364 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
365 ASSERT(FALSE);
366 }
367 }
368
369 frame = TtEndpoint->StartFrame + Frame;
370 uframe = TtEndpoint->StartMicroframe;
371
372 if (TtEndpoint->StartMicroframe == 0xFF)
373 USB2_GetPrevMicroFrame(&frame, &uframe);
374
375 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
376 {
377 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
378 OverheadSS,
379 USB2_MAX_MICROFRAME_ALLOCATION))
380 {
381 Result = FALSE;
382 }
383
384 if (Tt->NumStartSplits[frame][uframe] > (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
385 {
386 DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
387 Tt->NumStartSplits[frame][uframe] + 1);
388
389 ASSERT(FALSE);
390 Result = FALSE;
391 }
392
393 ++Tt->NumStartSplits[frame][uframe];
394 USB2_IncMicroFrame(&frame, &uframe);
395 }
396
397 frame = TtEndpoint->StartFrame + Frame;
398 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
399
400 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
401 {
402 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
403 OverheadCS,
404 USB2_MAX_MICROFRAME_ALLOCATION))
405 {
406 Result = FALSE;
407 }
408
409 USB2_IncMicroFrame(&frame, &uframe);
410 }
411
412 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
413 {
414 DPRINT("USB2_AllocateHS: DIRECTION OUT UNIMPLEMENTED\n");
415 ASSERT(FALSE);
416 }
417 else
418 {
419 frame = TtEndpoint->StartFrame + Frame;
420 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
421
422 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
423 {
424 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
425 {
426 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
427 {
428 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
429 Tt->TimeCS[frame][uframe];
430 }
431 else
432 {
433 RemainDataTime = 0;
434 }
435
436 PktSize = TtEndpoint->MaxPacketSize;
437
438 if (RemainDataTime >= USB2_AddDataBitStuff(PktSize))
439 {
440 DataTime = USB2_AddDataBitStuff(PktSize);
441 }
442 else
443 {
444 DataTime = RemainDataTime;
445 }
446
447 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
448 DataTime,
449 USB2_MAX_MICROFRAME_ALLOCATION))
450 {
451 Result = FALSE;
452 }
453 }
454
455 PktSize = TtEndpoint->MaxPacketSize;
456
457 if (USB2_AddDataBitStuff(PktSize) < USB2_FS_RAW_BYTES_IN_MICROFRAME)
458 {
459 Tt->TimeCS[frame][uframe] += USB2_AddDataBitStuff(PktSize);
460 }
461 else
462 {
463 Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
464 }
465
466 USB2_IncMicroFrame(&frame, &uframe);
467 }
468 }
469
470 DPRINT("USB2_AllocateHS: Result - %X\n", Result);
471 return Result;
472 }
473
474 BOOLEAN
475 NTAPI
476 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
477 IN PUSB2_REBALANCE Rebalance,
478 IN PULONG RebalanceListEntries,
479 IN ULONG MaxFrames)
480 {
481 DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
482 ASSERT(FALSE);
483 return FALSE;
484 }
485
486 BOOLEAN
487 NTAPI
488 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
489 IN PUSB2_REBALANCE Rebalance,
490 IN PULONG RebalanceListEntries)
491 {
492 PUSB2_TT Tt;
493 PUSB2_HC_EXTENSION HcExtension;
494 ULONG Speed;
495 ULONG TimeUsed;
496 ULONG MinTimeUsed;
497 ULONG ix;
498 ULONG frame;
499 ULONG uframe;
500 ULONG Microframe;
501 ULONG TransferType;
502 ULONG Overhead;
503 BOOLEAN Result = TRUE;
504
505 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
506
507 Tt = TtEndpoint->Tt;
508 HcExtension = Tt->HcExtension;
509
510 TtEndpoint->Nums.NumStarts = 0;
511 TtEndpoint->Nums.NumCompletes = 0;
512
513 TtEndpoint->StartFrame = 0;
514 TtEndpoint->StartMicroframe = 0;
515
516 if (TtEndpoint->CalcBusTime)
517 {
518 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
519 return FALSE;
520 }
521
522 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
523
524 if (Speed == UsbHighSpeed)
525 {
526 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
527 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
528 else
529 TtEndpoint->ActualPeriod = TtEndpoint->Period;
530
531 MinTimeUsed = HcExtension->TimeUsed[0][0];
532
533 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
534 {
535 frame = ix / USB2_MICROFRAMES;
536 uframe = ix % (USB2_MICROFRAMES - 1);
537
538 TimeUsed = HcExtension->TimeUsed[frame][uframe];
539
540 if (TimeUsed < MinTimeUsed)
541 {
542 MinTimeUsed = TimeUsed;
543 TtEndpoint->StartFrame = frame;
544 TtEndpoint->StartMicroframe = uframe;
545 }
546 }
547
548 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
549 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
550
551 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
552 TtEndpoint->StartFrame,
553 TtEndpoint->StartMicroframe,
554 TtEndpoint->CalcBusTime);
555
556 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
557 TtEndpoint->StartMicroframe;
558
559 if (Microframe >= USB2_MAX_MICROFRAMES)
560 {
561 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
562 return TRUE;
563 }
564
565 for (ix = Microframe;
566 ix < USB2_MAX_MICROFRAMES;
567 ix += TtEndpoint->ActualPeriod)
568 {
569 frame = ix / USB2_MICROFRAMES;
570 uframe = ix % (USB2_MICROFRAMES - 1);
571
572 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
573 frame,
574 uframe,
575 HcExtension->TimeUsed[frame][uframe]);
576
577 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
578 TtEndpoint->CalcBusTime,
579 USB2_MAX_MICROFRAME_ALLOCATION))
580 {
581 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
582 Result = FALSE;
583 }
584 }
585
586 if (!Result)
587 {
588 for (ix = Microframe;
589 ix < USB2_MAX_MICROFRAMES;
590 ix += TtEndpoint->ActualPeriod)
591 {
592 frame = ix / USB2_MICROFRAMES;
593 uframe = ix % (USB2_MICROFRAMES - 1);
594
595 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
596 }
597 }
598
599 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
600 return TRUE;
601 }
602
603 /* Speed != UsbHighSpeed (FS/LS) */
604
605 if (TtEndpoint->Period > USB2_FRAMES)
606 TtEndpoint->ActualPeriod = USB2_FRAMES;
607 else
608 TtEndpoint->ActualPeriod = TtEndpoint->Period;
609
610 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
611
612 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
613 {
614 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
615 {
616 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
617 TtEndpoint->StartFrame = ix;
618 }
619 }
620
621 TransferType = TtEndpoint->TtEndpointParams.TransferType;
622
623 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
624 {
625 if (Speed == UsbFullSpeed)
626 {
627 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
628 }
629 else
630 {
631 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
632 return FALSE;
633 }
634 }
635 else
636 {
637 if (Speed == UsbFullSpeed)
638 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
639 else
640 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
641 }
642
643 if (Speed == UsbLowSpeed)
644 {
645 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
646 }
647 else
648 {
649 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
650 }
651
652
653 DPRINT("USB2_AllocateTimeForEndpoint: UNIMPLEMENTED. FIXME\n");
654 ASSERT(FALSE);
655 return FALSE;
656 }
657
658 BOOLEAN
659 NTAPI
660 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
661 IN PUSB2_REBALANCE Rebalance,
662 IN PULONG RebalanceListEntries)
663 {
664 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
665 ASSERT(FALSE);
666 return FALSE;
667 }
668
669 VOID
670 NTAPI
671 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
672 {
673 ULONG BusBandwidth;
674 ULONG NewBusBandwidth;
675 ULONG MaxBusBandwidth = 0;
676 ULONG MinBusBandwidth;
677 ULONG ix;
678
679 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
680
681 BusBandwidth = TtExtension->BusBandwidth;
682 MinBusBandwidth = BusBandwidth;
683
684 for (ix = 0; ix < USB2_FRAMES; ix++)
685 {
686 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
687
688 if (NewBusBandwidth > MaxBusBandwidth)
689 MaxBusBandwidth = NewBusBandwidth;
690
691 if (NewBusBandwidth < MinBusBandwidth)
692 MinBusBandwidth = NewBusBandwidth;
693 }
694
695 TtExtension->MaxBandwidth = MaxBusBandwidth;
696
697 if (MinBusBandwidth == BusBandwidth)
698 TtExtension->MinBandwidth = 0;
699 else
700 TtExtension->MinBandwidth = MinBusBandwidth;
701 }
702
703 BOOLEAN
704 NTAPI
705 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
706 IN PUSBPORT_ENDPOINT Endpoint)
707 {
708 PUSBPORT_DEVICE_EXTENSION FdoExtension;
709 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
710 PUSB2_TT_EXTENSION TtExtension;
711 ULONG TransferType;
712 PUSB2_REBALANCE Rebalance;
713 LIST_ENTRY RebalanceList;
714 ULONG RebalanceListEntries;
715 PUSB2_TT_ENDPOINT TtEndpoint;
716 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
717 PUSB2_TT Tt;
718 USB_DEVICE_SPEED DeviceSpeed;
719 ULONG Period;
720 ULONG AllocedBusTime;
721 ULONG EndpointBandwidth;
722 ULONG ScheduleOffset;
723 ULONG Factor;
724 ULONG ix;
725 ULONG n;
726 BOOLEAN Direction;
727 UCHAR SMask;
728 UCHAR CMask;
729 UCHAR ActualPeriod;
730 BOOLEAN Result;
731
732 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
733 FdoDevice,
734 Endpoint);
735
736 EndpointProperties = &Endpoint->EndpointProperties;
737 EndpointProperties->ScheduleOffset = 0;
738
739 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
740 {
741 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
742 return TRUE;
743 }
744
745 FdoExtension = FdoDevice->DeviceExtension;
746
747 TransferType = EndpointProperties->TransferType;
748 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
749
750 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
751 TransferType == USBPORT_TRANSFER_TYPE_BULK)
752 {
753 return TRUE;
754 }
755
756 if (Endpoint->TtExtension)
757 TtExtension = Endpoint->TtExtension;
758 else
759 TtExtension = NULL;
760
761 InitializeListHead(&RebalanceList);
762
763 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
764 sizeof(USB2_REBALANCE),
765 USB_PORT_TAG);
766
767 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
768 Rebalance,
769 TtExtension);
770
771 if (Rebalance)
772 {
773 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
774
775 TtEndpoint = Endpoint->TtEndpoint;
776 TtEndpoint->Endpoint = Endpoint;
777
778 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
779 DeviceSpeed = EndpointProperties->DeviceSpeed;
780
781 switch (DeviceSpeed)
782 {
783 case UsbLowSpeed:
784 case UsbFullSpeed:
785 {
786 Tt = &TtExtension->Tt;
787
788 Period = USB2_FRAMES;
789
790 while (Period > 0 && Period > EndpointProperties->Period)
791 {
792 Period >>= 1;
793 }
794
795 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
796 break;
797 }
798
799 case UsbHighSpeed:
800 {
801 Tt = &FdoExtension->Usb2Extension->HcTt;
802
803 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
804 Period = USB2_MAX_MICROFRAMES;
805 else
806 Period = EndpointProperties->Period;
807
808 break;
809 }
810
811 default:
812 {
813 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
814 DeviceSpeed);
815
816 DbgBreakPoint();
817
818 Tt = &TtExtension->Tt;
819 break;
820 }
821 }
822
823 USB2_InitTtEndpoint(TtEndpoint,
824 TransferType,
825 Direction,
826 DeviceSpeed,
827 Period,
828 EndpointProperties->MaxPacketSize,
829 Tt);
830
831 RebalanceListEntries = USB2_FRAMES - 2;
832
833 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
834 Rebalance,
835 &RebalanceListEntries);
836
837 if (Result)
838 {
839 Result = USB2_PromotePeriods(TtEndpoint,
840 Rebalance,
841 &RebalanceListEntries);
842 }
843
844 RebalanceListEntries = 0;
845
846 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
847 {
848 RebalanceListEntries = ix + 1;
849 }
850 }
851 else
852 {
853 RebalanceListEntries = 0;
854 Result = FALSE;
855 }
856
857 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
858 RebalanceListEntries,
859 Result);
860
861 for (ix = 0; ix < RebalanceListEntries; ix++)
862 {
863 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
864
865 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
866 ix,
867 RebalanceTtEndpoint,
868 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
869
870 InsertTailList(&RebalanceList,
871 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
872 }
873
874 if (Rebalance)
875 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
876
877 if (Result)
878 {
879 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
880 EndpointProperties->InterruptScheduleMask = SMask;
881
882 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
883 EndpointProperties->SplitCompletionMask = CMask;
884
885 AllocedBusTime = TtEndpoint->CalcBusTime;
886
887 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
888 EndpointProperties->UsbBandwidth = EndpointBandwidth;
889
890 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
891 EndpointProperties->Period = ActualPeriod;
892
893 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
894 EndpointProperties->ScheduleOffset = ScheduleOffset;
895
896 Factor = USB2_FRAMES / ActualPeriod;
897 ASSERT(Factor);
898
899 n = ScheduleOffset * Factor;
900
901 if (TtExtension)
902 {
903 for (ix = 0; ix < Factor; ix++)
904 {
905 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
906 }
907 }
908 else
909 {
910 for (ix = 1; ix < Factor; ix++)
911 {
912 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
913 }
914 }
915
916 USBPORT_DumpingEndpointProperties(EndpointProperties);
917 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
918
919 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
920 {
921 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
922 }
923 }
924
925 //USB2_Rebalance(FdoDevice, &RebalanceList);
926
927 if (!TtExtension)
928 {
929 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
930 return Result;
931 }
932
933 for (ix = 0; ix < USB2_FRAMES; ix++)
934 {
935 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
936 }
937
938 USBPORT_UpdateAllocatedBwTt(TtExtension);
939
940 for (ix = 0; ix < USB2_FRAMES; ix++)
941 {
942 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
943 }
944
945 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
946
947 return Result;
948 }
949
950 VOID
951 NTAPI
952 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
953 IN PUSBPORT_ENDPOINT Endpoint)
954 {
955 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
956 }
957
958 VOID
959 NTAPI
960 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
961 IN PUSB2_TT Tt)
962 {
963 ULONG ix;
964 ULONG jx;
965
966 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
967
968 Tt->HcExtension = HcExtension;
969 Tt->DelayTime = 1;
970 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
971
972 for (ix = 0; ix < USB2_FRAMES; ix++)
973 {
974 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
975 Tt->FrameBudget[ix].AltEndpoint = NULL;
976
977 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
978 {
979 Tt->TimeCS[ix][jx] = 0;
980 Tt->NumStartSplits[ix][jx] = 0;
981 }
982
983 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
984
985 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
986 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
987 USBPORT_TRANSFER_DIRECTION_OUT,
988 UsbFullSpeed,
989 USB2_FRAMES,
990 0,
991 Tt);
992
993 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
994 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
995 Tt->IsoEndpoint[ix].StartFrame = ix;
996 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
997
998 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
999
1000 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
1001 USBPORT_TRANSFER_TYPE_INTERRUPT,
1002 USBPORT_TRANSFER_DIRECTION_OUT,
1003 UsbFullSpeed,
1004 USB2_FRAMES,
1005 0,
1006 Tt);
1007
1008 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
1009 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1010 Tt->IntEndpoint[ix].StartFrame = ix;
1011 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
1012 }
1013 }
1014
1015 VOID
1016 NTAPI
1017 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
1018 {
1019 ULONG ix;
1020 ULONG jx;
1021
1022 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
1023
1024 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
1025
1026 for (ix = 0; ix < USB2_FRAMES; ix++)
1027 {
1028 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1029 {
1030 HcExtension->TimeUsed[ix][jx] = 0;
1031 }
1032 }
1033
1034 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
1035
1036 USB2_InitTT(HcExtension, &HcExtension->HcTt);
1037 }