USB2_RebalanceEndpoint(IN PDEVICE_OBJECT FdoDevice,
IN PLIST_ENTRY List)
{
- DPRINT1("USB2_RebalanceEndpoint: UNIMPLEMENTED. FIXME\n");
- ASSERT(FALSE);
+ 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
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\n",
+ DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint - %p, MaxFrames - %X, CalcBusTime - %X\n",
TtEndpoint,
- MaxFrames);
+ MaxFrames,
+ TtEndpoint->CalcBusTime);
if (TtEndpoint->CalcBusTime == 0)
{
- DPRINT("USB2_DeallocateEndpointBudget: endpoint not allocated\n");//error((int)"endpoint not allocated");
+ DPRINT("USB2_DeallocateEndpointBudget: TtEndpoint not allocated!\n");
return FALSE;
}
/* Speed != UsbHighSpeed (FS/LS) */
- DPRINT("USB2_DeallocateEndpointBudget: UNIMPLEMENTED FIXME\n");
- ASSERT(FALSE);
+ 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;
}
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)
{
- 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;
}
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