PageRenderTime 24ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/headers/private/shared/cpu_type.h

https://bitbucket.org/ddevine/haiku
C Header | 366 lines | 287 code | 44 blank | 35 comment | 39 complexity | ce6c4de4720d1a6629482c388de443a4 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, MIT, ISC, BSD-3-Clause, AGPL-1.0, GPL-2.0, GPL-3.0, LGPL-3.0
  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, "Xeon") != NULL)
  170. return "Core 2 Xeon";
  171. if (strcasestr(cpuidName, "Pentium") != NULL)
  172. return "Pentium";
  173. if (strcasestr(cpuidName, "Extreme") != NULL)
  174. return "Core 2 Extreme";
  175. return "Core 2";
  176. case B_CPU_INTEL_PENTIUM_CORE_I5_M430:
  177. return "Core i5";
  178. case B_CPU_INTEL_PENTIUM_CORE_I7:
  179. case B_CPU_INTEL_PENTIUM_CORE_I7_Q720:
  180. get_cpuid_model_string(cpuidName);
  181. if (strcasestr(cpuidName, "Xeon") != NULL)
  182. return "Core i7 Xeon";
  183. return "Core i7";
  184. case B_CPU_INTEL_PENTIUM_IV:
  185. case B_CPU_INTEL_PENTIUM_IV_MODEL_1:
  186. case B_CPU_INTEL_PENTIUM_IV_MODEL_2:
  187. case B_CPU_INTEL_PENTIUM_IV_MODEL_3:
  188. case B_CPU_INTEL_PENTIUM_IV_MODEL_4:
  189. get_cpuid_model_string(cpuidName);
  190. if (strcasestr(cpuidName, "Celeron") != NULL)
  191. return "Pentium 4 Celeron";
  192. if (strcasestr(cpuidName, "Xeon") != NULL)
  193. return "Pentium 4 Xeon";
  194. return "Pentium 4";
  195. /* AMD */
  196. case B_CPU_AMD_K5_MODEL_0:
  197. case B_CPU_AMD_K5_MODEL_1:
  198. case B_CPU_AMD_K5_MODEL_2:
  199. case B_CPU_AMD_K5_MODEL_3:
  200. return "K5";
  201. case B_CPU_AMD_K6_MODEL_6:
  202. case B_CPU_AMD_K6_MODEL_7:
  203. return "K6";
  204. case B_CPU_AMD_K6_2:
  205. return "K6-2";
  206. case B_CPU_AMD_K6_III:
  207. case B_CPU_AMD_K6_III_MODEL_13:
  208. return "K6-III";
  209. case B_CPU_AMD_ATHLON_MODEL_1:
  210. case B_CPU_AMD_ATHLON_MODEL_2:
  211. case B_CPU_AMD_ATHLON_THUNDERBIRD:
  212. return "Athlon";
  213. case B_CPU_AMD_ATHLON_XP:
  214. case B_CPU_AMD_ATHLON_XP_MODEL_8:
  215. case B_CPU_AMD_ATHLON_XP_MODEL_10:
  216. return "Athlon XP";
  217. case B_CPU_AMD_DURON:
  218. case B_CPU_AMD_ATHLON_XP_MODEL_7:
  219. return "Duron";
  220. case B_CPU_AMD_ATHLON_64_MODEL_3:
  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_PHENOM_II:
  233. return "Phenom II";
  234. case B_CPU_AMD_GEODE_LX:
  235. return "Geode LX";
  236. /* Transmeta */
  237. case B_CPU_TRANSMETA_CRUSOE:
  238. return "Crusoe";
  239. case B_CPU_TRANSMETA_EFFICEON:
  240. case B_CPU_TRANSMETA_EFFICEON_2:
  241. return "Efficeon";
  242. /* IDT/VIA */
  243. case B_CPU_IDT_WINCHIP_C6:
  244. return "WinChip C6";
  245. case B_CPU_IDT_WINCHIP_2:
  246. return "WinChip 2";
  247. case B_CPU_VIA_C3_SAMUEL:
  248. return "C3 Samuel";
  249. case B_CPU_VIA_C3_SAMUEL_2:
  250. /* stepping identified the model */
  251. if ((info->cpu_revision & 0xf) < 8)
  252. return "C3 Eden/Samuel 2";
  253. return "C3 Ezra";
  254. case B_CPU_VIA_C3_EZRA_T:
  255. return "C3 Ezra-T";
  256. case B_CPU_VIA_C3_NEHEMIAH:
  257. /* stepping identified the model */
  258. if ((info->cpu_revision & 0xf) < 8)
  259. return "C3 Nehemiah";
  260. return "C3 Eden-N";
  261. case B_CPU_VIA_C7_ESTHER:
  262. case B_CPU_VIA_C7_ESTHER_2:
  263. return "C7";
  264. case B_CPU_VIA_NANO_ISAIAH:
  265. return "Nano";
  266. /* Cyrix/VIA */
  267. case B_CPU_CYRIX_GXm:
  268. return "GXm";
  269. case B_CPU_CYRIX_6x86MX:
  270. return "6x86MX";
  271. /* Rise */
  272. case B_CPU_RISE_mP6:
  273. return "mP6";
  274. /* National Semiconductor */
  275. case B_CPU_NATIONAL_GEODE_GX1:
  276. return "Geode GX1";
  277. #endif /* __INTEL__ */
  278. default:
  279. return NULL;
  280. }
  281. }
  282. void
  283. get_cpu_type(char *vendorBuffer, size_t vendorSize, char *modelBuffer,
  284. size_t modelSize)
  285. {
  286. const char *vendor, *model;
  287. system_info info;
  288. get_system_info(&info);
  289. vendor = get_cpu_vendor_string(info.cpu_type);
  290. if (vendor == NULL)
  291. vendor = "Unknown";
  292. model = get_cpu_model_string(&info);
  293. if (model == NULL)
  294. model = "Unknown";
  295. #ifdef R5_COMPATIBLE
  296. strncpy(vendorBuffer, vendor, vendorSize - 1);
  297. vendorBuffer[vendorSize - 1] = '\0';
  298. strncpy(modelBuffer, model, modelSize - 1);
  299. modelBuffer[modelSize - 1] = '\0';
  300. #else
  301. strlcpy(vendorBuffer, vendor, vendorSize);
  302. strlcpy(modelBuffer, model, modelSize);
  303. #endif
  304. }
  305. int32
  306. get_rounded_cpu_speed(void)
  307. {
  308. system_info info;
  309. int target, frac, delta;
  310. int freqs[] = { 100, 50, 25, 75, 33, 67, 20, 40, 60, 80, 10, 30, 70, 90 };
  311. uint x;
  312. get_system_info(&info);
  313. target = info.cpu_clock_speed / 1000000;
  314. frac = target % 100;
  315. delta = -frac;
  316. for (x = 0; x < sizeof(freqs) / sizeof(freqs[0]); x++) {
  317. int ndelta = freqs[x] - frac;
  318. if (abs(ndelta) < abs(delta))
  319. delta = ndelta;
  320. }
  321. return target + delta;
  322. }