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 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 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 <= (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 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 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 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 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 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 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 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 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 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 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 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 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 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