summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-09-18 05:35:49 +0200
committerMichael Brown2012-07-09 16:41:35 +0200
commitc69ba79e1fc265f0852ba179cacdd4eac0076e2c (patch)
tree88b38660728c7714921f8a7bc0eec5a28da936e4
parent[import] Import version 1.70 (diff)
downloadmemtest86-c69ba79e1fc265f0852ba179cacdd4eac0076e2c.tar.gz
memtest86-c69ba79e1fc265f0852ba179cacdd4eac0076e2c.tar.xz
memtest86-c69ba79e1fc265f0852ba179cacdd4eac0076e2c.zip
[import] Import version 2.00
http://www.memtest.org/download/2.00/memtest86+-2.00.tar.gz
-rw-r--r--FAQ2
-rw-r--r--Makefile103
-rw-r--r--README850
-rw-r--r--README.build-process20
-rw-r--r--changelog47
-rw-r--r--config.c185
-rw-r--r--config.h3
-rw-r--r--controller.c572
-rw-r--r--defs.h1
-rw-r--r--dmi.c15
-rw-r--r--error.c547
-rw-r--r--head.S4
-rw-r--r--head.s964
-rw-r--r--init.c302
-rw-r--r--lib.c231
-rw-r--r--main.c158
-rw-r--r--mt86+_loaderbin784 -> 784 bytes
-rw-r--r--mt86+_loader.asm11
-rw-r--r--patn.c2
-rw-r--r--pci.c2
-rw-r--r--pci.h1
-rw-r--r--serial.h4
-rw-r--r--setup.S2
-rw-r--r--spd.c140
-rw-r--r--test.c360
-rw-r--r--test.h49
26 files changed, 2934 insertions, 1641 deletions
diff --git a/FAQ b/FAQ
index f962443..3c2a01c 100644
--- a/FAQ
+++ b/FAQ
@@ -304,7 +304,7 @@
- When I run install.bat it doesn't write anything to floppy.
- You most likely have unpacked the memtest+-1.xx.floppy.zip file into a
+ You most likely have unpacked the memtest+-2.xx.floppy.zip file into a
folder with a long pathname and/or containing + and - signs. It seems
rawrite doesn't like that. Just move the files you unpacked to a directory
like c:\memtest and execure it from there.
diff --git a/Makefile b/Makefile
index af385d6..ef22f39 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# Makefile for MemTest-86
+# Makefile for MemTest86+
#
# Author: Chris Brady
# Created: January 1, 1996
@@ -9,79 +9,21 @@
FDISK=/dev/fd0
CC=gcc
-#
-# gcc compiler options, these settings should suffice
-#
-CCFLAGS=-Wall -m32 -march=i486 -Os -fomit-frame-pointer -fno-builtin -ffreestanding
-AS=as -32
+CFLAGS=-Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin -ffreestanding -fPIC
-OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o config.o linuxbios.o memsize.o pci.o controller.o extra.o random.o dmi.o
+OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \
+ config.o linuxbios.o memsize.o pci.o controller.o random.o extra.o \
+ spd.o error.o dmi.o
all: memtest.bin memtest
-reloc.o: reloc.c
- $(CC) -c -m32 -march=i486 -fPIC -Wall -g -O2 -fno-strict-aliasing reloc.c
-
-test.o: test.c test.h defs.h config.h
- $(CC) -c $(CCFLAGS) test.c
-
-main.o: main.c test.h defs.h
- $(CC) -c $(CCFLAGS) -fPIC main.c
-
-init.o: init.c test.h defs.h io.h config.h controller.h pci.h
- $(CC) -c $(CCFLAGS) -fPIC init.c
-
-linuxbios.o: linuxbios.c test.h linuxbios_tables.h defs.h config.h
- $(CC) -c $(CCFLAGS) -fPIC linuxbios.c
-
-memsize.o: memsize.c test.h defs.h config.h
- $(CC) -c $(CCFLAGS) -fPIC memsize.c
-
-lib.o: lib.c test.h defs.h io.h screen_buffer.h serial.h config.h
- $(CC) -c $(CCFLAGS) -fPIC lib.c
-
-screen_buffer.o: screen_buffer.c screen_buffer.h test.h config.h
- $(CC) -c $(CCFLAGS) -fPIC screen_buffer.c
-
-random.o: random.c
- $(CC) -c $(CCFLAGS) -fPIC random.c
-
-patn.o: patn.c
- $(CC) -c $(CCFLAGS) -fPIC patn.c
-
-config.o: config.c test.h controller.h screen_buffer.h
- $(CC) -c $(CCFLAGS) -fPIC config.c
-
-pci.o: pci.c pci.h io.h
- $(CC) -c $(CCFLAGS) -fPIC pci.c
-
-controller.o: controller.c defs.h config.h test.h pci.h controller.h
- $(CC) -c $(CCFLAGS) -fPIC controller.c
-
-extra.o: config.c test.h screen_buffer.h extra.h
- $(CC) -c $(CCFLAGS) -fPIC extra.c
-
-controller.s: controller.c defs.h config.h test.h pci.h controller.h
- $(CC) -S $(CCFLAGS) -fPIC controller.c
-
-head.s: head.S
- $(CC) -E -m32 -traditional $< -o $@
-
-head.o: head.s
- $(AS) -o $@ $<
-dmi.o: dmi.c test.h
- $(CC) -c $(CCFLAGS) -fPIC dmi.c
-
-makedefs: makedefs.c defs.h
- $(CC) $(CCFLAGS) makedefs.c -o $@
-
-
# Link it statically once so I know I don't have undefined
# symbols and then link it dynamically so I have full
# relocation information
memtest_shared: $(OBJS) memtest_shared.lds Makefile
- $(LD) --warn-constructors --warn-common -static -T memtest_shared.lds -o $@ $(OBJS) && \
+ $(LD) --warn-constructors --warn-common -static -T memtest_shared.lds \
+ -o $@ $(OBJS) && \
$(LD) -shared -Bsymbolic -T memtest_shared.lds -o $@ $(OBJS)
memtest_shared.bin: memtest_shared
@@ -90,34 +32,21 @@ memtest_shared.bin: memtest_shared
memtest: memtest_shared.bin memtest.lds
$(LD) -s -T memtest.lds -b binary memtest_shared.bin -o $@
-bootsect.s: bootsect.S defs.h
- $(CC) -E -traditional $< -o $@
-
-bootsect.o: bootsect.s
- $(AS) -o $@ $<
-
-bootsect: bootsect.o
- $(LD) -Ttext 0x00 -s --oformat binary -e _main --just-symbols=memtest_shared.o -o $@ $<
-
-setup.s: setup.S config.h defs.h
- $(CC) -E -traditional $< -o $@
-
-setup.o: setup.s
- $(AS) -o $@ $<
+memtest.bin: memtest_shared.bin bootsect.o setup.o memtest.bin.lds
+ $(LD) -T memtest.bin.lds bootsect.o setup.o -b binary \
+ memtest_shared.bin -o memtest.bin
+reloc.o: reloc.c
+ $(CC) -c $(CFLAGS) -fno-strict-aliasing reloc.c
-memtest.bin: memtest_shared.bin bootsect.o setup.o memtest.bin.lds
- $(LD) -T memtest.bin.lds bootsect.o setup.o -b binary memtest_shared.bin -o memtest.bin
+test.o: test.c
+ $(CC) -c -Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin -ffreestanding test.c
clean:
- rm -f *.o *.s memtest.bin bootsect setup low_mapfile high_mapfile \
- memtest memtest.out makedefs defs.lds memtest_shared memtest_shared.bin
-
-wormkill:
- rm -f *~
+ rm -f *.o memtest.bin memtest memtest_shared memtest_shared.bin
install: all
dd <memtest.bin >$(FDISK) bs=8192
-install-bin:
+install-precomp:
dd <precomp.bin >$(FDISK) bs=8192
diff --git a/README b/README
deleted file mode 100644
index dccbfd0..0000000
--- a/README
+++ /dev/null
@@ -1,850 +0,0 @@
- ====================
- = MemTest-86 v3.2 =
- = Nov 11, 2004 =
- = Chris Brady =
- ====================
-
-Table of Contents
-=================
- 1) Introduction
- 2) Licensing
- 3) Installation
- 4) Serial Port Console
- 5) Online Commands
- 6) Memory Sizing
- 7) Error Display
- 8) Trouble-shooting Memory Errors
- 9) Execution Time
- 10) Memory Testing Philosophy
- 11) Memtest86 Test Algorithms
- 12) Individual Test Descriptions
- 13) Problem Reporting - Contact Information
- 14) Known Problems
- 15) Planned Features List
- 16) Change Log
- 17) Donations
- 18) Acknowledgments
-
-
-1) Introduction
-===============
-Memtest86 is thorough, stand alone memory test for Intel/AMD x86 architecture
-systems. BIOS based memory tests are only a quick check and often miss
-failures that are detected by Memtest86.
-
-For updates go to the Memtest86 web page:
-
- http://www.memtest86.com
-
-
-2) Licensing
-============
-Memtest86 is released under the terms of the Gnu Public License (GPL). Other
-than the provisions of the GPL there are no restrictions for use, private or
-commercial. See: http://www.gnu.org/licenses/gpl.html for details.
-Explicit permission for inclusion of Memtest86 in software compilations and
-publications is hereby granted.
-
-
-3) Installation (Linux Only)
-============================
-Memtest86 is a stand alone program and can be loaded from either a disk
-partition or from a floppy disk.
-
-To build Memtest86:
- 1) Review the Makefile and adjust options as needed.
- 2) Type "make"
-
-This creates a file named "memtest.bin" which is a bootable image. This
-image file may be copied to a floppy disk or lilo may be used to boot this
-image from a hard disk partition.
-
-To create a Memtest86 bootdisk
- 1) Insert a blank write enabled floppy disk.
- 2) As root, Type "make install"
-
-To boot from a disk partition via lilo
- 1) Copy the image file to a permanent location (ie. /memtest).
- 2) Add an entry in the lilo config file (usually /etc/lilo.conf) to boot
- memtest86. Only the image and label fields need to be specified.
- The following is a sample lilo entry for booting memtest86:
-
- image = /memtest
- label = memtest
-
- 3) As root, type "lilo"
-
- At the lilo prompt enter memtest to boot memtest86.
-
-If you encounter build problems a binary image has been included (precomp.bin).
-To create a boot-disk with this pre-built image do the following:
- 1) Insert a blank write enabled floppy disk.
- 2) Type "make install-precomp"
-
-
-4) Serial Console
-=================
-Memtest86 can be used on PC's equipped with a serial port for the console.
-By default serial port console support is not enabled since it slows
-down testing. To enable change the SERIAL_CONSOLE_DEFAULT define in
-config.h from a zero to a one. The serial console baud rate may also
-be set in config.h with the SERIAL_BAUD_RATE define. The other serial
-port settings are no parity, 8 data bits, 1 stop bit. All of the features
-used by memtest86 are accessible via the serial console. However, the
-screen sometimes is garbled when the online commands are used.
-
-
-5) Online Commands
-==================
-Memtest86 has a limited number of online commands. Online commands
-provide control over caching, test selection, address range and error
-scrolling. A help bar is displayed at the bottom of the screen listing
-the available on-line commands.
-
- Command Description
-
- ESC Exits the test and does a warm restart via the BIOS.
-
- c Enters test configuration menu
- Menu options are:
- 1) Cache mode
- 2) Test selection
- 3) Address Range
- 4) Memory Sizing
- 5) Error Summary
- 6) Error Report Mode
- 7) ECC Mode
- 8) Restart
- 9) Adv. Options
-
- SP Set scroll lock (Stops scrolling of error messages)
- Note: Testing is stalled when the scroll lock is
- set and the scroll region is full.
-
- CR Clear scroll lock (Enables error message scrolling)
-
-
-6) Memory Sizing
-================
-The BIOS in modern PC's will often reserve several sections of memory for
-it's use and also to communicate information to the operating system (ie.
-ACPI tables). It is just as important to test these reserved memory blocks
-as it is for the remainder of memory. For proper operation all of memory
-needs to function properly regardless of what the eventual use is. For
-this reason Memtest86 has been designed to test as much memory as is
-possible.
-
-However, safely and reliably detecting all of the available memory has been
-problematic. Versions of Memtest86 prior to v2.9 would probe to find where
-memory is. This works for the vast majority of motherboards but is not 100%
-reliable. Sometimes the memory size is incorrect and worse probing the wrong
-places can in some cases cause the test to hang or crash.
-
-Starting in version 2.9 alternative methods are available for determining the
-memory size. By default the test attempts to get the memory size from the
-BIOS using the "e820" method. With "e820" the BIOS provides a table of memory
-segments and identifies what they will be used for. By default Memtest86
-will test all of the ram marked as available and also the area reserved for
-the ACPI tables. This is safe since the test does not use the ACPI tables
-and the "e820" specifications state that this memory may be reused after the
-tables have been copied. Although this is a safe default some memory will
-not be tested.
-
-Two additional options are available through online configuration options.
-The first option (BIOS-All) also uses the "e820" method to obtain a memory
-map. However, when this option is selected all of the reserved memory
-segments are tested, regardless of what their intended use is. The only
-exception is memory segments that begin above 3gb. Testing has shown that
-these segments are typically not safe to test. The BIOS-All option is more
-thorough but could be unstable with some motherboards.
-
-The second option for memory sizing is the traditional "Probe" method.
-This is a very thorough but not entirely safe method. In the majority of
-cases the BIOS-All and Probe methods will return the same memory map.
-
-For older BIOS's that do not support the "e820" method there are two
-additional methods (e801 and e88) for getting the memory size from the
-BIOS. These methods only provide the amount of extended memory that is
-available, not a memory table. When the e801 and e88 methods are used
-the BIOS-All option will not be available.
-
-The MemMap field on the display shows what memory size method is in use.
-Also the RsvdMem field shows how much memory is reserved and is not being
-tested.
-
-
-7) Error Information
-======================
-Memtest has two options for reporting errors. The default is to report
-individual errors. In BadRAM Patterns mode patterns are created for
-use with the Linux BadRAM feature. This slick feature allows Linux to
-avoid bad memory pages. Details about the BadRAM feature can be found at:
-
- http://home.zonnet.nl/vanrein/badram
-
-For individual errors the following information is displayed when a memory
-error is detected. An error message is only displayed for errors with a
-different address or failing bit pattern. All displayed values are in
-hexadecimal.
-
- Tst: Test number
- Failing Address : Failing memory address
- Good: Expected data pattern
- Bad: Failing data pattern
- Err-Bits: Exclusive or of good and bad data (this shows the
- position of the failing bit(s))
- Count: Number of consecutive errors with the same address
- and failing bits
-
-In BadRAM Patterns mode, Lines are printed in a form badram=F1,M1,F2,M2.
-In each F/M pair, the F represents a fault address, and the corresponding M
-is a bitmask for that address. These patterns state that faults have
-occurred in addresses that equal F on all "1" bits in M. Such a pattern may
-capture more errors that actually exist, but at least all the errors are
-captured. These patterns have been designed to capture regular patterns of
-errors caused by the hardware structure in a terse syntax.
-
-The BadRAM patterns are `grown' increment-ally rather than `designed' from an
-overview of all errors. The number of pairs is constrained to five for a
-number of practical reasons. As a result, handcrafting patterns from the
-output in address printing mode may, in exceptional cases, yield better
-results.
-
-
-8) Trouble-shooting Memory Errors
-================================
-Please be aware that not all errors reported by Memtest86 are due to
-bad memory. The test implicitly tests the CPU, L1 and L2 caches as well as
-the motherboard. It is impossible for the test to determine what causes
-the failure to occur. Most failures will be due to a problem with memory.
-When it is not, the only option is to replace parts until the failure is
-corrected.
-
-Once a memory error has been detected, determining the failing
-module is not a clear cut procedure. With the large number of motherboard
-vendors and possible combinations of simm slots it would be difficult if
-not impossible to assemble complete information about how a particular
-error would map to a failing memory module. However, there are steps
-that may be taken to determine the failing module. Here are three
-techniques that you may wish to use:
-
-1) Removing modules
-This is simplest method for isolating a failing modules, but may only be
-employed when one or more modules can be removed from the system. By
-selectively removing modules from the system and then running the test
-you will be able to find the bad module(s). Be sure to note exactly which
-modules are in the system when the test passes and when the test fails.
-
-2) Rotating modules
-When none of the modules can be removed then you may wish to rotate modules
-to find the failing one. This technique can only be used if there are
-three or more modules in the system. Change the location of two modules
-at a time. For example put the module from slot 1 into slot 2 and put
-the module from slot 2 in slot 1. Run the test and if either the failing
-bit or address changes then you know that the failing module is one of the
-ones just moved. By using several combinations of module movement you
-should be able to determine which module is failing.
-
-3) Replacing modules
-If you are unable to use either of the previous techniques then you are
-left to selective replacement of modules to find the failure.
-
-4) Avoiding allocation
-The printing mode for BadRAM patterns is intended to construct boot time
-parameters for a Linux kernel that is compiled with BadRAM support. This
-work-around makes it possible for Linux to reliably run on defective
-RAM. For more information on BadRAM support
-for Linux, sail to
-
- http://home.zonnet.nl/vanrein/badram
-
-Sometimes memory errors show up due to component incompatibility. A memory
-module may work fine in one system and not in another. This is not
-uncommon and is a source of confusion. The components are not necessarily
-bad but certain combinations may need to be avoided.
-
-I am often asked about the reliability of errors reported by Mestest86.
-In the vast majority of cases errors reported by the test are valid.
-There are some systems that cause Memtest86 to be confused about the size of
-memory and it will try to test non-existent memory. This will cause a large
-number of consecutive addresses to be reported as bad and generally there
-will be many bits in error. If you have a relatively small number of
-failing addresses and only one or two bits in error you can be certain
-that the errors are valid. Also intermittent errors are always valid.
-
-All valid memory errors should be corrected. It is possible that a
-particular error will never show up in normal operation. However, operating
-with marginal memory is risky and can result in data loss and even
-disk corruption. You can be sure that Murphy will get you if you know
-about a memory error and ignore it.
-
-Memtest86 can not diagnose many types of PC failures. For example a
-faulty CPU that causes Windows to crash will most likely just cause
-Memtest86 to crash in the same way.
-
-
-9) Execution Time
-==================
-The time required for a complete pass of Memtest86 will vary greatly
-depending on CPU speed, memory speed and memory size. Memtest86 executes
-indefinitely. The pass counter increments each time that all of the
-selected tests have been run. Generally a single pass is sufficient to
-catch all but the most obscure errors. However, for complete confidence
-when intermittent errors are suspected testing for a longer period is advised.
-
-10) Memory Testing Philosophy
-=============================
-There are many good approaches for testing memory. However, many tests
-simply throw some patterns at memory without much thought or knowledge
-of memory architecture or how errors can best be detected. This
-works fine for hard memory failures but does little to find intermittent
-errors. BIOS based memory tests are useless for finding intermittent
-memory errors.
-
-Memory chips consist of a large array of tightly packed memory cells,
-one for each bit of data. The vast majority of the intermittent failures
-are a result of interaction between these memory cells. Often writing a
-memory cell can cause one of the adjacent cells to be written with the
-same data. An effective memory test attempts to test for this
-condition. Therefore, an ideal strategy for testing memory would be
-the following:
-
- 1) write a cell with a zero
- 2) write all of the adjacent cells with a one, one or more times
- 3) check that the first cell still has a zero
-
-It should be obvious that this strategy requires an exact knowledge
-of how the memory cells are laid out on the chip. In addition there is a
-never ending number of possible chip layouts for different chip types
-and manufacturers making this strategy impractical. However, there
-are testing algorithms that can approximate this ideal strategy.
-
-
-11) Memtest86 Test Algorithms
-=============================
-Memtest86 uses two algorithms that provide a reasonable approximation
-of the ideal test strategy above. The first of these strategies is called
-moving inversions. The moving inversion test works as follows:
-
- 1) Fill memory with a pattern
- 2) Starting at the lowest address
- 2a check that the pattern has not changed
- 2b write the patterns complement
- 2c increment the address
- repeat 2a - 2c
- 3) Starting at the highest address
- 3a check that the pattern has not changed
- 3b write the patterns complement
- 3c decrement the address
- repeat 3a - 3c
-
-This algorithm is a good approximation of an ideal memory test but
-there are some limitations. Most high density chips today store data
-4 to 16 bits wide. With chips that are more than one bit wide it
-is impossible to selectively read or write just one bit. This means
-that we cannot guarantee that all adjacent cells have been tested
-for interaction. In this case the best we can do is to use some
-patterns to insure that all adjacent cells have at least been written
-with all possible one and zero combinations.
-
-It can also be seen that caching, buffering and out of order execution
-will interfere with the moving inversions algorithm and make less effective.
-It is possible to turn off cache but the memory buffering in new high
-performance chips can not be disabled. To address this limitation a new
-algorithm I call Modulo-X was created. This algorithm is not affected by
-cache or buffering. The algorithm works as follows:
- 1) For starting offsets of 0 - 20 do
- 1a write every 20th location with a pattern
- 1b write all other locations with the patterns complement
- repeat 1b one or more times
- 1c check every 20th location for the pattern
-
-This algorithm accomplishes nearly the same level of adjacency testing
-as moving inversions but is not affected by caching or buffering. Since
-separate write passes (1a, 1b) and the read pass (1c) are done for all of
-memory we can be assured that all of the buffers and cache have been
-flushed between passes. The selection of 20 as the stride size was somewhat
-arbitrary. Larger strides may be more effective but would take longer to
-execute. The choice of 20 seemed to be a reasonable compromise between
-speed and thoroughness.
-
-
-12) Individual Test Descriptions
-================================
-Memtest86 executes a series of numbered test sections to check for
-errors. These test sections consist of a combination of test
-algorithm, data pattern and caching. The execution order for these tests
-were arranged so that errors will be detected as rapidly as possible.
-A description of each of the test sections follows:
-
-Test 0 [Address test, walking ones, no cache]
- Tests all address bits in all memory banks by using a walking ones
- address pattern. Errors from this test are not used to calculate
- BadRAM patterns.
-
-Test 1 [Address test, own address]
- Each address is written with its own address and then is checked
- for consistency. In theory previous tests should have caught any
- memory addressing problems. This test should catch any addressing
- errors that somehow were not previously detected.
-
-Test 2 [Moving inversions, ones&zeros]
- This test uses the moving inversions algorithm with patterns of all
- ones and zeros. Cache is enabled even though it interferes to some
- degree with the test algorithm. With cache enabled this test does not
- take long and should quickly find all "hard" errors and some more
- subtle errors. This section is only a quick check.
-
-Test 3 [Moving inversions, 8 bit pat]
- This is the same as test 1 but uses a 8 bit wide pattern of
- "walking" ones and zeros. This test will better detect subtle errors
- in "wide" memory chips. A total of 20 data patterns are used.
-
-Test 4 [Moving inversions, random pattern]
- Test 4 uses the same algorithm as test 1 but the data pattern is a
- random number and it's complement. This test is particularly effective
- in finding difficult to detect data sensitive errors. A total of 60
- patterns are used. The random number sequence is different with each pass
- so multiple passes increase effectiveness.
-
-Test 5 [Block move, 64 moves]
- This test stresses memory by using block move (movsl) instructions
- and is based on Robert Redelmeier's burnBX test. Memory is initialized
- with shifting patterns that are inverted every 8 bytes. Then 4MB blocks
- of memory are moved around using the movsl instruction. After the moves
- are completed the data patterns are checked. Because the data is checked
- only after the memory moves are completed it is not possible to know
- where the error occurred. The addresses reported are only for where the
- bad pattern was found. Since the moves are constrained to a 8MB segment
- of memory the failing address will always be lest than 8MB away from the
- reported address. Errors from this test are not used to calculate
- BadRAM patterns.
-
-Test 6 [Moving inversions, 32 bit pat]
- This is a variation of the moving inversions algorithm that shifts the data
- pattern left one bit for each successive address. The starting bit position
- is shifted left for each pass. To use all possible data patterns 32 passes
- are required. This test is quite effective at detecting data sensitive
- errors but the execution time is long.
-
-Test 7 [Random number sequence]
- This test writes a series of random numbers into memory. By resetting the
- seed for the random number the same sequence of number can be created for
- a reference. The initial pattern is checked and then complemented and
- checked again on the next pass. However, unlike the moving inversions test
- writing and checking can only be done in the forward direction.
-
-Test 8 [Modulo 20, ones&zeros]
- Using the Modulo-X algorithm should uncover errors that are not
- detected by moving inversions due to cache and buffering interference
- with the the algorithm. All ones and zeros are used for data patterns.
-
-Test 9 [Bit fade test, 90 min, 2 patterns]
- The bit fade test initializes all of memory with a pattern and then
- sleeps for 90 minutes. Then memory is examined to see if any memory bits
- have changed. All ones and all zero patterns are used. This test takes
- 3 hours to complete. The Bit Fade test is not included in the normal test
- sequence and must be run manually via the runtime configuration menu.
-
-
-13) Problem Reporting - Contact Information
-===========================================
-Due to the growing popularity of Memtest86 (more than 200,000 downloads per
-month) I have been inundated by, questions, feedback, problem reports and
-requests for enhancements. I simply do not have time to repond to ANY Memtest86
-emails. Bug reports and suggestions are welcome but will typically not be
-responded to.
-
-*** NOTE: *** The Keyword MEM86 must appear in the subject of all emails or
-the message will be automaticly deleted before it gets to me. This thanks to
-spam and viruses!
-
-Problems/Bugs:
-Before submitting a problem report please check the Known Problems section
-to see if this problem has already been reported. Be sure to include the
-version number and also any details that may be relevant.
-
-Chris Brady, Email: bugs@memtest86.com
-
-With some PC's Memtest86 will just die with no hints as to what went wrong.
-Without any details it is impossible to fix these failures. Fixing these
-problems will require debugging on your part. There is no point in reporting
-these failures unless you have a Linux system and would be willing to debug
-the failure.
-
-Enhancements:
-If you would like to request an enhancement please see if is already on
-the Planned Features List before sending your request. All requests will
-be considered, but not all can be implemented. If you are be interested in
-contributing code please contact me so that the integration can be
-co-ordinated.
-
-Chris Brady, Email: enhance@memtest86.com
-
-Questions:
-Unfortunately, I do not have time to respond to any questions or provide
-assistance with troubleshooting problems. Please read the Troubleshooting
-and Known Problems sections for assistance with problems. These sections have
-the answers for the questions that I have answers to. If there is not an
-answer for your problem in these sections it is probably not something I can
-help you with.
-
-
-
-14) Known Problems
-==================
-Sometimes when booting from a floppy disk the following messages scroll up
-on the screen:
- X:8000
- AX:0212
- BX:8600
- CX:0201
- DX:0000
-This the BIOS reporting floppy disk read errors. Either re-write or toss
-the floppy disk.
-
-Memtest86 has no support for multiple CPUs. Memtest86 should run
-without problems, but it will only use one CPU.
-
-Memtest86 can not diagnose many types of PC failures. For example a
-faulty CPU that causes Windows to crash will most likely just cause
-Memtest86 to crash in the same way.
-
-There have been numerous reports of errors in only tests 5 and 8 on Athlon
-systems. Often the memory works in a different system or the vendor insists
-that it is good. In these cases the memory is not necessarily bad but is
-not able to operate reliably at Athlon speeds. Sometimes more conservative
-memory timings on the motherboard will correct these errors. In other
-cases the only option is to replace the memory with better quality, higher
-speed memory. Don't buy cheap memory and expect it to work with an Athlon!
-
-Memtest86 supports all types of memory. If fact the test has absolutely
-no knowledge of the memory type nor does it need to. This not a problem
-or bug but is listed here due to the many questions I get about this issue.
-
-Changes in the compiler and loader have caused problems with
-Memtest86 resulting in both build failures and errors in execution. A
-binary image (precomp.bin) of the test is included and may be used if
-problems are encountered.
-
-15) Planned Features List
-=========================
-This is a list of enhancements planned for future releases of Memtest86.
-There is no timetable for when these will be implemented, if ever.
-
- - Option to allow printing of error information on an attached printer.
- - Option to write error information to a floppy disk.
- - Supply Memtest in RPM format.
- - Read and display RAM SPD information.
-
-
-16) Change Log
-==============
-Enhancements in v3.2 (11/Nov/2004)
-
- Added two new, highly effective tests that use random number patterns
- (tests 4 and 6).
-
- Reworked the online commands:
- - Changed wording for better clarity
- - Dropped Cache Mode menu
-
- Updated CPU detection for newer AMD, Intel and Cyrix CPUs.
-
- Reworked test sequence:
- - Dropped ineffective non cached tests (Numbers 7-11)
- - Changed cache mode to cached for test 2
- - Fixed bug that did not allow tsome tests to be skipped
- - Added bailout for Bit fade test
-
- Error reports are highlighted in red to provide a more vivid error
- indication.
-
- Added support for a large number of additional chipsets. (from Memtest86+
- v1.30)
-
- Added an advanced setup feature that with new chiset allows memory timings
- to be altered from inside Memtest86. (from Memtest86+ v1.30)
-
-
-Enhancements in v3.1 (11/Mar/2004)
-
- Added processor detection for newer AMD processors.
-
- Added new "Bit Fade" extended test.
-
- Fixed a complile time bug with gcc version 3.x.
-
- E7500 memory controller ECC support
-
- Added support for 16bit ECC syndromes
-
- Option to keep the serial port baud rate of the boot loader
-
-
-Enhancements in v3.0 (22/May/2002) Provided by Eric Biederman
-
- Testing of more than 2gb of memory is at last fixed (tested with 6Gb)
-
- The infrastructure is to poll ecc error reporting chipset regisets,
- and the support has been done for some chipsets.
-
- Uses dynamic relocation information records to make itself PIC
- instead of requiring 2 copies of memtest86 in the binary.
-
- The serial console code does not do redundant writes to the serial port
- Very little slow down at 9600 baud.
-
- You can press ^l or just l to get a screen refresh, when you are
- connecting and unconnecting a serial cable.
-
- Netbooting is working again
-
- LinuxBIOS support (To get the memory size)
-
- Many bugfixes and code cleanup.
-
-Enhancements in v2.9 (29/Feb/2002)
-
- The memory sizing code has been completely rewritten. By default
- Memtest86 gets a memory map from the BIOS that is now used to find
- available memory. A new online configuration option provides three
- choices for how memory will be sized, including the old "probe" method.
- The default mode generally will not test all of memory, but should be more
- stable. See the "Memory Sizing" section for details.
-
- Testing of more than 2gb of memory should now work. A number of bugs
- were found and corrected that prevented testing above 2gb. Testing
- with more than 2gb has been limited and there could be problems with a
- full 4gb of memory.
-
- Memory is divided into segments for testing. This allow for frequent
- progress updates and responsiveness to interactive commands. The
- memory segment size has been increased from 8 to 32mb. This should
- improve testing effectivness but progress reports will be less frequent.
-
- Minor bug fixes.
-
-Enhancements in v2.8 (18/Oct/2001)
- Eric Biederman reworked the build process making it far simpler and also
- to produce a network bootable ELF image.
-
- Re-wrote the memory and cache speed detection code. Previously the
- reported numbers were inaccurate for intel CPU's and completely wrong
- for Athlon/Duron CPU's.
-
- By default the serial console is disabled since this was slowing
- down testing.
-
- Added CPU detection for Pentium 4.
-
-
-Enhancements in v2.7 (12/Jul/2001)
- Expanded workaround for errors caused by BIOS USB keyboard support to
- include test #5.
-
- Re-worked L1 / L2 cache detection code to provide clearer reporting.
-
- Fixed an obvious bug in the computation of cache and memory speeds.
-
- Changed on-line menu to stay in the menu between option selections.
-
- Fixed bugs in the test restart and redraw code.
-
- Adjusted code size to fix compilation problems with RedHat 7.1.
-
- Misc updates to the documentation.
-
-Enhancements in v2.6 (25/May/2001)
- Added workaround for errors caused by BIOS USB keyboard support.
-
- Fixed problems with reporting of 1 GHZ + processor speeds.
-
- Fixed Duron cache detection.
-
- Added screen buffer so that menus will work correctly from a serial
- console.
-
- The Memtest86 image is now built in ELF format.
-
-Enhancements in v2.5 (14/Dec/00)
- Enhanced CPU and cache detection to correctly identify Duron CPU
- and K6-III 1MB cache.
-
- Added code to report cache-able memory size.
-
- Added limited support for parity memory.
-
- Support was added to allow use of on-line commands from a serial
- port.
-
- Dropped option for changing refresh rates. This was not useful
- and did not work on newer motherboards.
-
- Improved fatal exception reporting to include a register and stack
- dump.
-
- The pass number is now displayed in the error report.
-
- Fixed a bug that crashed the test when selecting one of the extended
- tests.
-
-Enhancements in v2.4
- The error report format was reworked for better clarity and now
- includes a decimal address in megabytes.
-
- A new memory move test was added (from Robert Redelmeier's CPU-Burn)
-
- The test sequence and iterations were modified.
-
- Fixed scrolling problems with the BadRAM patterns.
-
-
-Enhancements in v2.3
- A progress meter was added to replace the spinner and dots.
-
- Measurement and reporting of memory and cache performance
- was added.
-
- Support for creating BadRAM patterns was added.
-
- All of the test routines were rewritten in assembler to
- improve both test performance and speed.
-
- The screen layout was reworked to hopefully be more readable.
-
- An error summary option was added to the online commands.
-
-
-Enhancements in v2.2
- Added two new address tests
-
- Added an on-line command for setting test address range
-
- Optimized test code for faster execution (-O3, -funroll-loops and
- -fomit-frame-pointer)
-
- Added and elapsed time counter.
-
- Adjusted menu options for better consistency
-
-
-Enhancements in v2.1
- Fixed a bug in the CPU detection that caused the test to
- hang or crash with some 486 and Cryrix CPU's
-
- Added CPU detection for Cyrix CPU's
-
- Extended and improved CPU detection for Intel and AMD CPU's
-
- Added a compile time option (BIOS_MEMSZ) for obtaining the last
- memory address from the BIOS. This should fix problems with memory
- sizing on certain motherboards. This option is not enabled by default.
- It may be enabled be default in a future release.
-
-Enhancements in v2.0
- Added new Modulo-20 test algorithm.
-
- Added a 32 bit shifting pattern to the moving inversions algorithm.
-
- Created test sections to specify algorithm, pattern and caching.
-
- Improved test progress indicators.
-
- Created popup menus for configuration.
-
- Added menu for test selection.
-
- Added CPU and cache identification.
-
- Added a "bail out" feature to quit the current test when it does not
- fit the test selection parameters.
-
- Re-arranged the screen layout and colors.
-
- Created local include files for I/O and serial interface definitions
- rather than using the sometimes incompatible system include files.
-
- Broke up the "C" source code into four separate source modules.
-
-Enhancements in v1.5
- Some additional changes were made to fix obscure memory sizing
- problems.
-
- The 4 bit wide data pattern was increased to 8 bits since 8 bit
- wide memory chips are becoming more common.
-
- A new test algorithm was added to improve detection of data
- pattern sensitive errors.
-
-
-Enhancements in v1.4
- Changes to the memory sizing code to avoid problems with some
- motherboards where memtest would find more memory than actually
- exists.
-
- Added support for a console serial port. (thanks to Doug Sisk)
-
- On-line commands are now available for configuring Memtest86 on
- the fly (see On-line Commands).
-
-
-Enhancements in v1.3
- Scrolling of memory errors is now provided. Previously, only one screen
- of error information was displayed.
-
- Memtest86 can now be booted from any disk via lilo.
-
- Testing of up to 4gb of memory has been fixed is now enabled by default.
- This capability was clearly broken in v1.2a and should work correctly
- now but has not been fully tested (4gb PC's are a bit rare).
-
- The maximum memory size supported by the motherboard is now being
- calculated correctly. In previous versions there were cases where not
- all of memory would be tested and the maximum memory size supported
- was incorrect.
-
- For some types of failures the good and bad values were reported to be
- same with an Xor value of 0. This has been fixed by retaining the data
- read from memory and not re-reading the bad data in the error reporting
- routine.
-
- APM (advanced power management) is now disabled by Memtest86. This
- keeps the screen from blanking while the test is running.
-
- Problems with enabling & disabling cache on some motherboards have been
- corrected.
-
-
-17) Donations
-=============
-With considerable reluctance I am resorting to a low key solicitation for
-donations. It never has been my intent to profit from this program and I am
-pleased that Memtest86 has been helpful. However, the time required to
-support this program has grown significantly. I also have the modest
-cost of hosting this web-site that I would like to recover. So if you find
-Memtest86 useful and you feel inclined to make a small PayPal donation please
-do so. Use "cbrady@memtest86.com" for the recipient.
-
-
-18) Acknowledgments
-===================
-Memtest86 was developed by Chris Brady with the resources and assistance
-listed below:
-
-- The initial versions of the source files bootsect.S, setup.S, head.S and
- build.c are from the Linux 1.2.1 kernel and have been heavily modified.
-
-- Doug Sisk provided code to support a console connected via a serial port.
-
-- Code to create BadRAM patterns was provided by Rick van Rein.
-
-- Tests 5 and 8 are based on Robert Redelmeier's burnBX test.
-
-- Screen buffer code was provided by Jani Averbach.
-
-- Eric Biederman provided all of the feature content for version 3.0
- plus many bugfixes and significant code cleanup.
-
-- Major enhancements to hardware detection and reporting in version 3.2
- provided by Samuel Demeulemeester (from Memtest86+ v1.11).
diff --git a/README.build-process b/README.build-process
index 37ca48a..a959e7b 100644
--- a/README.build-process
+++ b/README.build-process
@@ -1,7 +1,7 @@
-During memory testing memtest86 relocates itself in memory so it can test the
-memory it was previously running from. memtest86 is compiled as position mostly
+During memory testing memtest86+ relocates itself in memory so it can test the
+memory it was previously running from. memtest86+ is compiled as position mostly
independent code. Some relocations records must be processed to achieve the
-affect of position independent code. A 16 bit loader is prepended to memtest86
+affect of position independent code. A 16 bit loader is prepended to memtest86+
so it can be loaded from a floppy, or from lilo.
In restructuring the build process I had several goals. Maintainability and
@@ -11,16 +11,16 @@ and images bootable by bootloaders that directly load static ELF images.
With the ability to proecess relocation records, memtest.bin has been
reduced in size from 84480 bytes to 49308 bytes. And now only requires one copy
-of memtest86. A reduction in size of 35K. And the build process can now ignore
-the size of memtest86.
+of memtest86+. A reduction in size of 35K. And the build process can now ignore
+the size of memtest86+.
BIOS calls have been moved from setup.S to head.S making bootsect.S and
setup.S exclusively for booting.
-memtest86 is built in three stages. In the first stage the relocatable object
+memtest86+ is built in three stages. In the first stage the relocatable object
files are built as with any program. In the second stage the relocatable object
files are linked together into memtest_shared, a shared library version
-of memtest86. In the third stage a raw memory image of memtest_shared is formed
+of memtest86+. In the third stage a raw memory image of memtest_shared is formed
and linked into memtest.bin, and memtest.
memtest.bin is the floppy/lilo bootable target.
@@ -28,11 +28,11 @@ memtest.bin is the floppy/lilo bootable target.
memtest is the ELF bootable target.
Another major change is now data in the bss segment is also preserved
-when memtest86 is relocated, and memtest86 can be relocated to any address.
+when memtest86+ is relocated, and memtest86+ can be relocated to any address.
-The one thing to watch out for is pointers to data inside of memtest86. Except
+The one thing to watch out for is pointers to data inside of memtest86+. Except
for constant pointers to static data there is not enough information to generate
-relocation records for pointers so they will not change when memtest86 is
+relocation records for pointers so they will not change when memtest86+ is
relocated, which might lead to nasty surpises.
Eric Biederman <ebiederman@lnxi.com>
diff --git a/changelog b/changelog
index ad900a9..eebefa4 100644
--- a/changelog
+++ b/changelog
@@ -1,25 +1,24 @@
-Memtest86+ V.70 changelog
--------------------------
-
-- Added new DMI polling feature (Thanks to Joachim D.)
-- Added Support for Core/Core2 Solo/Duo/Quad CPU
-- Added Support for AMD K8 with DDR2 Memory
-- Added Support for Intel CPU with 192/384 KB L2 Cache
-- Added Support for FB-DIMM based memory (DMI)
-- Added Detection for ALI CyberAladdin-T (M1644)
-- Added Detection for Turion 64 X2
-- Added Detection for AMD K8 with unknown chipsets
-- Added Support for ATi Radeon xPress 3200
-- Added Support for Intel i975X
-- Added Support for Intel Q965/P965
-- Added Support for Intel Q963/Q965
-
-Thanks to Jesper Ekhall for betatesting.
-
-
-
-
-
-
-
+Memtest86+ V2.00 changelog
+--------------------------
+
+- Major Architectures changes
+- Modulo test now use random pattern for better accuracy
+- Added Advanced DMI Errors Reporting Mode
+- Added support for bus ratio changes on Intel Core CPU
+- Added support for non-integer bus ratio on latest Intel CPU
+- Added SPD Data Display for all Intel Chipsets (more to come)
+- Added serial support as a linux boot parameter (Thanks to Michal S.)
+- Added preliminary support for VIA CN Isaiah CPU
+- Added preliminary support for Intel Nehalem
+- Adedd support for VIA C7/C7-D/C7-M/Eden on Esther Core
+- Added support for AMD K10 (Phenom) CPU w/ timings detection
+- Added support for Intel Pentium E w/ 1 MB L2 Cache
+- Added support for Intel Core 2 45nm (Penryn)
+- Added support for FSB1333/FSB1600 Intel CPU
+- Added support for Intel 5400A/5400B w/ timings detection
+- Added support for Intel Q35/P35/G33/Q33 w/ timings detection
+- Added support for Intel X38/X48 w/ timings detection
+- Added preliminary support for Intel 5000P/V/Z
+- Removed on-fly memory timings change (unstable)
+- Numerous (really) bug fixes
diff --git a/config.c b/config.c
index becc1c2..d2dd0f7 100644
--- a/config.c
+++ b/config.c
@@ -1,4 +1,4 @@
-/* config.c - MemTest-86 Version 3.2
+/* config.c - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
@@ -17,6 +17,7 @@ extern int bail, beepmode;
extern struct tseq tseq[];
extern short e820_nr;
extern char memsz_mode;
+//void performance();
char save[2][POP_H][POP_W];
char save2[2][POP2_H][POP2_W];
@@ -30,16 +31,16 @@ void get_config()
popup();
wait_keyup();
while(!flag) {
- cprint(POP_Y+1, POP_X+2, "Configuration:");
+ cprint(POP_Y+1, POP_X+2, "Settings:");
cprint(POP_Y+3, POP_X+6, "(1) Test Selection");
cprint(POP_Y+4, POP_X+6, "(2) Address Range");
cprint(POP_Y+5, POP_X+6, "(3) Memory Sizing");
- cprint(POP_Y+6, POP_X+6, "(4) Error Summary");
- cprint(POP_Y+7, POP_X+6, "(5) Error Report Mode");
+ cprint(POP_Y+6, POP_X+6, "(4) Error Report Mode");
+ cprint(POP_Y+7, POP_X+6, "(5) Show DMI Memory Info");
cprint(POP_Y+8, POP_X+6, "(6) ECC Mode");
cprint(POP_Y+9, POP_X+6, "(7) Restart");
cprint(POP_Y+10, POP_X+6, "(8) Refresh Screen");
- cprint(POP_Y+11, POP_X+6, "(9) Adv. Options");
+ cprint(POP_Y+11, POP_X+6, "(9) Display SPD Data");
cprint(POP_Y+12, POP_X+6, "(0) Continue");
/* Wait for key release */
@@ -54,7 +55,7 @@ void get_config()
cprint(POP_Y+4, POP_X+6, "(2) Skip Current Test");
cprint(POP_Y+5, POP_X+6, "(3) Select Test");
cprint(POP_Y+6, POP_X+6, "(4) Select Bit Fade Test");
- cprint(POP_Y+7, POP_X+6, "(5) Select Uncached Test");
+ //cprint(POP_Y+7, POP_X+6, "(5) Select Uncached Test");
cprint(POP_Y+8, POP_X+6, "(0) Continue");
if (v->testsel < 0) {
cprint(POP_Y+3, POP_X+5, ">");
@@ -66,7 +67,7 @@ void get_config()
switch(get_key()) {
case 2:
/* Default */
- if (v->testsel > 8) {
+ if (v->testsel >= 9) {
bail++;
}
v->testsel = -1;
@@ -85,9 +86,9 @@ void get_config()
cprint(POP_Y+1, POP_X+3,
"Test Selection:");
cprint(POP_Y+4, POP_X+5,
- "Test Number [0-10]: ");
+ "Test Number [0-9]: ");
i = getval(POP_Y+4, POP_X+24, 0);
- if (i <= 10) {
+ if (i <= 9) {
if (i != v->testsel) {
v->pass = -1;
v->test = -1;
@@ -112,6 +113,7 @@ void get_config()
cprint(LINE_INFO, COL_TST, "#");
dprint(LINE_INFO, COL_TST+1, 9, 3, 1);
break;
+/*
case 6:
if (v->testsel != 10) {
v->pass = -1;
@@ -124,6 +126,7 @@ void get_config()
cprint(LINE_INFO, COL_TST, "#");
dprint(LINE_INFO, COL_TST+1, 10, 3, 1);
break;
+*/
case 11:
case 57:
sflag++;
@@ -156,6 +159,7 @@ void get_config()
page = getval(POP_Y+6, POP_X+9, 12);
if (page + 1 <= v->plim_upper) {
v->plim_lower = page;
+ v->test--;
bail++;
}
adj_mem();
@@ -175,6 +179,7 @@ void get_config()
page = getval(POP_Y+6, POP_X+9, 12);
if (page - 1 >= v->plim_lower) {
v->plim_upper = page;
+ v->test--;
bail++;
}
adj_mem();
@@ -185,6 +190,7 @@ void get_config()
/* All of memory */
v->plim_lower = 0;
v->plim_upper = v->pmap[v->msegs - 1].end;
+ v->test--;
bail++;
adj_mem();
find_ticks();
@@ -225,40 +231,19 @@ void get_config()
memsz_mode = SZ_MODE_BIOS;
wait_keyup();
restart();
-/*
- mem_size();
- v->test = 0;
- v->pass = 0;
- v->total_ticks = 0;
- bail++;
- sflag++;
-*/
+
break;
case 3:
memsz_mode = SZ_MODE_BIOS_RES;
wait_keyup();
restart();
-/*
- mem_size();
- v->test = 0;
- v->pass = 0;
- v->total_ticks = 0;
- bail++;
- sflag++;
-*/
+
break;
case 4:
memsz_mode = SZ_MODE_PROBE;
wait_keyup();
restart();
-/*
- mem_size();
- v->test = 0;
- v->pass = 0;
- v->total_ticks = 0;
- bail++;
- sflag++;
-*/
+
break;
case 11:
case 57:
@@ -270,68 +255,60 @@ void get_config()
popclear();
break;
case 5:
- /* 4 - Show error summary */
- popclear();
- for (i=0; tseq[i].msg != NULL; i++) {
- cprint(POP_Y+1+i, POP_X+2, "Test:");
- dprint(POP_Y+1+i, POP_X+8, i, 2, 1);
- cprint(POP_Y+1+i, POP_X+12, "Errors:");
- dprint(POP_Y+1+i, POP_X+20, tseq[i].errors,
- 5, 1);
- }
- wait_keyup();
- while (get_key() == 0);
- popclear();
- break;
- case 6:
- /* 5 - Printing Mode */
+ /* 4 - Show error Mode */
popclear();
cprint(POP_Y+1, POP_X+2, "Printing Mode:");
- cprint(POP_Y+3, POP_X+6, "(1) Individual Errors");
- cprint(POP_Y+4, POP_X+6, "(2) BadRAM Patterns");
- cprint(POP_Y+5, POP_X+6, "(3) DMI Device Name");
+ cprint(POP_Y+3, POP_X+6, "(1) Error Summary");
+ cprint(POP_Y+4, POP_X+6, "(2) Individual Errors");
+ cprint(POP_Y+5, POP_X+6, "(3) BadRAM Patterns");
cprint(POP_Y+6, POP_X+6, "(4) Error Counts Only");
- cprint(POP_Y+7, POP_X+6, "(5) Beep on Error");
- cprint(POP_Y+8, POP_X+6, "(6) Show DMI Memory Info");
- cprint(POP_Y+9, POP_X+6, "(0) Cancel");
+ cprint(POP_Y+7, POP_X+6, "(5) DMI Device Name");
+ cprint(POP_Y+8, POP_X+6, "(6) Beep on Error");
+ cprint(POP_Y+10, POP_X+6, "(0) Cancel");
cprint(POP_Y+3+v->printmode, POP_X+5, ">");
- if (beepmode) { cprint(POP_Y+7, POP_X+5, ">"); }
+ if (beepmode) { cprint(POP_Y+8, POP_X+5, ">"); }
wait_keyup();
while (!sflag) {
- switch(get_key()) {
+ switch(get_key()) {
case 2:
+ /* Error Summary */
+ v->printmode=PRINTMODE_SUMMARY;
+ v->erri.eadr = 0;
+ v->erri.hdr_flag = 0;
+ sflag++;
+ break;
+ case 3:
/* Separate Addresses */
v->printmode=PRINTMODE_ADDRESSES;
- v->eadr = 0;
+ v->erri.eadr = 0;
+ v->erri.hdr_flag = 0;
+ v->msg_line = LINE_SCROLL-1;
sflag++;
break;
- case 3:
+ case 4:
/* BadRAM Patterns */
v->printmode=PRINTMODE_PATTERNS;
+ v->erri.hdr_flag = 0;
sflag++;
prt++;
break;
- case 4:
- /* DMI Devices */
- v->printmode=PRINTMODE_DMI;
- sflag++;
- break;
- case 5:
+ case 5:
/* Error Counts Only */
v->printmode=PRINTMODE_NONE;
+ v->erri.hdr_flag = 0;
sflag++;
break;
case 6:
- /* Set Beep On Error mode */
- beepmode = !beepmode;
+ /* Error Counts Only */
+ v->printmode=PRINTMODE_DMI;
+ v->erri.hdr_flag = 0;
sflag++;
break;
case 7:
- /* Display DMI Memory Info */
- pop2up();
- print_dmi_info();
- pop2down();
- break;
+ /* Set Beep On Error mode */
+ beepmode = !beepmode;
+ sflag++;
+ break;
case 11:
case 57:
/* 0/CR - Continue */
@@ -341,6 +318,12 @@ void get_config()
}
popclear();
break;
+ case 6:
+ /* Display DMI Memory Info */
+ pop2up();
+ print_dmi_info();
+ pop2down();
+ break;
case 7:
/* 6 - ECC Polling Mode */
popclear();
@@ -382,7 +365,10 @@ void get_config()
flag++;
break;
case 10:
- get_menu();
+ popdown();
+ show_spd();
+ popup();
+ sflag++;
break;
case 11:
case 57:
@@ -560,3 +546,58 @@ void adj_mem(void)
}
}
}
+
+/*
+void performance()
+{
+ extern int l1_cache, l2_cache;
+ ulong speed;
+ int i;
+
+ popclear();
+
+ cprint(POP_Y+1, POP_X+1, " Read Write Copy");
+ cprint(POP_Y+3, POP_X+1, "L1 Cache:");
+ speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 500, MS_READ);
+ dprint(POP_Y+3, POP_X+10, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 50, MS_WRITE);
+ dprint(POP_Y+3, POP_X+17, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 50, MS_COPY);
+ dprint(POP_Y+3, POP_X+24, speed, 6, 0);
+
+ if (l2_cache < l1_cache) {
+ i = l1_cache / 4 + l2_cache / 4;
+ } else {
+ i = l1_cache;
+ }
+ cprint(POP_Y+5, POP_X+1, "L2 Cache:");
+ speed=memspeed((ulong)mapping(0x100), i*1024, 500, MS_READ);
+ dprint(POP_Y+5, POP_X+10, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_WRITE);
+ dprint(POP_Y+5, POP_X+17, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY);
+ dprint(POP_Y+5, POP_X+24, speed, 6, 0);
+
+ // Determine memory speed. To find the memory spped we use
+ // A block size that is 5x the sum of the L1 and L2 caches
+ i = (l2_cache + l1_cache) * 5;
+
+ // Make sure that we have enough memory to do the test
+ if ((1 + (i * 2)) > (v->plim_upper << 2)) {
+ i = ((v->plim_upper <<2) - 1) / 2;
+ }
+
+
+ cprint(POP_Y+7, POP_X+1, "Memory:");
+ speed=memspeed((ulong)mapping(0x100), i*1024, 500, MS_READ);
+ dprint(POP_Y+7, POP_X+10, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_WRITE);
+ dprint(POP_Y+7, POP_X+17, speed, 6, 0);
+ speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY);
+ dprint(POP_Y+7, POP_X+24, speed, 6, 0);
+
+ wait_keyup();
+ while (get_key() == 0);
+ popclear();
+}
+*/
diff --git a/config.h b/config.h
index 068d6ad..5a5c41f 100644
--- a/config.h
+++ b/config.h
@@ -15,6 +15,9 @@
/* to enable. */
#define SERIAL_CONSOLE_DEFAULT 0
+/* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */
+#define SERIAL_TTY 0
+
/* SERIAL_BAUD_RATE - Baud rate for the serial console */
#define SERIAL_BAUD_RATE 9600
diff --git a/controller.c b/controller.c
index 007338f..782394a 100644
--- a/controller.c
+++ b/controller.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V1.70 Specific code (GPL V2.0)
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -29,7 +29,6 @@ extern struct cpu_ident cpu_id;
: /* 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 */
@@ -117,7 +116,6 @@ void print_timings_info(float cas, int rcd, int rp, int ras) {
}
-
void print_fsb_info(float val, const char *text_fsb) {
cprint(LINE_CPU+5, col2, "Settings: ");
@@ -130,8 +128,13 @@ void print_fsb_info(float val, const char *text_fsb) {
col2 += 5;
cprint(LINE_CPU+5, col2, "(DDR");
col2 += 4;
+ if(val < 500) {
dprint(LINE_CPU+5, col2, val*2 ,3 ,0);
- col2 += 3;
+ col2 += 3;
+ } else {
+ dprint(LINE_CPU+5, col2, val*2 ,4 ,0);
+ col2 += 4;
+ }
cprint(LINE_CPU+5, col2, ")");
col2 += 1;
}
@@ -220,6 +223,37 @@ static void setup_amd64(void)
}
}
+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;
+
+ /* 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 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 );
+}
+
static void poll_amd64(void)
{
@@ -392,6 +426,30 @@ static void setup_cnb20(void)
*/
}
+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;
@@ -682,6 +740,27 @@ static void setup_i925(void)
}
+static void setup_p35(void)
+{
+
+ // Activate MMR I/O
+ ulong dev0, capid0;
+
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
+ if (!(dev0 & 0xFFFFC000) & 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;
+}
static void poll_i875(void)
{
@@ -980,17 +1059,23 @@ static void poll_iE7520(void)
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 int p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
+static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
-static int getP4PMmultiplier(void)
+static float getP4PMmultiplier(void)
{
unsigned int msr_lo, msr_hi;
- int coef;
+ float coef;
/* Find multiplier (by MSR) */
if (cpu_id.type == 6) {
- rdmsr(0x2A, msr_lo, msr_hi);
- coef = (msr_lo >> 22) & 0x1F;
+ if((cpu_id.feature_flag >> 7) & 1) {
+ rdmsr(0x198, msr_lo, msr_hi);
+ coef = ((msr_lo >> 8) & 0x1F);
+ if ((msr_lo >> 14) & 0x1) { coef = coef + 0.5f; }
+ } else {
+ rdmsr(0x2A, msr_lo, msr_hi);
+ coef = (msr_lo >> 22) & 0x1F;
+ }
}
else
{
@@ -998,7 +1083,7 @@ static int getP4PMmultiplier(void)
{
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 8) & 0xF;
- coef = p4model1ratios[coef];
+ coef = p4model1ratios[(int)coef];
}
else
{
@@ -1095,11 +1180,69 @@ static void poll_fsb_amd64(void) {
}
+static void poll_fsb_k10(void) {
+
+ unsigned int mcgsrl;
+ unsigned int mcgsth;
+ unsigned long fid, temp2;
+ unsigned long dramchr;
+ float clockratio;
+ double dramclock;
+ float coef;
+
+ /* First, got the FID by MSR */
+ rdmsr(0xc0010071, mcgsrl, mcgsth);
+ fid = mcgsrl & 0x3F;
+
+ /* Extreme simplification. */
+ coef = (fid + 16.0f) / 2.0f;
+
+ /* Next, we need the clock ratio */
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+ temp2 = (dramchr & 0x7);
+
+ switch (temp2) {
+ default:
+ case 0x0:
+ clockratio = coef;
+ break;
+ case 0x1:
+ clockratio = coef * 3.0f/4.0f;
+ break;
+ case 0x2:
+ clockratio = coef * 3.0f/5.0f;
+ break;
+ case 0x3:
+ clockratio = coef * 3.0f/6.0f;
+ break;
+ case 0x4:
+ clockratio = coef * 3.0f/7.0f;
+ break;
+ case 0x5:
+ clockratio = coef * 3.0f/8.0f;
+ break;
+ case 0x6:
+ clockratio = coef * 3.0f/9.0f;
+ break;
+ case 0x7:
+ clockratio = coef * 3.0f/10.0f;
+ break;
+ }
+
+
+ /* Compute the final DRAM Clock */
+ dramclock = (extclock /1000) / clockratio;
+
+ /* ...and print */
+ print_fsb_info(dramclock, "RAM : ");
+
+}
+
static void poll_fsb_i925(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
long *ptr;
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
@@ -1160,7 +1303,7 @@ static void poll_fsb_i945(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
@@ -1198,7 +1341,7 @@ static void poll_fsb_i975(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
@@ -1267,11 +1410,11 @@ static void poll_fsb_i965(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, dev0, fsb_mch;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
long *ptr;
/* Find dramratio */
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0xC00);
mchcfg = *ptr & 0xFFFF;
@@ -1281,7 +1424,9 @@ static void poll_fsb_i965(void) {
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 3: fsb_mch = 667; break;
+ case 4: fsb_mch = 1333; break;
+ case 6: fsb_mch = 1600; break;
}
@@ -1298,20 +1443,42 @@ static void poll_fsb_i965(void) {
case 800:
switch ((mchcfg >> 4)&7) {
case 0: dramratio = 1.0; break;
- case 1: dramratio = 1.33334; break;
- case 2: dramratio = 1.66667; 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.0; break;
- case 2: dramratio = 1.25; break;
- case 3: dramratio = 1.5; break;
- case 4: dramratio = 2.0; break;
+ 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
@@ -1331,12 +1498,61 @@ static void poll_fsb_i965(void) {
}
+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_fsb_info(dramclock, "RAM : ");
+
+ /* Print FSB (only if ECC is not enabled) */
+ cprint(LINE_CPU+4, col +1, "- FSB : ");
+ col += 9;
+ dprint(LINE_CPU+4, col, fsb, 3,0);
+ col += 3;
+ cprint(LINE_CPU+4, col +1, "MHz");
+ col += 4;
+
+}
+
+
static void poll_fsb_nf4ie(void) {
double dramclock, dramratio, fsb;
float mratio, nratio;
unsigned long reg74, reg60;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
/* Find dramratio */
pci_conf_read(0, 0, 2, 0x74, 2, &reg74);
@@ -1376,7 +1592,7 @@ static void poll_fsb_i875(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, smfs;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
/* Find dramratio */
pci_conf_read(0, 0, 0, 0xC6, 2, &mchcfg);
@@ -1418,7 +1634,7 @@ static void poll_fsb_i875(void) {
static void poll_fsb_p4(void) {
ulong fsb, idetect;
- int coef = getP4PMmultiplier();
+ float coef = getP4PMmultiplier();
fsb = ((extclock /1000) / coef);
@@ -1608,6 +1824,57 @@ static void poll_timings_nf4ie(void) {
}
+static void poll_timings_i875(void) {
+
+ ulong dev6, dev62;
+ ulong temp;
+ float cas;
+ int rcd, rp, ras;
+ long *ptr, *ptr2;
+
+ /* Read the MMR Base Address & Define the pointer */
+ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
+
+ /* Now, the PAT ritual ! (Kant and Luciano will love this) */
+ pci_conf_read( 0, 6, 0, 0x40, 4, &dev62);
+ ptr2=(long*)(dev6+0x68);
+
+ if ((dev62&0x3) == 0 && ((*ptr2 >> 14)&1) == 1) {
+ cprint(LINE_CPU+4, col +1, "- PAT : Enabled");
+ } else {
+ cprint(LINE_CPU+4, col +1, "- PAT : Disabled");
+ }
+
+ /* Now, we could check some additionnals timings infos) */
+
+ ptr=(long*)(dev6+0x60);
+ // CAS Latency (tCAS)
+ temp = ((*ptr >> 5)& 0x3);
+ if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; }
+
+ // RAS-To-CAS (tRCD)
+ temp = ((*ptr >> 2)& 0x3);
+ if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; }
+
+ // RAS Precharge (tRP)
+ temp = (*ptr&0x3);
+ if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; }
+
+ // RAS Active to precharge (tRAS)
+ temp = ((*ptr >> 7)& 0x7);
+ ras = 10 - temp;
+
+ // Print timings
+ print_timings_info(cas, rcd, rp, ras);
+
+ // Print 64 or 128 bits mode
+ if (((*ptr2 >> 21)&3) > 0) {
+ cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
+ } else {
+ cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
+ }
+}
+
static void poll_timings_i925(void) {
// Thanks for CDH optis
@@ -1688,55 +1955,151 @@ static void poll_timings_i925(void) {
}
-static void poll_timings_i875(void) {
- ulong dev6, dev62;
- ulong temp;
- float cas;
- int rcd, rp, ras;
- long *ptr, *ptr2;
+static void poll_timings_p35(void) {
- /* Read the MMR Base Address & Define the pointer */
- pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
+ // Thanks for CDH optis
+ ulong dev0, temp, Memory_Check, c0ckectrl, c1ckectrl;
+ ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register;
+ long *ptr;
- /* Now, the PAT ritual ! (Kant and Luciano will love this) */
- pci_conf_read( 0, 6, 0, 0x40, 4, &dev62);
- ptr2=(long*)(dev6+0x68);
+ //Now, read MMR Base Address
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
+ dev0 &= 0xFFFFC000;
- if ((dev62&0x3) == 0 && ((*ptr2 >> 14)&1) == 1) {
- cprint(LINE_CPU+4, col +1, "- PAT : Enabled");
+ ptr = (long*)(dev0+0x265);
+ ODT_Control_Register = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x25D);
+ Precharge_Register = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x252);
+ ACT_Register = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x258);
+ Read_Register = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x244);
+ Misc_Register = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x1E8);
+ Memory_Check = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x260);
+ c0ckectrl = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(dev0+0x660);
+ c1ckectrl = *ptr & 0xFFFFFFFF;
+
+ //Determine DDR or DDR-II
+
+ if (Memory_Check & 1) {
+ cprint(LINE_CPU+4, col +1, "- Type : DDR2");
} else {
- cprint(LINE_CPU+4, col +1, "- PAT : Disabled");
+ cprint(LINE_CPU+4, col +1, "- Type : DDR3");
}
- /* Now, we could check some additionnals timings infos) */
+ // Now, detect timings
+ cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
+ col2 += 9;
- ptr=(long*)(dev6+0x60);
// CAS Latency (tCAS)
- temp = ((*ptr >> 5)& 0x3);
- if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; }
+ temp = ((ODT_Control_Register >> 8)& 0x3F) - 9.0f;
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ (temp < 10)?(col2 += 2):(col2 += 3);
// RAS-To-CAS (tRCD)
- temp = ((*ptr >> 2)& 0x3);
- if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; }
+ temp = (Read_Register >> 17) & 0xF;
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ (temp < 10)?(col2 += 2):(col2 += 3);
// RAS Precharge (tRP)
- temp = (*ptr&0x3);
- if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; }
+ temp = (ACT_Register >> 13) & 0xF;
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ (temp < 10)?(col2 += 2):(col2 += 3);
// RAS Active to precharge (tRAS)
- temp = ((*ptr >> 7)& 0x7);
- ras = 10 - temp;
+ temp = Precharge_Register & 0x3F;
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ (temp < 10)?(col2 += 1):(col2 += 2);
- // Print timings
- print_timings_info(cas, rcd, rp, ras);
+ cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
- // Print 64 or 128 bits mode
- if (((*ptr2 >> 21)&3) > 0) {
- cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
- } else {
- cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
+
+ if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {
+ cprint(LINE_CPU+5, col2+1, "Dual Channel");
+ } else {
+ cprint(LINE_CPU+5, col2+1, "Single Channel");
+ }
+
+}
+
+static void poll_timings_5400(void) {
+
+ // Thanks for CDH optis
+ ulong ambase, mtr1, mtr2, offset, mca, temp;
+ long *ptr;
+
+ //Hard-coded Ambase value (should not be realocated by software when using Memtest86+
+ ambase = 0xFE000000;
+ offset = mtr1 = mtr2 = 0;
+
+ // Will loop until a valid populated channel is found
+ // Bug : DIMM 0 must be populated or it will fall in an endless loop
+ while(((mtr2 & 0xF) < 3) || ((mtr2 & 0xF) > 6)) {
+ ptr = (long*)(ambase+0x378+offset);
+ mtr1 = *ptr & 0xFFFFFFFF;
+
+ ptr = (long*)(ambase+0x37C+offset);
+ mtr2 = *ptr & 0xFFFFFFFF;
+ offset += 0x8000;
+ }
+
+ pci_conf_read( 0, 16, 1, 0x58, 4, &mca);
+
+ //This chipset only supports FB-DIMM (Removed => too long)
+ //cprint(LINE_CPU+4, col +1, "- Type : FBD");
+
+ // Now, detect timings
+ cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
+ col2 += 9;
+
+ // CAS Latency (tCAS)
+ temp = mtr2 & 0xF;
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ col2 += 2;
+
+ // RAS-To-CAS (tRCD)
+ temp = 6 - ((mtr1 >> 10) & 3);
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ col2 += 2;
+
+ // RAS Precharge (tRP)
+ temp = 6 - ((mtr1 >> 8) & 3);
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ cprint(LINE_CPU+5, col2+1, "-");
+ col2 += 2;
+
+ // RAS Active to precharge (tRAS)
+ temp = 16 - (3 * ((mtr1 >> 29) & 3)) + ((mtr1 >> 12) & 3);
+ if(((mtr1 >> 12) & 3) == 3 && ((mtr1 >> 29) & 3) == 2) { temp = 9; }
+
+ dprint(LINE_CPU+5, col2, temp, 1 ,0);
+ (temp < 10)?(col2 += 1):(col2 += 2);
+
+ cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
+
+ if ((mca >> 14) & 1) {
+ cprint(LINE_CPU+5, col2+1, "Single Channel");
+ } else {
+ cprint(LINE_CPU+5, col2+1, "Dual Channel");
}
+
}
static void poll_timings_E7520(void) {
@@ -1953,6 +2316,65 @@ static void poll_timings_amd64(void) {
}
}
+static void poll_timings_k10(void) {
+
+ ulong dramtlr, dramclr, dramchr;
+ int temp;
+ int trcd, trp, tras ;
+
+ cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
+ col2 += 9;
+
+ pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr);
+ pci_conf_read(0, 24, 2, 0x110, 4, &dramclr);
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ // CAS Latency (tCAS)
+ temp = (dramtlr & 0x7) + 1;
+ dprint(LINE_CPU+5, col2, temp , 1 ,0);
+ cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
+
+ // RAS-To-CAS (tRCD)
+ trcd = ((dramtlr >> 4) & 0x3) + 3;
+ dprint(LINE_CPU+5, col2, trcd , 1 ,0);
+ cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
+
+ // RAS Precharge (tRP)
+ trp = ((dramtlr >> 8) & 0x3) + 3;
+ dprint(LINE_CPU+5, col2, trp , 1 ,0);
+ cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
+
+ // RAS Active to precharge (tRAS)
+ tras = ((dramtlr >> 12) & 0xF) + 3;
+ dprint(LINE_CPU+5, col2, tras, 1 ,0);
+ (tras < 10)?(col2 += 1):(col2 += 2);
+ cprint(LINE_CPU+5, col2, "-");
+ col2 += 1;
+
+ // Row Cycle Time (tRC)
+ trp = ((dramtlr >> 16) & 0x1F) + 11;
+ dprint(LINE_CPU+5, col2, trp , 1 ,0);
+ col2 +=2;
+
+ cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
+
+ //Print DDR2 or DDR3
+ if ((dramchr >> 8)&1) {
+ cprint(LINE_CPU+5, col2+1, "DDR-3");
+ } else {
+ cprint(LINE_CPU+5, col2+1, "DDR-2");
+ }
+ col2 += 6;
+
+ // Print 64 or 128 bits mode
+ if ((dramclr >> 4)&1) {
+ cprint(LINE_CPU+5, col2+1, "(Dual)");
+ } else {
+ cprint(LINE_CPU+5, col2+1, "(Single)");
+ }
+
+}
+
static void poll_timings_nf2(void) {
ulong dramtlr, dramtlr2, dramtlr3, temp;
@@ -2020,8 +2442,7 @@ static struct pci_memory_controller controllers[] = {
{ 0x1022, 0x700c, "AMD 762", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
{ 0x1022, 0x700e, "AMD 761", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
{ 0x1022, 0x0000, "AMD K8", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1022, 0x1100, "AMD 8000", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1022, 0x7454, "AMD 8000", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
+ { 0x1022, 0x0000, "AMD K10", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing },
/* SiS */
{ 0x1039, 0x0600, "SiS 600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -2036,7 +2457,6 @@ static struct pci_memory_controller controllers[] = {
{ 0x1039, 0x0735, "SiS 735", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0740, "SiS 740", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0745, "SiS 745", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0755, "SiS 755", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
{ 0x1039, 0x0748, "SiS 748", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0655, "SiS 655", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1039, 0x0648, "SiS 648", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -2046,9 +2466,6 @@ static struct pci_memory_controller controllers[] = {
{ 0x10b9, 0x1531, "Aladdin 4", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x10b9, 0x1541, "Aladdin 5", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x10b9, 0x1644, "ALi Aladdin M1644", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10b9, 0x1687, "ALi M1687", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10b9, 0x1689, "ALi M1689", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10b9, 0x1695, "ALi M1695", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
/* ATi */
{ 0x1002, 0x5830, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
@@ -2057,16 +2474,10 @@ static struct pci_memory_controller controllers[] = {
{ 0x1002, 0x5833, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1002, 0x5954, "ATi Radeon xPress 200", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1002, 0x5A41, "ATi Radeon xPress 200", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5950, "ATi Radeon xPress 200", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1002, 0x5952, "ATi Radeon xPress 3200", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
/* nVidia */
{ 0x10de, 0x01A4, "nVidia nForce", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x10de, 0x01E0, "nVidia nForce2 SPP", 0, poll_fsb_nf2, poll_timings_nf2, setup_nothing, poll_nothing },
- { 0x10de, 0x00D1, "nVidia nForce3", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x00E1, "nForce3 250", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x005E, "nVidia nForce4", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x005F, "nVidia nForce4", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
{ 0x10de, 0x0071, "nForce4 SLI Intel Edition", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing },
/* VIA */
@@ -2089,9 +2500,6 @@ static struct pci_memory_controller controllers[] = {
{ 0x1106, 0x3123, "VIA CLE266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1106, 0x0198, "VIA PT800", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
{ 0x1106, 0x3258, "VIA PT880", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3188, "VIA K8T800", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1106, 0x0282, "VIA K8T800Pro", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1106, 0x3238, "VIA K8T890", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
/* Serverworks */
{ 0x1166, 0x0008, "CNB20HE", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
@@ -2136,9 +2544,18 @@ static struct pci_memory_controller controllers[] = {
{ 0x8086, 0x2770, "Intel i945P/G", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
{ 0x8086, 0x2774, "Intel i955X", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing},
{ 0x8086, 0x277C, "Intel i975X", 0, poll_fsb_i975, poll_timings_i925, setup_i925, poll_nothing},
- { 0x8086, 0x27A0, "Intel P965/G965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing},
- { 0x8086, 0x2790, "Intel Q963/Q965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing}
-};
+ { 0x8086, 0x27A0, "Intel P965/G965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing},
+ { 0x8086, 0x2790, "Intel Q963/Q965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing},
+ { 0x8086, 0x29B0, "Intel Q35", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29C0, "Intel P35/G33", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29D0, "Intel Q33", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29E0, "Intel X38/X48", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x4001, "Intel 5400A", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x4003, "Intel 5400B", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x25D8, "Intel 5000P", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x25D4, "Intel 5000V", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x25C0, "Intel 5000Z", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}
+};
static void print_memory_controller(void)
{
@@ -2237,8 +2654,11 @@ void find_controller(void)
}
}
- // AMD K8 use integrated mem controller. If SB not detected, force detection
- if (ctrl.index == 0 && cpu_id.type == 15 && cpu_id.vend_id[0] == 'A') { ctrl.index = 4; }
+ // AMD K8 use integrated mem controller, force detection
+ if (cpu_id.type == 15 && cpu_id.vend_id[0] == 'A') { ctrl.index = 4; }
+
+ // Same thing for K10. Detect by cpu_id.model = 2, will change it to ext.cpuid > 10 later
+ if (cpu_id.type == 15 && cpu_id.vend_id[0] == 'A' && cpu_id.model == 2) { ctrl.index = 5; }
controllers[ctrl.index].setup_ecc();
/* Don't enable ECC polling by default unless it has
diff --git a/defs.h b/defs.h
index b3b1caf..e1a3350 100644
--- a/defs.h
+++ b/defs.h
@@ -13,7 +13,6 @@
* so the build process should be more robust.
*/
#define LOW_TEST_ADR 0x00002000 /* Final adrs for test code */
-#define HIGH_TEST_ADR 0x00200000 /* Relocation base address */
#define BOOTSEG 0x07c0 /* Segment adrs for inital boot */
#define INITSEG 0x9000 /* Segment adrs for relocated boot */
diff --git a/dmi.c b/dmi.c
index 960ddd2..a538b42 100644
--- a/dmi.c
+++ b/dmi.c
@@ -14,9 +14,6 @@
#include <stdint.h>
-#define DMI_SEARCH_START 0x0000F000
-#define DMI_SEARCH_LENGTH 0x000F0FFF
-#define MAX_DMI_MEMDEVS 32
#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
#define round_down(x,y) ((x) & ~((y)-1))
@@ -104,8 +101,8 @@ struct mem_dev * mem_devs[MAX_DMI_MEMDEVS];
int mem_devs_count=0;
struct md_map * md_maps[MAX_DMI_MEMDEVS];
int md_maps_count=0;
-int bad_devs[MAX_DMI_MEMDEVS];
-int dmi_initialized=0;
+int dmi_err_cnts[MAX_DMI_MEMDEVS];
+short dmi_initialized=0;
int strlen(char * string){
int i=0;
@@ -192,7 +189,7 @@ int open_dmi(void){
void init_dmi(void){
int i;
for(i=0; i < MAX_DMI_MEMDEVS; i++)
- bad_devs[i]=0;
+ dmi_err_cnts[i]=0;
open_dmi();
dmi_initialized=1;
}
@@ -296,10 +293,10 @@ int add_dmi_err(ulong adr){
for(j=0; j < mem_devs_count; j++){
if (mem_devs[j]->header.handle != md_maps[i]->md_handle)
continue;
- if (bad_devs[j]){
+ if (dmi_err_cnts[j]){
found=0;
}else{
- found = bad_devs[j] = 1;
+ found = dmi_err_cnts[j] = 1;
}
}
}
@@ -316,7 +313,7 @@ void print_dmi_err(void){
cprint(v->msg_line, 0,"Bad Memory Devices: ");
of=20;
for ( i=count=0; i < MAX_DMI_MEMDEVS; i++){
- if (!bad_devs[i])
+ if (!dmi_err_cnts[i])
continue;
struct mem_dev *md = mem_devs[i];
if(count++){
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..cacef7e
--- /dev/null
+++ b/error.c
@@ -0,0 +1,547 @@
+
+/* error.c - MemTest-86 Version 3.4
+ *
+ * Released under version 2 of the Gnu Public License.
+ * By Chris Brady, cbrady@sgi.com
+ * ----------------------------------------------------
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.x86-secret.com - http://www.memtest.org
+ */
+
+#include "test.h"
+#include "config.h"
+#include <sys/io.h>
+#include "dmi.h"
+
+extern int test_ticks, nticks, beepmode;
+extern struct tseq tseq[];
+extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
+extern short dmi_initialized;
+void poll_errors();
+
+static void update_err_counts(void);
+static void print_err_counts(void);
+static void common_err();
+static int syn, chan, len=1;
+
+/*
+ * Display data error message. Don't display duplicate errors.
+ */
+void error(ulong *adr, ulong good, ulong bad)
+{
+ ulong xor;
+
+ xor = good ^ bad;
+#ifdef USB_WAR
+ /* Skip any errrors that appear to be due to the BIOS using location
+ * 0x4e0 for USB keyboard support. This often happens with Intel
+ * 810, 815 and 820 chipsets. It is possible that we will skip
+ * a real error but the odds are very low.
+ */
+ if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) {
+ return;
+ }
+#endif
+ common_err(adr, good, bad, xor, 0);
+}
+
+/*
+ * Display address error message.
+ * Since this is strictly an address test, trying to create BadRAM
+ * patterns does not make sense. Just report the error.
+ */
+void ad_err1(ulong *adr1, ulong *mask, ulong bad, ulong good)
+{
+ common_err(adr1, good, bad, (ulong)mask, 1);
+}
+
+/*
+ * Display address error message.
+ * Since this type of address error can also report data errors go
+ * ahead and generate BadRAM patterns.
+ */
+void ad_err2(ulong *adr, ulong bad)
+{
+ common_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad, 0);
+}
+
+static void update_err_counts(void)
+{
+ if (beepmode){
+ beep(600);
+ beep(1000);
+ }
+
+ if (v->pass && v->ecount == 0) {
+ cprint(LINE_MSG, COL_MSG,
+ " ");
+ }
+ ++(v->ecount);
+ tseq[v->test].errors++;
+
+}
+
+static void print_err_counts(void)
+{
+ int i;
+ char *pp;
+
+ if ((v->ecount > 4096) && (v->ecount % 256 != 0)) return;
+
+ dprint(LINE_INFO, COL_ERR, v->ecount, 6, 0);
+ dprint(LINE_INFO, COL_ECC_ERR, v->ecc_ecount, 6, 0);
+
+ /* Paint the error messages on the screen red to provide a vivid */
+ /* indicator that an error has occured */
+ if ((v->printmode == PRINTMODE_ADDRESSES ||
+ v->printmode == PRINTMODE_PATTERNS) &&
+ v->msg_line < 24) {
+ for(i=0, pp=(char *)((SCREEN_ADR+v->msg_line*160+1));
+ i<76; i++, pp+=2) {
+ *pp = 0x47;
+ }
+ }
+}
+
+/*
+ * Print an individual error
+ */
+void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
+{
+ int i, n, x, j, flag=0;
+ ulong page, offset;
+ int patnchg;
+ ulong mb;
+
+ update_err_counts();
+ add_dmi_err((ulong)adr);
+
+ switch(v->printmode) {
+ case PRINTMODE_SUMMARY:
+ /* Don't do anything for a parity error. */
+ if (type == 3) {
+ return;
+ }
+
+ /* Address error */
+ if (type == 1) {
+ xor = good ^ bad;
+ }
+
+ /* Ecc correctable errors */
+ if (type == 2) {
+ /* the bad value is the corrected flag */
+ if (bad) {
+ v->erri.cor_err++;
+ }
+ page = (ulong)adr;
+ offset = good;
+ } else {
+ page = page_of(adr);
+ offset = (ulong)adr & 0xFFF;
+ }
+
+ /* Calc upper and lower error addresses */
+ if (v->erri.low_addr.page > page) {
+ v->erri.low_addr.page = page;
+ v->erri.low_addr.offset = offset;
+ flag++;
+ } else if (v->erri.low_addr.page == page &&
+ v->erri.low_addr.offset > offset) {
+ v->erri.low_addr.offset = offset;
+ v->erri.high_addr.offset = offset;
+ flag++;
+ } else if (v->erri.high_addr.page < page) {
+ v->erri.high_addr.page = page;
+ flag++;
+ }
+ if (v->erri.high_addr.page == page &&
+ v->erri.high_addr.offset < offset) {
+ v->erri.high_addr.offset = offset;
+ flag++;
+ }
+
+ /* Calc bits in error */
+ for (i=0, n=0; i<32; i++) {
+ if (xor>>i & 1) {
+ n++;
+ }
+ }
+ v->erri.tbits += n;
+ if (n > v->erri.max_bits) {
+ v->erri.max_bits = n;
+ flag++;
+ }
+ if (n < v->erri.min_bits) {
+ v->erri.min_bits = n;
+ flag++;
+ }
+ if (v->erri.ebits ^ xor) {
+ flag++;
+ }
+ v->erri.ebits |= xor;
+
+ /* Calc max contig errors */
+ len = 1;
+ if ((ulong)adr == (ulong)v->erri.eadr+4 ||
+ (ulong)adr == (ulong)v->erri.eadr-4 ) {
+ len++;
+ }
+ if (len > v->erri.maxl) {
+ v->erri.maxl = len;
+ flag++;
+ }
+ v->erri.eadr = (ulong)adr;
+
+ if (v->erri.hdr_flag == 0) {
+ clear_scroll();
+ cprint(LINE_HEADER+0, 1, "Error Confidence Value:");
+ cprint(LINE_HEADER+1, 1, " Lowest Error Address:");
+ cprint(LINE_HEADER+2, 1, " Highest Error Address:");
+ cprint(LINE_HEADER+3, 1, " Bits in Error Mask:");
+ cprint(LINE_HEADER+4, 1, " Bits in Error - Total:");
+ cprint(LINE_HEADER+4, 29, "Min: Max: Avg:");
+ cprint(LINE_HEADER+5, 1, " Max Contiguous Errors:");
+ cprint(LINE_HEADER+6, 1, "ECC Correctable Errors:");
+ cprint(LINE_HEADER+7, 1, "Errors per Memory Slot:");
+ x = 24;
+ if (dmi_initialized) {
+ for ( i=0; i < MAX_DMI_MEMDEVS;){
+ n = LINE_HEADER+7;
+ for (j=0; j<4; j++) {
+ if (dmi_err_cnts[i] >= 0) {
+ dprint(n, x, i, 2, 0);
+ cprint(n, x+2, ": 0");
+ }
+ i++;
+ n++;
+ }
+ x += 10;
+ }
+ }
+
+ cprint(LINE_HEADER+0, 64, "Test Errors");
+ v->erri.hdr_flag++;
+ }
+ if (flag) {
+ /* Calc bits in error */
+ for (i=0, n=0; i<32; i++) {
+ if (v->erri.ebits>>i & 1) {
+ n++;
+ }
+ }
+ page = v->erri.low_addr.page;
+ offset = v->erri.low_addr.offset;
+ mb = page >> 8;
+ hprint(LINE_HEADER+1, 25, page);
+ hprint2(LINE_HEADER+1, 33, offset, 3);
+ cprint(LINE_HEADER+1, 36, " - . MB");
+ dprint(LINE_HEADER+1, 39, mb, 5, 0);
+ dprint(LINE_HEADER+1, 45, ((page & 0xF)*10)/16, 1, 0);
+ page = v->erri.high_addr.page;
+ offset = v->erri.high_addr.offset;
+ mb = page >> 8;
+ hprint(LINE_HEADER+2, 25, page);
+ hprint2(LINE_HEADER+2, 33, offset, 3);
+ cprint(LINE_HEADER+2, 36, " - . MB");
+ dprint(LINE_HEADER+2, 39, mb, 5, 0);
+ dprint(LINE_HEADER+2, 45, ((page & 0xF)*10)/16, 1, 0);
+ hprint(LINE_HEADER+3, 25, v->erri.ebits);
+ dprint(LINE_HEADER+4, 25, n, 2, 1);
+ dprint(LINE_HEADER+4, 34, v->erri.min_bits, 2, 1);
+ dprint(LINE_HEADER+4, 42, v->erri.max_bits, 2, 1);
+ dprint(LINE_HEADER+4, 50, v->erri.tbits/v->ecount, 2, 1);
+ dprint(LINE_HEADER+5, 25, v->erri.maxl, 7, 1);
+ x = 28;
+ for ( i=0; i < MAX_DMI_MEMDEVS;){
+ n = LINE_HEADER+7;
+ for (j=0; j<4; j++) {
+ if (dmi_err_cnts[i] > 0) {
+ dprint (n, x, dmi_err_cnts[i], 7, 1);
+ }
+ i++;
+ n++;
+ }
+ x += 10;
+ }
+
+ for (i=0; tseq[i].msg != NULL; i++) {
+ dprint(LINE_HEADER+1+i, 66, i, 2, 0);
+ dprint(LINE_HEADER+1+i, 68, tseq[i].errors, 8, 0);
+ }
+ }
+ if (v->erri.cor_err) {
+ dprint(LINE_HEADER+6, 25, v->erri.cor_err, 8, 1);
+ }
+ break;
+
+ case PRINTMODE_ADDRESSES:
+ /* Don't display duplicate errors */
+ if ((ulong)adr == (ulong)v->erri.eadr &&
+ xor == v->erri.exor) {
+ return;
+ }
+ if (v->erri.hdr_flag == 0) {
+ clear_scroll();
+ cprint(LINE_HEADER, 0,
+"Tst Pass Failing Address Good Bad Err-Bits Count Chan");
+ cprint(LINE_HEADER+1, 0,
+"--- ---- ----------------------- -------- -------- -------- ----- ----");
+ v->erri.hdr_flag++;
+ }
+ /* Check for keyboard input */
+ check_input();
+ scroll();
+
+ if ( type == 2 || type == 3) {
+ page = (ulong)adr;
+ offset = good;
+ } else {
+ page = page_of(adr);
+ offset = ((unsigned long)adr) & 0xFFF;
+ }
+ mb = page >> 8;
+ dprint(v->msg_line, 0, v->test, 3, 0);
+ dprint(v->msg_line, 4, v->pass, 5, 0);
+ hprint(v->msg_line, 11, page);
+ hprint2(v->msg_line, 19, offset, 3);
+ cprint(v->msg_line, 22, " - . MB");
+ dprint(v->msg_line, 25, mb, 5, 0);
+ dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0);
+
+ if (type == 3) {
+ /* ECC error */
+ cprint(v->msg_line, 36,
+ bad?"corrected ": "uncorrected ");
+ hprint2(v->msg_line, 60, syn, 4);
+ cprint(v->msg_line, 68, "ECC");
+ dprint(v->msg_line, 74, chan, 2, 0);
+ } else if (type == 2) {
+ cprint(v->msg_line, 36, "Parity error detected ");
+ } else {
+ hprint(v->msg_line, 36, good);
+ hprint(v->msg_line, 46, bad);
+ hprint(v->msg_line, 56, xor);
+ dprint(v->msg_line, 66, v->ecount, 5, 0);
+ v->erri.exor = xor;
+ }
+ v->erri.eadr = (ulong)adr;
+ print_err_counts();
+ break;
+
+ case PRINTMODE_PATTERNS:
+ if (v->erri.hdr_flag == 0) {
+ clear_scroll();
+ v->erri.hdr_flag++;
+ }
+ /* Do not do badram patterns from test 0 or 5 */
+ if (v->test == 0 || v->test == 5) {
+ return;
+ }
+ /* Only do patterns for data errors */
+ if ( type != 0) {
+ return;
+ }
+ /* Process the address in the pattern administration */
+ patnchg=insertaddress ((ulong) adr);
+ if (patnchg) {
+ printpatn();
+ }
+ break;
+
+ case PRINTMODE_NONE:
+ if (v->erri.hdr_flag == 0) {
+ clear_scroll();
+ v->erri.hdr_flag++;
+ }
+ break;
+ }
+}
+
+/*
+ * Print an ecc error
+ */
+void print_ecc_err(unsigned long page, unsigned long offset,
+ int corrected, unsigned short syndrome, int channel)
+{
+ ++(v->ecc_ecount);
+ syn = syndrome;
+ chan = channel;
+ common_err((ulong *)page, offset, corrected, 0, 2);
+}
+
+#ifdef PARITY_MEM
+/*
+ * Print a parity error message
+ */
+void parity_err( unsigned long edi, unsigned long esi)
+{
+ unsigned long addr;
+
+ if (v->test == 5) {
+ addr = esi;
+ } else {
+ addr = edi;
+ }
+ common_err((ulong *)addr, addr & 0xFFF, 0, 0, 3);
+}
+#endif
+
+/*
+ * Print the pattern array as a LILO boot option addressing BadRAM support.
+ */
+void printpatn (void)
+{
+ int idx=0;
+ int x;
+
+ /* Check for keyboard input */
+ check_input();
+
+ if (v->numpatn == 0)
+ return;
+
+ scroll();
+
+ cprint (v->msg_line, 0, "badram=");
+ x=7;
+
+ for (idx = 0; idx < v->numpatn; idx++) {
+
+ if (x > 80-22) {
+ scroll();
+ x=7;
+ }
+ cprint (v->msg_line, x, "0x");
+ hprint (v->msg_line, x+2, v->patn[idx].adr );
+ cprint (v->msg_line, x+10, ",0x");
+ hprint (v->msg_line, x+13, v->patn[idx].mask);
+ if (idx+1 < v->numpatn)
+ cprint (v->msg_line, x+21, ",");
+ x+=22;
+ }
+}
+
+/*
+ * Show progress by displaying elapsed time and update bar graphs
+ */
+void do_tick(void)
+{
+ int i, n, pct;
+ ulong h, l, t;
+
+ /* FIXME only print serial error messages from the tick handler */
+ if (v->ecount) {
+ print_err_counts();
+ }
+
+ nticks++;
+ v->total_ticks++;
+
+ pct = 100*nticks/test_ticks;
+ dprint(1, COL_MID+4, pct, 3, 0);
+ i = (BAR_SIZE * pct) / 100;
+ while (i > v->tptr) {
+ if (v->tptr >= BAR_SIZE) {
+ break;
+ }
+ cprint(1, COL_MID+9+v->tptr, "#");
+ v->tptr++;
+ }
+
+ pct = 100*v->total_ticks/v->pass_ticks;
+ dprint(0, COL_MID+4, pct, 3, 0);
+ i = (BAR_SIZE * pct) / 100;
+ while (i > v->pptr) {
+ if (v->pptr >= BAR_SIZE) {
+ break;
+ }
+ cprint(0, COL_MID+9+v->pptr, "#");
+ v->pptr++;
+ }
+
+ if (v->ecount && v->printmode == PRINTMODE_SUMMARY) {
+ /* Compute confidence score */
+ pct = 0;
+
+ /* If there are no errors within 1mb of start - end addresses */
+ h = v->pmap[v->msegs - 1].end - 0x100;
+ if (v->erri.low_addr.page > 0x100 &&
+ v->erri.high_addr.page < h) {
+ pct += 8;
+ }
+
+ /* Errors for only some tests */
+ if (v->pass) {
+ for (i=0, n=0; tseq[i].msg != NULL; i++) {
+ if (tseq[i].errors == 0) {
+ n++;
+ }
+ }
+ pct += n*3;
+ } else {
+ for (i=0, n=0; i<v->test; i++) {
+ if (tseq[i].errors == 0) {
+ n++;
+ }
+ }
+ pct += n*2;
+
+ }
+
+ /* Only some bits in error */
+ n = 0;
+ if (v->erri.ebits & 0xf) n++;
+ if (v->erri.ebits & 0xf0) n++;
+ if (v->erri.ebits & 0xf00) n++;
+ if (v->erri.ebits & 0xf000) n++;
+ if (v->erri.ebits & 0xf0000) n++;
+ if (v->erri.ebits & 0xf00000) n++;
+ if (v->erri.ebits & 0xf000000) n++;
+ if (v->erri.ebits & 0xf0000000) n++;
+ pct += (8-n)*2;
+
+ /* Adjust the score */
+ pct = pct*100/22;
+/*
+ if (pct > 100) {
+ pct = 100;
+ }
+*/
+ dprint(LINE_HEADER+0, 25, pct, 3, 1);
+ }
+
+
+ /* We can't do the elapsed time unless the rdtsc instruction
+ * is supported
+ */
+ if (v->rdtsc) {
+ asm __volatile__(
+ "rdtsc":"=a" (l),"=d" (h));
+ asm __volatile__ (
+ "subl %2,%0\n\t"
+ "sbbl %3,%1"
+ :"=a" (l), "=d" (h)
+ :"g" (v->startl), "g" (v->starth),
+ "0" (l), "1" (h));
+ t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
+ t += (l / v->clks_msec) / 1000;
+ i = t % 60;
+ dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0);
+ dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0);
+ t /= 60;
+ i = t % 60;
+ dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0);
+ dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0);
+ t /= 60;
+ dprint(LINE_TIME, COL_TIME, t, 4, 0);
+ }
+
+
+ /* Check for keyboard input */
+ check_input();
+
+ /* Poll for ECC errors */
+ poll_errors();
+}
diff --git a/head.S b/head.S
index 36db092..c39dc8e 100644
--- a/head.S
+++ b/head.S
@@ -30,6 +30,7 @@
#define X86_CACHE 24
#define X86_PWRCAP 40
#define X86_EXT 44
+#define X86_FFL 48
.code32
.globl startup_32
@@ -345,7 +346,8 @@ have_cpuid:
# CDH end
#
- movl %eax, X86_EXT(%esi) #save complete extended CPUID to X86_EXT
+ movl %eax, X86_EXT(%esi) # save complete extended CPUID to X86_EXT
+ movl %ecx, X86_FFL(%esi) # save ECX Feature Flags to X86_FFL
movb %al, %cl # save reg for future use
andb $0x0f, %ah # mask processor family
movb %ah, X86(%esi)
diff --git a/head.s b/head.s
new file mode 100644
index 0000000..577fc66
--- /dev/null
+++ b/head.s
@@ -0,0 +1,964 @@
+# 1 "head.S"
+# 1 "<built-in>"
+# 1 "<command line>"
+# 1 "head.S"
+# 14 "head.S"
+.text
+
+# 1 "defs.h" 1
+# 17 "head.S" 2
+# 1 "config.h" 1
+# 18 "head.S" 2
+# 1 "test.h" 1
+# 19 "head.S" 2
+# 35 "head.S"
+ .code32
+ .globl startup_32
+startup_32:
+ cld
+ cli
+
+
+ testl %esp, %esp
+ jnz 0f
+ movl $(0x00002000 + _GLOBAL_OFFSET_TABLE_), %esp
+ leal stack_top@GOTOFF(%esp), %esp
+0:
+
+
+ call 0f
+0: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx
+
+
+ leal stack_top@GOTOFF(%ebx), %esp
+
+
+ leal gdt@GOTOFF(%ebx), %eax
+ movl %eax, 2 + gdt_descr@GOTOFF(%ebx)
+ lgdt gdt_descr@GOTOFF(%ebx)
+ leal flush@GOTOFF(%ebx), %eax
+ pushl $0x10
+ pushl %eax
+ lret
+flush: movl $0x18, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+
+
+
+ cmpl $1, zerobss@GOTOFF(%ebx)
+ jnz zerobss_done
+ xorl %eax, %eax
+ leal _bss@GOTOFF(%ebx), %edi
+ leal _end@GOTOFF(%ebx), %ecx
+ subl %edi, %ecx
+1: movl %eax, (%edi)
+ addl $4, %edi
+ subl $4, %ecx
+ jnz 1b
+ movl $0, zerobss@GOTOFF(%ebx)
+zerobss_done:
+
+
+
+
+ cmpl $1, clear_display@GOTOFF(%ebx)
+ jnz clear_display_done
+ movw $0x0720, %ax
+ movl $0xb8000, %edi
+ movl $0xc0000, %ecx
+1: movw %ax, (%edi)
+ addl $2, %edi
+ cmpl %ecx, %edi
+ jnz 1b
+ movl $0, clear_display@GOTOFF(%ebx)
+clear_display_done:
+
+
+
+
+
+ leal idt@GOTOFF(%ebx), %edi
+
+ leal vec0@GOTOFF(%ebx), %edx
+ movl $(0x10 << 16),%eax
+ movw %dx, %ax
+ movw $0x8E00, %dx
+ movl %eax, (%edi)
+ movl %edx, 4(%edi)
+ addl $8, %edi
+
+ leal vec1@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec2@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec3@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec4@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec5@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec6@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec7@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec8@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec9@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec10@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec11@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec12@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec13@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec14@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec15@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec16@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec17@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec18@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+ leal vec19@GOTOFF(%ebx),%edx
+ movl $(0x10 << 16),%eax
+ movw %dx,%ax
+ movw $0x8E00,%dx
+ movl %eax,(%edi)
+ movl %edx,4(%edi)
+ addl $8,%edi
+
+
+ leal idt@GOTOFF(%ebx), %eax
+ movl %eax, 2 + idt_descr@GOTOFF(%ebx)
+ lidt idt_descr@GOTOFF(%ebx)
+
+
+
+ leal cpu_id@GOTOFF(%ebx), %esi
+ movl %ebx, %edi
+
+ movl $-1, 4(%esi) # -1 for no CPUID initially
+
+
+
+ movl $3, 0(%esi) # at least 386
+ pushfl # push EFLAGS
+ popl %eax # get EFLAGS
+ movl %eax, %ecx # save original EFLAGS
+ xorl $0x40000, %eax # flip AC bit in EFLAGS
+ pushl %eax # copy to EFLAGS
+ popfl # set EFLAGS
+ pushfl # get new EFLAGS
+ popl %eax # put it in eax
+ xorl %ecx, %eax # change in flags
+ andl $0x40000, %eax # check if AC bit changed
+ je id_done
+
+ movl $4, 0(%esi) # at least 486
+ movl %ecx, %eax
+ xorl $0x200000, %eax # check ID flag
+ pushl %eax
+ popfl # if we are on a straight 486DX, SX, or
+ pushfl # 487SX we can't change it
+ popl %eax
+ xorl %ecx, %eax
+ pushl %ecx # restore original EFLAGS
+ popfl
+ andl $0x200000, %eax
+ jne have_cpuid
+
+
+ xorw %ax, %ax # clear ax
+ sahf # clear flags
+ movw $5, %ax
+ movw $2, %bx
+ div %bl # do operation that does not change flags
+ lahf # get flags
+ cmp $2, %ah # check for change in flags
+ jne id_done # if not Cyrix
+ movl $2, 0(%esi) # Use two to identify as Cyrix
+ jmp id_done
+
+have_cpuid:
+
+ xorl %eax, %eax # call CPUID with 0 -> return vendor ID
+ cpuid
+ movl %eax, 4(%esi) # save CPUID level
+ movl %ebx, 12(%esi) # first 4 chars
+ movl %edx, 12 +4(%esi) # next 4 chars
+ movl %ecx, 12 +8(%esi) # last 4 chars
+
+ orl %eax, %eax # do we have processor info as well?
+ je id_done
+
+ movl $1, %eax # Use the CPUID instruction to get CPU type
+ cpuid
+
+
+
+ # CDH start
+ # Check FPU, initialize if present
+
+ testl $1, %edx # FPU available?
+ jz no_fpu
+ finit
+
+ no_fpu:
+
+ # CDH end
+
+
+ movl %eax, 44(%esi) # save complete extended CPUID to 44
+ movl %ecx, 48(%esi) # save ECX Feature Flags to 48
+ movb %al, %cl # save reg for future use
+ andb $0x0f, %ah # mask processor family
+ movb %ah, 0(%esi)
+ andb $0xf0, %al # mask model
+ shrb $4, %al
+ movb %al, 1(%esi)
+ andb $0x0f, %cl # mask mask revision
+ movb %cl, 2(%esi)
+ movl %edx, 8(%esi)
+
+ movl $0, 24(%esi)
+ movl $0, 24 +4(%esi)
+ movl $0, 24 +8(%esi)
+ movl $0, 24 +12(%esi)
+
+ movl 12 +8(%esi), %eax
+ cmpl $0x6c65746e,%eax # Is this an Intel CPU? "GenuineIntel"
+ jne not_intel
+ movb %bl, 40(%esi) # Store BrandID in AMD PWRCAP if the CPU is from Intel
+ movl $2, %eax # Use the CPUID instruction to get cache info
+ cpuid
+ movl %eax, 24(%esi)
+ movl %ebx, 24 +4(%esi)
+ movl %ecx, 24 +8(%esi)
+ movl %edx, 24 +12(%esi)
+ jmp id_done
+
+not_intel:
+ movl 12 +8(%esi),%eax
+ cmpl $0x444d4163, %eax # Is this an AMD CPU? "AuthenticAMD"
+ jne not_amd
+
+ movl $0x80000005, %eax # Use the CPUID instruction to get cache info
+ cpuid
+ movl %ecx, 24(%esi)
+ movl %edx, 24 +4(%esi)
+ movl $0x80000006,%eax # Use the CPUID instruction to get cache info
+ cpuid
+ movl %ecx,24 +8(%esi)
+ movl $0x80000007,%eax # Use the CPUID instruction to get AMD Powercap
+ cpuid
+ movl %edx,40(%esi)
+
+not_amd:
+ movl 12 +8(%esi), %eax
+ cmpl $0x3638784D, %eax # Is this a Transmeta CPU? "GenuineTMx86"
+ jne not_transmeta
+
+ movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
+ cpuid
+ cmp $6, %al # Is cache info available?
+ jb id_done
+
+ movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
+ cpuid
+ movl %ecx, 24(%esi)
+ movl %edx, 24 +4(%esi)
+ movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
+ cpuid
+ movl %ecx, 24 +8(%esi)
+
+not_transmeta:
+ movl 12 +8(%esi), %eax
+ cmpl $0x64616574, %eax # Is this a Via/Cyrix CPU? "CyrixInstead"
+ jne not_cyrix
+
+ movl 4(%esi), %eax # get CPUID level
+ cmpl $2, %eax # Is there cache information available ?
+ jne id_done
+
+ movl $2, %eax # Use the CPUID instruction to get cache info
+ cpuid
+ movl %edx, 24(%esi)
+
+not_cyrix:
+ movl 12 +8(%esi), %eax
+ cmpl $0x736C7561, %eax # Is this a Via/Centaur CPU "CentaurHauls"
+ jne not_centaur
+
+ movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
+ cpuid
+ cmp $6, %al # Is cache info available?
+ jb id_done
+
+ movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
+ cpuid
+ movl %ecx, 24(%esi)
+ movl %edx, 24 +4(%esi)
+ movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
+ cpuid
+ movl %ecx, 24 +8(%esi)
+
+
+not_centaur:
+id_done:
+ movl %edi, %ebx
+
+ leal _dl_start@GOTOFF(%ebx), %eax
+ call *%eax
+ call do_test
+
+ pushfl
+ pushl %cs
+ call 0f
+0: pushl $0
+ pushl $257
+ jmp int_hand
+
+vec0:
+ pushl $0
+ pushl $0
+ jmp int_hand
+vec1:
+ pushl $0
+ pushl $1
+ jmp int_hand
+
+vec2:
+ pushl $0
+ pushl $2
+ jmp int_hand
+
+vec3:
+ pushl $0
+ pushl $3
+ jmp int_hand
+
+vec4:
+ pushl $0
+ pushl $4
+ jmp int_hand
+
+vec5:
+ pushl $0
+ pushl $5
+ jmp int_hand
+
+vec6:
+ pushl $0
+ pushl $6
+ jmp int_hand
+
+vec7:
+ pushl $0
+ pushl $7
+ jmp int_hand
+
+vec8:
+
+ pushl $8
+ jmp int_hand
+
+vec9:
+ pushl $0
+ pushl $9
+ jmp int_hand
+
+vec10:
+
+ pushl $10
+ jmp int_hand
+
+vec11:
+
+ pushl $11
+ jmp int_hand
+
+vec12:
+
+ pushl $12
+ jmp int_hand
+
+vec13:
+
+ pushl $13
+ jmp int_hand
+
+vec14:
+
+ pushl $14
+ jmp int_hand
+
+vec15:
+ pushl $0
+ pushl $15
+ jmp int_hand
+
+vec16:
+ pushl $0
+ pushl $16
+ jmp int_hand
+
+vec17:
+
+ pushl $17
+ jmp int_hand
+
+vec18:
+ pushl $0
+ pushl $18
+ jmp int_hand
+
+vec19:
+ pushl $0
+ pushl $19
+ jmp int_hand
+
+int_hand:
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+
+
+ leal 20(%esp), %eax
+ pushl %eax
+
+ pushl %esp
+ call inter
+ addl $8, %esp
+
+ popl %ebp
+ popl %esi
+ popl %edi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+ iret
+
+
+
+
+.align 4
+.word 0
+idt_descr:
+ .word 20*8-1 # idt contains 32 entries
+ .long 0
+
+idt:
+ .fill 20,8,0 # idt is uninitialized
+
+gdt_descr:
+ .word gdt_end - gdt - 1
+ .long 0
+
+.align 4
+.globl gdt, gdt_end
+gdt:
+ .quad 0x0000000000000000
+ .quad 0x0000000000000000
+ .quad 0x00cf9a000000ffff
+ .quad 0x00cf92000000ffff
+
+ .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB)
+ .word 0 # base address = (0x9000 +0x20)
+ .byte 0x00, 0x9b # code read/exec/accessed
+ .byte 0x00, 0x00 # granularity = bytes
+
+
+ .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB)
+ .word 0 # base address = (0x9000 +0x20)
+ .byte 0x00, 0x93 # data read/write/accessed
+ .byte 0x00, 0x00 # granularity = bytes
+
+gdt_end:
+
+.data
+
+.macro ptes64 start, count=64
+.quad \start + 0x0000000 + 0xE3
+.quad \start + 0x0200000 + 0xE3
+.quad \start + 0x0400000 + 0xE3
+.quad \start + 0x0600000 + 0xE3
+.quad \start + 0x0800000 + 0xE3
+.quad \start + 0x0A00000 + 0xE3
+.quad \start + 0x0C00000 + 0xE3
+.quad \start + 0x0E00000 + 0xE3
+.if \count-1
+ptes64 "(\start+0x01000000)",\count-1
+.endif
+.endm
+
+.macro maxdepth depth=1
+.if \depth-1
+maxdepth \depth-1
+.endif
+.endm
+
+maxdepth
+
+.balign 4096
+.globl pd0
+pd0:
+ ptes64 0x0000000000000000
+
+.balign 4096
+.globl pd1
+pd1:
+ ptes64 0x0000000040000000
+
+.balign 4096
+.globl pd2
+pd2:
+ ptes64 0x0000000080000000
+
+.balign 4096
+.globl pd3
+pd3:
+ ptes64 0x00000000C0000000
+
+.balign 4096
+.globl pdp
+pdp:
+ .long pd0 + 1
+ .long 0
+ .long pd1 + 1
+ .long 0
+
+ .long pd2 + 1
+ .long 0
+
+ .long pd3 + 1
+ .long 0
+.previous
+
+
+
+ .globl query_pcbios
+query_pcbios:
+
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ pushl %ebp
+ call 1f
+1: popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+
+
+ leal startup_32@GOTOFF(%ebx), %esi
+
+
+ movl %esi, %eax
+ shrl $4, %eax
+ movw %ax, 2 + realptr@GOTOFF(%ebx)
+
+
+ leal prot@GOTOFF(%ebx), %eax
+ movl %eax, protptr@GOTOFF(%ebx)
+
+
+ movl %esi, %eax
+ shll $16, %eax # Base low
+
+ movl %esi, %ecx
+ shrl $16, %ecx
+ andl $0xff, %ecx
+
+ movl %esi, %edx
+ andl $0xff000000, %edx
+ orl %edx, %ecx
+
+
+ andl $0x0000ffff, 0x20 + 0 + gdt@GOTOFF(%ebx)
+ orl %eax, 0x20 + 0 + gdt@GOTOFF(%ebx)
+ andl $0x00ffff00, 0x20 + 4 + gdt@GOTOFF(%ebx)
+ orl %ecx, 0x20 + 4 + gdt@GOTOFF(%ebx)
+ andl $0x0000ffff, 0x28 + 0 + gdt@GOTOFF(%ebx)
+ orl %eax, 0x28 + 0 + gdt@GOTOFF(%ebx)
+ andl $0x00ffff00, 0x28 + 4 + gdt@GOTOFF(%ebx)
+ orl %ecx, 0x28 + 4 + gdt@GOTOFF(%ebx)
+
+
+ leal gdt@GOTOFF(%ebx), %eax
+ movl %eax, 2 + gdt_descr@GOTOFF(%ebx)
+
+ lidt idt_real@GOTOFF(%ebx)
+
+
+
+
+ movl $0x28, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+
+ leal stack@GOTOFF(%ebx), %ecx
+
+ leal mem_info@GOTOFF(%ebx), %edi
+
+
+ ljmp $0x20, $1f - startup_32
+1:
+ .code16
+
+
+ movl %cr0,%eax
+ andl $~((1 << 31)|(1<<0)),%eax
+ movl %eax,%cr0
+
+
+
+
+ ljmp *(realptr - startup_32)
+real:
+
+
+
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+
+ movl %ecx, %eax
+ shrl $4, %eax
+ movw %ax, %ss
+ subl %ecx, %esp
+
+
+ pushl %ebx
+
+
+ shrl $4, %edi
+ movl %edi, %ds
+
+
+ sti
+
+# Get memory size (extended mem, kB)
+
+
+
+ xorl %eax, %eax
+ movl %eax, (0x00)
+ movl %eax, (0x04)
+ movl %eax, (0x08)
+
+# Try three different memory detection schemes. First, try
+# e820h, which lets us assemble a memory map, then try e801h,
+# which returns a 32-bit memory size, and finally 88h, which
+# returns 0-64m
+
+# method E820H:
+# the memory map from hell. e820h returns memory classified into
+# a whole bunch of different types, and allows memory holes and
+# everything. We scan through this memory map and build a list
+# of the first 32 memory areas, which we return at [0x0c].
+# This is documented at http:
+
+meme820:
+ xorl %ebx, %ebx # continuation counter
+ movw $0x0c, %di # point into the whitelist
+ # so we can have the bios
+ # directly write into it.
+
+jmpe820:
+ movl $0x0000e820, %eax # e820, upper word zeroed
+ movl $0x534d4150, %edx # ascii 'SMAP'
+ movl $20, %ecx # size of the e820rec
+ pushw %ds # data record.
+ popw %es
+ int $0x15 # make the call
+ jc bail820 # fall to e801 if it fails
+
+ cmpl $0x534d4150, %eax # check the return is `0x534d4150'
+ jne bail820 # fall to e801 if it fails
+
+# cmpl $1, 16(%di) # is this usable memory?
+# jne again820
+
+ # If this is usable memory, we save it by simply advancing %di by
+ # sizeof(e820rec).
+
+good820:
+ movb (0x08), %al # up to 32 entries
+ cmpb $32, %al
+ jnl bail820
+
+ incb (0x08)
+ movw %di, %ax
+ addw $20, %ax
+ movw %ax, %di
+again820:
+ cmpl $0, %ebx # check to see if
+ jne jmpe820 # %ebx is set to EOF
+bail820:
+
+
+# method E801H:
+# memory size is in 1k chunksizes, to avoid confusing loadlin.
+# we store the 0xe801 memory size in a completely different place,
+# because it will most likely be longer than 16 bits.
+
+meme801:
+ stc # fix to work around buggy
+ xorw %cx,%cx # BIOSes which dont clear/set
+ xorw %dx,%dx # carry on pass/error of
+ # e801h memory size call
+ # or merely pass cx,dx though
+ # without changing them.
+ movw $0xe801, %ax
+ int $0x15
+ jc mem88
+
+ cmpw $0x0, %cx # Kludge to handle BIOSes
+ jne e801usecxdx # which report their extended
+ cmpw $0x0, %dx # memory in AX/BX rather than
+ jne e801usecxdx # CX/DX. The spec I have read
+ movw %ax, %cx # seems to indicate AX/BX
+ movw %bx, %dx # are more reasonable anyway...
+
+e801usecxdx:
+ andl $0xffff, %edx # clear sign extend
+ shll $6, %edx # and go from 64k to 1k chunks
+ movl %edx, (0x04) # store extended memory size
+ andl $0xffff, %ecx # clear sign extend
+ addl %ecx, (0x04) # and add lower memory into
+ # total size.
+
+# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
+# 64mb, depending on the bios) in ax.
+mem88:
+
+ movb $0x88, %ah
+ int $0x15
+ movw %ax, (0x00)
+
+
+# check for APM BIOS
+ movw $0x5300, %ax # APM BIOS installation check
+ xorw %bx, %bx
+ int $0x15
+ jc done_apm_bios # error -> no APM BIOS
+
+ cmpw $0x504d, %bx # check for "PM" signature
+ jne done_apm_bios # no signature -> no APM BIOS
+
+ movw $0x5304, %ax # Disconnect first just in case
+ xorw %bx, %bx
+ int $0x15 # ignore return code
+
+ movw $0x5301, %ax # Real Mode connect
+ xorw %bx, %bx
+ int $0x15
+ jc done_apm_bios # error
+
+ movw $0x5308, %ax # Disable APM
+ mov $0xffff, %bx
+ xorw %cx, %cx
+ int $0x15
+
+done_apm_bios:
+
+
+
+ cli
+
+
+ popl %ebx
+
+
+ movw %cs, %ax
+ movw %ax, %ds
+
+
+ addr32 lgdt gdt_descr - startup_32
+
+
+
+ movl %cr0,%eax
+ orl $(1<<0),%eax
+ movl %eax,%cr0
+
+
+ data32 ljmp *(protptr - startup_32)
+prot:
+ .code32
+
+ movl $0x18, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %eax, %ss
+
+
+ leal stack@GOTOFF(%ebx), %eax
+ addl %eax, %esp
+
+
+ popl %ebp
+ popl %edi
+ popl %esi
+ popl %ebx
+ movl $1, %eax
+ ret
+
+realptr:
+ .word real - startup_32
+ .word 0x0000
+protptr:
+ .long 0
+ .long 0x10
+
+idt_real:
+ .word 0x400 - 1 # idt limit ( 256 entries)
+ .word 0, 0 # idt base = 0L
+
+.data
+zerobss: .long 1
+clear_display: .long 1
+.previous
+.data
+.balign 16
+ .globl mem_info
+mem_info:
+ . = . + 0x28c
+.previous
+.bss
+.balign 16
+stack:
+ . = . + 4096
+stack_top:
+.previous
diff --git a/init.c b/init.c
index 14a9c38..741079c 100644
--- a/init.c
+++ b/init.c
@@ -3,9 +3,9 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V1.70 Specific code (GPL V2.0)
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.x86-secret.com - http://www.memtest.org
+ * http://www.canardplus.com - http://www.memtest.org
*/
#include "test.h"
@@ -15,9 +15,16 @@
#include "pci.h"
#include "io.h"
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+extern struct tseq tseq[];
extern short memsz_mode;
extern short firmware;
-int beepmode;
+extern short dmi_initialized;
+extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
struct cpu_ident cpu_id;
ulong st_low, st_high;
@@ -25,10 +32,14 @@ ulong end_low, end_high;
ulong cal_low, cal_high;
ulong extclock;
-static ulong memspeed(ulong src, ulong len, int iter);
+int l1_cache, l2_cache;
+int tsc_invariable = 0;
+
+ulong memspeed(ulong src, ulong len, int iter, int type);
static void cpu_type(void);
static void cacheable(void);
static int cpuspeed(void);
+int beepmode;
static void display_init(void)
{
@@ -52,7 +63,7 @@ static void display_init(void)
for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) {
*pp = 0x20;
}
- cprint(0, 0, " Memtest86 v1.70 ");
+ cprint(0, 0, " Memtest86 v2.00 ");
for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) {
*pp = 0xA4;
@@ -102,9 +113,36 @@ void init(void)
beepmode = BEEP_MODE;
v->test = 0;
+ v->pass = 0;
+ v->msg_line = 0;
+ v->ecount = 0;
+ v->ecc_ecount = 0;
v->testsel = -1;
v->msg_line = LINE_SCROLL-1;
v->scroll_start = v->msg_line * 160;
+ v->erri.low_addr.page = 0x7fffffff;
+ v->erri.low_addr.offset = 0xfff;
+ v->erri.high_addr.page = 0;
+ v->erri.high_addr.offset = 0;
+ v->erri.min_bits = 32;
+ v->erri.max_bits = 0;
+ v->erri.min_bits = 32;
+ v->erri.max_bits = 0;
+ v->erri.maxl = 0;
+ v->erri.cor_err = 0;
+ v->erri.ebits = 0;
+ v->erri.hdr_flag = 0;
+ v->erri.tbits = 0;
+ for (i=0; tseq[i].msg != NULL; i++) {
+ tseq[i].errors = 0;
+ }
+ if (dmi_initialized) {
+ for (i=0; i < MAX_DMI_MEMDEVS; i++){
+ if (dmi_err_cnts[i] > 0) {
+ dmi_err_cnts[i] = 0;
+ }
+ }
+ }
cprint(LINE_CPU+1, 0, "L1 Cache: Unknown ");
cprint(LINE_CPU+2, 0, "L2 Cache: Unknown ");
@@ -137,6 +175,8 @@ void init(void)
cprint(i, COL_MID-2, "| ");
}
footer();
+ // Default Print Mode
+ // v->printmode=PRINTMODE_SUMMARY;
v->printmode=PRINTMODE_ADDRESSES;
v->numpatn=0;
find_ticks();
@@ -513,6 +553,10 @@ void cpu_type(void)
}
off = 16;
break;
+ case 2:
+ cprint(LINE_CPU, 0, "AMD Phenom X4");
+ off = 13;
+ break;
}
break;
}
@@ -637,6 +681,9 @@ void cpu_type(void)
case 0x49:
l2_cache = 4096;
break;
+ case 0x4e:
+ l2_cache = 6144;
+ break;
}
}
@@ -685,24 +732,41 @@ void cpu_type(void)
}
break;
case 6:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
+ if (((cpu_id.ext >> 16) & 0xF) != 0) {
+ tsc_invariable = 1;
+ cprint(LINE_CPU, 0, "Intel Nehalem");
+ off = 13;
} else {
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
+ if (l2_cache == 128) {
+ cprint(LINE_CPU, 0, "Celeron");
+ off = 7;
+ } else {
+ cprint(LINE_CPU, 0, "Pentium II");
+ off = 10;
+ }
}
break;
case 7:
case 8:
case 10:
case 11:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
+ if (((cpu_id.ext >> 16) & 0xF) != 0) {
+ tsc_invariable = 1;
+ if (l2_cache < 1024) {
+ cprint(LINE_CPU, 0, "Celeron");
+ off = 7;
+ } else {
+ cprint(LINE_CPU, 0, "Intel Core 2");
+ off = 12;
+ }
} else {
- cprint(LINE_CPU, 0, "Pentium III");
- off = 11;
+ if (l2_cache == 128) {
+ cprint(LINE_CPU, 0, "Celeron");
+ off = 7;
+ } else {
+ cprint(LINE_CPU, 0, "Pentium III");
+ off = 11;
+ }
}
break;
case 9:
@@ -726,8 +790,14 @@ void cpu_type(void)
off = 10;
break;
case 15:
- cprint(LINE_CPU, 0, "Intel Core 2");
- off = 12;
+ if (l2_cache == 1024) {
+ cprint(LINE_CPU, 0, "Pentium E");
+ off = 9;
+ } else {
+ cprint(LINE_CPU, 0, "Intel Core 2");
+ off = 12;
+ }
+ tsc_invariable = 1;
break;
}
break;
@@ -806,14 +876,29 @@ void cpu_type(void)
off = 12;
break;
case 6: // VIA C3
- if (cpu_id.step < 8) {
- cprint(LINE_CPU, 0, "VIA C3 Samuel2");
- off = 14;
- } else {
- cprint(LINE_CPU, 0, "Via C3 Eden");
- off = 11;
+ switch(cpu_id.model){
+ default:
+ if (cpu_id.step < 8) {
+ cprint(LINE_CPU, 0, "VIA C3 Samuel2");
+ off = 14;
+ } else {
+ cprint(LINE_CPU, 0, "VIA C3 Eden");
+ off = 11;
+ }
+ break;
+ case 10:
+ cprint(LINE_CPU, 0, "VIA Esther (C5J)");
+ off = 16;
+ break;
+ case 13:
+ cprint(LINE_CPU, 0, "VIA C7 (C5R)");
+ off = 12;
+ break;
+ case 15:
+ cprint(LINE_CPU, 0, "VIA Isaiah (CN)");
+ off = 15;
+ break;
}
- break;
}
l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7];
l2_cache = cpu_id.cache_info[11];
@@ -899,12 +984,11 @@ void cpu_type(void)
/* To measure L1 cache speed we use a block size that is 1/4th */
/* of the total L1 cache size since half of it is for instructions */
if (l1_cache) {
- cprint(LINE_CPU+1, 10, " K ");
+ cprint(LINE_CPU+1, 0, "L1 Cache: K ");
dprint(LINE_CPU+1, 11, l1_cache, 3, 0);
- if ((speed=memspeed((ulong)mapping(0x100),
- (l1_cache / 4) * 1024, 50))) {
- cprint(LINE_CPU+1, 15, " MB/s");
- dprint(LINE_CPU+1, 15, speed, 6, 0);
+ if ((speed=memspeed((ulong)mapping(0x100), (l1_cache / 4) * 1024, 50, MS_COPY))) {
+ cprint(LINE_CPU+1, 16, " MB/s");
+ dprint(LINE_CPU+1, 16, speed, 6, 0);
}
}
@@ -913,8 +997,8 @@ void cpu_type(void)
/* the size of the L1 cache. We have to fudge if the L1 */
/* cache is bigger than the L2 */
if (l2_cache) {
- cprint(LINE_CPU+2, 9, " K ");
- cprint(LINE_CPU+2, 0, "L2 Cache: ?K");
+ cprint(LINE_CPU+2, 0, "L2 Cache: K ");
+ dprint(LINE_CPU+2, 10, l2_cache, 4, 0);
dprint(LINE_CPU+2, 10, l2_cache, 4, 0);
if (l2_cache < l1_cache) {
@@ -922,9 +1006,9 @@ void cpu_type(void)
} else {
i = l1_cache;
}
- if ((speed=memspeed((ulong)mapping(0x100), i*1024, 50))) {
- cprint(LINE_CPU+2, 15, " MB/s");
- dprint(LINE_CPU+2, 15, speed, 6, 0);
+ if ((speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY))) {
+ cprint(LINE_CPU+2, 16, " MB/s");
+ dprint(LINE_CPU+2, 16, speed, 6, 0);
}
}
@@ -936,9 +1020,9 @@ void cpu_type(void)
if ((1 + (i * 2)) > (v->plim_upper << 2)) {
i = ((v->plim_upper <<2) - 1) / 2;
}
- if((speed = memspeed((ulong)mapping(0x100), i*1024, 40))) {
- cprint(LINE_CPU+3, 15, " MB/s");
- dprint(LINE_CPU+3, 15, speed, 6, 0);
+ if((speed = memspeed((ulong)mapping(0x100), i*1024, 40, MS_COPY))) {
+ cprint(LINE_CPU+3, 16, " MB/s");
+ dprint(LINE_CPU+3, 16, speed, 6, 0);
}
/* Record the starting time */
@@ -976,7 +1060,7 @@ static void cacheable(void)
}
/* Map the range and perform the test */
map_page(paddr);
- speed = memspeed((ulong)mapping(paddr), 32*4096, 1);
+ speed = memspeed((ulong)mapping(paddr), 32*4096, 1, MS_COPY);
if (pspeed) {
if (speed < pspeed) {
cached -= 32;
@@ -1025,13 +1109,16 @@ static int cpuspeed(void)
if (loops < 4 || end_low < 50000) {
return(-1);
}
- v->clks_msec = end_low/50;
+
+ if(tsc_invariable){ end_low = correct_tsc(end_low); }
+
+ v->clks_msec = end_low/50;
return(v->clks_msec);
}
/* Measure cache/memory speed by copying a block of memory. */
/* Returned value is kbytes/second */
-static ulong memspeed(ulong src, ulong len, int iter)
+ulong memspeed(ulong src, ulong len, int iter, int type)
{
ulong dst;
ulong wlen;
@@ -1045,11 +1132,11 @@ static ulong memspeed(ulong src, ulong len, int iter)
for (i=0; i<iter; i++) {
asm __volatile__ (
"movl %0,%%esi\n\t" \
- "movl %1,%%edi\n\t" \
- "movl %2,%%ecx\n\t" \
- "cld\n\t" \
- "rep\n\t" \
- "movsl\n\t" \
+ "movl %1,%%edi\n\t" \
+ "movl %2,%%ecx\n\t" \
+ "cld\n\t" \
+ "rep\n\t" \
+ "movsl\n\t" \
:: "g" (src), "g" (dst), "g" (0)
: "esi", "edi", "ecx"
);
@@ -1065,33 +1152,78 @@ static ulong memspeed(ulong src, ulong len, int iter)
"0" (cal_low), "1" (cal_high)
);
- /* Do the first copy to prime the cache */
- asm __volatile__ (
- "movl %0,%%esi\n\t" \
- "movl %1,%%edi\n\t" \
- "movl %2,%%ecx\n\t" \
- "cld\n\t" \
- "rep\n\t" \
- "movsl\n\t" \
- :: "g" (src), "g" (dst), "g" (wlen)
- : "esi", "edi", "ecx"
- );
/* Now measure the speed */
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
- for (i=0; i<iter; i++) {
+ switch (type) {
+ case MS_COPY:
+ /* Do the first copy to prime the cache */
asm __volatile__ (
"movl %0,%%esi\n\t" \
"movl %1,%%edi\n\t" \
- "movl %2,%%ecx\n\t" \
- "cld\n\t" \
- "rep\n\t" \
- "movsl\n\t" \
- :: "g" (src), "g" (dst), "g" (wlen)
+ "movl %2,%%ecx\n\t" \
+ "cld\n\t" \
+ "rep\n\t" \
+ "movsl\n\t" \
+ :: "g" (src), "g" (dst), "g" (wlen)
: "esi", "edi", "ecx"
);
+ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ for (i=0; i<iter; i++) {
+ asm __volatile__ (
+ "movl %0,%%esi\n\t" \
+ "movl %1,%%edi\n\t" \
+ "movl %2,%%ecx\n\t" \
+ "cld\n\t" \
+ "rep\n\t" \
+ "movsl\n\t" \
+ :: "g" (src), "g" (dst), "g" (wlen)
+ : "esi", "edi", "ecx"
+ );
+ }
+ asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
+ break;
+ case MS_WRITE:
+ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ for (i=0; i<iter; i++) {
+ asm __volatile__ (
+ "movl %0,%%ecx\n\t" \
+ "movl %1,%%edi\n\t" \
+ "movl %2,%%eax\n\t" \
+ "rep\n\t" \
+ "stosl\n\t"
+ :: "g" (wlen), "g" (dst), "g" (0)
+ : "edi", "ecx", "eax"
+ );
+ }
+ asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
+ break;
+ case MS_READ:
+ asm __volatile__ (
+ "movl %0,%%esi\n\t" \
+ "movl %1,%%ecx\n\t" \
+ "cld\n\t" \
+ "L1:\n\t" \
+ "lodsl\n\t" \
+ "loop L1\n\t" \
+ :: "g" (src), "g" (wlen)
+ : "esi", "ecx"
+ );
+ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ for (i=0; i<iter; i++) {
+ asm __volatile__ (
+ "movl %0,%%esi\n\t" \
+ "movl %1,%%ecx\n\t" \
+ "cld\n\t" \
+ "L2:\n\t" \
+ "lodsl\n\t" \
+ "loop L2\n\t" \
+ :: "g" (src), "g" (wlen)
+ : "esi", "ecx"
+ );
+ }
+ asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
+ break;
}
- asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
/* Compute the elapsed time */
asm __volatile__ (
@@ -1115,8 +1247,10 @@ static ulong memspeed(ulong src, ulong len, int iter)
return(0);
}
- /* Since a copy does both a read & write we need to adjuect the time */
- end_low /= 2;
+ /* If this was a copy adjust the time */
+ if (type == MS_COPY) {
+ end_low /= 2;
+ }
/* Convert to clocks/KB */
end_low /= len;
@@ -1126,6 +1260,42 @@ static ulong memspeed(ulong src, ulong len, int iter)
return(0);
}
+ if(tsc_invariable){ end_low = correct_tsc(end_low); }
+
/* Convert to kbytes/sec */
return((v->clks_msec)/end_low);
}
+
+ulong correct_tsc(ulong el_org)
+{
+
+ float coef_now, coef_max;
+ int msr_lo, msr_hi, is_xe;
+
+ rdmsr(0x198, msr_lo, msr_hi);
+ is_xe = (msr_lo >> 31) & 0x1;
+
+ if(is_xe){
+ rdmsr(0x198, msr_lo, msr_hi);
+ coef_max = ((msr_hi >> 8) & 0x1F);
+ if ((msr_hi >> 14) & 0x1) { coef_max = coef_max + 0.5f; }
+ } else {
+ rdmsr(0x17, msr_lo, msr_hi);
+ coef_max = ((msr_lo >> 8) & 0x1F);
+ if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; }
+ }
+
+ if((cpu_id.feature_flag >> 7) & 1) {
+ rdmsr(0x198, msr_lo, msr_hi);
+ coef_now = ((msr_lo >> 8) & 0x1F);
+ if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; }
+ } else {
+ rdmsr(0x2A, msr_lo, msr_hi);
+ coef_now = (msr_lo >> 22) & 0x1F;
+ }
+
+ if(coef_max && coef_now) { el_org = (ulong)(el_org * coef_now / coef_max); }
+
+ return el_org;
+
+}
diff --git a/lib.c b/lib.c
index a23ac72..08578c3 100644
--- a/lib.c
+++ b/lib.c
@@ -2,17 +2,35 @@
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
- */
+ * ----------------------------------------------------
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardplus.com - http://www.memtest.org
+*/
+
#include "io.h"
#include "serial.h"
#include "test.h"
#include "config.h"
#include "screen_buffer.h"
-extern int fast_mode;
int slock = 0, lsr = 0;
short serial_cons = SERIAL_CONSOLE_DEFAULT;
+
+#if SERIAL_TTY != 0 && SERIAL_TTY != 1
+#error Bad SERIAL_TTY. Only ttyS0 and ttyS1 are supported.
+#endif
+short serial_tty = SERIAL_TTY;
+const short serial_base_ports[] = {0x3f8, 0x2f8};
+
+#if ((115200%SERIAL_BAUD_RATE) != 0)
+#error Bad default baud rate
+#endif
+int serial_baud_rate = SERIAL_BAUD_RATE;
+unsigned char serial_parity = 0;
+unsigned char serial_bits = 8;
+
char buf[18];
struct ascii_map_str {
@@ -71,6 +89,20 @@ int memcmp(const void *s1, const void *s2, ulong count)
return 0;
}
+int strncmp(const char *s1, const char *s2, ulong n) {
+ signed char res = 0;
+ while (n) {
+ res = *s1 - *s2;
+ if (res != 0)
+ return res;
+ if (*s1 == '\0')
+ return 0;
+ ++s1, ++s2;
+ --n;
+ }
+ return res;
+}
+
void *memmove(void *dest, const void *src, ulong n)
{
long i;
@@ -89,6 +121,52 @@ void *memmove(void *dest, const void *src, ulong n)
}
return dest;
}
+
+char toupper(char c)
+{
+ if (c >= 'a' && c <= 'z')
+ return c + 'A' -'a';
+ else
+ return c;
+}
+
+int isdigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+int isxdigit(char c)
+{
+ return isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F'); }
+
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) {
+ unsigned long result = 0, value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X' && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+
/*
* Scroll the error message area of the screen as needed
* Starts at line LINE_SCROLL and ends at line 23
@@ -126,6 +204,21 @@ void scroll(void)
}
/*
+ * Clear scroll region
+ */
+void clear_scroll(void)
+{
+ int i;
+ char *s;
+
+ s = (char*)(SCREEN_ADR+LINE_HEADER*160);
+ for(i=0; i<80*(24-LINE_HEADER); i++) {
+ *s++ = ' ';
+ *s++ = 0x17;
+ }
+}
+
+/*
* Print characters on screen
*/
void cprint(int y, int x, const char *text)
@@ -611,21 +704,7 @@ ulong getval(int x, int y, int result_shift)
shift -= result_shift;
/* Compute our current value */
- val = 0;
- for(i = (base == 16)? 2: 0; i < n; i++) {
- unsigned long digit = 0;
- if ((buf[i] >= '0') && (buf[i] <= '9')) {
- digit = buf[i] - '0';
- }
- else if ((buf[i] >= 'a') && (buf[i] <= 'f')) {
- digit = buf[i] - 'a' + 10;
- }
- else {
- /* It must be a suffix byte */
- break;
- }
- val = (val * base) + digit;
- }
+ val = simple_strtoul(buf, NULL, base);
if (shift > 0) {
if (shift >= 32) {
val = 0xffffffff;
@@ -661,19 +740,11 @@ void ttyprint(int y, int x, const char *p)
serial_echo_print(p);
}
-#if defined(SERIAL_BAUD_RATE)
-
-#if ((115200%SERIAL_BAUD_RATE) != 0)
-#error Bad ttys0 baud rate
-#endif
-
-#define SERIAL_DIV (115200/SERIAL_BAUD_RATE)
-
-#endif /* SERIAL_BAUD_RATE */
void serial_echo_init(void)
{
- int comstat, hi, lo;
+ int comstat, hi, lo, serial_div;
+ unsigned char lcr;
/* read the Divisor Latch */
comstat = serial_echo_inb(UART_LCR);
@@ -683,13 +754,14 @@ void serial_echo_init(void)
serial_echo_outb(comstat, UART_LCR);
/* now do hardwired init */
- serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
-#if defined(SERIAL_BAUD_RATE)
- serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
- serial_echo_outb(SERIAL_DIV & 0xff, UART_DLL); /* baud rate divisor */
- serial_echo_outb((SERIAL_DIV>> 8) & 0xff, UART_DLM);
- serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
-#endif
+ lcr = serial_parity | (serial_bits - 5);
+ serial_echo_outb(lcr, UART_LCR); /* No parity, 8 data bits, 1 stop */
+ serial_div = 115200 / serial_baud_rate;
+ serial_echo_outb(0x80|lcr, UART_LCR); /* Access divisor latch */
+ serial_echo_outb(serial_div & 0xff, UART_DLL); /* baud rate divisor */
+ serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM);
+ serial_echo_outb(lcr, UART_LCR); /* Done with divisor */
+
/* Prior to disabling interrupts, read the LSR and RBR
* registers */
@@ -914,6 +986,97 @@ void wait_keyup( void ) {
}
}
}
+
+
+/*
+ * Handles "console=<param>" command line option
+ *
+ * Examples of accepted params:
+ * ttyS0
+ * ttyS1
+ * ttyS0,115200
+ * ttyS0,9600e8
+ */
+void serial_console_setup(char *param)
+{
+ char *option, *end;
+ unsigned long tty;
+ unsigned long baud_rate;
+ unsigned char parity, bits;
+
+ if (strncmp(param, "ttyS", 4))
+ return; /* not a serial port */
+
+ param += 4;
+
+ tty = simple_strtoul(param, &option, 10);
+
+ if (option == param)
+ return; /* there were no digits */
+
+ if (tty > 1)
+ return; /* only ttyS0 and ttyS1 supported */
+
+ if (*option == '\0')
+ goto save_tty; /* no options given, just ttyS? */
+
+ if (*option != ',')
+ return; /* missing the comma separator */
+
+ /* baud rate must follow */
+ option++;
+ baud_rate = simple_strtoul(option, &end, 10);
+
+ if (end == option)
+ return; /* no baudrate after comma */
+
+ if (baud_rate == 0 || (115200 % baud_rate) != 0)
+ return; /* wrong baud rate */
+
+ if (*end == '\0')
+ goto save_baud_rate; /* no more options given */
+
+ switch (toupper(*end)) {
+ case 'N':
+ parity = 0;
+ break;
+ case 'O':
+ parity = UART_LCR_PARITY;
+ break;
+ case 'E':
+ parity = UART_LCR_PARITY | UART_LCR_EPAR;
+ break;
+ default:
+ /* Unknown parity */
+ return;
+ }
+
+ end++;
+ if (*end == '\0')
+ goto save_parity;
+
+ /* word length (bits) */
+ if (*end < '7' || *end > '8')
+ return; /* invalid number of bits */
+
+ bits = *end - '0';
+
+ end++;
+
+ if (*end != '\0')
+ return; /* garbage at the end */
+
+ serial_bits = bits;
+ save_parity:
+ serial_parity = parity;
+ save_baud_rate:
+ serial_baud_rate = (int) baud_rate;
+ save_tty:
+ serial_tty = (short) tty;
+ serial_cons = 1;
+}
+
+
#ifdef LP
#define DATA 0x00
#define STATUS 0x01
diff --git a/main.c b/main.c
index d8ab105..37eda7c 100644
--- a/main.c
+++ b/main.c
@@ -3,34 +3,34 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V1.65 Specific code (GPL V2.0)
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.x86-secret.com - http://www.memtest.org
+ * http://www.canardplus.com - http://www.memtest.org
*/
#include "test.h"
#include "defs.h"
#undef TEST_TIMES
-#define DEFTESTS 11
+#define DEFTESTS 9
extern void bzero();
const struct tseq tseq[] = {
- {1, 5, 3, 0, 0, "[Address test, walking ones] "},
+ {0, 5, 3, 0, 0, "[Address test, walking ones, uncached]"},
{1, 6, 3, 2, 0, "[Address test, own address] "},
{1, 0, 3, 14, 0, "[Moving inversions, ones & zeros] "},
{1, 1, 2, 80, 0, "[Moving inversions, 8 bit pattern] "},
{1, 10, 60, 300, 0, "[Moving inversions, random pattern] "},
{1, 7, 64, 66, 0, "[Block move, 64 moves] "},
{1, 2, 2, 320, 0, "[Moving inversions, 32 bit pattern] "},
- {1, 9, 40, 120, 0, "[Random number sequence] "},
- {1, 3, 4, 240, 0, "[Modulo 20, ones & zeros] "},
- {1, 8, 1, 2, 0, "[Bit fade test, 90 min, 2 patterns] "},
- {0, 4, 3, 2, 0, "[[Moving inversions, 0 & 1, uncached] "},
+ {1, 9, 40, 120, 0, "[Random number sequence] "},
+ {1, 3, 4, 1920, 0,"[Modulo 20, random pattern] "},
+ {1, 8, 1, 2, 0, "[Bit fade test, 90 min, 2 patterns] "},
{0, 0, 0, 0, 0, NULL}
};
char firsttime = 0;
+char cmdline_parsed = 0;
struct vars variables = {};
struct vars * const v = &variables;
@@ -40,13 +40,15 @@ ulong p1 = 0, p2 = 0, p0 = 0;
int segs = 0, bail = 0;
int test_ticks;
int nticks;
+ulong high_test_adr = 0x200000;
static int window = 0;
static struct pmap windows[] =
{
- { 0/* Written at startup */, 0x100000 },
- { 0, RES_START >> 12 },
+ { 0, 0x080000 },
+ { 0, 0 },
+ { 0x080000, 0x100000 },
{ 0x100000, 0x180000 },
{ 0x180000, 0x200000 },
@@ -93,9 +95,7 @@ static struct pmap windows[] =
{ 0xF80000, 0x1000000 },
};
-#if (LOW_TEST_ADR >= HIGH_TEST_ADR)
-#error LOW_TEST_ADR and HIGH_TEST_ADR may not overlap
-#endif
+
#if (LOW_TEST_ADR > (640*1024))
#error LOW_TEST_ADR must be below 640K
#endif
@@ -105,7 +105,7 @@ static void compute_segments(int win);
static void __run_at(unsigned long addr)
{
- /* Copy memtest86 code */
+ /* Copy memtest86+ code */
memmove((void *)addr, &_start, _end - _start);
/* Jump to the start address */
p = (ulong *)(addr + startup_32 - _start);
@@ -125,8 +125,8 @@ static void run_at(unsigned long addr)
if ( ((start < addr) && ((start + len) >= addr)) ||
((addr < start) && ((addr + len) >= start))) {
/* Handle overlap by doing an extra relocation */
- if (addr + len < HIGH_TEST_ADR) {
- __run_at(HIGH_TEST_ADR);
+ if (addr + len < high_test_adr) {
+ __run_at(high_test_adr);
}
else if (start + len < addr) {
__run_at(LOW_TEST_ADR);
@@ -135,12 +135,54 @@ static void run_at(unsigned long addr)
__run_at(run_at_addr);
}
+/* command line passing using the 'old' boot protocol */
+#define MK_PTR(seg,off) ((void*)(((unsigned long)(seg) << 4) + (off)))
+#define OLD_CL_MAGIC_ADDR ((unsigned short*) MK_PTR(INITSEG,0x20))
+#define OLD_CL_MAGIC 0xA33F
+#define OLD_CL_OFFSET_ADDR ((unsigned short*) MK_PTR(INITSEG,0x22))
+
+static void parse_command_line(void)
+{
+ char *cmdline;
+
+ if (cmdline_parsed)
+ return;
+
+ if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC)
+ return;
+
+ unsigned short offset = *OLD_CL_OFFSET_ADDR;
+ cmdline = MK_PTR(INITSEG, offset);
+
+ /* skip leading spaces */
+ while (*cmdline == ' ')
+ cmdline++;
+
+ while (*cmdline) {
+ if (!strncmp(cmdline, "console=", 8)) {
+ cmdline += 8;
+ serial_console_setup(cmdline);
+ }
+
+ /* go to the next parameter */
+ while (*cmdline && *cmdline != ' ')
+ cmdline++;
+ while (*cmdline == ' ')
+ cmdline++;
+ }
+
+ cmdline_parsed = 1;
+}
+
+
void do_test(void)
{
- int i = 0;
+ int i = 0, j = 0;
unsigned long chunks;
unsigned long lo, hi;
+ parse_command_line();
+
/* If we have a partial relocation finish it */
if (run_at_addr == (unsigned long)&_start) {
run_at_addr = 0xffffffff;
@@ -153,9 +195,15 @@ void do_test(void)
if ((ulong)&_start != LOW_TEST_ADR) {
restart();
}
- windows[0].start =
- ( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;
init();
+ windows[0].start =
+ ( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;
+
+ /* Set relocation address at 16Mb if there is enough memory */
+ if (v->pmap[v->msegs-1].end > 0x1100) {
+ high_test_adr = 0x01000000;
+ }
+ windows[1].end = (high_test_adr >> 12);
firsttime = 1;
}
bail = 0;
@@ -170,6 +218,14 @@ void do_test(void)
goto skip_window;
}
+ if ((ulong)&_start > LOW_TEST_ADR) {
+ /* Relocated so we need to test all selected lower memory */
+ v->map[0].start = mapping(v->plim_lower);
+ cprint(LINE_RANGE, COL_MID+28, " Relocated");
+ } else {
+ cprint(LINE_RANGE, COL_MID+28, " ");
+ }
+
/* Update display of memory segments being tested */
lo = page_of(v->map[0].start);
hi = page_of(v->map[segs -1].end);
@@ -177,8 +233,7 @@ void do_test(void)
cprint(LINE_RANGE, COL_MID+14, " - ");
aprint(LINE_RANGE, COL_MID+17, hi);
aprint(LINE_RANGE, COL_MID+23, v->selected_pages);
- cprint(LINE_RANGE, COL_MID+28,
- ((ulong)&_start == LOW_TEST_ADR)?" ":" Relocated");
+
#ifdef TEST_TIMES
{
@@ -232,7 +287,6 @@ void do_test(void)
/* Now do the testing according to the selected pattern */
case 0: /* Moving inversions, all ones and zeros */
- case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */
case 4:
if (tseq[v->test].pat == 1)
@@ -252,6 +306,22 @@ void do_test(void)
}
break;
+ case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */
+ p0 = 0x80;
+ for (i=0; i<8; i++, p0=p0>>1) {
+ p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
+ p2 = ~p1;
+ movinv1(tseq[v->test].iter,p1,p2);
+ BAILOUT;
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ movinv1(tseq[v->test].iter,p1,p2);
+ BAILOUT
+ }
+ break;
+
case 2: /* Moving inversions, 32 bit shifting pattern, very long */
for (i=0, p1=1; p1; p1=p1<<1, i++) {
@@ -262,18 +332,20 @@ void do_test(void)
}
break;
- case 3: /* Modulo X check, all ones and zeros */
- p1=0;
- for (i=0; i<MOD_SZ; i++) {
- p2 = ~p1;
- modtst(i, tseq[v->test].iter, p1, p2);
- BAILOUT
-
- /* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- modtst(i, tseq[v->test].iter, p1,p2);
- BAILOUT
+ case 3: /* Modulo 20, random */
+ for (j=0; j<tseq[v->test].iter; j++) {
+ p1 = rand();
+ for (i=0; i<MOD_SZ; i++) {
+ p2 = ~p1;
+ modtst(i, tseq[v->test].iter, p1, p2);
+ BAILOUT
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ modtst(i, tseq[v->test].iter, p1, p2);
+ BAILOUT
+ }
}
break;
@@ -333,15 +405,15 @@ void do_test(void)
* The lower limit is less than START_ADR
* - There is more than 1 meg of memory
*/
- if (windows[window].start <
- (LOW_TEST_ADR + (_end - _start)) >> 12) {
- if (v->pmap[v->msegs-1].end >
- (((HIGH_TEST_ADR + (_end - _start)) >> 12) +1)) {
+ if (windows[window].start <
+ ((ulong)&_start + (_end - _start)) >> 12) {
+ if (v->pmap[v->msegs-1].end >
+ (((high_test_adr + (_end - _start)) >> 12)+1)) {
/* We need the high copy and we have enough
* memory so use it.
*/
- run_at(HIGH_TEST_ADR);
- } else {
+ run_at(high_test_adr);
+ } else {
/* We can't use this window so skip it */
goto skip_window;
}
@@ -374,8 +446,12 @@ void do_test(void)
v->pptr = 0;
cprint(0, COL_MID+8,
" ");
+ if (v->ecount == 0 && v->testsel < 0) {
+ cprint(LINE_MSG, COL_MSG,
+ "Pass complete, no errors, press Esc to exit");
+ }
}
-
+
/* We always start a pass with the low copy */
run_at(LOW_TEST_ADR);
}
diff --git a/mt86+_loader b/mt86+_loader
index fec9f0d..2b30d8b 100644
--- a/mt86+_loader
+++ b/mt86+_loader
Binary files differ
diff --git a/mt86+_loader.asm b/mt86+_loader.asm
index 1437d5d..cba5f70 100644
--- a/mt86+_loader.asm
+++ b/mt86+_loader.asm
@@ -1,4 +1,4 @@
-; A loader for www.Memtest86.com images, by Eric Auer 2003.
+; A loader for www.memtest.org images, by Eric Auer 2003.
; This assumes that the image starts with the boot sector,
; which has the size of setup.S in sectors in a byte at offset
; 1f1h (497). Further, I assume setup.S directly after the boot
@@ -12,8 +12,8 @@
; The good thing is that you get a single file which can be
; compressed, for example with http://upx.sf.net/ (UPX).
-%define fullsize (99256 + buffer - exeh)
- ; 99256 is the size of memtest86+ V1.70, adjust as needed!
+%define fullsize (111512 + buffer - exeh)
+ ; 111512 is the size of memtest86+ V2.00, adjust as needed!
%define stacksize 2048
%define stackpara ((stacksize + 15) / 16)
@@ -46,6 +46,11 @@ exeh: db "MZ"
; loaded part begins here (set CS so that IP is 100h here)
start: ; entry point ; if you use obj + linker, use "..start:"
+ mov ah, 01h
+ mov bh, 00h
+ mov cx, 2000h
+ int 10h
+
mov ax,cs ; ***
mov ds,ax ; ***
mov es,ax ; ***
diff --git a/patn.c b/patn.c
index 0c5b490..8240333 100644
--- a/patn.c
+++ b/patn.c
@@ -7,7 +7,7 @@
*
* By Rick van Rein, vanrein@zonnet.nl
* ----------------------------------------------------
- * MemTest86+ V1.60 Specific code (GPL V2.0)
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
diff --git a/pci.c b/pci.c
index fe93930..f2eb58d 100644
--- a/pci.c
+++ b/pci.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V1.51 Specific code (GPL V2.0)
+ * MemTest86+ V1.94 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
diff --git a/pci.h b/pci.h
index 3149817..3629a6a 100644
--- a/pci.h
+++ b/pci.h
@@ -7,6 +7,7 @@ int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg,
unsigned len, unsigned long value);
int pci_init(void);
+
/*
* Under PCI, each device has 256 bytes of configuration address space,
* of which the first 64 bytes are standardized as follows:
diff --git a/serial.h b/serial.h
index 95e530a..0261073 100644
--- a/serial.h
+++ b/serial.h
@@ -136,8 +136,8 @@
*/
#include "io.h"
-#define serial_echo_outb(v,a) outb((v),(a)+0x3f8)
-#define serial_echo_inb(a) inb((a)+0x3f8)
+#define serial_echo_outb(v,a) outb((v),(a)+serial_base_ports[serial_tty])
+#define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty])
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/* Wait for transmitter & holding register to empty */
#define WAIT_FOR_XMITR \
diff --git a/setup.S b/setup.S
index 48e7773..87eb80f 100644
--- a/setup.S
+++ b/setup.S
@@ -21,6 +21,7 @@ start:
movb $0x80, %al # disable NMI for the bootup sequence
outb %al, $0x70
+
# The system will move itself to its rightful place.
push %cs
@@ -29,7 +30,6 @@ start:
lgdt gdt_48 - start # load gdt with whatever appropriate
# that was painless, now we enable A20
-
call empty_8042
movb $0xD1, %al # command write
diff --git a/spd.c b/spd.c
new file mode 100644
index 0000000..5612e68
--- /dev/null
+++ b/spd.c
@@ -0,0 +1,140 @@
+/* Memtest86 SPD extension
+ * added by Reto Sonderegger, 2004, reto@swissbit.com
+ *
+ * Released under version 2 of the Gnu Puclic License
+ */
+
+#include "test.h"
+#include "io.h"
+#include "pci.h"
+#include "msr.h"
+#include "screen_buffer.h"
+
+#define SMBHSTSTS smbusbase
+#define SMBHSTCNT smbusbase + 2
+#define SMBHSTCMD smbusbase + 3
+#define SMBHSTADD smbusbase + 4
+#define SMBHSTDAT smbusbase + 5
+
+extern void wait_keyup();
+
+int smbdev, smbfun;
+unsigned short smbusbase;
+unsigned char spd[256];
+char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0};
+
+static void ich5_get_smb(void)
+{
+ unsigned long x;
+ int result;
+ result = pci_conf_read(0, smbdev, smbfun, 0x20, 2, &x);
+ if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
+}
+
+unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
+{
+ int l1, h1, l2, h2;
+ unsigned long long t;
+ __outb(0x1f, SMBHSTSTS); // reset SMBus Controller
+ __outb(0xff, SMBHSTDAT);
+ while(__inb(SMBHSTSTS) & 0x01); // wait until ready
+ __outb(cmd, SMBHSTCMD);
+ __outb((adr << 1) | 0x01, SMBHSTADD);
+ __outb(0x48, SMBHSTCNT);
+ rdtsc(l1, h1);
+ cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
+ while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished
+ rdtsc(l2, h2);
+ t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
+ if (t > 10) break; // break after 10ms
+ }
+ return __inb(SMBHSTDAT);
+}
+
+static int ich5_read_spd(int dimmadr)
+{
+ int x;
+ spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd[0] == 0xff) return -1; // no spd here
+ for (x = 1; x < 256; x++) {
+ spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ }
+ return 0;
+}
+
+struct pci_smbus_controller {
+ unsigned vendor;
+ unsigned device;
+ char *name;
+ void (*get_adr)(void);
+ int (*read_spd)(int dimmadr);
+};
+
+static struct pci_smbus_controller smbcontrollers[] = {
+{0x8086, 0x2930, "Intel ICH9", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x283E, "Intel ICH8", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x27DA, "Intel ICH7", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x24A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
+{0, 0, "", NULL, NULL}
+};
+
+int find_smb_controller(void)
+{
+ int i = 0;
+ unsigned long valuev, valued;
+ for (smbdev = 0; smbdev < 32; smbdev++) {
+ for (smbfun = 0; smbfun < 8; smbfun++) {
+ pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev);
+ if (valuev != 0xFFFF) { // if there is something look what's it..
+ for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller
+ if (valuev == smbcontrollers[i].vendor) {
+ pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id
+ if (valued == smbcontrollers[i].device) {
+ return i;
+ }
+ }
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+void show_spd(void)
+{
+ int index;
+ int i, j;
+ int flag = 0;
+ pop2up();
+ wait_keyup();
+ index = find_smb_controller();
+ if (index == -1) {
+ cprint(POP2_Y, POP2_X+1, "SMBus Controller not known");
+ while (!get_key());
+ wait_keyup();
+ pop2down();
+ return;
+ }
+ else cprint(POP2_Y, POP2_X+1, "SPD Data: Slot");
+ smbcontrollers[index].get_adr();
+ for (j = 0; j < 16; j++) {
+ if (smbcontrollers[index].read_spd(j) == 0) {
+ dprint(POP2_Y, POP2_X + 15, j, 2, 0);
+ for (i = 0; i < 256; i++) {
+ hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd[i], 2);
+ }
+ flag = 0;
+ while(!flag) {
+ if (get_key()) flag++;
+ }
+ wait_keyup();
+ }
+ }
+ pop2down();
+}
+
diff --git a/test.c b/test.c
index d3660f6..1581ea0 100644
--- a/test.c
+++ b/test.c
@@ -4,7 +4,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady, cbrady@sgi.com
* ----------------------------------------------------
- * MemTest86+ V1.70 Specific code (GPL V2.0)
+ * MemTest86+ V2.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -14,19 +14,17 @@
#include <sys/io.h>
#include "dmi.h"
-
-extern int segs, bail, beepmode;
+extern int segs, bail;
extern volatile ulong *p;
extern ulong p1, p2;
extern int test_ticks, nticks;
extern struct tseq tseq[];
+extern void update_err_counts(void);
+extern void print_err_counts(void);
void poll_errors();
int ecount = 0;
-static void update_err_counts(void);
-static void print_err_counts(void);
-
static inline ulong roundup(ulong value, ulong mask)
{
return (value + mask) & ~mask;
@@ -1268,7 +1266,7 @@ void block_move(int iter)
"pushl 4(%%edi)\n\t"
"pushl %%ecx\n\t"
"pushl %%edi\n\t"
- "call mv_error\n\t"
+ "call error\n\t"
"popl %%edi\n\t"
"addl $8,%%esp\n\t"
"popl %%edx\n\t"
@@ -1311,7 +1309,7 @@ void bit_fade()
end = v->map[j].end;
pe = start;
p = start;
- for (p=end; p<end; p++) {
+ for (p=start; p<end; p++) {
*p = p1;
}
do_tick();
@@ -1326,7 +1324,7 @@ void bit_fade()
end = v->map[j].end;
pe = start;
p = start;
- for (p=end; p<end; p++) {
+ for (p=start; p<end; p++) {
if ((bad=*p) != p1) {
error((ulong*)p, p1, bad);
}
@@ -1343,350 +1341,6 @@ void bit_fade()
}
-/*
- * Display data error message. Don't display duplicate errors.
- */
-void error(ulong *adr, ulong good, ulong bad)
-{
- ulong xor;
- int patnchg,baddevchg;
-
- xor = good ^ bad;
-#ifdef USB_WAR
- /* Skip any errrors that appear to be due to the BIOS using location
- * 0x4e0 for USB keyboard support. This often happens with Intel
- * 810, 815 and 820 chipsets. It is possible that we will skip
- * a real error but the odds are very low.
- */
- if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) {
- return;
- }
-#endif
-
- /* Process the address in the pattern administration */
- patnchg=insertaddress ((ulong) adr);
- baddevchg=add_dmi_err((ulong) adr );
-
- update_err_counts();
-
- if (v->printmode == PRINTMODE_ADDRESSES) {
-
- /* Don't display duplicate errors */
- if ((ulong)adr == (ulong)v->eadr && xor == v->exor) {
- print_err_counts();
- dprint(v->msg_line, 66, ++ecount, 5, 0);
- return;
- }
- print_err(adr, good, bad, xor);
-
- } else if (v->printmode == PRINTMODE_PATTERNS) {
- print_err_counts();
-
- if (patnchg) {
- printpatn();
- }
- } else if (v->printmode == PRINTMODE_DMI) {
- print_err_counts();
- if (baddevchg==1)
- print_dmi_err();
- }
-}
-
-/*
- * Display data error message from the block move test. The actual failing
- * address is unknown so don't use this failure information to create
- * BadRAM patterns.
- */
-void mv_error(ulong *adr, ulong good, ulong bad)
-{
- ulong xor;
-
- update_err_counts();
- if (v->printmode == PRINTMODE_NONE) {
- return;
- }
- xor = good ^ bad;
- print_err(adr, good, bad, xor);
-}
-
-/*
- * Display address error message.
- * Since this is strictly an address test, trying to create BadRAM
- * patterns does not make sense. Just report the error.
- */
-void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad)
-{
- ulong xor;
- update_err_counts();
- if (v->printmode == PRINTMODE_NONE) {
- return;
- }
- xor = ((ulong)adr1) ^ ((ulong)adr2);
- print_err(adr1, good, bad, xor);
-}
-
-/*
- * Display address error message.
- * Since this type of address error can also report data errors go
- * ahead and generate BadRAM patterns.
- */
-void ad_err2(ulong *adr, ulong bad)
-{
- int patnchg,baddevchg;
-
- /* Process the address in the pattern administration */
- patnchg=insertaddress ((ulong) adr);
- baddevchg=add_dmi_err((ulong) adr );
-
- update_err_counts();
- if (v->printmode == PRINTMODE_ADDRESSES) {
- print_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad);
- } else if (v->printmode == PRINTMODE_PATTERNS) {
- print_err_counts();
- if (patnchg) {
- printpatn();
- }
- } else if (v->printmode == PRINTMODE_DMI) {
- print_err_counts();
- if (baddevchg==1)
- print_dmi_err();
- }
-}
-void print_hdr(void)
-{
- if ((v->ecount)>1) {
- return;
- }
- cprint(LINE_HEADER, 0, "Tst Pass Failing Address Good Bad Err-Bits Count Chan");
- cprint(LINE_HEADER+1, 0,"--- ---- ----------------------- -------- -------- -------- ----- ----");
-}
-
-static void update_err_counts(void)
-{
- ++(v->ecount);
-
- if (beepmode){
- beep(600);
- beep(1000);
- }
-
- tseq[v->test].errors++;
-}
-
-static void print_err_counts(void)
-{
- int i;
- char *pp;
-
- if ((v->ecount > 1048756) && (v->ecount % 32768 != 0))
- return;
-
- if ((v->ecount > 2048) && (v->ecount % 1024 != 0))
- return;
-
- dprint(LINE_INFO, COL_ERR, v->ecount, 6, 0);
- dprint(LINE_INFO, COL_ECC_ERR, v->ecc_ecount, 6, 0);
-
- /* Paint the error messages on the screen red to provide a vivid */
- /* indicator that an error has occured */
- if (v->msg_line < 24) {
- for(i=0, pp=(char *)((SCREEN_ADR+v->msg_line*160+1));
- i<76; i++, pp+=2) {
- *pp = 0x47;
- }
- }
-
-
-}
-
-static void common_err(ulong page, ulong offset)
-{
- ulong mb;
-
- /* Check for keyboard input */
- print_hdr();
- check_input();
- scroll();
- print_err_counts();
-
- mb = page >> 8;
- dprint(v->msg_line, 0, v->test, 3, 0);
- dprint(v->msg_line, 4, v->pass, 5, 0);
- hprint(v->msg_line, 11, page);
- hprint2(v->msg_line, 19, offset, 3);
- cprint(v->msg_line, 22, " - . MB");
- dprint(v->msg_line, 25, mb, 5, 0);
- dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0);
-}
-/*
- * Print an individual error
- */
-void print_err( ulong *adr, ulong good, ulong bad, ulong xor)
-{
- ulong page, offset;
-
- page = page_of(adr);
- offset = ((unsigned long)adr) & 0xFFF;
- common_err(page, offset);
-
-
- ecount = 1;
- hprint(v->msg_line, 36, good);
- hprint(v->msg_line, 46, bad);
- hprint(v->msg_line, 56, xor);
- dprint(v->msg_line, 66, ecount, 5, 0);
- v->eadr = adr;
- v->exor = xor;
-}
-
-/*
- * Print an ecc error
- */
-void print_ecc_err(unsigned long page, unsigned long offset,
- int corrected, unsigned short syndrome, int channel)
-{
- if (!corrected) {update_err_counts();}
- ++(v->ecc_ecount);
- if (v->printmode == PRINTMODE_NONE) {
- return;
- }
- common_err(page, offset);
-
- cprint(v->msg_line, 36,
- corrected?"corrected ": "uncorrected ");
- hprint2(v->msg_line, 60, syndrome, 4);
- cprint(v->msg_line, 68, "ECC");
- dprint(v->msg_line, 74, channel, 2, 0);
-}
-
-#ifdef PARITY_MEM
-/*
- * Print a parity error message
- */
-void parity_err( unsigned long edi, unsigned long esi)
-{
- unsigned long addr;
-
- if (v->test == 5) {
- addr = esi;
- } else {
- addr = edi;
- }
- update_err_counts();
- if (v->printmode == PRINTMODE_NONE) {
- return;
- }
- common_err(page_of((void *)addr), addr & 0xFFF);
- cprint(v->msg_line, 36, "Parity error detected ");
-}
-#endif
-
-
-/*
- * Print the pattern array as a LILO boot option addressing BadRAM support.
- */
-void printpatn (void)
-{
- int idx=0;
- int x;
-
- /* Check for keyboard input */
- check_input();
-
- if (v->numpatn == 0)
- return;
-
- scroll();
-
- cprint (v->msg_line, 0, "badram=");
- x=7;
-
- for (idx = 0; idx < v->numpatn; idx++) {
-
- if (x > 80-22) {
- scroll();
- x=7;
- }
- cprint (v->msg_line, x, "0x");
- hprint (v->msg_line, x+2, v->patn[idx].adr );
- cprint (v->msg_line, x+10, ",0x");
- hprint (v->msg_line, x+13, v->patn[idx].mask);
- if (idx+1 < v->numpatn)
- cprint (v->msg_line, x+21, ",");
- x+=22;
- }
-}
-
-/*
- * Show progress by displaying elapsed time and update bar graphs
- */
-void do_tick(void)
-{
- int i, pct;
- ulong h, l, t;
-
- /* FIXME only print serial error messages from the tick handler */
- if (v->ecount) {
- print_err_counts();
- }
-
- nticks++;
- v->total_ticks++;
-
- pct = 100*nticks/test_ticks;
- dprint(1, COL_MID+4, pct, 3, 0);
- i = (BAR_SIZE * pct) / 100;
- while (i > v->tptr) {
- if (v->tptr >= BAR_SIZE) {
- break;
- }
- cprint(1, COL_MID+9+v->tptr, "#");
- v->tptr++;
- }
-
- pct = 100*v->total_ticks/v->pass_ticks;
- dprint(0, COL_MID+4, pct, 3, 0);
- i = (BAR_SIZE * pct) / 100;
- while (i > v->pptr) {
- if (v->pptr >= BAR_SIZE) {
- break;
- }
- cprint(0, COL_MID+9+v->pptr, "#");
- v->pptr++;
- }
-
- /* We can't do the elapsed time unless the rdtsc instruction
- * is supported
- */
- if (v->rdtsc) {
- asm __volatile__(
- "rdtsc":"=a" (l),"=d" (h));
- asm __volatile__ (
- "subl %2,%0\n\t"
- "sbbl %3,%1"
- :"=a" (l), "=d" (h)
- :"g" (v->startl), "g" (v->starth),
- "0" (l), "1" (h));
- t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
- t += (l / v->clks_msec) / 1000;
- i = t % 60;
- dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0);
- dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0);
- t /= 60;
- i = t % 60;
- dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0);
- dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0);
- t /= 60;
- dprint(LINE_TIME, COL_TIME, t, 4, 0);
- }
-
- /* Check for keyboard input */
- check_input();
-
- /* Poll for ECC errors */
- poll_errors();
-}
-
/* Sleep function */
void sleep(int n, int sms)
diff --git a/test.h b/test.h
index ca53ecb..1fff1db 100644
--- a/test.h
+++ b/test.h
@@ -44,6 +44,10 @@ typedef unsigned long ulong;
#define BAILOUT if (bail) goto skip_test;
#define BAILR if (bail) return;
+#define DMI_SEARCH_START 0x0000F000
+#define DMI_SEARCH_LENGTH 0x000F0FFF
+#define MAX_DMI_MEMDEVS 16
+
#define RES_START 0xa0000
#define RES_END 0x100000
#define SCREEN_ADR 0xb8000
@@ -71,6 +75,8 @@ typedef unsigned long ulong;
#define LINE_HEADER 12
#define LINE_SCROLL 14
#define BAR_SIZE (78-COL_MID-9)
+#define LINE_MSG 18
+#define COL_MSG 18
#define POP_W 30
#define POP_H 15
@@ -83,10 +89,9 @@ typedef unsigned long ulong;
#define NULL 0
/* memspeed operations */
-#define MS_BCOPY 1
-#define MS_COPY 2
-#define MS_WRITE 3
-#define MS_READ 4
+#define MS_COPY 1
+#define MS_WRITE 2
+#define MS_READ 3
#define SZ_MODE_BIOS 1
#define SZ_MODE_BIOS_RES 2
@@ -94,6 +99,7 @@ typedef unsigned long ulong;
#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
int memcmp(const void *s1, const void *s2, ulong count);
+int strncmp(const char *s1, const char *s2, ulong n);
void *memmove(void *dest, const void *src, ulong n);
int query_linuxbios(void);
int query_pcbios(void);
@@ -102,6 +108,7 @@ void printpatn(void);
void printpatn(void);
void itoa(char s[], int n);
void reverse(char *p);
+void serial_console_setup(char *param);
void serial_echo_init(void);
void serial_echo_print(const char *s);
void ttyprint(int y, int x, const char *s);
@@ -130,6 +137,7 @@ void set_cache(int val);
void check_input(void);
void footer(void);
void scroll(void);
+void clear_scroll(void);
void popup(void);
void popdown(void);
void popclear(void);
@@ -161,15 +169,19 @@ void parity_err(ulong edi, ulong esi);
void start_config(void);
void clear_screen(void);
void paging_off(void);
+void show_spd(void);
int map_page(unsigned long page);
void *mapping(unsigned long page_address);
void *emapping(unsigned long page_address);
unsigned long page_of(void *ptr);
+ulong memspeed(ulong src, ulong len, int iter, int type);
+ulong correct_tsc(ulong el_org);
-#define PRINTMODE_ADDRESSES 0
-#define PRINTMODE_PATTERNS 1
-#define PRINTMODE_DMI 2
+#define PRINTMODE_SUMMARY 0
+#define PRINTMODE_ADDRESSES 1
+#define PRINTMODE_PATTERNS 2
#define PRINTMODE_NONE 3
+#define PRINTMODE_DMI 4
#define BADRAM_MAXPATNS 10
@@ -253,9 +265,29 @@ struct cpu_ident {
unsigned char cache_info[16];
long pwrcap;
long ext;
+ long feature_flag;
+};
+
+struct xadr {
+ ulong page;
+ ulong offset;
};
-#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
+struct err_info {
+ struct xadr low_addr;
+ struct xadr high_addr;
+ unsigned long ebits;
+ long tbits;
+ short min_bits;
+ short max_bits;
+ unsigned long maxl;
+ unsigned long eadr;
+ unsigned long exor;
+ unsigned long cor_err;
+ short hdr_flag;
+};
+
+#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
#define MAX_MEM_SEGMENTS E820MAX
/* Define common variables accross relocations of memtest86 */
@@ -277,6 +309,7 @@ struct vars {
int pptr;
int tptr;
int beepmode;
+ struct err_info erri;
struct pmap pmap[MAX_MEM_SEGMENTS];
struct mmap map[MAX_MEM_SEGMENTS];
ulong plim_lower;