[USBPORT] Add stub for USB2_DeallocateHS().
[reactos.git] / drivers / usb / usbport / usb2.c
index a91650e..e36bf1b 100644 (file)
@@ -159,6 +159,53 @@ USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
     return Overhead;
 }
 
+VOID
+NTAPI
+USB2_GetHsOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                   IN PULONG OverheadSS,
+                   IN PULONG OverheadCS)
+{
+    ULONG TransferType;
+    ULONG Direction;
+    ULONG HostDelay;
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+    Direction = TtEndpoint->TtEndpointParams.Direction;
+
+    HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
+
+    if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+    {
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD;
+            *OverheadCS = 0;
+        }
+        else
+        {
+            *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_OUT_OVERHEAD;
+            *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_OUT_OVERHEAD;
+        }
+    }
+    else
+    {
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            *OverheadSS = HostDelay + USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD;
+            *OverheadCS = HostDelay + USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD;
+        }
+        else
+        {
+            *OverheadSS = HostDelay + USB2_HS_SS_INTERRUPT_IN_OVERHEAD;
+            *OverheadCS = HostDelay + USB2_HS_CS_INTERRUPT_IN_OVERHEAD;
+        }
+
+        DPRINT("USB2_GetHsOverhead: *OverheadSS - %X, *OverheadCS - %X\n",
+               *OverheadSS,
+               *OverheadCS);
+    }
+}
+
 ULONG
 NTAPI
 USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,
@@ -204,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)
@@ -239,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;
@@ -248,15 +291,203 @@ 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
 NTAPI
 USB2_AllocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
-                IN ULONG Frame)
+                IN LONG Frame)
 {
-    DPRINT("USB2_AllocateHS: UNIMPLEMENTED FIXME\n");
-    return FALSE;
+    PUSB2_HC_EXTENSION HcExtension;
+    PUSB2_TT Tt;
+    ULONG TransferType;
+    ULONG Direction;
+    ULONG DataTime;
+    ULONG RemainDataTime;
+    ULONG OverheadCS;
+    ULONG OverheadSS;
+    ULONG ix;
+    USHORT PktSize;
+    UCHAR frame;
+    UCHAR uframe;
+    BOOL Result = TRUE;
+
+    DPRINT("USB2_AllocateHS: TtEndpoint - %p, Frame - %X, TtEndpoint->StartFrame - %X\n",
+           TtEndpoint,
+           Frame,
+           TtEndpoint->StartFrame);
+
+    Tt = TtEndpoint->Tt;
+    HcExtension = Tt->HcExtension;
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+    Direction = TtEndpoint->TtEndpointParams.Direction;
+
+    if (Frame == 0)
+    {
+        TtEndpoint->StartMicroframe =
+        TtEndpoint->StartTime / USB2_FS_RAW_BYTES_IN_MICROFRAME - 1;
+
+        DPRINT("USB2_AllocateHS: TtEndpoint->StartMicroframe - %X\n",
+               TtEndpoint->StartMicroframe);
+    }
+
+    USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        if (Frame == 0)
+        {
+            TtEndpoint->Nums.NumStarts = 1;
+
+            if ((CHAR)TtEndpoint->StartMicroframe < 5)
+            {
+                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);
+    }
+
+    if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+    {
+        DPRINT("USB2_AllocateHS: DIRECTION OUT UNIMPLEMENTED\n");
+        ASSERT(FALSE);
+    }
+    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)
+            {
+                if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+                {
+                    RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
+                                     Tt->TimeCS[frame][uframe];
+                }
+                else
+                {
+                    RemainDataTime = 0;
+                }
+
+                PktSize = TtEndpoint->MaxPacketSize;
+
+                if (RemainDataTime >= USB2_AddDataBitStuff(PktSize))
+                {
+                    DataTime = USB2_AddDataBitStuff(PktSize);
+                }
+                else
+                {
+                    DataTime = RemainDataTime;
+                }
+
+                if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+                                        DataTime,
+                                        USB2_MAX_MICROFRAME_ALLOCATION))
+                {
+                    Result = FALSE;
+                }
+            }
+
+            PktSize = TtEndpoint->MaxPacketSize;
+
+            if (USB2_AddDataBitStuff(PktSize) < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+            {
+                Tt->TimeCS[frame][uframe] += USB2_AddDataBitStuff(PktSize);
+            }
+            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)
+{
+    DPRINT("USB2_DeallocateHS: UNIMPLEMENTED FIXME\n");
+    ASSERT(FALSE);
 }
 
 BOOLEAN
@@ -277,9 +508,354 @@ USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
                              IN PUSB2_REBALANCE Rebalance,
                              IN PULONG RebalanceListEntries)
 {
-    DPRINT("USB2_AllocateTimeForEndpoint: UNIMPLEMENTED. FIXME\n");
-    ASSERT(FALSE);
-    return FALSE;
+    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 prevTtEndpoint;
+    PUSB2_TT_ENDPOINT nextTtEndpoint;
+    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 ((Tt->FrameBudget[ix].TimeUsed) < MinTimeUsed)
+        {
+            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_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;
+    }
+
+    if (Speed == UsbLowSpeed)
+    {
+        TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize * 8 + Overhead;
+    }
+    else
+    {
+        TtEndpoint->CalcBusTime = TtEndpoint->MaxPacketSize + Overhead;
+    }
+
+    LatestStart = USB2_HUB_DELAY + USB2_FS_SOF_TIME;
+
+    for (ix = 0;
+         (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+         ix += TtEndpoint->ActualPeriod)
+    {
+        frame = TtEndpoint->StartFrame + ix;
+
+        if (Tt->FrameBudget[frame].AltEndpoint &&
+            TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+        {
+            DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+            return FALSE;
+        }
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+            prevTtEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
+        else
+            prevTtEndpoint = Tt->FrameBudget[frame].IntEndpoint;
+
+        for (nextTtEndpoint = prevTtEndpoint->NextTtEndpoint;
+             nextTtEndpoint;
+             nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
+        {
+            if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
+            {
+                break;
+            }
+
+            prevTtEndpoint = nextTtEndpoint;
+        }
+
+        StartTime = USB2_GetStartTime(nextTtEndpoint,
+                                      TtEndpoint,
+                                      prevTtEndpoint,
+                                      frame);
+
+        if (StartTime > LatestStart)
+            LatestStart = StartTime;
+    }
+
+    TtEndpoint->StartTime = LatestStart;
+
+    if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
+    {
+        TtEndpoint->CalcBusTime = 0;
+        DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+        return FALSE;
+    }
+
+    for (ix = 0, frame = -TtEndpoint->StartFrame;
+         ix < USB2_FRAMES;
+         ix++, frame++)
+    {
+        DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
+               ix,
+               frame,
+               TtEndpoint->StartFrame);
+
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+        {
+            DPRINT1("USB2_AllocateTimeForEndpoint: Iso Ep UNIMPLEMENTED. FIXME\n");
+            ASSERT(FALSE);
+        }
+        else
+        {
+            IntEndpoint = Tt->FrameBudget[ix].IntEndpoint;
+            nextTtEndpoint = IntEndpoint->NextTtEndpoint;
+
+            for (nextTtEndpoint = IntEndpoint->NextTtEndpoint;
+                 nextTtEndpoint;
+                 nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
+            {
+                if (USB2_CheckTtEndpointInsert(nextTtEndpoint, TtEndpoint))
+                    break;
+                IntEndpoint = nextTtEndpoint;
+            }
+
+            if ((frame % TtEndpoint->ActualPeriod) == 0)
+            {
+                calcBusTime = 0;
+            }
+            else
+            {
+                if (nextTtEndpoint)
+                {
+                    calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
+                                  nextTtEndpoint->StartTime;
+                }
+                else
+                {
+                    calcBusTime = TtEndpoint->CalcBusTime;
+                }
+
+                if (calcBusTime > 0)
+                {
+                    TimeUsed = Tt->FrameBudget[ix].TimeUsed;
+
+                    if (!USB2_AllocateCheck(&TimeUsed,
+                                            calcBusTime,
+                                            USB2_FS_MAX_PERIODIC_ALLOCATION))
+                    {
+                        DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+                        Result = FALSE;
+                    }
+                }
+            }
+
+            if (nextTtEndpoint != TtEndpoint)
+            {
+                if ((frame % TtEndpoint->ActualPeriod) == 0)
+                {
+                    if (frame == 0)
+                    {
+                        DPRINT("USB2_AllocateTimeForEndpoint: frame == 0\n");
+                        TtEndpoint->NextTtEndpoint = nextTtEndpoint;
+                    }
+
+                    IntEndpoint->NextTtEndpoint = TtEndpoint;
+
+                    DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p, nextTtEndpoint - %p\n",
+                           TtEndpoint,
+                           nextTtEndpoint);
+                }
+
+                if (calcBusTime > 0)
+                {
+                    BOOLEAN IsMoved;
+                    BOOLEAN MoveResult;
+
+                    DPRINT("USB2_AllocateTimeForEndpoint: nextTtEndpoint - %p, calcBusTime - %X\n",
+                           nextTtEndpoint,
+                           calcBusTime);
+
+                    for (;
+                         nextTtEndpoint;
+                         nextTtEndpoint = nextTtEndpoint->NextTtEndpoint)
+                    {
+                        MoveResult = USB2_MoveTtEndpoint(nextTtEndpoint,
+                                                         calcBusTime,
+                                                         Rebalance,
+                                                         *RebalanceListEntries,
+                                                         &IsMoved);
+
+                        if (!IsMoved)
+                        {
+                            DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+                            Result = FALSE;
+                        }
+
+                        if (!MoveResult)
+                            break;
+                    }
+                }
+            }
+        }
+
+        if ((frame % TtEndpoint->ActualPeriod) == 0)
+        {
+            if (!USB2_AllocateHS(TtEndpoint, frame))
+            {
+                DPRINT1("USB2_AllocateTimeForEndpoint: USB2_AllocateHS return FALSE\n");
+                Result = FALSE;
+            }
+
+            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_AllocateTimeForEndpoint: Result - %X\n", Result);
+    return Result;
 }
 
 BOOLEAN
@@ -341,13 +917,19 @@ USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
     ULONG RebalanceListEntries;
     PUSB2_TT_ENDPOINT TtEndpoint;
     PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
-
     PUSB2_TT Tt;
     USB_DEVICE_SPEED DeviceSpeed;
     ULONG Period;
-
+    ULONG AllocedBusTime;
+    ULONG EndpointBandwidth;
+    ULONG ScheduleOffset;
+    ULONG Factor;
     ULONG ix;
+    ULONG n;
     BOOLEAN Direction;
+    UCHAR SMask;
+    UCHAR CMask;
+    UCHAR ActualPeriod;
     BOOLEAN Result;
 
     DPRINT("USBPORT_AllocateBandwidthUSB2: FdoDevice - %p, Endpoint - %p\n",
@@ -405,9 +987,10 @@ USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
             case UsbFullSpeed:
             {
                 Tt = &TtExtension->Tt;
+
                 Period = USB2_FRAMES;
 
-                while (Period && Period > EndpointProperties->Period)
+                while (Period > 0 && Period > EndpointProperties->Period)
                 {
                     Period >>= 1;
                 }
@@ -419,18 +1002,22 @@ USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
             case UsbHighSpeed:
             {
                 Tt = &FdoExtension->Usb2Extension->HcTt;
-                Period = EndpointProperties->Period;
 
                 if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
                     Period = USB2_MAX_MICROFRAMES;
+                else
+                    Period = EndpointProperties->Period;
 
                 break;
             }
 
             default:
             {
-                DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n", DeviceSpeed);
+                DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
+                        DeviceSpeed);
+
                 DbgBreakPoint();
+
                 Tt = &TtExtension->Tt;
                 break;
             }
@@ -476,23 +1063,66 @@ USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
 
     for (ix = 0; ix < RebalanceListEntries; ix++)
     {
-        DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceEndpoint[%X] - %X\n",
-               ix,
-               Rebalance->RebalanceEndpoint[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);
     }
 
     if (Rebalance)
-        ExFreePool(Rebalance);
+        ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
 
     if (Result)
     {
-        DPRINT1("USBPORT_AllocateBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
-        ASSERT(FALSE);
+        SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+        EndpointProperties->InterruptScheduleMask = SMask;
+
+        CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+        EndpointProperties->SplitCompletionMask = CMask;
+
+        AllocedBusTime = TtEndpoint->CalcBusTime;
+
+        EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
+        EndpointProperties->UsbBandwidth = EndpointBandwidth;
+
+        ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
+        EndpointProperties->Period = ActualPeriod;
+
+        ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+        EndpointProperties->ScheduleOffset = ScheduleOffset;
+
+        Factor = USB2_FRAMES / ActualPeriod;
+        ASSERT(Factor);
+
+        n = ScheduleOffset * Factor;
+
+        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;
+            }
+        }
+
+        USBPORT_DumpingEndpointProperties(EndpointProperties);
+        USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
+
+        if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+        {
+            DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
+        }
     }
 
     //USB2_Rebalance(FdoDevice, &RebalanceList);