pmudll.cpp

来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 667 行 · 第 1/2 页

CPP
667
字号
 *         91000, 104000, 117000, 130000, 143000,
 *         156000, 169000, 182000, 195000,
 *         208000, 377000, 390000, 403000};
 */

    static unsigned long FreqArray[MAXFREQS] =
    {104000, 117000, 130000, 143000,
        156000, 169000, 182000, 195000};


    unsigned int    i;

    if (numberfreqs > MAXFREQS)
    {
        return FAILURE_PMU;
    }

    //
    // Calculate possible frequencies
    //
    for (i=0; i < numberfreqs; i++)
    {
        FrequencyArray[i] = FreqArray[i];
    }

    return SUCCESS_PMU;
}

//------------------------------------------------------------------------------
//
//  Function:  GetNominalCoreClockFrequency
//
//  Returns the nominal or default runtime frequency (in KHz).
//
unsigned long WINAPI GetNominalCoreClockFrequency(void)
{
    return 208000;
}


//------------------------------------------------------------------------------
//
//  Function:  GetCurrentCoreClockFrequency
//
//  Returns the current core clock frequency (in KHz).
//
unsigned long WINAPI GetCurrentCoreClockFrequency(void)
{

    PMUCCFInfo      PMUCCFBuffer;
    unsigned long   CurFrequency,
                    nOutBytes;
    BOOL            rtnvalue = FALSE;

    //
    // This API calls KernelIoControl to access to get
    // the current core clock frequency.
    // This in turn calls the OEMIoControl routine.  
    // Note, the system is fully preemptible when this
    // routine is called.
    //

    //
    // Set the subcode for get ccf
    //
    PMUCCFBuffer.subcode = PMU_CCF_GETCURRENT;
    rtnvalue = 
        KernelIoControl (IOCTL_PMU_CCF, (void *)&PMUCCFBuffer, sizeof(PMUCCFInfo), 
                         &CurFrequency, sizeof(CurFrequency), &nOutBytes);

    if (rtnvalue && (nOutBytes == sizeof(unsigned long)))
    {
        return CurFrequency;
    }
    else
    {
        return 0;
    }
}


//------------------------------------------------------------------------------
//
//  Function:  SaveSetAndLockCoreClockFrequency
//
//  This function acquires ownership of the core clock frequency,
//  sets a new core clock frequency, and requests that the OS not change
//  the core clock until after the UnlockandRestoreCoreClockFrequency is called. 
//  
//  A callback routine is registered with the OS.  If the OS must change the
//  core clock frequency, then it needs to invoke the callback routine before
//  changing it. The will notify VTune to gracefully stop the data collection.
// 
STATUS_PMU WINAPI SaveSetAndLockCoreClockFrequency(
    PMUHandle handle,
    unsigned long NewFrequency, 
    void (*pCallBack)(void))
{

    PMUCCFInfo      PMUCCFBuffer;
    BOOL            rtnvalue = FALSE;

    if (handle == 0)
    {
        return INVALIDHANDLE_PMU;
    }

    //
    // Map callback address to virtual address slot of current process
    //
    PVTuneReleaseCCF = MapPtrToProcess(pCallBack, GetCurrentProcess());

    //
    // This API calls KernelIoControl to save, set, and
    // lock the core clock frequency.
    //
    // Note, the system is fully preemptible when this
    // routine is called.
    //

    //
    // Set the subcode for save, set, and lock CCF
    //
    PMUCCFBuffer.subcode = PMU_CCF_SETLOCK;
    PMUCCFBuffer.newFreq = NewFrequency;
    PMUCCFBuffer.pCallback = PVTuneReleaseCCF;

    rtnvalue = 
        KernelIoControl (IOCTL_PMU_CCF, (void *)&PMUCCFBuffer, sizeof(PMUCCFInfo), 
                         (LPVOID)NULL, 0, (LPDWORD)NULL);

    if (rtnvalue == FALSE)
    {
        return KERNELIOFAILED_PMU;
    }

    return SUCCESS_PMU;

}


//------------------------------------------------------------------------------
//
//  Function:  UnlockAndRestoreCoreClockFrequency
//
//  Unregister the callback routine, relinquishes core clock resource ownership,
//  and requests that the OS restore the core clock frequency as it was before
//  the SaveSetandLock... call
//
unsigned long WINAPI UnlockAndRestoreCoreClockFrequency(
    PMUHandle handle
    )
{
    PMUCCFInfo      PMUCCFBuffer;
    BOOL            rtnvalue = FALSE;

    if (handle == 0)
    {
        return 0;
    }

    PVTuneReleaseCCF = NULL;

    //
    // This API calls KernelIoControl to unlock and
    // restore the previous core clock frequency.
    //
    // Note, the system is fully preemptible when this
    // routine is called.
    //

    //
    // Set the subcode for unlock CCF
    //
    PMUCCFBuffer.subcode = PMU_CCF_UNLOCK;

    rtnvalue = 
        KernelIoControl (IOCTL_PMU_CCF, (void *)&PMUCCFBuffer, sizeof(PMUCCFInfo), 
                         (LPVOID)NULL, 0, (LPDWORD)NULL);

    if (rtnvalue)
    {
        // Returns the restored core clock frequency (in KHz).
        //
        return GetCurrentCoreClockFrequency();
    }
    else
    {
        return 0;
    }


}

//------------------------------------------------------------------------------
//
//  Function:  AccessPMUReg
//
//  This API calls KernelIoControl to access the PMU Register.
//  This in turn calls the OEMIoControl routine.  
//  Note, the system is fully preemptible when this
//  routine is called.
//
BOOL WINAPI AccessPMUReg(
    PMUHandle handle, 
    enum PMURegAccessType Access, 
    unsigned long RegisterNumber,
    unsigned long *pValue)
{
    PMURegInfo      PMURegBuffer;
    unsigned long   PMURegResults,
                    nOutBytes;
    BOOL            rtnvalue = FALSE;
        
    if (handle == 0)
    {
        return FALSE;
    }

    PMURegBuffer.PMUReg = RegisterNumber;

    switch (Access)
    {
    case READ:
        PMURegBuffer.subcode = PMU_READ_REG;
        rtnvalue = 
            KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                             &PMURegResults, sizeof(PMURegResults), &nOutBytes);
        if (rtnvalue && (nOutBytes == sizeof(unsigned long)))
        {
            *pValue = PMURegResults;
        }
        else
        {
            rtnvalue = FALSE;
        }

        break;
    case WRITE:
        PMURegBuffer.subcode = PMU_WRITE_REG;
        PMURegBuffer.PMUValue = *pValue;

        rtnvalue = 
            KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                             &PMURegResults, sizeof(PMURegResults), &nOutBytes);
        break;
    default:
        return FALSE;
        break;

    }

    return rtnvalue;
}

//------------------------------------------------------------------------------
//
//  Function:  GetCPUId
//
//  This API calls KernelIoControl to retrieve the CPU Id.
//  This in turn calls the OEMIoControl routine.  
//  Note, the system is fully preemptible when this
//  routine is called.
//
BOOL WINAPI GetCPUId(
    unsigned long *CPUId)
{
    CPUIdInfo       CPUIdBuffer;
    unsigned long   CPUIdResults,
                    nOutBytes;
    BOOL            rtnvalue = FALSE;

    rtnvalue = 
        KernelIoControl (IOCTL_GET_CPU_ID, (void *)&CPUIdBuffer, sizeof(CPUIdInfo), 
                         &CPUIdResults, sizeof(CPUIdResults), &nOutBytes);
    if (rtnvalue && (nOutBytes == sizeof(unsigned long)))
    {
        *CPUId = CPUIdResults;
    }
    else
    {
        rtnvalue = FALSE;
    }

    return rtnvalue;

}

//------------------------------------------------------------------------------
//
//  Function:  GetOEMConfigData
//
//  This API calls KernelIoControl to retrieve the OEM 
//  configuration data. This in turn calls the OEMIoControl routine.  
//  Note, the system is fully preemptible when this
//  routine is called.
//
//  Currently, the OEM configuration data retrieved consists 
//  of two items:  the system interrupt ID assigned by the OEM, 
//  and the address to the VTune PMU driver globals area.
//
BOOL WINAPI GetOEMConfigData (
    unsigned long   *configArray,
    unsigned long   maxItems,
    unsigned long   *nOutItems)
{
    OEMInfo         OEMBuffer;
    PMURegInfo      PMURegBuffer;
    unsigned long   nOutBytes;
    BOOL            rtnvalue = FALSE;

    PMURegBuffer.subcode = PMU_OEM_INFO;
    rtnvalue = 
        KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                     &OEMBuffer, sizeof(OEMInfo), &nOutBytes);

    if (rtnvalue && ((nOutBytes != sizeof(OEMInfo) || 
        (nOutBytes > (maxItems*sizeof(unsigned long))))))
    {
        rtnvalue = FALSE;
        *nOutItems = 0;
    }
    else
    {
        configArray[0] = OEMBuffer.sysintrID;
        configArray[1] = OEMBuffer.PMUglobals;
        *nOutItems = 2;
   }

    return rtnvalue;

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?