PageRenderTime 30ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/headers/private/shared/cpu_type.h

https://github.com/luciang/haiku
C Header | 364 lines | 285 code | 44 blank | 35 comment | 39 complexity | 6e298ad7826af533569826571878ea8f MD5 | raw file
Possible License(s): GPL-3.0, ISC, LGPL-2.0, LGPL-3.0, GPL-2.0, BSD-3-Clause, MPL-2.0-no-copyleft-exception
  1. /*
  2. * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
  3. * Distributed under the terms of the MIT License.
  4. */
  5. /* Taken from the Pulse application, and extended.
  6. * It's used by Pulse, AboutHaiku, and sysinfo.
  7. */
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <OS.h>
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. const char *get_cpu_vendor_string(enum cpu_types type);
  15. const char *get_cpu_model_string(system_info *info);
  16. void get_cpu_type(char *vendorBuffer, size_t vendorSize,
  17. char *modelBuffer, size_t modelSize);
  18. int32 get_rounded_cpu_speed(void);
  19. #ifdef __cplusplus
  20. }
  21. #endif
  22. const char *
  23. get_cpu_vendor_string(enum cpu_types type)
  24. {
  25. #if __POWERPC__
  26. /* We're not that nice here. */
  27. return "IBM/Motorola";
  28. #endif
  29. #if __INTEL__
  30. /* Determine x86 vendor name */
  31. switch (type & B_CPU_x86_VENDOR_MASK) {
  32. case B_CPU_INTEL_x86:
  33. return "Intel";
  34. case B_CPU_AMD_x86:
  35. return "AMD";
  36. case B_CPU_CYRIX_x86:
  37. return "Cyrix";
  38. case B_CPU_IDT_x86:
  39. /* IDT was bought by VIA */
  40. if (((type >> 8) & 0xf) >= 6)
  41. return "VIA";
  42. return "IDT";
  43. case B_CPU_RISE_x86:
  44. return "Rise";
  45. case B_CPU_TRANSMETA_x86:
  46. return "Transmeta";
  47. default:
  48. return NULL;
  49. }
  50. #endif
  51. }
  52. #ifdef __INTEL__
  53. /* Parameter 'name' needs to point to an allocated array of 49 characters. */
  54. void
  55. get_cpuid_model_string(char *name)
  56. {
  57. /* References:
  58. *
  59. * http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
  60. * http://www.sandpile.org/ia32/cpuid.htm
  61. * http://www.amd.com/us-en/assets/content_type/
  62. * white_papers_and_tech_docs/TN13.pdf (Duron erratum)
  63. */
  64. cpuid_info baseInfo;
  65. cpuid_info cpuInfo;
  66. int32 maxStandardFunction, maxExtendedFunction = 0;
  67. memset(name, 0, 49 * sizeof(char));
  68. if (get_cpuid(&baseInfo, 0, 0) != B_OK) {
  69. /* This CPU doesn't support cpuid. */
  70. return;
  71. }
  72. maxStandardFunction = baseInfo.eax_0.max_eax;
  73. if (maxStandardFunction >= 500) {
  74. maxStandardFunction = 0;
  75. /* Old Pentium sample chips have the CPU signature here. */
  76. }
  77. /* Extended cpuid */
  78. get_cpuid(&cpuInfo, 0x80000000, 0);
  79. /* hardcoded to CPU 0 */
  80. /* Extended cpuid is only supported if max_eax is greater than the */
  81. /* service id. */
  82. if (cpuInfo.eax_0.max_eax > 0x80000000)
  83. maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff;
  84. if (maxExtendedFunction >= 4) {
  85. int32 i;
  86. for (i = 0; i < 3; i++) {
  87. cpuid_info nameInfo;
  88. get_cpuid(&nameInfo, 0x80000002 + i, 0);
  89. memcpy(name, &nameInfo.regs.eax, 4);
  90. memcpy(name + 4, &nameInfo.regs.ebx, 4);
  91. memcpy(name + 8, &nameInfo.regs.ecx, 4);
  92. memcpy(name + 12, &nameInfo.regs.edx, 4);
  93. name += 16;
  94. }
  95. }
  96. }
  97. #endif /* __INTEL__ */
  98. const char *
  99. get_cpu_model_string(system_info *info)
  100. {
  101. #if __INTEL__
  102. char cpuidName[49];
  103. /* for use with get_cpuid_model_string() */
  104. #endif /* __INTEL__ */
  105. /* Determine CPU type */
  106. switch (info->cpu_type) {
  107. #if __POWERPC__
  108. case B_CPU_PPC_603:
  109. return "603";
  110. case B_CPU_PPC_603e:
  111. return "603e";
  112. case B_CPU_PPC_750:
  113. return "750";
  114. case B_CPU_PPC_604:
  115. return "604";
  116. case B_CPU_PPC_604e:
  117. return "604e";
  118. #endif /* __POWERPC__ */
  119. #if __INTEL__
  120. case B_CPU_x86:
  121. return "Unknown x86";
  122. /* Intel */
  123. case B_CPU_INTEL_PENTIUM:
  124. case B_CPU_INTEL_PENTIUM75:
  125. return "Pentium";
  126. case B_CPU_INTEL_PENTIUM_486_OVERDRIVE:
  127. case B_CPU_INTEL_PENTIUM75_486_OVERDRIVE:
  128. return "Pentium OD";
  129. case B_CPU_INTEL_PENTIUM_MMX:
  130. case B_CPU_INTEL_PENTIUM_MMX_MODEL_8:
  131. return "Pentium MMX";
  132. case B_CPU_INTEL_PENTIUM_PRO:
  133. return "Pentium Pro";
  134. case B_CPU_INTEL_PENTIUM_II_MODEL_3:
  135. case B_CPU_INTEL_PENTIUM_II_MODEL_5:
  136. return "Pentium II";
  137. case B_CPU_INTEL_CELERON:
  138. case B_CPU_INTEL_CELERON_MODEL_22:
  139. return "Celeron";
  140. case B_CPU_INTEL_PENTIUM_III:
  141. case B_CPU_INTEL_PENTIUM_III_MODEL_8:
  142. case B_CPU_INTEL_PENTIUM_III_MODEL_11:
  143. case B_CPU_INTEL_PENTIUM_III_XEON:
  144. return "Pentium III";
  145. case B_CPU_INTEL_PENTIUM_M:
  146. case B_CPU_INTEL_PENTIUM_M_MODEL_13:
  147. get_cpuid_model_string(cpuidName);
  148. if (strcasestr(cpuidName, "Celeron") != NULL)
  149. return "Pentium M Celeron";
  150. return "Pentium M";
  151. case B_CPU_INTEL_ATOM:
  152. return "Atom";
  153. case B_CPU_INTEL_PENTIUM_CORE:
  154. get_cpuid_model_string(cpuidName);
  155. if (strcasestr(cpuidName, "Celeron") != NULL)
  156. return "Core Celeron";
  157. return "Core";
  158. case B_CPU_INTEL_PENTIUM_CORE_2:
  159. get_cpuid_model_string(cpuidName);
  160. if (strcasestr(cpuidName, "Celeron") != NULL)
  161. return "Core 2 Celeron";
  162. if (strcasestr(cpuidName, "Xeon") != NULL)
  163. return "Core 2 Xeon";
  164. return "Core 2";
  165. case B_CPU_INTEL_PENTIUM_CORE_2_45_NM:
  166. get_cpuid_model_string(cpuidName);
  167. if (strcasestr(cpuidName, "Celeron") != NULL)
  168. return "Core 2 Celeron";
  169. if (strcasestr(cpuidName, "Duo") != NULL
  170. || strcasestr(cpuidName, "Quad") != NULL)
  171. return "Core 2";
  172. if (strcasestr(cpuidName, "Xeon") != NULL)
  173. return "Core 2 Xeon";
  174. return "Core 2 Extreme";
  175. case B_CPU_INTEL_PENTIUM_CORE_I5_M430:
  176. return "Core i5";
  177. case B_CPU_INTEL_PENTIUM_CORE_I7:
  178. case B_CPU_INTEL_PENTIUM_CORE_I7_Q720:
  179. get_cpuid_model_string(cpuidName);
  180. if (strcasestr(cpuidName, "Xeon") != NULL)
  181. return "Core i7 Xeon";
  182. return "Core i7";
  183. case B_CPU_INTEL_PENTIUM_IV:
  184. case B_CPU_INTEL_PENTIUM_IV_MODEL_1:
  185. case B_CPU_INTEL_PENTIUM_IV_MODEL_2:
  186. case B_CPU_INTEL_PENTIUM_IV_MODEL_3:
  187. case B_CPU_INTEL_PENTIUM_IV_MODEL_4:
  188. get_cpuid_model_string(cpuidName);
  189. if (strcasestr(cpuidName, "Celeron") != NULL)
  190. return "Pentium 4 Celeron";
  191. if (strcasestr(cpuidName, "Xeon") != NULL)
  192. return "Pentium 4 Xeon";
  193. return "Pentium 4";
  194. /* AMD */
  195. case B_CPU_AMD_K5_MODEL_0:
  196. case B_CPU_AMD_K5_MODEL_1:
  197. case B_CPU_AMD_K5_MODEL_2:
  198. case B_CPU_AMD_K5_MODEL_3:
  199. return "K5";
  200. case B_CPU_AMD_K6_MODEL_6:
  201. case B_CPU_AMD_K6_MODEL_7:
  202. return "K6";
  203. case B_CPU_AMD_K6_2:
  204. return "K6-2";
  205. case B_CPU_AMD_K6_III:
  206. case B_CPU_AMD_K6_III_MODEL_13:
  207. return "K6-III";
  208. case B_CPU_AMD_ATHLON_MODEL_1:
  209. case B_CPU_AMD_ATHLON_MODEL_2:
  210. case B_CPU_AMD_ATHLON_THUNDERBIRD:
  211. return "Athlon";
  212. case B_CPU_AMD_ATHLON_XP:
  213. case B_CPU_AMD_ATHLON_XP_MODEL_8:
  214. case B_CPU_AMD_ATHLON_XP_MODEL_10:
  215. return "Athlon XP";
  216. case B_CPU_AMD_DURON:
  217. case B_CPU_AMD_ATHLON_XP_MODEL_7:
  218. return "Duron";
  219. case B_CPU_AMD_ATHLON_64_MODEL_3:
  220. case B_CPU_AMD_ATHLON_64_MODEL_4:
  221. case B_CPU_AMD_ATHLON_64_MODEL_7:
  222. case B_CPU_AMD_ATHLON_64_MODEL_8:
  223. case B_CPU_AMD_ATHLON_64_MODEL_11:
  224. case B_CPU_AMD_ATHLON_64_MODEL_12:
  225. case B_CPU_AMD_ATHLON_64_MODEL_14:
  226. case B_CPU_AMD_ATHLON_64_MODEL_15:
  227. return "Athlon 64";
  228. case B_CPU_AMD_OPTERON:
  229. return "Opteron";
  230. case B_CPU_AMD_PHENOM:
  231. return "Phenom";
  232. case B_CPU_AMD_GEODE_LX:
  233. return "Geode LX";
  234. /* Transmeta */
  235. case B_CPU_TRANSMETA_CRUSOE:
  236. return "Crusoe";
  237. case B_CPU_TRANSMETA_EFFICEON:
  238. case B_CPU_TRANSMETA_EFFICEON_2:
  239. return "Efficeon";
  240. /* IDT/VIA */
  241. case B_CPU_IDT_WINCHIP_C6:
  242. return "WinChip C6";
  243. case B_CPU_IDT_WINCHIP_2:
  244. return "WinChip 2";
  245. case B_CPU_VIA_C3_SAMUEL:
  246. return "C3 Samuel";
  247. case B_CPU_VIA_C3_SAMUEL_2:
  248. /* stepping identified the model */
  249. if ((info->cpu_revision & 0xf) < 8)
  250. return "C3 Eden/Samuel 2";
  251. return "C3 Ezra";
  252. case B_CPU_VIA_C3_EZRA_T:
  253. return "C3 Ezra-T";
  254. case B_CPU_VIA_C3_NEHEMIAH:
  255. /* stepping identified the model */
  256. if ((info->cpu_revision & 0xf) < 8)
  257. return "C3 Nehemiah";
  258. return "C3 Eden-N";
  259. case B_CPU_VIA_C7_ESTHER:
  260. case B_CPU_VIA_C7_ESTHER_2:
  261. return "C7";
  262. case B_CPU_VIA_NANO_ISAIAH:
  263. return "Nano";
  264. /* Cyrix/VIA */
  265. case B_CPU_CYRIX_GXm:
  266. return "GXm";
  267. case B_CPU_CYRIX_6x86MX:
  268. return "6x86MX";
  269. /* Rise */
  270. case B_CPU_RISE_mP6:
  271. return "mP6";
  272. /* National Semiconductor */
  273. case B_CPU_NATIONAL_GEODE_GX1:
  274. return "Geode GX1";
  275. #endif /* __INTEL__ */
  276. default:
  277. return NULL;
  278. }
  279. }
  280. void
  281. get_cpu_type(char *vendorBuffer, size_t vendorSize, char *modelBuffer,
  282. size_t modelSize)
  283. {
  284. const char *vendor, *model;
  285. system_info info;
  286. get_system_info(&info);
  287. vendor = get_cpu_vendor_string(info.cpu_type);
  288. if (vendor == NULL)
  289. vendor = "Unknown";
  290. model = get_cpu_model_string(&info);
  291. if (model == NULL)
  292. model = "Unknown";
  293. #ifdef R5_COMPATIBLE
  294. strncpy(vendorBuffer, vendor, vendorSize - 1);
  295. vendorBuffer[vendorSize - 1] = '\0';
  296. strncpy(modelBuffer, model, modelSize - 1);
  297. modelBuffer[modelSize - 1] = '\0';
  298. #else
  299. strlcpy(vendorBuffer, vendor, vendorSize);
  300. strlcpy(modelBuffer, model, modelSize);
  301. #endif
  302. }
  303. int32
  304. get_rounded_cpu_speed(void)
  305. {
  306. system_info info;
  307. int target, frac, delta;
  308. int freqs[] = { 100, 50, 25, 75, 33, 67, 20, 40, 60, 80, 10, 30, 70, 90 };
  309. uint x;
  310. get_system_info(&info);
  311. target = info.cpu_clock_speed / 1000000;
  312. frac = target % 100;
  313. delta = -frac;
  314. for (x = 0; x < sizeof(freqs) / sizeof(freqs[0]); x++) {
  315. int ndelta = freqs[x] - frac;
  316. if (abs(ndelta) < abs(delta))
  317. delta = ndelta;
  318. }
  319. return target + delta;
  320. }