#include <i386/machine_routines.h>
#include <i386/machine_cpu.h>
#include <i386/misc_protos.h>
#include <i386/pmap.h>
#include <i386/asm.h>
#include <i386/mp.h>
#include <i386/proc_reg.h>
#include <kern/pms.h>
#include <kern/processor.h>
#include <i386/pmCPU.h>
#include <i386/cpuid.h>
#include <i386/rtclock.h>
#if MACH_KDB
#include <i386/db_machdep.h>
#include <ddb/db_aout.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#include <ddb/db_expr.h>
#endif
extern int disableConsoleOutput;
decl_simple_lock_data(,pm_init_lock);
pmDispatch_t *pmDispatch = NULL;
static pmInitState_t pmInitState;
uint32_t napCtl = 0;
uint32_t forcenap = 0;
uint32_t maxBusDelay = 0xFFFFFFFF;
uint32_t C4C2SnoopDelay = 0;
void
pmsCPUSet(uint32_t sel)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUSet != NULL)
(*pmDispatch->pmsCPUSet)(sel);
else
pmInitState.PState = sel;
}
void
pmsCPUConf(void)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUConf != NULL)
(*pmDispatch->pmsCPUConf)();
}
void
pmsCPUMachineInit(void)
{
pmInitState.PState = -1;
pmInitState.PLimit = -1;
if (pmDispatch != NULL && pmDispatch->pmsCPUMachineInit != NULL)
(*pmDispatch->pmsCPUMachineInit)();
}
void
pmsCPUInit(void)
{
pmsCPUMachineInit();
if (pmDispatch != NULL && pmDispatch->pmsCPUInit != NULL)
(*pmDispatch->pmsCPUInit)();
}
void
pmsCPURun(uint32_t nstep)
{
if (pmDispatch != NULL && pmDispatch->pmsCPURun != NULL)
(*pmDispatch->pmsCPURun)(nstep);
}
uint32_t
pmsCPUQuery(void)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUQuery != NULL)
return((*pmDispatch->pmsCPUQuery)());
return((~0) << 16);
}
uint32_t
pmsCPUPackageQuery(void)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUPackageQuery != NULL)
return((*pmDispatch->pmsCPUPackageQuery)());
return((~0) << 16);
}
void
pmsCPUYellowFlag(void)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUYellowFlag != NULL)
(*pmDispatch->pmsCPUYellowFlag)();
}
void
pmsCPUGreenFlag(void)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUGreenFlag != NULL)
(*pmDispatch->pmsCPUGreenFlag)();
}
kern_return_t
pmsCPULoadVIDTable(uint16_t *tablep, int nstates)
{
if (pmDispatch != NULL && pmDispatch->pmsCPULoadVIDTable != NULL)
return((*pmDispatch->pmsCPULoadVIDTable)(tablep, nstates));
else {
int i;
if (nstates > MAX_PSTATES)
return(KERN_FAILURE);
for (i = 0; i < nstates; i += 1)
pmInitState.VIDTable[i] = tablep[i];
}
return(KERN_SUCCESS);
}
kern_return_t
pmsCPUSetPStateLimit(uint32_t limit)
{
if (pmDispatch != NULL && pmDispatch->pmsCPUSetPStateLimit != NULL)
return((*pmDispatch->pmsCPUSetPStateLimit)(limit));
pmInitState.PLimit = limit;
return(KERN_SUCCESS);
}
void
power_management_init(void)
{
uint32_t cpuModel;
uint32_t cpuFamily;
uint32_t xcpuid[4];
simple_lock_init(&pm_init_lock, 0);
do_cpuid(1, xcpuid);
cpuFamily = (xcpuid[eax] >> 8) & 0xf;
cpuModel = (xcpuid[eax] >> 4) & 0xf;
if (cpuFamily != 0x6 || cpuModel < 0xe)
pmDispatch = NULL;
if (pmDispatch != NULL && pmDispatch->cstateInit != NULL)
(*pmDispatch->cstateInit)();
}
void
machine_nap_policy(void)
{
if (pmDispatch != NULL && pmDispatch->cstateNapPolicy != NULL)
napCtl = (*pmDispatch->cstateNapPolicy)(forcenap, napCtl);
}
kern_return_t
Cstate_table_set(Cstate_hint_t *tablep, unsigned int nstates)
{
if (forcenap)
return(KERN_SUCCESS);
if (pmDispatch != NULL && pmDispatch->cstateTableSet != NULL)
return((*pmDispatch->cstateTableSet)(tablep, nstates));
else {
unsigned int i;
for (i = 0; i < nstates; i += 1) {
pmInitState.CStates[i].number = tablep[i].number;
pmInitState.CStates[i].hint = tablep[i].hint;
}
pmInitState.CStatesCount = nstates;
}
return(KERN_SUCCESS);
}
static inline void
sti(void) {
__asm__ volatile ( "sti" : : : "memory");
}
void
machine_idle_cstate(void)
{
if (pmDispatch != NULL && pmDispatch->cstateMachineIdle != NULL)
(*pmDispatch->cstateMachineIdle)(napCtl);
else {
sti();
}
}
static pmStats_t *
pmsCPUStats(void)
{
cpu_data_t *pp;
pp = current_cpu_datap();
return(&pp->cpu_pmStats);
}
static pmsd *
pmsCPUStepperData(void)
{
cpu_data_t *pp;
pp = current_cpu_datap();
return(&pp->pms);
}
static uint64_t *
CPUHPETAddr(void)
{
cpu_data_t *pp;
pp = current_cpu_datap();
return(pp->cpu_pmHpet);
}
void
pmRegister(pmDispatch_t *cpuFuncs, pmCallBacks_t *callbacks)
{
if (callbacks != NULL) {
callbacks->Park = pmsPark;
callbacks->Run = pmsRun;
callbacks->RunLocal = pmsRunLocal;
callbacks->SetStep = pmsSetStep;
callbacks->NapPolicy = machine_nap_policy;
callbacks->Build = pmsBuild;
callbacks->Stats = pmsCPUStats;
callbacks->StepperData = pmsCPUStepperData;
callbacks->HPETAddr = CPUHPETAddr;
callbacks->InitState = &pmInitState;
callbacks->resetPop = resetPop;
}
if (cpuFuncs != NULL)
pmDispatch = cpuFuncs;
}
void
pmUnRegister(pmDispatch_t *cpuFuncs)
{
if (cpuFuncs != NULL && pmDispatch == cpuFuncs)
pmDispatch = NULL;
}
#if MACH_KDB
void
db_cfg(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_display_iokit(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_dtimers(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_intcnt(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_nap(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_pmgr(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_test(__unused db_expr_t addr,
__unused int have_addr,
__unused db_expr_t count,
__unused char *modif)
{
return;
}
void
db_getpmgr(__unused pmData_t *pmj)
{
}
#endif