summaryrefslogtreecommitdiffstats
path: root/spd.c
diff options
context:
space:
mode:
Diffstat (limited to 'spd.c')
-rw-r--r--spd.c193
1 files changed, 132 insertions, 61 deletions
diff --git a/spd.c b/spd.c
index cef93f0..fd3db9f 100644
--- a/spd.c
+++ b/spd.c
@@ -1,9 +1,5 @@
-/* Memtest86 SPD extension
- * added by Reto Sonderegger, 2004, reto@swissbit.com
- *
- * Released under version 2 of the Gnu Puclic License
- * ----------------------------------------------------
- * MemTest86+ V4.20 Specific code (GPL V2.0)
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -29,7 +25,7 @@ extern void wait_keyup();
int smbdev, smbfun;
unsigned short smbusbase;
-unsigned char spd[256];
+unsigned char spd_raw[256];
char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0};
static void ich5_get_smb(void)
@@ -40,6 +36,40 @@ static void ich5_get_smb(void)
if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
}
+static void piix4_get_smb(void)
+{
+ unsigned long x;
+ int result;
+
+ result = pci_conf_read(0, smbdev, smbfun, 0x08, 1, &x);
+
+ if(x < 0x40){
+ // SB600/700
+ result = pci_conf_read(0, smbdev, smbfun, 0x90, 2, &x);
+ if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
+ } else {
+ // SB800
+ sb800_get_smb();
+ }
+}
+
+void sb800_get_smb(void)
+{
+ int lbyte, hbyte;
+
+ __outb(AMD_SMBUS_BASE_REG + 1, AMD_INDEX_IO_PORT);
+ lbyte = __inb(AMD_DATA_IO_PORT);
+ __outb(AMD_SMBUS_BASE_REG, AMD_INDEX_IO_PORT);
+ hbyte = __inb(AMD_DATA_IO_PORT);
+
+ smbusbase = lbyte;
+ smbusbase <<= 8;
+ smbusbase += hbyte;
+ smbusbase &= 0xFFE0;
+
+ if (smbusbase == 0xFFE0) { smbusbase = 0; }
+}
+
unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
{
int l1, h1, l2, h2;
@@ -53,9 +83,9 @@ unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
rdtsc(l1, h1);
//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;
- if (t > 10) break; // break after 10ms
+ rdtsc(l2, h2);
+ t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
+ if (t > 10) break; // break after 10ms
}
return __inb(SMBHSTDAT);
}
@@ -63,10 +93,10 @@ unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
static int ich5_read_spd(int dimmadr)
{
int x;
- spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
- if (spd[0] == 0xff) return -1; // no spd here
+ spd_raw[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd_raw[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_raw[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
}
return 0;
}
@@ -106,10 +136,10 @@ unsigned char us15w_smb_read_byte(unsigned char adr, unsigned char cmd)
static int us15w_read_spd(int dimmadr)
{
int x;
- spd[0] = us15w_smb_read_byte(0x50 + dimmadr, 0);
- if (spd[0] == 0xff) return -1; // no spd here
+ spd_raw[0] = us15w_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd_raw[0] == 0xff) return -1; // no spd here
for (x = 1; x < 256; x++) {
- spd[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ spd_raw[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
}
return 0;
}
@@ -123,21 +153,29 @@ struct pci_smbus_controller {
};
static struct pci_smbus_controller smbcontrollers[] = {
-{0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x2930, "Intel ICH9", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x283E, "Intel ICH8", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x27DA, "Intel ICH7", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd},
-{0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd},
-{0, 0, "", NULL, NULL}
+ // Intel SMBUS
+ {0x8086, 0x9C22, "Intel HSW-ULT", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x8C22, "Intel HSW", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x1E22, "Intel Z77", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x2930, "Intel ICH9", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x283E, "Intel ICH8", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x27DA, "Intel ICH7", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd},
+ {0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd},
+
+ // AMD SMBUS
+ {0x1002, 0x4385, "AMD SB600/700", piix4_get_smb, ich5_read_spd},
+ {0x1022, 0x780B, "AMD SB800/900", sb800_get_smb, ich5_read_spd},
+ {0, 0, "", NULL, NULL}
};
@@ -145,6 +183,7 @@ 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);
@@ -173,6 +212,7 @@ void get_spd_spec(void)
int module_size;
int curcol;
int temp_nbd;
+ int tck;
index = find_smb_controller();
@@ -184,59 +224,75 @@ void get_spd_spec(void)
smbcontrollers[index].get_adr();
cprint(LINE_SPD-2, 0, "Memory SPD Informations");
- cprint(LINE_SPD-1, 0, "-----------------------------------");
+ cprint(LINE_SPD-1, 0, "--------------------------");
for (j = 0; j < 8; j++) {
if (smbcontrollers[index].read_spd(j) == 0) {
curcol = 1;
- if(spd[2] == 0x0b){
+ if(spd_raw[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);
+ module_size = get_ddr3_module_size(spd_raw[4] & 0xF, spd_raw[8] & 0x7, spd_raw[7] & 0x7, spd_raw[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;
+ // If XMP is supported, check Tck in XMP reg
+ if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A && spd_raw[12])
+ {
+ tck = spd_raw[186];
+ } else {
+ tck = spd_raw[12];
+ }
+
// Then module jedec speed
- switch(spd[12])
+ switch(tck)
{
default:
+ cprint(LINE_SPD+k, curcol, "DDR3-????");
+ break;
case 20:
- cprint(LINE_SPD+k, curcol, "PC3-6400");
- curcol += 8;
+ cprint(LINE_SPD+k, curcol, "DDR3-800");
+ curcol--;
break;
case 15:
- cprint(LINE_SPD+k, curcol, "PC3-8500");
- curcol += 8;
+ cprint(LINE_SPD+k, curcol, "DDR3-1066");
break;
case 12:
- cprint(LINE_SPD+k, curcol, "PC3-10600");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-1333");
break;
case 10:
- cprint(LINE_SPD+k, curcol, "PC3-12800");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-1600");
+ break;
+ case 9:
+ cprint(LINE_SPD+k, curcol, "DDR3-1866");
break;
case 8:
- cprint(LINE_SPD+k, curcol, "PC3-15000");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-2133");
+ break;
+ case 7:
+ cprint(LINE_SPD+k, curcol, "DDR3-2400");
break;
case 6:
- cprint(LINE_SPD+k, curcol, "PC3-16000");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-2533");
+ break;
+ case 5:
+ cprint(LINE_SPD+k, curcol, "DDR3-2666");
break;
}
- curcol++;
+ curcol += 10;
+
+ if((spd_raw[8] >> 3) == 1) { cprint(LINE_SPD+k, curcol, "ECC"); curcol += 4; }
// Then print module infos (manufacturer & part number)
- spd[117] &= 0x0F; // Parity odd or even
+ spd_raw[117] &= 0x0F; // Parity odd or even
for (i = 0; jep106[i].cont_code < 9; i++) {
- if (spd[117] == jep106[i].cont_code && spd[118] == jep106[i].hex_byte) {
+ if (spd_raw[117] == jep106[i].cont_code && spd_raw[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);
@@ -244,12 +300,25 @@ void get_spd_spec(void)
curcol++;
// Display module serial number
for (h = 128; h < 146; h++) {
- cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h]));
curcol++;
}
+
+ // Detect Week and Year of Manufacturing (Think to upgrade after 2015 !!!)
+ if(curcol <= 72 && spd_raw[120] > 3 && spd_raw[120] < 16 && spd_raw[121] < 55)
+ {
+ cprint(LINE_SPD+k, curcol, "(W");
+ dprint(LINE_SPD+k, curcol+2, spd_raw[121], 2, 0);
+ if(spd_raw[121] < 10) { cprint(LINE_SPD+k, curcol+2, "0"); }
+ cprint(LINE_SPD+k, curcol+4, "'");
+ dprint(LINE_SPD+k, curcol+5, spd_raw[120], 2, 0);
+ if(spd_raw[120] < 10) { cprint(LINE_SPD+k, curcol+5, "0"); }
+ cprint(LINE_SPD+k, curcol+7, ")");
+ curcol += 9;
+ }
// Detect XMP Memory
- if(spd[176] == 0x0C && spd[177] == 0x4A)
+ if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A)
{
cprint(LINE_SPD+k, curcol, "*XMP*");
}
@@ -257,12 +326,12 @@ void get_spd_spec(void)
}
}
// We enter this function if DDR2 is detected
- if(spd[2] == 0x08){
+ if(spd_raw[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]);
+ module_size = get_ddr2_module_size(spd_raw[31], spd_raw[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;
@@ -270,27 +339,29 @@ void get_spd_spec(void)
// Then module jedec speed
float ddr2_speed, byte1, byte2;
- byte1 = (spd[9] >> 4) * 10;
- byte2 = spd[9] & 0xF;
+ byte1 = (spd_raw[9] >> 4) * 10;
+ byte2 = spd_raw[9] & 0xF;
- ddr2_speed = 1 / (byte1 + byte2) * 10000;
+ ddr2_speed = 1 / (byte1 + byte2) * 10000 * 2;
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;
+
+ if((spd_raw[11] >> 1) == 1) { cprint(LINE_SPD+k, curcol+1, "ECC"); curcol += 4; }
// Then print module infos (manufacturer & part number)
int ccode = 0;
for(i = 64; i < 72; i++)
{
- if(spd[i] == 0x7F) { ccode++; }
+ if(spd_raw[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) {
+ if (ccode == jep106[i].cont_code && spd_raw[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);
@@ -298,7 +369,7 @@ void get_spd_spec(void)
curcol++;
// Display module serial number
for (h = 73; h < 91; h++) {
- cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h]));
curcol++;
}
@@ -333,7 +404,7 @@ void show_spd(void)
if (smbcontrollers[index].read_spd(j) == 0) {
dprint(POP2_Y, POP2_X + 15, j, 2, 0);
for (i = 0; i < 256; i++) {
- hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd[i], 2);
+ hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd_raw[i], 2);
}
flag = 0;
while(!flag) {