vulcanos/kernel/drivers/cpuid.c
2021-01-04 17:54:22 +01:00

196 lines
5.7 KiB
C

#include "cpuid.h"
#include "../libc/string.h"
#define INTEL_MAGIC_NUMBER 0x756e6547
#define AMD_MAGIC_NUMBER 0x68747541
#define UNRECOGNIZED_CPU 0xBADFF
static cpuid_t get_cpuid(icpuid_t cpu);
static icpuid_t detect_cpu(void);
static icpuid_t intel_cpu(void);
static icpuid_t amd_cpu(void);
static icpuid_t generic_cpu(void);
icpuid_t detect_cpu(void) {
uint32_t ebx, null;
icpuid_t i_cpu;
cpuid(0, null, ebx, null, null);
// Select CPU brand
switch(ebx) {
case INTEL_MAGIC_NUMBER:
i_cpu = intel_cpu();
break;
case AMD_MAGIC_NUMBER:
i_cpu = amd_cpu();
break;
default:
i_cpu = generic_cpu();
break;
}
return i_cpu;
}
icpuid_t intel_cpu(void) {
uint32_t eax, ebx, null;
icpuid_t icpu;
// Fill the structure
cpuid(1, eax, ebx, null, null);
icpu.model = (eax >> 4) & 0xF;
icpu.family = (eax >> 8) & 0xF;
icpu.type = (eax >> 12) & 0xF;
icpu.brand = INTEL_MAGIC_NUMBER;
icpu.stepping = eax & 0xF;
icpu.reserved = eax >> 14;
return icpu;
}
icpuid_t amd_cpu(void) {
uint32_t eax, null;
icpuid_t icpu;
// Fill the structure
cpuid(1, eax, null, null, null);
icpu.model = (eax >> 4) & 0xF;
icpu.family = (eax >> 8) & 0xF;
icpu.stepping = eax & 0xF;
icpu.reserved = eax >> 12;
icpu.brand = AMD_MAGIC_NUMBER;
return icpu;
}
icpuid_t generic_cpu(void) {
icpuid_t icpu;
icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs
return icpu;
}
cpuid_t get_cpuid(icpuid_t cpu) {
cpuid_t cpuid;
uint8_t model[64];
// Recognize CPU brand
if(cpu.brand == AMD_MAGIC_NUMBER) {
switch(cpu.family) {
case 4:
strcpy(model, (uint8_t*)"486 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model;
break;
case 5:
switch(cpu.model) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
strcpy(model, (uint8_t*)"K6 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model;
break;
case 8:
strcpy(model, (uint8_t*)"K6-2 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model;
break;
case 9:
strcpy(model, (uint8_t*)"K6-III model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model;
break;
default:
strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name
strcat(model, (void*)cpu.model); // Set model version
cpuid.model = model;
break;
}
break;
case 6:
switch(cpu.model) {
case 1:
case 2:
case 3:
cpuid.model = (uint8_t*)"Duron model 3";
break;
case 4:
strcpy(model, (uint8_t*)"Athlon model ");
strcat(model, (void*)cpu.model);
cpuid.model = model;
break;
case 6:
cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6";
break;
case 7:
cpuid.model = (uint8_t*)"Mobile Duron Model 7";
break;
default:
strcpy(model, (uint8_t*)"Duron/Athlon model ");
strcat(model, (void*)cpu.model);
cpuid.model = model;
break;
}
break;
}
} else if(cpu.brand == INTEL_MAGIC_NUMBER) {
switch(cpu.type) {
case 0:
cpuid.type =(uint8_t*)"Original OEM";
break;
case 1:
cpuid.type = (uint8_t*)"Overdrive";
break;
case 2:
cpuid.type = (uint8_t*)"Dual-capable";
break;
case 3:
cpuid.type = (uint8_t*)"Reserved";
break;
}
switch(cpu.family) {
case 3:
cpuid.family = (uint8_t*)"i386";
break;
case 4:
cpuid.family = (uint8_t*)"i486";
break;
case 5:
cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron";
break;
case 6:
cpuid.family = (uint8_t*)"Pentium Pro";
break;
case 15:
cpuid.family = (uint8_t*)"Pentium 4";
break;
}
} else if(cpu.brand == UNRECOGNIZED_CPU)
cpuid.family = (uint8_t*)"Generic (x86) CPU";
return cpuid;
}
uint8_t *get_cpu_type() {
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
cpuid_t cpu_type = get_cpuid(icpu);
return (uint8_t*)cpu_type.type;
}
uint8_t *get_cpu_family() {
icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
cpuid_t cpu_family = get_cpuid(icpu);
return (uint8_t*)cpu_family.family;
}