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

📄 controller.c

📁 Memtest86 is thorough, stand alone memory test for Intel/AMD x86 architecture systems. BIOS based m
💻 C
📖 第 1 页 / 共 4 页
字号:
/* controller.c - MemTest-86  Version 3.0 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- * MemTest86+ V1.30 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,};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 ((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 & 0x7F801EFC );	}	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 & 0x7F801EFC );		}}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);	}}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 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 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);	}	

⌨️ 快捷键说明

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