[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");
|
kprintf("I'm going to make text shorter. This is a silly demo.\n");
|
||||||
outportb(0x3D4, 0x9);
|
outportb(0x3D4, 0x9);
|
||||||
outportb(0x3D5, 0x0E);
|
outportb(0x3D5, 0x0E);
|
||||||
|
} else if (!strcmp(cmd, "cpu-detect")) {
|
||||||
|
detect_cpu();
|
||||||
} else if (!strcmp(cmd, "scroll")) {
|
} else if (!strcmp(cmd, "scroll")) {
|
||||||
bochs_scroll();
|
bochs_scroll();
|
||||||
} else if (!strcmp(cmd, "vid-mode")) {
|
} 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 */
|
/* CMOS */
|
||||||
extern void get_time(uint16_t * hours, uint16_t * minutes, uint16_t * seconds);
|
extern void get_time(uint16_t * hours, uint16_t * minutes, uint16_t * seconds);
|
||||||
|
|
||||||
|
/* CPU Detect by Brynet */
|
||||||
|
extern int detect_cpu();
|
||||||
|
|
||||||
/* Video Drivers */
|
/* Video Drivers */
|
||||||
/* BOCHS / QEMU VBE Driver */
|
/* BOCHS / QEMU VBE Driver */
|
||||||
extern void graphics_install_bochs();
|
extern void graphics_install_bochs();
|
||||||
|
Loading…
Reference in New Issue
Block a user