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 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 40 USB2_AddDataBitStuff(IN USHORT DataTime) 41 { 42 return (DataTime + (DataTime / 16)); 43 } 44 45 VOID 46 NTAPI 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 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 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 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 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 211 USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint, 212 IN ULONG Frame) 213 { 214 PUSB2_TT_ENDPOINT nextTtEndpoint; 215 ULONG Result; 216 217 //DPRINT("USB2_GetLastIsoTime: TtEndpoint - %p, Frame - %X\n", 218 // TtEndpoint, 219 // Frame); 220 221 nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].IsoEndpoint->NextTtEndpoint; 222 223 if (nextTtEndpoint || 224 (nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint) != NULL) 225 { 226 Result = nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime; 227 } 228 else 229 { 230 Result = USB2_FS_SOF_TIME; 231 } 232 233 return Result; 234 } 235 236 ULONG 237 NTAPI 238 USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint, 239 IN PUSB2_TT_ENDPOINT TtEndpoint, 240 IN PUSB2_TT_ENDPOINT prevTtEndpoint, 241 IN ULONG Frame) 242 { 243 PUSB2_TT_ENDPOINT ttEndpoint; 244 ULONG TransferType; 245 246 DPRINT("USB2_GetStartTime: nextTtEndpoint - %p, TtEndpoint - %p, prevTtEndpoint - %p, Frame - %X\n", 247 nextTtEndpoint, 248 TtEndpoint, 249 prevTtEndpoint, 250 Frame); 251 252 TransferType = TtEndpoint->TtEndpointParams.TransferType; 253 254 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 255 { 256 if (nextTtEndpoint) 257 return nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime; 258 259 ttEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint; 260 261 if (ttEndpoint) 262 return ttEndpoint->StartTime + ttEndpoint->CalcBusTime; 263 else 264 return USB2_FS_SOF_TIME; 265 } 266 else 267 { 268 ttEndpoint = prevTtEndpoint; 269 270 if (ttEndpoint == TtEndpoint->Tt->FrameBudget[Frame].IntEndpoint) 271 return USB2_GetLastIsoTime(TtEndpoint, Frame); 272 else 273 return ttEndpoint->StartTime + ttEndpoint->CalcBusTime; 274 } 275 } 276 277 VOID 278 NTAPI 279 USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint, 280 IN UCHAR TransferType, 281 IN UCHAR Direction, 282 IN UCHAR DeviceSpeed, 283 IN USHORT Period, 284 IN USHORT MaxPacketSize, 285 IN PUSB2_TT Tt) 286 { 287 TtEndpoint->TtEndpointParams.TransferType = TransferType; 288 TtEndpoint->TtEndpointParams.Direction = Direction; 289 TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed; 290 291 TtEndpoint->Period = Period; 292 TtEndpoint->MaxPacketSize = MaxPacketSize; 293 TtEndpoint->Tt = Tt; 294 295 TtEndpoint->CalcBusTime = 0; 296 TtEndpoint->StartTime = 0; 297 TtEndpoint->ActualPeriod = 0; 298 TtEndpoint->StartFrame = 0; 299 TtEndpoint->StartMicroframe = 0; 300 301 TtEndpoint->Nums.AsULONG = 0; 302 TtEndpoint->NextTtEndpoint = NULL; 303 TtEndpoint->Reserved2 = 0; 304 TtEndpoint->PreviosPeriod = 0; 305 TtEndpoint->IsPromoted = FALSE; 306 } 307 308 BOOLEAN 309 NTAPI 310 USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint, 311 IN LONG Frame) 312 { 313 PUSB2_HC_EXTENSION HcExtension; 314 PUSB2_TT Tt; 315 ULONG TransferType; 316 ULONG Direction; 317 ULONG DataTime; 318 ULONG DataSize; 319 ULONG RemainDataTime; 320 ULONG OverheadCS; 321 ULONG OverheadSS; 322 ULONG ix; 323 USHORT PktSize; 324 USHORT PktSizeBitStuff; 325 UCHAR frame; 326 UCHAR uframe; 327 BOOL Result = TRUE; 328 329 DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, StartFrame - %X\n", 330 TtEndpoint, 331 Frame, 332 TtEndpoint->StartFrame); 333 334 Tt = TtEndpoint->Tt; 335 HcExtension = Tt->HcExtension; 336 337 TransferType = TtEndpoint->TtEndpointParams.TransferType; 338 Direction = TtEndpoint->TtEndpointParams.Direction; 339 340 if (Frame == 0) 341 { 342 TtEndpoint->StartMicroframe = 343 TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1; 344 345 DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n", 346 TtEndpoint->StartMicroframe); 347 } 348 349 USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS); 350 351 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 352 { 353 if (Frame == 0) 354 { 355 TtEndpoint->Nums.NumStarts = 1; 356 357 if ((CHAR)TtEndpoint->StartMicroframe < (USB2_MICROFRAMES - 3)) 358 TtEndpoint->Nums.NumCompletes = 3; 359 else 360 TtEndpoint->Nums.NumCompletes = 2; 361 } 362 } 363 else 364 { 365 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT) 366 { 367 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n"); 368 ASSERT(FALSE); 369 } 370 else 371 { 372 DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n"); 373 ASSERT(FALSE); 374 } 375 } 376 377 frame = TtEndpoint->StartFrame + Frame; 378 uframe = TtEndpoint->StartMicroframe; 379 380 if (TtEndpoint->StartMicroframe == 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 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 619 USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint, 620 IN USHORT 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 == TRUE && 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 = TRUE; 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 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 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 >= 0 && 743 Microframe <= (USB2_MICROFRAMES - 2)) 744 { 745 *HcFrame = Frame; 746 *HcMicroframe = Microframe + 1; 747 } 748 749 if (Microframe == (USB2_MICROFRAMES - 1)) 750 { 751 *HcFrame = Frame + 1; 752 *HcMicroframe = 0; 753 } 754 } 755 756 UCHAR 757 NTAPI 758 USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint) 759 { 760 ULONG ix; 761 UCHAR SMask = 0; 762 UCHAR HcFrame; 763 UCHAR HcMicroFrame; 764 765 if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed) 766 { 767 SMask = (1 << TtEndpoint->StartMicroframe); 768 } 769 else 770 { 771 USB2_ConvertFrame(TtEndpoint->StartFrame, 772 TtEndpoint->StartMicroframe, 773 &HcFrame, 774 &HcMicroFrame); 775 776 for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++) 777 { 778 SMask |= (1 << HcMicroFrame); 779 HcMicroFrame++; 780 } 781 } 782 783 return SMask; 784 } 785 786 UCHAR 787 NTAPI 788 USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint) 789 { 790 ULONG NumCompletes; 791 ULONG TransferType; 792 ULONG DeviceSpeed; 793 ULONG Direction; 794 UCHAR Result; 795 UCHAR MicroFrameCS; 796 UCHAR HcFrame; 797 UCHAR HcMicroFrame; 798 UCHAR MaskCS = 0; 799 800 TransferType = TtEndpoint->TtEndpointParams.TransferType; 801 DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed; 802 Direction = TtEndpoint->TtEndpointParams.Direction; 803 804 if (DeviceSpeed == UsbHighSpeed) 805 return 0; 806 807 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 808 { 809 USB2_ConvertFrame(TtEndpoint->StartFrame, 810 TtEndpoint->StartMicroframe, 811 &HcFrame, 812 &HcMicroFrame); 813 814 Result = CMASKS[HcMicroFrame]; 815 } 816 else 817 { 818 if (Direction == USBPORT_TRANSFER_DIRECTION_OUT) 819 return 0; 820 821 USB2_ConvertFrame(TtEndpoint->StartFrame, 822 TtEndpoint->StartMicroframe, 823 &HcFrame, 824 &HcMicroFrame); 825 826 NumCompletes = TtEndpoint->Nums.NumCompletes; 827 828 for (MicroFrameCS = HcMicroFrame + 2; 829 MicroFrameCS < USB2_MICROFRAMES; 830 MicroFrameCS++) 831 { 832 MaskCS |= (1 << MicroFrameCS); 833 NumCompletes--; 834 835 if (!NumCompletes) 836 return MaskCS; 837 } 838 839 for (; NumCompletes; NumCompletes--) 840 { 841 MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES)); 842 } 843 844 Result = MaskCS; 845 } 846 847 return Result; 848 } 849 850 VOID 851 NTAPI 852 USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice, 853 IN PLIST_ENTRY List) 854 { 855 PUSBPORT_DEVICE_EXTENSION FdoExtension; 856 PUSBPORT_REGISTRATION_PACKET Packet; 857 PUSBPORT_ENDPOINT Endpoint; 858 PLIST_ENTRY Entry; 859 ULONG AllocedBusTime; 860 ULONG EndpointBandwidth; 861 ULONG Factor; 862 ULONG ScheduleOffset; 863 ULONG Bandwidth; 864 ULONG n; 865 ULONG ix; 866 KIRQL OldIrql; 867 UCHAR NewPeriod; 868 UCHAR SMask; 869 UCHAR CMask; 870 871 FdoExtension = FdoDevice->DeviceExtension; 872 Packet = &FdoExtension->MiniPortInterface->Packet; 873 874 while (!IsListEmpty(List)) 875 { 876 Entry = RemoveHeadList(List); 877 878 Endpoint = CONTAINING_RECORD(Entry, 879 USBPORT_ENDPOINT, 880 RebalanceLink.Flink); 881 882 DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint); 883 884 Endpoint->RebalanceLink.Flink = NULL; 885 Endpoint->RebalanceLink.Blink = NULL; 886 887 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, 888 &Endpoint->EndpointOldIrql); 889 890 SMask = USB2_GetSMASK(Endpoint->TtEndpoint); 891 CMask = USB2_GetCMASK(Endpoint->TtEndpoint); 892 893 ScheduleOffset = Endpoint->TtEndpoint->StartFrame; 894 NewPeriod = Endpoint->TtEndpoint->ActualPeriod; 895 896 AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime; 897 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime; 898 899 Endpoint->EndpointProperties.InterruptScheduleMask = SMask; 900 Endpoint->EndpointProperties.SplitCompletionMask = CMask; 901 902 if (Endpoint->EndpointProperties.Period != NewPeriod) 903 { 904 ASSERT(Endpoint->EndpointProperties.Period); 905 Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period; 906 907 for (ix = 0; ix < Factor; ix++) 908 { 909 Bandwidth = Endpoint->EndpointProperties.UsbBandwidth; 910 n = Factor * Endpoint->EndpointProperties.ScheduleOffset; 911 Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth; 912 } 913 914 Endpoint->EndpointProperties.Period = NewPeriod; 915 Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset; 916 Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth; 917 918 ASSERT(NewPeriod); 919 Factor = USB2_FRAMES / NewPeriod; 920 921 for (ix = 0; ix < Factor; ix++) 922 { 923 n = Factor * ScheduleOffset; 924 Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth; 925 } 926 } 927 928 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); 929 930 Packet->RebalanceEndpoint(FdoExtension->MiniPortExt, 931 &Endpoint->EndpointProperties, 932 (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT))); 933 934 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); 935 936 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, 937 Endpoint->EndpointOldIrql); 938 } 939 } 940 941 VOID 942 NTAPI 943 USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice, 944 IN PLIST_ENTRY RebalanceList) 945 { 946 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 947 PUSBPORT_ENDPOINT Endpoint; 948 PLIST_ENTRY Entry; 949 LIST_ENTRY BalanceListInt1; 950 LIST_ENTRY BalanceListInt2; 951 ULONG TransferType; 952 ULONG ScheduleOffset; 953 UCHAR SMask; 954 UCHAR CMask; 955 UCHAR ActualPeriod; 956 957 DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n", 958 FdoDevice, 959 RebalanceList); 960 961 InitializeListHead(&BalanceListInt1); 962 InitializeListHead(&BalanceListInt2); 963 964 while (!IsListEmpty(RebalanceList)) 965 { 966 Entry = RebalanceList->Flink; 967 968 Endpoint = CONTAINING_RECORD(Entry, 969 USBPORT_ENDPOINT, 970 RebalanceLink.Flink); 971 972 DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n", 973 Entry, 974 Endpoint); 975 976 RemoveHeadList(RebalanceList); 977 Entry->Flink = NULL; 978 Entry->Blink = NULL; 979 980 SMask = USB2_GetSMASK(Endpoint->TtEndpoint); 981 CMask = USB2_GetCMASK(Endpoint->TtEndpoint); 982 983 ScheduleOffset = Endpoint->TtEndpoint->StartFrame; 984 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod; 985 986 EndpointProperties = &Endpoint->EndpointProperties; 987 TransferType = EndpointProperties->TransferType; 988 989 switch (TransferType) 990 { 991 case USBPORT_TRANSFER_TYPE_ISOCHRONOUS: 992 DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n"); 993 ASSERT(FALSE); 994 break; 995 996 case USBPORT_TRANSFER_TYPE_INTERRUPT: 997 if (SMask != EndpointProperties->InterruptScheduleMask || 998 CMask != EndpointProperties->SplitCompletionMask || 999 ScheduleOffset != EndpointProperties->ScheduleOffset || 1000 ActualPeriod != EndpointProperties->Period) 1001 { 1002 if (ActualPeriod == EndpointProperties->Period && 1003 ScheduleOffset == EndpointProperties->ScheduleOffset) 1004 { 1005 InsertTailList(&BalanceListInt1, Entry); 1006 } 1007 else 1008 { 1009 InsertTailList(&BalanceListInt2, Entry); 1010 } 1011 } 1012 break; 1013 1014 default: 1015 ASSERT(FALSE); 1016 break; 1017 } 1018 } 1019 1020 USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2); 1021 USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1); 1022 //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso); 1023 } 1024 1025 BOOLEAN 1026 NTAPI 1027 USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint, 1028 IN PUSB2_REBALANCE Rebalance, 1029 IN PULONG RebalanceListEntries, 1030 IN ULONG MaxFrames) 1031 { 1032 PUSB2_TT Tt; 1033 PUSB2_HC_EXTENSION HcExtension; 1034 ULONG Speed; 1035 ULONG TransferType; 1036 ULONG Frame; 1037 ULONG StartMicroframe; 1038 ULONG ix; 1039 PUSB2_TT_ENDPOINT endpoint; 1040 PUSB2_TT_ENDPOINT nextEndpoint; 1041 PUSB2_TT_ENDPOINT lastEndpoint; 1042 PUSB2_TT_ENDPOINT tmpEndpoint; 1043 ULONG endTime; 1044 ULONG maxEndTime; 1045 ULONG lastEndTime; 1046 ULONG Factor; 1047 ULONG jx; 1048 UCHAR frame; 1049 UCHAR uframe; 1050 USHORT Period; 1051 BOOLEAN IsMoved = FALSE; 1052 1053 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n", 1054 TtEndpoint, 1055 MaxFrames, 1056 TtEndpoint->CalcBusTime); 1057 1058 if (TtEndpoint->CalcBusTime == 0) 1059 { 1060 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n"); 1061 return FALSE; 1062 } 1063 1064 Tt = TtEndpoint->Tt; 1065 HcExtension = Tt->HcExtension; 1066 1067 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed; 1068 DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed); 1069 1070 StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES + 1071 TtEndpoint->StartMicroframe; 1072 1073 if (Speed == UsbHighSpeed) 1074 { 1075 for (ix = StartMicroframe; 1076 ix < USB2_MAX_MICROFRAMES; 1077 ix += TtEndpoint->ActualPeriod) 1078 { 1079 frame = ix / USB2_MICROFRAMES; 1080 uframe = ix % (USB2_MICROFRAMES - 1); 1081 1082 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime; 1083 } 1084 1085 TtEndpoint->CalcBusTime = 0; 1086 1087 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n"); 1088 return TRUE; 1089 } 1090 1091 /* Speed != UsbHighSpeed (FS/LS) */ 1092 1093 TransferType = TtEndpoint->TtEndpointParams.TransferType; 1094 1095 for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame; 1096 ix > 0; 1097 ix--, Frame--) 1098 { 1099 frame = TtEndpoint->StartFrame + Frame; 1100 1101 DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n", 1102 frame, 1103 Frame, 1104 TtEndpoint->StartFrame); 1105 1106 if ((Frame % TtEndpoint->ActualPeriod) == 0) 1107 { 1108 USB2_DeallocateHS(TtEndpoint, Frame); 1109 Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime; 1110 } 1111 1112 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1113 endpoint = Tt->FrameBudget[frame].IntEndpoint; 1114 else 1115 endpoint = Tt->FrameBudget[frame].IsoEndpoint; 1116 1117 nextEndpoint = endpoint->NextTtEndpoint; 1118 1119 DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n", 1120 TtEndpoint, 1121 nextEndpoint); 1122 1123 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2)) 1124 { 1125 while (nextEndpoint) 1126 { 1127 endpoint = nextEndpoint; 1128 nextEndpoint = nextEndpoint->NextTtEndpoint; 1129 } 1130 1131 nextEndpoint = TtEndpoint; 1132 1133 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n", 1134 endpoint, 1135 nextEndpoint); 1136 } 1137 else 1138 { 1139 while (nextEndpoint && 1140 !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint)) 1141 { 1142 endpoint = nextEndpoint; 1143 nextEndpoint = nextEndpoint->NextTtEndpoint; 1144 } 1145 1146 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS && 1147 nextEndpoint) 1148 { 1149 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n"); 1150 ASSERT(FALSE); 1151 } 1152 1153 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n", 1154 endpoint, 1155 nextEndpoint); 1156 } 1157 1158 if ((Frame % TtEndpoint->ActualPeriod) == 0) 1159 { 1160 if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2)) 1161 { 1162 Tt->FrameBudget[frame].AltEndpoint = NULL; 1163 } 1164 else if (nextEndpoint) 1165 { 1166 nextEndpoint = nextEndpoint->NextTtEndpoint; 1167 endpoint->NextTtEndpoint = nextEndpoint; 1168 1169 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n", 1170 endpoint, 1171 nextEndpoint); 1172 } 1173 } 1174 1175 if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT) 1176 { 1177 if (endpoint == Tt->FrameBudget[frame].IntEndpoint) 1178 { 1179 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint) 1180 { 1181 endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint; 1182 } 1183 else if (Tt->FrameBudget[frame].AltEndpoint) 1184 { 1185 endpoint = Tt->FrameBudget[frame].AltEndpoint; 1186 } 1187 } 1188 } 1189 else 1190 { 1191 DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n"); 1192 ASSERT(FALSE); 1193 } 1194 1195 Period = TtEndpoint->ActualPeriod; 1196 1197 for (; 1198 nextEndpoint; 1199 endpoint = nextEndpoint, 1200 nextEndpoint = nextEndpoint->NextTtEndpoint) 1201 { 1202 DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n", 1203 endpoint, 1204 nextEndpoint); 1205 1206 endTime = endpoint->StartTime + endpoint->CalcBusTime; 1207 maxEndTime = endTime; 1208 1209 if (Period > nextEndpoint->ActualPeriod || 1210 TtEndpoint->StartFrame != nextEndpoint->StartFrame) 1211 { 1212 if (USB2_CommonFrames(nextEndpoint, TtEndpoint)) 1213 Factor = Period / nextEndpoint->ActualPeriod; 1214 else 1215 Factor = USB2_FRAMES / nextEndpoint->ActualPeriod; 1216 1217 maxEndTime = endTime; 1218 1219 for (jx = 0, frame = nextEndpoint->StartFrame; 1220 jx < Factor; 1221 jx++, frame += nextEndpoint->ActualPeriod) 1222 { 1223 if (nextEndpoint->StartFrame != TtEndpoint->StartFrame) 1224 { 1225 lastEndpoint = Tt->FrameBudget[frame].IntEndpoint; 1226 1227 if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint) 1228 { 1229 lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint; 1230 } 1231 else if (Tt->FrameBudget[frame].AltEndpoint) 1232 { 1233 lastEndpoint = Tt->FrameBudget[frame].AltEndpoint; 1234 } 1235 1236 for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint; 1237 tmpEndpoint && tmpEndpoint != nextEndpoint; 1238 tmpEndpoint = tmpEndpoint->NextTtEndpoint) 1239 { 1240 lastEndpoint = tmpEndpoint; 1241 } 1242 1243 lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime; 1244 1245 if (endTime < (lastEndTime - 1)) 1246 { 1247 maxEndTime = lastEndTime; 1248 endTime = maxEndTime; 1249 1250 if (nextEndpoint->StartTime == maxEndTime) 1251 break; 1252 } 1253 else 1254 { 1255 maxEndTime = endTime; 1256 } 1257 } 1258 } 1259 } 1260 1261 if (maxEndTime >= nextEndpoint->StartTime) 1262 break; 1263 1264 if (!USB2_MoveTtEndpoint(nextEndpoint, 1265 maxEndTime - nextEndpoint->StartTime, 1266 Rebalance, 1267 *RebalanceListEntries, 1268 &IsMoved)) 1269 { 1270 if (!IsMoved) 1271 { 1272 DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n"); 1273 } 1274 1275 break; 1276 } 1277 1278 if (Period > nextEndpoint->ActualPeriod) 1279 Period = nextEndpoint->ActualPeriod; 1280 } 1281 } 1282 1283 TtEndpoint->CalcBusTime = 0; 1284 1285 DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n"); 1286 return TRUE; 1287 } 1288 1289 BOOLEAN 1290 NTAPI 1291 USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint, 1292 IN PUSB2_REBALANCE Rebalance, 1293 IN PULONG RebalanceListEntries) 1294 { 1295 PUSB2_TT Tt; 1296 PUSB2_HC_EXTENSION HcExtension; 1297 ULONG Speed; 1298 ULONG TimeUsed; 1299 ULONG MinTimeUsed; 1300 ULONG ix; 1301 ULONG frame; 1302 ULONG uframe; 1303 ULONG Microframe; 1304 ULONG TransferType; 1305 ULONG Overhead; 1306 ULONG LatestStart; 1307 PUSB2_TT_ENDPOINT prevEndpoint; 1308 PUSB2_TT_ENDPOINT nextEndpoint; 1309 PUSB2_TT_ENDPOINT IntEndpoint; 1310 ULONG StartTime; 1311 ULONG calcBusTime; 1312 BOOLEAN Result = TRUE; 1313 1314 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint); 1315 1316 Tt = TtEndpoint->Tt; 1317 HcExtension = Tt->HcExtension; 1318 1319 TtEndpoint->Nums.NumStarts = 0; 1320 TtEndpoint->Nums.NumCompletes = 0; 1321 1322 TtEndpoint->StartFrame = 0; 1323 TtEndpoint->StartMicroframe = 0; 1324 1325 if (TtEndpoint->CalcBusTime) 1326 { 1327 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n"); 1328 return FALSE; 1329 } 1330 1331 Speed = TtEndpoint->TtEndpointParams.DeviceSpeed; 1332 1333 if (Speed == UsbHighSpeed) 1334 { 1335 if (TtEndpoint->Period > USB2_MAX_MICROFRAMES) 1336 TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES; 1337 else 1338 TtEndpoint->ActualPeriod = TtEndpoint->Period; 1339 1340 MinTimeUsed = HcExtension->TimeUsed[0][0]; 1341 1342 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++) 1343 { 1344 frame = ix / USB2_MICROFRAMES; 1345 uframe = ix % (USB2_MICROFRAMES - 1); 1346 1347 TimeUsed = HcExtension->TimeUsed[frame][uframe]; 1348 1349 if (TimeUsed < MinTimeUsed) 1350 { 1351 MinTimeUsed = TimeUsed; 1352 TtEndpoint->StartFrame = frame; 1353 TtEndpoint->StartMicroframe = uframe; 1354 } 1355 } 1356 1357 TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) + 1358 USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize); 1359 1360 DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n", 1361 TtEndpoint->StartFrame, 1362 TtEndpoint->StartMicroframe, 1363 TtEndpoint->CalcBusTime); 1364 1365 Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES + 1366 TtEndpoint->StartMicroframe; 1367 1368 if (Microframe >= USB2_MAX_MICROFRAMES) 1369 { 1370 DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n"); 1371 return TRUE; 1372 } 1373 1374 for (ix = Microframe; 1375 ix < USB2_MAX_MICROFRAMES; 1376 ix += TtEndpoint->ActualPeriod) 1377 { 1378 frame = ix / USB2_MICROFRAMES; 1379 uframe = ix % (USB2_MICROFRAMES - 1); 1380 1381 DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n", 1382 frame, 1383 uframe, 1384 HcExtension->TimeUsed[frame][uframe]); 1385 1386 if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe], 1387 TtEndpoint->CalcBusTime, 1388 USB2_MAX_MICROFRAME_ALLOCATION)) 1389 { 1390 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n"); 1391 Result = FALSE; 1392 } 1393 } 1394 1395 if (!Result) 1396 { 1397 for (ix = Microframe; 1398 ix < USB2_MAX_MICROFRAMES; 1399 ix += TtEndpoint->ActualPeriod) 1400 { 1401 frame = ix / USB2_MICROFRAMES; 1402 uframe = ix % (USB2_MICROFRAMES - 1); 1403 1404 HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime; 1405 } 1406 } 1407 1408 DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n"); 1409 return TRUE; 1410 } 1411 1412 /* Speed != UsbHighSpeed (FS/LS) */ 1413 1414 if (TtEndpoint->Period > USB2_FRAMES) 1415 TtEndpoint->ActualPeriod = USB2_FRAMES; 1416 else 1417 TtEndpoint->ActualPeriod = TtEndpoint->Period; 1418 1419 MinTimeUsed = Tt->FrameBudget[0].TimeUsed; 1420 1421 for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++) 1422 { 1423 if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed) 1424 { 1425 MinTimeUsed = Tt->FrameBudget[ix].TimeUsed; 1426 TtEndpoint->StartFrame = ix; 1427 } 1428 } 1429 1430 TransferType = TtEndpoint->TtEndpointParams.TransferType; 1431 1432 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1433 { 1434 if (Speed == UsbFullSpeed) 1435 { 1436 Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime; 1437 } 1438 else 1439 { 1440 DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n"); 1441 return FALSE; 1442 } 1443 } 1444 else 1445 { 1446 if (Speed == UsbFullSpeed) 1447 Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime; 1448 else 1449 Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime; 1450 } 1451 1452 if (Speed == UsbLowSpeed) 1453 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead; 1454 else 1455 TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead; 1456 1457 LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME; 1458 1459 for (ix = 0; 1460 (TtEndpoint->StartFrame + ix) < USB2_FRAMES; 1461 ix += TtEndpoint->ActualPeriod) 1462 { 1463 frame = TtEndpoint->StartFrame + ix; 1464 1465 if (Tt->FrameBudget[frame].AltEndpoint && 1466 TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2)) 1467 { 1468 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n"); 1469 return FALSE; 1470 } 1471 1472 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1473 prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint; 1474 else 1475 prevEndpoint = Tt->FrameBudget[frame].IntEndpoint; 1476 1477 for (nextEndpoint = prevEndpoint->NextTtEndpoint; 1478 nextEndpoint; 1479 nextEndpoint = nextEndpoint->NextTtEndpoint) 1480 { 1481 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint)) 1482 break; 1483 1484 prevEndpoint = nextEndpoint; 1485 } 1486 1487 StartTime = USB2_GetStartTime(nextEndpoint, 1488 TtEndpoint, 1489 prevEndpoint, 1490 frame); 1491 1492 LatestStart = max(LatestStart, StartTime); 1493 } 1494 1495 TtEndpoint->StartTime = LatestStart; 1496 1497 if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION) 1498 { 1499 TtEndpoint->CalcBusTime = 0; 1500 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n"); 1501 return FALSE; 1502 } 1503 1504 for (ix = 0, frame = -TtEndpoint->StartFrame; 1505 ix < USB2_FRAMES; 1506 ix++, frame++) 1507 { 1508 DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n", 1509 ix, 1510 frame, 1511 TtEndpoint->StartFrame); 1512 1513 if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) 1514 { 1515 DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n"); 1516 ASSERT(FALSE); 1517 } 1518 else 1519 { 1520 IntEndpoint = Tt->FrameBudget[ix].IntEndpoint; 1521 nextEndpoint = IntEndpoint->NextTtEndpoint; 1522 1523 for (nextEndpoint = IntEndpoint->NextTtEndpoint; 1524 nextEndpoint; 1525 nextEndpoint = nextEndpoint->NextTtEndpoint) 1526 { 1527 if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint)) 1528 break; 1529 IntEndpoint = nextEndpoint; 1530 } 1531 1532 if ((frame % TtEndpoint->ActualPeriod) == 0) 1533 { 1534 calcBusTime = 0; 1535 } 1536 else 1537 { 1538 if (nextEndpoint) 1539 { 1540 calcBusTime = LatestStart + TtEndpoint->CalcBusTime - 1541 nextEndpoint->StartTime; 1542 } 1543 else 1544 { 1545 calcBusTime = TtEndpoint->CalcBusTime; 1546 } 1547 1548 if (calcBusTime > 0) 1549 { 1550 TimeUsed = Tt->FrameBudget[ix].TimeUsed; 1551 1552 if (!USB2_AllocateCheck(&TimeUsed, 1553 calcBusTime, 1554 USB2_FS_MAX_PERIODIC_ALLOCATION)) 1555 { 1556 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n"); 1557 Result = FALSE; 1558 } 1559 } 1560 } 1561 1562 if (nextEndpoint != TtEndpoint) 1563 { 1564 if ((frame % TtEndpoint->ActualPeriod) == 0) 1565 { 1566 if (frame == 0) 1567 { 1568 DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n"); 1569 TtEndpoint->NextTtEndpoint = nextEndpoint; 1570 } 1571 1572 IntEndpoint->NextTtEndpoint = TtEndpoint; 1573 1574 DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n", 1575 TtEndpoint, 1576 nextEndpoint); 1577 } 1578 1579 if (calcBusTime > 0) 1580 { 1581 BOOLEAN IsMoved; 1582 BOOLEAN MoveResult; 1583 1584 DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n", 1585 nextEndpoint, 1586 calcBusTime); 1587 1588 for (; 1589 nextEndpoint; 1590 nextEndpoint = nextEndpoint->NextTtEndpoint) 1591 { 1592 MoveResult = USB2_MoveTtEndpoint(nextEndpoint, 1593 calcBusTime, 1594 Rebalance, 1595 *RebalanceListEntries, 1596 &IsMoved); 1597 1598 if (!IsMoved) 1599 { 1600 DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n"); 1601 Result = FALSE; 1602 } 1603 1604 if (!MoveResult) 1605 break; 1606 } 1607 } 1608 } 1609 } 1610 1611 if ((frame % TtEndpoint->ActualPeriod) == 0) 1612 { 1613 if (!USB2_AllocateHS(TtEndpoint, frame)) 1614 { 1615 DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n"); 1616 Result = FALSE; 1617 } 1618 1619 Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime; 1620 } 1621 1622 if (Result == FALSE) 1623 { 1624 USB2_DeallocateEndpointBudget(TtEndpoint, 1625 Rebalance, 1626 RebalanceListEntries, 1627 ix + 1); 1628 1629 DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n"); 1630 return FALSE; 1631 } 1632 } 1633 1634 DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result); 1635 return Result; 1636 } 1637 1638 BOOLEAN 1639 NTAPI 1640 USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint, 1641 IN PUSB2_REBALANCE Rebalance, 1642 IN PULONG RebalanceListEntries) 1643 { 1644 BOOLEAN Result; 1645 1646 DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n", 1647 *RebalanceListEntries); 1648 1649 USB2_DeallocateEndpointBudget(TtEndpoint, 1650 Rebalance, 1651 RebalanceListEntries, 1652 USB2_FRAMES); 1653 1654 TtEndpoint->PreviosPeriod = TtEndpoint->Period; 1655 TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms; 1656 1657 Result = USB2_AllocateTimeForEndpoint(TtEndpoint, 1658 Rebalance, 1659 RebalanceListEntries); 1660 1661 return Result; 1662 } 1663 1664 BOOLEAN 1665 NTAPI 1666 USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint, 1667 IN PUSB2_REBALANCE Rebalance, 1668 IN PULONG RebalanceListEntries) 1669 { 1670 PUSB2_TT_ENDPOINT ttEndpoint; 1671 ULONG TransferType; 1672 ULONG ix; 1673 1674 TransferType = TtEndpoint->TtEndpointParams.TransferType; 1675 1676 if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms && 1677 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT && 1678 (CHAR)TtEndpoint->StartMicroframe > 2 && 1679 !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries)) 1680 { 1681 DPRINT("USB2_PromotePeriods: return FALSE\n"); 1682 return FALSE; 1683 } 1684 1685 if (Rebalance->RebalanceEndpoint[0] == NULL) 1686 { 1687 DPRINT("USB2_PromotePeriods: return TRUE\n"); 1688 return TRUE; 1689 } 1690 1691 DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n", 1692 *RebalanceListEntries); 1693 1694 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++) 1695 { 1696 Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE; 1697 } 1698 1699 for (ix = 0; ; ix++) 1700 { 1701 ttEndpoint = Rebalance->RebalanceEndpoint[ix]; 1702 TransferType = ttEndpoint->TtEndpointParams.TransferType; 1703 1704 if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms && 1705 TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT && 1706 (CHAR)ttEndpoint->StartMicroframe > 2) 1707 { 1708 USB2_DeallocateEndpointBudget(ttEndpoint, 1709 Rebalance, 1710 RebalanceListEntries, 1711 USB2_FRAMES); 1712 1713 ttEndpoint->IsPromoted = TRUE; 1714 ttEndpoint->PreviosPeriod = ttEndpoint->Period; 1715 ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms; 1716 1717 if (!USB2_AllocateTimeForEndpoint(ttEndpoint, 1718 Rebalance, 1719 RebalanceListEntries)) 1720 { 1721 break; 1722 } 1723 } 1724 1725 if (Rebalance->RebalanceEndpoint[ix + 1] == NULL) 1726 { 1727 DPRINT("USB2_PromotePeriods: return TRUE\n"); 1728 return TRUE; 1729 } 1730 } 1731 1732 USB2_DeallocateEndpointBudget(TtEndpoint, 1733 Rebalance, 1734 RebalanceListEntries, 1735 USB2_FRAMES); 1736 1737 TtEndpoint->Period = TtEndpoint->PreviosPeriod; 1738 TtEndpoint->PreviosPeriod = 0; 1739 1740 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++) 1741 { 1742 ttEndpoint = Rebalance->RebalanceEndpoint[ix]; 1743 1744 if (ttEndpoint->IsPromoted) 1745 { 1746 if (ttEndpoint->CalcBusTime) 1747 { 1748 USB2_DeallocateEndpointBudget(ttEndpoint, 1749 Rebalance, 1750 RebalanceListEntries, 1751 USB2_FRAMES); 1752 } 1753 1754 TtEndpoint->Period = TtEndpoint->PreviosPeriod; 1755 TtEndpoint->PreviosPeriod = 0; 1756 1757 USB2_AllocateTimeForEndpoint(ttEndpoint, 1758 Rebalance, 1759 RebalanceListEntries); 1760 } 1761 } 1762 1763 DPRINT("USB2_PromotePeriods: return FALSE\n"); 1764 return FALSE; 1765 } 1766 1767 VOID 1768 NTAPI 1769 USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension) 1770 { 1771 ULONG BusBandwidth; 1772 ULONG NewBusBandwidth; 1773 ULONG MaxBusBandwidth = 0; 1774 ULONG MinBusBandwidth; 1775 ULONG ix; 1776 1777 DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension); 1778 1779 BusBandwidth = TtExtension->BusBandwidth; 1780 MinBusBandwidth = BusBandwidth; 1781 1782 for (ix = 0; ix < USB2_FRAMES; ix++) 1783 { 1784 NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix]; 1785 1786 MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth); 1787 MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth); 1788 } 1789 1790 TtExtension->MaxBandwidth = MaxBusBandwidth; 1791 1792 if (MinBusBandwidth == BusBandwidth) 1793 TtExtension->MinBandwidth = 0; 1794 else 1795 TtExtension->MinBandwidth = MinBusBandwidth; 1796 } 1797 1798 BOOLEAN 1799 NTAPI 1800 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice, 1801 IN PUSBPORT_ENDPOINT Endpoint) 1802 { 1803 PUSBPORT_DEVICE_EXTENSION FdoExtension; 1804 PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties; 1805 PUSB2_TT_EXTENSION TtExtension; 1806 ULONG TransferType; 1807 PUSB2_REBALANCE Rebalance; 1808 LIST_ENTRY RebalanceList; 1809 ULONG RebalanceListEntries; 1810 PUSB2_TT_ENDPOINT TtEndpoint; 1811 PUSB2_TT_ENDPOINT RebalanceTtEndpoint; 1812 PUSB2_TT Tt; 1813 USB_DEVICE_SPEED DeviceSpeed; 1814 ULONG Period; 1815 ULONG AllocedBusTime; 1816 ULONG EndpointBandwidth; 1817 ULONG ScheduleOffset; 1818 ULONG Factor; 1819 ULONG ix; 1820 ULONG n; 1821 BOOLEAN Direction; 1822 UCHAR SMask; 1823 UCHAR CMask; 1824 UCHAR ActualPeriod; 1825 BOOLEAN Result; 1826 1827 DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n", 1828 FdoDevice, 1829 Endpoint); 1830 1831 EndpointProperties = &Endpoint->EndpointProperties; 1832 EndpointProperties->ScheduleOffset = 0; 1833 1834 if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0) 1835 { 1836 DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n"); 1837 return TRUE; 1838 } 1839 1840 FdoExtension = FdoDevice->DeviceExtension; 1841 1842 TransferType = EndpointProperties->TransferType; 1843 DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType); 1844 1845 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 1846 TransferType == USBPORT_TRANSFER_TYPE_BULK) 1847 { 1848 return TRUE; 1849 } 1850 1851 if (Endpoint->TtExtension) 1852 TtExtension = Endpoint->TtExtension; 1853 else 1854 TtExtension = NULL; 1855 1856 InitializeListHead(&RebalanceList); 1857 1858 Rebalance = ExAllocatePoolWithTag(NonPagedPool, 1859 sizeof(USB2_REBALANCE), 1860 USB_PORT_TAG); 1861 1862 DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n", 1863 Rebalance, 1864 TtExtension); 1865 1866 if (Rebalance) 1867 { 1868 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE)); 1869 1870 TtEndpoint = Endpoint->TtEndpoint; 1871 TtEndpoint->Endpoint = Endpoint; 1872 1873 Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT; 1874 DeviceSpeed = EndpointProperties->DeviceSpeed; 1875 1876 switch (DeviceSpeed) 1877 { 1878 case UsbLowSpeed: 1879 case UsbFullSpeed: 1880 { 1881 Tt = &TtExtension->Tt; 1882 Period = USB2_FRAMES; 1883 1884 while (Period > 0 && Period > EndpointProperties->Period) 1885 { 1886 Period >>= 1; 1887 } 1888 1889 DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period); 1890 break; 1891 } 1892 1893 case UsbHighSpeed: 1894 { 1895 Tt = &FdoExtension->Usb2Extension->HcTt; 1896 1897 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES) 1898 Period = USB2_MAX_MICROFRAMES; 1899 else 1900 Period = EndpointProperties->Period; 1901 1902 break; 1903 } 1904 1905 default: 1906 { 1907 DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n", 1908 DeviceSpeed); 1909 1910 DbgBreakPoint(); 1911 1912 Tt = &TtExtension->Tt; 1913 break; 1914 } 1915 } 1916 1917 USB2_InitTtEndpoint(TtEndpoint, 1918 TransferType, 1919 Direction, 1920 DeviceSpeed, 1921 Period, 1922 EndpointProperties->MaxPacketSize, 1923 Tt); 1924 1925 RebalanceListEntries = USB2_FRAMES - 2; 1926 1927 Result = USB2_AllocateTimeForEndpoint(TtEndpoint, 1928 Rebalance, 1929 &RebalanceListEntries); 1930 1931 if (Result) 1932 { 1933 Result = USB2_PromotePeriods(TtEndpoint, 1934 Rebalance, 1935 &RebalanceListEntries); 1936 } 1937 1938 RebalanceListEntries = 0; 1939 1940 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++) 1941 { 1942 RebalanceListEntries = ix + 1; 1943 } 1944 } 1945 else 1946 { 1947 RebalanceListEntries = 0; 1948 Result = FALSE; 1949 } 1950 1951 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n", 1952 RebalanceListEntries, 1953 Result); 1954 1955 for (ix = 0; ix < RebalanceListEntries; ix++) 1956 { 1957 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix]; 1958 1959 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n", 1960 ix, 1961 RebalanceTtEndpoint, 1962 &RebalanceTtEndpoint->Endpoint->RebalanceLink); 1963 1964 InsertTailList(&RebalanceList, 1965 &RebalanceTtEndpoint->Endpoint->RebalanceLink); 1966 } 1967 1968 if (Rebalance) 1969 ExFreePoolWithTag(Rebalance, USB_PORT_TAG); 1970 1971 if (Result) 1972 { 1973 SMask = USB2_GetSMASK(Endpoint->TtEndpoint); 1974 EndpointProperties->InterruptScheduleMask = SMask; 1975 1976 CMask = USB2_GetCMASK(Endpoint->TtEndpoint); 1977 EndpointProperties->SplitCompletionMask = CMask; 1978 1979 AllocedBusTime = TtEndpoint->CalcBusTime; 1980 1981 EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime; 1982 EndpointProperties->UsbBandwidth = EndpointBandwidth; 1983 1984 ActualPeriod = Endpoint->TtEndpoint->ActualPeriod; 1985 EndpointProperties->Period = ActualPeriod; 1986 1987 ScheduleOffset = Endpoint->TtEndpoint->StartFrame; 1988 EndpointProperties->ScheduleOffset = ScheduleOffset; 1989 1990 ASSERT(ActualPeriod); 1991 Factor = USB2_FRAMES / ActualPeriod; 1992 n = ScheduleOffset * Factor; 1993 1994 if (TtExtension) 1995 { 1996 for (ix = 0; ix < Factor; ix++) 1997 { 1998 TtExtension->Bandwidth[n + ix] -= EndpointBandwidth; 1999 } 2000 } 2001 else 2002 { 2003 for (ix = 1; ix < Factor; ix++) 2004 { 2005 FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth; 2006 } 2007 } 2008 2009 USBPORT_DumpingEndpointProperties(EndpointProperties); 2010 USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint); 2011 2012 if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2)) 2013 { 2014 DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n"); 2015 } 2016 } 2017 2018 USB2_Rebalance(FdoDevice, &RebalanceList); 2019 2020 if (!TtExtension) 2021 { 2022 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result); 2023 return Result; 2024 } 2025 2026 for (ix = 0; ix < USB2_FRAMES; ix++) 2027 { 2028 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth; 2029 } 2030 2031 USBPORT_UpdateAllocatedBwTt(TtExtension); 2032 2033 for (ix = 0; ix < USB2_FRAMES; ix++) 2034 { 2035 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth; 2036 } 2037 2038 DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result); 2039 2040 return Result; 2041 } 2042 2043 VOID 2044 NTAPI 2045 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice, 2046 IN PUSBPORT_ENDPOINT Endpoint) 2047 { 2048 PUSBPORT_DEVICE_EXTENSION FdoExtension; 2049 ULONG Period; 2050 ULONG ScheduleOffset; 2051 ULONG EndpointBandwidth; 2052 LIST_ENTRY RebalanceList; 2053 ULONG TransferType; 2054 PUSB2_REBALANCE Rebalance; 2055 ULONG RebalanceListEntries; 2056 ULONG Factor; 2057 ULONG ix; 2058 ULONG n; 2059 PUSB2_TT_EXTENSION TtExtension; 2060 PUSB2_TT_ENDPOINT RebalanceTtEndpoint; 2061 2062 DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint); 2063 2064 FdoExtension = FdoDevice->DeviceExtension; 2065 2066 Period = Endpoint->EndpointProperties.Period; 2067 ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset; 2068 EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth; 2069 2070 InitializeListHead(&RebalanceList); 2071 2072 TransferType = Endpoint->EndpointProperties.TransferType; 2073 2074 if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL || 2075 TransferType == USBPORT_TRANSFER_TYPE_BULK || 2076 (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)) 2077 { 2078 return; 2079 } 2080 2081 Rebalance = ExAllocatePoolWithTag(NonPagedPool, 2082 sizeof(USB2_REBALANCE), 2083 USB_PORT_TAG); 2084 2085 if (!Rebalance) 2086 { 2087 DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n"); 2088 return; 2089 } 2090 2091 RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE)); 2092 2093 ASSERT(Period != 0); 2094 Factor = USB2_FRAMES / Period; 2095 n = ScheduleOffset * Factor; 2096 2097 TtExtension = Endpoint->TtExtension; 2098 2099 if (TtExtension) 2100 { 2101 for (ix = 0; ix < Factor; ix++) 2102 { 2103 TtExtension->Bandwidth[n + ix] += EndpointBandwidth; 2104 } 2105 } 2106 else 2107 { 2108 for (ix = 1; ix < Factor; ix++) 2109 { 2110 FdoExtension->Bandwidth[n + ix] += EndpointBandwidth; 2111 } 2112 } 2113 2114 RebalanceListEntries = USB2_FRAMES - 2; 2115 2116 USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint, 2117 Rebalance, 2118 &RebalanceListEntries, 2119 USB2_FRAMES); 2120 2121 RebalanceListEntries = 0; 2122 2123 for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++) 2124 { 2125 RebalanceListEntries = ix + 1; 2126 } 2127 2128 for (ix = 0; ix < RebalanceListEntries; ix++) 2129 { 2130 RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix]; 2131 2132 DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n", 2133 ix, 2134 RebalanceTtEndpoint, 2135 &RebalanceTtEndpoint->Endpoint->RebalanceLink); 2136 2137 InsertTailList(&RebalanceList, 2138 &RebalanceTtEndpoint->Endpoint->RebalanceLink); 2139 } 2140 2141 ExFreePoolWithTag(Rebalance, USB_PORT_TAG); 2142 2143 USB2_Rebalance(FdoDevice, &RebalanceList); 2144 2145 if (!TtExtension) 2146 return; 2147 2148 for (ix = 0; ix < USB2_FRAMES; ix++) 2149 { 2150 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth; 2151 } 2152 2153 USBPORT_UpdateAllocatedBwTt(TtExtension); 2154 2155 for (ix = 0; ix < USB2_FRAMES; ix++) 2156 { 2157 FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth; 2158 } 2159 2160 DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n"); 2161 } 2162 2163 VOID 2164 NTAPI 2165 USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension, 2166 IN PUSB2_TT Tt) 2167 { 2168 ULONG ix; 2169 ULONG jx; 2170 2171 DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt); 2172 2173 Tt->HcExtension = HcExtension; 2174 Tt->DelayTime = 1; 2175 Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION; 2176 2177 for (ix = 0; ix < USB2_FRAMES; ix++) 2178 { 2179 Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES; 2180 Tt->FrameBudget[ix].AltEndpoint = NULL; 2181 2182 for (jx = 0; jx < USB2_MICROFRAMES; jx++) 2183 { 2184 Tt->TimeCS[ix][jx] = 0; 2185 Tt->NumStartSplits[ix][jx] = 0; 2186 } 2187 2188 Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix]; 2189 2190 USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix], 2191 USBPORT_TRANSFER_TYPE_ISOCHRONOUS, 2192 USBPORT_TRANSFER_DIRECTION_OUT, 2193 UsbFullSpeed, 2194 USB2_FRAMES, 2195 0, 2196 Tt); 2197 2198 Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES; 2199 Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY; 2200 Tt->IsoEndpoint[ix].StartFrame = ix; 2201 Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME; 2202 2203 Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix]; 2204 2205 USB2_InitTtEndpoint(&Tt->IntEndpoint[ix], 2206 USBPORT_TRANSFER_TYPE_INTERRUPT, 2207 USBPORT_TRANSFER_DIRECTION_OUT, 2208 UsbFullSpeed, 2209 USB2_FRAMES, 2210 0, 2211 Tt); 2212 2213 Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES; 2214 Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY; 2215 Tt->IntEndpoint[ix].StartFrame = ix; 2216 Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME; 2217 } 2218 } 2219 2220 VOID 2221 NTAPI 2222 USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension) 2223 { 2224 ULONG ix; 2225 ULONG jx; 2226 2227 DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension); 2228 2229 HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION; 2230 2231 for (ix = 0; ix < USB2_FRAMES; ix++) 2232 { 2233 for (jx = 0; jx < USB2_MICROFRAMES; jx++) 2234 { 2235 HcExtension->TimeUsed[ix][jx] = 0; 2236 } 2237 } 2238 2239 HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY; 2240 2241 USB2_InitTT(HcExtension, &HcExtension->HcTt); 2242 } 2243