pmudll.cpp

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

CPP
667
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*
** Copyright 2000-2003 Intel Corporation All Rights Reserved.
**
** Portions of the source code contained or described herein and all documents
** related to such source code (Material) are owned by Intel Corporation
** or its suppliers or licensors and is licensed by Microsoft Corporation for distribution.  
** Title to the Material remains with Intel Corporation or its suppliers and licensors. 
** Use of the Materials is subject to the terms of the Microsoft license agreement which accompanied the Materials.  
** No other license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise 
** Some portion of the Materials may be copyrighted by Microsoft Corporation.
*/
/*++

Module Name:  PMUdll.cpp

Abstract:  
 Defines the entry points for the VTune PMU DLL.

Functions:


Notes: 

--*/


#include "stdafx.h"
#include <stdlib.h>
#include <ceddk.h>
#include <malloc.h>
#include <pmu.h>  
#include <pmuioctl.h>  
#include "pmudll.h"     

#define MAXFREQS 8


static HANDLE trySemaphore = 0;      // Semaphore for PMU resource allocation
static HANDLE semHandle = 0;         // Semaphore for PMU resource allocation

// Local copies of callback ptrs
//
LPVOID PVTuneInterrupt = NULL;      
LPVOID PVTuneReleasePMU = NULL;     
LPVOID PVTuneReleaseCCF = NULL;   


//------------------------------------------------------------------------------
//
//  Function:  AllocatePMU
//
//  Returns a handle identifying the PMU resource
//  If PMU not available, returns 0.
//
PMUHandle WINAPI AllocatePMU(void (*pCallBack)(void))
{

    PMUHandle   handle = 0;
    PMURegInfo  PMURegBuffer;
    BOOL        rtnvalue = FALSE;
    LPCTSTR     semName = TEXT("XSC_PMU_ALLOC");

    // Allocate a system resource, initialize to unsignalled state.
    // If it's already allocated, return NULL handle.
    //
    trySemaphore = CreateSemaphore (NULL, 1, 1, semName);
    if (trySemaphore == NULL) 
    {
        return 0;
    }

    if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
        //
        // Invalidate this handle
        //
        CloseHandle(trySemaphore);
        return 0;
    }

        semHandle = trySemaphore;

        // Map callback address to virtual address slot of current process
        //
        PVTuneReleasePMU = MapPtrToProcess(pCallBack, GetCurrentProcess());
        
        // Register callback with kernel
        //
        PMURegBuffer.subcode = PMU_ALLOCATE;
        PMURegBuffer.pCallback = PVTuneReleasePMU;

        rtnvalue = 
                KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                                 (LPVOID)NULL, 0, (LPDWORD)NULL);
        if (rtnvalue == FALSE)
        {
            return 0;
        }

        // Null other callbacks
        //
        PVTuneInterrupt = NULL;
        PVTuneReleaseCCF = NULL;

        // Allocate a PMUHandle
        //
        handle = (PMUHandle) malloc (sizeof (PMUHResource));

    return handle;

}

//------------------------------------------------------------------------------
//
//  Function:  ReleasePMUResources
//
//  Release the PMU Resources
//  So far this releases the PMU resource and
//  NULLs the handle.
//
BOOL WINAPI ReleasePMUResources(PMUHandle handle)
{   
    PMURegInfo  PMURegBuffer;
    BOOL        rtnvalue = FALSE;

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

    //
    // Remove Interrupt callback
    //
    RemovePMUInterruptCallback(handle);

    //
    // Remove lock, if any, and release CCF callback
    //
    UnlockAndRestoreCoreClockFrequency(handle);

    //
    // Null local copy
    //
    PVTuneReleasePMU = NULL;

    //
    // Unregister ReleasePMU callback in kernel
    //
    PMURegBuffer.subcode = PMU_RELEASE;
    rtnvalue = 
            KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                             (LPVOID)NULL, 0, (LPDWORD)NULL);

    //
    // Release resource, NULL handle
    //
    ReleaseSemaphore(semHandle, 1, NULL);
    CloseHandle(semHandle);
    free ((PMUHResource*) handle);
    handle = 0;

    return rtnvalue;
}

//------------------------------------------------------------------------------
//
//  Function:  SetPMUInterruptCallback
//
//  Registers the PMU Callback routine that is called
//  from the OS when the PMU interrupt occurs.
//
//  Note:  The FIQ_or_IRQ parameter is ignored.  We're
//  only implementing IRQs for the Cotulla WinCE kernel.
//
STATUS_PMU WINAPI SetPMUInterruptCallback(
    PMUHandle handle, 
    enum PMUIntType FIQ_or_IRQ, 
    BOOL (*pCallBack)(SampleInput *))
{
    PMURegInfo      PMURegBuffer;
    BOOL            rtnvalue = FALSE;

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

    //
    // Check the callback routine pointer.
    // If already set, then return an error
    //
    if (PVTuneInterrupt)
    {
        return ACTIVECALLBACK_PMU;
    }

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

    //
    // Interrupt callback not implemented yet.
    // PMU ISR still a part of the kernel, pmu.c
    //

    //
    //   Call KernelIoControl call to enable IRQ or FIQ interrupts
    //
    switch (FIQ_or_IRQ)
    {
    case IRQ:
        PMURegBuffer.subcode = PMU_ENABLE_IRQ;
        PMURegBuffer.pCallback = PVTuneInterrupt;
        break;

    case FIQ:
        //
        // Not yet implemented...
        //
        PMURegBuffer.subcode = PMU_ENABLE_FIQ;
        PMURegBuffer.pCallback = PVTuneInterrupt;
        return KERNELIOFAILED_PMU;
        break;
    default:
        return KERNELIOFAILED_PMU;
        break;
    }

    rtnvalue = 
            KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                             (LPVOID)NULL, 0, (LPDWORD)NULL);

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

    return SUCCESS_PMU;
}


//------------------------------------------------------------------------------
//
//  Function:  RemovePMUInterruptCallback
//
//  Unregisters the PMU interrupt callback routine.
//
STATUS_PMU WINAPI RemovePMUInterruptCallback(
    PMUHandle handle )
{
    PMURegInfo      PMURegBuffer;
    BOOL            rtnvalue = FALSE;

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

    //
    // Remove the interrupt callback
    //
    if (PVTuneInterrupt == NULL)
    {
        return NOCALLBACK_PMU;
    }

    PVTuneInterrupt = NULL;

    //
    // Disable the interrupt (IRQ for now...) and 
    // unregister the callback in the kernel
    //
    PMURegBuffer.subcode = PMU_DISABLE_IRQ;
    rtnvalue = 
            KernelIoControl (IOCTL_PMU_CONFIG, (void *)&PMURegBuffer, sizeof(PMURegInfo), 
                             (LPVOID)NULL, 0, (LPDWORD)NULL);

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

    return SUCCESS_PMU;

}


//------------------------------------------------------------------------------
//
//  Function:  GetNumberOfPossibleCoreClockFrequencies
//
//  Returns the number of frequency values that
//  can be set by the OS.
//
unsigned int WINAPI GetNumberOfPossibleCoreClockFrequencies(void)
{
    return MAXFREQS;
}


//------------------------------------------------------------------------------
//
//  Function:  GetPossibleCoreClockFrequencies
// 
//  Write the possible frequencies as unsigned ints in the buffer provided.
//  FrequencyArray buffer is allocated by the caller.
//
//  Frequencies expressed in KHz
//
STATUS_PMU WINAPI GetPossibleCoreClockFrequencies(
    unsigned int numberfreqs, 
    unsigned long *FrequencyArray)
{

/*
 * Restrict frequencies between the same LCD Frequency
 * (K) range until LCD controller can be disabled
 *
 *    static unsigned long FreqArray[MAXFREQS] =
 *      {26000, 39000, 52000, 65000, 78000,

⌨️ 快捷键说明

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