📄 cpuinfo.c
字号:
/****************************************************************************** SciTech OS Portability Manager Library** ========================================================================** The contents of this file are subject to the SciTech MGL Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.scitechsoft.com/mgl-license.txt** Software distributed under the License is distributed on an* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.** The Initial Developer of the Original Code is SciTech Software, Inc.* All Rights Reserved.** ========================================================================** Language: ANSI C* Environment: Any** Description: Main module to implement the Zen Timer support functions.*****************************************************************************/#include "ztimer.h"#include "pmapi.h"#include "oshdr.h"#if !defined(__WIN32_VXD__) && !defined(__OS2_VDD__) && !defined(__NT_DRIVER__)#include <stdio.h>#include <string.h>#endif/*----------------------------- Implementation ----------------------------*//* External Intel assembler functions */#ifdef __INTEL__/* {secret} */ibool _ASMAPI _CPU_haveCPUID(void);/* {secret} */ibool _ASMAPI _CPU_check80386(void);/* {secret} */ibool _ASMAPI _CPU_check80486(void);/* {secret} */uint _ASMAPI _CPU_checkCPUID(void);/* {secret} */uint _ASMAPI _CPU_getCPUIDModel(void);/* {secret} */uint _ASMAPI _CPU_getCPUIDStepping(void);/* {secret} */uint _ASMAPI _CPU_getCPUIDFeatures(void);/* {secret} */uint _ASMAPI _CPU_getCacheSize(void);/* {secret} */uint _ASMAPI _CPU_have3DNow(void);/* {secret} */ibool _ASMAPI _CPU_checkClone(void);/* {secret} */void _ASMAPI _CPU_readTimeStamp(CPU_largeInteger *time);/* {secret} */void _ASMAPI _CPU_runBSFLoop(ulong iterations);/* {secret} */ulong _ASMAPI _CPU_mulDiv(ulong a,ulong b,ulong c);/* {secret} */void ZTimerQuickInit(void);#define CPU_HaveMMX 0x00800000#define CPU_HaveRDTSC 0x00000010#define CPU_HaveSSE 0x02000000#endif#if defined(__SMX32__)#include "smx/cpuinfo.c"#elif defined(__RTTARGET__)#include "rttarget/cpuinfo.c"#elif defined(__REALDOS__)#include "dos/cpuinfo.c"#elif defined(__NT_DRIVER__)#include "ntdrv/cpuinfo.c"#elif defined(__WIN32_VXD__)#include "vxd/cpuinfo.c"#elif defined(__WINDOWS32__)#include "win32/cpuinfo.c"#elif defined(__OS2_VDD__)#include "vdd/cpuinfo.c"#elif defined(__OS2__)#include "os2/cpuinfo.c"#elif defined(__LINUX__)#include "linux/cpuinfo.c"#elif defined(__QNX__)#include "qnx/cpuinfo.c"#elif defined(__BEOS__)#include "beos/cpuinfo.c"#else#error CPU library not ported to this platform yet!#endif/*------------------------ Public interface routines ----------------------*//****************************************************************************REMARKS:Read an I/O port location.****************************************************************************/static uchar rdinx( int port, int index){ PM_outpb(port,(uchar)index); return PM_inpb(port+1);}/****************************************************************************REMARKS:Write an I/O port location.****************************************************************************/static void wrinx( ushort port, ushort index, ushort value){ PM_outpb(port,(uchar)index); PM_outpb(port+1,(uchar)value);}/****************************************************************************REMARKS:Enables the Cyrix CPUID instruction to properly detect MediaGX and 6x86processors.****************************************************************************/static void _CPU_enableCyrixCPUID(void){ uchar ccr3; PM_init(); ccr3 = rdinx(0x22,0xC3); wrinx(0x22,0xC3,(uchar)(ccr3 | 0x10)); wrinx(0x22,0xE8,(uchar)(rdinx(0x22,0xE8) | 0x80)); wrinx(0x22,0xC3,ccr3);}/****************************************************************************DESCRIPTION:Returns the type of processor in the system.HEADER:ztimer.hRETURNS:Numerical identifier for the installed processorREMARKS:Returns the type of processor in the system. Note that if the CPU is anunknown Pentium family processor that we don't have an enumeration for,the return value will be greater than or equal to the value of CPU_UnkPentium(depending on the value returned by the CPUID instruction).SEE ALSO:CPU_getProcessorSpeed, CPU_haveMMX, CPU_getProcessorName****************************************************************************/uint ZAPI CPU_getProcessorType(void){#if defined(__INTEL__) uint cpu,vendor,model,cacheSize; static ibool firstTime = true; if (_CPU_haveCPUID()) { cpu = _CPU_checkCPUID(); vendor = cpu & ~CPU_mask; if (vendor == CPU_Intel) { /* Check for Intel processors */ switch (cpu & CPU_mask) { case 4: cpu = CPU_i486; break; case 5: cpu = CPU_Pentium; break; case 6: if ((model = _CPU_getCPUIDModel()) == 1) cpu = CPU_PentiumPro; else if (model <= 6) { cacheSize = _CPU_getCacheSize(); if ((model == 5 && cacheSize == 0) || (model == 5 && cacheSize == 256) || (model == 6 && cacheSize == 128)) cpu = CPU_Celeron; else cpu = CPU_PentiumII; } else if (model >= 7) { /* Model 7 == Pentium III */ /* Model 8 == Celeron/Pentium III Coppermine */ cacheSize = _CPU_getCacheSize(); if ((model == 8 && cacheSize == 128)) cpu = CPU_Celeron; else cpu = CPU_PentiumIII; } break; default: cpu = CPU_UnkIntel; } } else if (vendor == CPU_Cyrix) { /* Check for Cyrix processors */ switch (cpu & CPU_mask) { case 4: if ((model = _CPU_getCPUIDModel()) == 4) cpu = CPU_CyrixMediaGX; else cpu = CPU_UnkCyrix; break; case 5: if ((model = _CPU_getCPUIDModel()) == 2) cpu = CPU_Cyrix6x86; else if (model == 4) cpu = CPU_CyrixMediaGXm; else cpu = CPU_UnkCyrix; break; case 6: if ((model = _CPU_getCPUIDModel()) <= 1) cpu = CPU_Cyrix6x86MX; else cpu = CPU_UnkCyrix; break; default: cpu = CPU_UnkCyrix; } } else if (vendor == CPU_AMD) { /* Check for AMD processors */ switch (cpu & CPU_mask) { case 4: if ((model = _CPU_getCPUIDModel()) == 0) cpu = CPU_AMDAm5x86; else cpu = CPU_AMDAm486; break; case 5: if ((model = _CPU_getCPUIDModel()) <= 3) cpu = CPU_AMDK5; else if (model <= 7) cpu = CPU_AMDK6; else if (model == 8) cpu = CPU_AMDK6_2; else if (model == 9) cpu = CPU_AMDK6_III; else if (model == 13) { if (_CPU_getCPUIDStepping() <= 3) cpu = CPU_AMDK6_IIIplus; else cpu = CPU_AMDK6_2plus; } else cpu = CPU_UnkAMD; break; case 6: if ((model = _CPU_getCPUIDModel()) == 3) cpu = CPU_AMDDuron; else cpu = CPU_AMDAthlon; break; default: cpu = CPU_UnkAMD; } } else if (vendor == CPU_IDT) { /* Check for IDT WinChip processors */ switch (cpu & CPU_mask) { case 5: if ((model = _CPU_getCPUIDModel()) <= 4) cpu = CPU_WinChipC6; else if (model == 8) cpu = CPU_WinChip2; else cpu = CPU_UnkIDT; break; default: cpu = CPU_UnkIDT; } } else { /* Assume a Pentium compatible Intel clone */ cpu = CPU_Pentium; } return cpu | vendor | (_CPU_getCPUIDStepping() << CPU_steppingShift); } else { if (_CPU_check80386()) cpu = CPU_i386; else if (_CPU_check80486()) { /* If we get here we may have a Cyrix processor so we can try * enabling the CPUID instruction and trying again. */ if (firstTime) { firstTime = false; _CPU_enableCyrixCPUID(); return CPU_getProcessorType(); } cpu = CPU_i486; } else cpu = CPU_Pentium; if (!_CPU_checkClone()) return cpu | CPU_Intel; return cpu; }#elif defined(__ALPHA__) return CPU_Alpha;#elif defined(__MIPS__) return CPU_Mips;#elif defined(__PPC__) return CPU_PowerPC;#endif}/****************************************************************************DESCRIPTION:Returns true if the processor supports Intel MMX extensions.HEADER:ztimer.hRETURNS:True if MMX is available, false if not.REMARKS:This function determines if the processor supports the Intel MMX extendedinstruction set.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_have3DNow, CPU_haveSSE,CPU_getProcessorName****************************************************************************/ibool ZAPI CPU_haveMMX(void){#ifdef __INTEL__ if (_CPU_haveCPUID()) return (_CPU_getCPUIDFeatures() & CPU_HaveMMX) != 0; return false;#else return false;#endif}/****************************************************************************DESCRIPTION:Returns true if the processor supports AMD 3DNow! extensions.HEADER:ztimer.hRETURNS:True if 3DNow! is available, false if not.REMARKS:This function determines if the processor supports the AMD 3DNow! extendedinstruction set.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_haveSSE,CPU_getProcessorName****************************************************************************/ibool ZAPI CPU_have3DNow(void){#ifdef __INTEL__ if (_CPU_haveCPUID()) return _CPU_have3DNow(); return false;#else return false;#endif}/****************************************************************************DESCRIPTION:Returns true if the processor supports Intel KNI extensions.HEADER:ztimer.hRETURNS:True if Intel KNI is available, false if not.REMARKS:This function determines if the processor supports the Intel KNI extendedinstruction set.SEE ALSO:CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow,CPU_getProcessorName****************************************************************************/ibool ZAPI CPU_haveSSE(void){#ifdef __INTEL__ if (_CPU_haveCPUID()) return (_CPU_getCPUIDFeatures() & CPU_HaveSSE) != 0; return false;#else return false;#endif}/****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -