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

📄 usb2lib.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 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 + -