blob: 6e41b6b4252fe4e444600fceb52c24a6255c7439 [file] [log] [blame]
/*
* MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*
* Edited by David McInnis Oct 4, 2014
*/
//#include "defs.h"
#include "config.h"
//#include "test.h"
#include "pci.h"
#include "controller.h"
#include "spd.h"
#include "test.h"
#include "stdint.h"
#include "cpuid.h"
#include "msr.h"
#include "dmi.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) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
: "c" (msr) : "edi")
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
: \
: "c" (msr), "a" (val1), "d" (val2) : "edi")
*/
/* controller ECC capabilities and mode */
#define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */
#define __ECC_DETECT 2 /* Can detect ECC errors */
#define __ECC_CORRECT 4 /* Can correct some ECC errors */
#define __ECC_SCRUB 8 /* Can scrub corrected ECC errors */
#define __ECC_CHIPKILL 16 /* Can corrected multi-errors */
#define ECC_UNKNOWN (~0UL) /* Unknown error correcting ability/status */
#define ECC_NONE 0 /* Doesn't support ECC (or is BIOS disabled) */
#define ECC_RESERVED __ECC_UNEXPECTED /* Reserved ECC type */
#define ECC_DETECT __ECC_DETECT
#define ECC_CORRECT (__ECC_DETECT | __ECC_CORRECT)
#define ECC_CHIPKILL (__ECC_DETECT | __ECC_CORRECT | __ECC_CHIPKILL)
#define ECC_SCRUB (__ECC_DETECT | __ECC_CORRECT | __ECC_SCRUB)
static struct ecc_info {
int index;
int poll;
unsigned bus;
unsigned dev;
unsigned fn;
unsigned cap;
unsigned mode;
} ctrl =
{
.index = 0,
/* I know of no case where the memory controller is not on the
* host bridge, and the host bridge is not on bus 0 device 0
* fn 0. But just in case leave these as variables.
*/
.bus = 0,
.dev = 0,
.fn = 0,
/* Properties of the current memory controller */
.cap = ECC_UNKNOWN,
.mode = ECC_UNKNOWN,
};
void coretemp(void)
{
unsigned int msrl, msrh;
unsigned int tjunc, tabs, tnow;
unsigned long rtcr;
double amd_raw_temp;
// Only enable coretemp if IMC is known
if (imc_type == 0) { return; }
// Intel CPU
if (cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6) {
if (cpu_id.dts_pmp & 1) {
rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
tabs = ((msrl >> 16) & 0x7F);
rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
tjunc = ((msrl >> 16) & 0x7F);
if (tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received.
tnow = tjunc - tabs;
dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
v->check_temp = tnow;
}
return;
}
// AMD CPU
if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0) {
pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr);
amd_raw_temp = ((rtcr >> 21) & 0x7FF);
v->check_temp = (int)(amd_raw_temp / 8);
dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
}
}
void print_cpu_line(float dram_freq, float fsb_freq, int ram_type)
{
int cur_col = COL_SPEC;
cprint(LINE_CPU, cur_col, "RAM: ");
cur_col += 5;
dprint(LINE_CPU, cur_col, dram_freq, 4, 1);
cur_col += 4;
cprint(LINE_CPU, cur_col, "MHz (");
cur_col += 5;
switch (ram_type) {
default:
case 1:
cprint(LINE_CPU, cur_col, "DDR-");
cur_col += 4;
break;
case 2:
cprint(LINE_CPU, cur_col, "DDR2-");
cur_col += 5;
break;
case 3:
cprint(LINE_CPU, cur_col, "DDR3-");
cur_col += 5;
break;
}
if (dram_freq < 500) {
dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0);
cur_col += 3;
} else {
dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0);
cur_col += 4;
}
cprint(LINE_CPU, cur_col, ")");
cur_col++;
if (fsb_freq > 10) {
cprint(LINE_CPU, cur_col, " - BCLK: ");
cur_col += 9;
dprint(LINE_CPU, cur_col, fsb_freq, 3, 0);
}
}
void print_ram_line(float cas, int rcd, int rp, int ras, int chan)
{
int cur_col = COL_SPEC;
cprint(LINE_RAM, cur_col, "Timings: CAS ");
cur_col += 13;
// CAS Latency (tCAS)
if (cas == 1.5) {
cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3;
} else if (cas == 2.5) {
cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3;
} else if (cas < 10) {
dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1;
} else {
dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2;
}
cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS-To-CAS (tRCD)
if (rcd < 10) {
dprint(LINE_RAM, cur_col, rcd, 1, 0);
cur_col += 1;
} else {
dprint(LINE_RAM, cur_col, rcd, 2, 0);
cur_col += 2;
}
cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS Precharge (tRP)
if (rp < 10) {
dprint(LINE_RAM, cur_col, rp, 1, 0);
cur_col += 1;
} else {
dprint(LINE_RAM, cur_col, rp, 2, 0);
cur_col += 2;
}
cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS Active to precharge (tRAS)
if (ras < 10) {
dprint(LINE_RAM, cur_col, ras, 1, 0);
cur_col += 1;
} else {
dprint(LINE_RAM, cur_col, ras, 2, 0);
cur_col += 2;
}
switch (chan) {
case 0:
break;
case 1:
cprint(LINE_RAM, cur_col, " @ 64-bit Mode");
break;
case 2:
cprint(LINE_RAM, cur_col, " @ 128-bit Mode");
break;
case 3:
cprint(LINE_RAM, cur_col, " @ 192-bit Mode");
break;
case 4:
cprint(LINE_RAM, cur_col, " @ 256-bit Mode");
break;
}
}
static void poll_fsb_nothing(void)
{
char *name;
/* Print the controller name */
name = controllers[ctrl.index].name;
cprint(LINE_CPU, COL_SPEC, "Chipset: ");
cprint(LINE_CPU, COL_SPEC+9, name);
return;
}
static void poll_timings_nothing(void)
{
char *ram_type;
/* Print the controller name */
ram_type = controllers[ctrl.index].ram_type;
cprint(LINE_RAM, COL_SPEC, "RAM Type: ");
cprint(LINE_RAM, COL_SPEC+10, ram_type);
return;
}
static void setup_nothing(void)
{
ctrl.cap = ECC_NONE;
ctrl.mode = ECC_NONE;
}
static void poll_nothing(void)
{
/* Code to run when we don't know how, or can't ask the memory
* controller about memory errors.
*/
return;
}
static void setup_wmr(void)
{
ulong dev0;
// Activate MMR I/O
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
if (!(dev0 & 0x1)) {
pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
}
}
static void setup_nhm(void)
{
static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
unsigned long did, vid, mc_control, mc_ssrcontrol;
int i;
//Nehalem supports Scrubbing */
ctrl.cap = ECC_SCRUB;
ctrl.mode = ECC_NONE;
/* First, locate the PCI bus where the MCH is located */
for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
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 &= 0xFF00;
if (vid == 0x8086 && did >= 0x2C00) {
nhm_bus = possible_nhm_bus[i];
}
}
/* Now, we have the last IMC bus number in nhm_bus */
/* Check for ECC & Scrub */
pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control);
if ((mc_control >> 4) & 1) {
ctrl.mode = ECC_CORRECT;
pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
if (mc_ssrcontrol & 3) {
ctrl.mode = ECC_SCRUB;
}
}
}
static void setup_nhm32(void)
{
static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
unsigned long did, vid, mc_control, mc_ssrcontrol;
int i;
//Nehalem supports Scrubbing */
ctrl.cap = ECC_SCRUB;
ctrl.mode = ECC_NONE;
/* First, locate the PCI bus where the MCH is located */
for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
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 &= 0xFF00;
if (vid == 0x8086 && did >= 0x2C00) {
nhm_bus = possible_nhm_bus[i];
}
}
/* Now, we have the last IMC bus number in nhm_bus */
/* Check for ECC & Scrub */
pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control);
if ((mc_control >> 1) & 1) {
ctrl.mode = ECC_CORRECT;
pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
if (mc_ssrcontrol & 1) {
ctrl.mode = ECC_SCRUB;
}
}
}
static void setup_amd64(void)
{
static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL };
unsigned long nbxcfg;
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long mcanb;
unsigned long dramcl;
/* All AMD64 support Chipkill */
ctrl.cap = ECC_CHIPKILL;
/* Check First if ECC DRAM Modules are used */
pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
if (cpu_id.vers.bits.extendedModel >= 4) {
/* NEW K8 0Fh Family 90 nm */
if ((dramcl >> 19)&1) {
/* Fill in the correct memory capabilities */
pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
ctrl.mode = ddim[(nbxcfg >> 22)&3];
} else {
ctrl.mode = ECC_NONE;
}
/* Enable NB ECC Logging by MSR Write */
rdmsr(0x017B, mcgsrl, mcgsth);
wrmsr(0x017B, 0x10, mcgsth);
/* Clear any previous error */
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
} else {
/* OLD K8 130 nm */
if ((dramcl >> 17)&1) {
/* Fill in the correct memory capabilities */
pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
ctrl.mode = ddim[(nbxcfg >> 22)&3];
} else {
ctrl.mode = ECC_NONE;
}
/* Enable NB ECC Logging by MSR Write */
rdmsr(0x017B, mcgsrl, mcgsth);
wrmsr(0x017B, 0x10, mcgsth);
/* Clear any previous error */
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC );
}
}
static void setup_k10(void)
{
static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL };
unsigned long nbxcfg;
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long mcanb;
unsigned long dramcl;
ulong msr_low, msr_high;
// All AMD64 support Chipkill */
ctrl.cap = ECC_CHIPKILL;
// Check First if ECC DRAM Modules are used */
pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
if ((dramcl >> 19)&1) {
// Fill in the correct memory capabilities */
pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
ctrl.mode = ddim[(nbxcfg >> 22)&3];
} else {
ctrl.mode = ECC_NONE;
}
// Enable NB ECC Logging by MSR Write */
rdmsr(0x017B, mcgsrl, mcgsth);
wrmsr(0x017B, 0x10, mcgsth);
// Clear any previous error */
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
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 setup_apu(void)
{
ulong msr_low, msr_high;
/* 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)
{
unsigned long mcanb;
unsigned long page, offset;
unsigned long celog_syndrome;
unsigned long mcanb_add;
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) {
// Find out about the first correctable error
// Syndrome code -> bits use a complex matrix. Will add this later
// Read the error location
pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
// Read the syndrome
celog_syndrome = (mcanb >> 15)&0xFF;
// Parse the error location
page = (mcanb_add >> 12);
offset = (mcanb_add >> 3) & 0xFFF;
// Report the error
print_ecc_err(page, offset, 1, celog_syndrome, 0);
// Clear the error registers
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
}
if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) {
// Found out about the first uncorrectable error
// Read the error location
pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
// Parse the error location
page = (mcanb_add >> 12);
offset = (mcanb_add >> 3) & 0xFFF;
// Report the error
print_ecc_err(page, offset, 0, 0, 0);
// Clear the error registers
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF );
}
}
*/
static void setup_amd751(void)
{
unsigned long dram_status;
/* Fill in the correct memory capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status);
ctrl.cap = ECC_CORRECT;
ctrl.mode = (dram_status & (1 << 2)) ? ECC_CORRECT : ECC_NONE;
}
/*
static void poll_amd751(void)
{
unsigned long ecc_status;
unsigned long bank_addr;
unsigned long bank_info;
unsigned long page;
int bits;
int i;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status);
if (ecc_status & (3 << 8)) {
for(i = 0; i < 6; i++) {
if (!(ecc_status & (1 << i))) {
continue;
}
// Find the bank the error occurred on
bank_addr = 0x40 + (i << 1);
// Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info);
// Parse the error location and error type
page = (bank_info & 0xFF80) << 4;
bits = (((ecc_status >> 8) &3) == 2)?1:2;
// Report the error
print_ecc_err(page, 0, bits==1?1:0, 0, 0);
}
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0);
}
}
// Still waiting for the CORRECT intel datasheet
static void setup_i85x(void)
{
unsigned long drc;
ctrl.cap = ECC_CORRECT;
pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc);
ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE;
}
*/
static void setup_amd76x(void)
{
static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
unsigned long ecc_mode_status;
/* Fill in the correct memory capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(ecc_mode_status >> 10)&3];
}
/*
static void poll_amd76x(void)
{
unsigned long ecc_mode_status;
unsigned long bank_addr;
unsigned long bank_info;
unsigned long page;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
// Multibit error
if (ecc_mode_status & (1 << 9)) {
// Find the bank the error occurred on
bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2);
// Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
// Parse the error location and error type
page = (bank_info & 0xFF800000) >> 12;
// Report the error
print_ecc_err(page, 0, 1, 0, 0);
}
// Singlebit error
if (ecc_mode_status & (1 << 8)) {
// Find the bank the error occurred on
bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2);
// Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
// Parse the error location and error type
page = (bank_info & 0xFF800000) >> 12;
// Report the error
print_ecc_err(page, 0, 0, 0, 0);
}
// Clear the error status
if (ecc_mode_status & (3 << 8)) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status);
}
}
*/
static void setup_cnb20(void)
{
/* Fill in the correct memory capabilities */
ctrl.cap = ECC_CORRECT;
/* FIXME add ECC error polling. I don't have the documentation
* do it right now.
*/
}
static void setup_E5400(void)
{
unsigned long mcs;
/* Read the hardware capabilities */
pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs);
/* Fill in the correct memory capabilities */
ctrl.mode = 0;
ctrl.cap = ECC_SCRUB;
/* Checking and correcting enabled */
if (((mcs >> 5) & 1) == 1) {
ctrl.mode |= ECC_CORRECT;
}
/* scrub enabled */
if (((mcs >> 7) & 1) == 1) {
ctrl.mode |= __ECC_SCRUB;
}
}
static void setup_iE7xxx(void)
{
unsigned long mchcfgns;
unsigned long drc;
unsigned long device;
unsigned long dvnp;
/* Read the hardare capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
/* This is a check for E7205 */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device);
/* Fill in the correct memory capabilities */
ctrl.mode = 0;
ctrl.cap = ECC_CORRECT;
/* checking and correcting enabled */
if (((drc >> 20) & 3) == 2) {
ctrl.mode |= ECC_CORRECT;
}
/* E7205 doesn't support scrubbing */
if (device != 0x255d) {
/* scrub enabled */
/* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */
ctrl.cap = ECC_SCRUB;
if (mchcfgns & 1) {
ctrl.mode |= __ECC_SCRUB;
}
/* Now, we can active Dev1/Fun1 */
/* Thanks to Tyan for providing us the board to solve this */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, (dvnp & 0xFE));
/* Clear any routing of ECC errors to interrupts that the BIOS might have set up */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0);
}
/* Clear any prexisting error reports */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3);
}
static void setup_iE7520(void)
{
unsigned long mchscrb;
unsigned long drc;
unsigned long dvnp1;
/* Read the hardare capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
/* Fill in the correct memory capabilities */
ctrl.mode = 0;
ctrl.cap = ECC_CORRECT;
/* Checking and correcting enabled */
if (((drc >> 20) & 3) != 0) {
ctrl.mode |= ECC_CORRECT;
}
/* scrub enabled */
ctrl.cap = ECC_SCRUB;
if ((mchscrb & 3) == 2) {
ctrl.mode |= __ECC_SCRUB;
}
/* Now, we can activate Fun1 */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, (dvnp1 | 0x20));
/* Clear any prexisting error reports */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747);
}
/*
static void poll_iE7xxx(void)
{
unsigned long ferr;
unsigned long nerr;
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
if (ferr & 1) {
// Find out about the first correctable error
unsigned long celog_add;
unsigned long celog_syndrome;
unsigned long page;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
// Read the syndrome
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome);
// Parse the error location
page = (celog_add & 0x0FFFFFC0) >> 6;
// Report the error
print_ecc_err(page, 0, 1, celog_syndrome, 0);
// Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
if (ferr & 2) {
// Found out about the first uncorrectable error
unsigned long uccelog_add;
unsigned long page;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
// Parse the error location
page = (uccelog_add & 0x0FFFFFC0) >> 6;
// Report the error
print_ecc_err(page, 0, 0, 0, 0);
// Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
// Check if DRAM_NERR contains data
if (nerr & 3) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
}
}
*/
static void setup_i440gx(void)
{
static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
unsigned long nbxcfg;
/* Fill in the correct memory capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(nbxcfg >> 7)&3];
}
/*
static void poll_i440gx(void)
{
unsigned long errsts;
unsigned long page;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts);
if (errsts & 0x11) {
unsigned long eap;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap);
// Parse the error location and error type
page = (eap & 0xFFFFF000) >> 12;
bits = 0;
if (eap &3) {
bits = ((eap & 3) == 1)?1:2;
}
if (bits) {
// Report the error
print_ecc_err(page, 0, bits==1?1:0, 0, 0);
}
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3);
}
}
*/
static void setup_i840(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
unsigned long mchcfg;
/* Fill in the correct memory capabilities */
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
/*
static void poll_i840(void)
{
unsigned long errsts;
unsigned long page;
unsigned long syndrome;
int channel;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
// Parse the error location and error type
page = (eap & 0xFFFFF800) >> 11;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
// Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
*/
static void setup_i875(void)
{
long *ptr;
ulong dev0, dev6;
/* Fill in the correct memory capabilities */
ctrl.cap = ECC_CORRECT;
ctrl.mode = ECC_NONE;
/* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */
/* Activate Device 6 */
pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0);
pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2));
/* Activate Device 6 MMR */
pci_conf_read( 0, 6, 0, 0x04, 2, &dev6);
pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2));
/* Read the MMR Base Address & Define the pointer*/
pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
ptr=(long*)(dev6+0x68);
if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; }
/* Resetting state */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
}
static void setup_i925(void)
{
// Activate MMR I/O
ulong dev0, drc;
unsigned long tolm;
long *ptr;
pci_conf_read( 0, 0, 0, 0x54, 4, &dev0);
dev0 = dev0 | 0x10000000;
pci_conf_write( 0, 0, 0, 0x54, 4, dev0);
// CDH start
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
if (!(dev0 & 0xFFFFC000)) {
pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm);
pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8);
}
// CDH end
// ECC Checking
ctrl.cap = ECC_CORRECT;
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0x120);
drc = *ptr & 0xFFFFFFFF;
if (((drc >> 20) & 3) == 2) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
ctrl.mode = ECC_CORRECT;
} else {
ctrl.mode = ECC_NONE;
}
}
static void setup_p35(void)
{
// Activate MMR I/O
ulong dev0, capid0;
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
if (!(dev0 & 0x1)) {
pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
}
// ECC Checking (No poll on X38/48 for now)
pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0);
if ((capid0 >> 8) & 1) {
ctrl.cap = ECC_NONE;
} else {
ctrl.cap = ECC_CORRECT;
}
ctrl.mode = ECC_NONE;
/*
ulong toto;
pci_conf_write(0, 31, 3, 0x40, 1, 0x1);
pci_conf_read(0, 31, 3, 0x0, 4, &toto);
hprint(11,0,toto);
pci_conf_read(0, 31, 3, 0x10, 4, &toto);
hprint(11,10,toto) ;
pci_conf_read(0, 31, 3, 0x20, 4, &toto);
hprint(11,20,toto) ;
pci_conf_read(0, 28, 0, 0x0, 4, &toto);
hprint(11,30,toto);
pci_conf_read(0, 31, 0, 0x0, 4, &toto);
hprint(11,40,toto) ;
pci_conf_read(0, 31, 1, 0x0, 4, &toto);
hprint(11,50,toto) ;
pci_conf_read(0, 31, 2, 0x0, 4, &toto);
hprint(11,60,toto) ;
*/
}
/*
static void poll_i875(void)
{
unsigned long errsts;
unsigned long page;
unsigned long des;
unsigned long syndrome;
int channel;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 0x81) {
unsigned long eap;
unsigned long derrsyn;
// Read the error location, syndrome and channel
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des);
// Parse the error location and error type
page = (eap & 0xFFFFF000) >> 12;
syndrome = derrsyn;
channel = des & 1;
bits = (errsts & 0x80)?0:1;
// Report the error
print_ecc_err(page, 0, bits, syndrome, channel);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
}
}
*/
static void setup_i845(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
unsigned long drc;
// Fill in the correct memory capabilities
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(drc >> 20)&3];
}
/*
static void poll_i845(void)
{
unsigned long errsts;
unsigned long page, offset;
unsigned long syndrome;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrsyn;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn);
// Parse the error location and error type
offset = (eap & 0xFE) << 4;
page = (eap & 0x3FFFFFFE) >> 8;
syndrome = derrsyn;
bits = ((errsts & 3) == 1)?1:2;
// Report the error
print_ecc_err(page, offset, bits==1?1:0, syndrome, 0);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
*/
static void setup_i820(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
unsigned long mchcfg;
// Fill in the correct memory capabilities
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
/*
static void poll_i820(void)
{
unsigned long errsts;
unsigned long page;
unsigned long syndrome;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap);
// Parse the error location and error type
page = (eap & 0xFFFFF000) >> 4;
syndrome = eap & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
// Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, 0);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
*/
static void setup_i850(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
unsigned long mchcfg;
// Fill in the correct memory capabilities
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
/*
static void poll_i850(void)
{
unsigned long errsts;
unsigned long page;
unsigned long syndrome;
int channel;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
// Parse the error location and error type
page = (eap & 0xFFFFF800) >> 11;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
// Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
}
*/
static void setup_i860(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
unsigned long mchcfg;
unsigned long errsts;
// Fill in the correct memory capabilities
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
// Clear any prexisting error reports
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
/*
static void poll_i860(void)
{
unsigned long errsts;
unsigned long page;
unsigned char syndrome;
int channel;
int bits;
// Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
// Parse the error location and error type
page = (eap & 0xFFFFFE00) >> 9;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
// Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
}
static void poll_iE7221(void)
{
unsigned long errsts;
unsigned long page;
unsigned char syndrome;
int channel;
int bits;
int errocc;
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
errocc = errsts & 3;
if ((errocc == 1) || (errocc == 2)) {
unsigned long eap, offset;
unsigned long derrctl_sts;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts);
// Parse the error location and error type
channel = eap & 1;
eap = eap & 0xFFFFFF80;
page = eap >> 12;
offset = eap & 0xFFF;
syndrome = derrctl_sts & 0xFF;
bits = errocc & 1;
// Report the error
print_ecc_err(page, offset, bits, syndrome, channel);
// Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
else if (errocc == 3) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
}
static void poll_iE7520(void)
{
unsigned long ferr;
unsigned long nerr;
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr);
if (ferr & 0x0101) {
// Find out about the first correctable error
unsigned long celog_add;
unsigned long celog_syndrome;
unsigned long page;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add);
// Read the syndrome
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome);
// Parse the error location
page = (celog_add & 0x7FFFFFFC) >> 2;
// Report the error
print_ecc_err(page, 0, 1, celog_syndrome, 0);
// Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101);
}
if (ferr & 0x4646) {
// Found out about the first uncorrectable error
unsigned long uccelog_add;
unsigned long page;
// Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add);
// Parse the error location
page = (uccelog_add & 0x7FFFFFFC) >> 2;
// Report the error
print_ecc_err(page, 0, 0, 0, 0);
// Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646);
}
// Check if DRAM_NERR contains data
if (nerr & 0x4747) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747);
}
}
*/
/* ----------------- Here's the code for FSB detection ----------------- */
/* --------------------------------------------------------------------- */
static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5};
static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0};
static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
static float getP4PMmultiplier(void)
{
//unsigned int msr_lo, msr_hi;
int msr_lo, msr_hi;
float coef;
/* Find multiplier (by MSR) */
if (cpu_id.vers.bits.family == 6) {
if (cpu_id.fid.bits.eist & 1) {
rdmsr(0x198, msr_lo, msr_hi);
coef = ((msr_lo) >> 8) & 0x1F;
if ((msr_lo >> 14) & 0x1) { coef += 0.5f; }
// Atom Fix
if (coef == 6) {
coef = ((msr_hi) >> 8) & 0x1F;
if ((msr_hi >> 14) & 0x1) { coef += 0.5f; }
}
} else {
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 22) & 0x1F;
}
} else {
if (cpu_id.vers.bits.model < 2) {
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 8) & 0xF;
coef = p4model1ratios[(int)coef];
} else {
rdmsr(0x2C, msr_lo, msr_hi);
coef = (msr_lo >> 24) & 0x1F;
}
}
return coef;
}
static float getNHMmultiplier(void)
{
unsigned int msr_lo, msr_hi;
float coef;
/* Find multiplier (by MSR) */
/* First, check if Flexible Ratio is Enabled */
rdmsr(0x194, msr_lo, msr_hi);
if ((msr_lo >> 16) & 1) {
coef = (msr_lo >> 8) & 0xFF;
} else {
rdmsr(0xCE, msr_lo, msr_hi);
coef = (msr_lo >> 8) & 0xFF;
}
return coef;
}
static float getSNBmultiplier(void)
{
unsigned int msr_lo, msr_hi;
float coef;
rdmsr(0xCE, msr_lo, msr_hi);
coef = (msr_lo >> 8) & 0xFF;
return coef;
}
static void poll_fsb_ct(void)
{
unsigned long mcr, mdr;
double dramratio, dramclock, fsb;
float coef = getP4PMmultiplier();
/* Build the MCR Message*/
mcr = (0x10 << 24); // 10h = Read - 11h = Write
mcr += (0x01 << 16); // DRAM Registers located on port 01h
mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h
mcr &= 0xFFFFFFF0; // bit 03:00 RSVD
/* Send Message to GMCH */
pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
/* Read Answer from Sideband bus */
pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
/* Get RAM ratio */
switch (mdr & 0x3) {
default:
case 0: dramratio = 3.0f; break;
case 1: dramratio = 4.0f; break;
case 2: dramratio = 5.0f; break;
case 3: dramratio = 6.0f; break;
}
// Compute FSB & RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print'em all. Whoa !
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_amd64(void)
{
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long fid, temp2;
unsigned long dramchr;
float clockratio;
double dramclock;
unsigned int dummy[4];
int ram_type;
float coef = 10;
cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]);
/* First, got the FID by MSR */
/* First look if Cool 'n Quiet is supported to choose the best msr */
if (((dummy[3] >> 1) & 1) == 1) {
rdmsr(0xc0010042, mcgsrl, mcgsth);
fid = (mcgsrl & 0x3F);
} else {
rdmsr(0xc0010015, mcgsrl, mcgsth);
fid = ((mcgsrl >> 24)& 0x3F);
}
/* Extreme simplification. */
coef = ( fid / 2 ) + 4.0;
/* Support for .5 coef */
if (fid & 1) { coef = coef + 0.5; }
/* Next, we need the clock ratio */
if (cpu_id.vers.bits.extendedModel >= 4) {
/* K8 0FH */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr & 0x7);
clockratio = coef;
ram_type = 2;
switch (temp2) {
case 0x0:
clockratio = (int)(coef);
break;
case 0x1:
clockratio = (int)(coef * 3.0f/4.0f);
break;
case 0x2:
clockratio = (int)(coef * 3.0f/5.0f);
break;
case 0x3:
clockratio = (int)(coef * 3.0f/6.0f);
break;
}
} else {
/* OLD K8 */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr >> 20) & 0x7;
ram_type = 1;
clockratio = coef;
switch (temp2) {
case 0x0:
clockratio = (int)(coef * 2.0f);
break;
case 0x2:
clockratio = (int)((coef * 3.0f/2.0f) + 0.81f);
break;
case 0x4:
clockratio = (int)((coef * 4.0f/3.0f) + 0.81f);
break;
case 0x5:
clockratio = (int)((coef * 6.0f/5.0f) + 0.81f);
break;
case 0x6:
clockratio = (int)((coef * 10.0f/9.0f) + 0.81f);
break;
case 0x7:
clockratio = (int)(coef + 0.81f);
break;
}
}
/* Compute the final DRAM Clock */
dramclock = (extclock / 1000) / clockratio;
/* ...and print */
print_cpu_line(dramclock, (extclock / 1000 / coef), ram_type);
}
static void poll_fsb_k10(void)
{
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long temp2;
unsigned long dramchr;
unsigned long mainPllId;
double dramclock;
ulong offset = 0;
int ram_type = 2;
/* First, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr & 0x7);
switch (temp2) {
case 0x7: temp2++;
case 0x6: temp2++;
case 0x5: temp2++;
case 0x4: temp2++;
default: temp2 += 3;
}
/* Compute the final DRAM Clock */
if (cpu_id.vers.bits.extendedModel == 1) {
dramclock = ((temp2 * 200) / 3.0) + 0.25;
} else {
unsigned long target;
unsigned long dx;
unsigned divisor;
target = temp2 * 400;
/* Get the FID by MSR */
rdmsr(0xc0010071, mcgsrl, mcgsth);
pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId);
if (mainPllId & 0x40)
mainPllId &= 0x3F;
else
mainPllId = 8; /* FID for 1600 */
mcgsth = (mcgsth >> 17) & 0x3F;
if (mcgsth) {
if (mainPllId > mcgsth)
mainPllId = mcgsth;
}
dx = (mainPllId + 8) * 1200;
for (divisor = 3; divisor < 100; divisor++)
if ( (dx / divisor) <= target)
break;
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
// 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);
}
//DDR2 or DDR3
if ((dramchr >> 8)&1) {
ram_type = 3;
} else {
ram_type = 2;
}
dramclock = ((dx / divisor) / 6.0) + 0.25;
}
/* ...and print */
print_cpu_line(dramclock, 0, ram_type);
}
static void poll_fsb_k12(void)
{
unsigned long temp2;
unsigned long dramchr;
double dramratio, dramclock, fsb, did;
unsigned int mcgsrl, mcgsth, fid, did_raw;
// Get current FID & DID
rdmsr(0xc0010071, mcgsrl, mcgsth);
did_raw = mcgsrl & 0xF;
fid = (mcgsrl >> 4) & 0xF;
switch (did_raw) {
default:
case 0x0:
did = 1.0f;
break;
case 0x1:
did = 1.5f;
break;
case 0x2:
did = 2.0f;
break;
case 0x3:
did = 3.0f;
break;
case 0x4:
did = 4.0f;
break;
case 0x5:
did = 6.0f;
break;
case 0x6:
did = 8.0f;
break;
case 0x7:
did = 12.0f;
break;
case 0x8:
did = 16.0f;
break;
}
fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did));
/* Finaly, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
if (((dramchr >> 14) & 0x1) == 1) {
pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
}
temp2 = (dramchr & 0x1F);
switch (temp2) {
default:
case 0x06:
dramratio = 4.0f;
break;
case 0x0A:
dramratio = 16.0f / 3.0f;
break;
case 0x0E:
dramratio = 20.0f / 3.0f;
break;
case 0x12:
dramratio = 8.0f;
break;
case 0x16:
dramratio = 28.0f / 3.0f;
break;
}
dramclock = fsb * dramratio;
/* print */
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_k16(void)
{
unsigned long dramchr;
double dramratio, dramclock, fsb;
// FIXME: Unable to find a real way to detect multiplier.
fsb = 100.0f;
/* Clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
switch (dramchr & 0x1F) {
default:
case 0x04: /* 333 */
dramratio = 10.0f / 3.0f;
break;
case 0x06: /* 400 */
dramratio = 4.0f;
break;
case 0x0A: /* 533 */
dramratio = 16.0f / 3.0f;
break;
case 0x0E: /* 667 */
dramratio = 20.0f / 3.0f;
break;
case 0x12: /* 800 */
dramratio = 8.0f;
break;
case 0x16: /* 933 */
dramratio = 28.0f / 3.0f;
break;
case 0x19: /* 1050 */
dramratio = 21.0f / 2.0f;
break;
case 0x1A: /* 1066 */
dramratio = 32.0f / 3.0f;
break;
}
dramclock = fsb * dramratio;
/* print */
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_k15(void)
{
unsigned long temp2;
unsigned long dramchr;
double dramclock, fsb;
unsigned int mcgsrl, mcgsth, fid, did;
// Get current FID & DID
rdmsr(0xc0010071, mcgsrl, mcgsth);
fid = mcgsrl & 0x3F;
did = (mcgsrl >> 6) & 0x7;
fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2);
/* Finaly, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
if (((dramchr >> 14) & 0x1) == 1) {
pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
}
temp2 = (dramchr & 0x1F);
switch (temp2) {
case 0x02:
dramclock = 200;
break;
case 0x04:
dramclock = 333;
break;
case 0x06:
dramclock = 400;
break;
case 0x0A:
dramclock = 533;
break;
case 0x0E:
dramclock = 667;
break;
case 0x12:
dramclock = 800;
break;
case 0x16:
dramclock = 933;
break;
case 0x1A:
dramclock = 1066;
break;
case 0x1F:
dramclock = 1200;
break;
default:
dramclock = 0;
break;
}
/* print */
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_k14(void)
{
unsigned long dramchr;
double dramratio, dramclock, fsb;
// FIXME: Unable to find a real way to detect multiplier.
fsb = 100.0f;
/* Clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
switch (dramchr & 0x1F) {
default:
case 0x06:
dramratio = 4.0f;
break;
case 0x0A:
dramratio = 16.0f / 3.0f;
break;
case 0x0E:
dramratio = 20.0f / 3.0f;
break;
case 0x12:
dramratio = 8.0f;
break;
}
dramclock = fsb * dramratio;
/* print */
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_i925(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
float coef = getP4PMmultiplier();
long *ptr;
int ddr_type;
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
dev0 = dev0 & 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
ptr=(long*)(dev0+0x120);
drc = *ptr & 0xFFFF;
dramratio = 1;
mchcfg2 = (mchcfg >> 4)&3;
if ((drc&3) != 2) {
// We are in DDR1 Mode
if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; }
ddr_type = 1;
} else {
// We are in DDR2 Mode
ddr_type = 2;
if ((mchcfg >> 2)&1) {
// We are in FSB1066 Mode
if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; }
} else {
switch (mchcfg2) {
case 1:
dramratio = 0.66667;
break;
case 2:
if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; }
break;
case 3:
// Checking for FSB533 Mode & Alviso
if ((mchcfg & 1) == 0) { dramratio = 1.33334; }
else if (idetect == 0x2590) { dramratio = 2; }
else { dramratio = 1.5; }
}
}
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
print_cpu_line(dramclock, fsb, ddr_type);
}
static void poll_fsb_i945(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0;
float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 1.0; break;
case 2: dramratio = 1.33334; break;
case 3: dramratio = 1.66667; break;
case 4: dramratio = 2.0; break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_i945gme(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch (mchcfg & 7) {
case 0: fsb_mch = 400; break;
default:
case 1: fsb_mch = 533; break;
case 2: fsb_mch = 667; break;
}
switch (fsb_mch) {
case 400:
switch ((mchcfg >> 4)&7) {
case 2: dramratio = 1.0f; break;
case 3: dramratio = 4.0f/3.0f; break;
case 4: dramratio = 5.0f/3.0f; break;
}
break;
default:
case 533:
switch ((mchcfg >> 4)&7) {
case 2: dramratio = 3.0f/4.0f; break;
case 3: dramratio = 1.0f; break;
case 4: dramratio = 5.0f/4.0f; break;
}
break;
case 667:
switch ((mchcfg >> 4)&7) {
case 2: dramratio = 3.0f/5.0f; break;
case 3: dramratio = 4.0f/5.0f; break;
case 4: dramratio = 1.0f; break;
}
break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio * 2;
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_i975(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch (mchcfg & 7) {
case 1: fsb_mch = 533; break;
case 2: fsb_mch = 800; break;
case 3: fsb_mch = 667; break;
default: fsb_mch = 1066; break;
}
switch (fsb_mch) {
case 533:
switch ((mchcfg >> 4)&7) {
case 0: dramratio = 1.25; break;
case 1: dramratio = 1.5; break;
case 2: dramratio = 2.0; break;
}
break;
default:
case 800:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 1.0; break;
case 2: dramratio = 1.33334; break;
case 3: dramratio = 1.66667; break;
case 4: dramratio = 2.0; break;
}
break;
case 1066:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 0.75; break;
case 2: dramratio = 1.0; break;
case 3: dramratio = 1.25; break;
case 4: dramratio = 1.5; break;
}
break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_i965(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch (mchcfg & 7) {
case 0: fsb_mch = 1066; break;
case 1: fsb_mch = 533; break;
default: case 2: fsb_mch = 800; break;
case 3: fsb_mch = 667; break;
case 4: fsb_mch = 1333; break;
case 6: fsb_mch = 1600; break;
}
switch (fsb_mch) {
case 533:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 2.0; break;
case 2: dramratio = 2.5; break;
case 3: dramratio = 3.0; break;
}
break;
default:
case 800:
switch ((mchcfg >> 4)&7) {
case 0: dramratio = 1.0; break;
case 1: dramratio = 5.0f/4.0f; break;
case 2: dramratio = 5.0f/3.0f; break;
case 3: dramratio = 2.0f; break;
case 4: dramratio = 8.0f/3.0f; break;
case 5: dramratio = 10.0f/3.0f; break;
}
break;
case 1066:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 1.0f; break;
case 2: dramratio = 5.0f/4.0f; break;
case 3: dramratio = 3.0f/2.0f; break;
case 4: dramratio = 2.0f; break;
case 5: dramratio = 5.0f/2.0f; break;
}
break;
case 1333:
switch ((mchcfg >> 4)&7) {
case 2: dramratio = 1.0f; break;
case 3: dramratio = 6.0f/5.0f; break;
case 4: dramratio = 8.0f/5.0f; break;
case 5: dramratio = 2.0f; break;
}
break;
case 1600:
switch ((mchcfg >> 4)&7) {
case 3: dramratio = 1.0f; break;
case 4: dramratio = 4.0f/3.0f; break;
case 5: dramratio = 3.0f/2.0f; break;
case 6: dramratio = 2.0f; break;
}
break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_p35(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch, Device_ID, Memory_Check, c0ckectrl, offset;
float coef = getP4PMmultiplier();
long *ptr;
int ram_type;
pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID);
Device_ID &= 0xFFFF;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr = (long*)(dev0+0x260);
c0ckectrl = *ptr & 0xFFFFFFFF;
// If DIMM 0 not populated, check DIMM 1
((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400);
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch (mchcfg & 7) {
case 0: fsb_mch = 1066; break;
case 1: fsb_mch = 533; break;
default: case 2: fsb_mch = 800; break;
case 3: fsb_mch = 667; break;
case 4: fsb_mch = 1333; break;
case 6: fsb_mch = 1600; break;
}
switch (fsb_mch) {
case 533:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 2.0; break;
case 2: dramratio = 2.5; break;
case 3: dramratio = 3.0; break;
}
break;
default:
case 800:
switch ((mchcfg >> 4)&7) {
case 0: dramratio = 1.0; break;
case 1: dramratio = 5.0f/4.0f; break;
case 2: dramratio = 5.0f/3.0f; break;
case 3: dramratio = 2.0; break;
case 4: dramratio = 8.0f/3.0f; break;
case 5: dramratio = 10.0f/3.0f; break;
}
break;
case 1066:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 1.0f; break;
case 2: dramratio = 5.0f/4.0f; break;
case 3: dramratio = 3.0f/2.0f; break;
case 4: dramratio = 2.0f; break;
case 5: dramratio = 5.0f/2.0f; break;
}
break;
case 1333:
switch ((mchcfg >> 4)&7) {
case 2: dramratio = 1.0f; break;
case 3: dramratio = 6.0f/5.0f; break;
case 4: dramratio = 8.0f/5.0f; break;
case 5: dramratio = 2.0f; break;
}
break;
case 1600:
switch ((mchcfg >> 4)&7) {
case 3: dramratio = 1.0f; break;
case 4: dramratio = 4.0f/3.0f; break;
case 5: dramratio = 3.0f/2.0f; break;
case 6: dramratio = 2.0f; break;
}
break;
}
// On P45, check 1A8
if (Device_ID > 0x2E00 && imc_type != 8) {
ptr = (long*)(dev0+offset+0x1A8);
Memory_Check = *ptr & 0xFFFFFFFF;
Memory_Check >>= 2;
Memory_Check &= 1;
Memory_Check = !Memory_Check;
} else if (imc_type == 8) {
ptr = (long*)(dev0+offset+0x224);
Memory_Check = *ptr & 0xFFFFFFFF;
Memory_Check &= 1;
Memory_Check = !Memory_Check;
} else {
ptr = (long*)(dev0+offset+0x1E8);
Memory_Check = *ptr & 0xFFFFFFFF;
}
//Determine DDR-II or DDR-III
if (Memory_Check & 1) {
ram_type = 2;
} else {
ram_type = 3;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, ram_type);
}
static void poll_fsb_im965(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
switch (mchcfg & 7) {
case 1: fsb_mch = 533; break;
default: case 2: fsb_mch = 800; break;
case 3: fsb_mch = 667; break;
case 6: fsb_mch = 1066; break;
}
switch (fsb_mch) {
case 533:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 5.0f/4.0f; break;
case 2: dramratio = 3.0f/2.0f; break;
case 3: dramratio = 2.0f; break;
}
break;
case 667:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 1.0f; break;
case 2: dramratio = 6.0f/5.0f; break;
case 3: dramratio = 8.0f/5.0f; break;
case 4: dramratio = 2.0f; break;
case 5: dramratio = 12.0f/5.0f; break;
}
break;
default:
case 800:
switch ((mchcfg >> 4)&7) {
case 1: dramratio = 5.0f/6.0f; break;
case 2: dramratio = 1.0f; break;
case 3: dramratio = 4.0f/3.0f; break;
case 4: dramratio = 5.0f/3.0f; break;
case 5: dramratio = 2.0f; break;
}
break;
case 1066:
switch ((mchcfg >> 4)&7) {
case 5: dramratio = 3.0f/2.0f; break;
case 6: dramratio = 2.0f; break;
}
break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_5400(void)
{
double dramclock, dramratio, fsb;
unsigned long ambase_low, ambase_high, ddrfrq;
float coef = getP4PMmultiplier();
/* Find dramratio */
pci_conf_read( 0, 16, 0, 0x48, 4, &ambase_low);
ambase_low &= 0xFFFE0000;
pci_conf_read( 0, 16, 0, 0x4C, 4, &ambase_high);
ambase_high &= 0xFF;
pci_conf_read( 0, 16, 1, 0x56, 1, &ddrfrq);
ddrfrq &= 7;
dramratio = 1;
switch (ddrfrq) {
case 0:
case 1:
case 4:
dramratio = 1.0;
break;
case 2:
dramratio = 5.0f/4.0f;
break;
case 3:
case 7:
dramratio = 4.0f/5.0f;
break;
}
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_nf4ie(void)
{
double dramclock, dramratio, fsb;
float mratio, nratio;
unsigned long reg74, reg60;
float coef = getP4PMmultiplier();
/* Find dramratio */
pci_conf_read(0, 0, 2, 0x74, 2, &reg74);
pci_conf_read(0, 0, 2, 0x60, 4, &reg60);
mratio = reg74 & 0xF;
nratio = (reg74 >> 4) & 0xF;
// If M or N = 0, then M or N = 16
if (mratio == 0) { mratio = 16; }
if (nratio == 0) { nratio = 16; }
// Check if synchro or pseudo-synchro mode
if ((reg60 >> 22) & 1) {
dramratio = 1;
} else {
dramratio = nratio / mratio;
}
/* Compute RAM Frequency */
fsb = ((extclock /1000) / coef);
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_i875(void)
{
double dramclock, dramratio, fsb;
unsigned long mchcfg, smfs;
float coef = getP4PMmultiplier();
/* Find dramratio */
pci_conf_read(0, 0, 0, 0xC6, 2, &mchcfg);
smfs = (mchcfg >> 10)&3;
dramratio = 1;
if ((mchcfg&3) == 3) { dramratio = 1; }
if ((mchcfg&3) == 2) {
if (smfs == 2) { dramratio = 1; }
if (smfs == 1) { dramratio = 1.25; }
if (smfs == 0) { dramratio = 1.5; }
}
if ((mchcfg&3) == 1) {
if (smfs == 2) { dramratio = 0.6666666666; }
if (smfs == 1) { dramratio = 0.8; }
if (smfs == 0) { dramratio = 1; }
}
if ((mchcfg&3) == 0) { dramratio = 0.75; }
/* Compute RAM Frequency */
dramclock = ((extclock /1000) / coef) / dramratio;
fsb = ((extclock /1000) / coef);
/* Print DRAM Freq */
print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_p4(void)
{
ulong fsb, idetect;
float coef = getP4PMmultiplier();
char *name;
int col, temp;
fsb = ((extclock /1000) / coef);
/* For synchro only chipsets */
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
if (idetect == 0x2540 || idetect == 0x254C) {
print_cpu_line(fsb, fsb, 1);
} else {
/* Print the controller name */
col = COL_SPEC;
cprint(LINE_CPU, col, "Chipset: ");
col += 9;
/* Print the controller name */
name = controllers[ctrl.index].name;
cprint(LINE_CPU, col, name);
/* Now figure out how much I just printed */
temp = 20;
while (name[temp - 20] != '\0') {
col++;
temp++;
}
if (temp < 36) {
cprint(LINE_CPU, col +1, "- FSB : ");
col += 9;
dprint(LINE_CPU, col, fsb, 3, 0);
col += 3;
}
}
}
static void poll_fsb_i855(void)
{
double dramclock, dramratio, fsb;
unsigned int msr_lo, msr_hi;
ulong mchcfg, idetect;
int coef;
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
/* Find multiplier (by MSR) */
/* Is it a Pentium M ? */
if (cpu_id.vers.bits.family == 6) {
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 22) & 0x1F;
} else {
rdmsr(0x2C, msr_lo, msr_hi);
coef = (msr_lo >> 24) & 0x1F;
}
fsb = ((extclock /1000) / coef);
/* Compute DRAM Clock */
dramratio = 1;
if (idetect == 0x3580) {
pci_conf_read( 0, 0, 3, 0xC0, 2, &mchcfg);
mchcfg = mchcfg & 0x7;
if (mchcfg == 1 || mchcfg == 2 || mchcfg == 4 || mchcfg == 5) { dramratio = 1; }
if (mchcfg == 0 || mchcfg == 3) { dramratio = 1.333333333; }
if (mchcfg == 6) { dramratio = 1.25; }
if (mchcfg == 7) { dramratio = 1.666666667; }
} else {
pci_conf_read( 0, 0, 0, 0xC6, 2, &mchcfg);
if (((mchcfg >> 10) & 3) == 0) { dramratio = 1; }
else if (((mchcfg >> 10) & 3) == 1) { dramratio = 1.666667; }
else { dramratio = 1.333333333; }
}
dramclock = fsb * dramratio;
/* ...and print */
print_cpu_line(dramclock, fsb, 1);
}
static void poll_fsb_amd32(void)
{
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long temp;
double dramclock;
double coef2;
int col;
char *name;
/* First, got the FID */
rdmsr(0x0c0010015, mcgsrl, mcgsth);
temp = (mcgsrl >> 24)&0x0F;
if ((mcgsrl >> 19) & 1) { coef2 = athloncoef2[temp]; }
else { coef2 = athloncoef[temp]; }
if (coef2 == 0) { coef2 = 1; }
/* Compute the final FSB Clock */
dramclock = (extclock /1000) / coef2;
/* Print the controller name */
col = COL_SPEC;
cprint(LINE_CPU, col, "Chipset: ");
col += 9;
/* Print the controller name */
name = controllers[ctrl.index].name;
cprint(LINE_CPU, col, name);
/* Now figure out how much I just printed */
temp = 20;
while (name[temp - 20] != '\0') {
col++;
temp++;
}
if (temp < 36) {
cprint(LINE_CPU, col +1, "- FSB : ");
col += 9;
dprint(LINE_CPU, col, dramclock, 3, 0);
col += 3;
}
}
static void poll_fsb_nf2(void)
{
unsigned int mcgsrl;
unsigned int mcgsth;
unsigned long temp, mempll;
double dramclock, fsb;
double mem_m, mem_n;
float coef;
/* First, got the FID */
rdmsr(0x0c0010015, mcgsrl, mcgsth);
temp = (mcgsrl >> 24)&0x0F;
if ((mcgsrl >> 19) & 1) { coef = athloncoef2[temp]; }
else { coef = athloncoef[temp]; }
/* Get the coef (COEF = N/M) - Here is for Crush17 */
pci_conf_read(0, 0, 3, 0x70, 4, &mempll);
mem_m = (mempll&0x0F);
mem_n = ((mempll >> 4) & 0x0F);
/* If something goes wrong, the chipset is probably a Crush18 */
if (mem_m == 0 || mem_n == 0) {
pci_conf_read(0, 0, 3, 0x7C, 4, &mempll);
mem_m = (mempll&0x0F);
mem_n = ((mempll >> 4) & 0x0F);
}
/* Compute the final FSB Clock */
dramclock = ((extclock /1000) / coef) * (mem_n/mem_m);
fsb = ((extclock /1000) / coef);
/* ...and print */
print_cpu_line(dramclock, fsb, 1);
}
static void poll_fsb_us15w(void)
{
double dramclock, dramratio, fsb;
unsigned long msr;
/* Find dramratio */
/* D0 MsgRd, 05 Zunit, 03 MSR */
pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0050300 );
pci_conf_read(0, 0, 0, 0xD4, 4, &msr );
dramratio = 0.5;
// Compute RAM Frequency
if (( msr >> 3 ) & 1) {
fsb = 533;
} else {
fsb = 400;
}
/*
switch (( msr >> 0 ) & 7) {
case 0:
gfx = 100;
break;
case 1:
gfx = 133;
break;
case 2:
gfx = 150;
break;
case 3:
gfx = 178;
break;
case 4:
gfx = 200;
break;
case 5:
gfx = 266;
break;
default:
gfx = 0;
break;
}
*/
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 1);
}
static void poll_fsb_nhm(void)
{
double dramclock, dramratio, fsb;
unsigned long mc_dimm_clk_ratio;
float coef = getNHMmultiplier();
//unsigned long qpi_pll_status;
//float qpi_speed;
/* Print QPI Speed (if ECC not supported) */
/*
if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.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 : ");
col += 9;
dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0);
col += 1;
cprint(LINE_CPU+5, col, ".");
col += 1;
qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10;
dprint(LINE_CPU+5, col, qpi_speed, 1,0);
col += 1;
cprint(LINE_CPU+5, col +1, "GT/s");
col += 5;
}
*/
/* Get the clock ratio */
pci_conf_read(nhm_bus, 3, 4, 0x54, 2, &mc_dimm_clk_ratio);
dramratio = (mc_dimm_clk_ratio & 0x1F);
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio / 2;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_nhm32(void)
{
double dramclock, dramratio, fsb;
unsigned long mc_dimm_clk_ratio;
float coef = getNHMmultiplier();
//unsigned long qpi_pll_status;
//float qpi_speed;
/* Print QPI Speed (if ECC not supported) */
/*
if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 12) {
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 : ");
col += 9;
dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0);
col += 1;
cprint(LINE_CPU+5, col, ".");
col += 1;
qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10;
dprint(LINE_CPU+5, col, qpi_speed, 1,0);
col += 1;
cprint(LINE_CPU+5, col +1, "GT/s");
col += 5;
}
*/
/* Get the clock ratio */
pci_conf_read(nhm_bus, 3, 4, 0x50, 2, &mc_dimm_clk_ratio);
dramratio = (mc_dimm_clk_ratio & 0x1F);
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio / 2;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_wmr(void)
{
double dramclock, dramratio, fsb;
unsigned long dev0;
float coef = getNHMmultiplier();
long *ptr;
fsb = ((extclock / 1000) / coef);
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0x2C20);
/* Get the clock ratio */
dramratio = 0.25 * (float)(*ptr & 0x1F);
// Compute RAM Frequency
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_snb(void)
{
double dramclock, dramratio, fsb;
unsigned long dev0;
float coef = getSNBmultiplier();
long *ptr;
fsb = ((extclock / 1000) / coef);
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0x5E04);
/* Get the clock ratio */
dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f);
// Compute RAM Frequency
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_ivb(void)
{
double dramclock, dramratio, fsb;
unsigned long dev0, mchcfg;
float coef = getSNBmultiplier();
long *ptr;
fsb = ((extclock / 1000) / coef);
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0x5E04);
mchcfg = *ptr & 0xFFFF;
dramratio = 1;
/* Get the clock ratio */
switch ((mchcfg >> 8) & 0x01) {
case 0x0:
dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f);
break;
case 0x1:
dramratio = (float)(*ptr & 0x1F) * (100.0f / 100.0f);
break;
}
// Compute RAM Frequency
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_snbe(void)
{
double dramclock, dramratio, fsb;
unsigned long dev0;
float coef = getSNBmultiplier();
fsb = ((extclock / 1000) / coef);
/* Find dramratio */
pci_conf_read( 0xFF, 10, 1, 0x98, 4, &dev0);
dev0 &= 0xFFFFFFFF;
/* Get the clock ratio */
dramratio = (float)(dev0 & 0x3F) * (66.67f / 100.0f);
// Compute RAM Frequency
dramclock = fsb * dramratio;
// Print DRAM Freq
print_cpu_line(dramclock, fsb, 3);
}
/* ------------------ Here the code for Timings detection ------------------ */
/* ------------------------------------------------------------------------- */
static void poll_timings_nf4ie(void)
{
ulong regd0, reg8c, reg9c, reg80;
int cas, rcd, rp, ras, chan;
//Now, read Registers
pci_conf_read( 0, 1, 1, 0xD0, 4, &regd0);