Merge PR #283 "[USBPORT] Transaction Translator (TT) support bringup"
authorColin Finck <colin@reactos.org>
Thu, 29 Mar 2018 21:52:22 +0000 (23:52 +0200)
committerColin Finck <colin@reactos.org>
Thu, 29 Mar 2018 21:52:22 +0000 (23:52 +0200)
12 files changed:
drivers/usb/usbport/debug.c
drivers/usb/usbport/device.c
drivers/usb/usbport/endpoint.c
drivers/usb/usbport/ioctl.c
drivers/usb/usbport/pnp.c
drivers/usb/usbport/power.c
drivers/usb/usbport/trfsplit.c
drivers/usb/usbport/usb2.c
drivers/usb/usbport/usbdebug.h
drivers/usb/usbport/usbport.c
drivers/usb/usbport/usbport.h
sdk/include/psdk/usb200.h

index 67ca9f6..1d2662d 100644 (file)
@@ -12,6 +12,7 @@
 
 #define NDEBUG_USBPORT_MINIPORT
 #define NDEBUG_USBPORT_URB
+//#define NDEBUG_USBPORT_USB2
 #include "usbdebug.h"
 
 ULONG
@@ -275,3 +276,39 @@ USBPORT_DumpingIDs(IN PVOID Buffer)
     DPRINT("\n");
 }
 
+VOID
+NTAPI
+USBPORT_DumpingEndpointProperties(IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties)
+{
+    DPRINT_USB2("DeviceAddress         - %X\n", EndpointProperties->DeviceAddress);
+    DPRINT_USB2("EndpointAddress       - %X\n", EndpointProperties->EndpointAddress);
+    DPRINT_USB2("TotalMaxPacketSize    - %X\n", EndpointProperties->TotalMaxPacketSize);
+    DPRINT_USB2("Period                - %X\n", EndpointProperties->Period);
+    DPRINT_USB2("DeviceSpeed           - %X\n", EndpointProperties->DeviceSpeed);
+    DPRINT_USB2("UsbBandwidth          - %X\n", EndpointProperties->UsbBandwidth);
+    DPRINT_USB2("ScheduleOffset        - %X\n", EndpointProperties->ScheduleOffset);
+    DPRINT_USB2("TransferType          - %X\n", EndpointProperties->TransferType);
+    DPRINT_USB2("MaxTransferSize       - %X\n", EndpointProperties->MaxTransferSize);
+    DPRINT_USB2("HubAddr               - %X\n", EndpointProperties->HubAddr);
+    DPRINT_USB2("PortNumber            - %X\n", EndpointProperties->PortNumber);
+    DPRINT_USB2("InterruptScheduleMask - %X\n", EndpointProperties->InterruptScheduleMask);
+    DPRINT_USB2("SplitCompletionMask   - %X\n", EndpointProperties->SplitCompletionMask);
+    DPRINT_USB2("MaxPacketSize         - %X\n", EndpointProperties->MaxPacketSize);
+}
+
+VOID
+NTAPI
+USBPORT_DumpingTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    DPRINT_USB2("MaxPacketSize   - %X\n", TtEndpoint->MaxPacketSize);
+    DPRINT_USB2("Period          - %X\n", TtEndpoint->Period);
+    DPRINT_USB2("TtEndpointParams- %X\n", TtEndpoint->TtEndpointParams.AsULONG);
+    DPRINT_USB2("CalcBusTime     - %X\n", TtEndpoint->CalcBusTime);
+    DPRINT_USB2("StartTime       - %X\n", TtEndpoint->StartTime);
+    DPRINT_USB2("ActualPeriod    - %X\n", TtEndpoint->ActualPeriod);
+    DPRINT_USB2("StartFrame      - %X\n", TtEndpoint->StartFrame);
+    DPRINT_USB2("StartMicroframe - %X\n", TtEndpoint->StartMicroframe);
+    DPRINT_USB2("Nums            - %X\n", TtEndpoint->Nums.AsULONG);
+    DPRINT_USB2("nextTtEndpoint  - %X\n", TtEndpoint->NextTtEndpoint);
+}
+
index f7180aa..070a6c9 100644 (file)
@@ -885,6 +885,76 @@ USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,
     }
 }
 
+PUSB2_TT_EXTENSION
+NTAPI 
+USBPORT_GetTt(IN PDEVICE_OBJECT FdoDevice,
+              IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
+              OUT PUSHORT OutPort,
+              OUT PUSBPORT_DEVICE_HANDLE * OutHubDeviceHandle)
+{
+    PUSBPORT_DEVICE_HANDLE DeviceHandle = HubDeviceHandle;
+    ULONG TtCount;
+    PLIST_ENTRY Entry;
+    PUSB2_TT_EXTENSION TtExtension = NULL;
+
+    DPRINT("USBPORT_GetTt: HubDeviceHandle - %p\n", HubDeviceHandle);
+
+    *OutHubDeviceHandle = NULL;
+
+    while (DeviceHandle->DeviceSpeed != UsbHighSpeed)
+    {
+        DPRINT("USBPORT_GetTt: DeviceHandle - %p, DeviceHandle->PortNumber - %X\n",
+               DeviceHandle,
+               DeviceHandle->PortNumber);
+
+        *OutPort = DeviceHandle->PortNumber;
+
+        DeviceHandle = DeviceHandle->HubDeviceHandle;
+
+        if (!DeviceHandle)
+            return NULL;
+    }
+
+    TtCount = DeviceHandle->TtCount;
+
+    if (!TtCount)
+        return NULL;
+
+    if (IsListEmpty(&DeviceHandle->TtList))
+        return NULL;
+
+    Entry = DeviceHandle->TtList.Flink;
+
+    if (TtCount > 1)
+    {
+        while (Entry != &DeviceHandle->TtList)
+        {
+            ASSERT(Entry != NULL);
+
+            TtExtension = CONTAINING_RECORD(Entry,
+                                            USB2_TT_EXTENSION,
+                                            Link);
+
+            if (TtExtension->TtNumber == *OutPort)
+                break;
+
+            Entry = Entry->Flink;
+
+            TtExtension = NULL;
+        }
+    }
+    else
+    {
+        TtExtension = CONTAINING_RECORD(Entry,
+                                        USB2_TT_EXTENSION,
+                                        Link);
+    }
+
+    *OutHubDeviceHandle = DeviceHandle;
+
+    return TtExtension;
+}
+
 NTSTATUS
 NTAPI
 USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
@@ -893,6 +963,9 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
                      IN USHORT PortStatus,
                      IN USHORT Port)
 {
+    PUSBPORT_DEVICE_HANDLE TtDeviceHandle = NULL;
+    PUSB2_TT_EXTENSION TtExtension = NULL;
+    USHORT port;
     PUSBPORT_DEVICE_HANDLE DeviceHandle;
     PUSBPORT_PIPE_HANDLE PipeHandle;
     BOOL IsOpenedPipe;
@@ -902,7 +975,7 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
     SIZE_T DescriptorMinSize;
     UCHAR MaxPacketSize;
     PUSBPORT_DEVICE_EXTENSION FdoExtension;
-
+    PUSBPORT_REGISTRATION_PACKET Packet;
     NTSTATUS Status;
 
     DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
@@ -910,6 +983,7 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
            Port);
 
     FdoExtension = FdoDevice->DeviceExtension;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
 
     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
                           Executive,
@@ -928,11 +1002,21 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
         return STATUS_DEVICE_NOT_CONNECTED;
     }
 
-    if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
+    port = Port;
+
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
         !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
     {
-        DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port. FIXME: Transaction Translator.\n");
-        DbgBreakPoint();
+        DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port\n");
+
+        TtExtension = USBPORT_GetTt(FdoDevice,
+                                    HubDeviceHandle,
+                                    &port,
+                                    &TtDeviceHandle);
+
+        DPRINT("USBPORT_CreateDevice: TtDeviceHandle - %p, port - %x\n",
+               TtDeviceHandle,
+               port);
     }
 
     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
@@ -954,6 +1038,7 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
 
     *pUsbdDeviceHandle = NULL;
 
+    DeviceHandle->TtExtension = TtExtension;
     DeviceHandle->PortNumber = Port;
     DeviceHandle->HubDeviceHandle = HubDeviceHandle;
 
@@ -993,6 +1078,7 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
     }
 
     InitializeListHead(&DeviceHandle->PipeHandleList);
+    InitializeListHead(&DeviceHandle->TtList);
 
     Status = USBPORT_OpenPipe(FdoDevice,
                               DeviceHandle,
@@ -1089,7 +1175,36 @@ USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
 
 ErrorExit:
 
-    // FIXME: if Transaction Translator
+    if (TtExtension && TtDeviceHandle)
+    {
+        SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_OTHER;
+        SetupPacket.bmRequestType.Reserved = 0;
+        SetupPacket.bmRequestType.Type = BMREQUEST_CLASS;
+        SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
+
+        /* Table 11-15.  Hub Class Requests */
+        if (TtDeviceHandle == HubDeviceHandle)
+        {
+            SetupPacket.bRequest = USB_REQUEST_RESET_TT;
+        }
+        else
+        {
+            SetupPacket.bRequest = USB_REQUEST_CLEAR_TT_BUFFER;
+        }
+
+        SetupPacket.wValue.LowByte = 0;
+        SetupPacket.wValue.HiByte = 0;
+        SetupPacket.wIndex.W = port;
+        SetupPacket.wLength = 0;
+
+        USBPORT_SendSetupPacket(TtDeviceHandle,
+                                FdoDevice,
+                                &SetupPacket,
+                                NULL,
+                                0,
+                                NULL,
+                                NULL);
+    }
 
     Status = STATUS_DEVICE_DATA_ERROR;
 
@@ -1262,6 +1377,12 @@ USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
                (MaxPacketSize == 16) ||
                (MaxPacketSize == 32) ||
                (MaxPacketSize == 64));
+
+        if (DeviceHandle->DeviceSpeed == UsbHighSpeed &&
+            DeviceHandle->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_HUB)
+        {
+            DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_USB2HUB;
+        }
     }
     else
     {
@@ -1443,6 +1564,9 @@ USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
                      IN ULONG Flags)
 {
     PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSB2_TT_EXTENSION TtExtension;
+    ULONG ix;
+    KIRQL OldIrql;
 
     DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
            DeviceHandle,
@@ -1502,6 +1626,41 @@ USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
         USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
     }
 
+    if (!IsListEmpty(&DeviceHandle->TtList))
+    {
+        DPRINT1("USBPORT_RemoveDevice: DeviceHandle->TtList not empty\n");
+    }
+
+    while (!IsListEmpty(&DeviceHandle->TtList))
+    {
+        TtExtension = CONTAINING_RECORD(DeviceHandle->TtList.Flink,
+                                        USB2_TT_EXTENSION,
+                                        Link);
+
+        RemoveHeadList(&DeviceHandle->TtList);
+
+        DPRINT("USBPORT_RemoveDevice: TtExtension - %p\n", TtExtension);
+
+        KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
+
+        TtExtension->Flags |= USB2_TT_EXTENSION_FLAG_DELETED;
+
+        if (IsListEmpty(&TtExtension->EndpointList))
+        {
+            USBPORT_UpdateAllocatedBwTt(TtExtension);
+
+            for (ix = 0; ix < USB2_FRAMES; ix++)
+            {
+                FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
+            }
+
+            DPRINT("USBPORT_RemoveDevice: ExFreePoolWithTag TtExtension - %p\n", TtExtension);
+            ExFreePoolWithTag(TtExtension, USB_PORT_TAG);
+        }
+
+        KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
+    }
+
     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
                        LOW_REALTIME_PRIORITY,
                        1,
@@ -1646,10 +1805,14 @@ USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
             }
         }
 
-        if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_INITIALIZED)
+        if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_USB2HUB)
         {
             DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
             NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
+
+#ifndef NDEBUG
+            DbgBreakPoint();
+#endif
         }
 
         while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
@@ -1770,7 +1933,55 @@ USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
                      IN ULONG TtNumber)
 {
-    DPRINT1("USBPORT_InitializeTT: UNIMPLEMENTED. FIXME. \n");
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSB2_TT_EXTENSION TtExtension;
+    ULONG ix;
+
+    DPRINT("USBPORT_InitializeTT: HubDeviceHandle - %p, TtNumber - %X\n",
+           HubDeviceHandle,
+           TtNumber);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    TtExtension = ExAllocatePoolWithTag(NonPagedPool,
+                                        sizeof(USB2_TT_EXTENSION),
+                                        USB_PORT_TAG);
+
+    if (!TtExtension)
+    {
+        DPRINT1("USBPORT_InitializeTT: ExAllocatePoolWithTag return NULL\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    DPRINT("USBPORT_InitializeTT: TtExtension - %p\n", TtExtension);
+
+    RtlZeroMemory(TtExtension, sizeof(USB2_TT_EXTENSION));
+
+    TtExtension->DeviceAddress = HubDeviceHandle->DeviceAddress;
+    TtExtension->TtNumber = TtNumber;
+    TtExtension->RootHubPdo = FdoExtension->RootHubPdo;
+    TtExtension->BusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
+
+    InitializeListHead(&TtExtension->EndpointList);
+
+    /* 90% maximum allowed for periodic endpoints */
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        TtExtension->Bandwidth[ix] = TtExtension->BusBandwidth -
+                                     TtExtension->BusBandwidth / 10;
+    }
+
+    USBPORT_UpdateAllocatedBwTt(TtExtension);
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
+    }
+
+    USB2_InitTT(FdoExtension->Usb2Extension, &TtExtension->Tt);
+
+    InsertTailList(&HubDeviceHandle->TtList, &TtExtension->Link);
+
     return STATUS_SUCCESS;
 }
 
@@ -1783,7 +1994,7 @@ USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
     NTSTATUS Status;
     ULONG ix;
 
-    DPRINT("USBPORT_Initialize20Hub \n");
+    DPRINT("USBPORT_Initialize20Hub: TtCount - %X\n", TtCount);
 
     if (!HubDeviceHandle)
     {
index 7cf250e..0386bd0 100644 (file)
@@ -20,7 +20,7 @@ USBPORT_CalculateUsbBandwidth(IN PDEVICE_OBJECT FdoDevice,
 {
     PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
     ULONG Bandwidth;
-    ULONG Additional;
+    ULONG Overhead;
 
     DPRINT("USBPORT_CalculateUsbBandwidth ... \n");
 
@@ -29,25 +29,25 @@ USBPORT_CalculateUsbBandwidth(IN PDEVICE_OBJECT FdoDevice,
     switch (EndpointProperties->TransferType)
     {
         case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
-            Additional = 9;
+            Overhead = USB2_FS_ISOCHRONOUS_OVERHEAD;
             break;
 
         case USBPORT_TRANSFER_TYPE_INTERRUPT:
-            Additional = 13;
+            Overhead = USB2_FS_INTERRUPT_OVERHEAD;
             break;
 
         default: //USBPORT_TRANSFER_TYPE_CONTROL or USBPORT_TRANSFER_TYPE_BULK
-            Additional = 0;
+            Overhead = 0;
             break;
     }
 
-    if (Additional == 0)
+    if (Overhead == 0)
     {
         Bandwidth = 0;
     }
     else
     {
-        Bandwidth = (EndpointProperties->TotalMaxPacketSize + Additional) * 8 * 7 / 6;
+        Bandwidth = (EndpointProperties->TotalMaxPacketSize + Overhead) * USB2_BIT_STUFFING_OVERHEAD;
     }
 
     if (EndpointProperties->DeviceSpeed == UsbLowSpeed)
@@ -68,9 +68,19 @@ USBPORT_AllocateBandwidth(IN PDEVICE_OBJECT FdoDevice,
     ULONG TransferType;
     ULONG TotalBusBandwidth;
     ULONG EndpointBandwidth;
+    ULONG MinBandwidth;
+    PULONG Bandwidth;
+    ULONG MaxBandwidth = 0;
+    ULONG ix;
+    ULONG Offset;
+    LONG ScheduleOffset = -1;
     ULONG Period;
+    ULONG Factor;
+    UCHAR Bit;
 
-    DPRINT("USBPORT_AllocateBandwidth: ... \n");
+    DPRINT("USBPORT_AllocateBandwidth: FdoDevice - %p, Endpoint - %p\n",
+           FdoDevice,
+           Endpoint);
 
     FdoExtension = FdoDevice->DeviceExtension;
     EndpointProperties = &Endpoint->EndpointProperties;
@@ -86,17 +96,74 @@ USBPORT_AllocateBandwidth(IN PDEVICE_OBJECT FdoDevice,
 
     TotalBusBandwidth = FdoExtension->TotalBusBandwidth;
     EndpointBandwidth = EndpointProperties->UsbBandwidth;
+
     Period = EndpointProperties->Period;
+    ASSERT(Period != 0);
+    Factor = USB2_FRAMES / Period;
 
-    DPRINT1("USBPORT_AllocateBandwidth: FIXME. \n");
-    DPRINT1("USBPORT_AllocateBandwidth: Endpoint - %p, Type - %x, TotalBandwidth - %x, EpBandwidth - %x, Period - %x\n",
-           Endpoint,
-           TransferType,
-           TotalBusBandwidth,
-           EndpointBandwidth,
-           Period);
+    for (Offset = 0; Offset < Period; Offset++)
+    {
+        MinBandwidth = TotalBusBandwidth;
+        Bandwidth = &FdoExtension->Bandwidth[Offset * Factor];
+
+        for (ix = 1; *Bandwidth >= EndpointBandwidth; ix++)
+        {
+            MinBandwidth = min(MinBandwidth, *Bandwidth); 
+
+            Bandwidth++;
+
+            if (Factor <= ix)
+            {
+                if (MinBandwidth > MaxBandwidth)
+                {
+                    MaxBandwidth = MinBandwidth;
+                    ScheduleOffset = Offset;
+
+                    DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n",
+                           ScheduleOffset);
+                }
+
+                break;
+            }
+        }
+    }
+
+    DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n", ScheduleOffset);
+
+    if (ScheduleOffset != -1)
+    {
+        EndpointProperties->ScheduleOffset = ScheduleOffset;
+
+        Bandwidth = &FdoExtension->Bandwidth[ScheduleOffset * Factor];
+
+        for (Factor = USB2_FRAMES / Period; Factor; Factor--)
+        {
+            FdoExtension->Bandwidth[ScheduleOffset * Factor] -= EndpointBandwidth;
+        }
 
-    return TRUE;
+        if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+        {
+            for (Bit = 0x80; Bit != 0; Bit >>= 1)
+            {
+                if ((Period & Bit) != 0)
+                {
+                    Period = Bit;
+                    break;
+                }
+            }
+
+            DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedInterrupt_XXms\n");
+        }
+        else
+        {
+            DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedIso\n");
+        }
+    }
+
+    DPRINT("USBPORT_AllocateBandwidth: FIXME USBPORT_UpdateAllocatedBw\n");
+
+    DPRINT("USBPORT_AllocateBandwidth: ScheduleOffset - %X\n", ScheduleOffset);
+    return ScheduleOffset != -1;
 }
 
 VOID
@@ -104,7 +171,63 @@ NTAPI
 USBPORT_FreeBandwidth(IN PDEVICE_OBJECT FdoDevice,
                       IN PUSBPORT_ENDPOINT Endpoint)
 {
-    DPRINT1("USBPORT_FreeBandwidth: UNIMPLEMENTED. FIXME. \n");
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    ULONG TransferType;
+    ULONG Offset;
+    ULONG EndpointBandwidth;
+    ULONG Period;
+    ULONG Factor;
+    UCHAR Bit;
+
+    DPRINT("USBPORT_FreeBandwidth: FdoDevice - %p, Endpoint - %p\n",
+           FdoDevice,
+           Endpoint);
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    EndpointProperties = &Endpoint->EndpointProperties;
+    TransferType = EndpointProperties->TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+        TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+        (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+    {
+        return;
+    }
+
+    Offset = Endpoint->EndpointProperties.ScheduleOffset;
+    EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
+
+    Period = Endpoint->EndpointProperties.Period;
+    ASSERT(Period != 0);
+
+    for (Factor = USB2_FRAMES / Period; Factor; Factor--)
+    {
+        FdoExtension->Bandwidth[Offset * Factor] += EndpointBandwidth;
+    }
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        for (Bit = 0x80; Bit != 0; Bit >>= 1)
+        {
+            if ((Period & Bit) != 0)
+            {
+                Period = Bit;
+                break;
+            }
+        }
+
+        ASSERT(Period != 0);
+
+        DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedInterrupt_XXms\n");
+    }
+    else
+    {
+        DPRINT("USBPORT_AllocateBandwidth: FIXME AllocatedIso\n");
+    }
+
+    DPRINT1("USBPORT_FreeBandwidth: FIXME USBPORT_UpdateAllocatedBw\n");
 }
 
 UCHAR
@@ -379,7 +502,7 @@ USBPORT_DeleteEndpoint(IN PDEVICE_OBJECT FdoDevice,
     BOOLEAN Result;
     KIRQL OldIrql;
 
-    DPRINT("USBPORT_DeleteEndpoint: Endpoint - %p\n", Endpoint);
+    DPRINT1("USBPORT_DeleteEndpoint: Endpoint - %p\n", Endpoint);
 
     FdoExtension = FdoDevice->DeviceExtension;
 
@@ -471,10 +594,13 @@ USBPORT_ClosePipe(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
     PUSBPORT_DEVICE_EXTENSION FdoExtension;
     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
     PUSBPORT_ENDPOINT Endpoint;
+    PUSBPORT_REGISTRATION_PACKET Packet;
+    PUSB2_TT_EXTENSION TtExtension;
+    ULONG ix;
     BOOLEAN IsReady;
     KIRQL OldIrql;
 
-    DPRINT("USBPORT_ClosePipe \n");
+    DPRINT1("USBPORT_ClosePipe \n");
 
     FdoExtension = FdoDevice->DeviceExtension;
 
@@ -492,7 +618,6 @@ USBPORT_ClosePipe(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
     }
 
     Endpoint = PipeHandle->Endpoint;
-    DPRINT("USBPORT_ClosePipe: Endpoint - %p\n", Endpoint);
 
     KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
 
@@ -543,16 +668,46 @@ USBPORT_ClosePipe(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
     }
 
     Endpoint->DeviceHandle = NULL;
+    Packet = &FdoExtension->MiniPortInterface->Packet;
 
-    if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
     {
-        DPRINT("USBPORT_ClosePipe: FIXME USBPORT_FreeBandwidthUSB20\n");
-        //USBPORT_FreeBandwidthUSB20();
+        USBPORT_FreeBandwidthUSB2(FdoDevice, Endpoint);
+
+        KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
+
+        TtExtension = Endpoint->TtExtension;
+        DPRINT1("USBPORT_ClosePipe: TtExtension - %p\n", TtExtension);
+
+        if (TtExtension)
+        {
+            RemoveEntryList(&Endpoint->TtLink);
+
+            Endpoint->TtLink.Flink = NULL;
+            Endpoint->TtLink.Blink = NULL;
+
+            if (TtExtension->Flags & USB2_TT_EXTENSION_FLAG_DELETED)
+            {
+                if (IsListEmpty(&TtExtension->EndpointList))
+                {
+                    USBPORT_UpdateAllocatedBwTt(TtExtension);
+
+                    for (ix = 0; ix < USB2_FRAMES; ix++)
+                    {
+                        FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
+                    }
+
+                    DPRINT1("USBPORT_ClosePipe: ExFreePoolWithTag TtExtension - %p\n", TtExtension);
+                    ExFreePoolWithTag(TtExtension, USB_PORT_TAG);
+                }
+            }
+        }
+
+        KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
     }
     else
     {
-        DPRINT("USBPORT_ClosePipe: FIXME USBPORT_FreeBandwidthUSB11\n");
-        //USBPORT_FreeBandwidthUSB11();
+        USBPORT_FreeBandwidth(FdoDevice, Endpoint);
     }
 
     KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
@@ -630,7 +785,7 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
     USHORT AdditionalTransaction;
     BOOLEAN IsAllocatedBandwidth;
 
-    DPRINT("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n",
+    DPRINT1("USBPORT_OpenPipe: DeviceHandle - %p, FdoDevice - %p, PipeHandle - %p\n",
            DeviceHandle,
            FdoDevice,
            PipeHandle);
@@ -642,13 +797,13 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
 
     if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
     {
-        DPRINT1("USBPORT_OpenPipe: FIXME USB2 EndpointSize\n");
+        EndpointSize += sizeof(USB2_TT_ENDPOINT);
     }
 
     if (PipeHandle->EndpointDescriptor.wMaxPacketSize == 0)
     {
         USBPORT_AddPipeHandle(DeviceHandle, PipeHandle);
-  
+
         PipeHandle->Flags = (PipeHandle->Flags & ~PIPE_HANDLE_FLAG_CLOSED) |
                              PIPE_HANDLE_FLAG_NULL_PACKET_SIZE;
 
@@ -672,6 +827,26 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
     Endpoint->DeviceHandle = DeviceHandle;
     Endpoint->LockCounter = -1;
 
+    Endpoint->TtExtension = DeviceHandle->TtExtension;
+
+    if (DeviceHandle->TtExtension)
+    {
+        ExInterlockedInsertTailList(&DeviceHandle->TtExtension->EndpointList,
+                                    &Endpoint->TtLink,
+                                    &FdoExtension->TtSpinLock);
+    }
+
+    if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        Endpoint->TtEndpoint = (PUSB2_TT_ENDPOINT)((ULONG_PTR)Endpoint +
+                                                   sizeof(USBPORT_ENDPOINT) +
+                                                   Packet->MiniPortEndpointSize);
+    }
+    else
+    {
+        Endpoint->TtEndpoint = NULL;
+    }
+
     KeInitializeSpinLock(&Endpoint->EndpointSpinLock);
     KeInitializeSpinLock(&Endpoint->StateChangeSpinLock);
 
@@ -695,6 +870,17 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
     EndpointProperties->TotalMaxPacketSize = MaxPacketSize *
                                              (AdditionalTransaction + 1);
 
+    if (Endpoint->TtExtension)
+    {
+        EndpointProperties->HubAddr = Endpoint->TtExtension->DeviceAddress;
+    }
+    else
+    {
+        EndpointProperties->HubAddr = -1;
+    }
+
+    EndpointProperties->PortNumber = DeviceHandle->PortNumber;
+
     switch (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
     {
         case USB_ENDPOINT_TYPE_CONTROL:
@@ -739,14 +925,14 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
             Interval = EndpointDescriptor->bInterval;
         }
 
-        EndpointProperties->Period = 32;
+        EndpointProperties->Period = ENDPOINT_INTERRUPT_32ms;
 
-        if (Interval && (Interval < 32))
+        if (Interval && (Interval < USB2_FRAMES))
         {
             if ((EndpointProperties->DeviceSpeed != UsbLowSpeed) ||
-                (Interval >= 8))
+                (Interval >= ENDPOINT_INTERRUPT_8ms))
             {
-                if (!(Interval & 0x20))
+                if (!(Interval & ENDPOINT_INTERRUPT_32ms))
                 {
                     Period = EndpointProperties->Period;
 
@@ -761,7 +947,7 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
             }
             else
             {
-                EndpointProperties->Period = 8;
+                EndpointProperties->Period = ENDPOINT_INTERRUPT_8ms;
             }
         }
     }
@@ -770,15 +956,20 @@ USBPORT_OpenPipe(IN PDEVICE_OBJECT FdoDevice,
     {
         if (EndpointProperties->DeviceSpeed == UsbHighSpeed)
         {
-            EndpointProperties->Period = 
+            EndpointProperties->Period =
                 USBPORT_NormalizeHsInterval(EndpointDescriptor->bInterval);
         }
         else
         {
-            EndpointProperties->Period = 1;
+            EndpointProperties->Period = ENDPOINT_INTERRUPT_1ms;
         }
     }
 
+    if ((DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB) != 0)
+    {
+        Endpoint->Flags |= ENDPOINT_FLAG_ROOTHUB_EP0;
+    }
+
     if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
     {
         IsAllocatedBandwidth = USBPORT_AllocateBandwidthUSB2(FdoDevice, Endpoint);
@@ -955,6 +1146,13 @@ ExitWithError:
             }
         }
 
+        if (Endpoint->TtExtension)
+        {
+            KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
+            RemoveEntryList(&Endpoint->TtLink);
+            KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
+        }
+
         ExFreePoolWithTag(Endpoint, USB_PORT_TAG);
     }
 
@@ -974,7 +1172,7 @@ USBPORT_ReopenPipe(IN PDEVICE_OBJECT FdoDevice,
     KIRQL MiniportOldIrql;
     NTSTATUS Status;
 
-    DPRINT("USBPORT_ReopenPipe ... \n");
+    DPRINT1("USBPORT_ReopenPipe ... \n");
 
     FdoExtension = FdoDevice->DeviceExtension;
     Packet = &FdoExtension->MiniPortInterface->Packet;
@@ -1081,7 +1279,7 @@ USBPORT_FlushClosedEndpointList(IN PDEVICE_OBJECT FdoDevice)
     PLIST_ENTRY ClosedList;
     PUSBPORT_ENDPOINT Endpoint;
 
-    DPRINT("USBPORT_FlushClosedEndpointList: ... \n");
+    DPRINT_CORE("USBPORT_FlushClosedEndpointList: ... \n");
 
     FdoExtension = FdoDevice->DeviceExtension;
 
index 7322958..7e29d3d 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "usbport.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 VOID
@@ -326,10 +326,10 @@ USBPORT_PdoInternalDeviceControl(IN PDEVICE_OBJECT PdoDevice,
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     IoCtl = IoStack->Parameters.DeviceIoControl.IoControlCode;
 
-    DPRINT("USBPORT_PdoInternalDeviceControl: PdoDevice - %p, Irp - %p, IoCtl - %x\n",
-           PdoDevice,
-           Irp,
-           IoCtl);
+    //DPRINT("USBPORT_PdoInternalDeviceControl: PdoDevice - %p, Irp - %p, IoCtl - %x\n",
+    //       PdoDevice,
+    //       Irp,
+    //       IoCtl);
 
     if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_URB)
     {
index e7ec311..7b0c5dd 100644 (file)
@@ -519,6 +519,7 @@ USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
     BOOLEAN IsCompanion = FALSE;
     ULONG LegacyBIOS;
     ULONG MiniportFlags;
+    ULONG ix;
 
     DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
            FdoDevice,
@@ -610,6 +611,7 @@ USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
     KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
     KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
     KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
+    KeInitializeSpinLock(&FdoExtension->TtSpinLock);
 
     KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
 
@@ -754,6 +756,12 @@ USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
         FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
     }
 
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        FdoExtension->Bandwidth[ix] = FdoExtension->TotalBusBandwidth -
+                                      FdoExtension->TotalBusBandwidth / 10;
+    }
+
     FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
                                                          sizeof(USBPORT_IRP_TABLE),
                                                          USB_PORT_TAG);
index 56f150d..0dca453 100644 (file)
@@ -105,8 +105,6 @@ USBPORT_DoSetPowerD0(IN PDEVICE_OBJECT FdoDevice)
 {
     DPRINT("USBPORT_DoSetPowerD0: FIXME!\n");
     return;
-    DbgBreakPoint();
-    //ASSERT(FALSE);
 }
 
 VOID
index 1964e8d..bc1efe3 100644 (file)
@@ -148,8 +148,8 @@ USBPORT_SplitBulkInterruptTransfer(IN PDEVICE_OBJECT FdoDevice,
 
     InitializeListHead(&tmplist);
 
-    DPRINT1("USBPORT_SplitBulkInterruptTransfer: TransferBufferLength - %x, NeedSplits - %x\n",
-            TransferBufferLength, NeedSplits);
+    DPRINT("USBPORT_SplitBulkInterruptTransfer: TransferBufferLength - %x, NeedSplits - %x\n",
+           TransferBufferLength, NeedSplits);
 
     if (!NeedSplits)
     {
@@ -214,7 +214,7 @@ Exit:
 
     while (!IsListEmpty(&tmplist))
     {
-        DPRINT1("USBPORT_SplitBulkInterruptTransfer: ... \n");
+        DPRINT("USBPORT_SplitBulkInterruptTransfer: ... \n");
 
         SplitTransfer = CONTAINING_RECORD(tmplist.Flink,
                                           USBPORT_TRANSFER,
index 920d01a..be13000 100644 (file)
 
 #include "usbport.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
+static const UCHAR CMASKS[USB2_MICROFRAMES] = {
+  0x1C, 0x38, 0x70, 0xE0, 0xC1, 0x83, 0x07, 0x0E 
+};
+
+BOOLEAN
+NTAPI
+USB2_AllocateCheck(IN OUT PULONG OutTimeUsed,
+                   IN ULONG CalcBusTime,
+                   IN ULONG LimitAllocation)
+{
+    ULONG BusTime;
+    BOOLEAN Result = TRUE;
+
+    BusTime = *OutTimeUsed + CalcBusTime;
+    *OutTimeUsed += CalcBusTime;
+
+    if (BusTime > LimitAllocation)
+    {
+        DPRINT("USB2_AllocateCheck: BusTime > LimitAllocation\n");
+        Result = FALSE;
+    }
+
+    return Result;
+}
+
+USHORT
+NTAPI
+USB2_AddDataBitStuff(IN USHORT DataTime)
+{
+    return (DataTime + (DataTime / 16));
+}
+
+VOID
+NTAPI
+USB2_IncMicroFrame(OUT PUCHAR frame,
+                   OUT PUCHAR uframe)
+{
+    ++*uframe;
+
+    if (*uframe > (USB2_MICROFRAMES - 1))
+    {
+        *uframe = 0;
+        *frame = (*frame + 1) & (USB2_FRAMES - 1);
+    }
+}
+
+VOID
+NTAPI
+USB2_GetPrevMicroFrame(OUT PUCHAR frame,
+                       OUT PUCHAR uframe)
+{
+    *uframe = USB2_MICROFRAMES - 1;
+
+    if (*frame)
+        --*frame;
+    else
+        *frame = USB2_FRAMES - 1;
+}
+
+BOOLEAN
+NTAPI
+USB2_CheckTtEndpointInsert(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
+                           IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    ULONG TransferType;
+
+    DPRINT("USB2_CheckTtEndpointInsert: nextTtEndpoint - %p, TtEndpoint - %p\n",
+           nextTtEndpoint,
+           TtEndpoint);
+
+    ASSERT(TtEndpoint);
+
+    if (TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+    {
+        DPRINT1("USB2_CheckTtEndpointInsert: Result - FALSE\n");
+        return FALSE;
+    }
+
+    if (!nextTtEndpoint)
+    {
+        DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
+        return TRUE;
+    }
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    if (nextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod &&
+        TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+    {
+        DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
+        return TRUE;
+    }
+
+    if ((nextTtEndpoint->ActualPeriod <= TtEndpoint->ActualPeriod &&
+        TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS) ||
+        nextTtEndpoint == TtEndpoint)
+    {
+        DPRINT("USB2_CheckTtEndpointInsert: Result - TRUE\n");
+        return TRUE;
+    }
+
+    DPRINT("USB2_CheckTtEndpointInsert: Result - FALSE\n");
+    return FALSE;
+}
+
+ULONG
+NTAPI
+USB2_GetOverhead(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+    ULONG TransferType;
+    ULONG Direction;
+    ULONG DeviceSpeed;
+    ULONG Overhead;
+    ULONG HostDelay;
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+    Direction = TtEndpoint->TtEndpointParams.Direction;
+    DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+
+    HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
+
+    if (DeviceSpeed == UsbHighSpeed)
+    {
+        if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+        {
+            if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+                Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
+            else
+                Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
+        }
+        else
+        {
+            if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+                Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
+            else
+                Overhead = HostDelay + USB2_HS_INTERRUPT_IN_OVERHEAD;
+        }
+    }
+    else if (DeviceSpeed == UsbFullSpeed)
+    {
+        if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+            Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
+        else
+            Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
+    }
+    else
+    {
+        Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
+    }
+
+    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;
+        }
+    }
+}
+
+ULONG
+NTAPI
+USB2_GetLastIsoTime(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                    IN ULONG Frame)
+{
+    PUSB2_TT_ENDPOINT nextTtEndpoint;
+    ULONG Result;
+
+    //DPRINT("USB2_GetLastIsoTime: TtEndpoint - %p, Frame - %X\n",
+    //       TtEndpoint,
+    //       Frame);
+
+    nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].IsoEndpoint->NextTtEndpoint;
+
+    if (nextTtEndpoint ||
+        (nextTtEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint) != NULL)
+    {
+        Result = nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
+    }
+    else
+    {
+        Result = USB2_FS_SOF_TIME;
+    }
+
+    return Result;
+}
+
+ULONG
+NTAPI
+USB2_GetStartTime(IN PUSB2_TT_ENDPOINT nextTtEndpoint,
+                  IN PUSB2_TT_ENDPOINT TtEndpoint,
+                  IN PUSB2_TT_ENDPOINT prevTtEndpoint,
+                  IN ULONG Frame)
+{
+    PUSB2_TT_ENDPOINT ttEndpoint;
+    ULONG TransferType;
+
+    DPRINT("USB2_GetStartTime: nextTtEndpoint - %p, TtEndpoint - %p, prevTtEndpoint - %p, Frame - %X\n",
+           nextTtEndpoint,
+           TtEndpoint,
+           prevTtEndpoint,
+           Frame);
+
+    TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
+    {
+        if (nextTtEndpoint)
+            return nextTtEndpoint->StartTime + nextTtEndpoint->CalcBusTime;
+
+        ttEndpoint = TtEndpoint->Tt->FrameBudget[Frame].AltEndpoint;
+
+        if (ttEndpoint)
+            return ttEndpoint->StartTime + ttEndpoint->CalcBusTime;
+        else
+            return USB2_FS_SOF_TIME;
+    }
+    else
+    {
+        ttEndpoint = prevTtEndpoint;
+
+        if (ttEndpoint == TtEndpoint->Tt->FrameBudget[Frame].IntEndpoint)
+            return USB2_GetLastIsoTime(TtEndpoint, Frame);
+        else
+            return ttEndpoint->StartTime + ttEndpoint->CalcBusTime;
+    }
+}
+
+VOID
+NTAPI
+USB2_InitTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                    IN UCHAR TransferType,
+                    IN UCHAR Direction,
+                    IN UCHAR DeviceSpeed,
+                    IN USHORT Period,
+                    IN USHORT MaxPacketSize,
+                    IN PUSB2_TT Tt)
+{
+    TtEndpoint->TtEndpointParams.TransferType = TransferType;
+    TtEndpoint->TtEndpointParams.Direction = Direction;
+    TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
+
+    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 LONG Frame)
+{
+    PUSB2_HC_EXTENSION HcExtension;
+    PUSB2_TT Tt;
+    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, 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 < (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 == USB2_PREV_MICROFRAME)
+        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 == USB2_PREV_MICROFRAME)
+            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 == USB2_PREV_MICROFRAME)
+        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 == USB2_PREV_MICROFRAME)
+            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
+                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 == USB2_PREV_MICROFRAME)
+    {
+        *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;
+
+    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)
+        {
+            ASSERT(Endpoint->EndpointProperties.Period);
+            Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
+
+            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;
+
+            ASSERT(NewPeriod);
+            Factor = USB2_FRAMES / NewPeriod;
+
+            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;
+                }
+                else if (Tt->FrameBudget[frame].AltEndpoint)
+                {
+                    endpoint = Tt->FrameBudget[frame].AltEndpoint;
+                }
+            }
+        }
+        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 ((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)
+            prevEndpoint = Tt->FrameBudget[frame].IsoEndpoint;
+        else
+            prevEndpoint = Tt->FrameBudget[frame].IntEndpoint;
+
+        for (nextEndpoint = prevEndpoint->NextTtEndpoint;
+             nextEndpoint;
+             nextEndpoint = nextEndpoint->NextTtEndpoint)
+        {
+            if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+                break;
+
+            prevEndpoint = nextEndpoint;
+        }
+
+        StartTime = USB2_GetStartTime(nextEndpoint,
+                                      TtEndpoint,
+                                      prevEndpoint,
+                                      frame);
+
+        LatestStart = max(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;
+            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 (nextEndpoint)
+                {
+                    calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
+                                  nextEndpoint->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 (nextEndpoint != TtEndpoint)
+            {
+                if ((frame % TtEndpoint->ActualPeriod) == 0)
+                {
+                    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 (calcBusTime > 0)
+                {
+                    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;
+                    }
+                }
+            }
+        }
+
+        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
+NTAPI
+USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                  IN PUSB2_REBALANCE Rebalance,
+                  IN PULONG RebalanceListEntries)
+{
+    BOOLEAN Result;
+
+    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
+NTAPI
+USB2_PromotePeriods(IN PUSB2_TT_ENDPOINT TtEndpoint,
+                    IN PUSB2_REBALANCE Rebalance,
+                    IN PULONG RebalanceListEntries)
+{
+    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 &&
+            (CHAR)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;
+}
+
+VOID
+NTAPI
+USBPORT_UpdateAllocatedBwTt(IN PUSB2_TT_EXTENSION TtExtension)
+{
+    ULONG BusBandwidth;
+    ULONG NewBusBandwidth;
+    ULONG MaxBusBandwidth = 0;
+    ULONG MinBusBandwidth;
+    ULONG ix;
+
+    DPRINT("USBPORT_UpdateAllocatedBwTt: TtExtension - %p\n", TtExtension);
+
+    BusBandwidth = TtExtension->BusBandwidth;
+    MinBusBandwidth = BusBandwidth;
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        NewBusBandwidth = BusBandwidth - TtExtension->Bandwidth[ix];
+
+        MaxBusBandwidth = max(MaxBusBandwidth, NewBusBandwidth);
+        MinBusBandwidth = min(MinBusBandwidth, NewBusBandwidth);
+    }
+
+    TtExtension->MaxBandwidth = MaxBusBandwidth;
+
+    if (MinBusBandwidth == BusBandwidth)
+        TtExtension->MinBandwidth = 0;
+    else
+        TtExtension->MinBandwidth = MinBusBandwidth;
+}
+
 BOOLEAN
 NTAPI
 USBPORT_AllocateBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
                               IN PUSBPORT_ENDPOINT Endpoint)
 {
-    DPRINT1("USBPORT_AllocateBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
-    return TRUE;
+    PUSBPORT_DEVICE_EXTENSION FdoExtension;
+    PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+    PUSB2_TT_EXTENSION TtExtension;
+    ULONG TransferType;
+    PUSB2_REBALANCE Rebalance;
+    LIST_ENTRY RebalanceList;
+    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",
+           FdoDevice,
+           Endpoint);
+
+    EndpointProperties = &Endpoint->EndpointProperties;
+    EndpointProperties->ScheduleOffset = 0;
+
+    if (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
+    {
+        DPRINT("USBPORT_AllocateBandwidthUSB2: ENDPOINT_FLAG_ROOTHUB_EP0\n");
+        return TRUE;
+    }
+
+    FdoExtension = FdoDevice->DeviceExtension;
+
+    TransferType = EndpointProperties->TransferType;
+    DPRINT("USBPORT_AllocateBandwidthUSB2: TransferType - %X\n", TransferType);
+
+    if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+        TransferType == USBPORT_TRANSFER_TYPE_BULK)
+    {
+        return TRUE;
+    }
+
+    if (Endpoint->TtExtension)
+        TtExtension = Endpoint->TtExtension;
+    else
+        TtExtension = NULL;
+
+    InitializeListHead(&RebalanceList);
+
+    Rebalance = ExAllocatePoolWithTag(NonPagedPool,
+                                      sizeof(USB2_REBALANCE),
+                                      USB_PORT_TAG);
+
+    DPRINT("USBPORT_AllocateBandwidthUSB2: Rebalance - %p, TtExtension - %p\n",
+           Rebalance,
+           TtExtension);
+
+    if (Rebalance)
+    {
+        RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
+
+        TtEndpoint = Endpoint->TtEndpoint;
+        TtEndpoint->Endpoint = Endpoint;
+
+        Direction = EndpointProperties->Direction == USBPORT_TRANSFER_DIRECTION_OUT;
+        DeviceSpeed = EndpointProperties->DeviceSpeed;
+
+        switch (DeviceSpeed)
+        {
+            case UsbLowSpeed:
+            case UsbFullSpeed:
+            {
+                Tt = &TtExtension->Tt;
+                Period = USB2_FRAMES;
+
+                while (Period > 0 && Period > EndpointProperties->Period)
+                {
+                    Period >>= 1;
+                }
+
+                DPRINT("USBPORT_AllocateBandwidthUSB2: Period - %X\n", Period);
+                break;
+            }
+
+            case UsbHighSpeed:
+            {
+                Tt = &FdoExtension->Usb2Extension->HcTt;
+
+                if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
+                    Period = USB2_MAX_MICROFRAMES;
+                else
+                    Period = EndpointProperties->Period;
+
+                break;
+            }
+
+            default:
+            {
+                DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
+                        DeviceSpeed);
+
+                DbgBreakPoint();
+
+                Tt = &TtExtension->Tt;
+                break;
+            }
+        }
+
+        USB2_InitTtEndpoint(TtEndpoint,
+                            TransferType,
+                            Direction,
+                            DeviceSpeed,
+                            Period,
+                            EndpointProperties->MaxPacketSize,
+                            Tt);
+
+        RebalanceListEntries = USB2_FRAMES - 2;
+
+        Result = USB2_AllocateTimeForEndpoint(TtEndpoint,
+                                              Rebalance,
+                                              &RebalanceListEntries);
+
+        if (Result)
+        {
+            Result = USB2_PromotePeriods(TtEndpoint,
+                                         Rebalance,
+                                         &RebalanceListEntries);
+        }
+
+        RebalanceListEntries = 0;
+
+        for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+        {
+            RebalanceListEntries = ix + 1;
+        }
+    }
+    else
+    {
+        RebalanceListEntries = 0;
+        Result = FALSE;
+    }
+
+    DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceListEntries - %X, Result - %X\n",
+           RebalanceListEntries,
+           Result);
+
+    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);
+    }
+
+    if (Rebalance)
+        ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
+
+    if (Result)
+    {
+        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;
+
+        ASSERT(ActualPeriod);
+        Factor = USB2_FRAMES / ActualPeriod;
+        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);
+
+    if (!TtExtension)
+    {
+        DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
+        return Result;
+    }
+
+    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;
+    }
+
+    DPRINT("USBPORT_AllocateBandwidthUSB2: Result - %X\n", Result);
+
+    return Result;
 }
 
 VOID
@@ -24,5 +2045,198 @@ 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;
+    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));
+
+    ASSERT(Period != 0);
+    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
+NTAPI
+USB2_InitTT(IN PUSB2_HC_EXTENSION HcExtension,
+            IN PUSB2_TT Tt)
+{
+    ULONG ix;
+    ULONG jx;
+
+    DPRINT("USB2_InitTT: HcExtension - %p, Tt - %p\n", HcExtension, Tt);
+
+    Tt->HcExtension = HcExtension;
+    Tt->DelayTime = 1;
+    Tt->MaxTime = USB2_FS_MAX_PERIODIC_ALLOCATION;
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        Tt->FrameBudget[ix].TimeUsed = USB2_MAX_MICROFRAMES;
+        Tt->FrameBudget[ix].AltEndpoint = NULL;
+
+        for (jx = 0; jx < USB2_MICROFRAMES; jx++)
+        {
+            Tt->TimeCS[ix][jx] = 0;
+            Tt->NumStartSplits[ix][jx] = 0;
+        }
+
+        Tt->FrameBudget[ix].IsoEndpoint = &Tt->IsoEndpoint[ix];
+
+        USB2_InitTtEndpoint(&Tt->IsoEndpoint[ix],
+                            USBPORT_TRANSFER_TYPE_ISOCHRONOUS,
+                            USBPORT_TRANSFER_DIRECTION_OUT,
+                            UsbFullSpeed,
+                            USB2_FRAMES,
+                            0,
+                            Tt);
+
+        Tt->IsoEndpoint[ix].ActualPeriod = USB2_FRAMES;
+        Tt->IsoEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
+        Tt->IsoEndpoint[ix].StartFrame = ix;
+        Tt->IsoEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
+
+        Tt->FrameBudget[ix].IntEndpoint = &Tt->IntEndpoint[ix];
+
+        USB2_InitTtEndpoint(&Tt->IntEndpoint[ix],
+                            USBPORT_TRANSFER_TYPE_INTERRUPT,
+                            USBPORT_TRANSFER_DIRECTION_OUT,
+                            UsbFullSpeed,
+                            USB2_FRAMES,
+                            0,
+                            Tt);
+
+        Tt->IntEndpoint[ix].ActualPeriod = USB2_FRAMES;
+        Tt->IntEndpoint[ix].CalcBusTime = USB2_FS_SOF_TIME + USB2_HUB_DELAY;
+        Tt->IntEndpoint[ix].StartFrame = ix;
+        Tt->IntEndpoint[ix].StartMicroframe = USB2_PREV_MICROFRAME;
+    }
+}
+
+VOID
+NTAPI
+USB2_InitController(IN PUSB2_HC_EXTENSION HcExtension)
+{
+    ULONG ix;
+    ULONG jx;
+
+    DPRINT("USB2_InitController: HcExtension - %p\n", HcExtension);
+
+    HcExtension->MaxHsBusAllocation = USB2_MAX_MICROFRAME_ALLOCATION;
+
+    for (ix = 0; ix < USB2_FRAMES; ix++)
+    {
+        for (jx = 0; jx < USB2_MICROFRAMES; jx++)
+        {
+            HcExtension->TimeUsed[ix][jx] = 0;
+        }
+    }
+
+    HcExtension->HcDelayTime = USB2_CONTROLLER_DELAY;
+
+    USB2_InitTT(HcExtension, &HcExtension->HcTt);
 }
index 98484f6..53e65b2 100644 (file)
 
     #endif
 
+    #ifndef NDEBUG_USBPORT_USB2
+
+        #define DPRINT_USB2(fmt, ...) do { \
+            if (DbgPrint("(%s:%d) " fmt, __RELFILE__, __LINE__, ##__VA_ARGS__))  \
+                DbgPrint("(%s:%d) DbgPrint() failed!\n", __RELFILE__, __LINE__); \
+        } while (0)
+
+    #else
+
+#if defined(_MSC_VER)
+        #define DPRINT_USB2   __noop
+#else
+        #define DPRINT_USB2(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+#endif
+
+    #endif
+
 #else /* not DBG */
 
 #if defined(_MSC_VER)
     #define DPRINT_INT    __noop
     #define DPRINT_TIMER    __noop
     #define DPRINT_QUEUE    __noop
+    #define DPRINT_USB2    __noop
 #else
     #define DPRINT_MINIPORT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
     #define DPRINT_CORE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
     #define DPRINT_INT(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
     #define DPRINT_TIMER(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
     #define DPRINT_QUEUE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
+    #define DPRINT_USB2(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
 #endif /* _MSC_VER */
 
 #endif /* not DBG */
index 0928646..cc85e73 100644 (file)
@@ -637,8 +637,8 @@ USBPORT_InvalidateControllerHandler(IN PDEVICE_OBJECT FdoDevice,
 {
     PUSBPORT_DEVICE_EXTENSION FdoExtension;
 
-    DPRINT("USBPORT_InvalidateControllerHandler: Invalidate Type - %x\n",
-           Type);
+    DPRINT_CORE("USBPORT_InvalidateControllerHandler: Invalidate Type - %x\n",
+                Type);
 
     FdoExtension = FdoDevice->DeviceExtension;
 
@@ -869,7 +869,7 @@ USBPORT_DpcHandler(IN PDEVICE_OBJECT FdoDevice)
     LIST_ENTRY List;
     LONG LockCounter;
 
-    DPRINT("USBPORT_DpcHandler: ... \n");
+    DPRINT_CORE("USBPORT_DpcHandler: ... \n");
 
     FdoExtension = FdoDevice->DeviceExtension;
 
@@ -1845,7 +1845,8 @@ USBPORT_AddDevice(IN PDRIVER_OBJECT DriverObject,
         RtlInitUnicodeString(&DeviceName, CharDeviceName);
 
         Length = sizeof(USBPORT_DEVICE_EXTENSION) +
-                 MiniPortInterface->Packet.MiniPortExtensionSize;
+                 MiniPortInterface->Packet.MiniPortExtensionSize +
+                 sizeof(USB2_HC_EXTENSION);
 
         /* Create device */
         Status = IoCreateDevice(DriverObject,
@@ -1903,6 +1904,22 @@ USBPORT_AddDevice(IN PDRIVER_OBJECT DriverObject,
     FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension +
                                         sizeof(USBPORT_DEVICE_EXTENSION));
 
+    if (MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
+    {
+        FdoExtension->Usb2Extension =
+        (PUSB2_HC_EXTENSION)((ULONG_PTR)FdoExtension->MiniPortExt +
+                             MiniPortInterface->Packet.MiniPortExtensionSize);
+
+        DPRINT("USBPORT_AddDevice: Usb2Extension - %p\n",
+               FdoExtension->Usb2Extension);
+
+        USB2_InitController(FdoExtension->Usb2Extension);
+    }
+    else
+    {
+        FdoExtension->Usb2Extension = NULL;
+    }
+
     FdoExtension->MiniPortInterface = MiniPortInterface;
     FdoExtension->FdoNameNumber = DeviceNumber;
 
@@ -1936,7 +1953,7 @@ USBPORT_Unload(IN PDRIVER_OBJECT DriverObject)
 
     if (!MiniPortInterface)
     {
-        DPRINT("USBPORT_Unload: CRITICAL ERROR!!! USBPORT_FindMiniPort not found MiniPortInterface\n");
+        DPRINT("USBPORT_Unload: CRITICAL ERROR!!! Not found MiniPortInterface\n");
         KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
     }
 
index 26e021c..20386f4 100644 (file)
 /* Device handle Flags (USBPORT_DEVICE_HANDLE) */
 #define DEVICE_HANDLE_FLAG_ROOTHUB     0x00000002
 #define DEVICE_HANDLE_FLAG_REMOVED     0x00000008
-#define DEVICE_HANDLE_FLAG_INITIALIZED 0x00000010
+#define DEVICE_HANDLE_FLAG_USB2HUB     0x00000010
 
 /* Endpoint Flags (USBPORT_ENDPOINT) */
 #define ENDPOINT_FLAG_DMA_TYPE      0x00000001
@@ -153,6 +153,11 @@ typedef struct _USBPORT_COMMON_BUFFER_HEADER {
 
 typedef struct _USBPORT_ENDPOINT *PUSBPORT_ENDPOINT;
 
+typedef struct _USB2_HC_EXTENSION *PUSB2_HC_EXTENSION;
+typedef struct _USB2_TT_EXTENSION *PUSB2_TT_EXTENSION;
+typedef struct _USB2_TT *PUSB2_TT;
+typedef struct _USB2_TT_ENDPOINT *PUSB2_TT_ENDPOINT;
+
 typedef struct _USBPORT_PIPE_HANDLE {
   ULONG Flags;
   ULONG PipeFlags;
@@ -191,6 +196,8 @@ typedef struct _USBPORT_DEVICE_HANDLE {
   LIST_ENTRY DeviceHandleLink;
   LONG DeviceHandleLock;
   ULONG TtCount;
+  PUSB2_TT_EXTENSION TtExtension; // Transaction Translator
+  LIST_ENTRY TtList;
 } USBPORT_DEVICE_HANDLE, *PUSBPORT_DEVICE_HANDLE;
 
 typedef struct _USBPORT_ENDPOINT {
@@ -198,6 +205,8 @@ typedef struct _USBPORT_ENDPOINT {
   PDEVICE_OBJECT FdoDevice;
   PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
   PUSBPORT_DEVICE_HANDLE DeviceHandle;
+  PUSB2_TT_EXTENSION TtExtension; // Transaction Translator
+  PUSB2_TT_ENDPOINT TtEndpoint;
   USBPORT_ENDPOINT_PROPERTIES EndpointProperties;
   ULONG EndpointWorker;
   ULONG FrameNumber;
@@ -226,6 +235,8 @@ typedef struct _USBPORT_ENDPOINT {
   LIST_ENTRY FlushLink;
   LIST_ENTRY FlushControllerLink;
   LIST_ENTRY FlushAbortLink;
+  LIST_ENTRY TtLink;
+  LIST_ENTRY RebalanceLink;
 } USBPORT_ENDPOINT, *PUSBPORT_ENDPOINT;
 
 typedef struct _USBPORT_ISO_BLOCK *PUSBPORT_ISO_BLOCK;
@@ -374,10 +385,14 @@ typedef struct _USBPORT_DEVICE_EXTENSION {
   KSPIN_LOCK SetPowerD0SpinLock;
   KDPC WorkerRequestDpc;
   KDPC HcWakeDpc;
+  /* Usb 2.0 HC Extension */
+  PUSB2_HC_EXTENSION Usb2Extension;
+  ULONG Bandwidth[32];
+  KSPIN_LOCK TtSpinLock;
 
   /* Miniport extension should be aligned on 0x100 */
 #if !defined(_M_X64)
-  ULONG Padded[34];
+  ULONG Padded[64];
 #else
   ULONG Padded[0];
 #endif
@@ -385,7 +400,7 @@ typedef struct _USBPORT_DEVICE_EXTENSION {
 } USBPORT_DEVICE_EXTENSION, *PUSBPORT_DEVICE_EXTENSION;
 
 #if !defined(_M_X64)
-C_ASSERT(sizeof(USBPORT_DEVICE_EXTENSION) == 0x400);
+C_ASSERT(sizeof(USBPORT_DEVICE_EXTENSION) == 0x500);
 #else
 C_ASSERT(sizeof(USBPORT_DEVICE_EXTENSION) == 0x600);
 #endif
@@ -430,6 +445,130 @@ typedef struct _TIMER_WORK_QUEUE_ITEM {
   ULONG Context;
 } TIMER_WORK_QUEUE_ITEM, *PTIMER_WORK_QUEUE_ITEM;
 
+/* Transaction Translator */
+/* See Chapter 5 - USB Data Flow Model and Chapter 11 - Hub Specification */
+
+#define USB2_FRAMES           32
+#define USB2_MICROFRAMES      8
+#define USB2_MAX_MICROFRAMES  (USB2_FRAMES * USB2_MICROFRAMES)
+#define USB2_PREV_MICROFRAME  0xFF
+
+#define USB2_MAX_MICROFRAME_ALLOCATION         7000 // bytes
+#define USB2_CONTROLLER_DELAY                  100
+#define USB2_FS_MAX_PERIODIC_ALLOCATION        1157 // ((12000 / 8 bits) * 0.9) / (7/6) - 90% max, and bits stuffing
+#define USB2_FS_SOF_TIME                       6
+#define USB2_HUB_DELAY                         30
+#define USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME  16
+#define USB2_FS_RAW_BYTES_IN_MICROFRAME        188  // (12000 / 8 bits / USB2_MICROFRAMES) = 187,5. But we use "best case budget"
+
+/* Overheads */
+#define USB2_LS_INTERRUPT_OVERHEAD             117 // FS-bytes
+#define USB2_FS_INTERRUPT_OVERHEAD             13
+#define USB2_HS_INTERRUPT_OUT_OVERHEAD         45
+#define USB2_HS_INTERRUPT_IN_OVERHEAD          25
+#define USB2_FS_ISOCHRONOUS_OVERHEAD           9
+#define USB2_HS_ISOCHRONOUS_OUT_OVERHEAD       38
+#define USB2_HS_ISOCHRONOUS_IN_OVERHEAD        18
+
+#define USB2_HS_SS_INTERRUPT_OUT_OVERHEAD      58
+#define USB2_HS_CS_INTERRUPT_OUT_OVERHEAD      36
+#define USB2_HS_SS_INTERRUPT_IN_OVERHEAD       39
+#define USB2_HS_CS_INTERRUPT_IN_OVERHEAD       38
+
+#define USB2_HS_SS_ISOCHRONOUS_OUT_OVERHEAD    58
+#define USB2_HS_SS_ISOCHRONOUS_IN_OVERHEAD     39
+#define USB2_HS_CS_ISOCHRONOUS_IN_OVERHEAD     38
+
+#define USB2_BIT_STUFFING_OVERHEAD  (8 * (7/6)) // 7.1.9 Bit Stuffing
+
+typedef union _USB2_TT_ENDPOINT_PARAMS {
+  struct {
+    ULONG TransferType           : 4;
+    ULONG Direction              : 1;
+    USB_DEVICE_SPEED DeviceSpeed : 2;
+    BOOL EndpointMoved           : 1;
+    ULONG Reserved               : 24;
+  };
+  ULONG AsULONG;
+} USB2_TT_ENDPOINT_PARAMS;
+
+C_ASSERT(sizeof(USB2_TT_ENDPOINT_PARAMS) == sizeof(ULONG));
+
+typedef union _USB2_TT_ENDPOINT_NUMS {
+  struct {
+    ULONG NumStarts     : 4;
+    ULONG NumCompletes  : 4;
+    ULONG Reserved      : 24;
+  };
+  ULONG AsULONG;
+} USB2_TT_ENDPOINT_NUMS;
+
+C_ASSERT(sizeof(USB2_TT_ENDPOINT_NUMS) == sizeof(ULONG));
+
+typedef struct _USB2_TT_ENDPOINT {
+  PUSB2_TT Tt;
+  PUSBPORT_ENDPOINT Endpoint;
+  struct _USB2_TT_ENDPOINT * NextTtEndpoint;
+  USB2_TT_ENDPOINT_PARAMS TtEndpointParams;
+  USB2_TT_ENDPOINT_NUMS Nums;
+  BOOL IsPromoted;
+  USHORT MaxPacketSize;
+  USHORT PreviosPeriod;
+  USHORT Period;
+  USHORT ActualPeriod;
+  USHORT CalcBusTime;
+  USHORT StartTime;
+  USHORT Reserved2;
+  UCHAR StartFrame;
+  UCHAR StartMicroframe;
+} USB2_TT_ENDPOINT, *PUSB2_TT_ENDPOINT;
+
+typedef struct _USB2_FRAME_BUDGET {
+  PUSB2_TT_ENDPOINT IsoEndpoint;
+  PUSB2_TT_ENDPOINT IntEndpoint;
+  PUSB2_TT_ENDPOINT AltEndpoint;
+  USHORT TimeUsed;
+  USHORT Reserved2;
+} USB2_FRAME_BUDGET, *PUSB2_FRAME_BUDGET;
+
+typedef struct _USB2_TT {
+  PUSB2_HC_EXTENSION HcExtension;
+  ULONG DelayTime;
+  ULONG MaxTime;
+  USB2_TT_ENDPOINT IntEndpoint[USB2_FRAMES];
+  USB2_TT_ENDPOINT IsoEndpoint[USB2_FRAMES];
+  USB2_FRAME_BUDGET FrameBudget[USB2_FRAMES];
+  ULONG NumStartSplits[USB2_FRAMES][USB2_MICROFRAMES];
+  ULONG TimeCS[USB2_FRAMES][USB2_MICROFRAMES];
+} USB2_TT, *PUSB2_TT;
+
+#define USB2_TT_EXTENSION_FLAG_DELETED  1
+
+typedef struct _USB2_TT_EXTENSION {
+  PDEVICE_OBJECT RootHubPdo;
+  ULONG Flags;
+  ULONG BusBandwidth;
+  ULONG Bandwidth[USB2_FRAMES];
+  ULONG MaxBandwidth;
+  ULONG MinBandwidth;
+  USHORT DeviceAddress;
+  USHORT TtNumber;
+  LIST_ENTRY EndpointList;
+  LIST_ENTRY Link;
+  USB2_TT Tt;
+} USB2_TT_EXTENSION, *PUSB2_TT_EXTENSION;
+
+typedef struct _USB2_HC_EXTENSION {
+  ULONG MaxHsBusAllocation;
+  ULONG HcDelayTime;
+  ULONG TimeUsed[USB2_FRAMES][USB2_MICROFRAMES];
+  USB2_TT HcTt;
+} USB2_HC_EXTENSION, *PUSB2_HC_EXTENSION;
+
+typedef struct _USB2_REBALANCE {
+  PUSB2_TT_ENDPOINT RebalanceEndpoint[USB2_FRAMES - 2];
+} USB2_REBALANCE, *PUSB2_REBALANCE;
+
 /* usbport.c */
 NTSTATUS
 NTAPI
@@ -1184,4 +1323,30 @@ USBPORT_FreeBandwidthUSB2(
   IN PDEVICE_OBJECT FdoDevice,
   IN PUSBPORT_ENDPOINT Endpoint);
 
+VOID
+NTAPI
+USBPORT_UpdateAllocatedBwTt(
+  IN PUSB2_TT_EXTENSION TtExtension);
+
+VOID
+NTAPI
+USB2_InitTT(
+  IN PUSB2_HC_EXTENSION HcExtension,
+  IN PUSB2_TT Tt);
+
+VOID
+NTAPI
+USB2_InitController(
+  IN PUSB2_HC_EXTENSION HcExtension);
+
+VOID
+NTAPI
+USBPORT_DumpingEndpointProperties(
+  IN PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties);
+
+VOID
+NTAPI
+USBPORT_DumpingTtEndpoint(
+  IN PUSB2_TT_ENDPOINT TtEndpoint);
+
 #endif /* USBPORT_H__ */
index 8babb86..c2afc73 100644 (file)
@@ -279,6 +279,14 @@ C_ASSERT(sizeof(USB_HUB_STATUS_AND_CHANGE) == sizeof(ULONG));
 #define USB_20_HUB_DESCRIPTOR_TYPE  0x29
 #define USB_30_HUB_DESCRIPTOR_TYPE  0x2A
 
+#define USB_REQUEST_CLEAR_TT_BUFFER     0x08
+#define USB_REQUEST_RESET_TT            0x09
+#define USB_REQUEST_GET_TT_STATE        0x0A
+#define USB_REQUEST_STOP_TT             0x0B
+
+#define USB_REQUEST_SET_HUB_DEPTH       0x0C
+#define USB_REQUEST_GET_PORT_ERR_COUNT  0x0D
+
 #define USB_DEVICE_CLASS_RESERVED             0x00
 #define USB_DEVICE_CLASS_AUDIO                0x01
 #define USB_DEVICE_CLASS_COMMUNICATIONS       0x02