⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb2lib.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:


/*******

	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 + -