[USBPORT] Add stub for USB2_DeallocateHS().
[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_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
496 IN PUSB2_REBALANCE Rebalance,
497 IN PULONG RebalanceListEntries,
498 IN ULONG MaxFrames)
499 {
500 DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
501 ASSERT(FALSE);
502 return FALSE;
503 }
504
505 BOOLEAN
506 NTAPI
507 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
508 IN PUSB2_REBALANCE Rebalance,
509 IN PULONG RebalanceListEntries)
510 {
511 PUSB2_TT Tt;
512 PUSB2_HC_EXTENSION HcExtension;
513 ULONG Speed;
514 ULONG TimeUsed;
515 ULONG MinTimeUsed;
516 ULONG ix;
517 ULONG frame;
518 ULONG uframe;
519 ULONG Microframe;
520 ULONG TransferType;
521 ULONG Overhead;
522 ULONG LatestStart;
523 PUSB2_TT_ENDPOINT prevTtEndpoint;
524 PUSB2_TT_ENDPOINT nextTtEndpoint;
525 PUSB2_TT_ENDPOINT IntEndpoint;
526 ULONG StartTime;
527 ULONG calcBusTime;
528 BOOLEAN Result = TRUE;
529
530 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
531
532 Tt = TtEndpoint->Tt;
533 HcExtension = Tt->HcExtension;
534
535 TtEndpoint->Nums.NumStarts = 0;
536 TtEndpoint->Nums.NumCompletes = 0;
537
538 TtEndpoint->StartFrame = 0;
539 TtEndpoint->StartMicroframe = 0;
540
541 if (TtEndpoint->CalcBusTime)
542 {
543 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
544 return FALSE;
545 }
546
547 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
548
549 if (Speed == UsbHighSpeed)
550 {
551 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
552 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
553 else
554 TtEndpoint->ActualPeriod = TtEndpoint->Period;
555
556 MinTimeUsed = HcExtension->TimeUsed[0][0];
557
558 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
559 {
560 frame = ix / USB2_MICROFRAMES;
561 uframe = ix % (USB2_MICROFRAMES - 1);
562
563 TimeUsed = HcExtension->TimeUsed[frame][uframe];
564
565 if (TimeUsed < MinTimeUsed)
566 {
567 MinTimeUsed = TimeUsed;
568 TtEndpoint->StartFrame = frame;
569 TtEndpoint->StartMicroframe = uframe;
570 }
571 }
572
573 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
574 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
575
576 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
577 TtEndpoint->StartFrame,
578 TtEndpoint->StartMicroframe,
579 TtEndpoint->CalcBusTime);
580
581 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
582 TtEndpoint->StartMicroframe;
583
584 if (Microframe >= USB2_MAX_MICROFRAMES)
585 {
586 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
587 return TRUE;
588 }
589
590 for (ix = Microframe;
591 ix < USB2_MAX_MICROFRAMES;
592 ix += TtEndpoint->ActualPeriod)
593 {
594 frame = ix / USB2_MICROFRAMES;
595 uframe = ix % (USB2_MICROFRAMES - 1);
596
597 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
598 frame,
599 uframe,
600 HcExtension->TimeUsed[frame][uframe]);
601
602 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
603 TtEndpoint->CalcBusTime,
604 USB2_MAX_MICROFRAME_ALLOCATION))
605 {
606 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
607 Result = FALSE;
608 }
609 }
610
611 if (!Result)
612 {
613 for (ix = Microframe;
614 ix < USB2_MAX_MICROFRAMES;
615 ix += TtEndpoint->ActualPeriod)
616 {
617 frame = ix / USB2_MICROFRAMES;
618 uframe = ix % (USB2_MICROFRAMES - 1);
619
620 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
621 }
622 }
623
624 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
625 return TRUE;
626 }
627
628 /* Speed != UsbHighSpeed (FS/LS) */
629
630 if (TtEndpoint->Period > USB2_FRAMES)
631 TtEndpoint->ActualPeriod = USB2_FRAMES;
632 else
633 TtEndpoint->ActualPeriod = TtEndpoint->Period;
634
635 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
636
637 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
638 {
639 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
640 {
641 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
642 TtEndpoint->StartFrame = ix;
643 }
644 }
645
646 TransferType = TtEndpoint->TtEndpointParams.TransferType;
647
648 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
649 {
650 if (Speed == UsbFullSpeed)
651 {
652 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
653 }
654 else
655 {
656 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
657 return FALSE;
658 }
659 }
660 else
661 {
662 if (Speed == UsbFullSpeed)
663 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
664 else
665 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
666 }
667
668 if (Speed == UsbLowSpeed)
669 {
670 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
671 }
672 else
673 {
674 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
675 }
676
677 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
678
679 for (ix = 0;
680 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
681 ix += TtEndpoint->ActualPeriod)
682 {
683 frame = TtEndpoint->StartFrame + ix;
684
685 if (Tt->FrameBudget[frame].AltEndpoint &&
686 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
687 {
688 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
689 return FALSE;
690 }
691
692 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
693 prevTtEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
694 else
695 prevTtEndpoint = Tt->FrameBudget[frame].IntEndpoint;
696
697 for (nextTtEndpoint = prevTtEndpoint->NextTtEndpoint;
698 nextTtEndpoint;
699 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
700 {
701 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
702 {
703 break;
704 }
705
706 prevTtEndpoint = nextTtEndpoint;
707 }
708
709 StartTime = USB2_GetStartTime(nextTtEndpoint,
710 TtEndpoint,
711 prevTtEndpoint,
712 frame);
713
714 if (StartTime > LatestStart)
715 LatestStart = StartTime;
716 }
717
718 TtEndpoint->StartTime = LatestStart;
719
720 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
721 {
722 TtEndpoint->CalcBusTime = 0;
723 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
724 return FALSE;
725 }
726
727 for (ix = 0, frame = -TtEndpoint->StartFrame;
728 ix < USB2_FRAMES;
729 ix++, frame++)
730 {
731 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
732 ix,
733 frame,
734 TtEndpoint->StartFrame);
735
736 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
737 {
738 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
739 ASSERT(FALSE);
740 }
741 else
742 {
743 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
744 nextTtEndpoint = IntEndpoint->NextTtEndpoint;
745
746 for (nextTtEndpoint = IntEndpoint->NextTtEndpoint;
747 nextTtEndpoint;
748 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
749 {
750 if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
751 break;
752 IntEndpoint = nextTtEndpoint;
753 }
754
755 if ((frame % TtEndpoint->ActualPeriod) == 0)
756 {
757 calcBusTime = 0;
758 }
759 else
760 {
761 if (nextTtEndpoint)
762 {
763 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
764 nextTtEndpoint->StartTime;
765 }
766 else
767 {
768 calcBusTime = TtEndpoint->CalcBusTime;
769 }
770
771 if (calcBusTime > 0)
772 {
773 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
774
775 if (!USB2_AllocateCheck(&TimeUsed,
776 calcBusTime,
777 USB2_FS_MAX_PERIODIC_ALLOCATION))
778 {
779 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
780 Result = FALSE;
781 }
782 }
783 }
784
785 if (nextTtEndpoint != TtEndpoint)
786 {
787 if ((frame % TtEndpoint->ActualPeriod) == 0)
788 {
789 if (frame == 0)
790 {
791 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
792 TtEndpoint->NextTtEndpoint = nextTtEndpoint;
793 }
794
795 IntEndpoint->NextTtEndpoint = TtEndpoint;
796
797 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextTtEndpoint - %p\n",
798 TtEndpoint,
799 nextTtEndpoint);
800 }
801
802 if (calcBusTime > 0)
803 {
804 BOOLEAN IsMoved;
805 BOOLEAN MoveResult;
806
807 DPRINT("USB2_AllocateTimeForEndpoint: nextTtEndpoint - %p, calcBusTime - %X\n",
808 nextTtEndpoint,
809 calcBusTime);
810
811 for (;
812 nextTtEndpoint;
813 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
814 {
815 MoveResult = USB2_MoveTtEndpoint(nextTtEndpoint,
816 calcBusTime,
817 Rebalance,
818 *RebalanceListEntries,
819 &IsMoved);
820
821 if (!IsMoved)
822 {
823 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
824 Result = FALSE;
825 }
826
827 if (!MoveResult)
828 break;
829 }
830 }
831 }
832 }
833
834 if ((frame % TtEndpoint->ActualPeriod) == 0)
835 {
836 if (!USB2_AllocateHS(TtEndpoint, frame))
837 {
838 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
839 Result = FALSE;
840 }
841
842 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
843 }
844
845 if (Result == FALSE)
846 {
847 USB2_DeallocateEndpointBudget(TtEndpoint,
848 Rebalance,
849 RebalanceListEntries,
850 ix + 1);
851
852 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
853 return FALSE;
854 }
855 }
856
857 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
858 return Result;
859 }
860
861 BOOLEAN
862 NTAPI
863 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
864 IN PUSB2_REBALANCE Rebalance,
865 IN PULONG RebalanceListEntries)
866 {
867 DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
868 ASSERT(FALSE);
869 return FALSE;
870 }
871
872 VOID
873 NTAPI
874 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
875 {
876 ULONG BusBandwidth;
877 ULONG NewBusBandwidth;
878 ULONG MaxBusBandwidth = 0;
879 ULONG MinBusBandwidth;
880 ULONG ix;
881
882 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
883
884 BusBandwidth = TtExtension->BusBandwidth;
885 MinBusBandwidth = BusBandwidth;
886
887 for (ix = 0; ix < USB2_FRAMES; ix++)
888 {
889 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
890
891 if (NewBusBandwidth > MaxBusBandwidth)
892 MaxBusBandwidth = NewBusBandwidth;
893
894 if (NewBusBandwidth < MinBusBandwidth)
895 MinBusBandwidth = NewBusBandwidth;
896 }
897
898 TtExtension->MaxBandwidth = MaxBusBandwidth;
899
900 if (MinBusBandwidth == BusBandwidth)
901 TtExtension->MinBandwidth = 0;
902 else
903 TtExtension->MinBandwidth = MinBusBandwidth;
904 }
905
906 BOOLEAN
907 NTAPI
908 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
909 IN PUSBPORT_ENDPOINT Endpoint)
910 {
911 PUSBPORT_DEVICE_EXTENSION FdoExtension;
912 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
913 PUSB2_TT_EXTENSION TtExtension;
914 ULONG TransferType;
915 PUSB2_REBALANCE Rebalance;
916 LIST_ENTRY RebalanceList;
917 ULONG RebalanceListEntries;
918 PUSB2_TT_ENDPOINT TtEndpoint;
919 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
920 PUSB2_TT Tt;
921 USB_DEVICE_SPEED DeviceSpeed;
922 ULONG Period;
923 ULONG AllocedBusTime;
924 ULONG EndpointBandwidth;
925 ULONG ScheduleOffset;
926 ULONG Factor;
927 ULONG ix;
928 ULONG n;
929 BOOLEAN Direction;
930 UCHAR SMask;
931 UCHAR CMask;
932 UCHAR ActualPeriod;
933 BOOLEAN Result;
934
935 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
936 FdoDevice,
937 Endpoint);
938
939 EndpointProperties = &Endpoint->EndpointProperties;
940 EndpointProperties->ScheduleOffset = 0;
941
942 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
943 {
944 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
945 return TRUE;
946 }
947
948 FdoExtension = FdoDevice->DeviceExtension;
949
950 TransferType = EndpointProperties->TransferType;
951 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
952
953 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
954 TransferType == USBPORT_TRANSFER_TYPE_BULK)
955 {
956 return TRUE;
957 }
958
959 if (Endpoint->TtExtension)
960 TtExtension = Endpoint->TtExtension;
961 else
962 TtExtension = NULL;
963
964 InitializeListHead(&RebalanceList);
965
966 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
967 sizeof(USB2_REBALANCE),
968 USB_PORT_TAG);
969
970 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
971 Rebalance,
972 TtExtension);
973
974 if (Rebalance)
975 {
976 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
977
978 TtEndpoint = Endpoint->TtEndpoint;
979 TtEndpoint->Endpoint = Endpoint;
980
981 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
982 DeviceSpeed = EndpointProperties->DeviceSpeed;
983
984 switch (DeviceSpeed)
985 {
986 case UsbLowSpeed:
987 case UsbFullSpeed:
988 {
989 Tt = &TtExtension->Tt;
990
991 Period = USB2_FRAMES;
992
993 while (Period > 0 && Period > EndpointProperties->Period)
994 {
995 Period >>= 1;
996 }
997
998 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
999 break;
1000 }
1001
1002 case UsbHighSpeed:
1003 {
1004 Tt = &FdoExtension->Usb2Extension->HcTt;
1005
1006 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
1007 Period = USB2_MAX_MICROFRAMES;
1008 else
1009 Period = EndpointProperties->Period;
1010
1011 break;
1012 }
1013
1014 default:
1015 {
1016 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1017 DeviceSpeed);
1018
1019 DbgBreakPoint();
1020
1021 Tt = &TtExtension->Tt;
1022 break;
1023 }
1024 }
1025
1026 USB2_InitTtEndpoint(TtEndpoint,
1027 TransferType,
1028 Direction,
1029 DeviceSpeed,
1030 Period,
1031 EndpointProperties->MaxPacketSize,
1032 Tt);
1033
1034 RebalanceListEntries = USB2_FRAMES - 2;
1035
1036 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1037 Rebalance,
1038 &RebalanceListEntries);
1039
1040 if (Result)
1041 {
1042 Result = USB2_PromotePeriods(TtEndpoint,
1043 Rebalance,
1044 &RebalanceListEntries);
1045 }
1046
1047 RebalanceListEntries = 0;
1048
1049 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1050 {
1051 RebalanceListEntries = ix + 1;
1052 }
1053 }
1054 else
1055 {
1056 RebalanceListEntries = 0;
1057 Result = FALSE;
1058 }
1059
1060 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1061 RebalanceListEntries,
1062 Result);
1063
1064 for (ix = 0; ix < RebalanceListEntries; ix++)
1065 {
1066 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1067
1068 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1069 ix,
1070 RebalanceTtEndpoint,
1071 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1072
1073 InsertTailList(&RebalanceList,
1074 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1075 }
1076
1077 if (Rebalance)
1078 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1079
1080 if (Result)
1081 {
1082 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1083 EndpointProperties->InterruptScheduleMask = SMask;
1084
1085 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1086 EndpointProperties->SplitCompletionMask = CMask;
1087
1088 AllocedBusTime = TtEndpoint->CalcBusTime;
1089
1090 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1091 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1092
1093 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1094 EndpointProperties->Period = ActualPeriod;
1095
1096 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1097 EndpointProperties->ScheduleOffset = ScheduleOffset;
1098
1099 Factor = USB2_FRAMES / ActualPeriod;
1100 ASSERT(Factor);
1101
1102 n = ScheduleOffset * Factor;
1103
1104 if (TtExtension)
1105 {
1106 for (ix = 0; ix < Factor; ix++)
1107 {
1108 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1109 }
1110 }
1111 else
1112 {
1113 for (ix = 1; ix < Factor; ix++)
1114 {
1115 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1116 }
1117 }
1118
1119 USBPORT_DumpingEndpointProperties(EndpointProperties);
1120 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
1121
1122 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1123 {
1124 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
1125 }
1126 }
1127
1128 //USB2_Rebalance(FdoDevice, &RebalanceList);
1129
1130 if (!TtExtension)
1131 {
1132 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1133 return Result;
1134 }
1135
1136 for (ix = 0; ix < USB2_FRAMES; ix++)
1137 {
1138 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1139 }
1140
1141 USBPORT_UpdateAllocatedBwTt(TtExtension);
1142
1143 for (ix = 0; ix < USB2_FRAMES; ix++)
1144 {
1145 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
1146 }
1147
1148 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
1149
1150 return Result;
1151 }
1152
1153 VOID
1154 NTAPI
1155 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1156 IN PUSBPORT_ENDPOINT Endpoint)
1157 {
1158 DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
1159 }
1160
1161 VOID
1162 NTAPI
1163 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
1164 IN PUSB2_TT Tt)
1165 {
1166 ULONG ix;
1167 ULONG jx;
1168
1169 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
1170
1171 Tt->HcExtension = HcExtension;
1172 Tt->DelayTime = 1;
1173 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
1174
1175 for (ix = 0; ix < USB2_FRAMES; ix++)
1176 {
1177 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
1178 Tt->FrameBudget[ix].AltEndpoint = NULL;
1179
1180 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1181 {
1182 Tt->TimeCS[ix][jx] = 0;
1183 Tt->NumStartSplits[ix][jx] = 0;
1184 }
1185
1186 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
1187
1188 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
1189 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
1190 USBPORT_TRANSFER_DIRECTION_OUT,
1191 UsbFullSpeed,
1192 USB2_FRAMES,
1193 0,
1194 Tt);
1195
1196 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
1197 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1198 Tt->IsoEndpoint[ix].StartFrame = ix;
1199 Tt->IsoEndpoint[ix].StartMicroframe = 0xFF;
1200
1201 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
1202
1203 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
1204 USBPORT_TRANSFER_TYPE_INTERRUPT,
1205 USBPORT_TRANSFER_DIRECTION_OUT,
1206 UsbFullSpeed,
1207 USB2_FRAMES,
1208 0,
1209 Tt);
1210
1211 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
1212 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
1213 Tt->IntEndpoint[ix].StartFrame = ix;
1214 Tt->IntEndpoint[ix].StartMicroframe = 0xFF;
1215 }
1216 }
1217
1218 VOID
1219 NTAPI
1220 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
1221 {
1222 ULONG ix;
1223 ULONG jx;
1224
1225 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
1226
1227 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
1228
1229 for (ix = 0; ix < USB2_FRAMES; ix++)
1230 {
1231 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
1232 {
1233 HcExtension->TimeUsed[ix][jx] = 0;
1234 }
1235 }
1236
1237 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
1238
1239 USB2_InitTT(HcExtension, &HcExtension->HcTt);
1240 }