//#define NDEBUG
#include <debug.h>
+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)
Direction = TtEndpoint->TtEndpointParams.Direction;
DeviceSpeed = TtEndpoint->TtEndpointParams.Direction;
- HostDelay = TtEndpoint->Tt->HcExtension->HcDelayTime;
+ 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_ISOCHRONOUS_OUT_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;
+ }
+
+ //DPRINT("USB2_GetHsOverhead: *OverheadSS - %X, *OverheadCS - %X\n",
+ // *OverheadSS,
+ // *OverheadCS);
+ }
+}
+
+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 == 0xFF)
+ USB2_GetPrevMicroFrame(&frame, &uframe);
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+ {
+ if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+ OverheadSS,
+ USB2_MAX_MICROFRAME_ALLOCATION))
+ {
+ Result = FALSE;
+ }
+
+ if (Tt->NumStartSplits[frame][uframe] >
+ (USB2_MAX_FS_LS_TRANSACTIONS_IN_UFRAME - 1))
+ {
+ DPRINT1("USB2_AllocateHS: Num Start Splits - %X\n",
+ Tt->NumStartSplits[frame][uframe] + 1);
+
+ ASSERT(FALSE);
+ Result = FALSE;
+ }
+
+ ++Tt->NumStartSplits[frame][uframe];
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+ {
+ if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+ OverheadCS,
+ USB2_MAX_MICROFRAME_ALLOCATION))
+ {
+ Result = FALSE;
+ }
+
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+
+ PktSize = TtEndpoint->MaxPacketSize;
+ PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
+
+ if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+ {
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe;
+
+ if (uframe == 0xFF)
+ USB2_GetPrevMicroFrame(&frame, &uframe);
+
+ DataTime = 0;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+ {
+ DataSize = PktSizeBitStuff - DataTime;
+
+ if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ DataTime = DataSize;
+ else
+ DataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+
+ DPRINT("USB2_AllocateHS: ix - %X, frame - %X, uframe - %X, TimeUsed - %X\n",
+ ix,
+ frame,
+ uframe,
+ HcExtension->TimeUsed[frame][uframe]);
+
+ if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+ DataTime,
+ USB2_MAX_MICROFRAME_ALLOCATION))
+ {
+ Result = FALSE;
+ }
+
+ USB2_IncMicroFrame(&frame, &uframe);
+ DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+ }
+ }
+ else
+ {
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+ {
+ if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ {
+ RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
+ Tt->TimeCS[frame][uframe];
+
+ if (RemainDataTime >= PktSizeBitStuff)
+ {
+ DataTime = PktSizeBitStuff;
+ }
+ else if (RemainDataTime > 0)
+ {
+ DataTime = RemainDataTime;
+ }
+ else
+ {
+ DataTime = 0;
+ }
+
+ if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+ DataTime,
+ USB2_MAX_MICROFRAME_ALLOCATION))
+ {
+ Result = FALSE;
+ }
+ }
+
+ if (PktSizeBitStuff < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ Tt->TimeCS[frame][uframe] += PktSizeBitStuff;
+ else
+ Tt->TimeCS[frame][uframe] += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+ }
+
+ DPRINT("USB2_AllocateHS: Result - %X\n", Result);
+ return Result;
+}
+
+VOID
+NTAPI
+USB2_DeallocateHS(IN PUSB2_TT_ENDPOINT TtEndpoint,
+ IN ULONG Frame)
+{
+ PUSB2_TT Tt;
+ PUSB2_HC_EXTENSION HcExtension;
+ ULONG OverheadCS;
+ ULONG OverheadSS;
+ ULONG Direction;
+ ULONG ix;
+ ULONG CurrentDataTime;
+ ULONG RemainDataTime;
+ ULONG DataTime;
+ ULONG DataSize;
+ USHORT PktSize;
+ USHORT PktSizeBitStuff;
+ UCHAR uframe;
+ UCHAR frame;
+
+ DPRINT("USB2_DeallocateHS: TtEndpoint - %p, Frame - %X\n",
+ TtEndpoint,
+ Frame);
+
+ Tt = TtEndpoint->Tt;
+ HcExtension = Tt->HcExtension;
+
+ USB2_GetHsOverhead(TtEndpoint, &OverheadSS, &OverheadCS);
+
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe;
+
+ if (TtEndpoint->StartMicroframe == 0xFF)
+ {
+ USB2_GetPrevMicroFrame(&frame, &uframe);
+ }
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+ {
+ HcExtension->TimeUsed[frame][uframe] -= OverheadSS;
+ --Tt->NumStartSplits[frame][uframe];
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+ {
+ HcExtension->TimeUsed[frame][uframe] -= OverheadCS;
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+
+ Direction = TtEndpoint->TtEndpointParams.Direction;
+ PktSize = TtEndpoint->MaxPacketSize;
+ PktSizeBitStuff = USB2_AddDataBitStuff(PktSize);
+
+ if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+ {
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe;
+
+ if (TtEndpoint->StartMicroframe == 0xFF)
+ {
+ USB2_GetPrevMicroFrame(&frame, &uframe);
+ }
+
+ DataTime = 0;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+ {
+ DataSize = PktSizeBitStuff - DataTime;
+
+ if (DataSize <= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ {
+ CurrentDataTime = PktSizeBitStuff - DataTime;
+ }
+ else
+ {
+ CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+ }
+
+ HcExtension->TimeUsed[frame][uframe] -= CurrentDataTime;
+ USB2_IncMicroFrame(&frame, &uframe);
+ DataTime += USB2_FS_RAW_BYTES_IN_MICROFRAME;
+ }
+ }
+ else
+ {
+ frame = TtEndpoint->StartFrame + Frame;
+ uframe = TtEndpoint->StartMicroframe + TtEndpoint->Nums.NumStarts + 1;
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumCompletes; ix++)
+ {
+ if (PktSizeBitStuff >= USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ {
+ CurrentDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME;
+ }
+ else
+ {
+ CurrentDataTime = PktSizeBitStuff;
+ }
+
+ Tt->TimeCS[frame][uframe] -= CurrentDataTime;
+
+ if (Tt->TimeCS[frame][uframe] < USB2_FS_RAW_BYTES_IN_MICROFRAME)
+ {
+ RemainDataTime = USB2_FS_RAW_BYTES_IN_MICROFRAME -
+ Tt->TimeCS[frame][uframe];
+
+ if (RemainDataTime >= PktSizeBitStuff)
+ RemainDataTime = PktSizeBitStuff;
+
+ HcExtension->TimeUsed[frame][uframe] -= RemainDataTime;
+ }
+
+ USB2_IncMicroFrame(&frame, &uframe);
+ }
+ }
+
+ return;
+}
+
+BOOLEAN
+NTAPI
+USB2_MoveTtEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
+ IN USHORT BusTime,
+ IN PUSB2_REBALANCE Rebalance,
+ IN ULONG RebalanceListEntries,
+ OUT BOOLEAN * OutResult)
+{
+ ULONG EndBusTime;
+ ULONG TransferType;
+ ULONG Num;
+ UCHAR ix;
+
+ DPRINT("USB2_MoveTtEndpoint: TtEndpoint - %p, BusTime - %X\n",
+ TtEndpoint,
+ BusTime);
+
+ *OutResult = TRUE;
+
+ for (Num = 0; Rebalance->RebalanceEndpoint[Num]; Num++)
+ {
+ if (Rebalance->RebalanceEndpoint[Num] == TtEndpoint)
+ break;
+ }
+
+ DPRINT("USB2_MoveTtEndpoint: Num - %X\n", Num);
+
+ TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+ if (Rebalance->RebalanceEndpoint[Num] &&
+ TtEndpoint->TtEndpointParams.EndpointMoved == TRUE &&
+ (TransferType != USBPORT_TRANSFER_TYPE_INTERRUPT || BusTime >= 0))
+ {
+ DPRINT("USB2_MoveTtEndpoint: result - FALSE\n");
+ return FALSE;
+ }
+
+ for (ix = 0;
+ (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+ ix += TtEndpoint->ActualPeriod)
+ {
+ USB2_DeallocateHS(TtEndpoint, ix);
+ }
+
+ TtEndpoint->StartTime += BusTime;
+
+ EndBusTime = TtEndpoint->StartTime + TtEndpoint->CalcBusTime;
+
+ if (EndBusTime > USB2_FS_MAX_PERIODIC_ALLOCATION)
+ {
+ DPRINT("USB2_MoveTtEndpoint: EndBusTime is too large!\n");
+ *OutResult = FALSE;
+ }
+
+ TtEndpoint->TtEndpointParams.EndpointMoved = TRUE;
+
+ if (Rebalance->RebalanceEndpoint[Num] == NULL)
+ {
+ if (Num >= RebalanceListEntries)
+ {
+ DPRINT("USB2_MoveTtEndpoint: Too many changes!\n");
+ *OutResult = FALSE;
+ }
+ else
+ {
+ Rebalance->RebalanceEndpoint[Num] = TtEndpoint;
+ Rebalance->RebalanceEndpoint[Num + 1] = NULL;
+ }
+ }
+
+ for (ix = 0;
+ (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+ ix += TtEndpoint->ActualPeriod)
+ {
+ if (!USB2_AllocateHS(TtEndpoint, ix))
+ {
+ DPRINT("USB2_MoveTtEndpoint: OutResult - FALSE\n");
+ OutResult = FALSE;
+ }
+ }
+
+ DPRINT("USB2_MoveTtEndpoint: result - TRUE\n");
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+USB2_CommonFrames(IN PUSB2_TT_ENDPOINT NextTtEndpoint,
+ IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+ UCHAR Frame;
+
+ DPRINT("USB2_CommonFrames: \n");
+
+ if (NextTtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms ||
+ TtEndpoint->ActualPeriod == ENDPOINT_INTERRUPT_1ms)
+ {
+ return TRUE;
+ }
+
+ if (NextTtEndpoint->ActualPeriod < TtEndpoint->ActualPeriod)
+ {
+ Frame = TtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
+ }
+ else
+ {
+ Frame = NextTtEndpoint->StartFrame % TtEndpoint->ActualPeriod;
+ }
+
+ return (Frame == TtEndpoint->StartFrame);
+}
+
+VOID
+NTAPI
+USB2_ConvertFrame(IN UCHAR Frame,
+ IN UCHAR Microframe,
+ OUT PUCHAR HcFrame,
+ OUT PUCHAR HcMicroframe)
+{
+ DPRINT("USB2_ConvertFrame: Frame - %x, Microframe - %x\n",
+ Frame,
+ Microframe);
+
+ if (Microframe == 0xFF)
+ {
+ *HcFrame = Frame;
+ *HcMicroframe = 0;
+ }
+
+ if (Microframe >= 0 &&
+ Microframe <= (USB2_MICROFRAMES - 2))
+ {
+ *HcFrame = Frame;
+ *HcMicroframe = Microframe + 1;
+ }
+
+ if (Microframe == (USB2_MICROFRAMES - 1))
+ {
+ *HcFrame = Frame + 1;
+ *HcMicroframe = 0;
+ }
+}
+
+UCHAR
+NTAPI
+USB2_GetSMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+ ULONG ix;
+ UCHAR SMask = 0;
+ UCHAR HcFrame;
+ UCHAR HcMicroFrame;
+
+ if (TtEndpoint->TtEndpointParams.DeviceSpeed == UsbHighSpeed)
+ {
+ SMask = (1 << TtEndpoint->StartMicroframe);
+ }
+ else
+ {
+ USB2_ConvertFrame(TtEndpoint->StartFrame,
+ TtEndpoint->StartMicroframe,
+ &HcFrame,
+ &HcMicroFrame);
+
+ for (ix = 0; ix < TtEndpoint->Nums.NumStarts; ix++)
+ {
+ SMask |= (1 << HcMicroFrame);
+ HcMicroFrame++;
+ }
+ }
+
+ return SMask;
+}
+
+UCHAR
+NTAPI
+USB2_GetCMASK(IN PUSB2_TT_ENDPOINT TtEndpoint)
+{
+ ULONG NumCompletes;
+ ULONG TransferType;
+ ULONG DeviceSpeed;
+ ULONG Direction;
+ UCHAR Result;
+ UCHAR MicroFrameCS;
+ UCHAR HcFrame;
+ UCHAR HcMicroFrame;
+ UCHAR MaskCS = 0;
+ static const UCHAR CMASKS[USB2_MICROFRAMES] = {
+ 0x1C, 0x38, 0x70, 0xE0, 0xC1, 0x83, 0x07, 0x0E
+ };
+
+ TransferType = TtEndpoint->TtEndpointParams.TransferType;
+ DeviceSpeed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+ Direction = TtEndpoint->TtEndpointParams.Direction;
+
+ if (DeviceSpeed == UsbHighSpeed)
+ {
+ return 0;
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ USB2_ConvertFrame(TtEndpoint->StartFrame,
+ TtEndpoint->StartMicroframe,
+ &HcFrame,
+ &HcMicroFrame);
+
+ Result = CMASKS[HcMicroFrame];
+ }
+ else
+ {
+ if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+ {
+ return 0;
+ }
+
+ USB2_ConvertFrame(TtEndpoint->StartFrame,
+ TtEndpoint->StartMicroframe,
+ &HcFrame,
+ &HcMicroFrame);
+
+ NumCompletes = TtEndpoint->Nums.NumCompletes;
+
+ for (MicroFrameCS = HcMicroFrame + 2;
+ MicroFrameCS < USB2_MICROFRAMES;
+ MicroFrameCS++)
+ {
+ MaskCS |= (1 << MicroFrameCS);
+ NumCompletes--;
+
+ if (!NumCompletes)
+ {
+ return MaskCS;
+ }
+ }
+
+ for (; NumCompletes; NumCompletes--)
+ {
+ MaskCS |= (1 << (MicroFrameCS - USB2_MICROFRAMES));
+ }
+
+ Result = MaskCS;
+ }
+
+ return Result;
+}
+
+VOID
+NTAPI
+USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
+ IN PLIST_ENTRY List)
+{
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ PUSBPORT_REGISTRATION_PACKET Packet;
+ PUSBPORT_ENDPOINT Endpoint;
+ PLIST_ENTRY Entry;
+ ULONG AllocedBusTime;
+ ULONG EndpointBandwidth;
+ ULONG Factor;
+ ULONG ScheduleOffset;
+ ULONG Bandwidth;
+ ULONG n;
+ ULONG ix;
+ KIRQL OldIrql;
+ UCHAR NewPeriod;
+ UCHAR SMask;
+ UCHAR CMask;
+
+ FdoExtension = FdoDevice->DeviceExtension;
+ Packet = &FdoExtension->MiniPortInterface->Packet;
+
+ while (!IsListEmpty(List))
+ {
+ Entry = RemoveHeadList(List);
+
+ Endpoint = CONTAINING_RECORD(Entry,
+ USBPORT_ENDPOINT,
+ RebalanceLink.Flink);
+
+ DPRINT("USB2_RebalanceEndpoint: Endpoint - %p\n", Endpoint);
+
+ Endpoint->RebalanceLink.Flink = NULL;
+ Endpoint->RebalanceLink.Blink = NULL;
+
+ KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
+ &Endpoint->EndpointOldIrql);
+
+ SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+ CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+
+ ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+ NewPeriod = Endpoint->TtEndpoint->ActualPeriod;
+
+ AllocedBusTime = Endpoint->TtEndpoint->CalcBusTime;
+ EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
+
+ Endpoint->EndpointProperties.InterruptScheduleMask = SMask;
+ Endpoint->EndpointProperties.SplitCompletionMask = CMask;
+
+ if (Endpoint->EndpointProperties.Period != NewPeriod)
+ {
+ Factor = USB2_FRAMES / Endpoint->EndpointProperties.Period;
+ ASSERT(Factor);
+
+ for (ix = 0; ix < Factor; ix++)
+ {
+ Bandwidth = Endpoint->EndpointProperties.UsbBandwidth;
+ n = Factor * Endpoint->EndpointProperties.ScheduleOffset;
+ Endpoint->TtExtension->Bandwidth[n + ix] += Bandwidth;
+ }
+
+ Endpoint->EndpointProperties.Period = NewPeriod;
+ Endpoint->EndpointProperties.ScheduleOffset = ScheduleOffset;
+ Endpoint->EndpointProperties.UsbBandwidth = EndpointBandwidth;
+
+ Factor = USB2_FRAMES / NewPeriod;
+ ASSERT(Factor);
+
+ for (ix = 0; ix < Factor; ix++)
+ {
+ n = Factor * ScheduleOffset;
+ Endpoint->TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
+ }
+ }
+
+ KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
+
+ Packet->RebalanceEndpoint(FdoExtension->MiniPortExt,
+ &Endpoint->EndpointProperties,
+ (PVOID)((ULONG_PTR)Endpoint + sizeof(USBPORT_ENDPOINT)));
+
+ KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
+
+ KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
+ Endpoint->EndpointOldIrql);
+ }
+}
+
+VOID
+NTAPI
+USB2_Rebalance(IN PDEVICE_OBJECT FdoDevice,
+ IN PLIST_ENTRY RebalanceList)
+{
+ PUSBPORT_ENDPOINT_PROPERTIES EndpointProperties;
+ PUSBPORT_ENDPOINT Endpoint;
+ PLIST_ENTRY Entry;
+ LIST_ENTRY BalanceListInt1;
+ LIST_ENTRY BalanceListInt2;
+ ULONG TransferType;
+ ULONG ScheduleOffset;
+ UCHAR SMask;
+ UCHAR CMask;
+ UCHAR ActualPeriod;
+
+ DPRINT("USB2_Rebalance: FdoDevice - %p, RebalanceList - %p\n",
+ FdoDevice,
+ RebalanceList);
+
+ InitializeListHead(&BalanceListInt1);
+ InitializeListHead(&BalanceListInt2);
+
+ while (!IsListEmpty(RebalanceList))
+ {
+ Entry = RebalanceList->Flink;
+
+ Endpoint = CONTAINING_RECORD(Entry,
+ USBPORT_ENDPOINT,
+ RebalanceLink.Flink);
+
+ DPRINT("USBPORT_Rebalance: Entry - %p, Endpoint - %p\n",
+ Entry,
+ Endpoint);
+
+ RemoveHeadList(RebalanceList);
+ Entry->Flink = NULL;
+ Entry->Blink = NULL;
+
+ SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+ CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+
+ ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+ ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
+
+ EndpointProperties = &Endpoint->EndpointProperties;
+ TransferType = EndpointProperties->TransferType;
+
+ switch (TransferType)
+ {
+ case USBPORT_TRANSFER_TYPE_ISOCHRONOUS:
+ DPRINT("USBPORT_Rebalance: USBPORT_TRANSFER_TYPE_ISOCHRONOUS. FIXME\n");
+ ASSERT(FALSE);
+ break;
+
+ case USBPORT_TRANSFER_TYPE_INTERRUPT:
+ if (SMask != EndpointProperties->InterruptScheduleMask ||
+ CMask != EndpointProperties->SplitCompletionMask ||
+ ScheduleOffset != EndpointProperties->ScheduleOffset ||
+ ActualPeriod != EndpointProperties->Period)
+ {
+ if (ActualPeriod == EndpointProperties->Period &&
+ ScheduleOffset == EndpointProperties->ScheduleOffset)
+ {
+ InsertTailList(&BalanceListInt1, Entry);
+ }
+ else
+ {
+ InsertTailList(&BalanceListInt2, Entry);
+ }
+ }
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+ }
+
+ USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt2);
+ USB2_RebalanceEndpoint(FdoDevice, &BalanceListInt1);
+ //USB2_RebalanceEndpoint(FdoDevice, &BalanceListIso);
+}
+
+BOOLEAN
+NTAPI
+USB2_DeallocateEndpointBudget(IN PUSB2_TT_ENDPOINT TtEndpoint,
+ IN PUSB2_REBALANCE Rebalance,
+ IN PULONG RebalanceListEntries,
+ IN ULONG MaxFrames)
+{
+ PUSB2_TT Tt;
+ PUSB2_HC_EXTENSION HcExtension;
+ ULONG Speed;
+ ULONG TransferType;
+ ULONG Frame;
+ ULONG StartMicroframe;
+ ULONG ix;
+ PUSB2_TT_ENDPOINT endpoint;
+ PUSB2_TT_ENDPOINT nextEndpoint;
+ PUSB2_TT_ENDPOINT lastEndpoint;
+ PUSB2_TT_ENDPOINT tmpEndpoint;
+ ULONG endTime;
+ ULONG maxEndTime;
+ ULONG lastEndTime;
+ ULONG Factor;
+ ULONG jx;
+ UCHAR frame;
+ UCHAR uframe;
+ USHORT Period;
+ BOOLEAN IsMoved = FALSE;
+
+ DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
+ TtEndpoint,
+ MaxFrames,
+ TtEndpoint->CalcBusTime);
+
+ if (TtEndpoint->CalcBusTime == 0)
+ {
+ DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
+ return FALSE;
+ }
+
+ Tt = TtEndpoint->Tt;
+ HcExtension = Tt->HcExtension;
+
+ Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+ DPRINT("USB2_DeallocateEndpointBudget: DeviceSpeed - %X\n", Speed);
+
+ StartMicroframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
+ TtEndpoint->StartMicroframe;
+
+ if (Speed == UsbHighSpeed)
+ {
+ for (ix = StartMicroframe;
+ ix < USB2_MAX_MICROFRAMES;
+ ix += TtEndpoint->ActualPeriod)
+ {
+ frame = ix / USB2_MICROFRAMES;
+ uframe = ix % (USB2_MICROFRAMES - 1);
+
+ HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
+ }
+
+ TtEndpoint->CalcBusTime = 0;
+
+ DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
+ return TRUE;
+ }
+
+ /* Speed != UsbHighSpeed (FS/LS) */
+
+ TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+ for (ix = MaxFrames, Frame = (MaxFrames - 1) - TtEndpoint->StartFrame;
+ ix > 0;
+ ix--, Frame--)
+ {
+ frame = TtEndpoint->StartFrame + Frame;
+
+ DPRINT("USB2_DeallocateEndpointBudget: frame - %X, Frame - %X, StartFrame - %X\n",
+ frame,
+ Frame,
+ TtEndpoint->StartFrame);
+
+ if ((Frame % TtEndpoint->ActualPeriod) == 0)
+ {
+ USB2_DeallocateHS(TtEndpoint, Frame);
+ Tt->FrameBudget[frame].TimeUsed -= TtEndpoint->CalcBusTime;
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ endpoint = Tt->FrameBudget[frame].IntEndpoint;
+ }
+ else
+ {
+ endpoint = Tt->FrameBudget[frame].IsoEndpoint;
+ }
+
+ nextEndpoint = endpoint->NextTtEndpoint;
+
+ DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, nextEndpoint - %p\n",
+ TtEndpoint,
+ nextEndpoint);
+
+ if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+ {
+ while (nextEndpoint)
+ {
+ endpoint = nextEndpoint;
+ nextEndpoint = nextEndpoint->NextTtEndpoint;
+ }
+
+ nextEndpoint = TtEndpoint;
+
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+ endpoint,
+ nextEndpoint);
+ }
+ else
+ {
+ while (nextEndpoint &&
+ !USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+ {
+ endpoint = nextEndpoint;
+ nextEndpoint = nextEndpoint->NextTtEndpoint;
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS &&
+ nextEndpoint)
+ {
+ DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
+ ASSERT(FALSE);
+ }
+
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+ endpoint,
+ nextEndpoint);
+ }
+
+ if ((Frame % TtEndpoint->ActualPeriod) == 0)
+ {
+ if (TtEndpoint->CalcBusTime > (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+ {
+ Tt->FrameBudget[frame].AltEndpoint = NULL;
+ }
+ else if (nextEndpoint)
+ {
+ nextEndpoint = nextEndpoint->NextTtEndpoint;
+ endpoint->NextTtEndpoint = nextEndpoint;
+
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+ endpoint,
+ nextEndpoint);
+ }
+ }
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT)
+ {
+ if (endpoint == Tt->FrameBudget[frame].IntEndpoint)
+ {
+ if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
+ {
+ endpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
+ }
+ else if (Tt->FrameBudget[frame].AltEndpoint)
+ {
+ endpoint = Tt->FrameBudget[frame].AltEndpoint;
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p\n", endpoint);
+ }
+ }
+ }
+ else
+ {
+ DPRINT1("USB2_DeallocateEndpointBudget: Iso Ep UNIMPLEMENTED. FIXME\n");
+ ASSERT(FALSE);
+ }
+
+ Period = TtEndpoint->ActualPeriod;
+
+ for (;
+ nextEndpoint;
+ endpoint = nextEndpoint,
+ nextEndpoint = nextEndpoint->NextTtEndpoint)
+ {
+ DPRINT("USB2_DeallocateEndpointBudget: endpoint - %p, nextEndpoint - %p\n",
+ endpoint,
+ nextEndpoint);
+
+ endTime = endpoint->StartTime + endpoint->CalcBusTime;
+ maxEndTime = endTime;
+
+ if (Period > nextEndpoint->ActualPeriod ||
+ TtEndpoint->StartFrame != nextEndpoint->StartFrame)
+ {
+ if (USB2_CommonFrames(nextEndpoint, TtEndpoint))
+ Factor = Period / nextEndpoint->ActualPeriod;
+ else
+ Factor = USB2_FRAMES / nextEndpoint->ActualPeriod;
+
+ maxEndTime = endTime;
+
+ for (jx = 0, frame = nextEndpoint->StartFrame;
+ jx < Factor;
+ jx++, frame += nextEndpoint->ActualPeriod)
+ {
+ if (nextEndpoint->StartFrame != TtEndpoint->StartFrame)
+ {
+ lastEndpoint = Tt->FrameBudget[frame].IntEndpoint;
+
+ if (Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint)
+ {
+ lastEndpoint = Tt->FrameBudget[frame].IsoEndpoint->NextTtEndpoint;
+ }
+ else if (Tt->FrameBudget[frame].AltEndpoint)
+ {
+ lastEndpoint = Tt->FrameBudget[frame].AltEndpoint;
+ }
+
+ for (tmpEndpoint = Tt->FrameBudget[frame].IntEndpoint->NextTtEndpoint;
+ tmpEndpoint && tmpEndpoint != nextEndpoint;
+ tmpEndpoint = tmpEndpoint->NextTtEndpoint)
+ {
+ lastEndpoint = tmpEndpoint;
+ }
+
+ lastEndTime = lastEndpoint->StartTime + lastEndpoint->CalcBusTime;
+
+ if (endTime < (lastEndTime - 1))
+ {
+ maxEndTime = lastEndTime;
+ endTime = maxEndTime;
+
+ if (nextEndpoint->StartTime == maxEndTime)
+ break;
+ }
+ else
+ {
+ maxEndTime = endTime;
+ }
+ }
+ }
+ }
+
+ if (maxEndTime >= nextEndpoint->StartTime)
+ break;
+
+ if (!USB2_MoveTtEndpoint(nextEndpoint,
+ maxEndTime - nextEndpoint->StartTime,
+ Rebalance,
+ *RebalanceListEntries,
+ &IsMoved))
+ {
+ if (!IsMoved)
+ {
+ DPRINT("USB2_DeallocateEndpointBudget: Not moved!\n");
+ }
+
+ break;
+ }
+
+ if (Period > nextEndpoint->ActualPeriod)
+ Period = nextEndpoint->ActualPeriod;
+ }
+ }
+
+ TtEndpoint->CalcBusTime = 0;
+
+ DPRINT("USB2_DeallocateEndpointBudget: return TRUE\n");
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+USB2_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
+ IN PUSB2_REBALANCE Rebalance,
+ IN PULONG RebalanceListEntries)
+{
+ PUSB2_TT Tt;
+ PUSB2_HC_EXTENSION HcExtension;
+ ULONG Speed;
+ ULONG TimeUsed;
+ ULONG MinTimeUsed;
+ ULONG ix;
+ ULONG frame;
+ ULONG uframe;
+ ULONG Microframe;
+ ULONG TransferType;
+ ULONG Overhead;
+ ULONG LatestStart;
+ PUSB2_TT_ENDPOINT prevEndpoint;
+ PUSB2_TT_ENDPOINT nextEndpoint;
+ PUSB2_TT_ENDPOINT IntEndpoint;
+ ULONG StartTime;
+ ULONG calcBusTime;
+ BOOLEAN Result = TRUE;
+
+ DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint - %p\n", TtEndpoint);
+
+ Tt = TtEndpoint->Tt;
+ HcExtension = Tt->HcExtension;
+
+ TtEndpoint->Nums.NumStarts = 0;
+ TtEndpoint->Nums.NumCompletes = 0;
+
+ TtEndpoint->StartFrame = 0;
+ TtEndpoint->StartMicroframe = 0;
+
+ if (TtEndpoint->CalcBusTime)
+ {
+ DPRINT("USB2_AllocateTimeForEndpoint: TtEndpoint already allocated!\n");
+ return FALSE;
+ }
+
+ Speed = TtEndpoint->TtEndpointParams.DeviceSpeed;
+
+ if (Speed == UsbHighSpeed)
+ {
+ if (TtEndpoint->Period > USB2_MAX_MICROFRAMES)
+ TtEndpoint->ActualPeriod = USB2_MAX_MICROFRAMES;
+ else
+ TtEndpoint->ActualPeriod = TtEndpoint->Period;
+
+ MinTimeUsed = HcExtension->TimeUsed[0][0];
+
+ for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
+ {
+ frame = ix / USB2_MICROFRAMES;
+ uframe = ix % (USB2_MICROFRAMES - 1);
+
+ TimeUsed = HcExtension->TimeUsed[frame][uframe];
+
+ if (TimeUsed < MinTimeUsed)
+ {
+ MinTimeUsed = TimeUsed;
+ TtEndpoint->StartFrame = frame;
+ TtEndpoint->StartMicroframe = uframe;
+ }
+ }
+
+ TtEndpoint->CalcBusTime = USB2_GetOverhead(TtEndpoint) +
+ USB2_AddDataBitStuff(TtEndpoint->MaxPacketSize);
+
+ DPRINT("USB2_AllocateTimeForEndpoint: StartFrame - %X, StartMicroframe - %X, CalcBusTime - %X\n",
+ TtEndpoint->StartFrame,
+ TtEndpoint->StartMicroframe,
+ TtEndpoint->CalcBusTime);
+
+ Microframe = TtEndpoint->StartFrame * USB2_MICROFRAMES +
+ TtEndpoint->StartMicroframe;
+
+ if (Microframe >= USB2_MAX_MICROFRAMES)
+ {
+ DPRINT("USB2_AllocateTimeForEndpoint: Microframe >= 256. Result - TRUE\n");
+ return TRUE;
+ }
+
+ for (ix = Microframe;
+ ix < USB2_MAX_MICROFRAMES;
+ ix += TtEndpoint->ActualPeriod)
+ {
+ frame = ix / USB2_MICROFRAMES;
+ uframe = ix % (USB2_MICROFRAMES - 1);
+
+ DPRINT("USB2_AllocateTimeForEndpoint: frame - %X, uframe - %X, TimeUsed[f][uf] - %X\n",
+ frame,
+ uframe,
+ HcExtension->TimeUsed[frame][uframe]);
+
+ if (!USB2_AllocateCheck(&HcExtension->TimeUsed[frame][uframe],
+ TtEndpoint->CalcBusTime,
+ USB2_MAX_MICROFRAME_ALLOCATION))
+ {
+ DPRINT("USB2_AllocateTimeForEndpoint: Result = FALSE\n");
+ Result = FALSE;
+ }
+ }
+
+ if (!Result)
+ {
+ for (ix = Microframe;
+ ix < USB2_MAX_MICROFRAMES;
+ ix += TtEndpoint->ActualPeriod)
+ {
+ frame = ix / USB2_MICROFRAMES;
+ uframe = ix % (USB2_MICROFRAMES - 1);
+
+ HcExtension->TimeUsed[frame][uframe] -= TtEndpoint->CalcBusTime;
+ }
+ }
+
+ DPRINT("USB2_AllocateTimeForEndpoint: Result - TRUE\n");
+ return TRUE;
+ }
+
+ /* Speed != UsbHighSpeed (FS/LS) */
+
+ if (TtEndpoint->Period > USB2_FRAMES)
+ TtEndpoint->ActualPeriod = USB2_FRAMES;
+ else
+ TtEndpoint->ActualPeriod = TtEndpoint->Period;
+
+ MinTimeUsed = Tt->FrameBudget[0].TimeUsed;
+
+ for (ix = 1; ix < TtEndpoint->ActualPeriod; ix++)
+ {
+ if ((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;
- if (DeviceSpeed == UsbHighSpeed)
+ for (ix = 0;
+ (TtEndpoint->StartFrame + ix) < USB2_FRAMES;
+ ix += TtEndpoint->ActualPeriod)
{
- if (Direction == USBPORT_TRANSFER_DIRECTION_OUT)
+ frame = TtEndpoint->StartFrame + ix;
+
+ if (Tt->FrameBudget[frame].AltEndpoint &&
+ TtEndpoint->CalcBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
{
- if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
- Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
- else
- Overhead = HostDelay + USB2_HS_INTERRUPT_OUT_OVERHEAD;
+ 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 (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
- Overhead = HostDelay + USB2_HS_ISOCHRONOUS_IN_OVERHEAD;
- else
- Overhead = HostDelay + USB2_HS_ISOCHRONOUS_OUT_OVERHEAD;
+ if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+ {
+ break;
+ }
+
+ prevEndpoint = nextEndpoint;
}
+
+ StartTime = USB2_GetStartTime(nextEndpoint,
+ TtEndpoint,
+ prevEndpoint,
+ frame);
+
+ if (StartTime > LatestStart)
+ LatestStart = StartTime;
}
- else if (DeviceSpeed == UsbFullSpeed)
+
+ TtEndpoint->StartTime = LatestStart;
+
+ if ((LatestStart + TtEndpoint->CalcBusTime) > USB2_FS_MAX_PERIODIC_ALLOCATION)
{
- if (TransferType == USBPORT_TRANSFER_TYPE_ISOCHRONOUS)
- Overhead = HostDelay + USB2_FS_ISOCHRONOUS_OVERHEAD;
- else
- Overhead = HostDelay + USB2_FS_INTERRUPT_OVERHEAD;
+ TtEndpoint->CalcBusTime = 0;
+ DPRINT("USB2_AllocateTimeForEndpoint: return FALSE\n");
+ return FALSE;
}
- else
+
+ for (ix = 0, frame = -TtEndpoint->StartFrame;
+ ix < USB2_FRAMES;
+ ix++, frame++)
{
- Overhead = HostDelay + USB2_LS_INTERRUPT_OVERHEAD;
- }
+ DPRINT("USB2_AllocateTimeForEndpoint: ix - %X, frame - %X, StartFrame - %X\n",
+ ix,
+ frame,
+ TtEndpoint->StartFrame);
- return Overhead;
-}
+ 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;
-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)
-{
- RtlZeroMemory(TtEndpoint, sizeof(USB2_TT_ENDPOINT));
+ for (nextEndpoint = IntEndpoint->NextTtEndpoint;
+ nextEndpoint;
+ nextEndpoint = nextEndpoint->NextTtEndpoint)
+ {
+ if (USB2_CheckTtEndpointInsert(nextEndpoint, TtEndpoint))
+ break;
+ IntEndpoint = nextEndpoint;
+ }
- TtEndpoint->TtEndpointParams.TransferType = TransferType;
- TtEndpoint->TtEndpointParams.Direction = Direction;
- TtEndpoint->TtEndpointParams.DeviceSpeed = DeviceSpeed;
+ if ((frame % TtEndpoint->ActualPeriod) == 0)
+ {
+ calcBusTime = 0;
+ }
+ else
+ {
+ if (nextEndpoint)
+ {
+ calcBusTime = LatestStart + TtEndpoint->CalcBusTime -
+ nextEndpoint->StartTime;
+ }
+ else
+ {
+ calcBusTime = TtEndpoint->CalcBusTime;
+ }
- TtEndpoint->Period = Period;
- TtEndpoint->MaxPacketSize = MaxPacketSize;
- TtEndpoint->Tt = Tt;
+ 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_AllocateTimeForEndpoint(IN PUSB2_TT_ENDPOINT TtEndpoint,
- IN PUSB2_REBALANCE Rebalance,
- IN PULONG RebalanceListEntries)
+USB2_ChangePeriod(IN PUSB2_TT_ENDPOINT TtEndpoint,
+ IN PUSB2_REBALANCE Rebalance,
+ IN PULONG RebalanceListEntries)
{
- DPRINT("USB2_AllocateTimeForEndpoint: UNIMPLEMENTED. FIXME\n");
- ASSERT(FALSE);
- return FALSE;
+ 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
IN PUSB2_REBALANCE Rebalance,
IN PULONG RebalanceListEntries)
{
- DPRINT1("USB2_PromotePeriods: UNIMPLEMENTED. FIXME\n");
- ASSERT(FALSE);
+ PUSB2_TT_ENDPOINT ttEndpoint;
+ ULONG TransferType;
+ ULONG ix;
+
+ TransferType = TtEndpoint->TtEndpointParams.TransferType;
+
+ if (TtEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
+ TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
+ (CHAR)TtEndpoint->StartMicroframe > 2 &&
+ !USB2_ChangePeriod(TtEndpoint, Rebalance, RebalanceListEntries))
+ {
+ DPRINT("USB2_PromotePeriods: return FALSE\n");
+ return FALSE;
+ }
+
+ if (Rebalance->RebalanceEndpoint[0] == NULL)
+ {
+ DPRINT("USB2_PromotePeriods: return TRUE\n");
+ return TRUE;
+ }
+
+ DPRINT("USB2_PromotePeriods: RebalanceListEntries - %X\n",
+ *RebalanceListEntries);
+
+ for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+ {
+ Rebalance->RebalanceEndpoint[ix]->IsPromoted = FALSE;
+ }
+
+ for (ix = 0; ; ix++)
+ {
+ ttEndpoint = Rebalance->RebalanceEndpoint[ix];
+ TransferType = ttEndpoint->TtEndpointParams.TransferType;
+
+ if (ttEndpoint->ActualPeriod != ENDPOINT_INTERRUPT_1ms &&
+ TransferType == USBPORT_TRANSFER_TYPE_INTERRUPT &&
+ ttEndpoint->StartMicroframe > 2)
+ {
+ USB2_DeallocateEndpointBudget(ttEndpoint,
+ Rebalance,
+ RebalanceListEntries,
+ USB2_FRAMES);
+
+ ttEndpoint->IsPromoted = TRUE;
+ ttEndpoint->PreviosPeriod = ttEndpoint->Period;
+ ttEndpoint->Period = ENDPOINT_INTERRUPT_1ms;
+
+ if (!USB2_AllocateTimeForEndpoint(ttEndpoint,
+ Rebalance,
+ RebalanceListEntries))
+ {
+ break;
+ }
+ }
+
+ if (Rebalance->RebalanceEndpoint[ix + 1] == NULL)
+ {
+ DPRINT("USB2_PromotePeriods: return TRUE\n");
+ return TRUE;
+ }
+ }
+
+ USB2_DeallocateEndpointBudget(TtEndpoint,
+ Rebalance,
+ RebalanceListEntries,
+ USB2_FRAMES);
+
+ TtEndpoint->Period = TtEndpoint->PreviosPeriod;
+ TtEndpoint->PreviosPeriod = 0;
+
+ for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+ {
+ ttEndpoint = Rebalance->RebalanceEndpoint[ix];
+
+ if (ttEndpoint->IsPromoted)
+ {
+ if (ttEndpoint->CalcBusTime)
+ {
+ USB2_DeallocateEndpointBudget(ttEndpoint,
+ Rebalance,
+ RebalanceListEntries,
+ USB2_FRAMES);
+ }
+
+ TtEndpoint->Period = TtEndpoint->PreviosPeriod;
+ TtEndpoint->PreviosPeriod = 0;
+
+ USB2_AllocateTimeForEndpoint(ttEndpoint,
+ Rebalance,
+ RebalanceListEntries);
+ }
+ }
+
+ DPRINT("USB2_PromotePeriods: return FALSE\n");
return FALSE;
}
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",
case UsbFullSpeed:
{
Tt = &TtExtension->Tt;
+
Period = USB2_FRAMES;
- while (Period && Period > EndpointProperties->Period);
+ while (Period > 0 && Period > EndpointProperties->Period)
{
Period >>= 1;
}
case UsbHighSpeed:
{
Tt = &FdoExtension->Usb2Extension->HcTt;
- Period = EndpointProperties->Period;
if (EndpointProperties->Period > USB2_MAX_MICROFRAMES)
Period = USB2_MAX_MICROFRAMES;
+ else
+ Period = EndpointProperties->Period;
break;
}
default:
{
- DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n", DeviceSpeed);
+ DPRINT1("USBPORT_AllocateBandwidthUSB2: DeviceSpeed - %X!\n",
+ DeviceSpeed);
+
DbgBreakPoint();
+
Tt = &TtExtension->Tt;
break;
}
for (ix = 0; ix < RebalanceListEntries; ix++)
{
- DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceEndpoint[%X] - %X\n",
- ix,
- Rebalance->RebalanceEndpoint[ix]);
-
RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
+ DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
+ ix,
+ RebalanceTtEndpoint,
+ &RebalanceTtEndpoint->Endpoint->RebalanceLink);
+
InsertTailList(&RebalanceList,
&RebalanceTtEndpoint->Endpoint->RebalanceLink);
}
if (Rebalance)
- ExFreePool(Rebalance);
+ ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
if (Result)
{
- DPRINT1("USBPORT_AllocateBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
- ASSERT(FALSE);
+ SMask = USB2_GetSMASK(Endpoint->TtEndpoint);
+ EndpointProperties->InterruptScheduleMask = SMask;
+
+ CMask = USB2_GetCMASK(Endpoint->TtEndpoint);
+ EndpointProperties->SplitCompletionMask = CMask;
+
+ AllocedBusTime = TtEndpoint->CalcBusTime;
+
+ EndpointBandwidth = USB2_MICROFRAMES * AllocedBusTime;
+ EndpointProperties->UsbBandwidth = EndpointBandwidth;
+
+ ActualPeriod = Endpoint->TtEndpoint->ActualPeriod;
+ EndpointProperties->Period = ActualPeriod;
+
+ ScheduleOffset = Endpoint->TtEndpoint->StartFrame;
+ EndpointProperties->ScheduleOffset = ScheduleOffset;
+
+ Factor = USB2_FRAMES / ActualPeriod;
+ ASSERT(Factor);
+
+ n = ScheduleOffset * Factor;
+
+ if (TtExtension)
+ {
+ for (ix = 0; ix < Factor; ix++)
+ {
+ TtExtension->Bandwidth[n + ix] -= EndpointBandwidth;
+ }
+ }
+ else
+ {
+ for (ix = 1; ix < Factor; ix++)
+ {
+ FdoExtension->Bandwidth[n + ix] -= EndpointBandwidth;
+ }
+ }
+
+ USBPORT_DumpingEndpointProperties(EndpointProperties);
+ USBPORT_DumpingTtEndpoint(Endpoint->TtEndpoint);
+
+ if (AllocedBusTime >= (USB2_FS_MAX_PERIODIC_ALLOCATION / 2))
+ {
+ DPRINT1("USBPORT_AllocateBandwidthUSB2: AllocedBusTime >= 0.5 * MAX_ALLOCATION \n");
+ }
}
- //USB2_Rebalance(FdoDevice, &RebalanceList);
+ USB2_Rebalance(FdoDevice, &RebalanceList);
if (!TtExtension)
{
USBPORT_FreeBandwidthUSB2(IN PDEVICE_OBJECT FdoDevice,
IN PUSBPORT_ENDPOINT Endpoint)
{
- DPRINT1("USBPORT_FreeBandwidthUSB2: UNIMPLEMENTED. FIXME. \n");
+ PUSBPORT_DEVICE_EXTENSION FdoExtension;
+ ULONG Period;
+ ULONG ScheduleOffset;
+ ULONG EndpointBandwidth;
+ LIST_ENTRY RebalanceList;
+ ULONG TransferType;
+ PUSB2_REBALANCE Rebalance;
+ ULONG RebalanceListEntries;
+ ULONG Factor;
+ ULONG ix;
+ ULONG n;
+ PUSB2_TT_EXTENSION TtExtension;
+ PUSB2_TT_ENDPOINT RebalanceTtEndpoint;
+
+ DPRINT("USBPORT_FreeBandwidthUSB2: Endpoint - %p\n", Endpoint);
+
+ FdoExtension = FdoDevice->DeviceExtension;
+
+ Period = Endpoint->EndpointProperties.Period;
+ ASSERT(Period != 0);
+
+ ScheduleOffset = Endpoint->EndpointProperties.ScheduleOffset;
+ EndpointBandwidth = Endpoint->EndpointProperties.UsbBandwidth;
+
+ InitializeListHead(&RebalanceList);
+
+ TransferType = Endpoint->EndpointProperties.TransferType;
+
+ if (TransferType == USBPORT_TRANSFER_TYPE_CONTROL ||
+ TransferType == USBPORT_TRANSFER_TYPE_BULK ||
+ (Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
+ {
+ return;
+ }
+
+ Rebalance = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(USB2_REBALANCE),
+ USB_PORT_TAG);
+
+ if (!Rebalance)
+ {
+ DPRINT1("USBPORT_FreeBandwidthUSB2: Rebalance == NULL!\n");
+ return;
+ }
+
+ RtlZeroMemory(Rebalance, sizeof(USB2_REBALANCE));
+
+ Factor = USB2_FRAMES / Period;
+ n = ScheduleOffset * Factor;
+
+ TtExtension = Endpoint->TtExtension;
+
+ if (TtExtension)
+ {
+ for (ix = 0; ix < Factor; ix++)
+ {
+ TtExtension->Bandwidth[n + ix] += EndpointBandwidth;
+ }
+ }
+ else
+ {
+ for (ix = 1; ix < Factor; ix++)
+ {
+ FdoExtension->Bandwidth[n + ix] += EndpointBandwidth;
+ }
+ }
+
+ RebalanceListEntries = USB2_FRAMES - 2;
+
+ USB2_DeallocateEndpointBudget(Endpoint->TtEndpoint,
+ Rebalance,
+ &RebalanceListEntries,
+ USB2_FRAMES);
+
+ RebalanceListEntries = 0;
+
+ for (ix = 0; Rebalance->RebalanceEndpoint[ix]; ix++)
+ {
+ RebalanceListEntries = ix + 1;
+ }
+
+ for (ix = 0; ix < RebalanceListEntries; ix++)
+ {
+ RebalanceTtEndpoint = Rebalance->RebalanceEndpoint[ix];
+
+ DPRINT("USBPORT_AllocateBandwidthUSB2: RebalanceTtEndpoint[%X] - %p, RebalanceTtEndpoint - %p, RebalanceLink - %p\n",
+ ix,
+ RebalanceTtEndpoint,
+ &RebalanceTtEndpoint->Endpoint->RebalanceLink);
+
+ InsertTailList(&RebalanceList,
+ &RebalanceTtEndpoint->Endpoint->RebalanceLink);
+ }
+
+ ExFreePoolWithTag(Rebalance, USB_PORT_TAG);
+
+ USB2_Rebalance(FdoDevice, &RebalanceList);
+
+ if (!TtExtension)
+ {
+ return;
+ }
+
+ for (ix = 0; ix < USB2_FRAMES; ix++)
+ {
+ FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
+ }
+
+ USBPORT_UpdateAllocatedBwTt(TtExtension);
+
+ for (ix = 0; ix < USB2_FRAMES; ix++)
+ {
+ FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
+ }
+
+ DPRINT1("USBPORT_FreeBandwidthUSB2: exit\n");
}
VOID