summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-09-22 22:20:42 +0200
committerMichael Brown2012-07-09 16:41:42 +0200
commit1abd405570a2692adcc3bef3845bfb9178a1d952 (patch)
treee00898ca6512883677073335334add8e3b22b33d
parent[import] Import version 2.11 (diff)
downloadmemtest86-1abd405570a2692adcc3bef3845bfb9178a1d952.tar.gz
memtest86-1abd405570a2692adcc3bef3845bfb9178a1d952.tar.xz
memtest86-1abd405570a2692adcc3bef3845bfb9178a1d952.zip
[import] Import version 4.00
http://www.memtest.org/download/4.00/memtest86+-4.00.tar.gz
-rw-r--r--Makefile9
-rw-r--r--README2
-rw-r--r--changelog25
-rw-r--r--config.c32
-rw-r--r--config.h3
-rw-r--r--controller.c171
-rw-r--r--cpuid.c258
-rw-r--r--cpuid.h217
-rw-r--r--dmi.c11
-rw-r--r--error.c26
-rw-r--r--init.c195
-rw-r--r--jedec_id.h887
-rw-r--r--lib.c44
-rw-r--r--main.c230
-rwxr-xr-xmakedos.sh10
-rwxr-xr-xmakeiso.sh6
-rw-r--r--memsize.c141
-rw-r--r--memtest.exebin0 -> 161064 bytes
-rw-r--r--memtest_shared.lds1
-rw-r--r--mt86+_loaderbin784 -> 784 bytes
-rw-r--r--mt86+_loader.asm4
-rw-r--r--pci.c13
-rwxr-xr-x[-rw-r--r--]precomp.binbin116508 -> 160280 bytes
-rw-r--r--smp.c440
-rw-r--r--smp.h265
-rw-r--r--spd.c407
-rw-r--r--spd.h13
-rw-r--r--stdint.h8
-rw-r--r--test.c125
-rw-r--r--test.h20
30 files changed, 3134 insertions, 429 deletions
diff --git a/Makefile b/Makefile
index bffb0d3..5ae302a 100644
--- a/Makefile
+++ b/Makefile
@@ -11,11 +11,11 @@ FDISK=/dev/fd0
AS=as -32
CC=gcc
-CFLAGS= -Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin -ffreestanding -fPIC
+CFLAGS= -Wall -march=i486 -m32 -O2 -fomit-frame-pointer -fno-builtin -ffreestanding -fPIC
OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \
- config.o linuxbios.o memsize.o pci.o controller.o random.o extra.o \
- spd.o error.o dmi.o
+ config.o linuxbios.o memsize.o pci.o controller.o random.o spd.o \
+ error.o dmi.o cpuid.o
all: memtest.bin memtest
@@ -55,6 +55,9 @@ test.o: test.c
clean:
rm -f *.o *.s *.iso memtest.bin memtest memtest_shared memtest_shared.bin
+asm:
+ @./makedos.sh
+
iso:
make all
./makeiso.sh
diff --git a/README b/README
index 6f2d02b..e02ca58 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Memtest86++ v2.10
+Memtest86++ v4.00
====================
Table of Contents
diff --git a/changelog b/changelog
index 201df77..5914646 100644
--- a/changelog
+++ b/changelog
@@ -1,10 +1,19 @@
-Memtest86+ V2.11 changelog
+Memtest86+ V4.00 changelog
--------------------------
- - Added support for Intel Core i5 (Lynnfield) CPU
- - Added support for Intel P55 Southbridge
- - Added support for Intel PM45/GM45/GM47 Mobile chipset
- - Added support for Intel GL40/GS45 Mobile chipset
- - Corrected DDR2/DDR3 detection on Intel x35/x45
- - Corrected detection on some Core i7 CPU
- - Various bug fixes
+ - Major Architectural changes
+ - First pass twice faster (reduced iterations)
+ - Detect DDR2/3 brands and part numbers
+ - Corrected detection for Intel "Lynnfield" CPU
+ - Added detection for Intel "Clarkdale" CPU
+ - Added detection for Intel "Gulftown" CPU
+ - Corrected detection for AMD 45nm K10 CPU
+ - Added detection for AMD "Magny-Cours" CPU
+ - Solved crash with AMD Geode LX
+ - Added detection for Intel XMP Memory
+ - Added for CPU w/ 0.5/1.5/3/6/12/16/18/24MB L3
+ - Added "clean" DMI detection for DDR3/FBDIMM2
+ - Better detection of Integrated Memory Ctrl
+ - Complies with SMBIOS 2.6.1 specs
+ - Fixed compilation issues with gcc 4.2+
+ - Many others bug fixes
diff --git a/config.c b/config.c
index d2dd0f7..6d29004 100644
--- a/config.c
+++ b/config.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V2.00 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -17,6 +17,7 @@ extern int bail, beepmode;
extern struct tseq tseq[];
extern short e820_nr;
extern char memsz_mode;
+extern int find_ticks_for_pass();
//void performance();
char save[2][POP_H][POP_W];
@@ -71,7 +72,7 @@ void get_config()
bail++;
}
v->testsel = -1;
- find_ticks();
+ find_ticks_for_pass();
sflag++;
cprint(LINE_INFO, COL_TST, "Std");
break;
@@ -95,7 +96,7 @@ void get_config()
}
v->testsel = i;
}
- find_ticks();
+ find_ticks_for_pass();
sflag++;
bail++;
cprint(LINE_INFO, COL_TST, "#");
@@ -107,7 +108,7 @@ void get_config()
v->test = -1;
}
v->testsel = 9;
- find_ticks();
+ find_ticks_for_pass();
sflag++;
bail++;
cprint(LINE_INFO, COL_TST, "#");
@@ -120,7 +121,7 @@ void get_config()
v->test = -1;
}
v->testsel = 9+1;
- find_ticks();
+ find_ticks_for_pass();
sflag++;
bail++;
cprint(LINE_INFO, COL_TST, "#");
@@ -163,7 +164,7 @@ void get_config()
bail++;
}
adj_mem();
- find_ticks();
+ find_ticks_for_pass();
sflag++;
break;
case 3:
@@ -183,7 +184,7 @@ void get_config()
bail++;
}
adj_mem();
- find_ticks();
+ find_ticks_for_pass();
sflag++;
break;
case 4:
@@ -193,7 +194,7 @@ void get_config()
v->test--;
bail++;
adj_mem();
- find_ticks();
+ find_ticks_for_pass();
sflag++;
break;
case 11:
@@ -210,14 +211,9 @@ void get_config()
popclear();
cprint(POP_Y+1, POP_X+2, "Memory Sizing:");
cprint(POP_Y+3, POP_X+6, "(1) BIOS - Std");
- if (e820_nr) {
- cprint(POP_Y+4, POP_X+6, "(2) BIOS - All");
- cprint(POP_Y+5, POP_X+6, "(3) Probe");
- cprint(POP_Y+6, POP_X+6, "(0) Continue");
- cprint(POP_Y+2+memsz_mode, POP_X+5, ">");
- } else {
- cprint(POP_Y+4, POP_X+6, "(3) Probe");
+ cprint(POP_Y+4, POP_X+6, "(2) Probe");
cprint(POP_Y+5, POP_X+6, "(0) Continue");
+ if(!e820_nr){
if (memsz_mode == SZ_MODE_BIOS) {
cprint(POP_Y+3, POP_X+5, ">");
} else {
@@ -234,12 +230,6 @@ void get_config()
break;
case 3:
- memsz_mode = SZ_MODE_BIOS_RES;
- wait_keyup();
- restart();
-
- break;
- case 4:
memsz_mode = SZ_MODE_PROBE;
wait_keyup();
restart();
diff --git a/config.h b/config.h
index b5f4573..8e68985 100644
--- a/config.h
+++ b/config.h
@@ -27,6 +27,9 @@
/* BEEP_END_NO_ERROR - Beep at end of each pass without error. Default off, Change to 1 to enable */
#define BEEP_END_NO_ERROR 0
+/* FIRST_PASS_HALF_ITERATIONS - First pass twice faster / half iterations. Change to 0 to disable */
+#define FIRST_PASS_HALF_ITERATIONS 1
+
/* SCRN_DEBUG - extra check for SCREEN_BUFFER
*/
/* #define SCRN_DEBUG */
diff --git a/controller.c b/controller.c
index f57618e..948785b 100644
--- a/controller.c
+++ b/controller.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V2.11 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -13,11 +13,14 @@
#include "test.h"
#include "pci.h"
#include "controller.h"
+#include "spd.h"
+#include "test.h"
int col, col2;
int nhm_bus = 0x3F;
extern ulong extclock;
+extern unsigned long imc_type;
extern struct cpu_ident cpu_id;
#define rdmsr(msr,val1,val2) \
@@ -80,6 +83,7 @@ struct pci_memory_controller {
void (*poll_errors)(void);
};
+
void print_timings_info(float cas, int rcd, int rp, int ras) {
/* Now, we could print some additionnals timings infos) */
@@ -199,8 +203,8 @@ static void setup_nhm(void)
pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
vid &= 0xFFFF;
- did &= 0xFFFF;
- if(vid == 0x8086 && did == 0x2C1C) {
+ did &= 0xFF00;
+ if(vid == 0x8086 && did == 0x2C00) {
nhm_bus = possible_nhm_bus[i];
}
}
@@ -282,6 +286,7 @@ static void setup_k10(void)
unsigned int mcgsth;
unsigned long mcanb;
unsigned long dramcl;
+ ulong msr_low, msr_high;
/* All AMD64 support Chipkill */
ctrl.cap = ECC_CHIPKILL;
@@ -302,7 +307,13 @@ static void setup_k10(void)
/* Clear any previous error */
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
- pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
+ pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
+
+ /* Enable ECS */
+ rdmsr(0xC001001F, msr_low, msr_high);
+ wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
+ rdmsr(0xC001001F, msr_low, msr_high);
+
}
static void poll_amd64(void)
@@ -1258,6 +1269,29 @@ static void poll_fsb_k10(void) {
unsigned long dramchr;
unsigned long mainPllId;
double dramclock;
+ unsigned long pns_low;
+ unsigned long pns_high;
+ unsigned long msr_psn;
+
+
+ /* If ECC not enabled : display CPU name as IMC */
+ if(ctrl.mode == ECC_NONE)
+ {
+ cprint(LINE_CPU+5, 0, "IMC : ");
+ for(msr_psn = 0; msr_psn < 5; msr_psn++)
+ {
+ rdmsr(0xC0010030+msr_psn, pns_low, pns_high);
+ cprint(LINE_CPU+5, 6+(msr_psn*8), convert_hex_to_char(pns_low & 0xff));
+ cprint(LINE_CPU+5, 7+(msr_psn*8), convert_hex_to_char((pns_low >> 8) & 0xff));
+ cprint(LINE_CPU+5, 8+(msr_psn*8), convert_hex_to_char((pns_low >> 16) & 0xff));
+ cprint(LINE_CPU+5, 9+(msr_psn*8), convert_hex_to_char((pns_low >> 24) & 0xff));
+ cprint(LINE_CPU+5, 10+(msr_psn*8), convert_hex_to_char(pns_high & 0xff));
+ cprint(LINE_CPU+5, 11+(msr_psn*8), convert_hex_to_char((pns_high >> 8) & 0xff));
+ cprint(LINE_CPU+5, 12+(msr_psn*8), convert_hex_to_char((pns_high >> 16) & 0xff));
+ cprint(LINE_CPU+5, 13+(msr_psn*8), convert_hex_to_char((pns_high >> 24) & 0xff));
+ }
+ cprint(LINE_CPU+5, 41, "(ECC : Disabled)");
+ }
/* First, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
@@ -2020,15 +2054,15 @@ static void poll_fsb_nhm(void) {
fsb = ((extclock /1000) / coef);
/* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ FSB : ");
- col += 9;
+ cprint(LINE_CPU+5, col +1, "/ BCLK : ");
+ col += 10;
dprint(LINE_CPU+5, col, fsb, 3,0);
col += 3;
cprint(LINE_CPU+5, col +1, "MHz");
col += 4;
/* Print QPI Speed (if ECC not supported) */
- if(ctrl.mode == ECC_NONE) {
+ if(ctrl.mode == ECC_NONE && cpu_id.model == 10) {
pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status);
qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2;
cprint(LINE_CPU+5, col +1, "/ QPI : ");
@@ -2167,9 +2201,9 @@ static void poll_timings_i925(void) {
//Determine DDR or DDR-II
if ((drc & 3) == 2) {
- cprint(LINE_CPU+5, col +1, "- Type : DDR-II");
+ cprint(LINE_CPU+5, col +1, "- Type : DDR2");
} else {
- cprint(LINE_CPU+5, col +1, "- Type : DDR-I");
+ cprint(LINE_CPU+5, col +1, "- Type : DDR1");
}
// Now, detect timings
@@ -2682,11 +2716,11 @@ static void poll_timings_amd64(void) {
// Print 64 or 128 bits mode
if ((dramclr >> 11)&1) {
- cprint(LINE_CPU+6, col2, " DDR-2 (128 bits)");
- col2 +=17;
- } else {
- cprint(LINE_CPU+6, col2, " DDR-2 (64 bits)");
+ cprint(LINE_CPU+6, col2, " DDR2 (128 bits)");
col2 +=16;
+ } else {
+ cprint(LINE_CPU+6, col2, " DDR2 (64 bits)");
+ col2 +=15;
}
} else {
@@ -2720,11 +2754,11 @@ static void poll_timings_amd64(void) {
// Print 64 or 128 bits mode
if (((dramclr >> 16)&1) == 1) {
- cprint(LINE_CPU+6, col2, " DDR-1 (128 bits)");
- col2 +=17;
- } else {
- cprint(LINE_CPU+6, col2, " DDR-1 (64 bits)");
+ cprint(LINE_CPU+6, col2, " DDR1 (128 bits)");
col2 +=16;
+ } else {
+ cprint(LINE_CPU+6, col2, " DDR1 (64 bits)");
+ col2 +=15;
}
}
}
@@ -2732,59 +2766,56 @@ static void poll_timings_amd64(void) {
static void poll_timings_k10(void) {
ulong dramtlr, dramclr, dramchr;
- int temp;
- int trcd, trp, tras ;
-
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
+ ulong offset = 0;
+ int cas, rcd, rp, rc, ras;
- pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr);
- pci_conf_read(0, 24, 2, 0x110, 4, &dramclr);
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
-
- // CAS Latency (tCAS)
- temp = (dramtlr & 0x7) + 1;
- dprint(LINE_CPU+6, col2, temp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
- // RAS-To-CAS (tRCD)
- trcd = ((dramtlr >> 4) & 0x3) + 3;
- dprint(LINE_CPU+6, col2, trcd , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
-
- // RAS Precharge (tRP)
- trp = ((dramtlr >> 8) & 0x3) + 3;
- dprint(LINE_CPU+6, col2, trp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
+ // If Channel A not enabled, switch to channel B
+ if(((dramchr>>14) & 0x1))
+ {
+ offset = 0x100;
+ pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr);
+ }
- // RAS Active to precharge (tRAS)
- tras = ((dramtlr >> 12) & 0xF) + 3;
- dprint(LINE_CPU+6, col2, tras, 1 ,0);
- (tras < 10)?(col2 += 1):(col2 += 2);
- cprint(LINE_CPU+6, col2, "-");
- col2 += 1;
+ pci_conf_read(0, 24, 2, 0x88+offset, 4, &dramtlr);
+ pci_conf_read(0, 24, 2, 0x110, 4, &dramclr);
+
+ // CAS Latency (tCAS)
+ if(((dramchr >> 8)&1) || ((dramchr & 0x7) == 0x4)){
+ // DDR3 or DDR2-1066
+ cas = (dramtlr & 0xF) + 4;
+ rcd = ((dramtlr >> 4) & 0x7) + 5;
+ rp = ((dramtlr >> 7) & 0x7) + 5;
+ ras = ((dramtlr >> 12) & 0xF) + 15;
+ rc = ((dramtlr >> 16) & 0x1F) + 11;
+ } else {
+ // DDR2-800 or less
+ cas = (dramtlr & 0xF) + 1;
+ rcd = ((dramtlr >> 4) & 0x3) + 3;
+ rp = ((dramtlr >> 8) & 0x3) + 3;
+ ras = ((dramtlr >> 12) & 0xF) + 3;
+ rc = ((dramtlr >> 16) & 0x1F) + 11;
+ }
- // Row Cycle Time (tRC)
- trp = ((dramtlr >> 16) & 0x1F) + 11;
- dprint(LINE_CPU+6, col2, trp , 1 ,0);
- col2 +=2;
+ print_timings_info(cas, rcd, rp, ras);
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
+ cprint(LINE_CPU+6, col2, "/"); col2++;
//Print DDR2 or DDR3
if ((dramchr >> 8)&1) {
- cprint(LINE_CPU+6, col2+1, "DDR-3");
+ cprint(LINE_CPU+6, col2+1, "DDR3");
} else {
- cprint(LINE_CPU+6, col2+1, "DDR-2");
+ cprint(LINE_CPU+6, col2+1, "DDR2");
}
- col2 += 6;
+ col2 += 5;
// Print 64 or 128 bits mode
- if ((dramclr >> 4)&1) {
- cprint(LINE_CPU+6, col2+1, "(Dual)");
- } else {
- cprint(LINE_CPU+6, col2+1, "(Single)");
- }
+ if ((dramclr >> 4)&1) {
+ cprint(LINE_CPU+6, col2+1, "(128 bits)");
+ } else {
+ cprint(LINE_CPU+6, col2+1, "(64 bits)");
+ }
}
@@ -2948,8 +2979,6 @@ static struct pci_memory_controller controllers[] = {
{ 0x1022, 0x7006, "AMD 751", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_amd751 },
{ 0x1022, 0x700c, "AMD 762", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
{ 0x1022, 0x700e, "AMD 761", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
- { 0x1022, 0x0000, "AMD K8", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1022, 0x0000, "AMD K10", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing },
/* SiS */
{ 0x1039, 0x0600, "SiS 600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -3081,12 +3110,13 @@ static struct pci_memory_controller controllers[] = {
{ 0x8086, 0x5020, "Intel EP80579", 0, poll_fsb_p4, poll_timings_EP80579, setup_nothing, poll_nothing },
{ 0x8086, 0x8100, "Intel US15W", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
{ 0x8086, 0x8101, "Intel UL11L/US15L", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
- { 0x8086, 0x3400, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0x8086, 0x3401, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0x8086, 0x3402, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0x8086, 0x3403, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0x8086, 0x3404, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0x8086, 0x3405, "NHM IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing}
+
+ /* Integrated Memory Controllers */
+ { 0xFFFF, 0x0001, "Core IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
+ { 0xFFFF, 0x0002, "Core IMC2", 0, poll_fsb_nhm, poll_timings_nothing, setup_nhm, poll_nothing},
+ { 0xFFFF, 0x0100, "AMD K8 IMC", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
+ { 0xFFFF, 0x0101, "AMD K10 IMC", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing }
+
};
static void print_memory_controller(void)
@@ -3155,7 +3185,6 @@ static void print_memory_controller(void)
col += 9;
}
-
/* Print advanced caracteristics */
col2 = 0;
d = get_key();
@@ -3176,6 +3205,10 @@ void find_controller(void)
int result;
result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_VENDOR_ID, 2, &vendor);
result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_DEVICE_ID, 2, &device);
+
+ // Detect IMC by CPUID
+ if(imc_type) { vendor = 0xFFFF; device = imc_type; }
+
ctrl.index = 0;
if (result == 0) {
for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) {
@@ -3185,12 +3218,6 @@ void find_controller(void)
}
}
}
-
- // AMD K8 use integrated mem controller, force detection
- if (cpu_id.type == 15 && cpu_id.vend_id[0] == 'A') { ctrl.index = 4; }
-
- // Same thing for K10. Detect by cpu_id.model = 2, will change it to ext.cpuid > 10 later
- if (cpu_id.type == 15 && cpu_id.vend_id[0] == 'A' && cpu_id.model == 2) { ctrl.index = 5; }
controllers[ctrl.index].setup_ecc();
/* Don't enable ECC polling by default unless it has
diff --git a/cpuid.c b/cpuid.c
new file mode 100644
index 0000000..9a0843b
--- /dev/null
+++ b/cpuid.c
@@ -0,0 +1,258 @@
+/*
+ * cpuid.c --
+ *
+ * Implements CPUID querying functions
+ *
+ */
+#include "cpuid.h"
+
+cpuid_t cpuid_data0;
+cpuid_t cpuid_data80;
+
+unsigned num_logical_cpus = 1; // number of logical cpus per physical package
+unsigned num_cores_per_package = 1; // number of cores in each physical cpu package
+unsigned num_hyper_threads_per_core = 1; // number of hyper-threads per core
+
+void
+cpuid_get(unsigned n, cpuid_t *data)
+{
+ data->eax = n;
+ GET_CPUID(data->eax, data->ebx, data->ecx, data->edx);
+}
+
+
+/* cpuid_get_vendor_string ---
+ *
+ * This function gets the vendor string from the processor's cpuid instruction
+ * and passes it back to the caller in an easy to use structure.
+ */
+cpuid_vendor_string_t
+cpuid_get_vendor_string(void)
+{
+ static cpuid_vendor_string_t v;
+
+ /* Note: the string gets passed in EBX-EDX-ECX, not the intuitive order. */
+ v.uint32_array[0] = cpuid_data0.ebx;
+ v.uint32_array[1] = cpuid_data0.edx;
+ v.uint32_array[2] = cpuid_data0.ecx;
+ v.char_array[CPUID_VENDOR_STR_LENGTH-1] = '\0';
+ return v;
+}
+
+
+/* cpuid_get_version ---
+ *
+ * This function reads the processors version information using CPUID and puts
+ * it into a union for easy use by the caller.
+ */
+cpuid_version_t
+cpuid_get_version(void)
+{
+ cpuid_version_t v;
+ uint32_t junkEBX = 0, junkECX = 0, junkEDX = 0;
+ v.flat = 0x1;
+ GET_CPUID(v.flat, junkEBX, junkECX, junkEDX);
+ return v;
+}
+
+
+cpuid_feature_flags_t
+cpuid_get_feature_flags(void)
+{
+ cpuid_feature_flags_t f;
+ uint32_t junkEAX = 0x1, junkEBX = 0;
+ GET_CPUID(junkEAX, junkEBX, f.uint32_array[1], f.uint32_array[0]);
+ return f;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * cpuid_get_ext_feature_flags --
+ *
+ * Passes back the caller the extended feature flags supported by
+ * this CPU. This can be used, among other things, to determine if the
+ * processor supports long mode.
+ *
+ * Results:
+ * Returns TRUE if the processor supports the extended feature flags
+ * CPUID node, and FALSE otherwise.
+ *
+ * Side effects:
+ * Calls CPUID a couple of times.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+bool
+cpuid_get_ext_feature_flags(cpuid_ext_feature_flags_t *f) // OUT: Flags for this CPU
+{
+ uint32_t eax, ebx, ecx;
+
+ if (cpuid_data80.eax < 0x80000001) {
+ // Extended feature flags not supported on this CPU
+ return FALSE;
+ }
+ eax = CPUID_EXTENDED_FEATURE;
+ GET_CPUID(eax, ebx, ecx, f->flat);
+ return TRUE;
+}
+
+#define CHAR_TO_INT(a,b,c,d) ((a) + (b) * 0x100 + (c) * 0x10000 + (d) * 0x1000000)
+
+bool
+cpuid_is_vendor_amd(void)
+{
+ return cpuid_data0.ebx == CHAR_TO_INT('A', 'u', 't', 'h')
+ && cpuid_data0.edx == CHAR_TO_INT('e', 'n', 't', 'i')
+ && cpuid_data0.ecx == CHAR_TO_INT('c', 'A', 'M', 'D');
+}
+
+
+bool
+cpuid_is_vendor_intel(void)
+{
+ return cpuid_data0.ebx == CHAR_TO_INT('G', 'e', 'n', 'u')
+ && cpuid_data0.edx == CHAR_TO_INT('i', 'n', 'e', 'I')
+ && cpuid_data0.ecx == CHAR_TO_INT('n', 't', 'e', 'l');
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * cpuid_is_family_p4 --
+ *
+ * Returns TRUE if the processor we're running on is an Intel processor
+ * of the P4 family.
+ *
+ * Results:
+ * The obvious.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+bool
+cpuid_is_family_p4(void)
+{
+ cpuid_version_t v = cpuid_get_version();
+
+ return cpuid_is_vendor_intel() && v.bits.family == CPUID_FAMILY_EXTENDED &&
+ v.bits.extendedFamily == CPUID_EXTENDED_FAMILY_PENTIUM4;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * cpuid_is_family_p6 --
+ *
+ * Returns TRUE if the processor we're running on belongs to the P6 family.
+ *
+ * Results:
+ * The obvious.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+bool
+cpuid_is_family_p6(void)
+{
+ cpuid_version_t v = cpuid_get_version();
+
+ return cpuid_is_vendor_intel() && v.bits.family == CPUID_FAMILY_P6;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * cpuid_is_family_opteron --
+ *
+ * Returns TRUE if the processor we're running on belongs to the
+ * Opteron family.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+bool
+cpuid_is_family_opteron(void)
+{
+ cpuid_version_t v = cpuid_get_version();
+ return cpuid_is_vendor_amd() && CPUID_FAMILY_IS_OPTERON(v.flat);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * cpuid_init --
+ *
+ * Executes CPUID and caches values in cpuid_data0 abd cpuid_data80.
+ *
+ *-----------------------------------------------------------------------------
+ */
+void
+cpuid_init(void)
+{
+ //bool htt = FALSE;
+ cpuid_t id1;
+
+ /* First get the basic cpuid information on what the
+ * type of the processor is , i.e intel or amd etc
+ * and how much of extra cpuid information is available
+ * with the processor
+ */
+ cpuid_data0.eax = 0;
+ GET_CPUID(cpuid_data0.eax, cpuid_data0.ebx,
+ cpuid_data0.ecx, cpuid_data0.edx);
+
+
+ /* Find out if hyper-threading is available and there is more than one
+ * logical processor. See section 7.6.3 in Intel IA-32 volume III.
+ */
+ cpuid_get(1, &id1);
+
+ if (cpuid_is_vendor_intel()) {
+ if (cpuid_is_family_p6()) {
+ // Extended CPUID features not supported on PIII
+ return;
+ }
+ if (cpuid_is_family_p4()) {
+ /*
+ * Multi-core processors have the HT feature bit set (even if they
+ * don't support HT).
+ * The number of HT is the total number, not per-core number.
+ * The number of cores is off by 1, i.e. single-core reports 0.
+ */
+ //htt = id1.edx & CPUID_FEATURE_COMMON_ID1EDX_HT;
+ if (id1.edx & CPUID_FEATURE_COMMON_ID1EDX_HT) {
+ num_hyper_threads_per_core = (id1.ebx >> 16) & 0xff;
+ if (cpuid_max_func() >= 4) {
+ cpuid_t id4;
+ cpuid_get(4, &id4);
+ num_cores_per_package = ((id4.eax >> 26) & 0x3f) + 1;
+ num_hyper_threads_per_core /= num_cores_per_package;
+ }
+ }
+ }
+ } else if (cpuid_is_vendor_amd()) {
+ cpuid_data80.eax = 0x80000000;
+ GET_CPUID(cpuid_data80.eax, cpuid_data80.ebx,
+ cpuid_data80.ecx, cpuid_data80.edx);
+ if (cpuid_max_ext_func() >= 0x80000008) {
+ /* Number of cores is reported in extended function 0x80000008
+ * For legacy multi-core support, AMD CPUs report the number of
+ * cores as hyper-threads. Adjust the numbers to reflect that there
+ * are no threads.
+ */
+ cpuid_t id88;
+ cpuid_get(0x80000008, &id88);
+ num_cores_per_package = id88.ecx & 0xff;
+ num_hyper_threads_per_core = 1;
+ }
+ } else {
+ /* Unknown cpu type. we use the defaults */
+ }
+}
diff --git a/cpuid.h b/cpuid.h
new file mode 100644
index 0000000..c35c2ba
--- /dev/null
+++ b/cpuid.h
@@ -0,0 +1,217 @@
+/*
+ * cpuid.h --
+ *
+ * contains the data structures required for CPUID
+ * implementation.
+ *
+ */
+
+#ifndef _CPUID_H_
+#define _CPUID_H_
+#include "stdint.h"
+#include "defs.h"
+#include "smp.h"
+
+#define CPUID_EXTENDED_BASE 0x80000000
+#define CPUID_EXTENDED_FEATURE 0x80000001
+#define CPUID_EXTENDED_BRAND1 0x80000002
+#define CPUID_EXTENDED_BRAND2 0x80000003
+#define CPUID_EXTENDED_BRAND3 0x80000004
+
+#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */
+#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
+#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */
+#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
+
+#define CPUID_FAMILY(_eax) (((_eax) >> 8) & 0xf)
+/* Intel CPU Family */
+#define CPUID_FAMILY_486 4
+#define CPUID_FAMILY_P5 5
+#define CPUID_FAMILY_P6 6
+#define CPUID_FAMILY_EXTENDED 15
+
+#define CPUID_EXTENDED_FAMILY(_eax) (((_eax) >> 20) & 0xff)
+#define CPUID_EXTENDED_FAMILY_PENTIUM4 0
+#define CPUID_EXTENDED_FAMILY_OPTERON 0
+
+
+#define CPUID_FAMILY_IS_OPTERON(_eax) \
+ (CPUID_FAMILY(_eax) == CPUID_FAMILY_EXTENDED && \
+ CPUID_EXTENDED_FAMILY(_eax) == CPUID_EXTENDED_FAMILY_OPTERON)
+#define CPUID_FEATURE_COMMON_ID1EDX_HT 0x10000000 /* 28 */
+
+
+typedef struct {
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+} cpuid_t;
+
+/* cached CPUID data for CPUID(0) and CPUID(0x80000000) */
+extern cpuid_t cpuid_data0;
+extern cpuid_t cpuid_data80;
+
+
+static inline unsigned
+cpuid_max_func()
+{
+ return cpuid_data0.eax;
+}
+
+
+static inline unsigned
+cpuid_max_ext_func()
+{
+ return cpuid_data80.eax;
+}
+
+
+/* Typedef for storing the CPUID Vendor String */
+typedef union {
+ /* Note: the extra byte in the char array is for '\0'. */
+ char char_array[CPUID_VENDOR_STR_LENGTH];
+ uint32_t uint32_array[CPUID_VENDOR_LENGTH];
+} cpuid_vendor_string_t;
+
+/* Typedef for storing the CPUID Brand String */
+typedef union {
+ /* Note: the extra byte in the char array is for '\0'. */
+ char char_array[CPUID_BRAND_STR_LENGTH];
+ uint32_t uint32_array[CPUID_BRAND_LENGTH];
+} cpuid_brand_string_t;
+
+/* Typedef for storing CPUID Version */
+typedef union {
+ uint32_t flat;
+ struct {
+ uint32_t stepping:4; /* Bit 0 */
+ uint32_t model:4;
+ uint32_t family:4;
+ uint32_t processorType:2;
+ uint32_t reserved1514:2;
+ uint32_t extendedModel:4;
+ uint32_t extendedFamily:8;
+ uint32_t reserved3128:4; /* Bit 31 */
+ } bits;
+} cpuid_version_t;
+
+/* Typedef for storing CPUID Processor Information */
+typedef union {
+ uint32_t flat;
+ struct {
+ uint32_t brandIndex:8; /* Bit 0 */
+ uint32_t cflushLineSize:8;
+ uint32_t logicalProcessorCount:8;
+ uint32_t apicID:8; /* Bit 31 */
+ } bits;
+} cpuid_proc_info_t;
+
+/* Typedef for storing CPUID Feature flags */
+typedef union {
+ uint64_t flat;
+ uint32_t uint32_array[2];
+ struct {
+ uint32_t fpu:1; /* Bit 0 */
+ uint32_t vme:1;
+ uint32_t de:1;
+ uint32_t pse:1;
+ uint32_t tsc:1;
+ uint32_t msr:1;
+ uint32_t pae:1;
+ uint32_t mce:1;
+ uint32_t cx8:1;
+ uint32_t apic:1;
+ uint32_t reserved10:1;
+ uint32_t sep:1;
+ uint32_t mtrr:1;
+ uint32_t pge:1;
+ uint32_t mca:1;
+ uint32_t cmov:1;
+ uint32_t pat:1;
+ uint32_t pse36:1;
+ uint32_t psn:1;
+ uint32_t cflush:1;
+ uint32_t reserved20:1;
+ uint32_t ds:1;
+ uint32_t acpi:1;
+ uint32_t mmx:1;
+ uint32_t fxsr:1;
+ uint32_t sse:1;
+ uint32_t sse2:1;
+ uint32_t ss:1;
+ uint32_t htt:1;
+ uint32_t tm:1;
+ uint32_t reserved30:1;
+ uint32_t pbe:1; /* Bit 31 */
+ uint32_t sse3:1; /* Bit 32 */
+ uint32_t reserved3433:2;
+ uint32_t monitor:1;
+ uint32_t dscpl:1;
+ uint32_t reserved3937:3;
+ uint32_t tm2:1;
+ uint32_t reserved41:1;
+ uint32_t cnxtid:1;
+ uint32_t reserved4443:2;
+ uint32_t cmpxchg16b:1;
+ uint32_t reserved6346:18; /* Bit 63 */
+ } bits;
+} cpuid_feature_flags_t;
+
+/* Feature flags returned by extended CPUID node function 8000_0001. */
+typedef union {
+ uint64_t flat;
+ uint32_t uint32_array[2];
+ struct {
+ uint32_t fpu:1; /* Bit 0 */
+ uint32_t vme:1;
+ uint32_t de:1;
+ uint32_t pse:1;
+ uint32_t tsc:1;
+ uint32_t msr:1;
+ uint32_t pae:1;
+ uint32_t mce:1;
+ uint32_t cx8:1;
+ uint32_t apic:1;
+ uint32_t reserved10:1;
+ uint32_t sep:1;
+ uint32_t mtrr:1;
+ uint32_t pge:1;
+ uint32_t mca:1;
+ uint32_t cmov:1;
+ uint32_t pat:1;
+ uint32_t pse36:1;
+ uint32_t reserved1918:2;
+ uint32_t nx:1;
+ uint32_t reserved21:1;
+ uint32_t mmxamd:1;
+ uint32_t mmx:1;
+ uint32_t fxsr:1;
+ uint32_t ffxsr:1;
+ uint32_t reserved26:1;
+ uint32_t rdtscp:1;
+ uint32_t reserved28:1;
+ uint32_t lm:1;
+ uint32_t threedeenowext:1;
+ uint32_t threedeenow:1; /* Bit 31 */
+ uint32_t lahf:1; /* Bit 32 */
+ uint32_t cmplegacy:1;
+ uint32_t reserved3534:2;
+ uint32_t cr8avail:1;
+ uint32_t reserved6337:27; /* Bit 63 */
+ } bits;
+} cpuid_ext_feature_flags_t;
+
+void cpuid_get(unsigned n, cpuid_t *data);
+cpuid_vendor_string_t cpuid_get_vendor_string(void);
+cpuid_version_t cpuid_get_version(void);
+cpuid_feature_flags_t cpuid_get_feature_flags(void);
+bool cpuid_get_ext_feature_flags(cpuid_ext_feature_flags_t *f);
+bool cpuid_is_vendor_amd(void);
+bool cpuid_is_vendor_intel(void);
+bool cpuid_is_family_p6(void);
+bool cpuid_is_family_p4(void);
+bool cpuid_is_family_opteron(void);
+void cpuid_init(void);
+
+#endif
diff --git a/dmi.c b/dmi.c
index f2654f4..0f05822 100644
--- a/dmi.c
+++ b/dmi.c
@@ -5,8 +5,7 @@
*
* Release under the GPL version 2
* ----------------------------------------------------
- * Memtest86+ V1.70 - Added compliance with SMBIOS Spec V2.5
- * - Support for FB-DIMM
+ * Memtest86+ V4.00 - Added compliance with SMBIOS Spec V2.6.1
*/
@@ -89,15 +88,13 @@ static char *form_factors[] = {
"SODIMM", "SRIMM", "FB-DIMM"
};
-// Slot 1 is "Other", according to SMBIOS 2.6.
-// BTW, SMBIOS 2.6 doesn't yet recognize DDR3 and I replaced Other to DDR3
-// Need fix as soon as SMBIOS will take DDR3 into consideration
static char *memory_types[] = {
"?",
- "DDR3", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
+ "Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
"ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM",
- "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB"
+ "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB", "RSVD",
+ "RSVD","RSVD","DDR3","FBD2"
};
diff --git a/error.c b/error.c
index bd4ef53..5b63be0 100644
--- a/error.c
+++ b/error.c
@@ -4,7 +4,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V2.01 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -13,6 +13,7 @@
#include "config.h"
#include <sys/io.h>
#include "dmi.h"
+#define NULL 0
extern int test_ticks, nticks, beepmode;
extern struct tseq tseq[];
@@ -158,7 +159,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
hprint2(LINE_HEADER+1, 33, offset, 3);
cprint(LINE_HEADER+1, 36, " - . MB");
dprint(LINE_HEADER+1, 39, mb, 5, 0);
- dprint(LINE_HEADER+1, 45, ((page & 0xF)*10)/16, 1, 0);
+ dprint(LINE_HEADER+1, 45, ((page & 0xFF)*10)/256, 1, 0);
page = v->erri.high_addr.page;
offset = v->erri.high_addr.offset;
mb = page >> 8;
@@ -166,7 +167,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
hprint2(LINE_HEADER+2, 33, offset, 3);
cprint(LINE_HEADER+2, 36, " - . MB");
dprint(LINE_HEADER+2, 39, mb, 5, 0);
- dprint(LINE_HEADER+2, 45, ((page & 0xF)*10)/16, 1, 0);
+ dprint(LINE_HEADER+2, 45, ((page & 0xFF)*10)/256, 1, 0);
hprint(LINE_HEADER+3, 25, v->erri.ebits);
dprint(LINE_HEADER+4, 25, n, 2, 1);
dprint(LINE_HEADER+4, 34, v->erri.min_bits, 2, 1);
@@ -228,7 +229,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
hprint2(v->msg_line, 19, offset, 3);
cprint(v->msg_line, 22, " - . MB");
dprint(v->msg_line, 25, mb, 5, 0);
- dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0);
+ dprint(v->msg_line, 31, ((page & 0xFF)*10)/256, 1, 0);
if (type == 3) {
/* ECC error */
@@ -439,7 +440,15 @@ void do_tick(void)
nticks++;
v->total_ticks++;
- pct = 100*nticks/test_ticks;
+ if (test_ticks) {
+ pct = 100*nticks/test_ticks;
+ if (pct > 100) {
+ pct = 100;
+ }
+ } else {
+ pct = 0;
+ }
+
dprint(1, COL_MID+4, pct, 3, 0);
i = (BAR_SIZE * pct) / 100;
while (i > v->tptr) {
@@ -450,7 +459,12 @@ void do_tick(void)
v->tptr++;
}
- pct = 100*v->total_ticks/v->pass_ticks;
+ if (v->pass_ticks) {
+ pct = 100*v->total_ticks/v->pass_ticks;
+ if (pct > 100) { pct = 100; }
+ } else {
+ pct = 0;
+ }
dprint(0, COL_MID+4, pct, 3, 0);
i = (BAR_SIZE * pct) / 100;
while (i > v->pptr) {
diff --git a/init.c b/init.c
index 976c146..4b3248a 100644
--- a/init.c
+++ b/init.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V2.11 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -14,6 +14,7 @@
#include "controller.h"
#include "pci.h"
#include "io.h"
+#include "spd.h"
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
@@ -31,6 +32,7 @@ ulong st_low, st_high;
ulong end_low, end_high;
ulong cal_low, cal_high;
ulong extclock;
+unsigned long imc_type = 0;
int l1_cache, l2_cache, l3_cache;
int tsc_invariable = 0;
@@ -63,7 +65,7 @@ static void display_init(void)
for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) {
*pp = 0x20;
}
- cprint(0, 0, " Memtest86 v2.11 ");
+ cprint(0, 0, " Memtest86 v4.00 ");
for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) {
*pp = 0xA4;
@@ -133,7 +135,7 @@ void init(void)
v->erri.ebits = 0;
v->erri.hdr_flag = 0;
v->erri.tbits = 0;
- for (i=0; tseq[i].msg != NULL; i++) {
+ for (i=0; tseq[i].msg != 0; i++) {
tseq[i].errors = 0;
}
if (dmi_initialized) {
@@ -153,9 +155,12 @@ void init(void)
cpu_type();
- /* Find the memory controller (inverted from standard) */
+ /* Find the memory controller */
find_controller();
+ /* Find Memory Specs */
+ get_spd_spec();
+
if (v->rdtsc) {
cacheable();
cprint(LINE_TIME, COL_TIME+4, ": :");
@@ -181,7 +186,6 @@ void init(void)
// v->printmode=PRINTMODE_SUMMARY;
v->printmode=PRINTMODE_ADDRESSES;
v->numpatn=0;
- find_ticks();
}
@@ -443,6 +447,14 @@ void cpu_type(void)
l2_cache = (cpu_id.cache_info[11] << 8);
l2_cache += cpu_id.cache_info[10];
break;
+ case 10:
+ cprint(LINE_CPU, 0, "AMD Geode LX");
+ off = 12;
+ l1_cache = cpu_id.cache_info[3];
+ l1_cache += cpu_id.cache_info[7];
+ l2_cache = (cpu_id.cache_info[11] << 8);
+ l2_cache += cpu_id.cache_info[10];
+ break;
case 13:
cprint(LINE_CPU, 0, "AMD K6-III+");
off = 11;
@@ -511,59 +523,77 @@ void cpu_type(void)
l1_cache = cpu_id.cache_info[3];
l2_cache = (cpu_id.cache_info[11] << 8);
l2_cache += cpu_id.cache_info[10];
- switch(cpu_id.model) {
- default:
- cprint(LINE_CPU, 0, "AMD K8");
- off = 6;
- break;
- case 1:
- case 5:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- cprint(LINE_CPU, 0, "AMD Opteron (0.09)");
- } else {
- cprint(LINE_CPU, 0, "AMD Opteron (0.13)");
- }
- off = 18;
- break;
- case 3:
- case 11:
- cprint(LINE_CPU, 0, "Athlon 64 X2");
- off = 12;
- break;
- case 8:
- cprint(LINE_CPU, 0, "Turion 64 X2");
- off = 12;
- break;
- case 4:
- case 7:
- case 9:
- case 12:
- case 14:
- case 15:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.09)");
+ imc_type = 0x0100;
+ if(((cpu_id.ext >> 16) & 0xFF) < 0x10) {
+ // Here if CPUID.EXT < 0x10h (old K8/K10)
+ switch(cpu_id.model) {
+ default:
+ cprint(LINE_CPU, 0, "AMD K8");
+ off = 6;
+ break;
+ case 1:
+ case 5:
+ if (((cpu_id.ext >> 16) & 0xF) != 0) {
+ cprint(LINE_CPU, 0, "AMD Opteron (0.09)");
} else {
- cprint(LINE_CPU, 0, "Sempron (0.09)");
+ cprint(LINE_CPU, 0, "AMD Opteron (0.13)");
}
- } else {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.13)");
+ off = 18;
+ break;
+ case 3:
+ case 11:
+ cprint(LINE_CPU, 0, "Athlon 64 X2");
+ off = 12;
+ break;
+ case 8:
+ cprint(LINE_CPU, 0, "Turion 64 X2");
+ off = 12;
+ break;
+ case 4:
+ case 7:
+ case 12:
+ case 14:
+ case 15:
+ if (((cpu_id.ext >> 16) & 0xF) != 0) {
+ if (l2_cache > 256) {
+ cprint(LINE_CPU, 0, "Athlon 64 (0.09)");
+ } else {
+ cprint(LINE_CPU, 0, "Sempron (0.09)");
+ }
} else {
- cprint(LINE_CPU, 0, "Sempron (0.13)");
- }
+ if (l2_cache > 256) {
+ cprint(LINE_CPU, 0, "Athlon 64 (0.13)");
+ } else {
+ cprint(LINE_CPU, 0, "Sempron (0.13)");
+ }
+ }
+ off = 16;
+ break;
}
- off = 16;
break;
- case 2:
+ } else {
+ // Here if CPUID.EXT >= 0x10h (new K10)
l3_cache = (cpu_id.cache_info[15] << 8);
l3_cache += (cpu_id.cache_info[14] >> 2);
l3_cache *= 512;
- cprint(LINE_CPU, 0, "AMD K10 CPU @");
- off = 13;
- break;
+ imc_type = 0x0101;
+ switch(cpu_id.model) {
+ default:
+ case 2:
+ cprint(LINE_CPU, 0, "AMD K10 (65nm) @");
+ off = 16;
+ break;
+ case 4:
+ cprint(LINE_CPU, 0, "AMD K10 (45nm) @");
+ off = 16;
+ break;
+ case 9:
+ cprint(LINE_CPU, 0, "AMD Magny-Cours");
+ off = 15;
+ break;
+ }
+ break;
}
- break;
}
break;
@@ -697,25 +727,54 @@ void cpu_type(void)
case 0x4e:
l2_cache = 6144;
break;
+ case 0x22:
+ case 0xd0:
+ l3_cache = 512;
+ case 0x23:
case 0xd1:
case 0xd6:
l3_cache = 1024;
break;
+ case 0xdc:
+ l3_cache = 1536;
+ break;
+ case 0x25:
case 0xd2:
case 0xd7:
- case 0xdc:
case 0xe2:
l3_cache = 2048;
break;
- case 0xd8:
case 0xdd:
+ l3_cache = 3072;
+ break;
+ case 0x29:
+ case 0x46:
+ case 0xd8:
case 0xe3:
l3_cache = 4096;
break;
+ case 0x4a:
case 0xde:
+ l3_cache = 6144;
+ break;
+ case 0x47:
+ case 0x4b:
case 0xe4:
l3_cache = 8192;
break;
+ case 0x4c:
+ case 0xea:
+ l3_cache = 12288;
+ break;
+ case 0x4d:
+ l3_cache = 16374;
+ break;
+ case 0xeb:
+ l3_cache = 18432;
+ break;
+ case 0xec:
+ l3_cache = 24576;
+ break;
}
}
@@ -755,10 +814,17 @@ void cpu_type(void)
off = 10;
break;
case 5:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- cprint(LINE_CPU, 0, "Intel EP80579");
- if (l2_cache == 0) { l2_cache = 256; }
- off = 13;
+ if ((cpu_id.ext >> 16) & 0xF) {
+ if(((cpu_id.ext >> 16) & 0xF) > 1) {
+ cprint(LINE_CPU, 0, "Intel Core i3/i5");
+ tsc_invariable = 1;
+ imc_type = 0x0002;
+ off = 16;
+ } else {
+ cprint(LINE_CPU, 0, "Intel EP80579");
+ if (l2_cache == 0) { l2_cache = 256; }
+ off = 13;
+ }
} else {
if (l2_cache == 0) {
cprint(LINE_CPU, 0, "Celeron");
@@ -811,6 +877,7 @@ void cpu_type(void)
case 10:
if (((cpu_id.ext >> 16) & 0xF) != 0) {
tsc_invariable = 1;
+ imc_type = 0x0001;
cprint(LINE_CPU, 0, "Intel Core i7");
off = 13;
} else {
@@ -819,9 +886,16 @@ void cpu_type(void)
}
break;
case 12:
- l1_cache = 24;
- cprint(LINE_CPU, 0, "Atom (0.045)");
- off = 12;
+ if (((cpu_id.ext >> 16) & 0xF) > 1) {
+ cprint(LINE_CPU, 0, "Intel Core i9");
+ tsc_invariable = 1;
+ imc_type = 0x0002;
+ off = 13;
+ } else {
+ l1_cache = 24;
+ cprint(LINE_CPU, 0, "Atom (0.045)");
+ off = 12;
+ }
break;
case 13:
if (l2_cache == 1024) {
@@ -834,8 +908,9 @@ void cpu_type(void)
case 14:
if (((cpu_id.ext >> 16) & 0xF) != 0) {
tsc_invariable = 1;
- cprint(LINE_CPU, 0, "Intel Core i5");
- off = 13;
+ imc_type = 0x0001;
+ cprint(LINE_CPU, 0, "Intel Core i5/i7");
+ off = 16;
} else {
cprint(LINE_CPU, 0, "Intel Core");
off = 10;
diff --git a/jedec_id.h b/jedec_id.h
new file mode 100644
index 0000000..6694c17
--- /dev/null
+++ b/jedec_id.h
@@ -0,0 +1,887 @@
+/* MemTest86+ V4.00 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
+ */
+
+struct spd_jedec_manufacturer {
+ unsigned cont_code;
+ unsigned hex_byte;
+ char *name;
+};
+
+struct spd_jedec_manufacturer jep106[] = {
+ { 0, 0x01, "AMD"},
+ { 0, 0x02, "AMI"},
+ { 0, 0x83, "Fairchild"},
+ { 0, 0x04, "Fujitsu"},
+ { 0, 0x85, "GTE"},
+ { 0, 0x86, "Harris"},
+ { 0, 0x07, "Hitachi"},
+ { 0, 0x08, "Inmos"},
+ { 0, 0x89, "Intel"},
+ { 0, 0x8a, "I.T.T."},
+ { 0, 0x0b, "Intersil"},
+ { 0, 0x8c, "Monolithic Memories"},
+ { 0, 0x0d, "Mostek"},
+ { 0, 0x0e, "Freescale (Motorola)"},
+ { 0, 0x8f, "National"},
+ { 0, 0x10, "NEC"},
+ { 0, 0x91, "RCA"},
+ { 0, 0x92, "Raytheon"},
+ { 0, 0x13, "Conexant (Rockwell)"},
+ { 0, 0x94, "Seeq"},
+ { 0, 0x15, "NXP (Philips)"},
+ { 0, 0x16, "Synertek"},
+ { 0, 0x97, "Texas Instruments"},
+ { 0, 0x98, "Toshiba"},
+ { 0, 0x19, "Xicor"},
+ { 0, 0x1a, "Zilog"},
+ { 0, 0x9b, "Eurotechnique"},
+ { 0, 0x1c, "Mitsubishi"},
+ { 0, 0x9d, "Lucent (AT&T)"},
+ { 0, 0x9e, "Exel"},
+ { 0, 0x1f, "Atmel"},
+ { 0, 0x20, "SGS/Thomson"},
+ { 0, 0xa1, "Lattice Semi."},
+ { 0, 0xa2, "NCR"},
+ { 0, 0x23, "Wafer Scale Integration"},
+ { 0, 0xa4, "IBM"},
+ { 0, 0x25, "Tristar"},
+ { 0, 0x26, "Visic"},
+ { 0, 0xa7, "Intl. CMOS Technology"},
+ { 0, 0xa8, "SSSI"},
+ { 0, 0x29, "MicrochipTechnology"},
+ { 0, 0x2a, "Ricoh"},
+ { 0, 0xab, "VLSI"},
+ { 0, 0x2c, "Micron Technology"},
+ { 0, 0xad, "Hynix Semiconductor"},
+ { 0, 0xae, "OKI Semiconductor"},
+ { 0, 0x2f, "ACTEL"},
+ { 0, 0xb0, "Sharp"},
+ { 0, 0x31, "Catalyst"},
+ { 0, 0x32, "Panasonic"},
+ { 0, 0xb3, "IDT"},
+ { 0, 0x34, "Cypress"},
+ { 0, 0xb5, "DEC"},
+ { 0, 0xb6, "LSI Logic"},
+ { 0, 0x37, "Zarlink (Plessey)"},
+ { 0, 0x38, "UTMC"},
+ { 0, 0xb9, "Thinking Machine"},
+ { 0, 0xba, "Thomson CSF"},
+ { 0, 0x3b, "Integrated CMOS (Vertex)"},
+ { 0, 0xbc, "Honeywell"},
+ { 0, 0x3d, "Tektronix"},
+ { 0, 0x3e, "Sun Microsystems"},
+ { 0, 0xbf, "SST"},
+ { 0, 0x40, "ProMos/Mosel Vitelic"},
+ { 0, 0xc1, "Infineon (Siemens)"},
+ { 0, 0xc2, "Macronix"},
+ { 0, 0x43, "Xerox"},
+ { 0, 0xc4, "Plus Logic"},
+ { 0, 0x45, "SanDisk"},
+ { 0, 0x46, "Elan Circuit Tech."},
+ { 0, 0xc7, "European Silicon Str."},
+ { 0, 0xc8, "Apple Computer"},
+ { 0, 0x49, "Xilinx"},
+ { 0, 0x4a, "Compaq"},
+ { 0, 0xcb, "Protocol Engines"},
+ { 0, 0x4c, "SCI"},
+ { 0, 0xcd, "Seiko Instruments"},
+ { 0, 0xce, "Samsung"},
+ { 0, 0x4f, "I3 Design System"},
+ { 0, 0xd0, "Klic"},
+ { 0, 0x51, "Crosspoint Solutions"},
+ { 0, 0x52, "Alliance Semiconductor"},
+ { 0, 0xd3, "Tandem"},
+ { 0, 0x54, "Hewlett-Packard"},
+ { 0, 0xd5, "Intg. Silicon Solutions"},
+ { 0, 0xd6, "Brooktree"},
+ { 0, 0x57, "New Media"},
+ { 0, 0x58, "MHS Electronic"},
+ { 0, 0xd9, "Performance Semi."},
+ { 0, 0xda, "Winbond Electronic"},
+ { 0, 0x5b, "Kawasaki Steel"},
+ { 0, 0xdc, "Bright Micro"},
+ { 0, 0x5d, "TECMAR"},
+ { 0, 0x5e, "Exar"},
+ { 0, 0xdf, "PCMCIA"},
+ { 0, 0xe0, "LG Semi (Goldstar)"},
+ { 0, 0x61, "Northern Telecom"},
+ { 0, 0x62, "Sanyo"},
+ { 0, 0xe3, "Array Microsystems"},
+ { 0, 0x64, "Crystal Semiconductor"},
+ { 0, 0xe5, "Analog Devices"},
+ { 0, 0xe6, "PMC-Sierra"},
+ { 0, 0x67, "Asparix"},
+ { 0, 0x68, "Convex Computer"},
+ { 0, 0xe9, "Quality Semiconductor"},
+ { 0, 0xea, "Nimbus Technology"},
+ { 0, 0x6b, "Transwitch"},
+ { 0, 0xec, "Micronas (ITT Intermetall)"},
+ { 0, 0x6d, "Cannon"},
+ { 0, 0x6e, "Altera"},
+ { 0, 0xef, "NEXCOM"},
+ { 0, 0x70, "QUALCOMM"},
+ { 0, 0xf1, "Sony"},
+ { 0, 0xf2, "Cray Research"},
+ { 0, 0x73, "AMS(Austria Micro)"},
+ { 0, 0xf4, "Vitesse"},
+ { 0, 0x75, "Aster Electronics"},
+ { 0, 0x76, "Bay Networks (Synoptic)"},
+ { 0, 0xf7, "Zentrum/ZMD"},
+ { 0, 0xf8, "TRW"},
+ { 0, 0x79, "Thesys"},
+ { 0, 0x7a, "Solbourne Computer"},
+ { 0, 0xfb, "Allied-Signal"},
+ { 0, 0x7c, "Dialog"},
+ { 0, 0xfd, "Media Vision"},
+ { 0, 0xfe, "Numonyx"},
+ { 1, 0x01, "Cirrus Logic"},
+ { 1, 0x02, "National Instruments"},
+ { 1, 0x83, "ILC Data Device"},
+ { 1, 0x04, "Alcatel Mietec"},
+ { 1, 0x85, "Micro Linear"},
+ { 1, 0x86, "Univ. of NC"},
+ { 1, 0x07, "JTAG Technologies"},
+ { 1, 0x08, "BAE Systems (Loral)"},
+ { 1, 0x89, "Nchip"},
+ { 1, 0x8a, "Galileo Tech"},
+ { 1, 0x0b, "Bestlink Systems"},
+ { 1, 0x8c, "Graychip"},
+ { 1, 0x0d, "GENNUM"},
+ { 1, 0x0e, "VideoLogic"},
+ { 1, 0x8f, "Robert Bosch"},
+ { 1, 0x10, "Chip Express"},
+ { 1, 0x91, "DATARAM"},
+ { 1, 0x92, "United Microelectronics Corp."},
+ { 1, 0x13, "TCSI"},
+ { 1, 0x94, "Smart Modular"},
+ { 1, 0x15, "Hughes Aircraft"},
+ { 1, 0x16, "Lanstar Semiconductor"},
+ { 1, 0x97, "Qlogic"},
+ { 1, 0x98, "Kingston"},
+ { 1, 0x19, "Music Semi"},
+ { 1, 0x1a, "Ericsson Components"},
+ { 1, 0x9b, "SpaSE"},
+ { 1, 0x1c, "Eon Silicon Devices"},
+ { 1, 0x9d, "Programmable Micro Corp"},
+ { 1, 0x9e, "DoD"},
+ { 1, 0x1f, "Integ. Memories Tech."},
+ { 1, 0x20, "Corollary"},
+ { 1, 0xa1, "Dallas Semiconductor"},
+ { 1, 0xa2, "Omnivision"},
+ { 1, 0x23, "EIV(Switzerland)"},
+ { 1, 0xa4, "Novatel Wireless"},
+ { 1, 0x25, "Zarlink (Mitel)"},
+ { 1, 0x26, "Clearpoint"},
+ { 1, 0xa7, "Cabletron"},
+ { 1, 0xa8, "STEC (Silicon Tech)"},
+ { 1, 0x29, "Vanguard"},
+ { 1, 0x2a, "Hagiwara Sys-Com"},
+ { 1, 0xab, "Vantis"},
+ { 1, 0x2c, "Celestica"},
+ { 1, 0xad, "Century"},
+ { 1, 0xae, "Hal Computers"},
+ { 1, 0x2f, "Rohm Company"},
+ { 1, 0xb0, "Juniper Networks"},
+ { 1, 0x31, "Libit Signal Processing"},
+ { 1, 0x32, "Mushkin Enhanced Memory"},
+ { 1, 0xb3, "Tundra Semiconductor"},
+ { 1, 0x34, "Adaptec"},
+ { 1, 0xb5, "LightSpeed Semi."},
+ { 1, 0xb6, "ZSP Corp."},
+ { 1, 0x37, "AMIC Technology"},
+ { 1, 0x38, "Adobe Systems"},
+ { 1, 0xb9, "Dynachip"},
+ { 1, 0xba, "PNY Electronics"},
+ { 1, 0x3b, "Newport Digital"},
+ { 1, 0xbc, "MMC Networks"},
+ { 1, 0x3d, "T Square"},
+ { 1, 0x3e, "Seiko Epson"},
+ { 1, 0xbf, "Broadcom"},
+ { 1, 0x40, "Viking Components"},
+ { 1, 0xc1, "V3 Semiconductor"},
+ { 1, 0xc2, "Flextronics (Orbit Semiconductor)"},
+ { 1, 0x43, "Suwa Electronics"},
+ { 1, 0xc4, "Transmeta"},
+ { 1, 0x45, "Micron CMS"},
+ { 1, 0x46, "American Computer & Digital Components"},
+ { 1, 0xc7, "Enhance 3000"},
+ { 1, 0xc8, "Tower Semiconductor"},
+ { 1, 0x49, "CPU Design"},
+ { 1, 0x4a, "Price Point"},
+ { 1, 0xcb, "Maxim Integrated Product"},
+ { 1, 0x4c, "Tellabs"},
+ { 1, 0xcd, "Centaur Technology"},
+ { 1, 0xce, "Unigen"},
+ { 1, 0x4f, "Transcend Information"},
+ { 1, 0xd0, "Memory Card Technology"},
+ { 1, 0x51, "CKD"},
+ { 1, 0x52, "Capital Instruments"},
+ { 1, 0xd3, "Aica Kogyo"},
+ { 1, 0x54, "Linvex Technology"},
+ { 1, 0xd5, "MSC Vertriebs"},
+ { 1, 0xd6, "AKM Company"},
+ { 1, 0x57, "Dynamem"},
+ { 1, 0x58, "NERA ASA"},
+ { 1, 0xd9, "GSI Technology"},
+ { 1, 0xda, "Dane-Elec (C Memory)"},
+ { 1, 0x5b, "Acorn Computers"},
+ { 1, 0xdc, "Lara Technology"},
+ { 1, 0x5d, "Oak Technology"},
+ { 1, 0x5e, "Itec Memory"},
+ { 1, 0xdf, "Tanisys Technology"},
+ { 1, 0xe0, "Truevision"},
+ { 1, 0x61, "Wintec Industries"},
+ { 1, 0x62, "Super PC Memory"},
+ { 1, 0xe3, "MGV Memory"},
+ { 1, 0x64, "Galvantech"},
+ { 1, 0xe5, "Gadzoox Networks"},
+ { 1, 0xe6, "Multi Dimensional Cons."},
+ { 1, 0x67, "GateField"},
+ { 1, 0x68, "Integrated Memory System"},
+ { 1, 0xe9, "Triscend"},
+ { 1, 0xea, "XaQti"},
+ { 1, 0x6b, "Goldenram"},
+ { 1, 0xec, "Clear Logic"},
+ { 1, 0x6d, "Cimaron Communications"},
+ { 1, 0x6e, "Nippon Steel Semi. Corp."},
+ { 1, 0xef, "Advantage Memory"},
+ { 1, 0x70, "AMCC"},
+ { 1, 0xf1, "LeCroy"},
+ { 1, 0xf2, "Yamaha"},
+ { 1, 0x73, "Digital Microwave"},
+ { 1, 0xf4, "NetLogic Microsystems"},
+ { 1, 0x75, "MIMOS Semiconductor"},
+ { 1, 0x76, "Advanced Fibre"},
+ { 1, 0xf7, "BF Goodrich Data."},
+ { 1, 0xf8, "Epigram"},
+ { 1, 0x79, "Acbel Polytech"},
+ { 1, 0x7a, "Apacer Technology"},
+ { 1, 0xfb, "Admor Memory"},
+ { 1, 0x7c, "FOXCONN"},
+ { 1, 0xfd, "Quadratics Superconductor"},
+ { 1, 0xfe, "3COM"},
+ { 2, 0x01, "Camintonn"},
+ { 2, 0x02, "ISOA"},
+ { 2, 0x83, "Agate Semiconductor"},
+ { 2, 0x04, "ADMtek"},
+ { 2, 0x85, "HYPERTEC"},
+ { 2, 0x86, "Adhoc Technologies"},
+ { 2, 0x07, "MOSAID Technologies"},
+ { 2, 0x08, "Ardent Technologies"},
+ { 2, 0x89, "Switchcore"},
+ { 2, 0x8a, "Cisco Systems"},
+ { 2, 0x0b, "Allayer Technologies"},
+ { 2, 0x8c, "WorkX AG (Wichman)"},
+ { 2, 0x0d, "Oasis Semiconductor"},
+ { 2, 0x0e, "Novanet Semiconductor"},
+ { 2, 0x8f, "E-M Solutions"},
+ { 2, 0x10, "Power General"},
+ { 2, 0x91, "Advanced Hardware Arch."},
+ { 2, 0x92, "Inova Semiconductors"},
+ { 2, 0x13, "Telocity"},
+ { 2, 0x94, "Delkin Devices"},
+ { 2, 0x15, "Symagery Microsystems"},
+ { 2, 0x16, "C-Port"},
+ { 2, 0x97, "SiberCore Technologies"},
+ { 2, 0x98, "Southland Microsystems"},
+ { 2, 0x19, "Malleable Technologies"},
+ { 2, 0x1a, "Kendin Communications"},
+ { 2, 0x9b, "Great Technology Microcomputer"},
+ { 2, 0x1c, "Sanmina"},
+ { 2, 0x9d, "HADCO"},
+ { 2, 0x9e, "Corsair"},
+ { 2, 0x1f, "Actrans System"},
+ { 2, 0x20, "ALPHA Technologies"},
+ { 2, 0xa1, "Silicon Laboratories (Cygnal)"},
+ { 2, 0xa2, "Artesyn Technologies"},
+ { 2, 0x23, "Align Manufacturing"},
+ { 2, 0xa4, "Peregrine Semiconductor"},
+ { 2, 0x25, "Chameleon Systems"},
+ { 2, 0x26, "Aplus Flash Technology"},
+ { 2, 0xa7, "MIPS Technologies"},
+ { 2, 0xa8, "Chrysalis ITS"},
+ { 2, 0x29, "ADTEC"},
+ { 2, 0x2a, "Kentron Technologies"},
+ { 2, 0xab, "Win Technologies"},
+ { 2, 0x2c, "Tachyon Semiconductor (ASIC)"},
+ { 2, 0xad, "Extreme Packet Devices"},
+ { 2, 0xae, "RF Micro Devices"},
+ { 2, 0x2f, "Siemens AG"},
+ { 2, 0xb0, "Sarnoff"},
+ { 2, 0x31, "Itautec SA"},
+ { 2, 0x32, "Radiata"},
+ { 2, 0xb3, "Benchmark Elect. (AVEX)"},
+ { 2, 0x34, "Legend"},
+ { 2, 0xb5, "SpecTek"},
+ { 2, 0xb6, "Hi/fn"},
+ { 2, 0x37, "Enikia"},
+ { 2, 0x38, "SwitchOn Networks"},
+ { 2, 0xb9, "AANetcom"},
+ { 2, 0xba, "Micro Memory Bank"},
+ { 2, 0x3b, "ESS Technology"},
+ { 2, 0xbc, "Virata"},
+ { 2, 0x3d, "Excess Bandwidth"},
+ { 2, 0x3e, "West Bay Semiconductor"},
+ { 2, 0xbf, "DSP Group"},
+ { 2, 0x40, "Newport Communications"},
+ { 2, 0xc1, "Chip2Chip"},
+ { 2, 0xc2, "Phobos"},
+ { 2, 0x43, "Intellitech"},
+ { 2, 0xc4, "Nordic VLSI ASA"},
+ { 2, 0x45, "Ishoni Networks"},
+ { 2, 0x46, "Silicon Spice"},
+ { 2, 0xc7, "Alchemy Semiconductor"},
+ { 2, 0xc8, "Agilent Technologies"},
+ { 2, 0x49, "Centillium Communications"},
+ { 2, 0x4a, "W.L. Gore"},
+ { 2, 0xcb, "HanBit Electronics"},
+ { 2, 0x4c, "GlobeSpan"},
+ { 2, 0xcd, "Element 14"},
+ { 2, 0xce, "Pycon"},
+ { 2, 0x4f, "Saifun Semiconductors"},
+ { 2, 0xd0, "Sibyte,"},
+ { 2, 0x51, "MetaLink Technologies"},
+ { 2, 0x52, "Feiya Technology"},
+ { 2, 0xd3, "I & C Technology"},
+ { 2, 0x54, "Shikatronics"},
+ { 2, 0xd5, "Elektrobit"},
+ { 2, 0xd6, "Megic"},
+ { 2, 0x57, "Com-Tier"},
+ { 2, 0x58, "Malaysia Micro Solutions"},
+ { 2, 0xd9, "Hyperchip"},
+ { 2, 0xda, "Gemstone Communications"},
+ { 2, 0x5b, "Anadigm (Anadyne)"},
+ { 2, 0xdc, "3ParData"},
+ { 2, 0x5d, "Mellanox Technologies"},
+ { 2, 0x5e, "Tenx Technologies"},
+ { 2, 0xdf, "Helix AG"},
+ { 2, 0xe0, "Domosys"},
+ { 2, 0x61, "Skyup Technology"},
+ { 2, 0x62, "HiNT"},
+ { 2, 0xe3, "Chiaro"},
+ { 2, 0x64, "MDT Technologies"},
+ { 2, 0xe5, "Exbit Technology A/S"},
+ { 2, 0xe6, "Integrated Technology Express"},
+ { 2, 0x67, "AVED Memory"},
+ { 2, 0x68, "Legerity"},
+ { 2, 0xe9, "Jasmine Networks"},
+ { 2, 0xea, "Caspian Networks"},
+ { 2, 0x6b, "nCUBE"},
+ { 2, 0xec, "Silicon Access Networks"},
+ { 2, 0x6d, "FDK"},
+ { 2, 0x6e, "High Bandwidth Access"},
+ { 2, 0xef, "MultiLink Technology"},
+ { 2, 0x70, "BRECIS"},
+ { 2, 0xf1, "World Wide Packets"},
+ { 2, 0xf2, "APW"},
+ { 2, 0x73, "Chicory Systems"},
+ { 2, 0xf4, "Xstream Logic"},
+ { 2, 0x75, "Fast-Chip"},
+ { 2, 0x76, "Zucotto Wireless"},
+ { 2, 0xf7, "Realchip"},
+ { 2, 0xf8, "Galaxy Power"},
+ { 2, 0x79, "eSilicon"},
+ { 2, 0x7a, "Morphics Technology"},
+ { 2, 0xfb, "Accelerant Networks"},
+ { 2, 0x7c, "Silicon Wave"},
+ { 2, 0xfd, "SandCraft"},
+ { 2, 0xfe, "Elpida"},
+ { 3, 0x01, "Solectron"},
+ { 3, 0x02, "Optosys Technologies"},
+ { 3, 0x83, "Buffalo (Formerly Melco)"},
+ { 3, 0x04, "TriMedia Technologies"},
+ { 3, 0x85, "Cyan Technologies"},
+ { 3, 0x86, "Global Locate"},
+ { 3, 0x07, "Optillion"},
+ { 3, 0x08, "Terago Communications"},
+ { 3, 0x89, "Ikanos Communications"},
+ { 3, 0x8a, "Preton Technology"},
+ { 3, 0x0b, "Nanya Technology"},
+ { 3, 0x8c, "Elite Flash Storage"},
+ { 3, 0x0d, "Mysticom"},
+ { 3, 0x0e, "LightSand Communications"},
+ { 3, 0x8f, "ATI Technologies"},
+ { 3, 0x10, "Agere Systems"},
+ { 3, 0x91, "NeoMagic"},
+ { 3, 0x92, "AuroraNetics"},
+ { 3, 0x13, "Golden Empire"},
+ { 3, 0x94, "Mushkin"},
+ { 3, 0x15, "Tioga Technologies"},
+ { 3, 0x16, "Netlist"},
+ { 3, 0x97, "TeraLogic"},
+ { 3, 0x98, "Cicada Semiconductor"},
+ { 3, 0x19, "Centon Electronics"},
+ { 3, 0x1a, "Tyco Electronics"},
+ { 3, 0x9b, "Magis Works"},
+ { 3, 0x1c, "Zettacom"},
+ { 3, 0x9d, "Cogency Semiconductor"},
+ { 3, 0x9e, "Chipcon AS"},
+ { 3, 0x1f, "Aspex Technology"},
+ { 3, 0x20, "F5 Networks"},
+ { 3, 0xa1, "Programmable Silicon Solutions"},
+ { 3, 0xa2, "ChipWrights"},
+ { 3, 0x23, "Acorn Networks"},
+ { 3, 0xa4, "Quicklogic"},
+ { 3, 0x25, "Kingmax Semiconductor"},
+ { 3, 0x26, "BOPS"},
+ { 3, 0xa7, "Flasys"},
+ { 3, 0xa8, "BitBlitz Communications"},
+ { 3, 0x29, "eMemory Technology"},
+ { 3, 0x2a, "Procket Networks"},
+ { 3, 0xab, "Purple Ray"},
+ { 3, 0x2c, "Trebia Networks"},
+ { 3, 0xad, "Delta Electronics"},
+ { 3, 0xae, "Onex Communications"},
+ { 3, 0x2f, "Ample Communications"},
+ { 3, 0xb0, "Memory Experts Intl"},
+ { 3, 0x31, "Astute Networks"},
+ { 3, 0x32, "Azanda Network Devices"},
+ { 3, 0xb3, "Dibcom"},
+ { 3, 0x34, "Tekmos"},
+ { 3, 0xb5, "API NetWorks"},
+ { 3, 0xb6, "Bay Microsystems"},
+ { 3, 0x37, "Firecron"},
+ { 3, 0x38, "Resonext Communications"},
+ { 3, 0xb9, "Tachys Technologies"},
+ { 3, 0xba, "Equator Technology"},
+ { 3, 0x3b, "Concept Computer"},
+ { 3, 0xbc, "SILCOM"},
+ { 3, 0x3d, "3Dlabs"},
+ { 3, 0x3e, "c?t Magazine"},
+ { 3, 0xbf, "Sanera Systems"},
+ { 3, 0x40, "Silicon Packets"},
+ { 3, 0xc1, "Viasystems Group"},
+ { 3, 0xc2, "Simtek"},
+ { 3, 0x43, "Semicon Devices Singapore"},
+ { 3, 0xc4, "Satron Handelsges"},
+ { 3, 0x45, "Improv Systems"},
+ { 3, 0x46, "INDUSYS"},
+ { 3, 0xc7, "Corrent"},
+ { 3, 0xc8, "Infrant Technologies"},
+ { 3, 0x49, "Ritek Corp"},
+ { 3, 0x4a, "empowerTel Networks"},
+ { 3, 0xcb, "Hypertec"},
+ { 3, 0x4c, "Cavium Networks"},
+ { 3, 0xcd, "PLX Technology"},
+ { 3, 0xce, "Massana Design"},
+ { 3, 0x4f, "Intrinsity"},
+ { 3, 0xd0, "Valence Semiconductor"},
+ { 3, 0x51, "Terawave Communications"},
+ { 3, 0x52, "IceFyre Semiconductor"},
+ { 3, 0xd3, "Primarion"},
+ { 3, 0x54, "Picochip Designs"},
+ { 3, 0xd5, "Silverback Systems"},
+ { 3, 0xd6, "Jade Star Technologies"},
+ { 3, 0x57, "Pijnenburg Securealink"},
+ { 3, 0x58, "takeMS International AG"},
+ { 3, 0xd9, "Cambridge Silicon Radio"},
+ { 3, 0xda, "Swissbit"},
+ { 3, 0x5b, "Nazomi Communications"},
+ { 3, 0xdc, "eWave System"},
+ { 3, 0x5d, "Rockwell Collins"},
+ { 3, 0x5e, "Picocel Co. (Paion)"},
+ { 3, 0xdf, "Alphamosaic"},
+ { 3, 0xe0, "Sandburst"},
+ { 3, 0x61, "SiCon Video"},
+ { 3, 0x62, "NanoAmp Solutions"},
+ { 3, 0xe3, "Ericsson Technology"},
+ { 3, 0x64, "PrairieComm"},
+ { 3, 0xe5, "Mitac International"},
+ { 3, 0xe6, "Layer N Networks"},
+ { 3, 0x67, "MtekVision (Atsana)"},
+ { 3, 0x68, "Allegro Networks"},
+ { 3, 0xe9, "Marvell Semiconductors"},
+ { 3, 0xea, "Netergy Microelectronic"},
+ { 3, 0x6b, "NVIDIA"},
+ { 3, 0xec, "Internet Machines"},
+ { 3, 0x6d, "Peak Electronics"},
+ { 3, 0x6e, "Litchfield Communication"},
+ { 3, 0xef, "Accton Technology"},
+ { 3, 0x70, "Teradiant Networks"},
+ { 3, 0xf1, "Scaleo Chip"},
+ { 3, 0xf2, "Cortina Systems"},
+ { 3, 0x73, "RAM Components"},
+ { 3, 0xf4, "Raqia Networks"},
+ { 3, 0x75, "ClearSpeed"},
+ { 3, 0x76, "Matsushita Battery"},
+ { 3, 0xf7, "Xelerated"},
+ { 3, 0xf8, "SimpleTech"},
+ { 3, 0x79, "Utron Technology"},
+ { 3, 0x7a, "Astec International"},
+ { 3, 0xfb, "AVM"},
+ { 3, 0x7c, "Redux Communications"},
+ { 3, 0xfd, "Dot Hill Systems"},
+ { 3, 0xfe, "TeraChip"},
+ { 4, 0x01, "T-RAM"},
+ { 4, 0x02, "Innovics Wireless"},
+ { 4, 0x83, "Teknovus"},
+ { 4, 0x04, "KeyEye Communications"},
+ { 4, 0x85, "Runcom Technologies"},
+ { 4, 0x86, "RedSwitch"},
+ { 4, 0x07, "Dotcast"},
+ { 4, 0x08, "Silicon Mountain Memory"},
+ { 4, 0x89, "Signia Technologies"},
+ { 4, 0x8a, "Pixim"},
+ { 4, 0x0b, "Galazar Networks"},
+ { 4, 0x8c, "White Electronic Designs"},
+ { 4, 0x0d, "Patriot Scientific"},
+ { 4, 0x0e, "Neoaxiom"},
+ { 4, 0x8f, "3Y Power Technology"},
+ { 4, 0x10, "Scaleo Chip"},
+ { 4, 0x91, "Potentia Power Systems"},
+ { 4, 0x92, "C-guys"},
+ { 4, 0x13, "Digital Communications Technology"},
+ { 4, 0x94, "Silicon-Based Technology"},
+ { 4, 0x15, "Fulcrum Microsystems"},
+ { 4, 0x16, "Positivo Informatica"},
+ { 4, 0x97, "XIOtech"},
+ { 4, 0x98, "PortalPlayer"},
+ { 4, 0x19, "Zhiying Software"},
+ { 4, 0x1a, "ParkerVision"},
+ { 4, 0x9b, "Phonex Broadband"},
+ { 4, 0x1c, "Skyworks Solutions"},
+ { 4, 0x9d, "Entropic Communications"},
+ { 4, 0x9e, "Pacific Force Technology"},
+ { 4, 0x1f, "Zensys A/S"},
+ { 4, 0x20, "Legend Silicon Corp."},
+ { 4, 0xa1, "Sci-worx"},
+ { 4, 0xa2, "SMSC (Standard Microsystems)"},
+ { 4, 0x23, "Renesas Technology"},
+ { 4, 0xa4, "Raza Microelectronics"},
+ { 4, 0x25, "Phyworks"},
+ { 4, 0x26, "MediaTek"},
+ { 4, 0xa7, "Non-cents Productions"},
+ { 4, 0xa8, "US Modular"},
+ { 4, 0x29, "Wintegra"},
+ { 4, 0x2a, "Mathstar"},
+ { 4, 0xab, "StarCore"},
+ { 4, 0x2c, "Oplus Technologies"},
+ { 4, 0xad, "Mindspeed"},
+ { 4, 0xae, "Just Young Computer"},
+ { 4, 0x2f, "Radia Communications"},
+ { 4, 0xb0, "OCZ"},
+ { 4, 0x31, "Emuzed"},
+ { 4, 0x32, "LOGIC Devices"},
+ { 4, 0xb3, "Inphi"},
+ { 4, 0x34, "Quake Technologies"},
+ { 4, 0xb5, "Vixel"},
+ { 4, 0xb6, "SolusTek"},
+ { 4, 0x37, "Kongsberg Maritime"},
+ { 4, 0x38, "Faraday Technology"},
+ { 4, 0xb9, "Altium"},
+ { 4, 0xba, "Insyte"},
+ { 4, 0x3b, "ARM"},
+ { 4, 0xbc, "DigiVision"},
+ { 4, 0x3d, "Vativ Technologies"},
+ { 4, 0x3e, "Endicott Interconnect Technologies"},
+ { 4, 0xbf, "Pericom"},
+ { 4, 0x40, "Bandspeed"},
+ { 4, 0xc1, "LeWiz Communications"},
+ { 4, 0xc2, "CPU Technology"},
+ { 4, 0x43, "Ramaxel Technology"},
+ { 4, 0xc4, "DSP Group"},
+ { 4, 0x45, "Axis Communications"},
+ { 4, 0x46, "Legacy Electronics"},
+ { 4, 0xc7, "Chrontel"},
+ { 4, 0xc8, "Powerchip Semiconductor"},
+ { 4, 0x49, "MobilEye Technologies"},
+ { 4, 0x4a, "Excel Semiconductor"},
+ { 4, 0xcb, "A-DATA Technology"},
+ { 4, 0x4c, "VirtualDigm"},
+ { 4, 0xcd, "G Skill Intl"},
+ { 4, 0xce, "Quanta Computer"},
+ { 4, 0x4f, "Yield Microelectronics"},
+ { 4, 0xd0, "Afa Technologies"},
+ { 4, 0x51, "KINGBOX Technology Co."},
+ { 4, 0x52, "Ceva"},
+ { 4, 0xd3, "iStor Networks"},
+ { 4, 0x54, "Advance Modules"},
+ { 4, 0xd5, "Microsoft"},
+ { 4, 0xd6, "Open-Silicon"},
+ { 4, 0x57, "Goal Semiconductor"},
+ { 4, 0x58, "ARC International"},
+ { 4, 0xd9, "Simmtec"},
+ { 4, 0xda, "Metanoia"},
+ { 4, 0x5b, "Key Stream"},
+ { 4, 0xdc, "Lowrance Electronics"},
+ { 4, 0x5d, "Adimos"},
+ { 4, 0x5e, "SiGe Semiconductor"},
+ { 4, 0xdf, "Fodus Communications"},
+ { 4, 0xe0, "Credence Systems Corp."},
+ { 4, 0x61, "Genesis Microchip"},
+ { 4, 0x62, "Vihana"},
+ { 4, 0xe3, "WIS Technologies"},
+ { 4, 0x64, "GateChange Technologies"},
+ { 4, 0xe5, "High Density Devices AS"},
+ { 4, 0xe6, "Synopsys"},
+ { 4, 0x67, "Gigaram"},
+ { 4, 0x68, "Enigma Semiconductor"},
+ { 4, 0xe9, "Century Micro"},
+ { 4, 0xea, "Icera Semiconductor"},
+ { 4, 0x6b, "Mediaworks Integrated Systems"},
+ { 4, 0xec, "O?Neil Product Development"},
+ { 4, 0x6d, "Supreme Top Technology"},
+ { 4, 0x6e, "MicroDisplay"},
+ { 4, 0xef, "Team Group"},
+ { 4, 0x70, "Sinett"},
+ { 4, 0xf1, "Toshiba"},
+ { 4, 0xf2, "Tensilica"},
+ { 4, 0x73, "SiRF Technology"},
+ { 4, 0xf4, "Bacoc"},
+ { 4, 0x75, "SMaL Camera Technologies"},
+ { 4, 0x76, "Thomson SC"},
+ { 4, 0xf7, "Airgo Networks"},
+ { 4, 0xf8, "Wisair"},
+ { 4, 0x79, "SigmaTel"},
+ { 4, 0x7a, "Arkados"},
+ { 4, 0xfb, "Compete IT Co. KG"},
+ { 4, 0x7c, "Eudar Technology"},
+ { 4, 0xfd, "Focus Enhancements"},
+ { 4, 0xfe, "Xyratex"},
+ { 5, 0x01, "Specular Networks"},
+ { 5, 0x02, "Patriot Memory (PDP Systems)"},
+ { 5, 0x83, "U-Chip Technology Corp."},
+ { 5, 0x04, "Silicon Optix"},
+ { 5, 0x85, "Greenfield Networks"},
+ { 5, 0x86, "CompuRAM"},
+ { 5, 0x07, "Stargen"},
+ { 5, 0x08, "NetCell"},
+ { 5, 0x89, "Excalibrus Technologies"},
+ { 5, 0x8a, "SCM Microsystems"},
+ { 5, 0x0b, "Xsigo Systems"},
+ { 5, 0x8c, "CHIPS & Systems"},
+ { 5, 0x0d, "Tier"},
+ { 5, 0x0e, "CWRL Labs"},
+ { 5, 0x8f, "Teradici"},
+ { 5, 0x10, "Gigaram"},
+ { 5, 0x91, "g2 Microsystems"},
+ { 5, 0x92, "PowerFlash Semiconductor"},
+ { 5, 0x13, "P.A. Semi"},
+ { 5, 0x94, "NovaTech Solutions, S.A."},
+ { 5, 0x15, "c2 Microsystems"},
+ { 5, 0x16, "Level5 Networks"},
+ { 5, 0x97, "COS Memory AG"},
+ { 5, 0x98, "Innovasic Semiconductor"},
+ { 5, 0x19, "02IC Co."},
+ { 5, 0x1a, "Tabula,"},
+ { 5, 0x9b, "Crucial Technology"},
+ { 5, 0x1c, "Chelsio Communications"},
+ { 5, 0x9d, "Solarflare Communications"},
+ { 5, 0x9e, "Xambala"},
+ { 5, 0x1f, "EADS Astrium"},
+ { 5, 0x20, "Terra Semiconductor"},
+ { 5, 0xa1, "Imaging Works"},
+ { 5, 0xa2, "Astute Networks"},
+ { 5, 0x23, "Tzero"},
+ { 5, 0xa4, "Emulex"},
+ { 5, 0x25, "Power-One"},
+ { 5, 0x26, "Pulse~LINK"},
+ { 5, 0xa7, "Hon Hai Precision Industry"},
+ { 5, 0xa8, "White Rock Networks"},
+ { 5, 0x29, "Telegent Systems USA"},
+ { 5, 0x2a, "Atrua Technologies"},
+ { 5, 0xab, "Acbel Polytech"},
+ { 5, 0x2c, "eRide"},
+ { 5, 0xad, "ULi Electronics"},
+ { 5, 0xae, "Magnum Semiconductor"},
+ { 5, 0x2f, "neoOne Technology"},
+ { 5, 0xb0, "Connex Technology"},
+ { 5, 0x31, "Stream Processors"},
+ { 5, 0x32, "Focus Enhancements"},
+ { 5, 0xb3, "Telecis Wireless"},
+ { 5, 0x34, "uNav Microelectronics"},
+ { 5, 0xb5, "Tarari"},
+ { 5, 0xb6, "Ambric"},
+ { 5, 0x37, "Newport Media"},
+ { 5, 0x38, "VMTS"},
+ { 5, 0xb9, "Enuclia Semiconductor"},
+ { 5, 0xba, "Virtium Technology"},
+ { 5, 0x3b, "Solid State System Co."},
+ { 5, 0xbc, "Kian Tech LLC"},
+ { 5, 0x3d, "Artimi"},
+ { 5, 0x3e, "Power Quotient International"},
+ { 5, 0xbf, "Avago Technologies"},
+ { 5, 0x40, "ADTechnology"},
+ { 5, 0xc1, "Sigma Designs"},
+ { 5, 0xc2, "SiCortex"},
+ { 5, 0x43, "Ventura Technology Group"},
+ { 5, 0xc4, "eASIC"},
+ { 5, 0x45, "M.H.S. SAS"},
+ { 5, 0x46, "Micro Star International"},
+ { 5, 0xc7, "Rapport"},
+ { 5, 0xc8, "Makway International"},
+ { 5, 0x49, "Broad Reach Engineering Co."},
+ { 5, 0x4a, "Semiconductor Mfg Intl Corp"},
+ { 5, 0xcb, "SiConnect"},
+ { 5, 0x4c, "FCI USA"},
+ { 5, 0xcd, "Validity Sensors"},
+ { 5, 0xce, "Coney Technology Co."},
+ { 5, 0x4f, "Spans Logic"},
+ { 5, 0xd0, "Neterion"},
+ { 5, 0x51, "Qimonda"},
+ { 5, 0x52, "New Japan Radio Co."},
+ { 5, 0xd3, "Velogix"},
+ { 5, 0x54, "Montalvo Systems"},
+ { 5, 0xd5, "iVivity"},
+ { 5, 0xd6, "Walton Chaintech"},
+ { 5, 0x57, "AENEON"},
+ { 5, 0x58, "Lorom Industrial Co."},
+ { 5, 0xd9, "Radiospire Networks"},
+ { 5, 0xda, "Sensio Technologies"},
+ { 5, 0x5b, "Nethra Imaging"},
+ { 5, 0xdc, "Hexon Technology Pte"},
+ { 5, 0x5d, "CompuStocx (CSX)"},
+ { 5, 0x5e, "Methode Electronics"},
+ { 5, 0xdf, "Connect One"},
+ { 5, 0xe0, "Opulan Technologies"},
+ { 5, 0x61, "Septentrio NV"},
+ { 5, 0x62, "Goldenmars Technology"},
+ { 5, 0xe3, "Kreton"},
+ { 5, 0x64, "Cochlear"},
+ { 5, 0xe5, "Altair Semiconductor"},
+ { 5, 0xe6, "NetEffect"},
+ { 5, 0x67, "Spansion"},
+ { 5, 0x68, "Taiwan Semiconductor Mfg"},
+ { 5, 0xe9, "Emphany Systems"},
+ { 5, 0xea, "ApaceWave Technologies"},
+ { 5, 0x6b, "Mobilygen"},
+ { 5, 0xec, "Tego"},
+ { 5, 0x6d, "Cswitch"},
+ { 5, 0x6e, "Haier (Beijing) IC Design Co."},
+ { 5, 0xef, "MetaRAM"},
+ { 5, 0x70, "Axel Electronics Co."},
+ { 5, 0xf1, "Tilera"},
+ { 5, 0xf2, "Aquantia"},
+ { 5, 0x73, "Vivace Semiconductor"},
+ { 5, 0xf4, "Redpine Signals"},
+ { 5, 0x75, "Octalica"},
+ { 5, 0x76, "InterDigital Communications"},
+ { 5, 0xf7, "Avant Technology"},
+ { 5, 0xf8, "Asrock"},
+ { 5, 0x79, "Availink"},
+ { 5, 0x7a, "Quartics"},
+ { 5, 0xfb, "Element CXI"},
+ { 5, 0x7c, "Innovaciones Microelectronicas"},
+ { 5, 0xfd, "VeriSilicon Microelectronics"},
+ { 5, 0xfe, "W5 Networks"},
+ { 6, 0x01, "MOVEKING"},
+ { 6, 0x02, "Mavrix Technology"},
+ { 6, 0x83, "CellGuide"},
+ { 6, 0x04, "Faraday Technology"},
+ { 6, 0x85, "Diablo Technologies"},
+ { 6, 0x86, "Jennic"},
+ { 6, 0x07, "Octasic"},
+ { 6, 0x08, "Molex"},
+ { 6, 0x89, "3Leaf Networks"},
+ { 6, 0x8a, "Bright Micron Technology"},
+ { 6, 0x0b, "Netxen"},
+ { 6, 0x8c, "NextWave Broadband"},
+ { 6, 0x0d, "DisplayLink"},
+ { 6, 0x0e, "ZMOS Technology"},
+ { 6, 0x8f, "Tec-Hill"},
+ { 6, 0x10, "Multigig"},
+ { 6, 0x91, "Amimon"},
+ { 6, 0x92, "Euphonic Technologies"},
+ { 6, 0x13, "BRN Phoenix"},
+ { 6, 0x94, "InSilica"},
+ { 6, 0x15, "Ember"},
+ { 6, 0x16, "Avexir Technologies"},
+ { 6, 0x97, "Echelon"},
+ { 6, 0x98, "Edgewater Computer Systems"},
+ { 6, 0x19, "XMOS Semiconductor"},
+ { 6, 0x1a, "GENUSION"},
+ { 6, 0x9b, "Memory Corp NV"},
+ { 6, 0x1c, "SiliconBlue Technologies"},
+ { 6, 0x9d, "Rambus"},
+ { 6, 0x9e, "Andes Technology"},
+ { 6, 0x1f, "Coronis Systems"},
+ { 6, 0x20, "Achronix Semiconductor"},
+ { 6, 0xa1, "Siano Mobile Silicon"},
+ { 6, 0xa2, "Semtech"},
+ { 6, 0x23, "Pixelworks"},
+ { 6, 0xa4, "Gaisler Research AB"},
+ { 6, 0x25, "Teranetics"},
+ { 6, 0x26, "Toppan Printing Co."},
+ { 6, 0xa7, "Kingxcon"},
+ { 6, 0xa8, "Silicon Integrated Systems"},
+ { 6, 0x29, "I-O Data Device"},
+ { 6, 0x2a, "NDS Americas"},
+ { 6, 0xab, "Solomon Systech Limited"},
+ { 6, 0x2c, "On Demand Microelectronics"},
+ { 6, 0xad, "Amicus Wireless"},
+ { 6, 0xae, "SMARDTV SNC"},
+ { 6, 0x2f, "Comsys Communication"},
+ { 6, 0xb0, "Movidia"},
+ { 6, 0x31, "Javad GNSS"},
+ { 6, 0x32, "Montage Technology Group"},
+ { 6, 0xb3, "Trident Microsystems"},
+ { 6, 0x34, "Super Talent"},
+ { 6, 0xb5, "Optichron"},
+ { 6, 0xb6, "Future Waves UK"},
+ { 6, 0x37, "SiBEAM"},
+ { 6, 0x38, "Inicore,"},
+ { 6, 0xb9, "Virident Systems"},
+ { 6, 0xba, "M2000"},
+ { 6, 0x3b, "ZeroG Wireless"},
+ { 6, 0xbc, "Gingle Technology Co."},
+ { 6, 0x3d, "Space Micro"},
+ { 6, 0x3e, "Wilocity"},
+ { 6, 0xbf, "Novafora, Ic."},
+ { 6, 0x40, "iKoa"},
+ { 6, 0xc1, "ASint Technology"},
+ { 6, 0xc2, "Ramtron"},
+ { 6, 0x43, "Plato Networks"},
+ { 6, 0xc4, "IPtronics AS"},
+ { 6, 0x45, "Infinite-Memories"},
+ { 6, 0x46, "Parade Technologies"},
+ { 6, 0xc7, "Dune Networks"},
+ { 6, 0xc8, "GigaDevice Semiconductor"},
+ { 6, 0x49, "Modu"},
+ { 6, 0x4a, "CEITEC"},
+ { 6, 0xcb, "Northrop Grumman"},
+ { 6, 0x4c, "XRONET"},
+ { 6, 0xcd, "Sicon Semiconductor AB"},
+ { 6, 0xce, "Atla Electronics Co."},
+ { 6, 0x4f, "TOPRAM Technology"},
+ { 6, 0xd0, "Silego Technology"},
+ { 6, 0x51, "Kinglife"},
+ { 6, 0x52, "Ability Industries"},
+ { 6, 0xd3, "Silicon Power Computer & Communications"},
+ { 6, 0x54, "Augusta Technology"},
+ { 6, 0xd5, "Nantronics Semiconductors"},
+ { 6, 0xd6, "Hilscher Gesellschaft"},
+ { 6, 0x57, "Quixant"},
+ { 6, 0x58, "Percello"},
+ { 6, 0xd9, "NextIO"},
+ { 6, 0xda, "Scanimetrics"},
+ { 6, 0x5b, "FS-Semi Company"},
+ { 6, 0xdc, "Infinera"},
+ { 6, 0x5d, "SandForce"},
+ { 6, 0x5e, "Lexar Media"},
+ { 6, 0xdf, "Teradyne"},
+ { 6, 0xe0, "Memory Exchange Corp."},
+ { 6, 0x61, "Suzhou Smartek Electronics"},
+ { 6, 0x62, "Avantium"},
+ { 6, 0xe3, "ATP Electronics"},
+ { 6, 0x64, "Valens Semiconductor"},
+ { 6, 0xe5, "Agate Logic"},
+ { 6, 0xe6, "Netronome"},
+ { 6, 0x67, "Zenverge"},
+ { 6, 0x68, "N-trig"},
+ { 6, 0xe9, "SanMax Technologies"},
+ { 6, 0xea, "Contour Semiconductor"},
+ { 6, 0x6b, "TwinMOS"},
+ { 6, 0xec, "Silicon Systems"},
+ { 6, 0x6d, "V-Color Technology"},
+ { 6, 0x6e, "Certicom"},
+ { 6, 0xef, "JSC ICC Milandr"},
+ { 6, 0x70, "PhotoFast Global"},
+ { 6, 0xf1, "InnoDisk"},
+ { 6, 0xf2, "Muscle Power"},
+ { 6, 0x73, "Energy Micro"},
+ { 6, 0xf4, "Innofidei"},
+ { 9, 0xff, ""}
+};
+
diff --git a/lib.c b/lib.c
index 01dc08c..27c7ec0 100644
--- a/lib.c
+++ b/lib.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V2.00 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, memtest@memtest.org
* http://www.canardplus.com - http://www.memtest.org
*/
@@ -13,7 +13,9 @@
#include "test.h"
#include "config.h"
#include "screen_buffer.h"
+#include "smp.h"
+#define NULL 0
int slock = 0, lsr = 0;
short serial_cons = SERIAL_CONSOLE_DEFAULT;
@@ -62,6 +64,8 @@ char *codes[] = {
};
struct eregs {
+ ulong ss;
+ ulong ds;
ulong esp;
ulong ebp;
ulong esi;
@@ -89,6 +93,19 @@ int memcmp(const void *s1, const void *s2, ulong count)
return 0;
}
+void memcpy (void *dst, void *src, int len)
+{
+ char *s = (char*)src;
+ char *d = (char*)dst;
+ int i;
+
+ if (len <= 0) {
+ return;
+ }
+ for (i = 0 ; i < len; i++) {
+ *d++ = *s++;
+ }
+}
int strncmp(const char *s1, const char *s2, ulong n) {
signed char res = 0;
while (n) {
@@ -344,6 +361,25 @@ void dprint(int y, int x, ulong val, int len, int right)
cprint(y,x,buf);
}
+
+/*
+ * Get_number of digits
+ */
+int getnum(ulong val)
+{
+ int len = 0;
+ int i = 1;
+
+ while(i <= val)
+ {
+ len++;
+ i *= 10;
+ }
+
+ return len;
+
+}
+
/*
* Print a hex number on screen at least digits long
*/
@@ -495,7 +531,10 @@ void inter(struct eregs *trap_regs)
hprint(line+8, 25, trap_regs->ebp);
cprint(line+9, 20, "esp: ");
hprint(line+9, 25, trap_regs->esp);
-
+ cprint(line+7, 0, " DS: ");
+ hprint(line+7, 7, trap_regs->ds);
+ cprint(line+8, 0, " SS: ");
+ hprint(line+8, 7, trap_regs->ss);
cprint(line+1, 38, "Stack:");
for (i=0; i<12; i++) {
hprint(line+2+i, 38, trap_regs->esp+(4*i));
@@ -1133,5 +1172,6 @@ put_lp(char c, short port)
outb((LP_PSELECP | LP_PINITP), CONTROL(port));
lp_wait(DELAY);
}
+
#endif
diff --git a/main.c b/main.c
index 012e539..ea96f2d 100644
--- a/main.c
+++ b/main.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V2.01 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -17,17 +17,17 @@
extern void bzero();
const struct tseq tseq[] = {
- {1, 5, 3, 0, 0, "[Address test, walking ones, uncached]"},
- {1, 6, 3, 2, 0, "[Address test, own address] "},
- {1, 0, 3, 14, 0, "[Moving inversions, ones & zeros] "},
- {1, 1, 2, 80, 0, "[Moving inversions, 8 bit pattern] "},
- {1, 10, 60, 300, 0, "[Moving inversions, random pattern] "},
- {1, 7, 64, 66, 0, "[Block move, 64 moves] "},
- {1, 2, 2, 320, 0, "[Moving inversions, 32 bit pattern] "},
- {1, 9, 40, 120, 0, "[Random number sequence] "},
- {1, 3, 2, 360, 0, "[Modulo 20, random pattern] "},
- {1, 8, 1, 2, 0, "[Bit fade test, 90 min, 2 patterns] "},
- {0, 0, 0, 0, 0, NULL}
+ {1, 5, 4, 0, "[Address test, walking ones] "},
+ {1, 6, 4, 0, "[Address test, own address] "},
+ {1, 0, 4, 0, "[Moving inversions, ones & zeros] "},
+ {1, 1, 2, 0, "[Moving inversions, 8 bit pattern] "},
+ {1, 10, 50, 0, "[Moving inversions, random pattern] "},
+ {1, 7, 80, 0, "[Block move, 80 moves] "},
+ {1, 2, 2, 0, "[Moving inversions, 32 bit pattern] "},
+ {1, 9, 30, 0, "[Random number sequence] "},
+ {1, 11, 6, 0, "[Modulo 20, Random pattern] "},
+ {1, 8, 1, 0, "[Bit fade test, 90 min, 2 patterns] "},
+ {0, 0, 0, 0, NULL}
};
char firsttime = 0;
@@ -44,6 +44,7 @@ int nticks;
ulong high_test_adr = 0x200000;
static int window = 0;
+static int c_iter;
static struct pmap windows[] =
{
{ 0, 0x080000 },
@@ -101,8 +102,9 @@ static struct pmap windows[] =
#error LOW_TEST_ADR must be below 640K
#endif
-static int find_ticks_for_test(unsigned long chunks, int test);
-static void compute_segments(int win);
+static int find_ticks_for_test(int ch, int test);
+static int compute_segments(int win);
+void find_ticks_for_pass(void);
static void __run_at(unsigned long addr)
{
@@ -196,7 +198,11 @@ void do_test(void)
if ((ulong)&_start != LOW_TEST_ADR) {
restart();
}
+
init();
+
+ find_ticks_for_pass();
+
windows[0].start =
( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;
@@ -279,6 +285,13 @@ void do_test(void)
if (v->testsel >= 0) {
v->test = v->testsel;
}
+
+ if (v->pass == 0) {
+ c_iter = tseq[v->test].iter/2;
+ } else {
+ c_iter = tseq[v->test].iter;
+ }
+
dprint(LINE_TST, COL_MID+6, v->test, 2, 1);
cprint(LINE_TST, COL_MID+9, tseq[v->test].msg);
set_cache(tseq[v->test].cache);
@@ -297,105 +310,128 @@ void do_test(void)
switch(tseq[v->test].pat) {
/* Now do the testing according to the selected pattern */
- case 0: /* Moving inversions, all ones and zeros */
- case 4:
+ case 0: /* Moving inversions, all ones and zeros (test #2) */
+ p1 = 0;
+ p2 = ~p1;
+ movinv1(c_iter,p1,p2);
+ BAILOUT;
- if (tseq[v->test].pat == 1)
- p0 = 0x80808080;
- else
- p0 = 0;
-
- for ( ; ; ) {
- movinv1(tseq[v->test].iter,p0,~p0);
- BAILOUT;
-
- /* Switch patterns */
- movinv1(tseq[v->test].iter,~p0,p0);
- BAILOUT
- if ( !((unsigned char)(p0 >>= 1) & 0x7F) )
- break;
- }
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ movinv1(c_iter,p1,p2);
+ BAILOUT;
break;
-
- case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */
+
+ case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */
p0 = 0x80;
for (i=0; i<8; i++, p0=p0>>1) {
p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
p2 = ~p1;
- movinv1(tseq[v->test].iter,p1,p2);
+ movinv1(c_iter,p1,p2);
BAILOUT;
/* Switch patterns */
p2 = p1;
p1 = ~p2;
- movinv1(tseq[v->test].iter,p1,p2);
+ movinv1(c_iter,p1,p2);
BAILOUT
}
- break;
-
+ break;
- case 2: /* Moving inversions, 32 bit shifting pattern, very long */
+ case 2: /* Moving inversions, 32 bit shifting pattern (test #6) */
for (i=0, p1=1; p1; p1=p1<<1, i++) {
- movinv32(tseq[v->test].iter,p1, 1, 0x80000000, 0, i);
+ movinv32(c_iter,p1, 1, 0x80000000, 0, i);
BAILOUT
- movinv32(tseq[v->test].iter,~p1, 0xfffffffe, 0x7fffffff, 1, i);
+ movinv32(c_iter,~p1, 0xfffffffe,
+ 0x7fffffff, 1, i);
BAILOUT
}
break;
- case 3: /* Modulo 20, random */
- for (j=0; j<tseq[v->test].iter; j++) {
- p1 = rand();
+ case 3: /* Modulo 20 check, all ones and zeros (unused) */
+ p1=0;
+ for (i=0; i<MOD_SZ; i++) {
+ p2 = ~p1;
+ modtst(i, c_iter, p1, p2);
+ BAILOUT
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ modtst(i, c_iter, p1,p2);
+ BAILOUT
+ }
+ break;
+
+ case 4: /* Modulo 20 check, 8 bit pattern (unused) */
+ p0 = 0x80;
+ for (j=0; j<8; j++, p0=p0>>1) {
+ p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- modtst(i, tseq[v->test].iter, p1, p2);
+ modtst(i, c_iter, p1, p2);
BAILOUT
/* Switch patterns */
p2 = p1;
p1 = ~p2;
- modtst(i, tseq[v->test].iter, p1, p2);
+ modtst(i, c_iter, p1, p2);
BAILOUT
}
}
break;
-
- case 5: /* Address test, walking ones */
+ case 5: /* Address test, walking ones (test #0) */
addr_tst1();
BAILOUT;
break;
- case 6: /* Address test, own address */
+ case 6: /* Address test, own address (test #1) */
addr_tst2();
BAILOUT;
break;
- case 7: /* Block move test */
- block_move(tseq[v->test].iter);
+ case 7: /* Block move (test #5) */
+ block_move(c_iter);
BAILOUT;
break;
-
- case 8: /* Bit fade test */
+ case 8: /* Bit fade test (test #9) */
if (window == 0 ) {
bit_fade();
}
BAILOUT;
break;
-
- case 9: /* Random Data Sequence */
- for (i=0; i < tseq[v->test].iter; i++) {
+ case 9: /* Random Data Sequence (test #7) */
+ for (i=0; i < c_iter; i++) {
movinvr();
BAILOUT;
}
break;
- case 10: /* Random Data */
- for (i=0; i < tseq[v->test].iter; i++) {
+ case 10: /* Random Data (test #4) */
+ for (i=0; i < c_iter; i++) {
p1 = rand();
p2 = ~p1;
movinv1(2,p1,p2);
BAILOUT;
}
break;
+
+ case 11: /* Modulo 20 check, Random pattern (test #8) */
+ for (j=0; j<c_iter; j++) {
+ p1 = rand();
+ for (i=0; i<MOD_SZ; i++) {
+ p2 = ~p1;
+ modtst(i, 2, p1, p2);
+ BAILOUT
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ modtst(i, 2, p1, p2);
+ BAILOUT
+ }
+ }
+ break;
}
skip_window:
if (bail) {
@@ -458,8 +494,8 @@ void do_test(void)
cprint(0, COL_MID+8,
" ");
if (v->ecount == 0 && v->testsel < 0) {
- cprint(LINE_MSG, COL_MSG,
- "Pass complete, no errors, press Esc to exit");
+ cprint(LINE_MSG+5, 0,
+ " *****Pass complete, no errors, press Esc to exit***** ");
if(BEEP_END_NO_ERROR) {
beep(1000);
beep(2000);
@@ -494,9 +530,7 @@ void restart()
run_at(LOW_TEST_ADR);
}
-
-/* Compute the total number of ticks per pass */
-void find_ticks(void)
+void find_ticks_for_pass(void)
{
int i, j, chunks;
@@ -526,18 +560,62 @@ void find_ticks(void)
}
}
-static int find_ticks_for_test(unsigned long chunks, int test)
+
+static int find_ticks_for_test(int ch, int test)
{
- int ticks;
- ticks = chunks * tseq[test].ticks;
- if (tseq[test].pat == 5) {
- /* Address test, walking ones */
+ int ticks=0, c;
+
+ /* Set the number of iterations. We only do half of the iterations */
+ /* on the first pass */
+ if (v->pass == 0 && FIRST_PASS_HALF_ITERATIONS) {
+ c = tseq[test].iter/2;
+ } else {
+ c = tseq[test].iter;
+ }
+
+ switch(tseq[test].pat) {
+ case 0: /* Moving inversions, all ones and zeros (test #2) */
+ ticks = 2 + 4 * c;
+ break;
+ case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */
+ ticks = 24 + 24 * c;
+ break;
+ case 2: /* Moving inversions, 32 bit shifting pattern, very long */
+ ticks = (1 + c * 2) * 80;
+ break;
+ case 3: /* Modulo 20 check, all ones and zeros (unused) */
+ ticks = (2 + c) * 40;
+ break;
+ case 4: /* Modulo 20 check, 8 bit pattern (unused) */
+ ticks = (2 + c) * 40 * 8;
+ break;
+ case 5: /* Address test, walking ones (test #0) */
ticks = 4;
+ break;
+ case 6: /* Address test, own address (test #1) */
+ ticks = 2;
+ break;
+ case 7: /* Block move (test #5) */
+ ticks = 2 + c;
+ break;
+ case 8: /* Bit fade test (test #9) */
+ ticks = 1;
+ break;
+ case 9: /* Random Data Sequence (test #7) */
+ ticks = 3 * c;
+ break;
+ case 10: /* Random Data (test #4) */
+ ticks = c + 4 * c;
+ break;
+ case 11: /* Modulo 20 check, Random pattern (test #8) */
+ ticks = 4 * 40 * c;
+ break;
}
- return ticks;
+
+ return ticks*ch;
}
-static void compute_segments(int win)
+static int compute_segments(int win)
{
unsigned long wstart, wend;
int i;
@@ -555,7 +633,7 @@ static void compute_segments(int win)
wend = v->plim_upper;
}
if (wstart >= wend) {
- return;
+ return(0);
}
/* List the segments being tested */
for (i=0; i< v->msegs; i++) {
@@ -601,11 +679,11 @@ static void compute_segments(int win)
cprint(LINE_SCROLL+(2*i+1), 44, "i=");
hprint(LINE_SCROLL+(2*i+1), 46, i);
-
- cprint(LINE_SCROLL+(2*i+2), 0,
+
+ cprint(LINE_SCROLL+(2*i+2), 0,
" "
" ");
- cprint(LINE_SCROLL+(2*i+3), 0,
+ cprint(LINE_SCROLL+(2*i+3), 0,
" "
" ");
#endif
@@ -614,10 +692,12 @@ static void compute_segments(int win)
v->map[segs].start = mapping(start);
v->map[segs].end = emapping(end);
#if 0
- cprint(LINE_SCROLL+(2*i+1), 54, " segs: ");
- hprint(LINE_SCROLL+(2*i+1), 61, segs);
+ cprint(LINE_SCROLL+(2*i+1), 54, " sg: ");
+ hprint(LINE_SCROLL+(2*i+1), 61, sg);
#endif
segs++;
}
}
+ return (segs);
}
+
diff --git a/makedos.sh b/makedos.sh
new file mode 100755
index 0000000..adeb29d
--- /dev/null
+++ b/makedos.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [ -f memtest.bin ]
+then
+CSIZE="$(awk 'NR==16' mt86+_loader.asm | awk '{print $2}')";
+NSIZE="$(ls -l memtest.bin | awk '{print $5}')";
+sed "s/$CSIZE/$NSIZE/" mt86+_loader.asm > mt86+_loader.asm.new;
+mv mt86+_loader.asm.new mt86+_loader.asm;
+nasm mt86+_loader.asm;
+fi
diff --git a/makeiso.sh b/makeiso.sh
index 7180879..95751b5 100755
--- a/makeiso.sh
+++ b/makeiso.sh
@@ -37,9 +37,9 @@ cd cd
echo -e "There is nothing to do here\r\r\nMemtest86+ is located on the bootsector of this CD\r\r\n" > README.TXT
echo -e "Just boot from this CD and Memtest86+ will launch" >> README.TXT
-mkisofs -A "MKISOFS 1.1.2" -p "Memtest86+ 2.11" -publisher "Samuel D. <sdemeule@memtest.org>" -b boot/memtest.img -c boot/boot.catalog -V "MT201" -o memtest.iso .
-mv memtest.iso ../mt211.iso
+mkisofs -A "MKISOFS 1.1.2" -p "Memtest86+ 4.00" -publisher "Samuel D. <sdemeule@memtest.org>" -b boot/memtest.img -c boot/boot.catalog -V "MT201" -o memtest.iso .
+mv memtest.iso ../mt400.iso
cd ..
rm -rf cd
-echo "Done! Memtest86+ ISO is mt211.iso"
+echo "Done! Memtest86+ 4.00 ISO is mt400.iso"
diff --git a/memsize.c b/memsize.c
index ce7e177..3916538 100644
--- a/memsize.c
+++ b/memsize.c
@@ -1,4 +1,4 @@
-/* memsize.c - MemTest-86 Version 3.2
+/* memsize.c - MemTest-86 Version 3.3
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
@@ -21,11 +21,11 @@ extern volatile ulong *p;
static void sort_pmap(void);
static int check_ram(void);
-static void memsize_bios(int res);
-static void memsize_820(int res);
+static void memsize_bios(void);
+static void memsize_820(void);
static void memsize_801(void);
-static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios,
- short old_nr, short res);
+static int sanitize_e820_map(struct e820entry *orig_map,
+ struct e820entry *new_bios, short old_nr);
static void memsize_linuxbios();
static void memsize_probe(void);
static int check_ram(void);
@@ -56,16 +56,12 @@ void mem_size(void)
switch (memsz_mode) {
case SZ_MODE_BIOS:
/* Get the memory size from the BIOS */
- memsize_bios(0);
- break;
- case SZ_MODE_BIOS_RES:
- /* Get the memory size from the BIOS, include reserved mem */
- memsize_bios(1);
+ memsize_bios();
break;
case SZ_MODE_PROBE:
/* Probe to find memory */
memsize_probe();
- cprint(LINE_INFO, COL_MMAP, " Probed ");
+ cprint(LINE_INFO, COL_MMAP, "Probed");
break;
}
/* Guarantee that pmap entries are in ascending order */
@@ -77,10 +73,10 @@ void mem_size(void)
aprint(LINE_INFO, COL_RESERVED, v->reserved_pages);
}
-static void memsize_bios(int res)
+static void memsize_bios()
{
if (firmware == FIRMWARE_PCBIOS) {
- memsize_820(res);
+ memsize_820();
}
else if (firmware == FIRMWARE_LINUXBIOS) {
memsize_linuxbios();
@@ -105,7 +101,7 @@ static void sort_pmap(void)
if (i != j) {
struct pmap temp;
temp = v->pmap[i];
- memmove(&v->pmap[j], &v->pmap[j+1],
+ memmove(&v->pmap[j], &v->pmap[j+1],
(i -j)* sizeof(temp));
v->pmap[j] = temp;
}
@@ -129,16 +125,15 @@ static void memsize_linuxbios(void)
n++;
}
v->msegs = n;
- cprint(LINE_INFO, COL_MMAP, "LinuxBIOS");
+ cprint(LINE_INFO, COL_MMAP, "LxBIOS");
}
-static void memsize_820(int res)
+static void memsize_820()
{
int i, n, nr;
struct e820entry nm[E820MAX];
/* Clean up, adjust and copy the BIOS-supplied E820-map. */
- /* If the res arg is true reclassify reserved memory as E820_RAM */
- nr = sanitize_e820_map(e820, nm, e820_nr, res);
+ nr = sanitize_e820_map(e820, nm, e820_nr);
/* If there is not a good 820 map use the BIOS 801/88 info */
if (nr < 1 || nr > E820MAX) {
@@ -149,7 +144,7 @@ static void memsize_820(int res)
/* Build the memory map for testing */
n = 0;
for (i=0; i<nr; i++) {
- if (nm[i].type == E820_RAM) {
+ if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) {
unsigned long long start;
unsigned long long end;
start = nm[i].addr;
@@ -169,24 +164,14 @@ static void memsize_820(int res)
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
- } else {
- /* If this is reserved memory starting at the top
- * of memory then don't count it as reserved, since
- * it is very unlikely to be real memory.
- */
- if (nm[i].addr < 0xff000000) {
- v->reserved_pages += nm[i].size >> 12;
- }
+ } else if (nm[i].type == E820_NVS) {
+ v->reserved_pages += nm[i].size >> 12;
}
}
v->msegs = n;
- if (res) {
- cprint(LINE_INFO, COL_MMAP, "e820-All");
- } else {
- cprint(LINE_INFO, COL_MMAP, "e820-Std");
- }
+ cprint(LINE_INFO, COL_MMAP, " e820");
}
-
+
static void memsize_801(void)
{
ulong mem_size;
@@ -196,10 +181,10 @@ static void memsize_801(void)
if (alt_mem_k < ext_mem_k) {
mem_size = ext_mem_k;
- cprint(LINE_INFO, COL_MMAP, "e88-Std ");
+ cprint(LINE_INFO, COL_MMAP, " e88");
} else {
mem_size = alt_mem_k;
- cprint(LINE_INFO, COL_MMAP, "e801-Std");
+ cprint(LINE_INFO, COL_MMAP, " e801");
}
/* First we map in the first 640k */
v->pmap[0].start = 0;
@@ -216,12 +201,12 @@ static void memsize_801(void)
/*
* Sanitize the BIOS e820 map.
*
- * Some e820 responses include overlapping entries. The following
+ * Some e820 responses include overlapping entries. The following
* replaces the original e820 map with a new one, removing overlaps.
*
*/
static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios,
- short old_nr, short res)
+ short old_nr)
{
struct change_member {
struct e820entry *pbios; /* pointer to original bios entry */
@@ -284,22 +269,6 @@ static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_b
for (i=0; i<old_nr; i++) {
if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
return 0;
- if (res) {
- /* If we want to test the reserved memory include
- * everything except for reserved segments that start
- * at the the top of memory
- */
- if (biosmap[i].type == E820_RESERVED &&
- biosmap[i].addr > 0xff000000) {
- continue;
- }
- biosmap[i].type = E820_RAM;
- } else {
- /* It is always be safe to test ACPI ram */
- if ( biosmap[i].type == E820_ACPI) {
- biosmap[i].type = E820_RAM;
- }
- }
}
/* create pointers for initial change-point information (for sorting) */
@@ -374,7 +343,7 @@ static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_b
/* move forward only if the new size was non-zero */
if (new_bios[new_bios_entry].size != 0)
if (++new_bios_entry >= E820MAX)
- break; /* no more space left for new bios entries */
+ break; /* no more space left for new bios entries */
}
if (current_type != 0) {
new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
@@ -397,8 +366,8 @@ static void memsize_probe(void)
* must be limited. The max address is found by checking for
* memory wrap from 1MB to 4GB. */
p1 = (ulong)&magic;
- m_lim = 0xfffffffc;
- for (p2 = 0x100000; p2; p2 <<= 1) {
+ m_lim = 0xfffffffc;
+ for (p2 = 0x100000; p2; p2 <<= 1) {
p = (ulong *)(p1 + p2);
if (*p == 0x1234569) {
m_lim = --p2;
@@ -415,7 +384,7 @@ static void memsize_probe(void)
v->pmap[i].start = ((ulong)&_end + (1 << 12) - 1) >> 12;
p = (ulong *)(v->pmap[i].start << 12);
- /* Limit search for memory to m_lim and make sure we don't
+ /* Limit search for memory to m_lim and make sure we don't
* overflow the 32 bit size of p. */
while ((ulong)p < m_lim && (ulong)p >= (ulong)&_end) {
/*
@@ -482,34 +451,34 @@ fstart:
* We then check that at least one bit changed in each byte before
* believing that it really is memory. */
-static int check_ram(void)
+static int check_ram(void)
{
- int s;
-
- p1 = *p;
-
- /* write the complement */
- *p = ~p1;
- p2 = *p;
- s = 0;
-
- /* Now make sure a bit changed in each byte */
- if ((0xff & p1) != (0xff & p2)) {
- s++;
- }
- if ((0xff00 & p1) != (0xff00 & p2)) {
- s++;
- }
- if ((0xff0000 & p1) != (0xff0000 & p2)) {
- s++;
- }
- if ((0xff000000 & p1) != (0xff000000 & p2)) {
- s++;
- }
- if (s == 4) {
- /* RAM at this address */
- return 1;
- }
-
- return 0;
+ int s;
+
+ p1 = *p;
+
+ /* write the complement */
+ *p = ~p1;
+ p2 = *p;
+ s = 0;
+
+ /* Now make sure a bit changed in each byte */
+ if ((0xff & p1) != (0xff & p2)) {
+ s++;
+ }
+ if ((0xff00 & p1) != (0xff00 & p2)) {
+ s++;
+ }
+ if ((0xff0000 & p1) != (0xff0000 & p2)) {
+ s++;
+ }
+ if ((0xff000000 & p1) != (0xff000000 & p2)) {
+ s++;
+ }
+ if (s == 4) {
+ /* RAM at this address */
+ return 1;
+ }
+
+ return 0;
}
diff --git a/memtest.exe b/memtest.exe
new file mode 100644
index 0000000..a79b407
--- /dev/null
+++ b/memtest.exe
Binary files differ
diff --git a/memtest_shared.lds b/memtest_shared.lds
index d4576a2..453916c 100644
--- a/memtest_shared.lds
+++ b/memtest_shared.lds
@@ -18,6 +18,7 @@ SECTIONS {
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynamic : { *(.dynamic) }
.rel.text : { *(.rel.text .rel.text.*) }
diff --git a/mt86+_loader b/mt86+_loader
index ee3d2ec..adac56e 100644
--- a/mt86+_loader
+++ b/mt86+_loader
Binary files differ
diff --git a/mt86+_loader.asm b/mt86+_loader.asm
index 29b0322..03cea01 100644
--- a/mt86+_loader.asm
+++ b/mt86+_loader.asm
@@ -12,8 +12,8 @@
; The good thing is that you get a single file which can be
; compressed, for example with http://upx.sf.net/ (UPX).
-%define fullsize (116508 + buffer - exeh)
- ; 116508 is the size of memtest86+ V2.11, adjust as needed!
+%define fullsize (160280 + buffer - exeh)
+ ; 160280 is the size of memtest86+ V4.00, adjust as needed!
%define stacksize 2048
%define stackpara ((stacksize + 15) / 16)
diff --git a/pci.c b/pci.c
index f2eb58d..e6c2cf6 100644
--- a/pci.c
+++ b/pci.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V1.94 Specific code (GPL V2.0)
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -25,17 +25,24 @@ static unsigned char pci_conf_type = PCI_CONF_TYPE_NONE;
#define PCI_CONF2_ADDRESS(dev, reg) (unsigned short)(0xC000 | (dev << 8) | reg)
+#define PCI_CONF3_ADDRESS(bus, dev, fn, reg) \
+ (0x80000000 | (((reg >> 8) & 0xF) << 24) | (bus << 16) | ((dev & 0x1F) << 11) | (fn << 8) | (reg & 0xFF))
+
int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value)
{
int result;
- if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1))
return -1;
result = -1;
switch(pci_conf_type) {
case PCI_CONF_TYPE_1:
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+ if(reg < 256){
+ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+ }else{
+ outl(PCI_CONF3_ADDRESS(bus, dev, fn, reg), 0xCF8);
+ }
switch(len) {
case 1: *value = inb(0xCFC + (reg & 3)); result = 0; break;
case 2: *value = inw(0xCFC + (reg & 2)); result = 0; break;
diff --git a/precomp.bin b/precomp.bin
index d7f7f2f..6603191 100644..100755
--- a/precomp.bin
+++ b/precomp.bin
Binary files differ
diff --git a/smp.c b/smp.c
new file mode 100644
index 0000000..e49f52c
--- /dev/null
+++ b/smp.c
@@ -0,0 +1,440 @@
+/*
+ * smp.c --
+ *
+ * Implements support for SMP machines. For reasons of
+ * simplicity, we do not handle all possible cases allowed by the
+ * MP spec. For example, we expect an explicit MP configuration
+ * table and do not handle default configurations. We also expect
+ * an on-chip local apic and do not support an external 82489DX
+ * apic controller.
+ *
+ */
+
+#include "stddef.h"
+#include "smp.h"
+#include "cpuid.h"
+#include "test.h"
+#define DELAY_FACTOR 1
+extern void memcpy(void *dst, void *src , int len);
+extern void test_start(void);
+
+typedef struct {
+ bool started;
+} ap_info_t;
+
+volatile apic_register_t *APIC = NULL;
+unsigned number_of_cpus = 1; // There is at least one cpu, the BSP
+/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */
+static unsigned cpu_num_to_apic_id[MAX_CPUS];
+volatile ap_info_t AP[MAX_CPUS];
+
+uint8_t
+checksum(uint8_t *data, unsigned len)
+{
+ uint32_t sum = 0;
+ uint8_t *end = data + len;
+ while (data < end) {
+ sum += *data;
+ data++;
+ }
+ return (uint8_t)(sum % 0x100);
+}
+
+
+bool
+read_mp_config_table(uintptr_t addr)
+{
+ mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
+ uint8_t *tab_entry_ptr;
+ uint8_t *mpc_table_end;
+ extern unsigned num_hyper_threads_per_core;
+
+ if (mpc->signature != MPCSignature) {
+ return FALSE;
+ }
+ if (checksum((uint8_t*)mpc, mpc->length) != 0) {
+ return FALSE;
+ }
+
+
+ /* FIXME: the uintptr_t cast here works around a compilation problem on
+ * AMD64, but it ignores the real problem, which is that lapic_addr
+ * is only 32 bits. Maybe that's OK, but it should be investigated.
+ */
+ APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
+
+ tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
+ mpc_table_end = ((uint8_t*)mpc) + mpc->length;
+ while (tab_entry_ptr < mpc_table_end) {
+ switch (*tab_entry_ptr) {
+ case MP_PROCESSOR: {
+ mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr;
+
+ if (pe->cpu_flag & CPU_BOOTPROCESSOR) {
+ // BSP is CPU 0
+ cpu_num_to_apic_id[0] = pe->apic_id;
+ } else if (number_of_cpus < MAX_CPUS) {
+ cpu_num_to_apic_id[number_of_cpus] = pe->apic_id;
+ number_of_cpus++;
+ }
+ if (num_hyper_threads_per_core > 1 ) {
+ cpu_num_to_apic_id[number_of_cpus] = pe->apic_id | 1;
+ number_of_cpus++;
+ }
+
+ // we cannot handle non-local 82489DX apics
+ if ((pe->apic_ver & 0xf0) != 0x10) {
+ return 0;
+ }
+
+ // we don't know what to do with disabled cpus
+
+ tab_entry_ptr += sizeof(mp_processor_entry_t);
+ break;
+ }
+ case MP_BUS: {
+ tab_entry_ptr += sizeof(mp_bus_entry_t);
+ break;
+ }
+ case MP_IOAPIC: {
+ tab_entry_ptr += sizeof(mp_io_apic_entry_t);
+ break;
+ }
+ case MP_INTSRC:
+ tab_entry_ptr += sizeof(mp_interrupt_entry_t);
+ case MP_LINTSRC:
+ tab_entry_ptr += sizeof(mp_local_interrupt_entry_t);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+floating_pointer_struct_t *
+scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length)
+{
+ floating_pointer_struct_t *fp;
+ uintptr_t end = addr + length;
+
+
+ fp = (floating_pointer_struct_t*)addr;
+ while ((uintptr_t)fp < end) {
+ if (fp->signature == FPSignature) {
+ if (fp->length == 1 && checksum((uint8_t*)fp, 16) == 0) {
+ return fp;
+ }
+ }
+ fp++;
+ }
+ return NULL;
+}
+
+void PUT_MEM16(uintptr_t addr, uint16_t val)
+{
+ *((volatile uint16_t *)addr) = val;
+}
+
+void PUT_MEM32(uintptr_t addr, uint32_t val)
+{
+ *((volatile uint32_t *)addr) = val;
+}
+
+static void inline
+APIC_WRITE(unsigned reg, uint32_t val)
+{
+ APIC[reg][0] = val;
+}
+
+static inline uint32_t
+APIC_READ(unsigned reg)
+{
+ return APIC[reg][0];
+}
+
+
+static void
+SEND_IPI(unsigned apic_id, unsigned trigger, unsigned level, unsigned mode,
+ uint8_t vector)
+{
+ uint32_t v;
+
+ v = APIC_READ(APICR_ICRHI) & 0x00ffffff;
+ APIC_WRITE(APICR_ICRHI, v | (apic_id << 24));
+
+ v = APIC_READ(APICR_ICRLO) & ~0xcdfff;
+ v |= (APIC_DEST_DEST << APIC_ICRLO_DEST_OFFSET)
+ | (trigger << APIC_ICRLO_TRIGGER_OFFSET)
+ | (level << APIC_ICRLO_LEVEL_OFFSET)
+ | (mode << APIC_ICRLO_DELMODE_OFFSET)
+ | (vector);
+ APIC_WRITE(APICR_ICRLO, v);
+}
+
+
+// Silly way of busywaiting, but we don't have a timer
+void delay(unsigned us)
+{
+ unsigned freq = 1000; // in MHz, assume 1GHz CPU speed
+ uint64_t cycles = us * freq;
+ uint64_t t0 = RDTSC();
+ uint64_t t1;
+ volatile unsigned k;
+
+ do {
+ for (k = 0; k < 1000; k++) continue;
+ t1 = RDTSC();
+ } while (t1 - t0 < cycles);
+}
+
+static inline void
+memset (void *dst,
+ char value,
+ int len)
+{
+ int i;
+ for (i = 0 ; i < len ; i++ ) {
+ *((char *) dst + i) = value;
+ }
+}
+
+void kick_cpu(unsigned cpu_num)
+{
+ unsigned num_sipi, apic_id;
+ apic_id = cpu_num_to_apic_id[cpu_num];
+
+ // clear the APIC ESR register
+ APIC_WRITE(APICR_ESR, 0);
+ APIC_READ(APICR_ESR);
+
+ // asserting the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0);
+ delay(100000 / DELAY_FACTOR);
+
+ // de-assert the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0);
+
+ for (num_sipi = 0; num_sipi < 2; num_sipi++) {
+ unsigned timeout;
+ bool send_pending;
+ unsigned err;
+
+ APIC_WRITE(APICR_ESR, 0);
+
+ SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (uint32_t)startup_32 >> 12);
+
+ timeout = 0;
+ do {
+ delay(10);
+ timeout++;
+ send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0;
+ } while (send_pending && timeout < 1000);
+
+ if (send_pending) {
+ //cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ }
+
+ delay(100000 / DELAY_FACTOR);
+
+ err = APIC_READ(APICR_ESR) & 0xef;
+ if (err) {
+ //cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
+ //hprint(LINE_STATUS+1, COL_MID, err);
+ }
+ }
+}
+
+// These memory locations are used for the trampoline code and data.
+
+#define BOOTCODESTART 0x9000
+#define GDTPOINTERADDR 0x9100
+#define GDTADDR 0x9110
+
+void boot_ap(unsigned cpu_num)
+{
+ unsigned num_sipi, apic_id;
+ extern uint8_t gdt;
+ extern uint8_t _ap_trampoline_start;
+ extern uint8_t _ap_trampoline_protmode;
+ unsigned len = &_ap_trampoline_protmode - &_ap_trampoline_start;
+ apic_id = cpu_num_to_apic_id[cpu_num];
+
+
+ memcpy((uint8_t*)BOOTCODESTART, &_ap_trampoline_start, len);
+
+ // Fixup the LGDT instruction to point to GDT pointer.
+ PUT_MEM16(BOOTCODESTART + 3, GDTPOINTERADDR);
+
+ // Copy a pointer to the temporary GDT to addr GDTPOINTERADDR.
+ // The temporary gdt is at addr GDTADDR
+ PUT_MEM16(GDTPOINTERADDR, 4 * 8);
+ PUT_MEM32(GDTPOINTERADDR + 2, GDTADDR);
+
+ // Copy the first 4 gdt entries from the currently used GDT to the
+ // temporary GDT.
+ memcpy((uint8_t *)GDTADDR, &gdt, 32);
+
+ // clear the APIC ESR register
+ APIC_WRITE(APICR_ESR, 0);
+ APIC_READ(APICR_ESR);
+
+ // asserting the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0);
+ delay(100000 / DELAY_FACTOR);
+
+ // de-assert the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0);
+
+ for (num_sipi = 0; num_sipi < 2; num_sipi++) {
+ unsigned timeout;
+ bool send_pending;
+ unsigned err;
+
+ APIC_WRITE(APICR_ESR, 0);
+
+ SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, BOOTCODESTART >> 12);
+
+ timeout = 0;
+ do {
+ delay(10);
+ timeout++;
+ send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0;
+ } while (send_pending && timeout < 1000);
+
+ if (send_pending) {
+ //cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ }
+
+ delay(100000 / DELAY_FACTOR);
+
+ err = APIC_READ(APICR_ESR) & 0xef;
+ if (err) {
+ //cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
+ // hprint(LINE_STATUS+1, COL_MID, err);
+ }
+ }
+}
+
+void
+smp_init_bsp()
+{
+ floating_pointer_struct_t *fp;
+ /* gets the details about the cpu, the type, the brand
+ * whether it is a multi-core package etc.
+ */
+ cpuid_init();
+
+ memset(&AP, 0, sizeof AP);
+
+ fp = scan_for_floating_ptr_struct(0x0, 0x400);
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(639*0x400, 0x400);
+ }
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
+ }
+ if (fp == NULL) {
+ /*
+ * If it is an SMP machine we should know now, unless the
+ * configuration is in an EISA/MCA bus machine with an
+ * extended bios data area.
+ *
+ * there is a real-mode segmented pointer pointing to the
+ * 4K EBDA area at 0x40E, calculate and scan it here.
+ */
+ unsigned int address = *(unsigned short *)0x40E;
+ address <<= 4;
+ if (address) {
+ fp = scan_for_floating_ptr_struct(address, 0x400);
+ }
+ }
+
+ if (fp != NULL && fp->phys_addr != 0) {
+ if (!read_mp_config_table(fp->phys_addr)) {
+ //cprint(LINE_STATUS+1,0, "SMP: Error while parsing MP config table");
+ }
+ }
+/*
+ if (fp == NULL) {
+ cprint(LINE_STATUS+1,0,"SMP: No floating pointer structure found");
+ }
+*/
+}
+
+void
+smp_init_aps()
+{
+ int cpuNum;
+ for(cpuNum = 0 ; cpuNum < MAX_CPUS ; cpuNum++) {
+ AP[cpuNum].started = FALSE;
+ }
+}
+
+unsigned
+my_apic_id()
+{
+ return (APIC[APICR_ID][0]) >> 24;
+}
+
+void
+smp_ap_booted(unsigned cpu_num)
+{
+ AP[cpu_num].started = TRUE;
+}
+
+void
+smp_boot_ap(unsigned cpu_num)
+{
+ unsigned timeout;
+ extern bool smp_mode;
+ boot_ap(cpu_num);
+ timeout = 0;
+ do {
+ delay(1000 / DELAY_FACTOR);
+ timeout++;
+ } while (!AP[cpu_num].started && timeout < 100000 / DELAY_FACTOR);
+
+ if (!AP[cpu_num].started) {
+ //cprint(LINE_STATUS+1, 0, "SMP: Boot timeout for");
+ //dprint(LINE_STATUS+1, COL_MID, cpu_num,2,1);
+ //cprint(LINE_STATUS+1, 26, "Turning off SMP");
+ smp_mode = FALSE;
+ }
+}
+
+unsigned
+smp_num_cpus()
+{
+ return number_of_cpus;
+}
+
+unsigned
+smp_my_cpu_num()
+{
+ unsigned apicid = my_apic_id();
+ unsigned i;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ if (apicid == cpu_num_to_apic_id[i]) {
+ break;
+ }
+ }
+ if (i == MAX_CPUS) {
+ i = 0;
+ }
+ return i;
+}
+
+volatile spinlock_t barr_lk={1};
+void barrier(volatile int *barr, int n)
+{
+ spin_lock(&barr_lk);
+ barr++;
+ spin_unlock(&barr_lk);
+ while((uint32_t)barr<n);
+ barr = 0;
+ return;
+}
+
diff --git a/smp.h b/smp.h
new file mode 100644
index 0000000..152068c
--- /dev/null
+++ b/smp.h
@@ -0,0 +1,265 @@
+/* **********************************************************
+ * Copyright 2002 VMware, Inc. All rights reserved. -- VMware Confidential
+ * **********************************************************/
+
+
+#ifndef _SMP_H_
+#define _SMP_H_
+#include "stdint.h"
+#include "defs.h"
+#define MAX_CPUS 16 // "16 CPUs ought to be enough for everybody."
+
+
+#define FPSignature ('_' | 'M' << 8 | 'P' << 16 | '_' << 24)
+
+typedef struct {
+ uint32_t signature; // "_MP_"
+ uint32_t phys_addr;
+ uint8_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t feature[5];
+} floating_pointer_struct_t;
+
+#define MPCSignature ('P' | 'C' << 8 | 'M' << 16 | 'P' << 24)
+typedef struct {
+ uint32_t signature; // "PCMP"
+ uint16_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ char oem[8];
+ char productid[12];
+ uint32_t oem_ptr;
+ uint16_t oem_size;
+ uint16_t oem_count;
+ uint32_t lapic_addr;
+ uint32_t reserved;
+} mp_config_table_header_t;
+
+/* Followed by entries */
+
+#define MP_PROCESSOR 0
+#define MP_BUS 1
+#define MP_IOAPIC 2
+#define MP_INTSRC 3
+#define MP_LINTSRC 4
+
+typedef struct {
+ uint8_t type; /* MP_PROCESSOR */
+ uint8_t apic_id; /* Local APIC number */
+ uint8_t apic_ver; /* Its versions */
+ uint8_t cpu_flag;
+#define CPU_ENABLED 1 /* Processor is available */
+#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
+ uint32_t cpu_signature;
+#define CPU_STEPPING_MASK 0x0F
+#define CPU_MODEL_MASK 0xF0
+#define CPU_FAMILY_MASK 0xF00
+ uint32_t featureflag; /* CPUID feature value */
+ uint32_t reserved[2];
+} mp_processor_entry_t;
+
+
+typedef struct {
+ uint8_t type; // has value MP_BUS
+ uint8_t busid;
+ char bustype[6];
+} mp_bus_entry_t;
+
+#define BUSTYPE_EISA "EISA"
+#define BUSTYPE_ISA "ISA"
+#define BUSTYPE_INTERN "INTERN"
+#define BUSTYPE_MCA "MCA"
+#define BUSTYPE_VL "VL"
+#define BUSTYPE_PCI "PCI"
+#define BUSTYPE_PCMCIA "PCMCIA"
+
+/* We don't understand the others */
+
+typedef struct {
+ uint8_t type; // set to MP_IOAPIC
+ uint8_t apicid;
+ uint8_t apicver;
+ uint8_t flags;
+#define MPC_APIC_USABLE 0x01
+ uint32_t apicaddr;
+} mp_io_apic_entry_t;
+
+
+typedef struct {
+ uint8_t type;
+ uint8_t irqtype;
+ uint16_t irqflag;
+ uint8_t srcbus;
+ uint8_t srcbusirq;
+ uint8_t dstapic;
+ uint8_t dstirq;
+} mp_interrupt_entry_t;
+
+#define MP_INT_VECTORED 0
+#define MP_INT_NMI 1
+#define MP_INT_SMI 2
+#define MP_INT_EXTINT 3
+
+#define MP_IRQDIR_DEFAULT 0
+#define MP_IRQDIR_HIGH 1
+#define MP_IRQDIR_LOW 3
+
+
+typedef struct {
+ uint8_t type;
+ uint8_t irqtype;
+ uint16_t irqflag;
+ uint8_t srcbusid;
+ uint8_t srcbusirq;
+ uint8_t destapic;
+#define MP_APIC_ALL 0xFF
+ uint8_t destapiclint;
+} mp_local_interrupt_entry_t;
+
+/* APIC definitions */
+/*
+ * APIC registers
+ */
+#define APICR_ID 0x02
+#define APICR_ESR 0x28
+#define APICR_ICRLO 0x30
+#define APICR_ICRHI 0x31
+
+/* APIC destination shorthands */
+#define APIC_DEST_DEST 0
+#define APIC_DEST_LOCAL 1
+#define APIC_DEST_ALL_INC 2
+#define APIC_DEST_ALL_EXC 3
+
+/* APIC IPI Command Register format */
+#define APIC_ICRHI_RESERVED 0x00ffffff
+#define APIC_ICRHI_DEST_MASK 0xff000000
+#define APIC_ICRHI_DEST_OFFSET 24
+
+#define APIC_ICRLO_RESERVED 0xfff32000
+#define APIC_ICRLO_DEST_MASK 0x000c0000
+#define APIC_ICRLO_DEST_OFFSET 18
+#define APIC_ICRLO_TRIGGER_MASK 0x00008000
+#define APIC_ICRLO_TRIGGER_OFFSET 15
+#define APIC_ICRLO_LEVEL_MASK 0x00004000
+#define APIC_ICRLO_LEVEL_OFFSET 14
+#define APIC_ICRLO_STATUS_MASK 0x00001000
+#define APIC_ICRLO_STATUS_OFFSET 12
+#define APIC_ICRLO_DESTMODE_MASK 0x00000800
+#define APIC_ICRLO_DESTMODE_OFFSET 11
+#define APIC_ICRLO_DELMODE_MASK 0x00000700
+#define APIC_ICRLO_DELMODE_OFFSET 8
+#define APIC_ICRLO_VECTOR_MASK 0x000000ff
+#define APIC_ICRLO_VECTOR_OFFSET 0
+
+/* APIC trigger types (edge/level) */
+#define APIC_TRIGGER_EDGE 0
+#define APIC_TRIGGER_LEVEL 1
+
+/* APIC delivery modes */
+#define APIC_DELMODE_FIXED 0
+#define APIC_DELMODE_LOWEST 1
+#define APIC_DELMODE_SMI 2
+#define APIC_DELMODE_NMI 4
+#define APIC_DELMODE_INIT 5
+#define APIC_DELMODE_STARTUP 6
+#define APIC_DELMODE_EXTINT 7
+typedef uint32_t apic_register_t[4];
+
+extern volatile apic_register_t *APIC;
+
+unsigned smp_num_cpus();
+unsigned smp_my_cpu_num();
+
+void smp_init_bsp(void);
+void smp_init_aps(void);
+
+void smp_boot_ap(unsigned cpu_num);
+void smp_ap_booted(unsigned cpu_num);
+
+static inline void
+__GET_CPUID(int ax, uint32_t *regs)
+{
+ __asm__ __volatile__("\t"
+ /* save ebx in case -fPIC is being used */
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+ : "a" (ax)
+ : "memory"
+ );
+}
+
+#define GET_CPUID(_ax,_bx,_cx,_dx) { \
+ uint32_t regs[4]; \
+ __GET_CPUID(_ax,regs); \
+ _ax = regs[0]; \
+ _bx = regs[1]; \
+ _cx = regs[2]; \
+ _dx = regs[3]; \
+}
+
+/*
+ * Checked against the Intel manual and GCC --hpreg
+ *
+ * volatile because the tsc always changes without the compiler knowing it.
+ */
+static inline uint64_t
+RDTSC(void)
+{
+ uint64_t tim;
+
+ __asm__ __volatile__(
+ "rdtsc"
+ : "=A" (tim)
+ );
+
+ return tim;
+}
+
+static inline uint64_t __GET_MSR(int cx)
+{
+ uint64_t msr;
+
+ __asm__ __volatile__(
+ "rdmsr"
+ : "=A" (msr)
+ : "c" (cx)
+ );
+
+ return msr;
+}
+
+#define __GCC_OUT(s, s2, port, val) do { \
+ __asm__( \
+ "out" #s " %" #s2 "1, %w0" \
+ : \
+ : "Nd" (port), "a" (val) \
+ ); \
+} while (0)
+#define OUTB(port, val) __GCC_OUT(b, b, port, val)
+
+typedef struct {
+ unsigned int slock;
+} spinlock_t;
+
+static inline void spin_lock(volatile spinlock_t *lock)
+{
+ asm volatile("\n1:\t"
+ " ; lock;decb %0\n\t"
+ "jns 3f\n"
+ "2:\t"
+ "rep;nop\n\t"
+ "cmpb $0,%0\n\t"
+ "jle 2b\n\t"
+ "jmp 1b\n"
+ "3:\n\t"
+ : "+m" (lock->slock) : : "memory");
+}
+static inline void spin_unlock(volatile spinlock_t *lock)
+{
+ asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory");
+}
+
+
+#endif /* _SMP_H_ */
diff --git a/spd.c b/spd.c
index 484bc26..0cdfe1e 100644
--- a/spd.c
+++ b/spd.c
@@ -2,13 +2,22 @@
* added by Reto Sonderegger, 2004, reto@swissbit.com
*
* Released under version 2 of the Gnu Puclic License
+ * ----------------------------------------------------
+ * MemTest86+ V4.00 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
*/
+
#include "test.h"
#include "io.h"
#include "pci.h"
#include "msr.h"
+#include "spd.h"
#include "screen_buffer.h"
+#include "jedec_id.h"
+
+#define NULL 0
#define SMBHSTSTS smbusbase
#define SMBHSTCNT smbusbase + 2
@@ -42,7 +51,7 @@ unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
__outb((adr << 1) | 0x01, SMBHSTADD);
__outb(0x48, SMBHSTCNT);
rdtsc(l1, h1);
- cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
+ //cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished
rdtsc(l2, h2);
t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
@@ -57,7 +66,7 @@ static int ich5_read_spd(int dimmadr)
spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
if (spd[0] == 0xff) return -1; // no spd here
for (x = 1; x < 256; x++) {
- spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
}
return 0;
}
@@ -136,24 +145,171 @@ int find_smb_controller(void)
int i = 0;
unsigned long valuev, valued;
for (smbdev = 0; smbdev < 32; smbdev++) {
- for (smbfun = 0; smbfun < 8; smbfun++) {
- pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev);
- if (valuev != 0xFFFF) { // if there is something look what's it..
- for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller
- if (valuev == smbcontrollers[i].vendor) {
- pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id
- if (valued == smbcontrollers[i].device) {
- return i;
+ for (smbfun = 0; smbfun < 8; smbfun++) {
+ pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev);
+ if (valuev != 0xFFFF) { // if there is something look what's it..
+ for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller
+ if (valuev == smbcontrollers[i].vendor) {
+ pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id
+ if (valued == smbcontrollers[i].device) {
+ return i;
+ }
+ }
+ }
+ }
}
- }
- }
- }
- }
}
return -1;
}
-
-
+
+
+
+void get_spd_spec(void)
+{
+ int index;
+ int h, i, j, z;
+ int k = 0;
+ int module_size;
+ int curcol;
+ int temp_nbd;
+
+ index = find_smb_controller();
+
+ if (index == -1)
+ {
+ // Unknown SMBUS Controller, exit
+ return;
+ }
+
+ smbcontrollers[index].get_adr();
+ cprint(LINE_SPD-2, 0, "Memory SPD Informations");
+ cprint(LINE_SPD-1, 0, "-----------------------------------");
+
+ for (j = 0; j < 8; j++) {
+ if (smbcontrollers[index].read_spd(j) == 0) {
+ curcol = 1;
+ if(spd[2] == 0x0b){
+ // We are here if DDR3 present
+
+ // First print slot#, module capacity
+ cprint(LINE_SPD+k, curcol, " - Slot :");
+ dprint(LINE_SPD+k, curcol+8, k, 1, 0);
+
+ module_size = get_ddr3_module_size(spd[4] & 0xF, spd[8] & 0x7, spd[7] & 0x7, spd[7] >> 3);
+ temp_nbd = getnum(module_size); curcol += 12;
+ dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd;
+ cprint(LINE_SPD+k, curcol, " MB"); curcol += 4;
+
+ // Then module jedec speed
+ switch(spd[12])
+ {
+ default:
+ case 20:
+ cprint(LINE_SPD+k, curcol, "PC3-6400");
+ curcol += 8;
+ break;
+ case 15:
+ cprint(LINE_SPD+k, curcol, "PC3-8500");
+ curcol += 8;
+ break;
+ case 12:
+ cprint(LINE_SPD+k, curcol, "PC3-10600");
+ curcol += 9;
+ break;
+ case 10:
+ cprint(LINE_SPD+k, curcol, "PC3-12800");
+ curcol += 9;
+ break;
+ case 8:
+ cprint(LINE_SPD+k, curcol, "PC3-15000");
+ curcol += 9;
+ break;
+ case 6:
+ cprint(LINE_SPD+k, curcol, "PC3-16000");
+ curcol += 9;
+ break;
+ }
+
+ curcol++;
+
+ // Then print module infos (manufacturer & part number)
+ for (i = 0; jep106[i].cont_code < 9; i++) {
+ if (spd[117] == jep106[i].cont_code && spd[118] == jep106[i].hex_byte) {
+ // We are here if a Jedec manufacturer is detected
+ cprint(LINE_SPD+k, curcol, "-"); curcol += 2;
+ cprint(LINE_SPD+k, curcol, jep106[i].name);
+ for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; }
+ curcol++;
+ // Display module serial number
+ for (h = 128; h < 146; h++) {
+ cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ curcol++;
+ }
+
+ // Detect XMP Memory
+ if(spd[176] == 0x0C && spd[177] == 0x4A)
+ {
+ cprint(LINE_SPD+k, curcol, "*XMP*");
+ }
+ }
+ }
+ }
+ // We enter this function if DDR2 is detected
+ if(spd[2] == 0x08){
+ // First print slot#, module capacity
+ cprint(LINE_SPD+k, curcol, " - Slot :");
+ dprint(LINE_SPD+k, curcol+8, k, 1, 0);
+
+ module_size = get_ddr2_module_size(spd[31], spd[5]);
+ temp_nbd = getnum(module_size); curcol += 12;
+ dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd;
+ cprint(LINE_SPD+k, curcol, " MB"); curcol += 4;
+
+ // Then module jedec speed
+ float ddr2_speed, byte1, byte2;
+
+ byte1 = (spd[9] >> 4) * 10;
+ byte2 = spd[9] & 0xF;
+
+ ddr2_speed = 1 / (byte1 + byte2) * 10000;
+
+ temp_nbd = getnum(ddr2_speed);
+ cprint(LINE_SPD+k, curcol, "DDR2-"); curcol += 5;
+ dprint(LINE_SPD+k, curcol, ddr2_speed, temp_nbd, 0); curcol += temp_nbd;
+
+ // Then print module infos (manufacturer & part number)
+ int ccode = 0;
+
+ for(i = 64; i < 72; i++)
+ {
+ if(spd[i] == 0x7F) { ccode++; }
+ }
+
+ curcol++;
+
+ for (i = 0; jep106[i].cont_code < 9; i++) {
+ if (ccode == jep106[i].cont_code && spd[64+ccode] == jep106[i].hex_byte) {
+ // We are here if a Jedec manufacturer is detected
+ cprint(LINE_SPD+k, curcol, "-"); curcol += 2;
+ cprint(LINE_SPD+k, curcol, jep106[i].name);
+ for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; }
+ curcol++;
+ // Display module serial number
+ for (h = 73; h < 91; h++) {
+ cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ curcol++;
+ }
+
+ }
+ }
+
+ }
+ k++;
+ }
+ }
+}
+
+
void show_spd(void)
{
int index;
@@ -187,3 +343,222 @@ void show_spd(void)
pop2down();
}
+int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks)
+{
+ int module_size;
+
+ switch(sdram_capacity)
+ {
+ case 0:
+ module_size = 256;
+ break;
+ case 1:
+ module_size = 512;
+ break;
+ default:
+ case 2:
+ module_size = 1024;
+ break;
+ case 3:
+ module_size = 2048;
+ break;
+ case 4:
+ module_size = 4096;
+ break;
+ case 5:
+ module_size = 8192;
+ break;
+ case 6:
+ module_size = 16384;
+ break;
+ }
+
+ module_size /= 8;
+
+ switch(prim_bus_width)
+ {
+ case 0:
+ module_size *= 8;
+ break;
+ case 1:
+ module_size *= 16;
+ break;
+ case 2:
+ module_size *= 32;
+ break;
+ case 3:
+ module_size *= 64;
+ break;
+ }
+
+ switch(sdram_width)
+ {
+ case 0:
+ module_size /= 4;
+ break;
+ case 1:
+ module_size /= 8;
+ break;
+ case 2:
+ module_size /= 16;
+ break;
+ case 3:
+ module_size /= 32;
+ break;
+
+ }
+
+ module_size *= (ranks + 1);
+
+ return module_size;
+}
+
+
+int get_ddr2_module_size(int rank_density_byte, int rank_num_byte)
+{
+ int module_size;
+
+ switch(rank_density_byte)
+ {
+ case 1:
+ module_size = 1024;
+ break;
+ case 2:
+ module_size = 2048;
+ break;
+ case 4:
+ module_size = 4096;
+ break;
+ case 8:
+ module_size = 8192;
+ break;
+ case 16:
+ module_size = 16384;
+ break;
+ case 32:
+ module_size = 128;
+ break;
+ case 64:
+ module_size = 256;
+ break;
+ default:
+ case 128:
+ module_size = 512;
+ break;
+ }
+
+ module_size *= (rank_num_byte & 7) + 1;
+
+ return module_size;
+
+}
+
+
+struct ascii_map {
+ unsigned hex_code;
+ char *name;
+};
+
+struct ascii_map amap[] = {
+{ 0x20, " "},
+{ 0x21, "!"},
+{ 0x22, "'"},
+{ 0x23, "#"},
+{ 0x24, "$"},
+{ 0x25, "%"},
+{ 0x26, "&"},
+{ 0x28, "("},
+{ 0x29, ")"},
+{ 0x2A, "*"},
+{ 0x2B, "+"},
+{ 0x2C, ","},
+{ 0x2D, "-"},
+{ 0x2E, "."},
+{ 0x30, "0"},
+{ 0x31, "1"},
+{ 0x32, "2"},
+{ 0x33, "3"},
+{ 0x34, "4"},
+{ 0x35, "5"},
+{ 0x36, "6"},
+{ 0x38, "8"},
+{ 0x39, "9"},
+{ 0x3A, ":"},
+{ 0x3B, ";"},
+{ 0x3C, "<"},
+{ 0x3D, "="},
+{ 0x3E, ">"},
+{ 0x40, "@"},
+{ 0x41, "A"},
+{ 0x42, "B"},
+{ 0x43, "C"},
+{ 0x44, "D"},
+{ 0x45, "E"},
+{ 0x46, "F"},
+{ 0x47, "G"},
+{ 0x48, "H"},
+{ 0x49, "I"},
+{ 0x4A, "J"},
+{ 0x4B, "K"},
+{ 0x4C, "L"},
+{ 0x4D, "M"},
+{ 0x4E, "N"},
+{ 0x4F, "O"},
+{ 0x50, "P"},
+{ 0x51, "Q"},
+{ 0x52, "R"},
+{ 0x53, "S"},
+{ 0x54, "T"},
+{ 0x55, "U"},
+{ 0x56, "V"},
+{ 0x57, "W"},
+{ 0x58, "X"},
+{ 0x59, "Y"},
+{ 0x5A, "Z"},
+{ 0x5B, "["},
+{ 0x5C, "-"},
+{ 0x5D, "]"},
+{ 0x5E, "^"},
+{ 0x60, "`"},
+{ 0x61, "a"},
+{ 0x62, "b"},
+{ 0x63, "c"},
+{ 0x64, "d"},
+{ 0x65, "e"},
+{ 0x66, "f"},
+{ 0x68, "h"},
+{ 0x69, "i"},
+{ 0x6A, "j"},
+{ 0x6B, "k"},
+{ 0x6C, "l"},
+{ 0x6D, "m"},
+{ 0x6E, "n"},
+{ 0x6F, "o"},
+{ 0x70, "p"},
+{ 0x71, "q"},
+{ 0x72, "r"},
+{ 0x73, "s"},
+{ 0x74, "t"},
+{ 0x75, "u"},
+{ 0x76, "v"},
+{ 0x78, "x"},
+{ 0x79, "y"},
+{ 0x7A, "z"},
+{ 0x7B, "{"},
+{ 0x7C, "|"},
+{ 0x7D, "}"},
+{ 0x7E, "~"},
+{ 0, ""}
+};
+
+char* convert_hex_to_char(unsigned hex_org){
+ int i;
+
+ for (i = 0; amap[i].hex_code > 0; i++) {
+ if (hex_org == amap[i].hex_code) {
+ return amap[i].name;
+ }
+ }
+ return "";
+}
+
diff --git a/spd.h b/spd.h
new file mode 100644
index 0000000..7150381
--- /dev/null
+++ b/spd.h
@@ -0,0 +1,13 @@
+/*
+ * MemTest86+ V3.00 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
+ */
+
+void get_spd_spec(void);
+int get_ddr2_module_size(int rank_density_byte, int rank_num_byte);
+int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks);
+char* convert_hex_to_char(unsigned hex_org);
+#define LINE_SPD 16
+
+
diff --git a/stdint.h b/stdint.h
index 58d7519..1c136e0 100644
--- a/stdint.h
+++ b/stdint.h
@@ -48,5 +48,13 @@ typedef unsigned int uintptr_t;
typedef long long int intmax_t;
typedef unsigned long long uintmax_t;
+typedef char bool;
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
#endif /* I386_STDINT_H */
diff --git a/test.c b/test.c
index c73d9dc..f30f3c4 100644
--- a/test.c
+++ b/test.c
@@ -4,7 +4,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V2.01 Specific code (GPL V2.0)
+ * MemTest86+ V3.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -13,6 +13,7 @@
#include "config.h"
#include <sys/io.h>
#include "dmi.h"
+#include <inttypes.h>
extern int segs, bail;
extern volatile ulong *p;
@@ -50,19 +51,19 @@ void addr_tst1()
/* Now write pattern compliment */
p1 = ~p1;
end = v->map[segs-1].end;
- for (i=0; i<1000; i++) {
+ for (i=0; i<100; i++) {
mask = 4;
do {
pt = (ulong *)((ulong)p | mask);
- if (pt == p) {
+ if ((uintptr_t)pt == (uintptr_t)p) {
mask = mask << 1;
continue;
}
- if (pt >= end) {
+ if ((uintptr_t)pt >= (uintptr_t)end) {
break;
}
*pt = p1;
- if ((bad = *p) != ~p1) {
+ if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) {
ad_err1((ulong *)p, (ulong *)mask,
bad, ~p1);
i = 1000;
@@ -90,7 +91,7 @@ void addr_tst1()
/* Force start address to be a multiple of 256k */
p = (ulong *)roundup((ulong)p, bank - 1);
end = v->map[j].end;
- while (p < end) {
+ while ((uintptr_t)p < (uintptr_t)end) {
*p = p1;
p1 = ~p1;
@@ -99,15 +100,15 @@ void addr_tst1()
do {
pt = (ulong *)
((ulong)p | mask);
- if (pt == p) {
+ if ((uintptr_t)pt == (uintptr_t)p) {
mask = mask << 1;
continue;
}
- if (pt >= end) {
+ if ((uintptr_t)pt >= (uintptr_t)end) {
break;
}
*pt = p1;
- if ((bad = *p) != ~p1) {
+ if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) {
ad_err1((ulong *)p,
(ulong *)mask,
bad,~p1);
@@ -116,7 +117,7 @@ void addr_tst1()
mask = mask << 1;
} while(mask);
}
- if (p + bank/4 > p) {
+ if ((uintptr_t)(p + bank/4) > (uintptr_t)p) {
p += bank/4;
} else {
p = end;
@@ -150,16 +151,16 @@ void addr_tst2()
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
@@ -194,16 +195,16 @@ void addr_tst2()
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -260,6 +261,7 @@ void movinvr()
volatile ulong *pe;
volatile ulong *start,*end;
ulong num;
+ uintptr_t seg_start;
/* Initialize memory with initial sequence of random numbers. */
if (v->rdtsc) {
@@ -277,19 +279,20 @@ void movinvr()
end = v->map[j].end;
pe = start;
p = start;
+ seg_start = (uintptr_t)p;
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if (seg_start == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code */
@@ -310,7 +313,7 @@ void movinvr()
"jb L200\n\t"
: "=D" (p)
: "D" (p), "b" (pe)
- : "eax"
+ : "eax", "edx"
);
do_tick();
@@ -328,19 +331,20 @@ void movinvr()
end = v->map[j].end;
pe = start;
p = start;
+ seg_start = (uintptr_t)p;
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if (seg_start == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code */
@@ -427,17 +431,17 @@ void movinv1(int iter, ulong p1, ulong p2)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
len = pe - p;
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -468,16 +472,16 @@ void movinv1(int iter, ulong p1, ulong p2)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -534,16 +538,16 @@ void movinv1(int iter, ulong p1, ulong p2)
done = 0;
do {
/* Check for underflow */
- if (pe - SPINSZ < pe) {
+ if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) {
pe -= SPINSZ;
} else {
pe = start;
}
- if (pe <= start) {
+ if ((uintptr_t)pe <= (uintptr_t)start) {
pe = start;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -623,16 +627,16 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
pat = p1;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Do a SPINSZ section of memory */
@@ -685,16 +689,16 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
pat = p1;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -798,16 +802,16 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
done = 0;
do {
/* Check for underflow */
- if (pe - SPINSZ < pe) {
+ if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) {
pe -= SPINSZ;
} else {
pe = start;
}
- if (pe <= start) {
+ if ((uintptr_t)pe <= (uintptr_t)start) {
pe = start;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -906,16 +910,16 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -951,16 +955,16 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
k = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -1009,16 +1013,17 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
pe += SPINSZ;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
+
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
/* Original C code replaced with hand tuned assembly code
@@ -1098,16 +1103,18 @@ void block_move(int iter)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
+ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
pe += SPINSZ*4;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
+
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
+
break;
}
len = ((ulong)pe - (ulong)p) / 64;
@@ -1167,16 +1174,16 @@ void block_move(int iter)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
+ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
pe += SPINSZ*4;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
pp = p + ((pe - p) / 2);
@@ -1234,16 +1241,16 @@ void block_move(int iter)
done = 0;
do {
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
+ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
pe += SPINSZ*4;
} else {
pe = end;
}
- if (pe >= end) {
+ if ((uintptr_t)pe >= (uintptr_t)end) {
pe = end;
done++;
}
- if (p == pe ) {
+ if ((uintptr_t)p == (uintptr_t)pe) {
break;
}
asm __volatile__ (
diff --git a/test.h b/test.h
index 1bb6902..cfc6fa0 100644
--- a/test.h
+++ b/test.h
@@ -8,7 +8,8 @@
* http://www.canardpc.com - http://www.memtest.org
*/
-
+#ifndef _TEST_H_
+#define _TEST_H_
#define E88 0x00
#define E801 0x04
#define E820NR 0x08 /* # entries in E820MAP */
@@ -16,6 +17,7 @@
#define E820MAX 32 /* number of entries in E820MAP */
#define E820ENTRY_SIZE 20
#define MEMINFO_SIZE 0x28c
+#define MAX_DMI_MEMDEVS 16
#ifndef __ASSEMBLY__
@@ -39,10 +41,11 @@ struct mem_info_t {
};
typedef unsigned long ulong;
-#define SPINSZ 0x800000
+#define SPINSZ 0x2000000
#define MOD_SZ 20
#define BAILOUT if (bail) goto skip_test;
#define BAILR if (bail) return;
+#define NULL 0
#define DMI_SEARCH_START 0x0000F000
#define DMI_SEARCH_LENGTH 0x000F0FFF
@@ -86,7 +89,7 @@ typedef unsigned long ulong;
#define POP2_H 21
#define POP2_X 3
#define POP2_Y 2
-#define NULL 0
+//#define NULL 0
/* memspeed operations */
#define MS_COPY 1
@@ -152,6 +155,7 @@ void addr_tst2(void);
void bit_fade(void);
void sleep(int sec, int sms);
void beep(unsigned int frequency);
+int getnum(ulong val);
void block_move(int iter);
void find_ticks(void);
void print_err(ulong *adr, ulong good, ulong bad, ulong xor);
@@ -249,7 +253,6 @@ struct tseq {
short cache;
short pat;
short iter;
- short ticks;
short errors;
char *msg;
};
@@ -292,7 +295,7 @@ struct err_info {
/* Define common variables accross relocations of memtest86+ */
struct vars {
- int test;
+ volatile int test;
int pass;
unsigned long *eadr;
unsigned long exor;
@@ -320,6 +323,7 @@ struct vars {
ulong snaph;
ulong snapl;
ulong extclock;
+ unsigned long imc_type;
int printmode;
int numpatn;
struct pair patn [BADRAM_MAXPATNS];
@@ -338,4 +342,10 @@ extern unsigned char _size, _pages;
extern struct mem_info_t mem_info;
+/* CPU mode types */
+#define CPM_SINGLE 1
+#define CPM_RROBIN 2
+#define CPM_SEQ 3
+
#endif /* __ASSEMBLY__ */
+#endif /* _TEST_H_ */ \ No newline at end of file