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 static const UCHAR CMASKS[USB2_MICROFRAMES] = {
14 0x1C, 0x38, 0x70, 0xE0, 0xC1, 0x83, 0x07, 0x0E
15 };
16
17 BOOLEAN
18 NTAPI
USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,IN ULONG CalcBusTime,IN ULONG LimitAllocation)19 USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,
20 IN ULONG CalcBusTime,
21 IN ULONG LimitAllocation)
22 {
23 ULONG BusTime;
24 BOOLEAN Result = TRUE;
25
26 BusTime = *OutTimeUsed + CalcBusTime;
27 *OutTimeUsed += CalcBusTime;
28
29 if (BusTime > LimitAllocation)
30 {
31 DPRINT("USB2_AllocateCheck: BusTime > LimitAllocation\n");
32 Result = FALSE;
33 }
34
35 return Result;
36 }
37
38 USHORT
39 NTAPI
USB2_AddDataBitStuff(IN USHORT DataTime)40 USB2_AddDataBitStuff(IN USHORT DataTime)
41 {
42 return (DataTime + (DataTime / 16));
43 }
44
45 VOID
46 NTAPI
USB2_IncMicroFrame(OUT PUCHAR frame,OUT PUCHAR uframe)47 USB2_IncMicroFrame(OUT PUCHAR frame,
48 OUT PUCHAR uframe)
49 {
50 ++*uframe;
51
52 if (*uframe > (USB2_MICROFRAMES - 1))
53 {
54 *uframe = 0;
55 *frame = (*frame + 1) & (USB2_FRAMES - 1);
56 }
57 }
58
59 VOID
60 NTAPI
USB2_GetPrevMicroFrame(OUT PUCHAR frame,OUT PUCHAR uframe)61 USB2_GetPrevMicroFrame(OUT PUCHAR frame,
62 OUT PUCHAR uframe)
63 {
64 *uframe = USB2_MICROFRAMES - 1;
65
66 if (*frame)
67 --*frame;
68 else
69 *frame = USB2_FRAMES - 1;
70 }
71
72 BOOLEAN
73 NTAPI
USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint)74 USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
75 IN PUSB2_TT_ENDPOINT TtEndpoint)
76 {
77 ULONG TransferType;
78
79 DPRINT("USB2_CheckTtEndpointInsert: nextTtEndpoint - %p, TtEndpoint - %p\n",
80 nextTtEndpoint,
81 TtEndpoint);
82
83 ASSERT(TtEndpoint);
84
85 if (TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
86 {
87 DPRINT1("USB2_CheckTtEndpointInsert: Result - FALSE\n");
88 return FALSE;
89 }
90
91 if (!nextTtEndpoint)
92 {
93 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
94 return TRUE;
95 }
96
97 TransferType = TtEndpoint->TtEndpointParams.TransferType;
98
99 if (nextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod &&
100 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
101 {
102 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
103 return TRUE;
104 }
105
106 if ((nextTtEndpoint->ActualPeriod <= TtEndpoint->ActualPeriod &&
107 TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) ||
108 nextTtEndpoint == TtEndpoint)
109 {
110 DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
111 return TRUE;
112 }
113
114 DPRINT("USB2_CheckTtEndpointInsert: Result - FALSE\n");
115 return FALSE;
116 }
117
118 ULONG
119 NTAPI
USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)120 USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
121 {
122 ULONG TransferType;
123 ULONG Direction;
124 ULONG DeviceSpeed;
125 ULONG Overhead;
126 ULONG HostDelay;
127
128 TransferType = TtEndpoint->TtEndpointParams.TransferType;
129 Direction = TtEndpoint->TtEndpointParams.Direction;
130 DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
131
132 HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
133
134 if (DeviceSpeed == UsbHighSpeed)
135 {
136 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
137 {
138 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
139 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
140 else
141 Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
142 }
143 else
144 {
145 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
146 Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
147 else
148 Overhead = HostDelay + USB2_HS_INTERRUPT_IN_OVERHEAD;
149 }
150 }
151 else if (DeviceSpeed == UsbFullSpeed)
152 {
153 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
154 Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
155 else
156 Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
157 }
158 else
159 {
160 Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
161 }
162
163 return Overhead;
164 }
165
166 VOID
167 NTAPI
USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PULONG OverheadSS,IN PULONG OverheadCS)168 USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,
169 IN PULONG OverheadSS,
170 IN PULONG OverheadCS)
171 {
172 ULONG TransferType;
173 ULONG Direction;
174 ULONG HostDelay;
175
176 TransferType = TtEndpoint->TtEndpointParams.TransferType;
177 Direction = TtEndpoint->TtEndpointParams.Direction;
178
179 HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
180
181 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
182 {
183 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
184 {
185 *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD;
186 *OverheadCS = 0;
187 }
188 else
189 {
190 *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_OUT_OVERHEAD;
191 *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_OUT_OVERHEAD;
192 }
193 }
194 else
195 {
196 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
197 {
198 *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD;
199 *OverheadCS = HostDelay + USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD;
200 }
201 else
202 {
203 *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_IN_OVERHEAD;
204 *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_IN_OVERHEAD;
205 }
206 }
207 }
208
209 ULONG
210 NTAPI
USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,IN ULONG Frame)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
USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_TT_ENDPOINT prevTtEndpoint,IN ULONG Frame)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
USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN UCHAR TransferType,IN UCHAR Direction,IN UCHAR DeviceSpeed,IN USHORT Period,IN USHORT MaxPacketSize,IN PUSB2_TT Tt)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
USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,IN LONG Frame)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 == USB2_PREV_MICROFRAME)
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 == USB2_PREV_MICROFRAME)
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
USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,IN ULONG Frame)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 == USB2_PREV_MICROFRAME)
539 USB2_GetPrevMicroFrame(&frame, &uframe);
540
541 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
542 {
543 HcExtension->TimeUsed[frame][uframe] -= OverheadSS;
544 --Tt->NumStartSplits[frame][uframe];
545 USB2_IncMicroFrame(&frame, &uframe);
546 }
547
548 frame = TtEndpoint->StartFrame + Frame;
549 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
550
551 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
552 {
553 HcExtension->TimeUsed[frame][uframe] -= OverheadCS;
554 USB2_IncMicroFrame(&frame, &uframe);
555 }
556
557 Direction = TtEndpoint->TtEndpointParams.Direction;
558 PktSize = TtEndpoint->MaxPacketSize;
559 PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
560
561 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
562 {
563 frame = TtEndpoint->StartFrame + Frame;
564 uframe = TtEndpoint->StartMicroframe;
565
566 if (TtEndpoint->StartMicroframe == USB2_PREV_MICROFRAME)
567 USB2_GetPrevMicroFrame(&frame, &uframe);
568
569 DataTime = 0;
570
571 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
572 {
573 DataSize = PktSizeBitStuff - DataTime;
574
575 if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
576 CurrentDataTime = PktSizeBitStuff - DataTime;
577 else
578 CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
579
580 HcExtension->TimeUsed[frame][uframe] -= CurrentDataTime;
581 USB2_IncMicroFrame(&frame, &uframe);
582 DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
583 }
584 }
585 else
586 {
587 frame = TtEndpoint->StartFrame + Frame;
588 uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
589
590 for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
591 {
592 if (PktSizeBitStuff >= USB2_FS_RAW_BYTES_IN_MICROFRAME)
593 CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
594 else
595 CurrentDataTime = PktSizeBitStuff;
596
597 Tt->TimeCS[frame][uframe] -= CurrentDataTime;
598
599 if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
600 {
601 RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
602 Tt->TimeCS[frame][uframe];
603
604 if (RemainDataTime >= PktSizeBitStuff)
605 RemainDataTime = PktSizeBitStuff;
606
607 HcExtension->TimeUsed[frame][uframe] -= RemainDataTime;
608 }
609
610 USB2_IncMicroFrame(&frame, &uframe);
611 }
612 }
613
614 return;
615 }
616
617 BOOLEAN
618 NTAPI
USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN LONG BusTime,IN PUSB2_REBALANCE Rebalance,IN ULONG RebalanceListEntries,OUT BOOLEAN * OutResult)619 USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
620 IN LONG BusTime,
621 IN PUSB2_REBALANCE Rebalance,
622 IN ULONG RebalanceListEntries,
623 OUT BOOLEAN * OutResult)
624 {
625 ULONG EndBusTime;
626 ULONG TransferType;
627 ULONG Num;
628 UCHAR ix;
629
630 DPRINT("USB2_MoveTtEndpoint: TtEndpoint - %p, BusTime - %X\n",
631 TtEndpoint,
632 BusTime);
633
634 *OutResult = TRUE;
635
636 for (Num = 0; Rebalance->RebalanceEndpoint[Num]; Num++)
637 {
638 if (Rebalance->RebalanceEndpoint[Num] == TtEndpoint)
639 break;
640 }
641
642 DPRINT("USB2_MoveTtEndpoint: Num - %X\n", Num);
643
644 TransferType = TtEndpoint->TtEndpointParams.TransferType;
645
646 if (Rebalance->RebalanceEndpoint[Num] &&
647 TtEndpoint->TtEndpointParams.EndpointMoved &&
648 ((TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT) || BusTime >= 0))
649 {
650 DPRINT("USB2_MoveTtEndpoint: result - FALSE\n");
651 return FALSE;
652 }
653
654 for (ix = 0;
655 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
656 ix += TtEndpoint->ActualPeriod)
657 {
658 USB2_DeallocateHS(TtEndpoint, ix);
659 }
660
661 TtEndpoint->StartTime += BusTime;
662
663 EndBusTime = TtEndpoint->StartTime + TtEndpoint->CalcBusTime;
664
665 if (EndBusTime > USB2_FS_MAX_PERIODIC_ALLOCATION)
666 {
667 DPRINT("USB2_MoveTtEndpoint: EndBusTime is too large!\n");
668 *OutResult = FALSE;
669 }
670
671 TtEndpoint->TtEndpointParams.EndpointMoved = 1;
672
673 if (Rebalance->RebalanceEndpoint[Num] == NULL)
674 {
675 if (Num >= RebalanceListEntries)
676 {
677 DPRINT("USB2_MoveTtEndpoint: Too many changes!\n");
678 *OutResult = FALSE;
679 }
680 else
681 {
682 Rebalance->RebalanceEndpoint[Num] = TtEndpoint;
683 Rebalance->RebalanceEndpoint[Num + 1] = NULL;
684 }
685 }
686
687 for (ix = 0;
688 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
689 ix += TtEndpoint->ActualPeriod)
690 {
691 if (!USB2_AllocateHS(TtEndpoint, ix))
692 {
693 DPRINT("USB2_MoveTtEndpoint: OutResult - FALSE\n");
694 OutResult = FALSE;
695 }
696 }
697
698 DPRINT("USB2_MoveTtEndpoint: result - TRUE\n");
699 return TRUE;
700 }
701
702 BOOLEAN
703 NTAPI
USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,IN PUSB2_TT_ENDPOINT TtEndpoint)704 USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,
705 IN PUSB2_TT_ENDPOINT TtEndpoint)
706 {
707 UCHAR Frame;
708
709 DPRINT("USB2_CommonFrames: \n");
710
711 if (NextTtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms ||
712 TtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms)
713 {
714 return TRUE;
715 }
716
717 if (NextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod)
718 Frame = TtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
719 else
720 Frame = NextTtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
721
722 return (Frame == TtEndpoint->StartFrame);
723 }
724
725 VOID
726 NTAPI
USB2_ConvertFrame(IN UCHAR Frame,IN UCHAR Microframe,OUT PUCHAR HcFrame,OUT PUCHAR HcMicroframe)727 USB2_ConvertFrame(IN UCHAR Frame,
728 IN UCHAR Microframe,
729 OUT PUCHAR HcFrame,
730 OUT PUCHAR HcMicroframe)
731 {
732 DPRINT("USB2_ConvertFrame: Frame - %x, Microframe - %x\n",
733 Frame,
734 Microframe);
735
736 if (Microframe == USB2_PREV_MICROFRAME)
737 {
738 *HcFrame = Frame;
739 *HcMicroframe = 0;
740 }
741
742 if (Microframe <= (USB2_MICROFRAMES - 2))
743 {
744 *HcFrame = Frame;
745 *HcMicroframe = Microframe + 1;
746 }
747
748 if (Microframe == (USB2_MICROFRAMES - 1))
749 {
750 *HcFrame = Frame + 1;
751 *HcMicroframe = 0;
752 }
753 }
754
755 UCHAR
756 NTAPI
USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)757 USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
758 {
759 ULONG ix;
760 UCHAR SMask = 0;
761 UCHAR HcFrame;
762 UCHAR HcMicroFrame;
763
764 if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
765 {
766 SMask = (1 << TtEndpoint->StartMicroframe);
767 }
768 else
769 {
770 USB2_ConvertFrame(TtEndpoint->StartFrame,
771 TtEndpoint->StartMicroframe,
772 &HcFrame,
773 &HcMicroFrame);
774
775 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
776 {
777 SMask |= (1 << HcMicroFrame);
778 HcMicroFrame++;
779 }
780 }
781
782 return SMask;
783 }
784
785 UCHAR
786 NTAPI
USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)787 USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
788 {
789 ULONG NumCompletes;
790 ULONG TransferType;
791 ULONG DeviceSpeed;
792 ULONG Direction;
793 UCHAR Result;
794 UCHAR MicroFrameCS;
795 UCHAR HcFrame;
796 UCHAR HcMicroFrame;
797 UCHAR MaskCS = 0;
798
799 TransferType = TtEndpoint->TtEndpointParams.TransferType;
800 DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
801 Direction = TtEndpoint->TtEndpointParams.Direction;
802
803 if (DeviceSpeed == UsbHighSpeed)
804 return 0;
805
806 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
807 {
808 USB2_ConvertFrame(TtEndpoint->StartFrame,
809 TtEndpoint->StartMicroframe,
810 &HcFrame,
811 &HcMicroFrame);
812
813 Result = CMASKS[HcMicroFrame];
814 }
815 else
816 {
817 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
818 return 0;
819
820 USB2_ConvertFrame(TtEndpoint->StartFrame,
821 TtEndpoint->StartMicroframe,
822 &HcFrame,
823 &HcMicroFrame);
824
825 NumCompletes = TtEndpoint->Nums.NumCompletes;
826
827 for (MicroFrameCS = HcMicroFrame + 2;
828 MicroFrameCS < USB2_MICROFRAMES;
829 MicroFrameCS++)
830 {
831 MaskCS |= (1 << MicroFrameCS);
832 NumCompletes--;
833
834 if (!NumCompletes)
835 return MaskCS;
836 }
837
838 for (; NumCompletes; NumCompletes--)
839 {
840 MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES));
841 }
842
843 Result = MaskCS;
844 }
845
846 return Result;
847 }
848
849 VOID
850 NTAPI
USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,IN PLIST_ENTRY List)851 USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
852 IN PLIST_ENTRY List)
853 {
854 PUSBPORT_DEVICE_EXTENSION FdoExtension;
855 PUSBPORT_REGISTRATION_PACKET Packet;
856 PUSBPORT_ENDPOINT Endpoint;
857 PLIST_ENTRY Entry;
858 ULONG AllocedBusTime;
859 ULONG EndpointBandwidth;
860 ULONG Factor;
861 ULONG ScheduleOffset;
862 ULONG Bandwidth;
863 ULONG n;
864 ULONG ix;
865 KIRQL OldIrql;
866 UCHAR NewPeriod;
867 UCHAR SMask;
868 UCHAR CMask;
869
870 FdoExtension = FdoDevice->DeviceExtension;
871 Packet = &FdoExtension->MiniPortInterface->Packet;
872
873 while (!IsListEmpty(List))
874 {
875 Entry = RemoveHeadList(List);
876
877 Endpoint = CONTAINING_RECORD(Entry,
878 USBPORT_ENDPOINT,
879 RebalanceLink.Flink);
880
881 DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
882
883 Endpoint->RebalanceLink.Flink = NULL;
884 Endpoint->RebalanceLink.Blink = NULL;
885
886 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
887 &Endpoint->EndpointOldIrql);
888
889 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
890 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
891
892 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
893 NewPeriod = Endpoint->TtEndpoint->ActualPeriod;
894
895 AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime;
896 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
897
898 Endpoint->EndpointProperties.InterruptScheduleMask = SMask;
899 Endpoint->EndpointProperties.SplitCompletionMask = CMask;
900
901 if (Endpoint->EndpointProperties.Period != NewPeriod)
902 {
903 ASSERT(Endpoint->EndpointProperties.Period);
904 Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
905
906 for (ix = 0; ix < Factor; ix++)
907 {
908 Bandwidth = Endpoint->EndpointProperties.UsbBandwidth;
909 n = Factor * Endpoint->EndpointProperties.ScheduleOffset;
910 Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth;
911 }
912
913 Endpoint->EndpointProperties.Period = NewPeriod;
914 Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset;
915 Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth;
916
917 ASSERT(NewPeriod);
918 Factor = USB2_FRAMES / NewPeriod;
919
920 for (ix = 0; ix < Factor; ix++)
921 {
922 n = Factor * ScheduleOffset;
923 Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
924 }
925 }
926
927 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
928
929 Packet->RebalanceEndpoint(FdoExtension->MiniPortExt,
930 &Endpoint->EndpointProperties,
931 (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT)));
932
933 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
934
935 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
936 Endpoint->EndpointOldIrql);
937 }
938 }
939
940 VOID
941 NTAPI
USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,IN PLIST_ENTRY RebalanceList)942 USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,
943 IN PLIST_ENTRY RebalanceList)
944 {
945 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
946 PUSBPORT_ENDPOINT Endpoint;
947 PLIST_ENTRY Entry;
948 LIST_ENTRY BalanceListInt1;
949 LIST_ENTRY BalanceListInt2;
950 ULONG TransferType;
951 ULONG ScheduleOffset;
952 UCHAR SMask;
953 UCHAR CMask;
954 UCHAR ActualPeriod;
955
956 DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n",
957 FdoDevice,
958 RebalanceList);
959
960 InitializeListHead(&BalanceListInt1);
961 InitializeListHead(&BalanceListInt2);
962
963 while (!IsListEmpty(RebalanceList))
964 {
965 Entry = RebalanceList->Flink;
966
967 Endpoint = CONTAINING_RECORD(Entry,
968 USBPORT_ENDPOINT,
969 RebalanceLink.Flink);
970
971 DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n",
972 Entry,
973 Endpoint);
974
975 RemoveHeadList(RebalanceList);
976 Entry->Flink = NULL;
977 Entry->Blink = NULL;
978
979 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
980 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
981
982 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
983 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
984
985 EndpointProperties = &Endpoint->EndpointProperties;
986 TransferType = EndpointProperties->TransferType;
987
988 switch (TransferType)
989 {
990 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
991 DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
992 ASSERT(FALSE);
993 break;
994
995 case USBPORT_TRANSFER_TYPE_INTERRUPT:
996 if (SMask != EndpointProperties->InterruptScheduleMask ||
997 CMask != EndpointProperties->SplitCompletionMask ||
998 ScheduleOffset != EndpointProperties->ScheduleOffset ||
999 ActualPeriod != EndpointProperties->Period)
1000 {
1001 if (ActualPeriod == EndpointProperties->Period &&
1002 ScheduleOffset == EndpointProperties->ScheduleOffset)
1003 {
1004 InsertTailList(&BalanceListInt1, Entry);
1005 }
1006 else
1007 {
1008 InsertTailList(&BalanceListInt2, Entry);
1009 }
1010 }
1011 break;
1012
1013 default:
1014 ASSERT(FALSE);
1015 break;
1016 }
1017 }
1018
1019 USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2);
1020 USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1);
1021 //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso);
1022 }
1023
1024 BOOLEAN
1025 NTAPI
USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries,IN ULONG MaxFrames)1026 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
1027 IN PUSB2_REBALANCE Rebalance,
1028 IN PULONG RebalanceListEntries,
1029 IN ULONG MaxFrames)
1030 {
1031 PUSB2_TT Tt;
1032 PUSB2_HC_EXTENSION HcExtension;
1033 ULONG Speed;
1034 ULONG TransferType;
1035 ULONG Frame;
1036 ULONG StartMicroframe;
1037 ULONG ix;
1038 PUSB2_TT_ENDPOINT endpoint;
1039 PUSB2_TT_ENDPOINT nextEndpoint;
1040 PUSB2_TT_ENDPOINT lastEndpoint;
1041 PUSB2_TT_ENDPOINT tmpEndpoint;
1042 ULONG endTime;
1043 ULONG maxEndTime;
1044 ULONG lastEndTime;
1045 ULONG Factor;
1046 ULONG jx;
1047 UCHAR frame;
1048 UCHAR uframe;
1049 USHORT Period;
1050 BOOLEAN IsMoved = FALSE;
1051
1052 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
1053 TtEndpoint,
1054 MaxFrames,
1055 TtEndpoint->CalcBusTime);
1056
1057 if (TtEndpoint->CalcBusTime == 0)
1058 {
1059 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
1060 return FALSE;
1061 }
1062
1063 Tt = TtEndpoint->Tt;
1064 HcExtension = Tt->HcExtension;
1065
1066 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1067 DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
1068
1069 StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1070 TtEndpoint->StartMicroframe;
1071
1072 if (Speed == UsbHighSpeed)
1073 {
1074 for (ix = StartMicroframe;
1075 ix < USB2_MAX_MICROFRAMES;
1076 ix += TtEndpoint->ActualPeriod)
1077 {
1078 frame = ix / USB2_MICROFRAMES;
1079 uframe = ix % (USB2_MICROFRAMES - 1);
1080
1081 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1082 }
1083
1084 TtEndpoint->CalcBusTime = 0;
1085
1086 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1087 return TRUE;
1088 }
1089
1090 /* Speed != UsbHighSpeed (FS/LS) */
1091
1092 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1093
1094 for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
1095 ix > 0;
1096 ix--, Frame--)
1097 {
1098 frame = TtEndpoint->StartFrame + Frame;
1099
1100 DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
1101 frame,
1102 Frame,
1103 TtEndpoint->StartFrame);
1104
1105 if ((Frame % TtEndpoint->ActualPeriod) == 0)
1106 {
1107 USB2_DeallocateHS(TtEndpoint, Frame);
1108 Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
1109 }
1110
1111 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1112 endpoint = Tt->FrameBudget[frame].IntEndpoint;
1113 else
1114 endpoint = Tt->FrameBudget[frame].IsoEndpoint;
1115
1116 nextEndpoint = endpoint->NextTtEndpoint;
1117
1118 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
1119 TtEndpoint,
1120 nextEndpoint);
1121
1122 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1123 {
1124 while (nextEndpoint)
1125 {
1126 endpoint = nextEndpoint;
1127 nextEndpoint = nextEndpoint->NextTtEndpoint;
1128 }
1129
1130 nextEndpoint = TtEndpoint;
1131
1132 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1133 endpoint,
1134 nextEndpoint);
1135 }
1136 else
1137 {
1138 while (nextEndpoint &&
1139 !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1140 {
1141 endpoint = nextEndpoint;
1142 nextEndpoint = nextEndpoint->NextTtEndpoint;
1143 }
1144
1145 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
1146 nextEndpoint)
1147 {
1148 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1149 ASSERT(FALSE);
1150 }
1151
1152 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1153 endpoint,
1154 nextEndpoint);
1155 }
1156
1157 if ((Frame % TtEndpoint->ActualPeriod) == 0)
1158 {
1159 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1160 {
1161 Tt->FrameBudget[frame].AltEndpoint = NULL;
1162 }
1163 else if (nextEndpoint)
1164 {
1165 nextEndpoint = nextEndpoint->NextTtEndpoint;
1166 endpoint->NextTtEndpoint = nextEndpoint;
1167
1168 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1169 endpoint,
1170 nextEndpoint);
1171 }
1172 }
1173
1174 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
1175 {
1176 if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
1177 {
1178 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1179 {
1180 endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1181 }
1182 else if (Tt->FrameBudget[frame].AltEndpoint)
1183 {
1184 endpoint = Tt->FrameBudget[frame].AltEndpoint;
1185 }
1186 }
1187 }
1188 else
1189 {
1190 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
1191 ASSERT(FALSE);
1192 }
1193
1194 Period = TtEndpoint->ActualPeriod;
1195
1196 for (;
1197 nextEndpoint;
1198 endpoint = nextEndpoint,
1199 nextEndpoint = nextEndpoint->NextTtEndpoint)
1200 {
1201 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
1202 endpoint,
1203 nextEndpoint);
1204
1205 endTime = endpoint->StartTime + endpoint->CalcBusTime;
1206 maxEndTime = endTime;
1207
1208 if (Period > nextEndpoint->ActualPeriod ||
1209 TtEndpoint->StartFrame != nextEndpoint->StartFrame)
1210 {
1211 if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
1212 Factor = Period / nextEndpoint->ActualPeriod;
1213 else
1214 Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
1215
1216 maxEndTime = endTime;
1217
1218 for (jx = 0, frame = nextEndpoint->StartFrame;
1219 jx < Factor;
1220 jx++, frame += nextEndpoint->ActualPeriod)
1221 {
1222 if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
1223 {
1224 lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1225
1226 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
1227 {
1228 lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
1229 }
1230 else if (Tt->FrameBudget[frame].AltEndpoint)
1231 {
1232 lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
1233 }
1234
1235 for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
1236 tmpEndpoint && tmpEndpoint != nextEndpoint;
1237 tmpEndpoint = tmpEndpoint->NextTtEndpoint)
1238 {
1239 lastEndpoint = tmpEndpoint;
1240 }
1241
1242 lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
1243
1244 if (endTime < (lastEndTime - 1))
1245 {
1246 maxEndTime = lastEndTime;
1247 endTime = maxEndTime;
1248
1249 if (nextEndpoint->StartTime == maxEndTime)
1250 break;
1251 }
1252 else
1253 {
1254 maxEndTime = endTime;
1255 }
1256 }
1257 }
1258 }
1259
1260 if (maxEndTime >= nextEndpoint->StartTime)
1261 break;
1262
1263 if (!USB2_MoveTtEndpoint(nextEndpoint,
1264 maxEndTime - nextEndpoint->StartTime,
1265 Rebalance,
1266 *RebalanceListEntries,
1267 &IsMoved))
1268 {
1269 if (!IsMoved)
1270 {
1271 DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
1272 }
1273
1274 break;
1275 }
1276
1277 if (Period > nextEndpoint->ActualPeriod)
1278 Period = nextEndpoint->ActualPeriod;
1279 }
1280 }
1281
1282 TtEndpoint->CalcBusTime = 0;
1283
1284 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
1285 return TRUE;
1286 }
1287
1288 BOOLEAN
1289 NTAPI
USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1290 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
1291 IN PUSB2_REBALANCE Rebalance,
1292 IN PULONG RebalanceListEntries)
1293 {
1294 PUSB2_TT Tt;
1295 PUSB2_HC_EXTENSION HcExtension;
1296 ULONG Speed;
1297 ULONG TimeUsed;
1298 ULONG MinTimeUsed;
1299 ULONG ix;
1300 ULONG frame;
1301 ULONG uframe;
1302 ULONG Microframe;
1303 ULONG TransferType;
1304 ULONG Overhead;
1305 ULONG LatestStart;
1306 PUSB2_TT_ENDPOINT prevEndpoint;
1307 PUSB2_TT_ENDPOINT nextEndpoint;
1308 PUSB2_TT_ENDPOINT IntEndpoint;
1309 ULONG StartTime;
1310 ULONG calcBusTime;
1311 BOOLEAN Result = TRUE;
1312
1313 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
1314
1315 Tt = TtEndpoint->Tt;
1316 HcExtension = Tt->HcExtension;
1317
1318 TtEndpoint->Nums.NumStarts = 0;
1319 TtEndpoint->Nums.NumCompletes = 0;
1320
1321 TtEndpoint->StartFrame = 0;
1322 TtEndpoint->StartMicroframe = 0;
1323
1324 if (TtEndpoint->CalcBusTime)
1325 {
1326 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
1327 return FALSE;
1328 }
1329
1330 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
1331
1332 if (Speed == UsbHighSpeed)
1333 {
1334 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
1335 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
1336 else
1337 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1338
1339 MinTimeUsed = HcExtension->TimeUsed[0][0];
1340
1341 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1342 {
1343 frame = ix / USB2_MICROFRAMES;
1344 uframe = ix % (USB2_MICROFRAMES - 1);
1345
1346 TimeUsed = HcExtension->TimeUsed[frame][uframe];
1347
1348 if (TimeUsed < MinTimeUsed)
1349 {
1350 MinTimeUsed = TimeUsed;
1351 TtEndpoint->StartFrame = frame;
1352 TtEndpoint->StartMicroframe = uframe;
1353 }
1354 }
1355
1356 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
1357 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
1358
1359 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
1360 TtEndpoint->StartFrame,
1361 TtEndpoint->StartMicroframe,
1362 TtEndpoint->CalcBusTime);
1363
1364 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
1365 TtEndpoint->StartMicroframe;
1366
1367 if (Microframe >= USB2_MAX_MICROFRAMES)
1368 {
1369 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
1370 return TRUE;
1371 }
1372
1373 for (ix = Microframe;
1374 ix < USB2_MAX_MICROFRAMES;
1375 ix += TtEndpoint->ActualPeriod)
1376 {
1377 frame = ix / USB2_MICROFRAMES;
1378 uframe = ix % (USB2_MICROFRAMES - 1);
1379
1380 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
1381 frame,
1382 uframe,
1383 HcExtension->TimeUsed[frame][uframe]);
1384
1385 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
1386 TtEndpoint->CalcBusTime,
1387 USB2_MAX_MICROFRAME_ALLOCATION))
1388 {
1389 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1390 Result = FALSE;
1391 }
1392 }
1393
1394 if (!Result)
1395 {
1396 for (ix = Microframe;
1397 ix < USB2_MAX_MICROFRAMES;
1398 ix += TtEndpoint->ActualPeriod)
1399 {
1400 frame = ix / USB2_MICROFRAMES;
1401 uframe = ix % (USB2_MICROFRAMES - 1);
1402
1403 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
1404 }
1405 }
1406
1407 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
1408 return TRUE;
1409 }
1410
1411 /* Speed != UsbHighSpeed (FS/LS) */
1412
1413 if (TtEndpoint->Period > USB2_FRAMES)
1414 TtEndpoint->ActualPeriod = USB2_FRAMES;
1415 else
1416 TtEndpoint->ActualPeriod = TtEndpoint->Period;
1417
1418 MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
1419
1420 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
1421 {
1422 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
1423 {
1424 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
1425 TtEndpoint->StartFrame = ix;
1426 }
1427 }
1428
1429 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1430
1431 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1432 {
1433 if (Speed == UsbFullSpeed)
1434 {
1435 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
1436 }
1437 else
1438 {
1439 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
1440 return FALSE;
1441 }
1442 }
1443 else
1444 {
1445 if (Speed == UsbFullSpeed)
1446 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1447 else
1448 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
1449 }
1450
1451 if (Speed == UsbLowSpeed)
1452 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
1453 else
1454 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
1455
1456 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
1457
1458 for (ix = 0;
1459 (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
1460 ix += TtEndpoint->ActualPeriod)
1461 {
1462 frame = TtEndpoint->StartFrame + ix;
1463
1464 if (Tt->FrameBudget[frame].AltEndpoint &&
1465 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
1466 {
1467 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1468 return FALSE;
1469 }
1470
1471 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1472 prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
1473 else
1474 prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
1475
1476 for (nextEndpoint = prevEndpoint->NextTtEndpoint;
1477 nextEndpoint;
1478 nextEndpoint = nextEndpoint->NextTtEndpoint)
1479 {
1480 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1481 break;
1482
1483 prevEndpoint = nextEndpoint;
1484 }
1485
1486 StartTime = USB2_GetStartTime(nextEndpoint,
1487 TtEndpoint,
1488 prevEndpoint,
1489 frame);
1490
1491 LatestStart = max(LatestStart, StartTime);
1492 }
1493
1494 TtEndpoint->StartTime = LatestStart;
1495
1496 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
1497 {
1498 TtEndpoint->CalcBusTime = 0;
1499 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1500 return FALSE;
1501 }
1502
1503 for (ix = 0, frame = -TtEndpoint->StartFrame;
1504 ix < USB2_FRAMES;
1505 ix++, frame++)
1506 {
1507 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
1508 ix,
1509 frame,
1510 TtEndpoint->StartFrame);
1511
1512 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
1513 {
1514 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
1515 ASSERT(FALSE);
1516 }
1517 else
1518 {
1519 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
1520 nextEndpoint = IntEndpoint->NextTtEndpoint;
1521
1522 for (nextEndpoint = IntEndpoint->NextTtEndpoint;
1523 nextEndpoint;
1524 nextEndpoint = nextEndpoint->NextTtEndpoint)
1525 {
1526 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
1527 break;
1528 IntEndpoint = nextEndpoint;
1529 }
1530
1531 if ((frame % TtEndpoint->ActualPeriod) == 0)
1532 {
1533 calcBusTime = 0;
1534 }
1535 else
1536 {
1537 if (nextEndpoint)
1538 {
1539 calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
1540 nextEndpoint->StartTime;
1541 }
1542 else
1543 {
1544 calcBusTime = TtEndpoint->CalcBusTime;
1545 }
1546
1547 if (calcBusTime > 0)
1548 {
1549 TimeUsed = Tt->FrameBudget[ix].TimeUsed;
1550
1551 if (!USB2_AllocateCheck(&TimeUsed,
1552 calcBusTime,
1553 USB2_FS_MAX_PERIODIC_ALLOCATION))
1554 {
1555 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1556 Result = FALSE;
1557 }
1558 }
1559 }
1560
1561 if (nextEndpoint != TtEndpoint)
1562 {
1563 if ((frame % TtEndpoint->ActualPeriod) == 0)
1564 {
1565 if (frame == 0)
1566 {
1567 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
1568 TtEndpoint->NextTtEndpoint = nextEndpoint;
1569 }
1570
1571 IntEndpoint->NextTtEndpoint = TtEndpoint;
1572
1573 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
1574 TtEndpoint,
1575 nextEndpoint);
1576 }
1577
1578 if (calcBusTime > 0)
1579 {
1580 BOOLEAN IsMoved;
1581 BOOLEAN MoveResult;
1582
1583 DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
1584 nextEndpoint,
1585 calcBusTime);
1586
1587 for (;
1588 nextEndpoint;
1589 nextEndpoint = nextEndpoint->NextTtEndpoint)
1590 {
1591 MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
1592 calcBusTime,
1593 Rebalance,
1594 *RebalanceListEntries,
1595 &IsMoved);
1596
1597 if (!IsMoved)
1598 {
1599 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
1600 Result = FALSE;
1601 }
1602
1603 if (!MoveResult)
1604 break;
1605 }
1606 }
1607 }
1608 }
1609
1610 if ((frame % TtEndpoint->ActualPeriod) == 0)
1611 {
1612 if (!USB2_AllocateHS(TtEndpoint, frame))
1613 {
1614 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
1615 Result = FALSE;
1616 }
1617
1618 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
1619 }
1620
1621 if (Result == FALSE)
1622 {
1623 USB2_DeallocateEndpointBudget(TtEndpoint,
1624 Rebalance,
1625 RebalanceListEntries,
1626 ix + 1);
1627
1628 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
1629 return FALSE;
1630 }
1631 }
1632
1633 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
1634 return Result;
1635 }
1636
1637 BOOLEAN
1638 NTAPI
USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1639 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
1640 IN PUSB2_REBALANCE Rebalance,
1641 IN PULONG RebalanceListEntries)
1642 {
1643 BOOLEAN Result;
1644
1645 DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
1646 *RebalanceListEntries);
1647
1648 USB2_DeallocateEndpointBudget(TtEndpoint,
1649 Rebalance,
1650 RebalanceListEntries,
1651 USB2_FRAMES);
1652
1653 TtEndpoint->PreviosPeriod = TtEndpoint->Period;
1654 TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1655
1656 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1657 Rebalance,
1658 RebalanceListEntries);
1659
1660 return Result;
1661 }
1662
1663 BOOLEAN
1664 NTAPI
USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,IN PUSB2_REBALANCE Rebalance,IN PULONG RebalanceListEntries)1665 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
1666 IN PUSB2_REBALANCE Rebalance,
1667 IN PULONG RebalanceListEntries)
1668 {
1669 PUSB2_TT_ENDPOINT ttEndpoint;
1670 ULONG TransferType;
1671 ULONG ix;
1672
1673 TransferType = TtEndpoint->TtEndpointParams.TransferType;
1674
1675 if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1676 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1677 (CHAR)TtEndpoint->StartMicroframe > 2 &&
1678 !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
1679 {
1680 DPRINT("USB2_PromotePeriods: return FALSE\n");
1681 return FALSE;
1682 }
1683
1684 if (Rebalance->RebalanceEndpoint[0] == NULL)
1685 {
1686 DPRINT("USB2_PromotePeriods: return TRUE\n");
1687 return TRUE;
1688 }
1689
1690 DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
1691 *RebalanceListEntries);
1692
1693 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1694 {
1695 Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
1696 }
1697
1698 for (ix = 0; ; ix++)
1699 {
1700 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1701 TransferType = ttEndpoint->TtEndpointParams.TransferType;
1702
1703 if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
1704 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
1705 (CHAR)ttEndpoint->StartMicroframe > 2)
1706 {
1707 USB2_DeallocateEndpointBudget(ttEndpoint,
1708 Rebalance,
1709 RebalanceListEntries,
1710 USB2_FRAMES);
1711
1712 ttEndpoint->IsPromoted = TRUE;
1713 ttEndpoint->PreviosPeriod = ttEndpoint->Period;
1714 ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
1715
1716 if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
1717 Rebalance,
1718 RebalanceListEntries))
1719 {
1720 break;
1721 }
1722 }
1723
1724 if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
1725 {
1726 DPRINT("USB2_PromotePeriods: return TRUE\n");
1727 return TRUE;
1728 }
1729 }
1730
1731 USB2_DeallocateEndpointBudget(TtEndpoint,
1732 Rebalance,
1733 RebalanceListEntries,
1734 USB2_FRAMES);
1735
1736 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1737 TtEndpoint->PreviosPeriod = 0;
1738
1739 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1740 {
1741 ttEndpoint = Rebalance->RebalanceEndpoint[ix];
1742
1743 if (ttEndpoint->IsPromoted)
1744 {
1745 if (ttEndpoint->CalcBusTime)
1746 {
1747 USB2_DeallocateEndpointBudget(ttEndpoint,
1748 Rebalance,
1749 RebalanceListEntries,
1750 USB2_FRAMES);
1751 }
1752
1753 TtEndpoint->Period = TtEndpoint->PreviosPeriod;
1754 TtEndpoint->PreviosPeriod = 0;
1755
1756 USB2_AllocateTimeForEndpoint(ttEndpoint,
1757 Rebalance,
1758 RebalanceListEntries);
1759 }
1760 }
1761
1762 DPRINT("USB2_PromotePeriods: return FALSE\n");
1763 return FALSE;
1764 }
1765
1766 VOID
1767 NTAPI
USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)1768 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
1769 {
1770 ULONG BusBandwidth;
1771 ULONG NewBusBandwidth;
1772 ULONG MaxBusBandwidth = 0;
1773 ULONG MinBusBandwidth;
1774 ULONG ix;
1775
1776 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
1777
1778 BusBandwidth = TtExtension->BusBandwidth;
1779 MinBusBandwidth = BusBandwidth;
1780
1781 for (ix = 0; ix < USB2_FRAMES; ix++)
1782 {
1783 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
1784
1785 MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
1786 MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
1787 }
1788
1789 TtExtension->MaxBandwidth = MaxBusBandwidth;
1790
1791 if (MinBusBandwidth == BusBandwidth)
1792 TtExtension->MinBandwidth = 0;
1793 else
1794 TtExtension->MinBandwidth = MinBusBandwidth;
1795 }
1796
1797 BOOLEAN
1798 NTAPI
USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint)1799 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
1800 IN PUSBPORT_ENDPOINT Endpoint)
1801 {
1802 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1803 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
1804 PUSB2_TT_EXTENSION TtExtension;
1805 ULONG TransferType;
1806 PUSB2_REBALANCE Rebalance;
1807 LIST_ENTRY RebalanceList;
1808 ULONG RebalanceListEntries;
1809 PUSB2_TT_ENDPOINT TtEndpoint;
1810 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
1811 PUSB2_TT Tt;
1812 USB_DEVICE_SPEED DeviceSpeed;
1813 ULONG Period;
1814 ULONG AllocedBusTime;
1815 ULONG EndpointBandwidth;
1816 ULONG ScheduleOffset;
1817 ULONG Factor;
1818 ULONG ix;
1819 ULONG n;
1820 BOOLEAN Direction;
1821 UCHAR SMask;
1822 UCHAR CMask;
1823 UCHAR ActualPeriod;
1824 BOOLEAN Result;
1825
1826 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
1827 FdoDevice,
1828 Endpoint);
1829
1830 EndpointProperties = &Endpoint->EndpointProperties;
1831 EndpointProperties->ScheduleOffset = 0;
1832
1833 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
1834 {
1835 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
1836 return TRUE;
1837 }
1838
1839 FdoExtension = FdoDevice->DeviceExtension;
1840
1841 TransferType = EndpointProperties->TransferType;
1842 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
1843
1844 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
1845 TransferType == USBPORT_TRANSFER_TYPE_BULK)
1846 {
1847 return TRUE;
1848 }
1849
1850 if (Endpoint->TtExtension)
1851 TtExtension = Endpoint->TtExtension;
1852 else
1853 TtExtension = NULL;
1854
1855 InitializeListHead(&RebalanceList);
1856
1857 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
1858 sizeof(USB2_REBALANCE),
1859 USB_PORT_TAG);
1860
1861 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
1862 Rebalance,
1863 TtExtension);
1864
1865 if (Rebalance)
1866 {
1867 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
1868
1869 TtEndpoint = Endpoint->TtEndpoint;
1870 TtEndpoint->Endpoint = Endpoint;
1871
1872 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
1873 DeviceSpeed = EndpointProperties->DeviceSpeed;
1874
1875 switch (DeviceSpeed)
1876 {
1877 case UsbLowSpeed:
1878 case UsbFullSpeed:
1879 {
1880 Tt = &TtExtension->Tt;
1881 Period = USB2_FRAMES;
1882
1883 while (Period > 0 && Period > EndpointProperties->Period)
1884 {
1885 Period >>= 1;
1886 }
1887
1888 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
1889 break;
1890 }
1891
1892 case UsbHighSpeed:
1893 {
1894 Tt = &FdoExtension->Usb2Extension->HcTt;
1895 Period = EndpointProperties->Period;
1896
1897 break;
1898 }
1899
1900 default:
1901 {
1902 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
1903 DeviceSpeed);
1904
1905 DbgBreakPoint();
1906
1907 Tt = &TtExtension->Tt;
1908 break;
1909 }
1910 }
1911
1912 USB2_InitTtEndpoint(TtEndpoint,
1913 TransferType,
1914 Direction,
1915 DeviceSpeed,
1916 Period,
1917 EndpointProperties->MaxPacketSize,
1918 Tt);
1919
1920 RebalanceListEntries = USB2_FRAMES - 2;
1921
1922 Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
1923 Rebalance,
1924 &RebalanceListEntries);
1925
1926 if (Result)
1927 {
1928 Result = USB2_PromotePeriods(TtEndpoint,
1929 Rebalance,
1930 &RebalanceListEntries);
1931 }
1932
1933 RebalanceListEntries = 0;
1934
1935 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
1936 {
1937 RebalanceListEntries = ix + 1;
1938 }
1939 }
1940 else
1941 {
1942 RebalanceListEntries = 0;
1943 Result = FALSE;
1944 }
1945
1946 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
1947 RebalanceListEntries,
1948 Result);
1949
1950 for (ix = 0; ix < RebalanceListEntries; ix++)
1951 {
1952 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
1953
1954 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
1955 ix,
1956 RebalanceTtEndpoint,
1957 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1958
1959 InsertTailList(&RebalanceList,
1960 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
1961 }
1962
1963 if (Rebalance)
1964 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
1965
1966 if (Result)
1967 {
1968 SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
1969 EndpointProperties->InterruptScheduleMask = SMask;
1970
1971 CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
1972 EndpointProperties->SplitCompletionMask = CMask;
1973
1974 AllocedBusTime = TtEndpoint->CalcBusTime;
1975
1976 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
1977 EndpointProperties->UsbBandwidth = EndpointBandwidth;
1978
1979 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
1980 EndpointProperties->Period = ActualPeriod;
1981
1982 ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
1983 EndpointProperties->ScheduleOffset = ScheduleOffset;
1984
1985 ASSERT(ActualPeriod);
1986 Factor = USB2_FRAMES / ActualPeriod;
1987 n = ScheduleOffset * Factor;
1988
1989 if (TtExtension)
1990 {
1991 for (ix = 0; ix < Factor; ix++)
1992 {
1993 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
1994 }
1995 }
1996 else
1997 {
1998 for (ix = 1; ix < Factor; ix++)
1999 {
2000 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
2001 }
2002 }
2003
2004 USBPORT_DumpingEndpointProperties(EndpointProperties);
2005 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
2006
2007 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
2008 {
2009 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
2010 }
2011 }
2012
2013 USB2_Rebalance(FdoDevice, &RebalanceList);
2014
2015 if (!TtExtension)
2016 {
2017 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2018 return Result;
2019 }
2020
2021 for (ix = 0; ix < USB2_FRAMES; ix++)
2022 {
2023 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2024 }
2025
2026 USBPORT_UpdateAllocatedBwTt(TtExtension);
2027
2028 for (ix = 0; ix < USB2_FRAMES; ix++)
2029 {
2030 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2031 }
2032
2033 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
2034
2035 return Result;
2036 }
2037
2038 VOID
2039 NTAPI
USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint)2040 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
2041 IN PUSBPORT_ENDPOINT Endpoint)
2042 {
2043 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2044 ULONG Period;
2045 ULONG ScheduleOffset;
2046 ULONG EndpointBandwidth;
2047 LIST_ENTRY RebalanceList;
2048 ULONG TransferType;
2049 PUSB2_REBALANCE Rebalance;
2050 ULONG RebalanceListEntries;
2051 ULONG Factor;
2052 ULONG ix;
2053 ULONG n;
2054 PUSB2_TT_EXTENSION TtExtension;
2055 PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
2056
2057 DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
2058
2059 FdoExtension = FdoDevice->DeviceExtension;
2060
2061 Period = Endpoint->EndpointProperties.Period;
2062 ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
2063 EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
2064
2065 InitializeListHead(&RebalanceList);
2066
2067 TransferType = Endpoint->EndpointProperties.TransferType;
2068
2069 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
2070 TransferType == USBPORT_TRANSFER_TYPE_BULK ||
2071 (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
2072 {
2073 return;
2074 }
2075
2076 Rebalance = ExAllocatePoolWithTag(NonPagedPool,
2077 sizeof(USB2_REBALANCE),
2078 USB_PORT_TAG);
2079
2080 if (!Rebalance)
2081 {
2082 DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
2083 return;
2084 }
2085
2086 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
2087
2088 ASSERT(Period != 0);
2089 Factor = USB2_FRAMES / Period;
2090 n = ScheduleOffset * Factor;
2091
2092 TtExtension = Endpoint->TtExtension;
2093
2094 if (TtExtension)
2095 {
2096 for (ix = 0; ix < Factor; ix++)
2097 {
2098 TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
2099 }
2100 }
2101 else
2102 {
2103 for (ix = 1; ix < Factor; ix++)
2104 {
2105 FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
2106 }
2107 }
2108
2109 RebalanceListEntries = USB2_FRAMES - 2;
2110
2111 USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
2112 Rebalance,
2113 &RebalanceListEntries,
2114 USB2_FRAMES);
2115
2116 RebalanceListEntries = 0;
2117
2118 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
2119 {
2120 RebalanceListEntries = ix + 1;
2121 }
2122
2123 for (ix = 0; ix < RebalanceListEntries; ix++)
2124 {
2125 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
2126
2127 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
2128 ix,
2129 RebalanceTtEndpoint,
2130 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2131
2132 InsertTailList(&RebalanceList,
2133 &RebalanceTtEndpoint->Endpoint->RebalanceLink);
2134 }
2135
2136 ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
2137
2138 USB2_Rebalance(FdoDevice, &RebalanceList);
2139
2140 if (!TtExtension)
2141 return;
2142
2143 for (ix = 0; ix < USB2_FRAMES; ix++)
2144 {
2145 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
2146 }
2147
2148 USBPORT_UpdateAllocatedBwTt(TtExtension);
2149
2150 for (ix = 0; ix < USB2_FRAMES; ix++)
2151 {
2152 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2153 }
2154
2155 DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
2156 }
2157
2158 VOID
2159 NTAPI
USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,IN PUSB2_TT Tt)2160 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
2161 IN PUSB2_TT Tt)
2162 {
2163 ULONG ix;
2164 ULONG jx;
2165
2166 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
2167
2168 Tt->HcExtension = HcExtension;
2169 Tt->DelayTime = 1;
2170 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
2171
2172 for (ix = 0; ix < USB2_FRAMES; ix++)
2173 {
2174 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
2175 Tt->FrameBudget[ix].AltEndpoint = NULL;
2176
2177 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2178 {
2179 Tt->TimeCS[ix][jx] = 0;
2180 Tt->NumStartSplits[ix][jx] = 0;
2181 }
2182
2183 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
2184
2185 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
2186 USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
2187 USBPORT_TRANSFER_DIRECTION_OUT,
2188 UsbFullSpeed,
2189 USB2_FRAMES,
2190 0,
2191 Tt);
2192
2193 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
2194 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2195 Tt->IsoEndpoint[ix].StartFrame = ix;
2196 Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2197
2198 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
2199
2200 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
2201 USBPORT_TRANSFER_TYPE_INTERRUPT,
2202 USBPORT_TRANSFER_DIRECTION_OUT,
2203 UsbFullSpeed,
2204 USB2_FRAMES,
2205 0,
2206 Tt);
2207
2208 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
2209 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
2210 Tt->IntEndpoint[ix].StartFrame = ix;
2211 Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
2212 }
2213 }
2214
2215 VOID
2216 NTAPI
USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)2217 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
2218 {
2219 ULONG ix;
2220 ULONG jx;
2221
2222 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
2223
2224 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
2225
2226 for (ix = 0; ix < USB2_FRAMES; ix++)
2227 {
2228 for (jx = 0; jx < USB2_MICROFRAMES; jx++)
2229 {
2230 HcExtension->TimeUsed[ix][jx] = 0;
2231 }
2232 }
2233
2234 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
2235
2236 USB2_InitTT(HcExtension, &HcExtension->HcTt);
2237 }
2238