[USBPORT] Check Period instead Factor.
[reactos.git] / drivers / usb / usbport / usb2.c
index 86e45a1..6259cf4 100644 (file)
@@ -200,9 +200,9 @@ USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,
             *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_IN_OVERHEAD;
         }
 
-        DPRINT("USB2_GetHsOverhead: *OverheadSS - %X, *OverheadCS - %X\n",
-               *OverheadSS,
-               *OverheadCS);
+        //DPRINT("USB2_GetHsOverhead: *OverheadSS - %X, *OverheadCS - %X\n",
+        //       *OverheadSS,
+        //       *OverheadCS);
     }
 }
 
@@ -214,9 +214,9 @@ USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,
     PUSB2_TT_ENDPOINT nextTtEndpoint;
     ULONG Result;
 
-    DPRINT("USB2_GetLastIsoTime: TtEndpoint - %p, Frame - %X\n",
-           TtEndpoint,
-           Frame);
+    //DPRINT("USB2_GetLastIsoTime: TtEndpoint - %p, Frame - %X\n",
+    //       TtEndpoint,
+    //       Frame);
 
     nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].IsoEndpoint->NextTtEndpoint;
 
@@ -251,13 +251,11 @@ USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
 
     TransferType = TtEndpoint->TtEndpointParams.TransferType;
 
-    if (nextTtEndpoint && TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
-    {
-        return nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
-    }
-
     if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
     {
+        if (nextTtEndpoint)
+            return nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
+
         ttEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint;
 
         if (ttEndpoint)
@@ -286,8 +284,6 @@ USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
                     IN USHORT MaxPacketSize,
                     IN PUSB2_TT Tt)
 {
-    RtlZeroMemory(TtEndpoint, sizeof(USB2_TT_ENDPOINT));
-
     TtEndpoint->TtEndpointParams.TransferType = TransferType;
     TtEndpoint->TtEndpointParams.Direction = Direction;
     TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
@@ -295,6 +291,18 @@ USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
     TtEndpoint->Period = Period;
     TtEndpoint->MaxPacketSize = MaxPacketSize;
     TtEndpoint->Tt = Tt;
+
+    TtEndpoint->CalcBusTime = 0;
+    TtEndpoint->StartTime = 0;
+    TtEndpoint->ActualPeriod = 0;
+    TtEndpoint->StartFrame = 0;
+    TtEndpoint->StartMicroframe = 0;
+
+    TtEndpoint->Nums.AsULONG = 0;
+    TtEndpoint->NextTtEndpoint = NULL;
+    TtEndpoint->Reserved2 = 0;
+    TtEndpoint->PreviosPeriod = 0;
+    TtEndpoint->IsPromoted = FALSE;
 }
 
 BOOLEAN
@@ -307,16 +315,18 @@ USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
     ULONG TransferType;
     ULONG Direction;
     ULONG DataTime;
+    ULONG DataSize;
     ULONG RemainDataTime;
     ULONG OverheadCS;
     ULONG OverheadSS;
     ULONG ix;
     USHORT PktSize;
+    USHORT PktSizeBitStuff;
     UCHAR frame;
     UCHAR uframe;
     BOOL Result = TRUE;
 
-    DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, TtEndpoint->StartFrame - %X\n",
+    DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, StartFrame - %X\n",
            TtEndpoint,
            Frame,
            TtEndpoint->StartFrame);
@@ -344,156 +354,1349 @@ USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
         {
             TtEndpoint->Nums.NumStarts = 1;
 
-            if ((CHAR)TtEndpoint->StartMicroframe < 5)
-            {
+            if ((CHAR)TtEndpoint->StartMicroframe < (USB2_MICROFRAMES - 3))
                 TtEndpoint->Nums.NumCompletes = 3;
+            else
+                TtEndpoint->Nums.NumCompletes = 2;
+        }
+    }
+    else
+    {
+        if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+        {
+            DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
+            ASSERT(FALSE);
+        }
+        else
+        {
+            DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
+            ASSERT(FALSE);
+        }
+    }
+
+    frame = TtEndpoint->StartFrame + Frame;
+    uframe = TtEndpoint->StartMicroframe;
+
+    if (TtEndpoint->StartMicroframe == 0xFF)
+        USB2_GetPrevMicroFrame(&frame, &uframe);
+
+    for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+    {
+        if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                OverheadSS,
+                                USB2_MAX_MICROFRAME_ALLOCATION))
+        {
+            Result = FALSE;
+        }
+
+        if (Tt->NumStartSplits[frame][uframe] > 
+            (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
+        {
+            DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
+                    Tt->NumStartSplits[frame][uframe] + 1);
+
+            ASSERT(FALSE);
+            Result = FALSE;
+        }
+
+        ++Tt->NumStartSplits[frame][uframe];
+        USB2_IncMicroFrame(&frame, &uframe);
+    }
+
+    frame = TtEndpoint->StartFrame + Frame;
+    uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+    for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+    {
+        if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                OverheadCS,
+                                USB2_MAX_MICROFRAME_ALLOCATION))
+        {
+            Result = FALSE;
+        }
+
+        USB2_IncMicroFrame(&frame, &uframe);
+    }
+
+    PktSize = TtEndpoint->MaxPacketSize;
+    PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
+
+    if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+    {
+        frame = TtEndpoint->StartFrame + Frame;
+        uframe = TtEndpoint->StartMicroframe;
+
+        if (uframe == 0xFF)
+            USB2_GetPrevMicroFrame(&frame, &uframe);
+
+        DataTime = 0;
+
+        for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+        {
+            DataSize = PktSizeBitStuff - DataTime;
+
+            if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+                DataTime = DataSize;
+            else
+                DataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+
+            DPRINT("USB2_AllocateHS: ix - %X, frame - %X, uframe - %X, TimeUsed - %X\n",
+                   ix,
+                   frame,
+                   uframe,
+                   HcExtension->TimeUsed[frame][uframe]);
+
+            if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                    DataTime,
+                                    USB2_MAX_MICROFRAME_ALLOCATION))
+            {
+                Result = FALSE;
+            }
+
+            USB2_IncMicroFrame(&frame, &uframe);
+            DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+        }
+    }
+    else
+    {
+        frame = TtEndpoint->StartFrame + Frame;
+        uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+        for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+        {
+            if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            {
+                RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
+                                 Tt->TimeCS[frame][uframe];
+
+                if (RemainDataTime >= PktSizeBitStuff)
+                {
+                    DataTime = PktSizeBitStuff;
+                }
+                else if (RemainDataTime > 0)
+                {
+                    DataTime = RemainDataTime;
+                }
+                else
+                {
+                    DataTime = 0;
+                }
+
+                if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                        DataTime,
+                                        USB2_MAX_MICROFRAME_ALLOCATION))
+                {
+                    Result = FALSE;
+                }
+            }
+
+            if (PktSizeBitStuff < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+                Tt->TimeCS[frame][uframe] += PktSizeBitStuff;
+            else
+                Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+
+            USB2_IncMicroFrame(&frame, &uframe);
+        }
+    }
+
+    DPRINT("USB2_AllocateHS: Result - %X\n", Result);
+    return Result;
+}
+
+VOID
+NTAPI
+USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                  IN ULONG Frame)
+{
+    PUSB2_TT Tt;
+    PUSB2_HC_EXTENSION HcExtension;
+    ULONG OverheadCS;
+    ULONG OverheadSS;
+    ULONG Direction;
+    ULONG ix;
+    ULONG CurrentDataTime;
+    ULONG RemainDataTime;
+    ULONG DataTime;
+    ULONG DataSize;
+    USHORT PktSize;
+    USHORT PktSizeBitStuff;
+    UCHAR uframe;
+    UCHAR frame;
+
+    DPRINT("USB2_DeallocateHS: TtEndpoint - %p, Frame - %X\n",
+           TtEndpoint,
+           Frame);
+
+    Tt = TtEndpoint->Tt;
+    HcExtension = Tt->HcExtension;
+
+    USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
+
+    frame = TtEndpoint->StartFrame + Frame;
+    uframe = TtEndpoint->StartMicroframe;
+
+    if (TtEndpoint->StartMicroframe == 0xFF)
+    {
+        USB2_GetPrevMicroFrame(&frame, &uframe);
+    }
+
+    for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+    {
+        HcExtension->TimeUsed[frame][uframe] -= OverheadSS;
+        --Tt->NumStartSplits[frame][uframe];
+        USB2_IncMicroFrame(&frame, &uframe);
+    }
+
+    frame = TtEndpoint->StartFrame + Frame;
+    uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+    for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+    {
+        HcExtension->TimeUsed[frame][uframe] -= OverheadCS;
+        USB2_IncMicroFrame(&frame, &uframe);
+    }
+
+    Direction = TtEndpoint->TtEndpointParams.Direction;
+    PktSize = TtEndpoint->MaxPacketSize;
+    PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
+
+    if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+    {
+        frame = TtEndpoint->StartFrame + Frame;
+        uframe = TtEndpoint->StartMicroframe;
+
+        if (TtEndpoint->StartMicroframe == 0xFF)
+        {
+            USB2_GetPrevMicroFrame(&frame, &uframe);
+        }
+
+        DataTime = 0;
+
+        for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+        {
+            DataSize = PktSizeBitStuff - DataTime;
+
+            if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            {
+                CurrentDataTime = PktSizeBitStuff - DataTime;
             }
             else
             {
-                TtEndpoint->Nums.NumCompletes = 2;
+                CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+            }
+
+            HcExtension->TimeUsed[frame][uframe] -= CurrentDataTime;
+            USB2_IncMicroFrame(&frame, &uframe);
+            DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+        }
+    }
+    else
+    {
+        frame = TtEndpoint->StartFrame + Frame;
+        uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+        for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+        {
+            if (PktSizeBitStuff >= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            {
+                CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+            }
+            else
+            {
+                CurrentDataTime = PktSizeBitStuff;
             }
+
+            Tt->TimeCS[frame][uframe] -= CurrentDataTime;
+
+            if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            {
+                RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
+                                 Tt->TimeCS[frame][uframe];
+
+                if (RemainDataTime >= PktSizeBitStuff)
+                    RemainDataTime = PktSizeBitStuff;
+
+                HcExtension->TimeUsed[frame][uframe] -= RemainDataTime;
+            }
+
+            USB2_IncMicroFrame(&frame, &uframe);
+        }
+    }
+
+    return;
+}
+
+BOOLEAN
+NTAPI
+USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                    IN USHORT BusTime,
+                    IN PUSB2_REBALANCE Rebalance,
+                    IN ULONG RebalanceListEntries,
+                    OUT BOOLEAN * OutResult)
+{
+    ULONG EndBusTime;
+    ULONG TransferType;
+    ULONG Num;
+    UCHAR ix;
+
+    DPRINT("USB2_MoveTtEndpoint: TtEndpoint - %p, BusTime - %X\n",
+           TtEndpoint,
+           BusTime);
+
+    *OutResult = TRUE;
+
+    for (Num = 0; Rebalance->RebalanceEndpoint[Num]; Num++)
+    {
+        if (Rebalance->RebalanceEndpoint[Num] == TtEndpoint)
+            break;
+    }
+
+    DPRINT("USB2_MoveTtEndpoint: Num - %X\n", Num);
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    if (Rebalance->RebalanceEndpoint[Num] &&
+        TtEndpoint->TtEndpointParams.EndpointMoved == TRUE &&
+        (TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT || BusTime >= 0))
+    {
+        DPRINT("USB2_MoveTtEndpoint: result - FALSE\n");
+        return FALSE;
+    }
+
+    for (ix = 0;
+         (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+         ix += TtEndpoint->ActualPeriod)
+    {
+        USB2_DeallocateHS(TtEndpoint, ix);
+    }
+
+    TtEndpoint->StartTime += BusTime;
+
+    EndBusTime = TtEndpoint->StartTime + TtEndpoint->CalcBusTime;
+
+    if (EndBusTime > USB2_FS_MAX_PERIODIC_ALLOCATION)
+    {
+        DPRINT("USB2_MoveTtEndpoint: EndBusTime is too large!\n");
+        *OutResult = FALSE;
+    }
+
+    TtEndpoint->TtEndpointParams.EndpointMoved = TRUE;
+
+    if (Rebalance->RebalanceEndpoint[Num] == NULL)
+    {
+        if (Num >= RebalanceListEntries)
+        {
+            DPRINT("USB2_MoveTtEndpoint: Too many changes!\n");
+            *OutResult = FALSE;
+        }
+        else
+        {
+            Rebalance->RebalanceEndpoint[Num] = TtEndpoint;
+            Rebalance->RebalanceEndpoint[Num + 1] = NULL;
+        }
+    }
+
+    for (ix = 0;
+         (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+         ix += TtEndpoint->ActualPeriod)
+    {
+        if (!USB2_AllocateHS(TtEndpoint, ix))
+        {
+            DPRINT("USB2_MoveTtEndpoint: OutResult - FALSE\n");
+            OutResult = FALSE;
         }
     }
+
+    DPRINT("USB2_MoveTtEndpoint: result - TRUE\n");
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,
+                  IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    UCHAR Frame;
+
+    DPRINT("USB2_CommonFrames: \n");
+
+    if (NextTtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms ||
+        TtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms)
+    {
+        return TRUE;
+    }
+
+    if (NextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod)
+    {
+        Frame = TtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
+    }
+    else
+    {
+        Frame = NextTtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
+    }
+
+    return (Frame == TtEndpoint->StartFrame);
+}
+
+VOID
+NTAPI
+USB2_ConvertFrame(IN UCHAR Frame,
+                  IN UCHAR Microframe,
+                  OUT PUCHAR HcFrame,
+                  OUT PUCHAR HcMicroframe)
+{
+    DPRINT("USB2_ConvertFrame: Frame - %x, Microframe - %x\n",
+           Frame,
+           Microframe);
+
+    if (Microframe == 0xFF)
+    {
+        *HcFrame = Frame;
+        *HcMicroframe = 0;
+    }
+
+    if (Microframe >= 0 &&
+        Microframe <= (USB2_MICROFRAMES - 2))
+    {
+        *HcFrame = Frame;
+        *HcMicroframe = Microframe + 1;
+    }
+
+    if (Microframe == (USB2_MICROFRAMES - 1))
+    {
+        *HcFrame = Frame + 1;
+        *HcMicroframe = 0;
+    }
+}
+
+UCHAR
+NTAPI
+USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    ULONG ix;
+    UCHAR SMask = 0;
+    UCHAR HcFrame;
+    UCHAR HcMicroFrame;
+
+    if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
+    {
+        SMask = (1 << TtEndpoint->StartMicroframe);
+    }
+    else
+    {
+        USB2_ConvertFrame(TtEndpoint->StartFrame,
+                          TtEndpoint->StartMicroframe,
+                          &HcFrame,
+                          &HcMicroFrame);
+
+        for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+        {
+            SMask |= (1 << HcMicroFrame);
+            HcMicroFrame++;
+        }
+    }
+
+    return SMask;
+}
+
+UCHAR
+NTAPI
+USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    ULONG NumCompletes;
+    ULONG TransferType;
+    ULONG DeviceSpeed;
+    ULONG Direction;
+    UCHAR Result;
+    UCHAR MicroFrameCS;
+    UCHAR HcFrame;
+    UCHAR HcMicroFrame;
+    UCHAR MaskCS = 0;
+    static const UCHAR CMASKS[USB2_MICROFRAMES] = {
+      0x1C, 0x38, 0x70, 0xE0, 0xC1, 0x83, 0x07, 0x0E 
+    };   
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+    DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+    Direction = TtEndpoint->TtEndpointParams.Direction;
+
+    if (DeviceSpeed == UsbHighSpeed)
+    {
+        return 0;
+    }
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        USB2_ConvertFrame(TtEndpoint->StartFrame,
+                          TtEndpoint->StartMicroframe,
+                          &HcFrame,
+                          &HcMicroFrame);
+
+        Result = CMASKS[HcMicroFrame];
+    }
+    else
+    {
+        if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+        {
+            return 0;
+        }
+
+        USB2_ConvertFrame(TtEndpoint->StartFrame,
+                          TtEndpoint->StartMicroframe,
+                          &HcFrame,
+                          &HcMicroFrame);
+
+        NumCompletes = TtEndpoint->Nums.NumCompletes;
+
+        for (MicroFrameCS = HcMicroFrame + 2;
+             MicroFrameCS < USB2_MICROFRAMES;
+             MicroFrameCS++)
+        {
+            MaskCS |= (1 << MicroFrameCS);
+            NumCompletes--;
+
+            if (!NumCompletes)
+            {
+                return MaskCS;
+            }
+        }
+
+        for (; NumCompletes; NumCompletes--)
+        {
+            MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES));
+        }
+
+        Result = MaskCS;
+    }
+
+    return Result;
+}
+
+VOID
+NTAPI
+USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
+                       IN PLIST_ENTRY List)
+{
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSBPORT_ENDPOINT Endpoint;
+    PLIST_ENTRY Entry;
+    ULONG AllocedBusTime;
+    ULONG EndpointBandwidth;
+    ULONG Factor;
+    ULONG ScheduleOffset;
+    ULONG Bandwidth;
+    ULONG n;
+    ULONG ix;
+    KIRQL OldIrql;
+    UCHAR NewPeriod;
+    UCHAR SMask;
+    UCHAR CMask;
+
+    FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
+
+    while (!IsListEmpty(List))
+    {
+        Entry = RemoveHeadList(List);
+
+        Endpoint = CONTAINING_RECORD(Entry,
+                                     USBPORT_ENDPOINT,
+                                     RebalanceLink.Flink);
+
+        DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
+
+        Endpoint->RebalanceLink.Flink = NULL;
+        Endpoint->RebalanceLink.Blink = NULL;
+
+        KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+                          &Endpoint->EndpointOldIrql);
+
+        SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+        CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+
+        ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+        NewPeriod = Endpoint->TtEndpoint->ActualPeriod;
+
+        AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime;
+        EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
+
+        Endpoint->EndpointProperties.InterruptScheduleMask = SMask;
+        Endpoint->EndpointProperties.SplitCompletionMask = CMask;
+
+        if (Endpoint->EndpointProperties.Period != NewPeriod)
+        {
+            Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
+            ASSERT(Factor);
+
+            for (ix = 0; ix < Factor; ix++)
+            {
+                Bandwidth = Endpoint->EndpointProperties.UsbBandwidth;
+                n = Factor * Endpoint->EndpointProperties.ScheduleOffset;
+                Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth;
+            }
+
+            Endpoint->EndpointProperties.Period = NewPeriod;
+            Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset;
+            Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth;
+
+            Factor = USB2_FRAMES / NewPeriod;
+            ASSERT(Factor);
+
+            for (ix = 0; ix < Factor; ix++)
+            {
+                n = Factor * ScheduleOffset;
+                Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
+            }
+        }
+
+        KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+        Packet->RebalanceEndpoint(FdoExtension->MiniPortExt,
+                                  &Endpoint->EndpointProperties,
+                                  (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT)));
+
+        KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+        KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+                          Endpoint->EndpointOldIrql);
+    }
+}
+
+VOID
+NTAPI
+USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,
+               IN PLIST_ENTRY RebalanceList)
+{
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    PUSBPORT_ENDPOINT Endpoint;
+    PLIST_ENTRY Entry;
+    LIST_ENTRY BalanceListInt1;
+    LIST_ENTRY BalanceListInt2;
+    ULONG TransferType;
+    ULONG ScheduleOffset;
+    UCHAR SMask;
+    UCHAR CMask;
+    UCHAR ActualPeriod;
+
+    DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n",
+           FdoDevice,
+           RebalanceList);
+
+    InitializeListHead(&BalanceListInt1);
+    InitializeListHead(&BalanceListInt2);
+
+    while (!IsListEmpty(RebalanceList))
+    {
+        Entry = RebalanceList->Flink;
+
+        Endpoint = CONTAINING_RECORD(Entry,
+                                     USBPORT_ENDPOINT,
+                                     RebalanceLink.Flink);
+
+        DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n",
+               Entry,
+               Endpoint);
+
+        RemoveHeadList(RebalanceList);
+        Entry->Flink = NULL;
+        Entry->Blink = NULL;
+
+        SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+        CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+
+        ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+        ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
+
+        EndpointProperties = &Endpoint->EndpointProperties;
+        TransferType = EndpointProperties->TransferType;
+
+        switch (TransferType)
+        {
+            case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+                DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
+                ASSERT(FALSE);
+                break;
+
+            case USBPORT_TRANSFER_TYPE_INTERRUPT:
+                if (SMask != EndpointProperties->InterruptScheduleMask ||
+                    CMask != EndpointProperties->SplitCompletionMask || 
+                    ScheduleOffset != EndpointProperties->ScheduleOffset ||
+                    ActualPeriod != EndpointProperties->Period)
+                {
+                    if (ActualPeriod == EndpointProperties->Period &&
+                        ScheduleOffset == EndpointProperties->ScheduleOffset)
+                    {
+                        InsertTailList(&BalanceListInt1, Entry);
+                    }
+                    else
+                    {
+                        InsertTailList(&BalanceListInt2, Entry);
+                    }
+                }
+                break;
+
+            default:
+                ASSERT(FALSE);
+                break;
+        }
+    }
+
+    USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2);
+    USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1);
+    //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso);
+}
+
+BOOLEAN
+NTAPI
+USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                              IN PUSB2_REBALANCE Rebalance,
+                              IN PULONG RebalanceListEntries,
+                              IN ULONG MaxFrames)
+{
+    PUSB2_TT Tt;
+    PUSB2_HC_EXTENSION HcExtension;
+    ULONG Speed;
+    ULONG TransferType;
+    ULONG Frame;
+    ULONG StartMicroframe;
+    ULONG ix;
+    PUSB2_TT_ENDPOINT endpoint;
+    PUSB2_TT_ENDPOINT nextEndpoint;
+    PUSB2_TT_ENDPOINT lastEndpoint;
+    PUSB2_TT_ENDPOINT tmpEndpoint;
+    ULONG endTime;
+    ULONG maxEndTime;
+    ULONG lastEndTime;
+    ULONG Factor;
+    ULONG jx;
+    UCHAR frame;
+    UCHAR uframe;
+    USHORT Period;
+    BOOLEAN IsMoved = FALSE;
+
+    DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
+           TtEndpoint,
+           MaxFrames,
+           TtEndpoint->CalcBusTime);
+
+    if (TtEndpoint->CalcBusTime == 0)
+    {
+        DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
+        return FALSE;
+    }
+
+    Tt = TtEndpoint->Tt;
+    HcExtension = Tt->HcExtension;
+
+    Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+    DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
+
+    StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
+                      TtEndpoint->StartMicroframe;
+
+    if (Speed == UsbHighSpeed)
+    {
+        for (ix = StartMicroframe;
+             ix < USB2_MAX_MICROFRAMES;
+             ix += TtEndpoint->ActualPeriod)
+        {
+            frame = ix / USB2_MICROFRAMES;
+            uframe = ix % (USB2_MICROFRAMES - 1);
+
+            HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
+        }
+
+        TtEndpoint->CalcBusTime = 0;
+
+        DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
+        return TRUE;
+    }
+
+    /* Speed != UsbHighSpeed (FS/LS) */
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
+         ix > 0;
+         ix--, Frame--)
+    {
+        frame = TtEndpoint->StartFrame + Frame;
+
+        DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
+               frame,
+               Frame,
+               TtEndpoint->StartFrame);
+
+        if ((Frame % TtEndpoint->ActualPeriod) == 0)
+        {
+            USB2_DeallocateHS(TtEndpoint, Frame);
+            Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
+        }
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+        {
+            endpoint = Tt->FrameBudget[frame].IntEndpoint;
+        }
+        else
+        {
+            endpoint = Tt->FrameBudget[frame].IsoEndpoint;
+        }
+
+        nextEndpoint = endpoint->NextTtEndpoint;
+
+        DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
+               TtEndpoint,
+               nextEndpoint);
+
+        if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+        {
+            while (nextEndpoint)
+            {
+                endpoint = nextEndpoint;
+                nextEndpoint = nextEndpoint->NextTtEndpoint;
+            }
+
+            nextEndpoint = TtEndpoint;
+
+            DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+                   endpoint,
+                   nextEndpoint);
+        }
+        else
+        {
+            while (nextEndpoint &&
+                   !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+            {
+                endpoint = nextEndpoint;
+                nextEndpoint = nextEndpoint->NextTtEndpoint;
+            }
+
+            if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
+                nextEndpoint)
+            {
+                DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
+                ASSERT(FALSE);
+            }
+
+            DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+                   endpoint,
+                   nextEndpoint);
+        }
+
+        if ((Frame % TtEndpoint->ActualPeriod) == 0)
+        {
+            if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+            {
+                Tt->FrameBudget[frame].AltEndpoint = NULL;
+            }
+            else if (nextEndpoint)
+            {
+                nextEndpoint = nextEndpoint->NextTtEndpoint;
+                endpoint->NextTtEndpoint = nextEndpoint;
+
+                DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+                       endpoint,
+                       nextEndpoint);
+            }
+        }
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+        {
+            if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
+            {
+                if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
+                {
+                    endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
+                    DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
+                }
+                else if (Tt->FrameBudget[frame].AltEndpoint)
+                {
+                    endpoint = Tt->FrameBudget[frame].AltEndpoint;
+                    DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
+                }
+            }
+        }
+        else
+        {
+            DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
+            ASSERT(FALSE);
+        }
+
+        Period = TtEndpoint->ActualPeriod;
+
+        for (;
+             nextEndpoint;
+             endpoint = nextEndpoint,
+             nextEndpoint = nextEndpoint->NextTtEndpoint)
+        {
+            DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+                   endpoint,
+                   nextEndpoint);
+
+            endTime = endpoint->StartTime + endpoint->CalcBusTime;
+            maxEndTime = endTime;
+
+            if (Period > nextEndpoint->ActualPeriod ||
+                TtEndpoint->StartFrame != nextEndpoint->StartFrame)
+            {
+                if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
+                    Factor = Period / nextEndpoint->ActualPeriod;
+                else
+                    Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
+
+                maxEndTime = endTime;
+
+                for (jx = 0, frame = nextEndpoint->StartFrame;
+                     jx < Factor;
+                     jx++, frame += nextEndpoint->ActualPeriod)
+                {
+                    if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
+                    {
+                        lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
+
+                        if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
+                        {
+                            lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
+                        }
+                        else if (Tt->FrameBudget[frame].AltEndpoint)
+                        {
+                            lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
+                        }
+
+                        for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
+                             tmpEndpoint && tmpEndpoint != nextEndpoint;
+                             tmpEndpoint = tmpEndpoint->NextTtEndpoint)
+                        {
+                            lastEndpoint = tmpEndpoint;
+                        }
+
+                        lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
+
+                        if (endTime < (lastEndTime - 1))
+                        {
+                            maxEndTime = lastEndTime;
+                            endTime = maxEndTime;
+
+                            if (nextEndpoint->StartTime == maxEndTime)
+                                break;
+                        }
+                        else
+                        {
+                            maxEndTime = endTime;
+                        }
+                    }
+                }
+            }
+
+            if (maxEndTime >= nextEndpoint->StartTime)
+                break;
+
+            if (!USB2_MoveTtEndpoint(nextEndpoint,
+                                     maxEndTime - nextEndpoint->StartTime,
+                                     Rebalance,
+                                     *RebalanceListEntries,
+                                     &IsMoved))
+            {
+                if (!IsMoved)
+                {
+                    DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
+                }
+
+                break;
+            }
+
+            if (Period > nextEndpoint->ActualPeriod)
+                Period = nextEndpoint->ActualPeriod;
+        }
+    }
+
+    TtEndpoint->CalcBusTime = 0;
+
+    DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                             IN PUSB2_REBALANCE Rebalance,
+                             IN PULONG RebalanceListEntries)
+{
+    PUSB2_TT Tt;
+    PUSB2_HC_EXTENSION HcExtension;
+    ULONG Speed;
+    ULONG TimeUsed;
+    ULONG MinTimeUsed;
+    ULONG ix;
+    ULONG frame;
+    ULONG uframe;
+    ULONG Microframe;
+    ULONG TransferType;
+    ULONG Overhead;
+    ULONG LatestStart;
+    PUSB2_TT_ENDPOINT prevEndpoint;
+    PUSB2_TT_ENDPOINT nextEndpoint;
+    PUSB2_TT_ENDPOINT IntEndpoint;
+    ULONG StartTime;
+    ULONG calcBusTime;
+    BOOLEAN Result = TRUE;
+
+    DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
+
+    Tt = TtEndpoint->Tt;
+    HcExtension = Tt->HcExtension;
+
+    TtEndpoint->Nums.NumStarts = 0;
+    TtEndpoint->Nums.NumCompletes = 0;
+
+    TtEndpoint->StartFrame = 0;
+    TtEndpoint->StartMicroframe = 0;
+
+    if (TtEndpoint->CalcBusTime)
+    {
+        DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
+        return FALSE;
+    }
+
+    Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+
+    if (Speed == UsbHighSpeed)
+    {
+        if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
+            TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
+        else
+            TtEndpoint->ActualPeriod = TtEndpoint->Period;
+
+        MinTimeUsed = HcExtension->TimeUsed[0][0];
+
+        for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
+        {
+            frame = ix / USB2_MICROFRAMES;
+            uframe = ix % (USB2_MICROFRAMES - 1);
+
+            TimeUsed = HcExtension->TimeUsed[frame][uframe];
+
+            if (TimeUsed < MinTimeUsed)
+            {
+                MinTimeUsed = TimeUsed;
+                TtEndpoint->StartFrame = frame;
+                TtEndpoint->StartMicroframe = uframe;
+            }
+        }
+
+        TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
+                                  USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
+
+        DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
+               TtEndpoint->StartFrame,
+               TtEndpoint->StartMicroframe,
+               TtEndpoint->CalcBusTime);
+
+        Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
+                     TtEndpoint->StartMicroframe;
+
+        if (Microframe >= USB2_MAX_MICROFRAMES)
+        {
+            DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
+            return TRUE;
+        }
+
+        for (ix = Microframe;
+             ix < USB2_MAX_MICROFRAMES;
+             ix += TtEndpoint->ActualPeriod)
+        {
+            frame = ix / USB2_MICROFRAMES;
+            uframe = ix % (USB2_MICROFRAMES - 1);
+
+            DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
+                   frame,
+                   uframe,
+                   HcExtension->TimeUsed[frame][uframe]);
+
+            if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                    TtEndpoint->CalcBusTime,
+                                    USB2_MAX_MICROFRAME_ALLOCATION))
+            {
+                DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+                Result = FALSE;
+            }
+        }
+
+        if (!Result)
+        {
+            for (ix = Microframe;
+                 ix < USB2_MAX_MICROFRAMES;
+                 ix += TtEndpoint->ActualPeriod)
+            {
+                frame = ix / USB2_MICROFRAMES;
+                uframe = ix % (USB2_MICROFRAMES - 1);
+
+                HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
+            }
+        }
+
+        DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
+        return TRUE;
+    }
+
+    /* Speed != UsbHighSpeed (FS/LS) */
+
+    if (TtEndpoint->Period > USB2_FRAMES)
+        TtEndpoint->ActualPeriod = USB2_FRAMES;
     else
+        TtEndpoint->ActualPeriod = TtEndpoint->Period;
+
+    MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
+
+    for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
     {
-        if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+        if ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
         {
-            DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
-            ASSERT(FALSE);
+            MinTimeUsed = Tt->FrameBudget[ix].TimeUsed;
+            TtEndpoint->StartFrame = ix;
+        }
+    }
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+    {
+        if (Speed == UsbFullSpeed)
+        {
+            Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD + Tt->DelayTime;
         }
         else
         {
-            DPRINT("USB2_AllocateHS: ISO UNIMPLEMENTED\n");
-            ASSERT(FALSE);
+            DPRINT("USB2_AllocateTimeForEndpoint: ISO can not be on a LS bus!\n");
+            return FALSE;
         }
     }
+    else
+    {
+        if (Speed == UsbFullSpeed)
+            Overhead = USB2_FS_INTERRUPT_OVERHEAD + Tt->DelayTime;
+        else
+            Overhead = USB2_LS_INTERRUPT_OVERHEAD + Tt->DelayTime;
+    }
 
-    frame = TtEndpoint->StartFrame + Frame;
-    uframe = TtEndpoint->StartMicroframe;
+    if (Speed == UsbLowSpeed)
+    {
+        TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
+    }
+    else
+    {
+        TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
+    }
 
-    if (TtEndpoint->StartMicroframe == 0xFF)
-        USB2_GetPrevMicroFrame(&frame, &uframe);
+    LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
 
-    for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+    for (ix = 0;
+         (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+         ix += TtEndpoint->ActualPeriod)
     {
-        if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
-                                OverheadSS,
-                                USB2_MAX_MICROFRAME_ALLOCATION))
+        frame = TtEndpoint->StartFrame + ix;
+
+        if (Tt->FrameBudget[frame].AltEndpoint &&
+            TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
         {
-            Result = FALSE;
+            DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+            return FALSE;
         }
 
-        if (Tt->NumStartSplits[frame][uframe] > (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+            prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
+        else
+            prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
+
+        for (nextEndpoint = prevEndpoint->NextTtEndpoint;
+             nextEndpoint;
+             nextEndpoint = nextEndpoint->NextTtEndpoint)
         {
-            DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
-                    Tt->NumStartSplits[frame][uframe] + 1);
+            if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+            {
+                break;
+            }
 
-            ASSERT(FALSE);
-            Result = FALSE;
+            prevEndpoint = nextEndpoint;
         }
 
-        ++Tt->NumStartSplits[frame][uframe];
-        USB2_IncMicroFrame(&frame, &uframe);
+        StartTime = USB2_GetStartTime(nextEndpoint,
+                                      TtEndpoint,
+                                      prevEndpoint,
+                                      frame);
+
+        if (StartTime > LatestStart)
+            LatestStart = StartTime;
     }
 
-    frame = TtEndpoint->StartFrame + Frame;
-    uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+    TtEndpoint->StartTime = LatestStart;
 
-    for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+    if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
     {
-        if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
-                                OverheadCS,
-                                USB2_MAX_MICROFRAME_ALLOCATION))
-        {
-            Result = FALSE;
-        }
-
-        USB2_IncMicroFrame(&frame, &uframe);
+        TtEndpoint->CalcBusTime = 0;
+        DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+        return FALSE;
     }
 
-    if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
-    {
-        DPRINT("USB2_AllocateHS: DIRECTION OUT UNIMPLEMENTED\n");
-        ASSERT(FALSE);
-    }
-    else
+    for (ix = 0, frame = -TtEndpoint->StartFrame;
+         ix < USB2_FRAMES;
+         ix++, frame++)
     {
-        frame = TtEndpoint->StartFrame + Frame;
-        uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+        DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
+               ix,
+               frame,
+               TtEndpoint->StartFrame);
 
-        for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
         {
-            if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
+            ASSERT(FALSE);
+        }
+        else
+        {
+            IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
+            nextEndpoint = IntEndpoint->NextTtEndpoint;
+
+            for (nextEndpoint = IntEndpoint->NextTtEndpoint;
+                 nextEndpoint;
+                 nextEndpoint = nextEndpoint->NextTtEndpoint)
+            {
+                if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+                    break;
+                IntEndpoint = nextEndpoint;
+            }
+
+            if ((frame % TtEndpoint->ActualPeriod) == 0)
+            {
+                calcBusTime = 0;
+            }
+            else
             {
-                if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+                if (nextEndpoint)
                 {
-                    RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
-                                     Tt->TimeCS[frame][uframe];
+                    calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
+                                  nextEndpoint->StartTime;
                 }
                 else
                 {
-                    RemainDataTime = 0;
+                    calcBusTime = TtEndpoint->CalcBusTime;
                 }
 
-                PktSize = TtEndpoint->MaxPacketSize;
-
-                if (RemainDataTime >= USB2_AddDataBitStuff(PktSize))
+                if (calcBusTime > 0)
                 {
-                    DataTime = USB2_AddDataBitStuff(PktSize);
+                    TimeUsed = Tt->FrameBudget[ix].TimeUsed;
+
+                    if (!USB2_AllocateCheck(&TimeUsed,
+                                            calcBusTime,
+                                            USB2_FS_MAX_PERIODIC_ALLOCATION))
+                    {
+                        DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+                        Result = FALSE;
+                    }
                 }
-                else
+            }
+
+            if (nextEndpoint != TtEndpoint)
+            {
+                if ((frame % TtEndpoint->ActualPeriod) == 0)
                 {
-                    DataTime = RemainDataTime;
+                    if (frame == 0)
+                    {
+                        DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
+                        TtEndpoint->NextTtEndpoint = nextEndpoint;
+                    }
+
+                    IntEndpoint->NextTtEndpoint = TtEndpoint;
+
+                    DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextEndpoint - %p\n",
+                           TtEndpoint,
+                           nextEndpoint);
                 }
 
-                if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
-                                        DataTime,
-                                        USB2_MAX_MICROFRAME_ALLOCATION))
+                if (calcBusTime > 0)
                 {
-                    Result = FALSE;
+                    BOOLEAN IsMoved;
+                    BOOLEAN MoveResult;
+
+                    DPRINT("USB2_AllocateTimeForEndpoint: nextEndpoint - %p, calcBusTime - %X\n",
+                           nextEndpoint,
+                           calcBusTime);
+
+                    for (;
+                         nextEndpoint;
+                         nextEndpoint = nextEndpoint->NextTtEndpoint)
+                    {
+                        MoveResult = USB2_MoveTtEndpoint(nextEndpoint,
+                                                         calcBusTime,
+                                                         Rebalance,
+                                                         *RebalanceListEntries,
+                                                         &IsMoved);
+
+                        if (!IsMoved)
+                        {
+                            DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+                            Result = FALSE;
+                        }
+
+                        if (!MoveResult)
+                            break;
+                    }
                 }
             }
+        }
 
-            PktSize = TtEndpoint->MaxPacketSize;
-
-            if (USB2_AddDataBitStuff(PktSize) < USB2_FS_RAW_BYTES_IN_MICROFRAME)
-            {
-                Tt->TimeCS[frame][uframe] += USB2_AddDataBitStuff(PktSize);
-            }
-            else
+        if ((frame % TtEndpoint->ActualPeriod) == 0)
+        {
+            if (!USB2_AllocateHS(TtEndpoint, frame))
             {
-                Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+                DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
+                Result = FALSE;
             }
 
-            USB2_IncMicroFrame(&frame, &uframe);
+            Tt->FrameBudget[ix].TimeUsed += TtEndpoint->CalcBusTime;
+        }
+
+        if (Result == FALSE)
+        {
+            USB2_DeallocateEndpointBudget(TtEndpoint,
+                                          Rebalance,
+                                          RebalanceListEntries,
+                                          ix + 1);
+
+            DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+            return FALSE;
         }
     }
 
-    DPRINT("USB2_AllocateHS: Result - %X\n", Result);
+    DPRINT("USB2_AllocateTimeForEndpoint: Result - %X\n", Result);
     return Result;
 }
 
 BOOLEAN
 NTAPI
-USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
-                              IN PUSB2_REBALANCE Rebalance,
-                              IN PULONG RebalanceListEntries,
-                              IN ULONG MaxFrames)
+USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                  IN PUSB2_REBALANCE Rebalance,
+                  IN PULONG RebalanceListEntries)
 {
-    DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
-    ASSERT(FALSE);
-    return FALSE;
-}
+    BOOLEAN Result;
 
-BOOLEAN
-NTAPI
-USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
-                             IN PUSB2_REBALANCE Rebalance,
-                             IN PULONG RebalanceListEntries)
-{
-    DPRINT("USB2_AllocateTimeForEndpoint: UNIMPLEMENTED. FIXME\n");
-    ASSERT(FALSE);
-    return FALSE;
+    DPRINT("USB2_ChangePeriod: RebalanceListEntries - %X\n",
+           *RebalanceListEntries);
+
+    USB2_DeallocateEndpointBudget(TtEndpoint,
+                                  Rebalance,
+                                  RebalanceListEntries,
+                                  USB2_FRAMES);
+
+    TtEndpoint->PreviosPeriod = TtEndpoint->Period;
+    TtEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
+
+    Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
+                                          Rebalance,
+                                          RebalanceListEntries);
+
+    return Result;
 }
 
 BOOLEAN
@@ -502,8 +1705,100 @@ USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
                     IN PUSB2_REBALANCE Rebalance,
                     IN PULONG RebalanceListEntries)
 {
-    DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
-    ASSERT(FALSE);
+    PUSB2_TT_ENDPOINT ttEndpoint;
+    ULONG TransferType;
+    ULONG ix;
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
+        TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
+        (CHAR)TtEndpoint->StartMicroframe > 2 &&
+        !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
+    {
+        DPRINT("USB2_PromotePeriods: return FALSE\n");
+        return FALSE;
+    }
+
+    if (Rebalance->RebalanceEndpoint[0] == NULL)
+    {
+        DPRINT("USB2_PromotePeriods: return TRUE\n");
+        return TRUE;
+    }
+
+    DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
+           *RebalanceListEntries);
+
+    for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+    {
+        Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
+    }
+
+    for (ix = 0; ; ix++)
+    {
+        ttEndpoint = Rebalance->RebalanceEndpoint[ix];
+        TransferType = ttEndpoint->TtEndpointParams.TransferType;
+
+        if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
+            TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
+            ttEndpoint->StartMicroframe > 2)
+        {
+            USB2_DeallocateEndpointBudget(ttEndpoint,
+                                          Rebalance,
+                                          RebalanceListEntries,
+                                          USB2_FRAMES);
+
+            ttEndpoint->IsPromoted = TRUE;
+            ttEndpoint->PreviosPeriod = ttEndpoint->Period;
+            ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
+
+            if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
+                                              Rebalance,
+                                              RebalanceListEntries))
+            {
+                break;
+            }
+        }
+
+        if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
+        {
+            DPRINT("USB2_PromotePeriods: return TRUE\n");
+            return TRUE;
+        }
+    }
+
+    USB2_DeallocateEndpointBudget(TtEndpoint,
+                                  Rebalance,
+                                  RebalanceListEntries,
+                                  USB2_FRAMES);
+
+    TtEndpoint->Period = TtEndpoint->PreviosPeriod;
+    TtEndpoint->PreviosPeriod = 0;
+
+    for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+    {
+        ttEndpoint = Rebalance->RebalanceEndpoint[ix];
+
+        if (ttEndpoint->IsPromoted)
+        {
+            if (ttEndpoint->CalcBusTime)
+            {
+                USB2_DeallocateEndpointBudget(ttEndpoint,
+                                              Rebalance,
+                                              RebalanceListEntries,
+                                              USB2_FRAMES);
+            }
+
+            TtEndpoint->Period = TtEndpoint->PreviosPeriod;
+            TtEndpoint->PreviosPeriod = 0;
+
+            USB2_AllocateTimeForEndpoint(ttEndpoint,
+                                         Rebalance,
+                                         RebalanceListEntries);
+        }
+    }
+
+    DPRINT("USB2_PromotePeriods: return FALSE\n");
     return FALSE;
 }
 
@@ -763,7 +2058,7 @@ USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
         }
     }
 
-    //USB2_Rebalance(FdoDevice, &RebalanceList);
+    USB2_Rebalance(FdoDevice, &RebalanceList);
 
     if (!TtExtension)
     {
@@ -793,7 +2088,122 @@ NTAPI
 USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
                           IN PUSBPORT_ENDPOINT Endpoint)
 {
-    DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    ULONG Period;
+    ULONG ScheduleOffset;
+    ULONG EndpointBandwidth;
+    LIST_ENTRY RebalanceList;
+    ULONG TransferType;
+    PUSB2_REBALANCE Rebalance;
+    ULONG RebalanceListEntries;
+    ULONG Factor;
+    ULONG ix;
+    ULONG n;
+    PUSB2_TT_EXTENSION TtExtension;
+    PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
+
+    DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    Period = Endpoint->EndpointProperties.Period;
+    ASSERT(Period != 0);
+
+    ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
+    EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
+
+    InitializeListHead(&RebalanceList);
+
+    TransferType = Endpoint->EndpointProperties.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+        TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+        (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+    {
+        return;
+    }
+
+    Rebalance = ExAllocatePoolWithTag(NonPagedPool,
+                                      sizeof(USB2_REBALANCE),
+                                      USB_PORT_TAG);
+
+    if (!Rebalance)
+    {
+        DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
+        return;
+    }
+
+    RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
+
+    Factor = USB2_FRAMES / Period;
+    n = ScheduleOffset * Factor;
+
+    TtExtension = Endpoint->TtExtension;
+
+    if (TtExtension)
+    {
+        for (ix = 0; ix < Factor; ix++)
+        {
+            TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
+        }
+    }
+    else
+    {
+        for (ix = 1; ix < Factor; ix++)
+        {
+            FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
+        }
+    }
+
+    RebalanceListEntries = USB2_FRAMES - 2;
+
+    USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
+                                  Rebalance,
+                                  &RebalanceListEntries,
+                                  USB2_FRAMES);
+
+    RebalanceListEntries = 0;
+
+    for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+    {
+        RebalanceListEntries = ix + 1;
+    }
+
+    for (ix = 0; ix < RebalanceListEntries; ix++)
+    {
+        RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
+
+        DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
+               ix,
+               RebalanceTtEndpoint,
+               &RebalanceTtEndpoint->Endpoint->RebalanceLink);
+
+        InsertTailList(&RebalanceList,
+                       &RebalanceTtEndpoint->Endpoint->RebalanceLink);
+    }
+
+    ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
+
+    USB2_Rebalance(FdoDevice, &RebalanceList);
+
+    if (!TtExtension)
+    {
+        return;
+    }
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
+    }
+
+    USBPORT_UpdateAllocatedBwTt(TtExtension);
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
+    }
+
+    DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
 }
 
 VOID