]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.20-ecc.patch
- added description of djurban's branch
[packages/kernel.git] / linux-2.4.20-ecc.patch
CommitLineData
da79e8e8 1diff -urN Linux/drivers/char/Config.in linux/drivers/char/Config.in
2--- Linux/drivers/char/Config.in Tue May 21 11:16:05 2002
3+++ linux/drivers/char/Config.in Tue May 21 11:18:53 2002
4@@ -5,6 +5,7 @@
5 comment 'Character devices'
6
7 bool 'Virtual terminal' CONFIG_VT
8+tristate ' ECC memory monitoring' CONFIG_ECC
9 if [ "$CONFIG_VT" = "y" ]; then
10 bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE
11 fi
12diff -urN Linux/drivers/char/Makefile linux/drivers/char/Makefile
13--- Linux/drivers/char/Makefile Tue May 21 11:16:05 2002
14+++ linux/drivers/char/Makefile Tue May 21 11:18:53 2002
15@@ -144,6 +144,7 @@
16 endif
17
18 obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
19+obj-$(CONFIG_ECC) += ecc.o
20 obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
21 obj-$(CONFIG_ROCKETPORT) += rocket.o
22 obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
23diff -urN Linux/drivers/char/ecc.c linux/drivers/char/ecc.c
24--- Linux/drivers/char/ecc.c Thu Jan 1 01:00:00 1970
25+++ linux/drivers/char/ecc.c Tue May 21 11:19:17 2002
26@@ -0,0 +1,1434 @@
27+/*
28+ * ECC kernel module (C) 1998, 1999, 2002 Dan Hollis <goemon at anime dot net>
29+ * Portions thanks to
30+ * Michael O'Reilly <michael at metal dot iinet dot net dot au>
31+ * Osma Ahvenlampi <oa at spray dot fi>
32+ * Martin Maney <maney at pobox dot com>
33+ * Peter Heckert <peter.heckert at arcormail dot de>
34+ * Ishikawa <ishikawa at yk dot rim dot or dot jp>
35+ * Jaakko Hyvti <jaakko dot hyvatti at iki dot fi>
36+ * Various Linux Networx, LLNL & Red Hat staff.
37+ */
38+
39+#define DEBUG 0
40+
41+#include <linux/config.h>
42+#include <linux/version.h>
43+#include <linux/module.h>
44+
45+#include <linux/mm.h>
46+#include <linux/sched.h>
47+#include <linux/delay.h>
48+#include <linux/pci.h>
49+#include <linux/timer.h>
50+#include <asm/io.h>
51+#include <linux/proc_fs.h>
52+#include <linux/sysctl.h>
53+#include <linux/kernel.h>
54+#include <asm/uaccess.h>
55+
56+#define ECC_VER "0.14 (Oct 10 2001)"
57+
58+static struct timer_list ecctimer;
59+static struct pci_dev *bridge = NULL;
60+static u16 vendor, device;
61+static int scrub_needed;
62+static int scrub_row;
63+
64+/* These are tunable by either module parameter or sysctl */
65+int panic_on_mbe = 1;
66+int log_mbe = 1;
67+int log_sbe = 1;
68+int poll_msec = 1000;
69+
70+#ifdef MODULE
71+MODULE_PARM(panic_on_mbe, "i");
72+MODULE_PARM(log_mbe, "i");
73+MODULE_PARM(log_sbe, "i");
74+MODULE_PARM(poll_msec, "i");
75+#endif
76+
77+#define CTL_ECC 2740
78+
79+static ctl_table ecc_table[] = {
80+ {1, "panic_on_mbe",
81+ &panic_on_mbe, sizeof(int), 0644, NULL, &proc_dointvec},
82+ {2, "log_mbe",
83+ &log_mbe, sizeof(int), 0644, NULL, &proc_dointvec},
84+ {3, "log_sbe",
85+ &log_sbe, sizeof(int), 0644, NULL, &proc_dointvec},
86+ {4, "poll_msec",
87+ &poll_msec, sizeof(int), 0644, NULL, &proc_dointvec},
88+ {0}
89+};
90+
91+static ctl_table ecc_root_table[] = {
92+ {CTL_DEBUG, "ecc", NULL, 0, 0555, ecc_table},
93+ {0}
94+};
95+
96+static struct ctl_table_header *ecc_sysctl_header = NULL;
97+
98+#define MAXBANKS 16
99+
100+#define I860_DUMPCONFIG 0
101+
102+#define mbe_printk(fmt,args...) do { \
103+ if (panic_on_mbe) panic("ECC: MBE " fmt,##args); \
104+ else if (log_mbe) printk(KERN_EMERG "ECC: MBE " fmt,##args); \
105+} while(0)
106+#define sbe_printk(fmt,args...) do { \
107+ if (log_sbe) printk(KERN_WARNING "ECC: SBE " fmt,##args); \
108+} while(0)
109+
110+#if defined(NDEBUG)
111+#define assert(EX) do { } while (0)
112+#else
113+#define assert(EX) do { \
114+ if (!(EX)) printk("assertion failed: %s, %s::%d\n", \
115+ #EX, __FILE__, __LINE__); \
116+ } while (0)
117+#endif
118+
119+/* memory types */
120+#define BANK_EMPTY 0 /* Empty bank */
121+#define BANK_RESERVED 1 /* Reserved bank type */
122+#define BANK_UNKNOWN 2 /* Unknown bank type */
123+#define BANK_FPM 3 /* Fast page mode */
124+#define BANK_EDO 4 /* Extended data out */
125+#define BANK_BEDO 5 /* Burst Extended data out */
126+#define BANK_SDR 6 /* Single data rate SDRAM */
127+#define BANK_DDR 7 /* Double data rate SDRAM */
128+#define BANK_RDR 8 /* Registered SDRAM */
129+#define BANK_RMBS 9 /* Rambus DRAM */
130+
131+/* Memory bank info */
132+static struct bankstruct
133+{
134+ u32 endaddr; /* bank ending address */
135+ u32 mbecount; /* total number of MBE errors */
136+ u32 sbecount; /* total number of SBE errors */
137+ u8 eccmode; /* ECC enabled for this bank? */
138+ u8 mtype; /* memory bank type */
139+} bank[MAXBANKS]; /* do any chipsets support more? */
140+
141+/* chipset ECC capabilities and mode */
142+#define ECC_NONE 0 /* Doesnt support ECC (or is BIOS disabled) */
143+#define ECC_RESERVED 1 /* Reserved ECC type */
144+#define ECC_PARITY 2 /* Detects parity errors */
145+#define ECC_DETECT 3 /* Detects ECC errors */
146+#define ECC_CORRECT 4 /* Detects ECC errors and corrects SBE */
147+#define ECC_AUTO 5 /* Detects ECC errors and has hardware scrubber */
148+
149+static struct ChipsetInfo
150+{
151+ int ecc_cap; /* chipset ECC capabilities */
152+ int ecc_mode; /* current ECC mode */
153+ void (*check)(void); /* pointer to ecc checking routine */
154+ void (*clear_err)(void);/* pointer to error clear routine */
155+#if 0
156+/*
157+ * I dont think we care about SERR at the moment.
158+ * We may if/when we hook into an NMI handler.
159+ */
160+ int SERR; /* SERR enabled? */
161+ int SERR_MBE; /* SERR on multi-bit error? */
162+ int SERR_SBE; /* SERR on single-bit error? */
163+#endif
164+ int MBE_flag_address; /* pci offset for mbe register */
165+ int MBE_flag_shift; /* bits to shift for mbe flag */
166+ int MBE_flag_mask; /* mask for mbe flag */
167+ int MBE_row_shift; /* bits to shift for mbe row flag */
168+ int MBE_row_mask; /* mask for mbe register (shifted) */
169+ int SBE_flag_address; /* pci offset for sbe register */
170+ int SBE_flag_shift; /* bits to shift for sbe flag */
171+ int SBE_flag_mask; /* mask for sbe flag */
172+ int SBE_row_shift; /* bits to shift for sbe row flag */
173+ int SBE_row_mask; /* mask for sbe register (shifted) */
174+ int MBE_err_address1; /* pci offset for mbe address register */
175+ int MBE_err_shift1; /* bits to shift for mbe address register */
176+ int MBE_err_address2; /* pci offset for mbe address register */
177+ int MBE_err_shift2; /* bits to shift for mbe address register */
178+ u32 MBE_err_mask; /* mask for mbe address register */
179+ int MBE_err_flag; /* MBE error flag */
180+ int MBE_err_row; /* MBE row */
181+ u32 MBE_addr; /* address of last MBE */
182+ int SBE_err_address1; /* pci offset for mbe address register */
183+ int SBE_err_shift1; /* bits to shift for mbe address register */
184+ int SBE_err_address2; /* pci offset for mbe address register */
185+ int SBE_err_shift2; /* bits to shift for mbe address register */
186+ u32 SBE_err_mask; /* mask for mbe address register */
187+ int SBE_err_flag; /* SBE error flag */
188+ int SBE_err_row; /* SBE row */
189+ u32 SBE_addr; /* address of last SBE */
190+} cs;
191+
192+static inline unsigned int pci_byte(int offset)
193+{
194+ u8 value;
195+ pci_read_config_byte(bridge, offset, &value);
196+ return value & 0xFF;
197+}
198+
199+static inline unsigned int pci_word(int offset)
200+{
201+ u16 value;
202+ pci_read_config_word(bridge, offset, &value);
203+ return value;
204+}
205+
206+static inline unsigned int pci_dword(int offset)
207+{
208+ u32 value;
209+ pci_read_config_dword(bridge, offset, &value);
210+ return value;
211+}
212+
213+/* write all or some bits in a byte-register*/
214+static inline void pci_write_bits8(int offset,u8 value,u8 mask)
215+{
216+ if (mask != 0xff){
217+ u8 buf;
218+ pci_read_config_byte(bridge,offset, &buf);
219+ value &=mask;
220+ buf &= ~mask;
221+ value |= buf;
222+ }
223+ pci_write_config_byte(bridge,offset,value);
224+}
225+
226+static int find_row(unsigned long err_addr)
227+{
228+ int row = 0, loop;
229+ for(loop=0; loop < MAXBANKS; loop++) {
230+ if (err_addr < bank[loop].endaddr) {
231+ row=loop;
232+ break;
233+ }
234+ }
235+ return row;
236+}
237+
238+/*
239+ * generic ECC check routine
240+ *
241+ * This routine assumes that the MBE and SBE error status consist of:
242+ * * one or more bits in a status byte that are non-zero on error
243+ * * zero or more bits in a status byte that encode the row
244+ * It accomodates both the case where both the MBE and SBE data are
245+ * packed into a single byte (all chipsets currently known to me) as
246+ * well as the case where the MBE and SBE information are contained in
247+ * separate locations. The status byte is read only once for the packed
248+ * case in case the status value should be altered by being read.
249+ */
250+static void generic_check(void)
251+{
252+ int status = pci_byte(cs.MBE_flag_address);
253+ if ((status >> cs.MBE_flag_shift) & cs.MBE_flag_mask)
254+ {
255+ int row = (status >> cs.MBE_row_shift) & cs.MBE_row_mask;
256+ mbe_printk("detected in DRAM row %d\n", row);
257+ if (cs.MBE_err_address1)
258+ {
259+ cs.MBE_addr =
260+ ( pci_word(cs.MBE_err_address1 << cs.MBE_err_shift1) |
261+ pci_word(cs.MBE_err_address2 << cs.MBE_err_shift2) ) &
262+ cs.MBE_err_mask;
263+ mbe_printk("at memory address %lx\n", (long unsigned int)cs.MBE_addr);
264+ }
265+ scrub_needed = 2;
266+ scrub_row = row;
267+ bank[row].mbecount++;
268+ }
269+ if (cs.SBE_flag_address != cs.MBE_flag_address)
270+ status = pci_byte(cs.SBE_flag_address);
271+ if ((status >> cs.SBE_flag_shift) & cs.SBE_flag_mask)
272+ {
273+ int row = (status >> cs.SBE_row_shift) & cs.SBE_row_mask;
274+ sbe_printk("detected in DRAM row %d\n", row);
275+ if (cs.SBE_err_address1)
276+ {
277+ cs.SBE_addr =
278+ ( pci_word(cs.SBE_err_address1 << cs.SBE_err_shift1) |
279+ pci_word(cs.SBE_err_address2 << cs.SBE_err_shift2) ) &
280+ cs.SBE_err_mask;
281+ sbe_printk("at memory address %lx\n", (long unsigned int)cs.SBE_addr);
282+ }
283+ scrub_needed = 1;
284+ scrub_row = row;
285+ bank[row].sbecount++;
286+ }
287+}
288+
289+/* VIA specific error clearing */
290+static void clear_via_err(void)
291+{
292+ pci_write_bits8(0x6f,0xff,0xff);
293+ /* as scrubbing is unimplemented, we reset it here */
294+ scrub_needed = 0;
295+}
296+
297+/* unified VIA probe */
298+static void probe_via(void)
299+{
300+ int loop, ecc_ctrl, dimmslots = 3, bankshift = 23;
301+ int m_mem[] = { BANK_FPM, BANK_EDO, BANK_DDR, BANK_SDR };
302+ switch (device) {
303+ case 0x0391: /* VIA VT8371 - KX133 */
304+ dimmslots = 4;
305+ bankshift = 24;
306+ bank[6].endaddr=(unsigned long)pci_byte(0x56)<<24;
307+ bank[7].endaddr=(unsigned long)pci_byte(0x57)<<24;
308+ case 0x0595: /* VIA VT82C595 - VP2,VP2/97 */
309+ m_mem[2] = BANK_RESERVED;
310+ cs.ecc_cap = ECC_CORRECT;
311+ break;
312+ case 0x0501: /* VIA VT8501 - MVP4 */
313+ case 0x0597: /* VIA VT82C597 - VP3 */
314+ case 0x0598: /* VIA VT82C598 - MVP3 */
315+ cs.ecc_cap = ECC_CORRECT;
316+ break;
317+ case 0x0694: /* VIA VT82C694XDP - Apollo PRO133A smp */
318+ dimmslots = 4;
319+ case 0x0691: /* VIA VT82C691 - Apollo PRO */
320+ /* VIA VT82C693A - Apollo Pro133 (rev 40?) */
321+ /* VIA VT82C694X - Apollo Pro133A (rev 8x,Cx)
322+ has 4 dimm slots */
323+ case 0x0693: /* VIA VT82C693 - Apollo PRO-Plus */
324+ bankshift = 24;
325+ cs.ecc_cap = ECC_CORRECT;
326+ break;
327+ case 0x0305: /* VIA VT8363 - KT133 - no ecc!! */
328+ /* VIA VT8363A - KT133A (rev 8) - no ecc!! */
329+ bankshift = 24;
330+ cs.ecc_cap = ECC_NONE;
331+ break;
332+ case 0x0585: /* VIA VT82C585 - VP,VPX,VPX/97 */
333+ default:
334+ cs.ecc_cap = ECC_NONE;
335+ return;
336+ }
337+ ecc_ctrl = pci_byte(0x6E);
338+ cs.ecc_mode = (ecc_ctrl>>7)&1 ? cs.ecc_cap : ECC_NONE;
339+
340+ cs.check = generic_check;
341+ if (cs.ecc_mode != ECC_NONE) {
342+ cs.clear_err = clear_via_err;
343+ /* clear initial errors */
344+ cs.clear_err();
345+ }
346+ cs.MBE_flag_address = 0x6F;
347+ cs.MBE_flag_shift = 7;
348+ cs.MBE_flag_mask = 1;
349+ cs.MBE_row_shift = 4;
350+ cs.MBE_row_mask = 7;
351+ cs.SBE_flag_address = 0x6F;
352+ cs.SBE_flag_shift = 3;
353+ cs.SBE_flag_mask = 1;
354+ cs.SBE_row_shift = 0;
355+ cs.SBE_row_mask = 7;
356+
357+ for(loop=0;loop<6;loop++)
358+ bank[loop].endaddr = (unsigned long)pci_byte(0x5a+loop)<<bankshift;
359+ for(loop=0;loop<dimmslots;loop++)
360+ {
361+ bank[loop*2].mtype = m_mem[(pci_byte(0x60)>>(loop*2))&3];
362+ bank[(loop*2)+1].mtype = m_mem[(pci_byte(0x60)>>(loop*2))&3];
363+ bank[loop*2].eccmode = (ecc_ctrl>>(loop))&1;
364+ bank[(loop*2)+1].eccmode = (ecc_ctrl>>(loop))&1;
365+ }
366+}
367+
368+static void check_serverworks(void)
369+{
370+ unsigned long mesr;
371+ int row;
372+
373+ mesr = pci_dword(0x94); /* mesr0 */
374+ row = (int)(mesr>>29)&0x7;
375+ if((mesr>>31)&1)
376+ {
377+ mbe_printk("Detected in DRAM row %d\n", row);
378+ scrub_needed |= 2;
379+ bank[row].mbecount++;
380+ }
381+ if((mesr>>30)&1)
382+ {
383+ sbe_printk("Detected in DRAM row %d\n", row);
384+ scrub_needed |= 1;
385+ bank[row].sbecount++;
386+ }
387+ if (scrub_needed)
388+ {
389+ /*
390+ * clear error flag bits that were set by writing 1 to them
391+ * we hope the error was a fluke or something :)
392+ */
393+ unsigned long value = scrub_needed<<30;
394+ pci_write_config_dword(bridge, 0x94, value);
395+ scrub_needed = 0;
396+ }
397+
398+ mesr = pci_dword(0x98); /* mesr1 */
399+ row = (int)(mesr>>29)&0x7;
400+ if((mesr>>31)&1)
401+ {
402+ mbe_printk("Detected in DRAM row %d\n", row);
403+ scrub_needed |= 2;
404+ bank[row].mbecount++;
405+ }
406+ if((mesr>>30)&1)
407+ {
408+ sbe_printk("Detected in DRAM row %d\n", row);
409+ scrub_needed |= 1;
410+ bank[row].sbecount++;
411+ }
412+ if (scrub_needed)
413+ {
414+ /*
415+ * clear error flag bits that were set by writing 1 to them
416+ * we hope the error was a fluke or something :)
417+ */
418+ unsigned long value = scrub_needed<<30;
419+ pci_write_config_dword(bridge, 0x98, value);
420+ scrub_needed = 0;
421+ }
422+}
423+
424+static void probe_serverworks(void)
425+{
426+ int loop, efcr, mccr;
427+ switch (device) {
428+ case 0x0008: /* serverworks iii he */
429+ case 0x0009: /* serverworks iii le */
430+ cs.ecc_cap = ECC_AUTO;
431+ break;
432+ default:
433+ cs.ecc_cap = ECC_NONE;
434+ return;
435+ }
436+ efcr = pci_byte(0xE0);
437+ mccr = pci_word(0x92);
438+ cs.ecc_mode = (efcr>>2)&1 ? (mccr&1 ? ECC_AUTO : ECC_CORRECT) : ECC_NONE;
439+
440+ cs.check = check_serverworks;
441+
442+ for(loop=0;loop<8;loop++)
443+ {
444+ bank[loop].mtype = BANK_UNKNOWN;
445+ bank[loop].eccmode = cs.ecc_mode;
446+ bank[loop].endaddr = 0;
447+ }
448+}
449+
450+/*
451+ * 450gx probing is buggered at the moment. help me obi-wan.
452+ */
453+static void probe_450gx(void)
454+{
455+ int loop, dramc, merrcmd;
456+ u32 nbxcfg;
457+ int m_mem[] = { BANK_EDO, BANK_SDR, BANK_RDR, BANK_RESERVED };
458+/* int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_AUTO }; */
459+ nbxcfg = pci_dword(0x50);
460+ dramc = pci_byte(0x57);
461+ merrcmd = pci_word(0xC0);
462+ for(loop=0;loop<8;loop++)
463+ {
464+ bank[loop].endaddr=(unsigned long)pci_byte(0x60+loop)<<23;
465+ /* 450gx doesnt allow mixing memory types. bleah. */
466+ bank[loop].mtype = m_mem[(dramc>>3)&3];
467+ /* yes, bit is _zero_ if ecc is _enabled_. */
468+ bank[loop].eccmode = !((nbxcfg>>(loop+24))&1);
469+ }
470+ cs.ecc_cap = ECC_AUTO;
471+ cs.ecc_mode = (merrcmd>>1)&1 ? ECC_AUTO : ECC_DETECT;
472+
473+ cs.check = generic_check;
474+ cs.MBE_flag_address = 0xC2;
475+ cs.MBE_flag_shift = 0;
476+ cs.MBE_flag_mask = 1;
477+ cs.MBE_row_shift = 5;
478+ cs.MBE_row_mask = 7;
479+ cs.SBE_flag_address = 0xC2;
480+ cs.SBE_flag_shift = 1;
481+ cs.SBE_flag_mask = 1;
482+ cs.SBE_row_shift = 1;
483+ cs.SBE_row_mask = 7;
484+
485+ cs.MBE_err_address1 = 0xA8;
486+ cs.MBE_err_shift1 = 0;
487+ cs.MBE_err_address2 = 0xAA;
488+ cs.MBE_err_shift2 = 16;
489+ cs.MBE_err_mask = 0xFFFFFFFC;
490+
491+ cs.SBE_err_address1 = 0x74;
492+ cs.SBE_err_shift1 = 0;
493+ cs.SBE_err_address2 = 0x76;
494+ cs.SBE_err_shift2 = 16;
495+ cs.SBE_err_mask = 0xFFFFFFFC;
496+}
497+
498+/* there seems to be NO WAY to distinguish 440zx from 440bx!! >B( */
499+static void probe_440bx(void)
500+{
501+ int loop, dramc, errcmd;
502+ u32 nbxcfg;
503+ int m_mem[] = { BANK_EDO, BANK_SDR, BANK_RDR, BANK_RESERVED };
504+ int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_AUTO };
505+ nbxcfg = pci_dword(0x50);
506+ dramc = pci_byte(0x57);
507+ errcmd = pci_byte(0x90);
508+ cs.ecc_cap = ECC_AUTO;
509+ cs.ecc_mode = ddim[(nbxcfg>>7)&3];
510+
511+ cs.check = generic_check;
512+ cs.MBE_flag_address = 0x91;
513+ cs.MBE_flag_shift = 4;
514+ cs.MBE_flag_mask = 1;
515+ cs.MBE_row_shift = 5;
516+ cs.MBE_row_mask = 7;
517+ cs.SBE_flag_address = 0x91;
518+ cs.SBE_flag_shift = 0;
519+ cs.SBE_flag_mask = 1;
520+ cs.SBE_row_shift = 1;
521+ cs.SBE_row_mask = 7;
522+
523+ cs.MBE_err_address1 = 80;
524+ cs.MBE_err_shift1 = 0;
525+ cs.MBE_err_address2 = 82;
526+ cs.MBE_err_shift2 = 16;
527+ cs.MBE_err_mask = 0xFFFFF000;
528+
529+ cs.SBE_err_address1 = 80;
530+ cs.SBE_err_shift1 = 0;
531+ cs.SBE_err_address2 = 82;
532+ cs.SBE_err_shift2 = 16;
533+ cs.SBE_err_mask = 0xFFFFF000;
534+
535+ for(loop=0;loop<8;loop++)
536+ {
537+ bank[loop].endaddr=(unsigned long)pci_byte(0x60+loop)<<23;
538+ /* 440bx doesnt allow mixing memory types. bleah. */
539+ bank[loop].mtype = m_mem[(dramc>>3)&3];
540+ /* yes, bit is _zero_ if ecc is _enabled_. */
541+ bank[loop].eccmode = !((nbxcfg>>(loop+24))&1);
542+ }
543+}
544+
545+/* no way to tell 440ex from 440lx!? grr. */
546+static void probe_440lx(void)
547+{
548+ int loop, drt, paccfg, errcmd;
549+ int m_mem[] = { BANK_EDO, BANK_RESERVED, BANK_SDR, BANK_EMPTY };
550+ int ddim[] = { ECC_NONE, ECC_DETECT, ECC_RESERVED, ECC_CORRECT } ;
551+ paccfg = pci_word(0x50);
552+ drt = pci_byte(0x55) | (pci_byte(0x56)<<8);
553+ errcmd = pci_byte(0x90);
554+ /* 440ex doesnt support ecc, but no way to tell if its 440ex! */
555+ cs.ecc_cap = ECC_CORRECT;
556+ cs.ecc_mode = ddim[(paccfg>>7)&3];
557+
558+ cs.check = generic_check;
559+ cs.MBE_flag_address = 0x91;
560+ cs.MBE_flag_shift = 4;
561+ cs.MBE_flag_mask = 1;
562+ cs.MBE_row_shift = 5;
563+ cs.MBE_row_mask = 7;
564+ cs.SBE_flag_address = 0x91;
565+ cs.SBE_flag_shift = 0;
566+ cs.SBE_flag_mask = 1;
567+ cs.SBE_row_shift = 1;
568+ cs.SBE_row_mask = 7;
569+
570+ for(loop=0;loop<8;loop++)
571+ {
572+ bank[loop].endaddr = (unsigned long)pci_byte(0x60+loop)<<23;
573+ bank[loop].mtype = m_mem[(drt>>(loop*2))&3];
574+ bank[loop].eccmode = (cs.ecc_mode != 0);
575+ }
576+}
577+
578+static void probe_440fx(void)
579+{
580+ int loop, drt, pmccfg, errcmd;
581+ int m_mem[] = { BANK_FPM, BANK_EDO, BANK_BEDO, BANK_EMPTY };
582+ int ddim[] = { ECC_NONE, ECC_PARITY, ECC_DETECT, ECC_CORRECT };
583+ pmccfg = pci_word(0x50);
584+ drt = pci_byte(0x55) | (pci_byte(0x56)<<8);
585+ errcmd = pci_byte(0x90);
586+ for(loop=0;loop<8;loop++)
587+ {
588+ bank[loop].endaddr=(unsigned long)pci_byte(0x60+loop)<<23;
589+ bank[loop].mtype = m_mem[(drt>>(loop*2))&3];
590+ }
591+ cs.ecc_cap = ECC_CORRECT;
592+ cs.ecc_mode = ddim[(pmccfg>>4)&3];
593+
594+ cs.check = generic_check;
595+ cs.MBE_flag_address = 0x91;
596+ cs.MBE_flag_shift = 4;
597+ cs.MBE_flag_mask = 1;
598+ cs.MBE_row_shift = 5;
599+ cs.MBE_row_mask = 7;
600+ cs.SBE_flag_address = 0x91;
601+ cs.SBE_flag_shift = 0;
602+ cs.SBE_flag_mask = 1;
603+ cs.SBE_row_shift = 1;
604+ cs.SBE_row_mask = 7;
605+}
606+
607+static void probe_430hx(void)
608+{
609+ int pcicmd, pcon, errcmd, drt, loop;
610+ pcicmd = pci_word(0x4);
611+ pcon = pci_byte(0x50);
612+ drt = pci_byte(0x68);
613+ errcmd = pci_byte(0x90);
614+ cs.ecc_cap = ECC_CORRECT;
615+ cs.ecc_mode = (pcon>>7)&1 ? ECC_CORRECT : ECC_PARITY;
616+
617+ cs.check = generic_check;
618+ cs.MBE_flag_address = 0x91;
619+ cs.MBE_flag_shift = 4;
620+ cs.MBE_flag_mask = 1;
621+ cs.MBE_row_shift = 5;
622+ cs.MBE_row_mask = 7;
623+ cs.SBE_flag_address = 0x91;
624+ cs.SBE_flag_shift = 0;
625+ cs.SBE_flag_mask = 1;
626+ cs.SBE_row_shift = 1;
627+ cs.SBE_row_mask = 7;
628+
629+ for(loop=0;loop<8;loop++)
630+ {
631+ bank[loop].endaddr=(unsigned long)pci_byte(0x60+loop)<<22;
632+ bank[loop].mtype = (drt>>loop)&1 ? BANK_EDO : BANK_FPM;
633+ bank[loop].eccmode = cs.ecc_mode;
634+ }
635+}
636+
637+static void check_840(void)
638+{
639+ int errsts = pci_word(0xE2);
640+ if ((errsts>>9) & 1)
641+ {
642+ u32 eap = pci_dword(0xE4) & 0xFFFFF800;
643+ mbe_printk("at memory address %lx\n row %d syndrome %x",
644+ (long unsigned int)eap, find_row(eap), errsts&0xFF);
645+ scrub_needed = 2;
646+ scrub_row = find_row(eap);
647+ bank[scrub_row].mbecount++;
648+ }
649+ if ((errsts>>10) & 1)
650+ {
651+ u32 eap = pci_dword(0xE4) & 0xFFFFF800;
652+ sbe_printk("at memory address %lx row %d syndrome %x\n",
653+ (long unsigned int)eap, find_row(eap), errsts&0xFF);
654+ scrub_needed = 1;
655+ scrub_row = find_row(eap);
656+ bank[scrub_row].sbecount++;
657+ }
658+}
659+
660+static void probe_840(void)
661+{
662+ int loop, mchcfg;
663+ int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_AUTO };
664+ mchcfg = pci_word(0x50);
665+ cs.ecc_cap = ECC_AUTO;
666+ cs.ecc_mode = ddim[(mchcfg>>7)&3];
667+
668+ cs.check = check_840;
669+
670+ for(loop=0;loop<16;loop++)
671+ {
672+ bank[loop].endaddr=(unsigned long)pci_word(0x60+(loop*2))<<23;
673+ bank[loop].mtype = BANK_RMBS;
674+ bank[loop].eccmode = cs.ecc_mode;
675+ }
676+}
677+
678+static void check_845(void)
679+{
680+ int errsts = pci_word(0xC8);
681+ if ((errsts>>1) & 1)
682+ {
683+ u32 eap = (pci_dword(0x8C) & 0xFFFFFFFE)<<4;
684+ char derrsyn = pci_byte(0x86);
685+ mbe_printk("at memory address %lx\n row %d syndrome %x",
686+ (long unsigned int)eap, find_row(eap), derrsyn);
687+ scrub_needed = 2;
688+ scrub_row = find_row(eap);
689+ bank[scrub_row].mbecount++;
690+ }
691+ if (errsts & 1)
692+ {
693+ u32 eap = (pci_dword(0x8C) & 0xFFFFFFFE)<<4;
694+ char derrsyn = pci_byte(0x86);
695+ sbe_printk("at memory address %lx row %d syndrome %x\n",
696+ (long unsigned int)eap, find_row(eap), derrsyn);
697+ scrub_needed = 1;
698+ scrub_row = find_row(eap);
699+ bank[scrub_row].sbecount++;
700+ }
701+}
702+
703+static void probe_845(void)
704+{
705+ int loop;
706+ u32 drc;
707+ int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
708+ drc = pci_dword(0x7C);
709+ cs.ecc_cap = ECC_CORRECT;
710+ cs.ecc_mode = ddim[(drc>>19)&3];
711+
712+ cs.check = check_845;
713+
714+ for(loop=0;loop<8;loop++)
715+ {
716+ bank[loop].endaddr=(unsigned long)pci_byte(0x60+loop)<<24;
717+ bank[loop].mtype = BANK_SDR;
718+ bank[loop].eccmode = cs.ecc_mode;
719+ }
720+}
721+
722+static void check_850(void)
723+{
724+ int errsts = pci_word(0xC8);
725+ if ((errsts>>1) & 1)
726+ {
727+ u32 eap = pci_dword(0xE4) & 0xFFFFE000;
728+ char derrsyn = pci_word(0xE2) & 0x7F;
729+ mbe_printk("at memory address %lx\n row %d syndrome %x",
730+ (long unsigned int)eap, find_row(eap), derrsyn);
731+ scrub_needed = 2;
732+ scrub_row = find_row(eap);
733+ bank[scrub_row].mbecount++;
734+ }
735+ if (errsts & 1)
736+ {
737+ u32 eap = pci_dword(0xE4) & 0xFFFFE000;
738+ char derrsyn = pci_byte(0xE2) & 0x7F;
739+ sbe_printk("at memory address %lx row %d syndrome %x\n",
740+ (long unsigned int)eap, find_row(eap), derrsyn);
741+ scrub_needed = 1;
742+ scrub_row = find_row(eap);
743+ bank[scrub_row].sbecount++;
744+ }
745+}
746+
747+static void probe_850(void)
748+{
749+ int loop;
750+ int mchcfg;
751+ int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
752+ mchcfg = pci_word(0x50);
753+ cs.ecc_cap = ECC_CORRECT;
754+ cs.ecc_mode = ddim[(mchcfg>>7)&3];
755+
756+ cs.check = check_850;
757+
758+ for(loop=0;loop<16;loop++)
759+ {
760+ bank[loop].endaddr=(unsigned long)pci_word(0x60+(loop*2))<<23;
761+ bank[loop].mtype = BANK_RMBS;
762+ bank[loop].eccmode = cs.ecc_mode;
763+ }
764+}
765+
766+/* 860 specific error clearing */
767+static void clear_860_err(void)
768+{
769+ pci_write_bits8(0xc8,0x03,0x03);
770+ /* as scrubbing is unimplemented, we reset it here */
771+ scrub_needed = 0;
772+ cs.clear_err = 0;
773+}
774+
775+static void check_860(void)
776+{
777+ int errsts = pci_word(0xC8);
778+ if ((errsts>>1) & 1)
779+ {
780+ u32 eap = (pci_dword(0xE4) & 0xFFFFFE00)<<2;
781+ int channel = pci_dword(0xE4) & 1;
782+ unsigned char derrsyn = pci_word(0xE2) & 0xFF;
783+ mbe_printk("at memory address %08lx row %d syndrome %02x channel=%s\n",
784+ (long unsigned int)eap, find_row(eap), derrsyn, channel==0?"A":"B");
785+ scrub_needed = 2;
786+ scrub_row = find_row(eap);
787+ bank[scrub_row].mbecount++;
788+ cs.clear_err = clear_860_err;
789+ }
790+ if (errsts & 1)
791+ {
792+ u32 eap = (pci_dword(0xE4) & 0xFFFFFE00)<<2;
793+ int channel = pci_dword(0xE4) & 1;
794+ unsigned char derrsyn = pci_byte(0xE2) & 0xFF;
795+ sbe_printk("at memory address %08lx row %d syndrome %02x channel=%s\n",
796+ (long unsigned int)eap, find_row(eap), derrsyn, channel==0?"A":"B");
797+ scrub_needed = 1;
798+ scrub_row = find_row(eap);
799+ bank[scrub_row].sbecount++;
800+ cs.clear_err = clear_860_err;
801+ }
802+ /*
803+ * We should catch other error bits, however we need to add code
804+ * to clear them if we want to continue on (otherwise we will report
805+ * the same error on every poll). Having never seen other bits set
806+ * on our systems, just panic for now. -jg
807+ */
808+ if (errsts & 0xfc)
809+ panic("ECC: MCH ERRSTS register contains 0x%x\n", errsts);
810+}
811+
812+#if I860_DUMPCONFIG
813+void info_860(void)
814+{
815+ int i;
816+
817+ printk("RDRAM Device Group Architecture Registers (16): \n");
818+ for (i = 0; i < 16; i++) {
819+ printk("GAR[%d]=%-2.2x ", i, pci_byte(0x40 + i));
820+ if ((i + 1) % 4 == 0)
821+ printk("\n");
822+ }
823+ printk("MCH Configuration Register: MCHCFG=%-4.4x\n", pci_word(0x50));
824+ printk("Fixed DRAM Hole Control Register: FDHC=%-2.2x\n",
825+ pci_byte(0x58));
826+ printk("Programmable Attribute Map Registers (7):\n");
827+ for (i = 0; i < 7; i++) {
828+ printk("PAM[%d]=%-2.2x ", i, pci_byte(0x59 + i));
829+ if ((i + 1) % 4 == 0)
830+ printk("\n");
831+ }
832+ printk("\n");
833+ printk("RDRAM Device Pool Sizing Register: RDPS=%-2.2x\n",
834+ pci_byte(0x88));
835+ printk("RDRAM Device Init Control Management Register: RICM=%-8.8x\n",
836+ pci_dword(0x94));
837+ printk("System Management RAM Control Register: SMRAM=%-2.2x\n",
838+ pci_byte(0x9D));
839+ printk("Extended System Mgmt RAM Control Register: ESMRAMC=%-2.2x\n",
840+ pci_byte(0x9E));
841+ printk("RDRAM Device Timing Register: RDTR=%-2.2x\n", pci_byte(0xBE));
842+ printk("Top of Low Memory Register: TOM=%-4.4x\n", pci_word(0xC4));
843+ printk("Error Command Register: ERRCMD=%-4.4x\n", pci_word(0xCA));
844+ printk("SMI Command Register: SCICMD=%-4.4x\n", pci_word(0xCC));
845+ printk("SCI Command Register: SCICMD=%-4.4x\n", pci_word(0xCE));
846+ printk("RDRAM Device Refresh Control Register: DRAMRC=%-4.4x\n",
847+ pci_word(0xDC));
848+ printk("Misc. Control Register: MISC_CNTL=%-8.8x\n", pci_dword(0xF4));
849+ printk("PCI Command Register: PCICMD=%-4.4x\n", pci_word(0x04));
850+}
851+#else
852+void info_860(void)
853+{
854+ printk("ECC: Intel 860 MCH probed successfully\n");
855+}
856+#endif
857+
858+static void probe_860(void)
859+{
860+ int loop;
861+ u32 drc;
862+ int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
863+ drc = pci_word(0x50);
864+ cs.ecc_cap = ECC_CORRECT;
865+ cs.ecc_mode = ddim[(drc>>7)&3];
866+
867+ cs.check = check_860;
868+
869+ for(loop=0;loop<MAXBANKS;loop++)
870+ {
871+ bank[loop].endaddr=(unsigned long)pci_word(0x60+(loop*2))<<24;
872+ bank[loop].mtype = BANK_RMBS;
873+ bank[loop].eccmode = cs.ecc_mode;
874+ if (loop > 0) { /* find_bank assumes ascending addresses */
875+ assert(bank[loop].endaddr >= bank[loop-1].endaddr);
876+ }
877+ }
878+ clear_860_err(); /* start off with a clean slate */
879+ info_860();
880+}
881+
882+static void check_amd751(void)
883+{
884+ int eccstat = pci_word(0x58);
885+ int csbits = eccstat & 0x3F;
886+ int row;
887+ switch (csbits)
888+ {
889+ case 1: row = 0; break;
890+ case 2: row = 1; break;
891+ case 4: row = 2; break;
892+ case 8: row = 3; break;
893+ case 16: row = 4; break;
894+ case 32: row = 5; break;
895+ default: row = 6;
896+ }
897+ if(((eccstat>>8)&3) == 1)
898+ {
899+ mbe_printk("Detected in DRAM row %d\n", row);
900+ scrub_needed=2;
901+ bank[row].mbecount++;
902+ }
903+ if(((eccstat>>8)&3) == 2)
904+ {
905+ sbe_printk("Detected in DRAM row %d\n", row);
906+ scrub_needed=1;
907+ bank[row].sbecount++;
908+ }
909+ if(((eccstat>>8)&3) == 3)
910+ {
911+ mbe_printk("and SBE Detected in DRAM row %d\n", row);
912+ scrub_needed=1;
913+ bank[row].sbecount++;
914+ }
915+ if (scrub_needed)
916+ {
917+ /*
918+ * clear error flag bits that were set by writing 0 to them
919+ * we hope the error was a fluke or something :)
920+ */
921+ int value = eccstat & 0xFCFF;
922+ pci_write_config_word(bridge, 0x58, value);
923+ scrub_needed = 0;
924+ }
925+}
926+
927+static void probe_amd751(void)
928+{
929+ int loop;
930+ cs.ecc_cap = ECC_CORRECT;
931+ cs.ecc_mode = (pci_byte(0x5a)>>2)&1 ? ECC_CORRECT : ECC_NONE;
932+ cs.check = check_amd751;
933+ for(loop=0;loop<6;loop++)
934+ {
935+ unsigned flag = pci_byte(0x40+loop*2);
936+ /* bank address mask. */
937+ unsigned mask = (flag&0x7F)>>1;
938+ /* actually starting address */
939+ bank[loop].endaddr=(unsigned long)(pci_word(0x40+loop*2)&0xFF80)<<(23-7);
940+ /* only when bank is populated */
941+ if((flag&1)&&(mask!=0)){
942+ /* mask+1 * 8mb appears to be bank size */
943+ bank[loop].endaddr += (mask + 1) * 8 * (1024 * 1024); /* -1? */
944+ }
945+ bank[loop].mtype = flag&1 ? BANK_SDR : BANK_EMPTY;
946+ /* no per-bank register, assumed same for all banks? */
947+ bank[loop].eccmode = (pci_byte(0x5a)>>2)&1;
948+ }
949+}
950+
951+static void check_amd76x(void)
952+{
953+ unsigned long eccstat = pci_dword(0x48);
954+ if(eccstat & 0x10)
955+ {
956+ /* bits 7-4 of eccstat indicate the row the MBE occurred. */
957+ int row = (eccstat >> 4) & 0xf;
958+ mbe_printk("Detected in DRAM row %d\n", row);
959+ scrub_needed |= 2;
960+ bank[row].mbecount++;
961+ }
962+ if(eccstat & 0x20)
963+ {
964+ /* bits 3-0 of eccstat indicate the row the SBE occurred. */
965+ int row = eccstat & 0xf;
966+ sbe_printk("Detected in DRAM row %d\n", row);
967+ scrub_needed |= 1;
968+ bank[row].sbecount++;
969+ }
970+ if (scrub_needed)
971+ {
972+ /*
973+ * clear error flag bits that were set by writing 0 to them
974+ * we hope the error was a fluke or something :)
975+ */
976+ unsigned long value = eccstat;
977+ if (scrub_needed & 1)
978+ value &= 0xFFFFFDFF;
979+ if (scrub_needed & 2)
980+ value &= 0xFFFFFEFF;
981+ pci_write_config_dword(bridge, 0x48, value);
982+ scrub_needed = 0;
983+ }
984+}
985+
986+static void probe_amd76x(void)
987+{
988+ static const int modetab[] = {ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_AUTO};
989+ int loop;
990+ unsigned long addr = 0;
991+ cs.ecc_cap = ECC_AUTO;
992+ cs.ecc_mode = modetab [(pci_dword(0x48)>>10)&3];
993+ cs.check = check_amd76x;
994+
995+ /* create fake end addresses, as the chipset is capable of
996+ matching addresses to banks in random order */
997+ for(loop=0;loop<8;loop++)
998+ {
999+ unsigned long r = pci_dword(0xc0+(loop*4));
1000+ bank[loop].mtype = r & 1 ? BANK_DDR : BANK_EMPTY;
1001+ if (r & 1)
1002+ addr += ((r & 0xff80) << 16) + 0x800000;
1003+ bank[loop].endaddr=addr;
1004+ /* no per-bank register, assumed same for all banks? */
1005+ bank[loop].eccmode = cs.ecc_mode != ECC_NONE;
1006+ }
1007+}
1008+
1009+/* SiS */
1010+void probe_sis(void)
1011+{
1012+ int loop;
1013+ u32 endaddr;
1014+ int m_mem[] = { BANK_FPM, BANK_EDO, BANK_RESERVED, BANK_SDR };
1015+ int dramsize[] = { 256, 1024, 4096, 16384, 1024, 2048, 4096,
1016+ 8192, 512, 1024, 2048, 0, 0, 0, 0, 0 };
1017+ int sdramsize[] = { 1024, 4096, 4096, 8192, 2048, 8192,
1018+ 8192, 16384, 4096, 16384, 16384, 32768, 2048, 0, 0, 0 };
1019+
1020+ cs.ecc_cap = ECC_CORRECT;
1021+
1022+ cs.check = generic_check;
1023+
1024+ cs.MBE_flag_address = 0x64;
1025+ cs.MBE_flag_shift = 4;
1026+ cs.MBE_flag_mask = 1;
1027+ cs.MBE_row_shift = 5;
1028+ cs.MBE_row_mask = 7;
1029+
1030+ cs.SBE_flag_address = 0x64;
1031+ cs.SBE_flag_shift = 3;
1032+ cs.SBE_flag_mask = 1;
1033+ cs.SBE_row_shift = 5;
1034+ cs.SBE_row_mask = 7;
1035+
1036+ cs.MBE_err_address1 = 0x64;
1037+ cs.MBE_err_shift1 = 0;
1038+ cs.MBE_err_address2 = 0x66;
1039+ cs.MBE_err_shift2 = 16;
1040+ cs.MBE_err_mask = 0xFFFFF000;
1041+
1042+ cs.SBE_err_address1 = 0x64;
1043+ cs.SBE_err_shift1 = 0;
1044+ cs.SBE_err_address2 = 0x66;
1045+ cs.SBE_err_shift2 = 16;
1046+ cs.MBE_err_mask = 0xFFFFF000;
1047+
1048+ endaddr = 0;
1049+ for(loop=0;loop<3;loop++)
1050+ {
1051+ /* populated bank? */
1052+ if ((pci_byte(0x63)>>loop)&1)
1053+ {
1054+ u32 banksize;
1055+ int mtype = pci_byte(0x60+loop);
1056+
1057+ bank[loop*2].mtype = m_mem[(mtype>>6)&3];
1058+ if(bank[loop*2].mtype == BANK_SDR)
1059+ {
1060+ banksize = sdramsize[mtype&15]*1024;
1061+ } else {
1062+ banksize = dramsize[mtype&15]*1024;
1063+ }
1064+ endaddr += banksize;
1065+ bank[loop*2].endaddr = endaddr;
1066+ /* double sided dimm? */
1067+ if ((mtype>>5)&1)
1068+ {
1069+ bank[(loop*2)+1].mtype = bank[loop*2].mtype;
1070+ endaddr += banksize;
1071+ bank[(loop*2)+1].endaddr = endaddr;
1072+ }
1073+ } else {
1074+ bank[loop*2].mtype = BANK_EMPTY;
1075+ bank[(loop*2)+1].mtype = BANK_EMPTY;
1076+ bank[loop*2].endaddr = endaddr;
1077+ bank[(loop*2)+1].endaddr = endaddr;
1078+ }
1079+ }
1080+ cs.ecc_mode = ECC_NONE;
1081+ for(loop=0;loop<6;loop++)
1082+ {
1083+ int eccmode = (pci_byte(0x74)>>loop)&1;
1084+ bank[loop].eccmode = eccmode;
1085+ if(eccmode)
1086+ cs.ecc_mode = ECC_CORRECT;
1087+ }
1088+}
1089+
1090+/* ALi */
1091+void probe_aladdin4(void)
1092+{
1093+ int loop;
1094+ int m_mem[] = { BANK_FPM, BANK_EDO, BANK_RESERVED, BANK_SDR };
1095+ cs.ecc_cap = ECC_CORRECT;
1096+ cs.ecc_mode = pci_byte(0x49)&1 ? ECC_CORRECT : ECC_PARITY;
1097+
1098+ cs.check = generic_check;
1099+
1100+ cs.MBE_flag_address = 0x4a;
1101+ cs.MBE_flag_shift = 4;
1102+ cs.MBE_flag_mask = 1;
1103+ cs.MBE_row_shift = 5;
1104+ cs.MBE_row_mask = 7;
1105+
1106+ cs.SBE_flag_address = 0x4a;
1107+ cs.SBE_flag_shift = 0;
1108+ cs.SBE_flag_mask = 1;
1109+ cs.SBE_row_shift = 1;
1110+ cs.SBE_row_mask = 7;
1111+
1112+ for(loop=0;loop<8;loop++)
1113+ {
1114+ bank[loop].endaddr = (unsigned long)(pci_byte(0x61+(loop*2))&15)<<27|(pci_byte(0x60+(loop*2))<<20);
1115+ bank[loop].mtype = m_mem[(pci_byte(0x61+(loop*2))>>1)&3];
1116+ if (cs.ecc_mode == ECC_CORRECT) {
1117+ bank[loop].eccmode = 1;
1118+ } else {
1119+ bank[loop].eccmode = 0;
1120+ }
1121+ }
1122+}
1123+
1124+void probe_aladdin5(void)
1125+{
1126+ int loop;
1127+ int m_mem[] = { BANK_FPM, BANK_EDO, BANK_RDR, BANK_SDR };
1128+ cs.ecc_cap = ECC_CORRECT;
1129+ cs.ecc_mode = pci_byte(0x50)&1 ? ECC_CORRECT : ECC_PARITY;
1130+
1131+ cs.check = generic_check;
1132+
1133+ cs.MBE_flag_address = 0x51;
1134+ cs.MBE_flag_shift = 4;
1135+ cs.MBE_flag_mask = 1;
1136+ cs.MBE_row_shift = 5;
1137+ cs.MBE_row_mask = 7;
1138+
1139+ cs.SBE_flag_address = 0x51;
1140+ cs.SBE_flag_shift = 0;
1141+ cs.SBE_flag_mask = 1;
1142+ cs.SBE_row_shift = 1;
1143+ cs.SBE_row_mask = 7;
1144+
1145+ for(loop=0;loop<8;loop++)
1146+ {
1147+ /* DBxCII not disabled address mapping? */
1148+ if(pci_byte(0x61+(loop*2))&0xF0)
1149+ {
1150+ /* endaddr always 1 unit low, granularity 1mb */
1151+ bank[loop].endaddr = (unsigned long)((pci_byte(0x61+(loop*2))&15)<<27|(pci_byte(0x60+(loop*2))<<20))+1048576;
1152+ bank[loop].mtype = m_mem[(pci_byte(0x61+(loop*2))>>1)&3];
1153+ if (cs.ecc_mode == ECC_CORRECT) {
1154+ bank[loop].eccmode = 1;
1155+ } else {
1156+ bank[loop].eccmode = 0;
1157+ }
1158+ }
1159+ }
1160+}
1161+
1162+#if 0
1163+/*
1164+ * memory scrubber routines, not ready to be used yet...
1165+ */
1166+/* start at 16mb */
1167+unsigned long start = 4096;
1168+unsigned long pages = 1;
1169+/* other architectures have different page sizes... */
1170+unsigned long step = 4096;
1171+
1172+char buff[8192] = {0,};
1173+
1174+/*
1175+ * Michael's page scrubber routine
1176+ */
1177+void scrub_page(unsigned long volatile * p)
1178+{
1179+ int i;
1180+ int len, err = 0;
1181+ unsigned long *q;
1182+ q = (unsigned long *) ((((int)buff)+4095) & ~4095);
1183+
1184+ if (((int)p) >= 640 * 1024 && ((int)p) < 1024 * 1024)
1185+ return;
1186+
1187+ cli(); /* kill interrupts */
1188+ err = pci_byte(0x91);
1189+ outb(0x11, PCI_DATA + 1); /* clear the memory error indicator */
1190+
1191+ for (i = 0; i < step / 4 ; ++i)
1192+ q[i] = p[i];
1193+ for (i = 0; i < step / 4 ; ++i)
1194+ p[i] = q[i];
1195+ err = inb(PCI_DATA + 1);
1196+ sti();
1197+ if (err & 0x11) {
1198+ printk(KERN_ERR "ECC: Memory error @ %08x (0x%02x)\n", p, err);
1199+ return 1;
1200+ }
1201+ return 0;
1202+}
1203+
1204+void scrub(void)
1205+{
1206+ int i,j = 0;
1207+ for (i = 0; i < pages; ++i) {
1208+ j = scrub_page(start);
1209+ start += step;
1210+ }
1211+ if (!j) {
1212+ /*
1213+ * Hmm... This is probably a very bad situation.
1214+ */
1215+ printk(KERN_ERR "ECC: Scrubbed, no errors found?!\n");
1216+ scrub_needed=0;
1217+ return;
1218+ }
1219+ if (scrub_needed==2) {
1220+ /*
1221+ * TODO: We should determine what process owns the memory
1222+ * and send a SIGBUS to it. We should also printk something
1223+ * along the lines of
1224+ * "ECC: Process (PID) killed with SIGBUS due to uncorrectable memory error at 0xDEADBEEF"
1225+ */
1226+ scrub_needed=0;
1227+ }
1228+}
1229+#endif
1230+
1231+int unload = 0;
1232+/*
1233+ * Check ECC status every second.
1234+ * SMP safe, doesn't use NMI, and auto-rate-limits.
1235+ */
1236+void checkecc(void) {
1237+ MOD_INC_USE_COUNT;
1238+ if (!scrub_needed)
1239+ if (cs.check)
1240+ cs.check();
1241+ if (cs.clear_err)
1242+ cs.clear_err();
1243+ init_timer(&ecctimer);
1244+ ecctimer.expires = jiffies + (HZ * poll_msec) / 1000;
1245+ ecctimer.function = (void *)&checkecc;
1246+ if (!unload)
1247+ add_timer(&ecctimer);
1248+ MOD_DEC_USE_COUNT;
1249+}
1250+
1251+#ifdef CONFIG_PROC_FS
1252+int procfile_read(char *memstat, char **buffer_location, off_t offset,
1253+ int buffer_length, int *eof, void *data)
1254+{
1255+ char *ecc[] = { "None", "Reserved", "Parity checking", "ECC detection",
1256+ "ECC detection and correction", "ECC with hardware scrubber" };
1257+ char *dram[] = { "Empty", "Reserved", "Unknown", "FPM", "EDO", "BEDO", "SDR",
1258+ "DDR", "RDR", "RMBS" };
1259+ unsigned long mem_end = 0;
1260+ unsigned long last_mem = 0;
1261+ int loop;
1262+ int len = 0;
1263+
1264+ if (offset)
1265+ return 0;
1266+
1267+ len += sprintf(memstat, "Chipset ECC capability : %s\n", ecc[cs.ecc_cap]);
1268+ len += sprintf(memstat + len, "Current ECC mode : %s\n", ecc[cs.ecc_mode]);
1269+ len += sprintf(memstat + len, "Bank\tSize\tType\tECC\tSBE\tMBE\n");
1270+ for (loop=0;loop<MAXBANKS;loop++){
1271+ last_mem=bank[loop].endaddr;
1272+ if (last_mem>mem_end) {
1273+ len += sprintf(memstat + len, "%d\t", loop);
1274+ len += sprintf(memstat + len, "%dM\t", (int)(last_mem-mem_end)/1048576);
1275+ len += sprintf(memstat + len, "%s\t", dram[bank[loop].mtype]);
1276+ len += sprintf(memstat + len, "%s\t", bank[loop].eccmode ? "Y" : "N");
1277+ len += sprintf(memstat + len, "%ld\t", (unsigned long)bank[loop].sbecount);
1278+ len += sprintf(memstat + len, "%ld\n", (unsigned long)bank[loop].mbecount);
1279+ mem_end=last_mem;
1280+ }
1281+ }
1282+ len += sprintf(memstat + len, "Total\t%dM\n", (int)(mem_end>>20));
1283+
1284+ if (len <= buffer_length)
1285+ *eof = 1;
1286+ else
1287+ len = buffer_length;
1288+ return len;
1289+}
1290+#endif
1291+
1292+struct pci_probe_matrix {
1293+ int vendor; /* pci vendor id */
1294+ int device; /* pci device id */
1295+ void (*check)(void); /* pointer to chipset probing routine */
1296+};
1297+
1298+static struct pci_probe_matrix probe_matrix[] = {
1299+ /* AMD */
1300+ { 0x1022, 0x7006, probe_amd751 },
1301+ { 0x1022, 0x700c, probe_amd76x }, /* amd762 2 CPU */
1302+ { 0x1022, 0x700e, probe_amd76x }, /* amd761 1 CPU */
1303+ /* Motorola */
1304+ { 0x1057, 0x4802, 0 }, /* falcon - not yet supported */
1305+ /* Apple */
1306+ { 0x106b, 0x0001, 0 }, /* bandit - not yet supported */
1307+ /* SiS */
1308+ { 0x1039, 0x0600, probe_sis }, /* 600 programatically same as 5600 */
1309+ { 0x1039, 0x0620, 0 }, /* 620 doesnt support ecc */
1310+ { 0x1039, 0x5600, probe_sis },
1311+ /* ALi */
1312+ { 0x10b9, 0x1531, probe_aladdin4 },
1313+ { 0x10b9, 0x1541, probe_aladdin5 },
1314+ /* VIA */
1315+ { 0x1106, 0x0305, probe_via }, /* vt8363 - kt133/km133 */
1316+ { 0x1106, 0x0391, probe_via }, /* vt8371 - kx133 */
1317+ { 0x1106, 0x0501, probe_via }, /* vt8501 - mvp4 */
1318+ { 0x1106, 0x0585, probe_via }, /* vt82c585 - vp/vpx */
1319+ { 0x1106, 0x0595, probe_via }, /* vt82c595 - vp2 */
1320+ { 0x1106, 0x0597, probe_via }, /* vt82c597 - vp3 */
1321+ { 0x1106, 0x0598, probe_via }, /* vt82c598 - mvp3 */
1322+ { 0x1106, 0x0691, probe_via }, /* vt82c691 - pro133/pro133a */
1323+ { 0x1106, 0x0693, probe_via }, /* vt82c693 - pro+ */
1324+ { 0x1106, 0x0694, probe_via }, /* vt82c694 - pro133a */
1325+ /* Serverworks */
1326+ { 0x1166, 0x0008, probe_serverworks }, /* CNB20HE - serverset iii he */
1327+ { 0x1166, 0x0009, probe_serverworks }, /* serverset iii le */
1328+ /* Intel */
1329+ { 0x8086, 0x1130, 0 }, /* 815 doesnt support ecc */
1330+ { 0x8086, 0x122d, 0 }, /* 430fx doesnt support ecc */
1331+ { 0x8086, 0x1237, probe_440fx },
1332+ { 0x8086, 0x1250, probe_430hx },
1333+ { 0x8086, 0x1A21, probe_840 },
1334+ { 0x8086, 0x1A30, probe_845 },
1335+ { 0x8086, 0x2530, probe_850 },
1336+ { 0x8086, 0x2531, probe_860 },
1337+ { 0x8086, 0x7030, 0 }, /* 430vx doesnt support ecc */
1338+ { 0x8086, 0x7120, 0 }, /* 810 doesnt support ecc */
1339+ { 0x8086, 0x7122, 0 },
1340+ { 0x8086, 0x7124, 0 }, /* 810e doesnt support ecc */
1341+ { 0x8086, 0x7180, probe_440lx }, /* also 440ex */
1342+ { 0x8086, 0x7190, probe_440bx }, /* also 440zx */
1343+ { 0x8086, 0x7192, probe_440bx }, /* also 440zx */
1344+ { 0x8086, 0x71A0, probe_440bx }, /* also 440gx */
1345+ { 0x8086, 0x71A2, probe_440bx }, /* also 440gx */
1346+ { 0x8086, 0x84C5, probe_450gx },
1347+ { 0, 0, 0 }
1348+};
1349+
1350+static int find_chipset(void) {
1351+
1352+ if (!pci_present()) {
1353+ printk(KERN_ERR "ECC: No PCI bus.\n");
1354+ return 0;
1355+ }
1356+
1357+ while ((bridge = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, bridge)))
1358+ {
1359+ int loop = 0;
1360+ /* Direct reading of the pci config space of these is not
1361+ allowed in linux (eg it leaves no place for fixups and
1362+ other items); so replacing the following two lines with
1363+ those that follow immediately after it is a bugfix added by
1364+ RH. - arjanv@redhat.com 3/26/2002
1365+ pci_read_config_word(bridge, PCI_VENDOR_ID, &vendor);
1366+ pci_read_config_word(bridge, PCI_DEVICE_ID, &device);
1367+ */
1368+ vendor = bridge->vendor;
1369+ device = bridge->device;
1370+ while(probe_matrix[loop].vendor)
1371+ {
1372+ if( (vendor == probe_matrix[loop].vendor) &&
1373+ (device == probe_matrix[loop].device) )
1374+ {
1375+ if(probe_matrix[loop].check)
1376+ {
1377+ probe_matrix[loop].check();
1378+ return 1;
1379+ } else {
1380+ printk(KERN_WARNING "ECC: Unsupported device %x:%x.\n", vendor, device);
1381+ return 0;
1382+ }
1383+ }
1384+ loop++;
1385+ }
1386+ printk(KERN_DEBUG "ECC: Unknown device %x:%x.\n", vendor, device);
1387+ }
1388+ printk(KERN_ERR "ECC: Can't find host bridge.\n");
1389+ return 0;
1390+}
1391+
1392+static void ecc_fini(void) {
1393+ unload = 1;
1394+ wmb();
1395+ del_timer_sync(&ecctimer);
1396+#ifdef CONFIG_PROC_FS
1397+ remove_proc_entry("ram", 0);
1398+#endif
1399+ if (ecc_sysctl_header) {
1400+ unregister_sysctl_table(ecc_sysctl_header);
1401+ ecc_sysctl_header = NULL;
1402+ }
1403+
1404+ /*
1405+ * If we are expecting to find errors in the logs, we need notification
1406+ * when the module is unloaded.
1407+ */
1408+ if (log_sbe || log_mbe || panic_on_mbe) {
1409+ printk("ECC: Unloaded\n");
1410+ }
1411+}
1412+
1413+static int ecc_init(void) {
1414+ int loop;
1415+#ifdef CONFIG_PROC_FS
1416+ struct proc_dir_entry *ent;
1417+#endif
1418+ printk(KERN_INFO "ECC: monitor version %s\n", ECC_VER);
1419+
1420+ for (loop=0;loop<MAXBANKS;loop++) {
1421+ bank[loop].endaddr = 0;
1422+ bank[loop].sbecount = 0;
1423+ bank[loop].mbecount = 0;
1424+ bank[loop].eccmode = 0;
1425+ bank[loop].mtype = ECC_RESERVED;
1426+ }
1427+
1428+ if (!find_chipset()) {
1429+ printk("ECC: failed to find a supported memory controller\n");
1430+ return -ENODEV;
1431+ }
1432+
1433+#ifdef CONFIG_PROC_FS
1434+ ent = create_proc_entry("ram", S_IFREG | S_IRUGO, 0);
1435+ if (ent) {
1436+ ent->nlink = 1;
1437+ ent->read_proc = procfile_read;
1438+ }
1439+#endif
1440+ ecc_sysctl_header = register_sysctl_table(ecc_root_table, 1);
1441+
1442+ init_timer(&ecctimer);
1443+ ecctimer.expires = jiffies + (HZ * poll_msec) / 1000;
1444+ ecctimer.function = (void *)&checkecc;
1445+ add_timer(&ecctimer);
1446+
1447+ return 0;
1448+}
1449+
1450+#ifdef MODULE
1451+int init_module(void) {
1452+ return ecc_init();
1453+}
1454+void cleanup_module(void) {
1455+ ecc_fini();
1456+}
1457+#ifdef MODULE_LICENSE
1458+MODULE_LICENSE("GPL");
1459+#endif
1460+#endif
This page took 1.47936 seconds and 4 git commands to generate.