[cpu] CPU detection by Brynet, BSD license
This commit is contained in:
parent
9057eade4e
commit
2686ba9cc1
374
kernel/core/cpudet.c
Normal file
374
kernel/core/cpudet.c
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 - http://brynet.biz.tm - <brynet@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* = CHANGES =
|
||||
* Ported to ToAruOS kernel environment by replacing printf() with kprintf()
|
||||
* Included <system.h>, the kernel C library header.
|
||||
*/
|
||||
|
||||
/* You need to include a file with fairly(ish) compliant printf prototype, Decimal and String support like %s and %d and this is truely all you need! */
|
||||
//#include <stdio.h> /* for kprintf(); */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
/* Required Declarations */
|
||||
int do_intel(void);
|
||||
int do_amd(void);
|
||||
void printregs(int eax, int ebx, int ecx, int edx);
|
||||
|
||||
#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
|
||||
|
||||
/* Simply call this function detect_cpu(); */
|
||||
int detect_cpu(void) { /* or main() if your trying to port this as an independant application */
|
||||
unsigned long ebx, unused;
|
||||
cpuid(0, unused, ebx, unused, unused);
|
||||
switch(ebx) {
|
||||
case 0x756e6547: /* Intel Magic Code */
|
||||
do_intel();
|
||||
break;
|
||||
case 0x68747541: /* AMD Magic Code */
|
||||
do_amd();
|
||||
break;
|
||||
default:
|
||||
kprintf("Unknown x86 CPU Detected\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Intel Specific brand list */
|
||||
char *Intel[] = {
|
||||
"Brand ID Not Supported.",
|
||||
"Intel(R) Celeron(R) processor",
|
||||
"Intel(R) Pentium(R) III processor",
|
||||
"Intel(R) Pentium(R) III Xeon(R) processor",
|
||||
"Intel(R) Pentium(R) III processor",
|
||||
"Reserved",
|
||||
"Mobile Intel(R) Pentium(R) III processor-M",
|
||||
"Mobile Intel(R) Celeron(R) processor",
|
||||
"Intel(R) Pentium(R) 4 processor",
|
||||
"Intel(R) Pentium(R) 4 processor",
|
||||
"Intel(R) Celeron(R) processor",
|
||||
"Intel(R) Xeon(R) Processor",
|
||||
"Intel(R) Xeon(R) processor MP",
|
||||
"Reserved",
|
||||
"Mobile Intel(R) Pentium(R) 4 processor-M",
|
||||
"Mobile Intel(R) Pentium(R) Celeron(R) processor",
|
||||
"Reserved",
|
||||
"Mobile Genuine Intel(R) processor",
|
||||
"Intel(R) Celeron(R) M processor",
|
||||
"Mobile Intel(R) Celeron(R) processor",
|
||||
"Intel(R) Celeron(R) processor",
|
||||
"Mobile Geniune Intel(R) processor",
|
||||
"Intel(R) Pentium(R) M processor",
|
||||
"Mobile Intel(R) Celeron(R) processor"
|
||||
};
|
||||
|
||||
/* This table is for those brand strings that have two values depending on the processor signature. It should have the same number of entries as the above table. */
|
||||
char *Intel_Other[] = {
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Intel(R) Celeron(R) processor",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Intel(R) Xeon(R) processor MP",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Intel(R) Xeon(R) processor",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
/* Intel-specific information */
|
||||
int do_intel(void) {
|
||||
kprintf("Intel Specific Features:\n");
|
||||
unsigned long eax, ebx, ecx, edx, max_eax, signature, unused;
|
||||
int model, family, type, brand, stepping, reserved;
|
||||
int extended_family = -1;
|
||||
cpuid(1, eax, ebx, unused, unused);
|
||||
model = (eax >> 4) & 0xf;
|
||||
family = (eax >> 8) & 0xf;
|
||||
type = (eax >> 12) & 0x3;
|
||||
brand = ebx & 0xff;
|
||||
stepping = eax & 0xf;
|
||||
reserved = eax >> 14;
|
||||
signature = eax;
|
||||
kprintf("Type %d - ", type);
|
||||
switch(type) {
|
||||
case 0:
|
||||
kprintf("Original OEM");
|
||||
break;
|
||||
case 1:
|
||||
kprintf("Overdrive");
|
||||
break;
|
||||
case 2:
|
||||
kprintf("Dual-capable");
|
||||
break;
|
||||
case 3:
|
||||
kprintf("Reserved");
|
||||
break;
|
||||
}
|
||||
kprintf("\n");
|
||||
kprintf("Family %d - ", family);
|
||||
switch(family) {
|
||||
case 3:
|
||||
kprintf("i386");
|
||||
break;
|
||||
case 4:
|
||||
kprintf("i486");
|
||||
break;
|
||||
case 5:
|
||||
kprintf("Pentium");
|
||||
break;
|
||||
case 6:
|
||||
kprintf("Pentium Pro");
|
||||
break;
|
||||
case 15:
|
||||
kprintf("Pentium 4");
|
||||
}
|
||||
kprintf("\n");
|
||||
if(family == 15) {
|
||||
extended_family = (eax >> 20) & 0xff;
|
||||
kprintf("Extended family %d\n", extended_family);
|
||||
}
|
||||
kprintf("Model %d - ", model);
|
||||
switch(family) {
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
switch(model) {
|
||||
case 0:
|
||||
case 1:
|
||||
kprintf("DX");
|
||||
break;
|
||||
case 2:
|
||||
kprintf("SX");
|
||||
break;
|
||||
case 3:
|
||||
kprintf("487/DX2");
|
||||
break;
|
||||
case 4:
|
||||
kprintf("SL");
|
||||
break;
|
||||
case 5:
|
||||
kprintf("SX2");
|
||||
break;
|
||||
case 7:
|
||||
kprintf("Write-back enhanced DX2");
|
||||
break;
|
||||
case 8:
|
||||
kprintf("DX4");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch(model) {
|
||||
case 1:
|
||||
kprintf("60/66");
|
||||
break;
|
||||
case 2:
|
||||
kprintf("75-200");
|
||||
break;
|
||||
case 3:
|
||||
kprintf("for 486 system");
|
||||
break;
|
||||
case 4:
|
||||
kprintf("MMX");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch(model) {
|
||||
case 1:
|
||||
kprintf("Pentium Pro");
|
||||
break;
|
||||
case 3:
|
||||
kprintf("Pentium II Model 3");
|
||||
break;
|
||||
case 5:
|
||||
kprintf("Pentium II Model 5/Xeon/Celeron");
|
||||
break;
|
||||
case 6:
|
||||
kprintf("Celeron");
|
||||
break;
|
||||
case 7:
|
||||
kprintf("Pentium III/Pentium III Xeon - external L2 cache");
|
||||
break;
|
||||
case 8:
|
||||
kprintf("Pentium III/Pentium III Xeon - internal L2 cache");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
break;
|
||||
}
|
||||
kprintf("\n");
|
||||
cpuid(0x80000000, max_eax, unused, unused, unused);
|
||||
/* Quok said: If the max extended eax value is high enough to support the processor brand string
|
||||
(values 0x80000002 to 0x80000004), then we'll use that information to return the brand information.
|
||||
Otherwise, we'll refer back to the brand tables above for backwards compatibility with older processors.
|
||||
According to the Sept. 2006 Intel Arch Software Developer's Guide, if extended eax values are supported,
|
||||
then all 3 values for the processor brand string are supported, but we'll test just to make sure and be safe. */
|
||||
if(max_eax >= 0x80000004) {
|
||||
kprintf("Brand: ");
|
||||
if(max_eax >= 0x80000002) {
|
||||
cpuid(0x80000002, eax, ebx, ecx, edx);
|
||||
printregs(eax, ebx, ecx, edx);
|
||||
}
|
||||
if(max_eax >= 0x80000003) {
|
||||
cpuid(0x80000003, eax, ebx, ecx, edx);
|
||||
printregs(eax, ebx, ecx, edx);
|
||||
}
|
||||
if(max_eax >= 0x80000004) {
|
||||
cpuid(0x80000004, eax, ebx, ecx, edx);
|
||||
printregs(eax, ebx, ecx, edx);
|
||||
}
|
||||
kprintf("\n");
|
||||
} else if(brand > 0) {
|
||||
kprintf("Brand %d - ", brand);
|
||||
if(brand < 0x18) {
|
||||
if(signature == 0x000006B1 || signature == 0x00000F13) {
|
||||
kprintf("%s\n", Intel_Other[brand]);
|
||||
} else {
|
||||
kprintf("%s\n", Intel[brand]);
|
||||
}
|
||||
} else {
|
||||
kprintf("Reserved\n");
|
||||
}
|
||||
}
|
||||
kprintf("Stepping: %d Reserved: %d\n", stepping, reserved);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print Registers */
|
||||
void printregs(int eax, int ebx, int ecx, int edx) {
|
||||
int j;
|
||||
char string[17];
|
||||
string[16] = '\0';
|
||||
for(j = 0; j < 4; j++) {
|
||||
string[j] = eax >> (8 * j);
|
||||
string[j + 4] = ebx >> (8 * j);
|
||||
string[j + 8] = ecx >> (8 * j);
|
||||
string[j + 12] = edx >> (8 * j);
|
||||
}
|
||||
kprintf("%s", string);
|
||||
}
|
||||
|
||||
/* AMD-specific information */
|
||||
int do_amd(void) {
|
||||
kprintf("AMD Specific Features:\n");
|
||||
unsigned long extended, eax, ebx, ecx, edx, unused;
|
||||
int family, model, stepping, reserved;
|
||||
cpuid(1, eax, unused, unused, unused);
|
||||
model = (eax >> 4) & 0xf;
|
||||
family = (eax >> 8) & 0xf;
|
||||
stepping = eax & 0xf;
|
||||
reserved = eax >> 12;
|
||||
kprintf("Family: %d Model: %d [", family, model);
|
||||
switch(family) {
|
||||
case 4:
|
||||
kprintf("486 Model %d", model);
|
||||
break;
|
||||
case 5:
|
||||
switch(model) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 6:
|
||||
case 7:
|
||||
kprintf("K6 Model %d", model);
|
||||
break;
|
||||
case 8:
|
||||
kprintf("K6-2 Model 8");
|
||||
break;
|
||||
case 9:
|
||||
kprintf("K6-III Model 9");
|
||||
break;
|
||||
default:
|
||||
kprintf("K5/K6 Model %d", model);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
switch(model) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
kprintf("Athlon Model %d", model);
|
||||
break;
|
||||
case 3:
|
||||
kprintf("Duron Model 3");
|
||||
break;
|
||||
case 6:
|
||||
kprintf("Athlon MP/Mobile Athlon Model 6");
|
||||
break;
|
||||
case 7:
|
||||
kprintf("Mobile Duron Model 7");
|
||||
break;
|
||||
default:
|
||||
kprintf("Duron/Athlon Model %d", model);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
kprintf("]\n");
|
||||
cpuid(0x80000000, extended, unused, unused, unused);
|
||||
if(extended == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(extended >= 0x80000002) {
|
||||
unsigned int j;
|
||||
kprintf("Detected Processor Name: ");
|
||||
for(j = 0x80000002; j <= 0x80000004; j++) {
|
||||
cpuid(j, eax, ebx, ecx, edx);
|
||||
printregs(eax, ebx, ecx, edx);
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
if(extended >= 0x80000007) {
|
||||
cpuid(0x80000007, unused, unused, unused, edx);
|
||||
if(edx & 1) {
|
||||
kprintf("Temperature Sensing Diode Detected!\n");
|
||||
}
|
||||
}
|
||||
kprintf("Stepping: %d Reserved: %d\n", stepping, reserved);
|
||||
return 0;
|
||||
}
|
@ -202,6 +202,8 @@ start_shell() {
|
||||
kprintf("I'm going to make text shorter. This is a silly demo.\n");
|
||||
outportb(0x3D4, 0x9);
|
||||
outportb(0x3D5, 0x0E);
|
||||
} else if (!strcmp(cmd, "cpu-detect")) {
|
||||
detect_cpu();
|
||||
} else if (!strcmp(cmd, "scroll")) {
|
||||
bochs_scroll();
|
||||
} else if (!strcmp(cmd, "vid-mode")) {
|
||||
|
18
kernel/core/video/font.c
Normal file
18
kernel/core/video/font.c
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* vim:tabstop=4
|
||||
* vim:noexpandtab
|
||||
*
|
||||
* Standard VGA-like Alphanumeric Font
|
||||
*/
|
||||
|
||||
char fb_font [][8] = {
|
||||
/* _ */
|
||||
{ 0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00, /* 4 */
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00 } /* 8 */
|
||||
};
|
@ -183,6 +183,9 @@ extern void parse_args(char * argv);
|
||||
/* CMOS */
|
||||
extern void get_time(uint16_t * hours, uint16_t * minutes, uint16_t * seconds);
|
||||
|
||||
/* CPU Detect by Brynet */
|
||||
extern int detect_cpu();
|
||||
|
||||
/* Video Drivers */
|
||||
/* BOCHS / QEMU VBE Driver */
|
||||
extern void graphics_install_bochs();
|
||||
|
Loading…
Reference in New Issue
Block a user