From 5ae4a8dd8ee6e67523528c64e7171f2fec0ada97 Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Sat, 27 Dec 2008 15:46:03 +0000 Subject: [PATCH] Added known-cpu-list function. Rearranged Intel CPU list to be better chronologically ordered git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@45 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- cpuid_tool/cpuid_tool.c | 36 ++++++++++++++- libcpuid/cpuid_main.c | 69 +++++++++++++++++++++++++++++ libcpuid/libcpuid.h | 37 ++++++++++++++++ libcpuid/libcpuid_util.c | 20 +++++++++ libcpuid/libcpuid_util.h | 9 +++- libcpuid/recog_amd.c | 5 +++ libcpuid/recog_amd.h | 1 + libcpuid/recog_intel.c | 94 +++++++++++++++++++++------------------- libcpuid/recog_intel.h | 1 + 9 files changed, 225 insertions(+), 47 deletions(-) diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c index 34b78f6..00c61c5 100644 --- a/cpuid_tool/cpuid_tool.c +++ b/cpuid_tool/cpuid_tool.c @@ -92,7 +92,8 @@ int need_input = 0, need_clockreport = 0, need_timed_clockreport = 0, verbose_level = 0, - need_version = 0; + need_version = 0, + need_cpulist = 0; #define MAX_REQUESTS 32 int num_requests = 0; @@ -152,6 +153,7 @@ static void usage(void) printf(" --outfile= - redirect all output to this file, instead of stdout\n"); printf(" --verbose, -v - be extra verbose (more keys increase verbosiness level)\n"); printf(" --version - print library version\n"); + printf(" --cpulist - list all known CPUs\n"); printf("\n"); printf("Query switches (generate 1 line of ouput per switch; in order of appearance):"); @@ -258,6 +260,10 @@ static int parse_cmdline(int argc, char** argv) need_version = 1; recog = 1; } + if (!strcmp(arg, "--cpulist")) { + need_cpulist = 1; + recog = 1; + } if (arg[0] == '-' && arg[1] == 'v') { num_vs = 1; while (arg[num_vs] == 'v') @@ -401,6 +407,31 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, } } +static void print_cpulist(void) +{ + int i, j; + struct cpu_list_t list; + const struct { const char *name; cpu_vendor_t vendor; } cpu_vendors[] = { + { "Intel", VENDOR_INTEL }, + { "AMD", VENDOR_AMD }, + { "Cyrix", VENDOR_CYRIX }, + { "NexGen", VENDOR_NEXGEN }, + { "Transmeta", VENDOR_TRANSMETA }, + { "UMC", VENDOR_UMC }, + { "Centaur/VIA", VENDOR_CENTAUR }, + { "Rise", VENDOR_RISE }, + { "SiS", VENDOR_SIS }, + { "NSC", VENDOR_NSC }, + }; + for (i = 0; i < sizeof(cpu_vendors)/sizeof(cpu_vendors[0]); i++) { + fprintf(fout, "-----%s-----\n", cpu_vendors[i].name); + cpuid_get_cpu_list(cpu_vendors[i].vendor, &list); + for (j = 0; j < list.num_entries; j++) + fprintf(fout, "%s\n", list.names[j]); + cpuid_free_cpu_list(&list); + } +} + int main(int argc, char** argv) { int parseres = parse_cmdline(argc, argv); @@ -578,6 +609,9 @@ int main(int argc, char** argv) for (i = 0; i < num_requests; i++) print_info(requests[i], &raw, &data); } + if (need_cpulist) { + print_cpulist(); + } return 0; } diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index 8782c17..383d47e 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -33,6 +33,7 @@ #endif #include #include +#include /* Implementation: */ @@ -253,6 +254,26 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat return set_error(ERR_OK); } +static void make_list_from_string(const char* csv, struct cpu_list_t* list) +{ + int i, n, l, last; + l = (int) strlen(csv); + n = 0; + for (i = 0; i < l; i++) if (csv[i] == ',') n++; + n++; + list->num_entries = n; + list->names = (char**) malloc(sizeof(char*) * n); + last = -1; + n = 0; + for (i = 0; i <= l; i++) if (i == l || csv[i] == ',') { + list->names[n] = (char*) malloc(i - last); + memcpy(list->names[n], &csv[last + 1], i - last - 1); + list->names[n][i - last - 1] = '\0'; + n++; + last = i; + } +} + /* Interface: */ @@ -538,3 +559,51 @@ void cpuid_set_verbosiness_level(int level) { _current_verboselevel = level; } + +void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list) +{ + switch (vendor) { + case VENDOR_INTEL: + cpuid_get_list_intel(list); + break; + case VENDOR_AMD: + cpuid_get_list_amd(list); + break; + case VENDOR_CYRIX: + make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list); + break; + case VENDOR_NEXGEN: + make_list_from_string("Nx586", list); + break; + case VENDOR_TRANSMETA: + make_list_from_string("Crusoe,Efficeon", list); + break; + case VENDOR_UMC: + make_list_from_string("UMC x86 CPU", list); + break; + case VENDOR_CENTAUR: + make_list_from_string("VIA C3,VIA C7,VIA Nano", list); + break; + case VENDOR_RISE: + make_list_from_string("Rise mP6", list); + break; + case VENDOR_SIS: + make_list_from_string("SiS mP6", list); + break; + case VENDOR_NSC: + make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list); + break; + default: + warnf("Unknown vendor passed to cpuid_get_cpu_list()\n"); + break; + } +} + +void cpuid_free_cpu_list(struct cpu_list_t* list) +{ + int i; + if (list->num_entries <= 0) return; + for (i = 0; i < list->num_entries; i++) + free(list->names[i]); + free(list->names); +} diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 4296ef2..d7da135 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -648,6 +648,43 @@ libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun); */ void cpuid_set_verbosiness_level(int level); + +/** @see cpuid_get_cpu_list */ +struct cpu_list_t { + int num_entries; + char **names; +}; + +/** + * @brief Gets a list of all known CPU names from a specific vendor. + * + * This function compiles a list of all known CPU (code)names + * (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor. + * + * There are about 100 entries for Intel and AMD, and a few for the other + * vendors. The list is written out in approximate chronological introduction + * order of the parts. + * + * @param vendor - the vendor to be queried + * @param list [out] - the resulting list will be written here. The `names' + * field of the structure will hold the names (memory is + * allocated by this function). `num_entries' will hold + * the count. + * NOTE: As the memory is dynamically allocated, be sure to call + * @see cpuid_free_cpu_list() after you're done with the data + */ +void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list); + +/** + * @brief Frees a CPU list + * + * This function deletes all the memory associated with a CPU list, as obtained + * by @see cpuid_get_cpu_list() + * + * @param list - the list to be free()'d. + */ +void cpuid_free_cpu_list(struct cpu_list_t* list); + #ifdef __cplusplus }; /* extern "C" */ #endif diff --git a/libcpuid/libcpuid_util.c b/libcpuid/libcpuid_util.c index 856236a..7465233 100644 --- a/libcpuid/libcpuid_util.c +++ b/libcpuid/libcpuid_util.c @@ -108,3 +108,23 @@ void match_cpu_codename(const struct match_entry_t* matchtable, int count, } strcpy(data->cpu_codename, matchtable[bestindex].name); } + +void generic_get_cpu_list(const struct match_entry_t* matchtable, int count, + struct cpu_list_t* list) +{ + int i, j, n, good; + n = 0; + list->names = (char**) malloc(sizeof(char*) * count); + for (i = 0; i < count; i++) { + if (strstr(matchtable[i].name, "Unknown")) continue; + good = 1; + for (j = n - 1; j >= 0; j--) + if (!strcmp(list->names[j], matchtable[i].name)) { + good = 0; + break; + } + if (!good) continue; + list->names[n++] = strdup(matchtable[i].name); + } + list->num_entries = n; +} diff --git a/libcpuid/libcpuid_util.h b/libcpuid/libcpuid_util.h index 93f665a..383d283 100644 --- a/libcpuid/libcpuid_util.h +++ b/libcpuid/libcpuid_util.h @@ -50,8 +50,13 @@ void warnf(const char* format, ...) __attribute__((format(printf, 1, 2))) #endif ; - -void debugf(int verboselevel, const char* format, ...); +void debugf(int verboselevel, const char* format, ...) +#ifdef __GNUC__ +__attribute__((format(printf, 2, 3))) +#endif +; +void generic_get_cpu_list(const struct match_entry_t* matchtable, int count, + struct cpu_list_t* list); extern libcpuid_warn_fn_t _warn_fun; extern int _current_verboselevel; diff --git a/libcpuid/recog_amd.c b/libcpuid/recog_amd.c index ec51f42..1cde1e5 100644 --- a/libcpuid/recog_amd.c +++ b/libcpuid/recog_amd.c @@ -406,3 +406,8 @@ int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data) decode_amd_codename(raw, data); return 0; } + +void cpuid_get_list_amd(struct cpu_list_t* list) +{ + generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list); +} diff --git a/libcpuid/recog_amd.h b/libcpuid/recog_amd.h index e5d3ccf..e0f3b61 100644 --- a/libcpuid/recog_amd.h +++ b/libcpuid/recog_amd.h @@ -27,5 +27,6 @@ #define __RECOG_AMD_H__ int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data); +void cpuid_get_list_amd(struct cpu_list_t* list); #endif /* __RECOG_AMD_H__ */ diff --git a/libcpuid/recog_intel.c b/libcpuid/recog_intel.c index 1898426..122f262 100644 --- a/libcpuid/recog_intel.c +++ b/libcpuid/recog_intel.c @@ -135,7 +135,52 @@ const struct match_entry_t cpudb_intel[] = { { 6, 10, -1, -1, -1, 1, -1, CELERON , 0, "P-III Celeron" }, { 6, 11, -1, -1, -1, 1, -1, CELERON , 0, "P-III Celeron" }, + /* Netburst based (Pentium 4 and later) + classic P4s */ + { 15, -1, -1, -1, -1, 1, -1, NO_CODE , 0, "Unknown Pentium 4" }, + { 15, -1, -1, 15, -1, 1, -1, CELERON , 0, "Unknown P-4 Celeron" }, + { 15, -1, -1, 15, -1, 1, -1, XEON , 0, "Unknown Xeon" }, + + { 15, 0, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Willamette)" }, + { 15, 1, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Willamette)" }, + { 15, 2, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Northwood)" }, + { 15, 3, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Prescott)" }, + { 15, 4, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Prescott)" }, + { 15, 6, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Cedar Mill)" }, + { 15, 0, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Willamette)" }, + { 15, 1, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Willamette)" }, + { 15, 2, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Northwood)" }, + { 15, 3, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Prescott)" }, + { 15, 4, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Prescott)" }, + { 15, 6, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Cedar Mill)" }, + + /* server CPUs */ + { 15, 0, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Foster)" }, + { 15, 1, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Foster)" }, + { 15, 2, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Prestonia)" }, + { 15, 2, -1, 15, -1, 1, -1, XEONMP , 0, "Xeon (Gallatin)" }, + { 15, 3, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Nocona)" }, + { 15, 4, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Nocona)" }, + { 15, 4, -1, 15, -1, 1, -1, XEON_IRWIN , 0, "Xeon (Irwindale)" }, + { 15, 4, -1, 15, -1, 1, -1, XEONMP , 0, "Xeon (Cranford)" }, + { 15, 4, -1, 15, -1, 1, -1, XEON_POTOMAC , 0, "Xeon (Potomac)" }, + { 15, 6, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Dempsey)" }, + + /* Pentium Ds */ + { 15, 4, 4, 15, -1, 1, -1, NO_CODE , 0, "Pentium D" }, + { 15, 4, -1, 15, -1, 1, -1, PENTIUM_D , 0, "Pentium D" }, + { 15, 4, 7, 15, -1, 1, -1, NO_CODE , 0, "Pentium D" }, + { 15, 6, -1, 15, -1, 1, -1, PENTIUM_D , 0, "Pentium D" }, + + /* Celeron and Celeron Ds */ + { 15, 1, -1, 15, -1, 1, -1, CELERON , 0, "P-4 Celeron (128K)" }, + { 15, 2, -1, 15, -1, 1, -1, CELERON , 0, "P-4 Celeron (128K)" }, + { 15, 3, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, + { 15, 4, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, + { 15, 6, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, + /* -------------------------------------------------- */ + /* Intel Core microarchitecture - P6-based */ { 6, 9, -1, -1, -1, 1, -1, NO_CODE , 0, "Unknown Pentium M" }, { 6, 9, -1, -1, -1, 1, -1, MOBILE_PENTIUM_M , 0, "Unknown Pentium M" }, @@ -207,54 +252,10 @@ const struct match_entry_t cpudb_intel[] = { { 6, 7, -1, -1, 23, 4, 3072, XEON , X3300, "Xeon (Yorkfield/3M)" }, { 6, 7, -1, -1, 23, 4, 6144, XEON , X3300, "Xeon (Yorkfield/6M)" }, - /* Itaniums */ { 7, -1, -1, -1, -1, 1, -1, NO_CODE , 0, "Itanium" }, { 15, -1, -1, 16, -1, 1, -1, NO_CODE , 0, "Itanium 2" }, - /* Netburst based (Pentium 4 and later) - classic P4s */ - { 15, -1, -1, -1, -1, 1, -1, NO_CODE , 0, "Unknown Pentium 4" }, - { 15, -1, -1, 15, -1, 1, -1, CELERON , 0, "Unknown P-4 Celeron" }, - { 15, -1, -1, 15, -1, 1, -1, XEON , 0, "Unknown Xeon" }, - - { 15, 0, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Willamette)" }, - { 15, 1, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Willamette)" }, - { 15, 2, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Northwood)" }, - { 15, 3, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Prescott)" }, - { 15, 4, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Prescott)" }, - { 15, 6, -1, 15, -1, 1, -1, NO_CODE , 0, "Pentium 4 (Cedar Mill)" }, - { 15, 0, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Willamette)" }, - { 15, 1, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Willamette)" }, - { 15, 2, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Northwood)" }, - { 15, 3, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Prescott)" }, - { 15, 4, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Prescott)" }, - { 15, 6, -1, 15, -1, 1, -1, MOBILE_PENTIUM , 0, "Mobile P-4 (Cedar Mill)" }, - - /* server CPUs */ - { 15, 0, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Foster)" }, - { 15, 1, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Foster)" }, - { 15, 2, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Prestonia)" }, - { 15, 2, -1, 15, -1, 1, -1, XEONMP , 0, "Xeon (Gallatin)" }, - { 15, 3, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Nocona)" }, - { 15, 4, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Nocona)" }, - { 15, 4, -1, 15, -1, 1, -1, XEON_IRWIN , 0, "Xeon (Irwindale)" }, - { 15, 4, -1, 15, -1, 1, -1, XEONMP , 0, "Xeon (Cranford)" }, - { 15, 4, -1, 15, -1, 1, -1, XEON_POTOMAC , 0, "Xeon (Potomac)" }, - { 15, 6, -1, 15, -1, 1, -1, XEON , 0, "Xeon (Dempsey)" }, - - /* Pentium Ds */ - { 15, 4, 4, 15, -1, 1, -1, NO_CODE , 0, "Pentium D" }, - { 15, 4, -1, 15, -1, 1, -1, PENTIUM_D , 0, "Pentium D" }, - { 15, 4, 7, 15, -1, 1, -1, NO_CODE , 0, "Pentium D" }, - { 15, 6, -1, 15, -1, 1, -1, PENTIUM_D , 0, "Pentium D" }, - - /* Celeron and Celeron Ds */ - { 15, 1, -1, 15, -1, 1, -1, CELERON , 0, "P-4 Celeron (128K)" }, - { 15, 2, -1, 15, -1, 1, -1, CELERON , 0, "P-4 Celeron (128K)" }, - { 15, 3, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, - { 15, 4, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, - { 15, 6, -1, 15, -1, 1, -1, CELERON , 0, "Celeron D" }, }; @@ -637,3 +638,8 @@ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data) get_brand_code(data), get_model_code(data)); return 0; } + +void cpuid_get_list_intel(struct cpu_list_t* list) +{ + generic_get_cpu_list(cpudb_intel, COUNT_OF(cpudb_intel), list); +} diff --git a/libcpuid/recog_intel.h b/libcpuid/recog_intel.h index dbb8841..6727937 100644 --- a/libcpuid/recog_intel.h +++ b/libcpuid/recog_intel.h @@ -27,5 +27,6 @@ #define __RECOG_INTEL_H__ int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data); +void cpuid_get_list_intel(struct cpu_list_t* list); #endif /*__RECOG_INTEL_H__*/