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

/headers/private/shared/cpu_type.h

https://github.com/brechtm/haiku
C Header | 365 lines | 286 code | 44 blank | 35 comment | 39 complexity | abc8e62cfb3660f0ece59bb2e3347410 MD5 | raw file
  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_7:
  221. case B_CPU_AMD_ATHLON_64_MODEL_8:
  222. case B_CPU_AMD_ATHLON_64_MODEL_11:
  223. case B_CPU_AMD_ATHLON_64_MODEL_12:
  224. case B_CPU_AMD_ATHLON_64_MODEL_14:
  225. case B_CPU_AMD_ATHLON_64_MODEL_15:
  226. return "Athlon 64";
  227. case B_CPU_AMD_OPTERON:
  228. return "Opteron";
  229. case B_CPU_AMD_PHENOM:
  230. return "Phenom";
  231. case B_CPU_AMD_PHENOM_II:
  232. return "Phenom II";
  233. case B_CPU_AMD_GEODE_LX:
  234. return "Geode LX";
  235. /* Transmeta */
  236. case B_CPU_TRANSMETA_CRUSOE:
  237. return "Crusoe";
  238. case B_CPU_TRANSMETA_EFFICEON:
  239. case B_CPU_TRANSMETA_EFFICEON_2:
  240. return "Efficeon";
  241. /* IDT/VIA */
  242. case B_CPU_IDT_WINCHIP_C6:
  243. return "WinChip C6";
  244. case B_CPU_IDT_WINCHIP_2:
  245. return "WinChip 2";
  246. case B_CPU_VIA_C3_SAMUEL:
  247. return "C3 Samuel";
  248. case B_CPU_VIA_C3_SAMUEL_2:
  249. /* stepping identified the model */
  250. if ((info->cpu_revision & 0xf) < 8)
  251. return "C3 Eden/Samuel 2";
  252. return "C3 Ezra";
  253. case B_CPU_VIA_C3_EZRA_T:
  254. return "C3 Ezra-T";
  255. case B_CPU_VIA_C3_NEHEMIAH:
  256. /* stepping identified the model */
  257. if ((info->cpu_revision & 0xf) < 8)
  258. return "C3 Nehemiah";
  259. return "C3 Eden-N";
  260. case B_CPU_VIA_C7_ESTHER:
  261. case B_CPU_VIA_C7_ESTHER_2:
  262. return "C7";
  263. case B_CPU_VIA_NANO_ISAIAH:
  264. return "Nano";
  265. /* Cyrix/VIA */
  266. case B_CPU_CYRIX_GXm:
  267. return "GXm";
  268. case B_CPU_CYRIX_6x86MX:
  269. return "6x86MX";
  270. /* Rise */
  271. case B_CPU_RISE_mP6:
  272. return "mP6";
  273. /* National Semiconductor */
  274. case B_CPU_NATIONAL_GEODE_GX1:
  275. return "Geode GX1";
  276. #endif /* __INTEL__ */
  277. default:
  278. return NULL;
  279. }
  280. }
  281. void
  282. get_cpu_type(char *vendorBuffer, size_t vendorSize, char *modelBuffer,
  283. size_t modelSize)
  284. {
  285. const char *vendor, *model;
  286. system_info info;
  287. get_system_info(&info);
  288. vendor = get_cpu_vendor_string(info.cpu_type);
  289. if (vendor == NULL)
  290. vendor = "Unknown";
  291. model = get_cpu_model_string(&info);
  292. if (model == NULL)
  293. model = "Unknown";
  294. #ifdef R5_COMPATIBLE
  295. strncpy(vendorBuffer, vendor, vendorSize - 1);
  296. vendorBuffer[vendorSize - 1] = '\0';
  297. strncpy(modelBuffer, model, modelSize - 1);
  298. modelBuffer[modelSize - 1] = '\0';
  299. #else
  300. strlcpy(vendorBuffer, vendor, vendorSize);
  301. strlcpy(modelBuffer, model, modelSize);
  302. #endif
  303. }
  304. int32
  305. get_rounded_cpu_speed(void)
  306. {
  307. system_info info;
  308. int target, frac, delta;
  309. int freqs[] = { 100, 50, 25, 75, 33, 67, 20, 40, 60, 80, 10, 30, 70, 90 };
  310. uint x;
  311. get_system_info(&info);
  312. target = info.cpu_clock_speed / 1000000;
  313. frac = target % 100;
  314. delta = -frac;
  315. for (x = 0; x < sizeof(freqs) / sizeof(freqs[0]); x++) {
  316. int ndelta = freqs[x] - frac;
  317. if (abs(ndelta) < abs(delta))
  318. delta = ndelta;
  319. }
  320. return target + delta;
  321. }