You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
769 lines
19 KiB
769 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
usb2lib.c
|
|
|
|
Abstract:
|
|
|
|
interface to usb2lib, usb2 low/full speed scheduling algorithms
|
|
|
|
Environment:
|
|
|
|
kernel or user mode only
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
10-31-00 : created
|
|
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
USB2LIB_DATA LibData;
|
|
|
|
|
|
VOID
|
|
USB2LIB_InitializeLib(
|
|
PULONG HcContextSize,
|
|
PULONG EndpointContextSize,
|
|
PULONG TtContextSize,
|
|
PUSB2LIB_DBGPRINT Usb2LibDbgPrint,
|
|
PUSB2LIB_DBGBREAK Usb2LibDbgBreak
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
*HcContextSize = sizeof(USB2LIB_HC_CONTEXT);
|
|
*TtContextSize = sizeof(USB2LIB_TT_CONTEXT);
|
|
*EndpointContextSize = sizeof(USB2LIB_ENDPOINT_CONTEXT);
|
|
|
|
LibData.DbgPrint = Usb2LibDbgPrint;
|
|
LibData.DbgBreak = Usb2LibDbgBreak;
|
|
}
|
|
|
|
|
|
VOID
|
|
USB2LIB_InitController(
|
|
PUSB2LIB_HC_CONTEXT HcContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called at init time for an instance of the USB 2
|
|
controller
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBGPRINT(("USB2LIB_InitController %x\n", HcContext));
|
|
|
|
HcContext->Sig = SIG_LIB_HC;
|
|
init_hc(&HcContext->Hc);
|
|
init_tt(&HcContext->Hc, &HcContext->DummyTt); // set up dummy TT for use by HS endpoints
|
|
}
|
|
|
|
|
|
VOID
|
|
USB2LIB_InitTt(
|
|
PUSB2LIB_HC_CONTEXT HcContext,
|
|
PUSB2LIB_TT_CONTEXT TtContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBGPRINT(("USB2LIB_InitTt %x %x\n", HcContext, TtContext));
|
|
|
|
TtContext->Sig = SIG_LIB_TT;
|
|
init_tt(&HcContext->Hc, &TtContext->Tt);
|
|
}
|
|
|
|
|
|
#if 1
|
|
void Shift_to_list_end(
|
|
int move_ep,
|
|
PEndpoint RebalanceList[]
|
|
)
|
|
{
|
|
// int i;
|
|
PEndpoint ep = RebalanceList[move_ep];
|
|
|
|
move_ep++;
|
|
while (RebalanceList[move_ep])
|
|
{
|
|
RebalanceList[move_ep-1] = RebalanceList[move_ep];
|
|
move_ep++;
|
|
}
|
|
RebalanceList[move_ep-1] = ep;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
Promote_endpoint_periods(
|
|
PEndpoint ep,
|
|
PEndpoint RebalanceList[],
|
|
PULONG RebalanceListEntries
|
|
)
|
|
{
|
|
int unwind = 0, check_ep;
|
|
unsigned result;
|
|
|
|
if ((ep->actual_period != 1) && (ep->ep_type == interrupt) && (ep->start_microframe > 2))
|
|
{
|
|
DBGPRINT((">Period Promotion of allocated endpoint\n"));
|
|
|
|
// To promote an endpoint period:
|
|
// 0) unwind = false
|
|
// 1) deallocate original endpoint
|
|
// 2) change new ep period to 1
|
|
// 3) (re)allocate new endpoint (with new period 1)
|
|
// 4) if successful
|
|
// 5) check endpoints in change list for need of period promotion
|
|
// 6) deallocate endpoint, move to end of change list, change period to 1, reallocate
|
|
// 7) if unsuccessful
|
|
// 8) unwind = true; break
|
|
// 9) next ep
|
|
//10) if unwind
|
|
//11) deallocate orginal ep
|
|
//12) check change list for promotion endpoint(s)
|
|
//13) if promoted ep
|
|
//14) deallocate ep, change back to original period, allocate
|
|
//15) next ep
|
|
//16) return false
|
|
//17) else return true
|
|
//18) else return false
|
|
|
|
/*
|
|
// On return, change list will have promoted endpoints in order of reallocation, but it is possible
|
|
// to have other endpoints interspersed with the promoted endpoints. The corresponding schedule of endpoints
|
|
// must be adjusted to match the order of the promoted endpoints (since they are reinserted into the budget).
|
|
// The promoted endpoints (except the original endpoint) are moved to the end of the change list as the
|
|
// promotion reallocations are done to ensure that they are in the change list in the order of insertion
|
|
// into the budget. This allows the scheduler to derive the new schedule/budget order from the order the
|
|
// promoted endpoints appear in the change list.
|
|
//
|
|
// This algorithm (critically) depends on the Allocate/Deallocate "appending"/reusing an existing change list
|
|
// as the "final" change list is composed during the period promotion processing is performed.
|
|
*/
|
|
|
|
Deallocate_time_for_endpoint(ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
ep->saved_period = ep->period;
|
|
ep->period = 1;
|
|
|
|
// 3) (re)allocate new endpoint (with new period 1)
|
|
result = Allocate_time_for_endpoint(ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
if (!result) {
|
|
ep->period = ep->saved_period;
|
|
ep->saved_period = 0;
|
|
ep->promoted_this_time = 0;
|
|
return 0; // failed period promotion of original endpoint
|
|
}
|
|
}
|
|
|
|
check_ep = 0;
|
|
while (RebalanceList[check_ep])
|
|
{
|
|
RebalanceList[check_ep]->promoted_this_time = 0;
|
|
check_ep++;
|
|
}
|
|
|
|
check_ep = 0;
|
|
while (RebalanceList[check_ep])
|
|
{
|
|
if ((RebalanceList[check_ep]->actual_period != 1) &&
|
|
(RebalanceList[check_ep]->ep_type == interrupt) &&
|
|
(RebalanceList[check_ep]->start_microframe > 2))
|
|
{
|
|
|
|
// 6) deallocate endpoint, move to end of change list, change period to 1, reallocate
|
|
|
|
DBGPRINT((">Period Promoting endpoint\n"));
|
|
|
|
Deallocate_time_for_endpoint(
|
|
RebalanceList[check_ep],
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
// Shift_to_list_end(check_ep, RebalanceList);
|
|
|
|
RebalanceList[check_ep]->promoted_this_time = 1;
|
|
|
|
RebalanceList[check_ep]->saved_period = RebalanceList[check_ep]->period;
|
|
RebalanceList[check_ep]->period = 1;
|
|
|
|
result = Allocate_time_for_endpoint(
|
|
RebalanceList[check_ep],
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
if (!result)
|
|
{
|
|
unwind = 1;
|
|
break;
|
|
}
|
|
}
|
|
check_ep++;
|
|
}
|
|
|
|
if (unwind)
|
|
{
|
|
|
|
DBGPRINT((">Unwinding Promoted endpoints\n"));
|
|
|
|
//11) deallocate orginal ep
|
|
Deallocate_time_for_endpoint(
|
|
ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
ep->period = ep->saved_period;
|
|
ep->saved_period = 0;
|
|
|
|
//12) check change list for promotion endpoint(s)
|
|
|
|
check_ep = 0;
|
|
|
|
while (RebalanceList[check_ep])
|
|
{
|
|
|
|
//13) if promoted ep
|
|
|
|
if (RebalanceList[check_ep]->promoted_this_time)
|
|
{
|
|
|
|
//14) deallocate ep, change back to original period, allocate
|
|
|
|
DBGPRINT((">Reallocating Unpromoted endpoint\n"));
|
|
|
|
if(RebalanceList[check_ep]->calc_bus_time != 0)
|
|
Deallocate_time_for_endpoint(
|
|
RebalanceList[check_ep],
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
RebalanceList[check_ep]->period = RebalanceList[check_ep]->saved_period;
|
|
RebalanceList[check_ep]->saved_period = 0;
|
|
|
|
// Leave the promoted flag set since order could have changed.
|
|
// schedule must be reconciled accordingly by the HC code.
|
|
//RebalanceList[check_ep]->promoted_this_time = 0;
|
|
|
|
result = Allocate_time_for_endpoint(
|
|
RebalanceList[check_ep],
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
}
|
|
check_ep++;
|
|
}
|
|
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
USB2LIB_AllocUsb2BusTime(
|
|
PUSB2LIB_HC_CONTEXT HcContext,
|
|
PUSB2LIB_TT_CONTEXT TtContext,
|
|
PUSB2LIB_ENDPOINT_CONTEXT EndpointContext,
|
|
PUSB2LIB_BUDGET_PARAMETERS Budget,
|
|
PVOID RebalanceContext,
|
|
PVOID RebalanceList,
|
|
PULONG RebalanceListEntries
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
eptype endpointType;
|
|
unsigned direction, speed;
|
|
//PEndpoint changed_ep_list[];
|
|
unsigned result;
|
|
//unsigned changed_eps;
|
|
PEndpoint ep;
|
|
BOOLEAN alloced;
|
|
ULONG ilop;
|
|
PREBALANCE_LIST rbl;
|
|
PTT tt;
|
|
|
|
ep = &EndpointContext->Ep;
|
|
EndpointContext->Sig = SIG_LIB_EP;
|
|
EndpointContext->RebalanceContext = RebalanceContext;
|
|
|
|
//changed_ep_list = RebalanceList;
|
|
|
|
switch (Budget->TransferType) {
|
|
case Budget_Iso:
|
|
DBGPRINT((">Iso \n"));
|
|
endpointType = isoch;
|
|
break;
|
|
case Budget_Interrupt:
|
|
DBGPRINT((">Interrupt \n"));
|
|
endpointType = interrupt;
|
|
break;
|
|
default:
|
|
TEST_TRAP();
|
|
}
|
|
|
|
if (Budget->Direction == Budget_In) {
|
|
DBGPRINT((">In \n"));
|
|
direction = INDIR;
|
|
} else {
|
|
DBGPRINT((">Out \n"));
|
|
direction = OUTDIR;
|
|
}
|
|
|
|
switch (Budget->Speed) {
|
|
case Budget_FullSpeed:
|
|
DBGPRINT((">FullSpeed \n"));
|
|
speed = FSSPEED;
|
|
tt = &TtContext->Tt;
|
|
break;
|
|
case Budget_HighSpeed:
|
|
DBGPRINT((">HighSpeed \n"));
|
|
speed = HSSPEED;
|
|
tt = &HcContext->DummyTt; // set endpoint to dummy TT so HC can be reached
|
|
break;
|
|
case Budget_LowSpeed:
|
|
DBGPRINT((">LowSpeed \n"));
|
|
speed = LSSPEED;
|
|
tt = &TtContext->Tt;
|
|
break;
|
|
default:
|
|
DBGPRINT(("BAD SPEED\n"));
|
|
}
|
|
|
|
DBGPRINT((">Period %d\n", Budget->Period));
|
|
|
|
if(Budget->Speed == Budget_HighSpeed) {
|
|
// This value should be a power of 2, so we don't have to check
|
|
// but limit its value to MAXFRAMES * 8
|
|
if(Budget->Period > MAXMICROFRAMES) {
|
|
Budget->Period = MAXMICROFRAMES;
|
|
}
|
|
} else {
|
|
// We are full / low speed endpoint
|
|
//
|
|
// Round down the period to the nearest power of two (if it isn't already)
|
|
//
|
|
for(ilop = MAXFRAMES; ilop >= 1; ilop = ilop >> 1) {
|
|
if(Budget->Period >= ilop) {
|
|
break;
|
|
}
|
|
}
|
|
Budget->Period = ilop;
|
|
}
|
|
|
|
DBGPRINT((">MaxPacket %d\n", Budget->MaxPacket));
|
|
DBGPRINT((">Converted Period %d\n", Budget->Period));
|
|
DBGPRINT((">RebalanceListEntries %d\n", *RebalanceListEntries));
|
|
|
|
Set_endpoint(
|
|
ep,
|
|
endpointType,
|
|
direction,
|
|
speed,
|
|
Budget->Period,
|
|
Budget->MaxPacket,
|
|
tt);
|
|
|
|
// ask John Garney to do the math
|
|
DBGPRINT((">alloc (ep) %x \n", ep));
|
|
result = Allocate_time_for_endpoint(ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
// check if successful, period != 1, interrupt, and "late" in frame,
|
|
// then need to promote period to 1
|
|
// DBGPRINT((">Executing Promote_endpoint_periods (ep) %x \n", ep));
|
|
if (result)
|
|
{
|
|
result = Promote_endpoint_periods(ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
}
|
|
|
|
// nonzero indicates success
|
|
if (result) {
|
|
// set return parameters
|
|
DBGPRINT((">Results\n"));
|
|
DBGPRINT((">num_starts %d \n", ep->num_starts));
|
|
DBGPRINT((">num_completes %d \n", ep->num_completes));
|
|
DBGPRINT((">start_microframe %d \n", ep->start_microframe));
|
|
// this is the schedule offset
|
|
DBGPRINT((">start_frame %d \n", ep->start_frame));
|
|
// period awarded, may be less than requested
|
|
DBGPRINT((">actual_period %d \n", ep->actual_period));
|
|
DBGPRINT((">start_time %d \n", ep->start_time));
|
|
DBGPRINT((">calc_bus_time %d \n", ep->calc_bus_time));
|
|
DBGPRINT((">promoted_this_time %d \n", ep->promoted_this_time));
|
|
|
|
alloced = TRUE;
|
|
} else {
|
|
alloced = FALSE;
|
|
}
|
|
|
|
// fix up rebalance list
|
|
rbl = RebalanceList;
|
|
ilop = 0;
|
|
while (rbl->RebalanceContext[ilop]) {
|
|
PUSB2LIB_ENDPOINT_CONTEXT endpointContext;
|
|
PEndpoint rep;
|
|
|
|
DBGPRINT((">rb[%d] %x\n", ilop, rbl->RebalanceContext[ilop]));
|
|
endpointContext = CONTAINING_RECORD(rbl->RebalanceContext[ilop],
|
|
struct _USB2LIB_ENDPOINT_CONTEXT,
|
|
Ep);
|
|
|
|
rep = &endpointContext->Ep;
|
|
|
|
DBGPRINT((">rb Results\n"));
|
|
DBGPRINT((">rb num_starts %d \n", rep->num_starts));
|
|
DBGPRINT((">rb num_completes %d \n", rep->num_completes));
|
|
DBGPRINT((">rb start_microframe %d \n", rep->start_microframe));
|
|
// this is the schedule offset
|
|
DBGPRINT((">rb start_frame %d \n", rep->start_frame));
|
|
// period awarded, may be less than requested
|
|
DBGPRINT((">rb actual_period %d \n", rep->actual_period));
|
|
DBGPRINT((">rb start_time %d \n", rep->start_time));
|
|
DBGPRINT((">rb calc_bus_time %d \n", rep->calc_bus_time));
|
|
DBGPRINT((">rb promoted_this_time %d \n", rep->promoted_this_time));
|
|
|
|
rbl->RebalanceContext[ilop] = endpointContext->RebalanceContext;
|
|
ilop++;
|
|
}
|
|
|
|
DBGPRINT((">Change List Size = %d RBE = %d\n", ilop, *RebalanceListEntries));
|
|
|
|
*RebalanceListEntries = ilop;
|
|
return alloced;
|
|
}
|
|
|
|
|
|
VOID
|
|
USB2LIB_FreeUsb2BusTime(
|
|
PUSB2LIB_HC_CONTEXT HcContext,
|
|
PUSB2LIB_TT_CONTEXT TtContext,
|
|
PUSB2LIB_ENDPOINT_CONTEXT EndpointContext,
|
|
PVOID RebalanceList,
|
|
PULONG RebalanceListEntries
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
unsigned result;
|
|
PEndpoint ep;
|
|
PREBALANCE_LIST rbl;
|
|
ULONG i;
|
|
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
ep = &EndpointContext->Ep;
|
|
|
|
DBGPRINT((">dealloc ep Context = 0x%x (ep) %x \n", EndpointContext, ep));
|
|
DBGPRINT((">RebalanceListEntries %d \n", *RebalanceListEntries));
|
|
|
|
Deallocate_time_for_endpoint(ep,
|
|
RebalanceList,
|
|
RebalanceListEntries);
|
|
|
|
// fix up rebalance list
|
|
rbl = RebalanceList;
|
|
i = 0;
|
|
while (rbl->RebalanceContext[i]) {
|
|
PUSB2LIB_ENDPOINT_CONTEXT endpointContext;
|
|
|
|
DBGPRINT((">rb[%d] %x\n", i, rbl->RebalanceContext[i]));
|
|
endpointContext = CONTAINING_RECORD(rbl->RebalanceContext[i],
|
|
struct _USB2LIB_ENDPOINT_CONTEXT,
|
|
Ep);
|
|
rbl->RebalanceContext[i] = endpointContext->RebalanceContext;
|
|
i++;
|
|
}
|
|
DBGPRINT((">Change List Size = %d RBE = %d\n", i, *RebalanceListEntries));
|
|
|
|
*RebalanceListEntries = i;
|
|
}
|
|
|
|
VOID
|
|
ConvertBtoHFrame(UCHAR BFrame, UCHAR BUFrame, PUCHAR HFrame, PUCHAR HUFrame)
|
|
{
|
|
// The budgeter returns funky values that we have to convert to something
|
|
// that the host controller understands.
|
|
// If bus micro frame is -1, that means that the start split is scheduled
|
|
// in the last microframe of the previous bus frame.
|
|
// to convert to hframes, you simply change the microframe to 0 and
|
|
// keep the bus frame (see one of the tables in the host controller spec
|
|
// eg 4-17.
|
|
if(BUFrame == 0xFF) {
|
|
*HUFrame = 0;
|
|
*HFrame = BFrame;
|
|
}
|
|
|
|
// if the budgeter returns a value in the range from 0-6
|
|
// we simply add one to the bus micro frame to get the host
|
|
// microframe
|
|
if(BUFrame >= 0 && BUFrame <= 6) {
|
|
*HUFrame = BUFrame + 1;
|
|
*HFrame = BFrame;
|
|
}
|
|
|
|
// if the budgeter returns a value of 7 for the bframe
|
|
// then the HUframe = 0 and the HUframe = buframe +1
|
|
if(BUFrame == 7) {
|
|
*HUFrame = 0;
|
|
*HFrame = BFrame + 1;
|
|
}
|
|
}
|
|
|
|
UCHAR
|
|
USB2LIB_GetSMASK(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
UCHAR tmp = 0;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
if(Ep->speed == HSSPEED) {
|
|
//DBGPRINT(("in GetSMASK StartUFrame on High Speed Endpoint = 0x%x\n", Ep->start_microframe));
|
|
tmp |= 1 << Ep->start_microframe;
|
|
} else {
|
|
ULONG ilop;
|
|
UCHAR HFrame; // H (Host) frame for endpoint
|
|
UCHAR HUFrame; // H (Host) micro frame for endpoint
|
|
// For Full and Low Speed Endpoints
|
|
// the budgeter returns a bframe. Convert to HUFrame to get SMASK
|
|
ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe, &HFrame, &HUFrame);
|
|
|
|
for(ilop = 0; ilop < Ep->num_starts; ilop++) {
|
|
tmp |= 1 << HUFrame++;
|
|
}
|
|
}
|
|
|
|
return tmp;
|
|
}
|
|
|
|
//
|
|
// I'm too brain dead to calculate this so just do table lookup
|
|
//
|
|
// Calculated by 1 << Start H Frame + 2. If Start H Frame + 2 > 7 wrap the bits
|
|
// to the lower part of the word
|
|
// eg. hframe 0 +2 means cmask in frames 2,3,4 ==> cmask 0x1c
|
|
// eg. hframe 5 + 2 means cmasks in frames 7, 8, 9 which means cmask 0x83
|
|
#define SIZE_OF_CMASK 8
|
|
static UCHAR CMASKS [SIZE_OF_CMASK] =
|
|
{ 0x1c, // Start HUFRAME 0
|
|
0x38, // Start HUFRAME 1
|
|
0x70, // Start HUFRAME 2
|
|
0xE0, // Start HUFRAME 3
|
|
0xC1, // Start HUFRAME 4
|
|
0x83, // Start HUFRAME 5
|
|
0x07, // Start HUFRAME 6
|
|
0x0E, // Start HUFRAME 7
|
|
};
|
|
|
|
|
|
UCHAR
|
|
USB2LIB_GetCMASK(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
if(Ep->speed == HSSPEED) {
|
|
return 0;
|
|
} else if(Ep->ep_type == interrupt) {
|
|
UCHAR HFrame; // H (Host) frame for endpoint
|
|
UCHAR HUFrame; // H (Host) micro frame for endpoint
|
|
|
|
ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
|
|
&HFrame, &HUFrame);
|
|
|
|
return CMASKS[HUFrame];
|
|
} else {
|
|
// Split ISO!
|
|
UCHAR HFrame; // H (Host) frame for endpoint
|
|
UCHAR HUFrame; // H (Host) micro frame for endpoint
|
|
UCHAR tmp = 0;
|
|
ULONG NumCompletes;
|
|
|
|
if(Ep->direction == OUTDIR) {
|
|
// Split iso out -- NO complete splits
|
|
return 0;
|
|
}
|
|
ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
|
|
&HFrame, &HUFrame);
|
|
|
|
HUFrame += 2;
|
|
NumCompletes = Ep->num_completes;
|
|
|
|
// ASSERT(NumCompletes > 0);
|
|
|
|
//
|
|
// Set all CMASKS bits to be set at the end of the frame
|
|
//
|
|
for(; HUFrame < 8; HUFrame++) {
|
|
tmp |= 1 << HUFrame;
|
|
NumCompletes--;
|
|
if(!NumCompletes){
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now set all CMASKS bits to be set at the end of the
|
|
// frame I.E. for the next frame wrap condition
|
|
//
|
|
while(NumCompletes) {
|
|
tmp |= 1 << (HUFrame - 8);
|
|
NumCompletes--;
|
|
}
|
|
|
|
//DBGPRINT(("in GetCMASK HFRAME = 0x%x HUFRAME 0x%x\n", HFrame, HUFrame));
|
|
return tmp;
|
|
}
|
|
}
|
|
|
|
UCHAR
|
|
USB2LIB_GetStartMicroFrame(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
UCHAR HFrame; // H (Host) frame for endpoint
|
|
UCHAR HUFrame; // H (Host) micro frame for endpoint
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
|
|
&HFrame, &HUFrame);
|
|
|
|
return HUFrame;
|
|
}
|
|
|
|
UCHAR
|
|
USB2LIB_GetPromotedThisTime(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
UCHAR Promoted = 0;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
Promoted = (UCHAR) Ep->promoted_this_time;
|
|
|
|
Ep->promoted_this_time = 0;
|
|
|
|
return Promoted;
|
|
}
|
|
|
|
UCHAR
|
|
USB2LIB_GetNewPeriod(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// ASSERT(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
return (UCHAR) Ep->actual_period;
|
|
}
|
|
|
|
|
|
ULONG
|
|
USB2LIB_GetScheduleOffset(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// assert(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
return Ep->start_frame;
|
|
}
|
|
|
|
PVOID
|
|
USB2LIB_GetEndpoint(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
return &(EndpointContext->Ep);
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
USB2LIB_GetAllocedBusTime(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
// assert(EndpointContext->Sig == SIG_LIB_EP);
|
|
|
|
return Ep->calc_bus_time;
|
|
}
|
|
|
|
|
|
PVOID
|
|
USB2LIB_GetNextEndpoint(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
|
|
{
|
|
PEndpoint Ep, nextEp;
|
|
PUSB2LIB_ENDPOINT_CONTEXT nextContext;
|
|
|
|
Ep = &EndpointContext->Ep;
|
|
nextEp = Ep->next_ep;
|
|
|
|
if (nextEp) {
|
|
|
|
nextContext = CONTAINING_RECORD(nextEp,
|
|
struct _USB2LIB_ENDPOINT_CONTEXT,
|
|
Ep);
|
|
// assert(EndpointContext->Sig == SIG_LIB_EP);
|
|
return nextContext->RebalanceContext;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|