📄 usb2lib.cpp
字号:
/*******
Compute_nonsplit_overhead
********/
int USB2lib::Compute_nonsplit_overhead(LPEndpointBuget ep)
{
if (ep->speed == HSSPEED)
{
if (ep->direction == OUTDIR)
{
if (ep->ep_type == isoch)
{
return HS_TOKEN_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD + thinktime;
} else // interrupt
{
return HS_TOKEN_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD +
HS_HANDSHAKE_OVERHEAD + thinktime;
}
} else
{ // IN
if (ep->ep_type == isoch)
{
return HS_TOKEN_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD + thinktime;
} else // interrupt
{
return HS_TOKEN_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD +
HS_HANDSHAKE_OVERHEAD + thinktime;
}
} // end of IN overhead calculations
} else if (ep->speed == FSSPEED)
{
if (ep->ep_type == isoch)
{
return FS_ISOCH_OVERHEAD + thinktime;
} else // interrupt
{
return FS_INT_OVERHEAD + thinktime;
}
} else // LS
{
return LS_INT_OVERHEAD + thinktime;
}
}
int USB2lib::AllocUsb2BusTime( IN const UCHAR uHubAddress,IN const UCHAR uHubPort,LPEndpointBuget ep)
{
int retv;
unsigned changed_eps, i, min_used;
//PEndpoint curr_ep, last_ep, p;
changed_eps = 0;
retv = 1;
Lock();
// OVERVIEW of algorithm steps:
// 1. Determine starting frame # for period
// 2. Calculate classic time required
// 3. For all period frames, find the latest starting time so we can check the classic allocation later
// 4. Process each frame data structure for endpoint period in budget window
// 5. Now check allocation for each frame using shift adjustment based on latest start time
// 6a. Now move isoch endpoints, insert new isoch and then move interrupt endpoints
// 6b. Now insert new interrupt and move rest of interrupt endpoints
// 7. Allocate HS bus time
// 8. Allocate classic bus time
//***
//*** 1. Determine starting frame # for period
//***
// Also remember the maximum frame time allocation since it will be used to pass the allocation check.
// Find starting frame number for reasonable balance of all classic frames
ep->start_frame = 0;
ep->start_microframe = 0;
ep->num_completes = 0;
ep->num_starts = 0;
// check that this endpoint isn't already allocated
if (ep->calc_bus_time)
{
DEBUGMSG(1,(TEXT("endpoint already allocated\r\n")));
ASSERT(FALSE);
Unlock();
return 0;
}
// handle nonsplit HS allocation
if (ep->speed == HSSPEED) {
min_used = HS_microframe_info[0][0].time_used;
if (ep->period > MAXFRAMES*MICROFRAMES_PER_FRAME)
ep->actual_period = MAXFRAMES*MICROFRAMES_PER_FRAME;
else
ep->actual_period = ep->period;
// Look at all candidate frames for this period to find the one with min
// allocated bus time.
//
for (i=1; i < ep->actual_period; i++){
if (HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used < min_used)
{
min_used = HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used;
ep->start_frame = i/MICROFRAMES_PER_FRAME;
ep->start_microframe = i % MICROFRAMES_PER_FRAME;
}
}
// compute and allocate HS bandwidth
ep->calc_bus_time = Compute_nonsplit_overhead(ep) + Add_bitstuff(ep->max_packet);
for (i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
i < MAXFRAMES*MICROFRAMES_PER_FRAME;
i += ep->actual_period){
HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used +=ep->calc_bus_time;
if (HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used >HS_MAX_PERIODIC_ALLOCATION)
retv = 0;
}
if (! retv) // if allocation failed, deallocate
{
for (i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
i < MAXFRAMES*MICROFRAMES_PER_FRAME;
i += ep->actual_period){
HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used -= ep->calc_bus_time;
}
}
Unlock();
return retv;
}
// above handles all speeds, the rest of this code is for split transaction processing
//***
//*** 2. Calculate classic time required
//***
TransactionTrasnlate * pTT=GetTT( uHubAddress,uHubPort);
if (pTT== NULL || pTT->AddedEp(ep)!=TRUE) {
Unlock();
return 0;
}
if ((ep->start_time + ep->calc_bus_time) > FS_MAX_PERIODIC_ALLOCATION)
{
// error("start time %d past end of frame", ep->start_time + ep->calc_bus_time);
ep->calc_bus_time = 0;
Unlock();
return 0;
}
ep->start_microframe = (ep->start_time / FS_BYTES_PER_MICROFRAME) - 1;
UCHAR lastcs = (UCHAR)(( (ep->start_time + ep->calc_bus_time) / FS_BYTES_PER_MICROFRAME) + 1);
// determine number of splits (starts and completes)
if (ep->direction == OUTDIR) {
if (ep->ep_type == isoch)
{
ep->num_starts = (ep->max_packet / FS_BYTES_PER_MICROFRAME) + 1;
ep->num_completes = 0;
} else // interrupt
{
ep->num_starts = 1;
ep->num_completes = 2;
if (ep->start_microframe + 1 < 6)
ep->num_completes++;
}
} else { // IN
if (ep->ep_type == isoch) {
ep->num_starts = 1;
ep->num_completes = lastcs - (ep->start_microframe + 1);
if (lastcs <= 6)
{
if ((ep->start_microframe + 1) == 0)
ep->num_completes++;
else
ep->num_completes += 2; // this can cause one CS to be in the next frame
}
else if (lastcs == 7)
{
if ((ep->start_microframe + 1) != 0)
ep->num_completes++; // only one more CS if late in the frame.
}
} else // interrupt
{
ep->num_starts = 1;
ep->num_completes = 2;
if (ep->start_microframe + 1 < 6)
ep->num_completes++;
}
} // end of IN
Unlock();
return retv;
}
void USB2lib::FreeUsb2BusTime(IN const UCHAR uHubAddress,IN const UCHAR uHubPort, LPEndpointBuget ep)
{
Lock();
if (ep && ep->calc_bus_time!=0){
// handle nonsplit HS allocation
if (ep->speed == HSSPEED) {
for (DWORD i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
i < MAXFRAMES*MICROFRAMES_PER_FRAME;
i += ep->actual_period){
if (HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used >= ep->calc_bus_time)
HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used -= ep->calc_bus_time;
else {
ASSERT(FALSE);
HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used =0;
}
}
}
else {
TransactionTrasnlate * pTT=GetTT( uHubAddress,uHubPort);
if (pTT!=NULL)
pTT->DeletedEp(ep);
}
}
Unlock();
}
UCHAR USB2lib::GetSMASK(LPEndpointBuget Ep)
{
UCHAR tmp = 0;
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;
};
UCHAR USB2lib::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(LPEndpointBuget 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;
}
}
VOID
USB2lib::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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -