⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 controller.c

📁 系统启动时检测内存状况的软件C代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* controller.c - MemTest-86  Version 3.0 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- * MemTest86+ V1.70 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */#include "defs.h"#include "config.h"#include "test.h"#include "pci.h"#include "controller.h"int col, col2;extern ulong extclock;extern struct cpu_ident cpu_id;#define rdmsr(msr,val1,val2) \	__asm__ __volatile__("rdmsr" \			  : "=a" (val1), "=d" (val2) \			  : "c" (msr))#define wrmsr(msr,val1,val2) \	__asm__ __volatile__("wrmsr" \			  : /* no outputs */ \			  : "c" (msr), "a" (val1), "d" (val2))/* 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       /* Doesnt 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,};struct pci_memory_controller {	unsigned vendor;	unsigned device;	char *name;	int tested;	void (*poll_fsb)(void);	void (*poll_timings)(void);	void (*setup_ecc)(void);	void (*poll_errors)(void);};void print_timings_info(float cas, int rcd, int rp, int ras) {	/* Now, we could print some additionnals timings infos) */	cprint(LINE_CPU+5, col2 +1, "/ CAS : ");	col2 += 9;	// CAS Latency (tCAS)	if (cas == 1.5) {		cprint(LINE_CPU+5, col2, "1.5"); col2 += 3;	} else if (cas == 2.5) {		cprint(LINE_CPU+5, col2, "2.5"); col2 += 3;	} else {		dprint(LINE_CPU+5, col2, cas, 1, 0); col2 += 1;	}	cprint(LINE_CPU+5, col2, "-"); col2 += 1;	// RAS-To-CAS (tRCD)	dprint(LINE_CPU+5, col2, rcd, 1, 0);	cprint(LINE_CPU+5, col2+1, "-");	col2 +=2;	// RAS Precharge (tRP)	dprint(LINE_CPU+5, col2, rp, 1, 0);	cprint(LINE_CPU+5, col2+1, "-");	col2 +=2;	// RAS Active to precharge (tRAS)	if (ras < 9) {		dprint(LINE_CPU+5, col2, ras, 1, 0);		col2 += 2;	} else {		dprint(LINE_CPU+5, col2, ras, 2, 0);		col2 += 3;	}}void print_fsb_info(float val, const char *text_fsb) {	cprint(LINE_CPU+5, col2, "Settings: ");	col2 += 10;	cprint(LINE_CPU+5, col2, text_fsb);	col2 += 6;	dprint(LINE_CPU+5, col2, val ,3 ,0);	col2 += 3;	cprint(LINE_CPU+5, col2 +1, "MHz ");	col2 += 5;	cprint(LINE_CPU+5, col2, "(DDR");	col2 += 4;	dprint(LINE_CPU+5, col2, val*2 ,3 ,0);	col2 += 3;	cprint(LINE_CPU+5, col2, ")");	col2 += 1;}static void poll_fsb_nothing(void){/* Code to run for no specific fsb detection */	return;}static void poll_timings_nothing(void){/* Code to run for no specific timings detection */	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_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.ext >> 16) & 0xF) >= 4) {		/* NEW K8 0Fh Family 90 nm */				if ((dramcl >> 19)&1){			/* Fill in the correct memory capabilites */			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 capabilites */			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 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 capabilites */	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 occured 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 datasheetstatic 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 capabilites */	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 occured 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 occured 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 capabilites */	ctrl.cap = ECC_CORRECT;	/* FIXME add ECC error polling.  I don't have the documentation	 * do it right now.	 */}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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -