summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2013-09-27 19:45:22 +0200
committerMichael Brown2014-04-08 00:39:05 +0200
commit541d4c97110cefeda23461c691e02dd2e431e609 (patch)
treea26b9d72e52dd9430f2824e3c74d1adacadd7310
parent[import] Import version 4.20 (diff)
downloadmemtest86-541d4c97110cefeda23461c691e02dd2e431e609.tar.gz
memtest86-541d4c97110cefeda23461c691e02dd2e431e609.tar.xz
memtest86-541d4c97110cefeda23461c691e02dd2e431e609.zip
[import] Import version 5.01
http://www.memtest.org/download/5.01/memtest86+-5.01.tar.gz
-rw-r--r--Makefile33
-rw-r--r--README1405
-rw-r--r--README.background156
-rw-r--r--README.build-process78
-rw-r--r--build-number.txt1
-rw-r--r--build.number1
-rw-r--r--build_number.h9
-rw-r--r--buildnumber.mak10
-rw-r--r--changelog32
-rw-r--r--config.c360
-rw-r--r--config.h32
-rw-r--r--controller.c2531
-rw-r--r--controller.h15
-rw-r--r--cpuid.c321
-rw-r--r--cpuid.h231
-rw-r--r--defs.h11
-rw-r--r--dmi.c125
-rw-r--r--dmi.h1
-rw-r--r--elf.h43
-rw-r--r--error.c322
-rw-r--r--extra.c31
-rw-r--r--head.S365
-rw-r--r--init.c1933
-rw-r--r--io.h1
-rw-r--r--jedec_id.h1849
-rw-r--r--lib.c518
-rw-r--r--main.c1488
-rw-r--r--major_version1
-rwxr-xr-xmake_buildnum.sh20
-rwxr-xr-xmakeiso.sh8
-rw-r--r--memsize.c197
-rw-r--r--memtest.bin.lds30
-rw-r--r--memtest.lds22
-rw-r--r--memtest_shared.lds106
-rw-r--r--msr.h23
-rw-r--r--mt86+_loaderbin784 -> 784 bytes
-rw-r--r--mt86+_loader.asm4
-rw-r--r--patn.c2
-rw-r--r--pci.c58
-rw-r--r--pci.h1
-rwxr-xr-xprecomp.binbin164504 -> 150024 bytes
-rw-r--r--random.c43
-rw-r--r--reloc.c31
-rw-r--r--screen_buffer.c83
-rw-r--r--screen_buffer.h5
-rw-r--r--setup.S301
-rw-r--r--smp.c620
-rw-r--r--smp.h159
-rw-r--r--spd.c193
-rw-r--r--spd.h8
-rw-r--r--stddef.h8
-rw-r--r--stdin.h52
-rw-r--r--test.c1301
-rw-r--r--test.h231
-rw-r--r--version.number1
-rw-r--r--vmem.c154
56 files changed, 8734 insertions, 6830 deletions
diff --git a/Makefile b/Makefile
index f51b813..9717a14 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
# Author: Chris Brady
# Created: January 1, 1996
+
#
# Path for the floppy disk device
#
@@ -11,20 +12,23 @@ FDISK=/dev/fd0
AS=as -32
CC=gcc
-CFLAGS= -Wall -march=i486 -m32 -O2 -fomit-frame-pointer -fno-builtin -ffreestanding -fPIC -fno-stack-protector
-
+CFLAGS= -Wall -march=i486 -m32 -O1 -fomit-frame-pointer -fno-builtin \
+ -ffreestanding -fPIC $(SMP_FL) -fno-stack-protector
+
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 spd.o \
- error.o dmi.o cpuid.o
+ config.o cpuid.o linuxbios.o pci.o memsize.o spd.o error.o dmi.o controller.o \
+ smp.o vmem.o random.o
+
-all: memtest.bin memtest
+all: clean memtest.bin memtest
+ scp memtest.bin root@192.168.0.12:/srv/tftp/mt86plus
# 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) && \
+ -o $@ $(OBJS) && \
$(LD) -shared -Bsymbolic -T memtest_shared.lds -o $@ $(OBJS)
memtest_shared.bin: memtest_shared
@@ -50,18 +54,22 @@ reloc.o: reloc.c
$(CC) -c $(CFLAGS) -fno-strict-aliasing reloc.c
test.o: test.c
- $(CC) -c -Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin -ffreestanding test.c
+ $(CC) -c -Wall -march=i486 -m32 -O0 -fomit-frame-pointer -fno-builtin -ffreestanding test.c
-clean:
- rm -f *.o *.s *.iso memtest.bin memtest memtest_shared memtest_shared.bin
+random.o: random.c
+ $(CC) -c -Wall -march=i486 -m32 -O3 -fomit-frame-pointer -fno-builtin -ffreestanding random.c
+
+# rule for build number generation
+build_number:
+ sh make_buildnum.sh
-asm:
- @./makedos.sh
+clean:
+ rm -f *.o *.s *.iso memtest.bin memtest memtest_shared \
+ memtest_shared.bin memtest.iso
iso:
make all
./makeiso.sh
- rm -f *.o *.s memtest.bin memtest memtest_shared memtest_shared.bin
install: all
dd <memtest.bin >$(FDISK) bs=8192
@@ -71,4 +79,3 @@ install-precomp:
dos: all
cat mt86+_loader memtest.bin > memtest.exe
-
diff --git a/README b/README
index 963cfc4..f9df887 100644
--- a/README
+++ b/README
@@ -1,480 +1,925 @@
-Memtest86++ v4.20
-====================
-
-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
-
-
-
-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.memtest.org
-
-
-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 v0.91 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 0.91 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 Memtest86+.
-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.
-
-
-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.
-
-
+ ====================
+ = MemTest-86 v4.0 =
+ = 28 Mar, 2011 =
+ = 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) 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.
+
+
+3) Linux Installation
+============================
+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 may be loaded from a disk
+partition via Lilo or Grub 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 Grub
+ 1) Copy the image file to a permanent location (ie. /boot/memtest.bin).
+ 2) Add an entry in the Grub config file (/boot/grub/menu.lst) to boot
+ memtest86. Only the title and kernel fields need to be specified.
+ The following is a sample Grub entry for booting memtest86:
+
+ title Memtest86
+ kernel (hd0,0)/memtest.bin
+
+ To boot from a disk partition via Lilo
+ 1) Copy the image file to a permanent location (ie. /boot/memtest.bin).
+ 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 = /boot/memtest.bin
+ label = memtest86
+
+ 3) As root, type "lilo"
+
+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) Test selection
+ 2) Address Range
+ 3) Error Report Mode
+ 4) CPU Selection Mode
+ 5) Refresh Screen
+
+ 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) Error Information
+======================
+Memtest has three options for reporting errors. The default is an an error
+summary that displays the most relevant error information. The second option
+is reporting of 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
+
+The error summary mode displays the following information:
+
+ Error Confidence Value:
+ A value that indicates the validity of the errors being reported with
+ larger values indicating greater validity. There is a high probability
+ that all errors reported are valid regardless of this value. However,
+ when this value exceeds 100 it is nearly impossible that the reported
+ errors will be invalid.
+
+ Lowest Error Address:
+ The lowest address that where an error has been reported.
+
+ Highest Error Address:
+ The highest address that where an error has been reported.
+
+ Bits in Error Mask:
+ A mask of all bits that have been in error (hexadecimal).
+
+ Bits in Error:
+ Total bit in error for all error instances and the min, max and average
+ bit in error of each individual occurrence.
+
+ Max Contiguous Errors:
+ The maximum of contiguous addresses with errors.
+
+ ECC Correctable Errors:
+ The number of errors that have been corrected by ECC hardware.
+
+ Test Errors:
+ On the right hand side of the screen the number of errors for each test
+ are displayed.
+
+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
+ CPU: CPU that detected the error
+
+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.
+
+
+7) 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.
+
+
+8) 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.
+
+9) 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.
+
+
+11) 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 Sequential]
+ 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. This test is done
+ sequentially with each available CPU.
+
+Test 2 [Address test, own address Parallel]
+ Same as test 1 but the testing is done in parallel using all CPUs using
+ overlapping addresses.
+
+Test 3 [Moving inversions, ones&zeros Sequential]
+ 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 test is done sequentially with each available CPU.
+
+Test 4 [Moving inversions, ones&zeros Parallel]
+ Same as test 3 but the testing is done in parallel using all CPUs.
+
+Test 5 [Moving inversions, 8 bit pat]
+ This is the same as test 4 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 6 [Moving inversions, random pattern]
+ Test 6 uses the same algorithm as test 4 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.
+ The random number sequence is different with each pass
+ so multiple passes increase effectiveness.
+
+Test 7 [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 8 [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 9 [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 10 [Modulo 20, random pattern]
+ 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. A 32 bit random pattern is used.
+
+Test 11 [Bit fade test, 2 patterns]
+ The bit fade test initializes all of memory with a pattern and then
+ sleeps for 5 minutes. Then memory is examined to see if any memory bits
+ have changed. All ones and all zero patterns are used.
+
+
+12) 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 respond 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.
+
+
+15) 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 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 the block move test. 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 high 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 at full speed.
+
+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.
+
+ - Testing in 64 bit mode with 64 data patterns
+ - Support for reporting ECC errors was removed in the 4.0 release. A
+ simplified implementation of ECC reporting is planned for a future release.
+
+
+16) Change Log
+==============
+Enhancements in v4.0 (28/Mar/2011)
+
+ Full support for testing with multiple CPUs. All tests except for #11 (Bit
+ Fade) have been multi-threaded. A maximum of 16 CPUs will be used for testing.
+
+ CPU detection has been completely re-written to use the brand ID string
+ rather than the cumbersome, difficult to maintain and often out of date
+ CPUID family information. All new processors will now be correctly
+ identified without requiring code support.
+
+ All code related to controller identification, PCI and DMI has been removed.
+ This may be a controversial decision and was not made lightly. The following
+ are justifications for the decision:
+
+ 1. Controller identification has nothing to do with actual testing of
+ memory, the core purpose of Memtest86.
+ 2. This code needed to be updated with every new chipset. With the ever
+ growing number of chipsets it is not possible to keep up with the
+ changes. The result is that new chipsets were more often than not
+ reported in-correctly. In the authors opinion incorrect information is
+ worse than no information.
+ 3. Probing for chipset information carries the risk of making the program
+ crash.
+ 4. The amount of code involved with controller identification was quite
+ large, making support more difficult.
+
+ Removing this code also had the unfortunate effect of removing reporting of
+ correctable ECC errors. The code to support ECC was hopelessly intertwined
+ the controller identification code. A fresh, streamlined implementation of
+ ECC reporting is planned for a future release.
+
+ A surprising number of conditions existed that potentially cause problems
+ when testing more than 4 GB of memory. Most if not all of these conditions
+ have been identified and corrected.
+
+ A number of cases were corrected where not all of memory was being tested.
+ For most tests the last word of each test block was not tested. In addition
+ an error in the paging code was fixed that omitted from testing the last 256
+ bytes of each block above 2 GB.
+
+ The information display has been simplified and a number of details that were
+ not relevant to testing were removed.
+
+ Memory speed reporting has been parallelized for more accurate reporting for
+ multi channel memory controllers.
+
+ This is a major re-write of the Memtest86 with a large number of minor
+ bug-fixes and substantial cleanup and re-organization of the code.
+
+
+Enhancements in v3.5 (3/Jan/2008)
+
+ Limited support for execution with multiple CPUs. CPUs are selected
+ round-robin or sequential for each test.
+
+ Support for additional chipsets. (from Memtest86+ v2.11).
+
+ Additions and corrections for CPU detection including reporting of L3 cache.
+
+ Reworked information display for better readability and new information.
+
+ Abbreviated iterations for first pass.
+
+ Enhancements to memory sizing.
+
+ Misc fixes.
+
+Enhancements in v3.4 (2/Aug/2007)
+
+ A new error summary display with error confidence analysis.
+
+ Support for additional chipsets. (from Memtest86+ v1.70).
+
+ Additions and corrections for CPU detection.
+
+ Support for memory module information reporting.
+
+ Misc bug fixes.
+
+Enhancements in v3.3 (12/Jan/2007)
+
+ Added support for additional chipsets. (from Memtest86+ v1.60)
+
+ Changed Modulo 20 test (#8) to use a more effective random pattern rather
+ than simple ones and zeros.
+
+ Fixed a bug that prevented testing of low memory.
+
+ Added an advanced menu option to display SPD info (only for selected
+ chipsets).
+
+ Updated CPU detection for new CPUs and corrected some bugs.
+
+ Reworked online command text for better clarity.
+
+ Added a fix to correct a Badram pattern bug.
+
+
+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 some 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 compile 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 UN-connecting a serial cable.
+
+ Net-booting is working again
+
+ Linux-BIOS support (To get the memory size)
+
+ Many bug-fixes 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 effectiveness 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) 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,
+ 3.3 pnd 3.4 rovided by Samuel Demeulemeester (from Memtest86+ v1.11, v1.60
+ and v1.70).
diff --git a/README.background b/README.background
new file mode 100644
index 0000000..9c35250
--- /dev/null
+++ b/README.background
@@ -0,0 +1,156 @@
+ The Anatomy & Physiology of Memtest86-SMP
+ -----------------------------------------
+
+1. Binary layout
+
+ ---------------------------------------------------------------
+ | bootsect.o | setup.o | head.o memtest_shared |
+ ---------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ -----------------------------------------------------------
+addr 0 512 512+4*512 |
+ -----------------------------------------------------------
+
+2. The following steps occur after we power on.
+ a. The bootsect.o code gets loaded at 0x7c00
+ and copies
+ i. itself to 0x90000
+ ii. setup.o to 0x90200
+ iii. everything between _start and _end i.e memtest
+ to 0x10000
+ b. jumps somewhere into the copied bootsect.o code at 0x90000
+ ,does some trivial stuff and jumps to setup.o
+ c. setup.o puts the processor in protected mode, with a basic
+ gdt and idt and does a long jump to the start of the
+ memtest code (startup_32, see 4 below). The code and data
+ segment base address are all set to 0x0. So a linear
+ address range and no paging is enabled.
+ d. From now on we no longer required the bootsect.o and setup.o
+ code.
+3. The code in memtest is compiled as position independent
+ code. Which implies that the code can be moved dynamically in
+ the address space and can still work. Since we are now in head.o,
+ which is compiled with PIC , we no longer should use absolute
+ addresses references while accessing functions or globals.
+ All symbols are stored in a table called Global Offset Table(GOT)
+ and %ebx is set to point to the base of that table. So to get/set
+ the value of a symbol we need to read (%ebx + symbolOffsetIntoGOT) to
+ get the symbol value. For eg. if foo is global varible the assembly
+ code to store %eax value into foo will be changed from
+ mov %eax, foo
+ to
+ mov %eax, foo@GOTOFF(%ebx)
+4. (startup_32) The first step done in head.o is to change
+ the gdtr and idtr register values to point to the final(!)
+ gdt and ldt tables in head.o, since we can no longer use the
+ gdt and ldt tables in setup.o, and call the dynamic linker
+ stub in memtest_shared (see call _dl_start in head.S). This
+ dynamic linker stub relocates all the code in memtest w.r.t
+ the new base location i.e 0x1000. Finally we call the test_start()
+ 'C' routine.
+5. The test_start() C routine is the main routine which lets the BSP
+ bring up the APs from their halt state, relocate the code
+ (if necessary) to new address, move the APs to the newly
+ relocated address and execute the tests. The BSP is the
+ master which controls the execution of the APs, and mostly
+ it is the one which manupulates the global variables.
+ i. we change the stack to a private per cpu stack.
+ (this step happens every time we move to a new location)
+ ii. We kick start the APs in the system by
+ a. Putting a temporary real mode code
+ (_ap_trampoline_start - _ap_trampoline_protmode)
+ at 0x9000, which puts the AP in protected mode and jumps
+ to _ap_trampoline_protmode in head.o. The code in
+ _ap_trampoline_protmode calls start_32 in head.o which
+ reinitialises the AP's gdt and idt to point to the
+ final(!) gdt and idt. (see step 4 above)
+ b. Since the APs also traverse through the same initialisation
+ code(startup_32 in head.o), the APs also call test_start().
+ The APs just spin wait (see AP_SpinWaitStart) till the
+ are instructed by the BSP to jump to a new location,
+ which can either be a test execution or spin wait at a
+ new location.
+ iii. The base address at which memtest tries to execute as far
+ as possible is 0x2000. This is the lowest possible address
+ memtest can put itself at. So the next step is to
+ move to 0x2000, which it cannot directly, since copying
+ code to 0x2000 will override the existing code at 0x1000.
+ 0x2000 +sizeof(memtest) will usually be greater than 0x1000.
+ so we temporarily relocated to 0x200000 and then relocate
+ back to 0x2000. Every time the BSP relocates the code to the
+ new location, it pulls up the APs spin waiting at the old
+ location to spin wait at the corresponding relocated
+ spin wait location, by making them jump to the new
+ statup_32 relocated location(see 4 above).
+ Hence forth during the tests 0x200000 is the only place
+ we relocate to if we need to test a memory window
+ (see v. below to get a description of what a window is)
+ which includes address range 0x2000.
+
+ Address map during normal execution.
+ --------------------------------------------------------------------
+ | head.o memtest_shared | |RAM_END
+ --------------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ --------------------------------------------------------------------
+addr 0x0 0x2000 | Memory that is being tested.. |RAM_END
+ --------------------------------------------------------------------
+
+ Address map during relocated state.
+ --------------------------------------------------------------------
+ | head.o memtest_shared | |RAM_END
+ --------------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ --------------------------------------------------------------------
+addr memory that is being tested... |0x200000 | |RAM_END
+ --------------------------------------------------------------------
+
+ iv. Once we are at 0x2000 we initialise the system, and
+ determine the memory map ,usually via the bios e820 map.
+ The sorted, and non-overlapping RAM page ranges are
+ placed in v->pmap[] array. This array is the reference
+ of the RAM memory map on the system.
+ v. The memory range(in page numbers) which the
+ memtest86 can test is partitioned into windows.
+ the current version of memtest86-smp has the capability
+ to test the memory from 0x0 - 0xFFFFFFFFF (max address
+ when pae mode is enabled).
+ We then compute the linear memory address ranges(called
+ segments) for the window we are currently about to
+ test. The windows are
+ a. 0 - 640K
+ b. (0x2000 + (_end - _start)) - 4G (since the code is at 0x2000).
+ c. >4G to test pae address range, each window with size
+ of 0x80000(2G), large enough to be mapped in one page directory
+ entry. So a window size of 0x80000 means we can map 1024 page
+ table entries, with page size of 2M(pae mode), with one
+ page directory entry. Something similar to kseg entry
+ in linux. The upper bound page number is 0x1000000 which
+ corresponds to linear address 0xFFFFFFFFF + 1 which uses
+ all the 36 address bits.
+ Each window is compared against the sorted & non-overlapping
+ e820 map which we have stored in v->pmap[] array, since all
+ memory in the selected window address range may correspond to
+ RAM or can be usable. A list of segments within the window is
+ created , which contain the usable portions of the window.
+ This is stored in v->mmap[] array.
+ vi. Once the v->mmap[] array populated, we have the list of
+ non-overlapping segments in the current window which are the
+ final address ranges that can be tested. The BSP executes the
+ test first and lets each AP execute the test one by one. Once
+ all the APs finish execting the same test, the BSP moves to the
+ next window follows the same procedure till all the windows
+ are done. Once all the windows are done, the BSP moves to the
+ next test. Before executing in any window the BSP checks if
+ the window overlaps with the code/data of memtest86, if so
+ tries to relocate to 0x200000. If the window includes both
+ 0x2000 as well as 0x200000 the BSP skips that window.
+ Looking at the window values the only time the memtest
+ relocates is when testing the 0 - 640K window.
+
+Known Issues:
+* Memtest86-smp does not work on IBM-NUMA machines, x440 and friends.
+
+email comments to:
+Kalyan Rajasekharuni<kc_rajasekharuni@yahoo.com>
+Sub: Memtest86-SMP
diff --git a/README.build-process b/README.build-process
index a959e7b..19edfcf 100644
--- a/README.build-process
+++ b/README.build-process
@@ -1,39 +1,39 @@
-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+
-so it can be loaded from a floppy, or from lilo.
-
-In restructuring the build process I had several goals. Maintainability and
-comprehsibility of the build process. Simplicity of the toolset. And the
-ability to build images bootable by both the legacy x86 bootloader,
-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+.
-
-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
-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
-and linked into memtest.bin, and memtest.
-
-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.
-
-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
-relocated, which might lead to nasty surpises.
-
-Eric Biederman <ebiederman@lnxi.com>
-
+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
+so it can be loaded from a floppy, or from lilo.
+
+In restructuring the build process I had several goals. Maintainability and
+comprehsibility of the build process. Simplicity of the toolset. And the
+ability to build images bootable by both the legacy x86 bootloader,
+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.
+
+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
+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
+and linked into memtest.bin, and memtest.
+
+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.
+
+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
+relocated, which might lead to nasty surpises.
+
+Eric Biederman <ebiederman@lnxi.com>
+
diff --git a/build-number.txt b/build-number.txt
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/build-number.txt
@@ -0,0 +1 @@
+7
diff --git a/build.number b/build.number
new file mode 100644
index 0000000..e110e8d
--- /dev/null
+++ b/build.number
@@ -0,0 +1 @@
+617
diff --git a/build_number.h b/build_number.h
new file mode 100644
index 0000000..d1f2abc
--- /dev/null
+++ b/build_number.h
@@ -0,0 +1,9 @@
+#ifndef BUILD_NUMBER_STR
+#define BUILD_NUMBER_STR "617"
+#endif
+#ifndef VERSION_STR
+#define VERSION_STR "4.99617 - Thu May 3 11:45:57 CEST 2012"
+#endif
+#ifndef VERSION_STR_SHORT
+#define VERSION_STR_SHORT "4.99617"
+#endif
diff --git a/buildnumber.mak b/buildnumber.mak
new file mode 100644
index 0000000..8d5b85d
--- /dev/null
+++ b/buildnumber.mak
@@ -0,0 +1,10 @@
+# Create an auto-incrementing build number.
+
+BUILD_NUMBER_LDFLAGS = -Xlinker --defsym -Xlinker __BUILD_DATE=$$(date +'%Y%m%d')
+BUILD_NUMBER_LDFLAGS += -Xlinker --defsym -Xlinker __BUILD_NUMBER=$$(cat $(BUILD_NUMBER_FILE))
+
+# Build number file. Increment if any object file changes.
+$(BUILD_NUMBER_FILE): $(OBJS)
+ @if ! test -f $(BUILD_NUMBER_FILE); then echo 0 > $(BUILD_NUMBER_FILE); fi
+ @echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE)
+
diff --git a/changelog b/changelog
index d6e49d2..9379a5b 100644
--- a/changelog
+++ b/changelog
@@ -1,9 +1,25 @@
-Memtest86+ V4.20 changelog
---------------------------
+Memtest86+ V5.01 changelog
+----------------------------
- - Added failsafe mode (F1 at startup)
- - Added support for Intel "Sandy Bridge" CPU
- - Added support for AMD "fusion" CPU
- - Added Coreboot "table forward" support
- - Corrected some memory brand not detected
- - Various bug fixes \ No newline at end of file
+ - Added support for up to 2 TB of RAM on X64 CPUs
+ - Added experimental SMT support up to 32 cores
+ - Added complete detection for memory controllers.
+ - Added Motherboard Manufacturer & Model reporting
+ - Added CPU temperature reporting
+ - Added enhanced Fail Safe Mode (Press F1 at startup)
+ - Added support for Intel "Sandy Bridge-E" CPUs
+ - Added support for Intel "Ivy Bridge" CPUs
+ - Added preliminary support for Intel "Haswell" CPUs
+ - Added preliminary support for Intel "Haswell-ULT" CPUs
+ - Added support for AMD "Kabini" (K16) CPUs
+ - Added support for AMD "Bulldozer" CPUs
+ - Added support for AMD "Trinity" CPUs
+ - Added support for AMD E-/C-/G-/Z- "Bobcat" CPUs
+ - Added support for Intel Atom "Pineview" CPUs
+ - Added support for Intel Atom "Cedar Trail" CPUs
+ - Added SPD detection on most AMD Chipsets
+ - Enforced Coreboot support
+ - Optimized run time for faster memory error detection
+ - Rewriten lots of memory timings detection code
+ - Corrected bugs, bugs and more bugs
+
diff --git a/config.c b/config.c
index 6d29004..18d8887 100644
--- a/config.c
+++ b/config.c
@@ -3,30 +3,36 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V4.00 Specific code (GPL V2.0)
+ * MemTest86+ V5.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 "screen_buffer.h"
-#include "controller.h"
#include "dmi.h"
-#define ITER 20
extern int bail, beepmode;
extern struct tseq tseq[];
extern short e820_nr;
-extern char memsz_mode;
-extern int find_ticks_for_pass();
-//void performance();
+void performance();
+extern volatile short cpu_mode;
+extern volatile int test;
+extern void find_chunks();
+extern volatile short start_seq;
+extern short restart_flag;
+extern short onepass;
+extern short btflag;
+
+extern void get_list(int x, int y, int len, char *buf);
char save[2][POP_H][POP_W];
char save2[2][POP2_H][POP2_W];
void get_config()
{
- int flag = 0, sflag = 0, i, prt = 0;
- int reprint_screen = 0;
+ int flag = 0, sflag = 0, i, j, k, n, m, prt = 0;
+ int reprint_screen = 0;
+ char cp[64];
ulong page;
popup();
@@ -35,14 +41,12 @@ void get_config()
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 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) Display SPD Data");
- cprint(POP_Y+12, POP_X+6, "(0) Continue");
+ cprint(POP_Y+5, POP_X+6, "(3) Error Report Mode");
+ cprint(POP_Y+6, POP_X+6, "(4) Core Selection");
+ cprint(POP_Y+7, POP_X+6, "(5) Refresh Screen");
+ cprint(POP_Y+8, POP_X+6, "(6) Display DMI Data");
+ cprint(POP_Y+9, POP_X+6, "(7) Display SPD Data");
+ cprint(POP_Y+11, POP_X+6, "(0) Continue");
/* Wait for key release */
/* Fooey! This nuts'es up the serial input. */
@@ -55,9 +59,8 @@ void get_config()
cprint(POP_Y+3, POP_X+6, "(1) Default Tests");
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+8, POP_X+6, "(0) Continue");
+ cprint(POP_Y+6, POP_X+6, "(4) Enter Test List");
+ cprint(POP_Y+7, POP_X+6, "(0) Cancel");
if (v->testsel < 0) {
cprint(POP_Y+3, POP_X+5, ">");
} else {
@@ -67,14 +70,14 @@ void get_config()
while (!sflag) {
switch(get_key()) {
case 2:
- /* Default */
- if (v->testsel >= 9) {
- bail++;
+ /* Default - All tests */
+ i = 0;
+ while (tseq[i].cpu_sel) {
+ tseq[i].sel = 1;
+ i++;
}
- v->testsel = -1;
find_ticks_for_pass();
sflag++;
- cprint(LINE_INFO, COL_TST, "Std");
break;
case 3:
/* Skip test */
@@ -87,47 +90,79 @@ void get_config()
cprint(POP_Y+1, POP_X+3,
"Test Selection:");
cprint(POP_Y+4, POP_X+5,
- "Test Number [0-9]: ");
- i = getval(POP_Y+4, POP_X+24, 0);
- if (i <= 9) {
- if (i != v->testsel) {
- v->pass = -1;
- v->test = -1;
+ "Test Number [1-11]: ");
+ n = getval(POP_Y+4, POP_X+24, 0) - 1;
+ if (n <= 11)
+ {
+ /* Deselect all tests */
+ i = 0;
+ while (tseq[i].cpu_sel) {
+ tseq[i].sel = 0;
+ i++;
+ }
+ /* Now set the selection */
+ tseq[n].sel = 1;
+ v->pass = -1;
+ test = n;
+ find_ticks_for_pass();
+ sflag++;
+ bail++;
}
- v->testsel = i;
- }
- find_ticks_for_pass();
- sflag++;
- bail++;
- cprint(LINE_INFO, COL_TST, "#");
- dprint(LINE_INFO, COL_TST+1, i, 2, 1);
break;
case 5:
- if (v->testsel != 9) {
- v->pass = -1;
- v->test = -1;
+ /* Enter a test list */
+ popclear();
+ cprint(POP_Y+1, POP_X+3,
+ "Enter a comma separated list");
+ cprint(POP_Y+2, POP_X+3,
+ "of tests to execute:");
+ cprint(POP_Y+5, POP_X+5, "List: ");
+ /* Deselect all tests */
+ k = 0;
+ while (tseq[k].cpu_sel) {
+ tseq[k].sel = 0;
+ k++;
}
- v->testsel = 9;
- find_ticks_for_pass();
- sflag++;
- bail++;
- cprint(LINE_INFO, COL_TST, "#");
- dprint(LINE_INFO, COL_TST+1, 9, 3, 1);
- break;
-/*
- case 6:
- if (v->testsel != 10) {
- v->pass = -1;
- v->test = -1;
+
+ /* Get the list */
+ for (i=0; i<64; i++) cp[i] = 0;
+ get_list(POP_Y+5, POP_X+10, 64, cp);
+
+ /* Now enable all of the tests in the
+ * list */
+ i = j = m = 0;
+ while (1) {
+ if (isdigit(cp[i])) {
+ n = cp[i]-'0';
+ j = j*10 + n;
+ i++;
+ if (cp[i] == ',' || cp[i] == 0){
+ if (j < k) {
+ tseq[j].sel = 1;
+ m++;
+ }
+ if (cp[i] == 0) break;
+ j = 0;
+ i++;
+ }
+ }
}
- v->testsel = 9+1;
+
+ /* If we didn't select at least one
+ * test turn them all back on */
+ if (m == 0) {
+ k = 0;
+ while (tseq[k].cpu_sel) {
+ tseq[k].sel = 1;
+ k++;
+ }
+ }
+ v->pass = -1;
+ test = n;
find_ticks_for_pass();
sflag++;
- bail++;
- cprint(LINE_INFO, COL_TST, "#");
- dprint(LINE_INFO, COL_TST+1, 10, 3, 1);
+ bail++;
break;
-*/
case 11:
case 57:
sflag++;
@@ -143,7 +178,7 @@ void get_config()
cprint(POP_Y+3, POP_X+6, "(1) Set Lower Limit");
cprint(POP_Y+4, POP_X+6, "(2) Set Upper Limit");
cprint(POP_Y+5, POP_X+6, "(3) Test All Memory");
- cprint(POP_Y+6, POP_X+6, "(0) Continue");
+ cprint(POP_Y+6, POP_X+6, "(0) Cancel");
wait_keyup();
while (!sflag) {
switch(get_key()) {
@@ -160,10 +195,11 @@ void get_config()
page = getval(POP_Y+6, POP_X+9, 12);
if (page + 1 <= v->plim_upper) {
v->plim_lower = page;
- v->test--;
+ test--;
bail++;
}
adj_mem();
+ find_chunks();
find_ticks_for_pass();
sflag++;
break;
@@ -180,20 +216,23 @@ 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++;
+ test--;
}
adj_mem();
+ find_chunks();
find_ticks_for_pass();
sflag++;
break;
case 4:
/* All of memory */
v->plim_lower = 0;
- v->plim_upper = v->pmap[v->msegs - 1].end;
- v->test--;
+ v->plim_upper =
+ v->pmap[v->msegs - 1].end;
+ test--;
bail++;
adj_mem();
+ find_chunks();
find_ticks_for_pass();
sflag++;
break;
@@ -207,59 +246,20 @@ void get_config()
popclear();
break;
case 4:
- /* 3 - Memory Sizing */
- popclear();
- cprint(POP_Y+1, POP_X+2, "Memory Sizing:");
- cprint(POP_Y+3, POP_X+6, "(1) BIOS - Std");
- cprint(POP_Y+4, POP_X+6, "(2) Probe");
- cprint(POP_Y+5, POP_X+6, "(0) Continue");
- if(!e820_nr){
- if (memsz_mode == SZ_MODE_BIOS) {
- cprint(POP_Y+3, POP_X+5, ">");
- } else {
- cprint(POP_Y+4, POP_X+5, ">");
- }
- }
- wait_keyup();
- while (!sflag) {
- switch(get_key()) {
- case 2:
- memsz_mode = SZ_MODE_BIOS;
- wait_keyup();
- restart();
-
- break;
- case 3:
- memsz_mode = SZ_MODE_PROBE;
- wait_keyup();
- restart();
-
- break;
- case 11:
- case 57:
- /* 0/CR - Continue */
- sflag++;
- break;
- }
- }
- popclear();
- break;
- case 5:
- /* 4 - Show error Mode */
+ /* Error Mode */
popclear();
cprint(POP_Y+1, POP_X+2, "Printing Mode:");
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) 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+7, POP_X+6, "(5) Beep on Error");
+ cprint(POP_Y+8, POP_X+6, "(0) Cancel");
cprint(POP_Y+3+v->printmode, POP_X+5, ">");
- if (beepmode) { cprint(POP_Y+8, POP_X+5, ">"); }
+ if (beepmode) { cprint(POP_Y+7, POP_X+5, ">"); }
wait_keyup();
while (!sflag) {
- switch(get_key()) {
+ switch(get_key()) {
case 2:
/* Error Summary */
v->printmode=PRINTMODE_SUMMARY;
@@ -289,16 +289,10 @@ void get_config()
sflag++;
break;
case 6:
- /* Error Counts Only */
- v->printmode=PRINTMODE_DMI;
- v->erri.hdr_flag = 0;
- sflag++;
- break;
- case 7:
/* Set Beep On Error mode */
beepmode = !beepmode;
sflag++;
- break;
+ break;
case 11:
case 57:
/* 0/CR - Continue */
@@ -308,34 +302,42 @@ void get_config()
}
popclear();
break;
- case 6:
- /* Display DMI Memory Info */
- pop2up();
- print_dmi_info();
- pop2down();
- break;
- case 7:
- /* 6 - ECC Polling Mode */
+ case 5:
+ /* CPU Mode */
+ reprint_screen = 1;
popclear();
- cprint(POP_Y+1, POP_X+2, "ECC Polling Mode:");
- cprint(POP_Y+3, POP_X+6, "(1) Recommended");
- cprint(POP_Y+4, POP_X+6, "(2) On");
- cprint(POP_Y+5, POP_X+6, "(3) Off");
- cprint(POP_Y+6, POP_X+6, "(0) Continue");
+ cprint(POP_Y+1, POP_X+2, "CPU Selection Mode:");
+ cprint(POP_Y+3, POP_X+6, "(1) Parallel (All)");
+ cprint(POP_Y+4, POP_X+6, "(2) Round Robin (RRb)");
+ cprint(POP_Y+5, POP_X+6, "(3) Sequential (Seq)");
+ cprint(POP_Y+6, POP_X+6, "(0) Cancel");
+ cprint(POP_Y+2+cpu_mode, POP_X+5, ">");
wait_keyup();
while(!sflag) {
switch(get_key()) {
case 2:
- set_ecc_polling(-1);
+ if (cpu_mode != CPM_ALL) bail++;
+ cpu_mode = CPM_ALL;
sflag++;
+ popdown();
+ cprint(9,34,"All");
+ popup();
break;
case 3:
- set_ecc_polling(1);
+ if (cpu_mode != CPM_RROBIN) bail++;
+ cpu_mode = CPM_RROBIN;
sflag++;
+ popdown();
+ cprint(9,34,"RRb");
+ popup();
break;
case 4:
- set_ecc_polling(0);
+ if (cpu_mode != CPM_SEQ) bail++;
+ cpu_mode = CPM_SEQ;
sflag++;
+ popdown();
+ cprint(9,34,"Seq");
+ popup();
break;
case 11:
case 57:
@@ -346,15 +348,18 @@ void get_config()
}
popclear();
break;
- case 8:
- wait_keyup();
- restart();
- break;
- case 9:
+ case 6:
reprint_screen = 1;
flag++;
break;
- case 10:
+ case 7:
+ /* Display DMI Memory Info */
+ pop2up();
+ print_dmi_info();
+ pop2down();
+ break;
+ case 8:
+ /* Display SPD Data */
popdown();
show_spd();
popup();
@@ -372,12 +377,11 @@ void get_config()
if (prt) {
printpatn();
}
- if (reprint_screen){
- tty_print_screen();
- }
+ if (reprint_screen){
+ tty_print_screen();
+ }
}
-
void popup()
{
int i, j;
@@ -386,11 +390,11 @@ void popup()
for (i=POP_Y; i<POP_Y + POP_H; i++) {
for (j=POP_X; j<POP_X + POP_W; j++) {
pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2));
- save[0][i-POP_Y][j-POP_X] = *pp; /* Save screen */
- set_scrn_buf(i, j, ' ');
- *pp = ' '; /* Clear */
+ save[0][i-POP_Y][j-POP_X] = *pp; /* Save screen */
+ set_scrn_buf(i, j, ' ');
+ *pp = ' '; /* Clear */
pp++;
- save[1][i-POP_Y][j-POP_X] = *pp;
+ save[1][i-POP_Y][j-POP_X] = *pp;
*pp = 0x07; /* Change Background to black */
}
}
@@ -406,7 +410,7 @@ void popdown()
for (j=POP_X; j<POP_X + POP_W; j++) {
pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2));
*pp = save[0][i-POP_Y][j-POP_X]; /* Restore screen */
- set_scrn_buf(i, j, save[0][i-POP_Y][j-POP_X]);
+ set_scrn_buf(i, j, save[0][i-POP_Y][j-POP_X]);
pp++;
*pp = save[1][i-POP_Y][j-POP_X]; /* Restore color */
}
@@ -423,14 +427,13 @@ void popclear()
for (j=POP_X; j<POP_X + POP_W; j++) {
pp = (char *)(SCREEN_ADR + (i * 160) + (j * 2));
*pp = ' '; /* Clear popup */
- set_scrn_buf(i, j, ' ');
+ set_scrn_buf(i, j, ' ');
pp++;
}
}
tty_print_region(POP_Y, POP_X, POP_Y+POP_H, POP_X+POP_W);
}
-
void pop2up()
{
int i, j;
@@ -483,16 +486,6 @@ void pop2clear()
tty_print_region(POP2_Y, POP2_X, POP2_Y+POP2_H, POP2_X+POP2_W);
}
-void clear_screen()
-{
- int i;
- volatile char *pp;
-
- for(i=0, pp=(char *)(SCREEN_ADR); i<80*24; i++) {
- *pp++ = ' ';
- *pp++ = 0x07;
- }
-}
void adj_mem(void)
{
@@ -536,58 +529,3 @@ 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 e32eef4..aa4c9fb 100644
--- a/config.h
+++ b/config.h
@@ -1,11 +1,27 @@
-/* config.h - MemTest-86 Version 3.0
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
+ * ------------------------------------------------
+ * config.h - MemTest-86 Version 3.3
*
* Compile time configuration options
*
* Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
+ * By Chris Brady
*/
+/* CONSERVATIVE_SMP - If set to 0, SMP will be enabled by default */
+/* Might be enabled in future revision after extensive testing */
+/* In all cases, SMP is disabled by defaut on server platform */
+#define CONSERVATIVE_SMP 1
+
+/* BEEP_MODE - Beep on error. Default off, Change to 1 to enable */
+#define BEEP_MODE 0
+
+/* BEEP_END_NO_ERROR - Beep at end of each pass without error. Default off, Change to 1 to enable */
+#define BEEP_END_NO_ERROR 0
+
/* PARITY_MEM - Enables support for reporting memory parity errors */
/* Experimental, normally enabled */
#define PARITY_MEM
@@ -21,18 +37,6 @@
/* SERIAL_BAUD_RATE - Baud rate for the serial console */
#define SERIAL_BAUD_RATE 9600
-/* START_FAIL_SAFE - Default 0 = normal. Change to 1 to always start in fail safe mode */
-#define START_FAIL_SAFE 0
-
-/* BEEP_MODE - Beep on error. Default off, Change to 1 to enable */
-#define BEEP_MODE 0
-
-/* BEEP_END_NO_ERROR - Beep at end of each pass without error. Default off, Change to 1 to enable */
-#define BEEP_END_NO_ERROR 0
-
-/* FIRST_PASS_HALF_ITERATIONS - First pass twice faster / half iterations. Change to 0 to disable */
-#define FIRST_PASS_HALF_ITERATIONS 1
-
/* SCRN_DEBUG - extra check for SCREEN_BUFFER
*/
/* #define SCRN_DEBUG */
diff --git a/controller.c b/controller.c
index 9009996..f4f7371 100644
--- a/controller.c
+++ b/controller.c
@@ -1,21 +1,20 @@
-/* controller.c - MemTest-86 Version 3.0
- *
- * Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- * ----------------------------------------------------
- * MemTest86+ V4.20 Specific code (GPL V2.0)
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
-#include "defs.h"
+//#include "defs.h"
#include "config.h"
-#include "test.h"
+//#include "test.h"
#include "pci.h"
#include "controller.h"
#include "spd.h"
#include "test.h"
-
+#include "stdint.h"
+#include "cpuid.h"
+#include "msr.h"
+#include "dmi.h"
int col, col2;
int nhm_bus = 0x3F;
@@ -23,18 +22,17 @@ int nhm_bus = 0x3F;
extern ulong extclock;
extern unsigned long imc_type;
extern struct cpu_ident cpu_id;
-extern int fail_safe;
-
+/*
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
- : "c" (msr))
+ : "c" (msr) : "edi")
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
+ : \
+ : "c" (msr), "a" (val1), "d" (val2) : "edi")
+*/
/* controller ECC capabilities and mode */
#define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */
#define __ECC_DETECT 2 /* Can detect ECC errors */
@@ -74,115 +72,187 @@ static struct ecc_info {
.mode = ECC_UNKNOWN,
};
-struct pci_memory_controller {
- unsigned vendor;
- unsigned device;
- char *name;
- int tested;
- void (*poll_fsb)(void);
- void (*poll_timings)(void);
- void (*setup_ecc)(void);
- void (*poll_errors)(void);
-};
+void coretemp(void)
+{
+ unsigned int msrl, msrh;
+ unsigned int tjunc, tabs, tnow;
+ unsigned long rtcr;
+ double amd_raw_temp;
+
+ // Only enable coretemp if IMC is known
+ if(imc_type == 0) { return; }
+
+ tnow = 0;
+
+ // Intel CPU
+ if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6)
+ {
+ if(cpu_id.dts_pmp & 1){
+ rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
+ tabs = ((msrl >> 16) & 0x7F);
+ rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
+ tjunc = ((msrl >> 16) & 0x7F);
+ if(tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received.
+ tnow = tjunc - tabs;
+ dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
+ v->check_temp = tnow;
+ }
+ return;
+ }
+
+ // AMD CPU
+ if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0)
+ {
+ pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr);
+ amd_raw_temp = ((rtcr >> 21) & 0x7FF);
+ v->check_temp = (int)(amd_raw_temp / 8);
+ dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
+ }
+
+
+}
+
+void print_cpu_line(float dram_freq, float fsb_freq, int ram_type)
+{
+ int cur_col = COL_SPEC;
+
+ cprint(LINE_CPU, cur_col, "RAM: ");
+ cur_col += 5;
+ dprint(LINE_CPU, cur_col, dram_freq, 4, 1);
+ cur_col += 4;
+ cprint(LINE_CPU, cur_col, "MHz (");
+ cur_col += 5;
+
+ switch(ram_type)
+ {
+ default:
+ case 1:
+ cprint(LINE_CPU, cur_col, "DDR-");
+ cur_col += 4;
+ break;
+ case 2:
+ cprint(LINE_CPU, cur_col, "DDR2-");
+ cur_col += 5;
+ break;
+ case 3:
+ cprint(LINE_CPU, cur_col, "DDR3-");
+ cur_col += 5;
+ break;
+ }
+
+ if(dram_freq < 500)
+ {
+ dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0);
+ cur_col += 3;
+ } else {
+ dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0);
+ cur_col += 4;
+ }
+ cprint(LINE_CPU, cur_col, ")");
+ cur_col++;
+
+ if(fsb_freq > 10)
+ {
+ cprint(LINE_CPU, cur_col, " - BCLK: ");
+ cur_col += 9;
+
+ dprint(LINE_CPU, cur_col, fsb_freq, 3, 0);
+ }
+
+}
-void print_timings_info(float cas, int rcd, int rp, int ras) {
+void print_ram_line(float cas, int rcd, int rp, int ras, int chan)
+{
+ int cur_col = COL_SPEC;
- /* Now, we could print some additionnals timings infos) */
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
+ cprint(LINE_RAM, cur_col, "Timings: CAS ");
+ cur_col += 13;
// CAS Latency (tCAS)
if (cas == 1.5) {
- cprint(LINE_CPU+6, col2, "1.5"); col2 += 3;
+ cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3;
} else if (cas == 2.5) {
- cprint(LINE_CPU+6, col2, "2.5"); col2 += 3;
+ cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3;
} else if (cas < 10) {
- dprint(LINE_CPU+6, col2, cas, 1, 0); col2 += 1;
+ dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1;
} else {
- dprint(LINE_CPU+6, col2, cas, 2, 0); col2 += 2;
+ dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2;
}
- cprint(LINE_CPU+6, col2, "-"); col2 += 1;
+ cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS-To-CAS (tRCD)
if (rcd < 10) {
- dprint(LINE_CPU+6, col2, rcd, 1, 0);
- col2 += 1;
+ dprint(LINE_RAM, cur_col, rcd, 1, 0);
+ cur_col += 1;
} else {
- dprint(LINE_CPU+6, col2, rcd, 2, 0);
- col2 += 2;
+ dprint(LINE_RAM, cur_col, rcd, 2, 0);
+ cur_col += 2;
}
- cprint(LINE_CPU+6, col2, "-"); col2 += 1;
+ cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS Precharge (tRP)
if (rp < 10) {
- dprint(LINE_CPU+6, col2, rp, 1, 0);
- col2 += 1;
+ dprint(LINE_RAM, cur_col, rp, 1, 0);
+ cur_col += 1;
} else {
- dprint(LINE_CPU+6, col2, rp, 2, 0);
- col2 += 2;
+ dprint(LINE_RAM, cur_col, rp, 2, 0);
+ cur_col += 2;
}
- cprint(LINE_CPU+6, col2, "-"); col2 += 1;
+ cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
// RAS Active to precharge (tRAS)
if (ras < 10) {
- dprint(LINE_CPU+6, col2, ras, 1, 0);
- col2 += 2;
+ dprint(LINE_RAM, cur_col, ras, 1, 0);
+ cur_col += 1;
} else {
- dprint(LINE_CPU+6, col2, ras, 2, 0);
- col2 += 3;
+ dprint(LINE_RAM, cur_col, ras, 2, 0);
+ cur_col += 2;
}
-
-}
-
-void print_fsb_info(float val, const char *text_fsb, const char *text_ddr) {
-
- int i;
-
- cprint(LINE_CPU+6, col2, "Settings: ");
- col2 += 10;
- cprint(LINE_CPU+6, col2, text_fsb);
- col2 += 6;
- dprint(LINE_CPU+6, col2, val ,3 ,0);
- col2 += 3;
- cprint(LINE_CPU+6, col2 +1, "MHz (");
- col2 += 6;
-
- cprint(LINE_CPU+6, col2, text_ddr);
- for(i = 0; text_ddr[i] != '\0'; i++) { col2++; }
-
- if(val < 500) {
- dprint(LINE_CPU+6, col2, val*2 ,3 ,0);
- col2 += 3;
- } else {
- dprint(LINE_CPU+6, col2, val*2 ,4 ,0);
- col2 += 4;
+
+
+ switch(chan)
+ {
+ case 0:
+ break;
+ case 1:
+ cprint(LINE_RAM, cur_col, " @ 64-bit Mode");
+ break;
+ case 2:
+ cprint(LINE_RAM, cur_col, " @ 128-bit Mode");
+ break;
+ case 3:
+ cprint(LINE_RAM, cur_col, " @ 192-bit Mode");
+ break;
+ case 4:
+ cprint(LINE_RAM, cur_col, " @ 256-bit Mode");
+ break;
}
- cprint(LINE_CPU+6, col2, ")");
- col2 += 1;
}
-
-
static void poll_fsb_nothing(void)
{
-/* Code to run for no specific fsb detection */
+
+ char *name;
+
+ /* Print the controller name */
+ name = controllers[ctrl.index].name;
+ cprint(LINE_CPU, COL_SPEC, "Chipset: ");
+ cprint(LINE_CPU, COL_SPEC+9, name);
return;
}
static void poll_timings_nothing(void)
{
-/* Code to run for no specific timings detection */
+ char *ram_type;
+
+ /* Print the controller name */
+ ram_type = controllers[ctrl.index].ram_type;
+ cprint(LINE_RAM, COL_SPEC, "RAM Type: ");
+ cprint(LINE_RAM, COL_SPEC+10, ram_type);
return;
}
-static void poll_fsb_failsafe(void)
-{
-/* Code to run for no specific fsb detection */
- cprint(LINE_CPU+5, 0, "Chipset/IMC : ***FAIL SAFE***FAIL SAFE***FAIL SAFE***FAIL SAFE***FAIL SAFE***");
- cprint(LINE_CPU+6, 0, "*** Memtest86+ is running in fail safe mode. Same reliability, less details ***");
- return;
-}
static void setup_nothing(void)
{
ctrl.cap = ECC_NONE;
@@ -199,18 +269,14 @@ static void poll_nothing(void)
static void setup_wmr(void)
{
-
- // Activate MMR I/O
ulong dev0;
- ctrl.cap = ECC_CORRECT;
-
+
+ // Activate MMR I/O
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
if (!(dev0 & 0x1)) {
pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
}
- ctrl.mode = ECC_NONE;
-
}
@@ -261,7 +327,6 @@ static void setup_nhm32(void)
ctrl.mode = ECC_NONE;
/* First, locate the PCI bus where the MCH is located */
-
for(i = 0; i < sizeof(possible_nhm_bus); i++) {
pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
@@ -270,7 +335,7 @@ static void setup_nhm32(void)
if(vid == 0x8086 && did >= 0x2C00) {
nhm_bus = possible_nhm_bus[i];
}
-}
+ }
/* Now, we have the last IMC bus number in nhm_bus */
/* Check for ECC & Scrub */
@@ -287,7 +352,6 @@ static void setup_nhm32(void)
static void setup_amd64(void)
{
-
static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL };
unsigned long nbxcfg;
unsigned int mcgsrl;
@@ -301,8 +365,7 @@ static void setup_amd64(void)
/* Check First if ECC DRAM Modules are used */
pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
+ if (cpu_id.vers.bits.extendedModel >= 4) {
/* NEW K8 0Fh Family 90 nm */
if ((dramcl >> 19)&1){
@@ -350,24 +413,24 @@ static void setup_k10(void)
unsigned long dramcl;
ulong msr_low, msr_high;
- /* All AMD64 support Chipkill */
+ // All AMD64 support Chipkill */
ctrl.cap = ECC_CHIPKILL;
- /* Check First if ECC DRAM Modules are used */
+ // 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 */
+ // 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 */
+ // Enable NB ECC Logging by MSR Write */
rdmsr(0x017B, mcgsrl, mcgsth);
wrmsr(0x017B, 0x10, mcgsth);
- /* Clear any previous error */
+ // Clear any previous error */
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
@@ -378,6 +441,19 @@ static void setup_k10(void)
}
+static void setup_apu(void)
+{
+
+ ulong msr_low, msr_high;
+
+ /* Enable ECS */
+ rdmsr(0xC001001F, msr_low, msr_high);
+ wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
+ rdmsr(0xC001001F, msr_low, msr_high);
+
+}
+
+/*
static void poll_amd64(void)
{
@@ -389,42 +465,43 @@ static void poll_amd64(void)
pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) {
- /* Find out about the first correctable error */
- /* Syndrome code -> bits use a complex matrix. Will add this later */
- /* Read the error location */
+ // Find out about the first correctable error
+ // Syndrome code -> bits use a complex matrix. Will add this later
+ // Read the error location
pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
- /* Read the syndrome */
+ // Read the syndrome
celog_syndrome = (mcanb >> 15)&0xFF;
- /* Parse the error location */
+ // Parse the error location
page = (mcanb_add >> 12);
offset = (mcanb_add >> 3) & 0xFFF;
- /* Report the error */
+ // Report the error
print_ecc_err(page, offset, 1, celog_syndrome, 0);
- /* Clear the error registers */
+ // Clear the error registers
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
}
if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) {
- /* Found out about the first uncorrectable error */
- /* Read the error location */
+ // Found out about the first uncorrectable error
+ // Read the error location
pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
- /* Parse the error location */
+ // Parse the error location
page = (mcanb_add >> 12);
offset = (mcanb_add >> 3) & 0xFFF;
- /* Report the error */
+ // Report the error
print_ecc_err(page, offset, 0, 0, 0);
- /* Clear the error registers */
+ // Clear the error registers
pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF );
}
}
+*/
static void setup_amd751(void)
{
@@ -436,6 +513,7 @@ static void setup_amd751(void)
ctrl.mode = (dram_status & (1 << 2))?ECC_CORRECT: ECC_NONE;
}
+/*
static void poll_amd751(void)
{
unsigned long ecc_status;
@@ -445,34 +523,34 @@ static void poll_amd751(void)
int bits;
int i;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status);
if (ecc_status & (3 << 8)) {
for(i = 0; i < 6; i++) {
if (!(ecc_status & (1 << i))) {
continue;
}
- /* Find the bank the error occured on */
+ // Find the bank the error occured on
bank_addr = 0x40 + (i << 1);
- /* Now get the information on the erroring bank */
+ // Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (bank_info & 0xFF80) << 4;
bits = (((ecc_status >> 8) &3) == 2)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, 0, 0);
}
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0);
}
}
-/* Still waiting for the CORRECT intel datasheet
+// Still waiting for the CORRECT intel datasheet
static void setup_i85x(void)
{
unsigned long drc;
@@ -495,6 +573,7 @@ static void setup_amd76x(void)
ctrl.mode = ddim[(ecc_mode_status >> 10)&3];
}
+/*
static void poll_amd76x(void)
{
unsigned long ecc_mode_status;
@@ -502,43 +581,44 @@ static void poll_amd76x(void)
unsigned long bank_info;
unsigned long page;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
- /* Multibit error */
+ // Multibit error
if (ecc_mode_status & (1 << 9)) {
- /* Find the bank the error occured on */
+ // Find the bank the error occured on
bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2);
- /* Now get the information on the erroring bank */
+ // Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (bank_info & 0xFF800000) >> 12;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 1, 0, 0);
}
- /* Singlebit error */
+ // Singlebit error
if (ecc_mode_status & (1 << 8)) {
- /* Find the bank the error occured on */
+ // Find the bank the error occured on
bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2);
- /* Now get the information on the erroring bank */
+ // Now get the information on the erroring bank
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (bank_info & 0xFF800000) >> 12;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 0, 0, 0);
}
- /* Clear the error status */
+ // Clear the error status
if (ecc_mode_status & (3 << 8)) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status);
}
}
+*/
static void setup_cnb20(void)
{
@@ -658,8 +738,10 @@ static void setup_iE7520(void)
/* Clear any prexisting error reports */
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747);
+
}
+/*
static void poll_iE7xxx(void)
{
unsigned long ferr;
@@ -669,50 +751,51 @@ static void poll_iE7xxx(void)
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
if (ferr & 1) {
- /* Find out about the first correctable error */
+ // Find out about the first correctable error
unsigned long celog_add;
unsigned long celog_syndrome;
unsigned long page;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
- /* Read the syndrome */
+ // Read the syndrome
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome);
- /* Parse the error location */
+ // Parse the error location
page = (celog_add & 0x0FFFFFC0) >> 6;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 1, celog_syndrome, 0);
- /* Clear Bit */
+ // Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
if (ferr & 2) {
- /* Found out about the first uncorrectable error */
+ // Found out about the first uncorrectable error
unsigned long uccelog_add;
unsigned long page;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
- /* Parse the error location */
+ // Parse the error location
page = (uccelog_add & 0x0FFFFFC0) >> 6;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 0, 0, 0);
- /* Clear Bit */
+ // Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
}
- /* Check if DRAM_NERR contains data */
+ // Check if DRAM_NERR contains data
if (nerr & 3) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
}
}
+*/
static void setup_i440gx(void)
{
@@ -725,19 +808,20 @@ static void setup_i440gx(void)
ctrl.mode = ddim[(nbxcfg >> 7)&3];
}
+/*
static void poll_i440gx(void)
{
unsigned long errsts;
unsigned long page;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts);
if (errsts & 0x11) {
unsigned long eap;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFF000) >> 12;
bits = 0;
if (eap &3) {
@@ -745,16 +829,19 @@ static void poll_i440gx(void)
}
if (bits) {
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, 0, 0);
}
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3);
}
}
+*/
+
+
static void setup_i840(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
@@ -766,6 +853,7 @@ static void setup_i840(void)
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
+/*
static void poll_i840(void)
{
unsigned long errsts;
@@ -773,29 +861,32 @@ static void poll_i840(void)
unsigned long syndrome;
int channel;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFF800) >> 11;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
+*/
+
+
static void setup_i875(void)
{
@@ -883,8 +974,27 @@ static void setup_p35(void)
ctrl.mode = ECC_NONE;
+ /*
+ ulong toto;
+ pci_conf_write(0, 31, 3, 0x40, 1, 0x1);
+ pci_conf_read(0, 31, 3, 0x0, 4, &toto);
+ hprint(11,0,toto);
+ pci_conf_read(0, 31, 3, 0x10, 4, &toto);
+ hprint(11,10,toto) ;
+ pci_conf_read(0, 31, 3, 0x20, 4, &toto);
+ hprint(11,20,toto) ;
+ pci_conf_read(0, 28, 0, 0x0, 4, &toto);
+ hprint(11,30,toto);
+ pci_conf_read(0, 31, 0, 0x0, 4, &toto);
+ hprint(11,40,toto) ;
+ pci_conf_read(0, 31, 1, 0x0, 4, &toto);
+ hprint(11,50,toto) ;
+ pci_conf_read(0, 31, 2, 0x0, 4, &toto);
+ hprint(11,60,toto) ;
+ */
}
+/*
static void poll_i875(void)
{
unsigned long errsts;
@@ -893,117 +1003,125 @@ static void poll_i875(void)
unsigned long syndrome;
int channel;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 0x81) {
unsigned long eap;
unsigned long derrsyn;
- /* Read the error location, syndrome and channel */
+ // Read the error location, syndrome and channel
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFF000) >> 12;
syndrome = derrsyn;
channel = des & 1;
bits = (errsts & 0x80)?0:1;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits, syndrome, channel);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
}
}
+*/
static void setup_i845(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
unsigned long drc;
- /* Fill in the correct memory capabilites */
+ // Fill in the correct memory capabilites
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(drc >> 20)&3];
}
+/*
static void poll_i845(void)
{
unsigned long errsts;
unsigned long page, offset;
unsigned long syndrome;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrsyn;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn);
- /* Parse the error location and error type */
+ // Parse the error location and error type
offset = (eap & 0xFE) << 4;
page = (eap & 0x3FFFFFFE) >> 8;
syndrome = derrsyn;
bits = ((errsts & 3) == 1)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, offset, bits==1?1:0, syndrome, 0);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
+*/
+
+
static void setup_i820(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
unsigned long mchcfg;
- /* Fill in the correct memory capabilites */
+ // Fill in the correct memory capabilites
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
+/*
static void poll_i820(void)
{
unsigned long errsts;
unsigned long page;
unsigned long syndrome;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFF000) >> 4;
syndrome = eap & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, 0);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
}
}
+*/
static void setup_i850(void)
{
static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
unsigned long mchcfg;
- /* Fill in the correct memory capabilites */
+ // Fill in the correct memory capabilites
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
}
+/*
static void poll_i850(void)
{
unsigned long errsts;
@@ -1011,28 +1129,29 @@ static void poll_i850(void)
unsigned long syndrome;
int channel;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFF800) >> 11;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
}
+*/
static void setup_i860(void)
{
@@ -1040,16 +1159,17 @@ static void setup_i860(void)
unsigned long mchcfg;
unsigned long errsts;
- /* Fill in the correct memory capabilites */
+ // Fill in the correct memory capabilites
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
ctrl.cap = ECC_CORRECT;
ctrl.mode = ddim[(mchcfg >> 7)&3];
- /* Clear any prexisting error reports */
+ // Clear any prexisting error reports
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
+/*
static void poll_i860(void)
{
unsigned long errsts;
@@ -1057,29 +1177,30 @@ static void poll_i860(void)
unsigned char syndrome;
int channel;
int bits;
- /* Read the error status */
+ // Read the error status
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
if (errsts & 3) {
unsigned long eap;
unsigned long derrctl_sts;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
- /* Parse the error location and error type */
+ // Parse the error location and error type
page = (eap & 0xFFFFFE00) >> 9;
channel = eap & 1;
syndrome = derrctl_sts & 0xFF;
bits = ((errsts & 3) == 1)?1:2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
}
+
static void poll_iE7221(void)
{
unsigned long errsts;
@@ -1097,11 +1218,11 @@ static void poll_iE7221(void)
unsigned long eap, offset;
unsigned long derrctl_sts;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts);
- /* Parse the error location and error type */
+ // Parse the error location and error type
channel = eap & 1;
eap = eap & 0xFFFFFF80;
page = eap >> 12;
@@ -1109,10 +1230,10 @@ static void poll_iE7221(void)
syndrome = derrctl_sts & 0xFF;
bits = errocc & 1;
- /* Report the error */
+ // Report the error
print_ecc_err(page, offset, bits, syndrome, channel);
- /* Clear the error status */
+ // Clear the error status
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
}
@@ -1123,6 +1244,7 @@ static void poll_iE7221(void)
}
}
+
static void poll_iE7520(void)
{
unsigned long ferr;
@@ -1132,54 +1254,54 @@ static void poll_iE7520(void)
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr);
if (ferr & 0x0101) {
- /* Find out about the first correctable error */
+ // Find out about the first correctable error
unsigned long celog_add;
unsigned long celog_syndrome;
unsigned long page;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add);
- /* Read the syndrome */
+ // Read the syndrome
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome);
- /* Parse the error location */
+ // Parse the error location
page = (celog_add & 0x7FFFFFFC) >> 2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 1, celog_syndrome, 0);
- /* Clear Bit */
+ // Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101);
}
if (ferr & 0x4646) {
- /* Found out about the first uncorrectable error */
+ // Found out about the first uncorrectable error
unsigned long uccelog_add;
unsigned long page;
- /* Read the error location */
+ // Read the error location
pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add);
- /* Parse the error location */
+ // Parse the error location
page = (uccelog_add & 0x7FFFFFFC) >> 2;
- /* Report the error */
+ // Report the error
print_ecc_err(page, 0, 0, 0, 0);
- /* Clear Bit */
+ // Clear Bit
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646);
}
- /* Check if DRAM_NERR contains data */
+ // Check if DRAM_NERR contains data
if (nerr & 0x4747) {
pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747);
}
}
+*/
-
-/* ------------------ Here the code for FSB detection ------------------ */
+/* ----------------- Here's the code for FSB detection ----------------- */
/* --------------------------------------------------------------------- */
static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5};
@@ -1188,15 +1310,25 @@ static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 1
static float getP4PMmultiplier(void)
{
- unsigned int msr_lo, msr_hi;
+ //unsigned int msr_lo, msr_hi;
+ int msr_lo, msr_hi;
float coef;
- /* Find multiplier (by MSR) */
- if (cpu_id.type == 6) {
- if((cpu_id.feature_flag >> 7) & 1) {
+
+ /* Find multiplier (by MSR) */
+ if (cpu_id.vers.bits.family == 6)
+ {
+ if(cpu_id.fid.bits.eist & 1)
+ {
rdmsr(0x198, msr_lo, msr_hi);
- coef = ((msr_lo >> 8) & 0x1F);
- if ((msr_lo >> 14) & 0x1) { coef = coef + 0.5f; }
+ coef = ((msr_lo) >> 8) & 0x1F;
+ if ((msr_lo >> 14) & 0x1) { coef += 0.5f; }
+ // Atom Fix
+ if(coef == 6)
+ {
+ coef = ((msr_hi) >> 8) & 0x1F;
+ if ((msr_hi >> 14) & 0x1) { coef += 0.5f; }
+ }
} else {
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 22) & 0x1F;
@@ -1204,7 +1336,7 @@ static float getP4PMmultiplier(void)
}
else
{
- if (cpu_id.model < 2)
+ if (cpu_id.vers.bits.model < 2)
{
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 8) & 0xF;
@@ -1216,6 +1348,7 @@ static float getP4PMmultiplier(void)
coef = (msr_lo >> 24) & 0x1F;
}
}
+
return coef;
}
@@ -1236,75 +1369,51 @@ static float getNHMmultiplier(void)
return coef;
}
-
static float getSNBmultiplier(void)
{
unsigned int msr_lo, msr_hi;
float coef;
- rdmsr(0x198, msr_lo, msr_hi);
- coef = (msr_lo >> 8) & 0xFF;
- if(coef < 4)
- {
- rdmsr(0xCE, msr_lo, msr_hi);
- coef = (msr_lo >> 16) & 0xFF;
- }
-
-
+ rdmsr(0xCE, msr_lo, msr_hi);
+ coef = (msr_lo >> 8) & 0xFF;
return coef;
}
-
-void getIntelPNS(void)
+static void poll_fsb_ct(void)
{
- int i,j;
- long psn_eax, psn_ebx, psn_ecx, psn_edx;
- long char_hex;
- long ocpuid = 0x80000002;
-
- for(j = 0; j < 4; j++)
- {
-
- asm __volatile__(
- "pushl %%ebx\n\t" \
- "cpuid\n\t" \
- "movl %%ebx, %1\n\t" \
- "popl %%ebx\n\t" \
- : "=a" (psn_eax), "=r" (psn_ebx), "=c" (psn_ecx), "=d" (psn_edx)
- : "a" (ocpuid)
- : "cc"
- );
-
+ unsigned long mcr, mdr;
+ double dramratio, dramclock, fsb;
+ float coef = getP4PMmultiplier();
- for(i = 0; i < 4; i++)
- {
- char_hex = (psn_eax >> (i*8)) & 0xff;
- cprint(LINE_CPU+5, col + i, convert_hex_to_char(char_hex));
+ /* Build the MCR Message*/
+ mcr = (0x10 << 24); // 10h = Read - 11h = Write
+ mcr += (0x01 << 16); // DRAM Registers located on port 01h
+ mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h
+ mcr &= 0xFFFFFFF0; // bit 03:00 RSVD
- char_hex = (psn_ebx >> (i*8)) & 0xff;
- cprint(LINE_CPU+5, col + i + 4, convert_hex_to_char(char_hex));
-
- if(psn_ecx != 0x20202020)
- {
- char_hex = (psn_ecx >> (i*8)) & 0xff;
- cprint(LINE_CPU+5, col + i + 8, convert_hex_to_char(char_hex));
-
- char_hex = (psn_edx >> (i*8)) & 0xff;
- cprint(LINE_CPU+5, col + i + 12, convert_hex_to_char(char_hex));
- }
- else
- {
- char_hex = (psn_edx >> (i*8)) & 0xff;
- cprint(LINE_CPU+5, col + i + 8, convert_hex_to_char(char_hex));
- }
- }
- (psn_ecx != 0x20202020)?(col += 16):(col +=12);
- if(psn_edx == 0x20202020) { col -= 4; }
- ocpuid++;
- }
+ /* Send Message to GMCH */
+ pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
+
+ /* Read Answer from Sideband bus */
+ pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
- col -= 16;
+ /* Get RAM ratio */
+ switch (mdr & 0x3) {
+ default:
+ case 0: dramratio = 3.0f; break;
+ case 1: dramratio = 4.0f; break;
+ case 2: dramratio = 5.0f; break;
+ case 3: dramratio = 6.0f; break;
+ }
+
+ // Compute FSB & RAM Frequency
+ fsb = ((extclock / 1000) / coef);
+ dramclock = fsb * dramratio;
+
+ // Print'em all. Whoa !
+ print_cpu_line(dramclock, fsb, 3);
+
}
static void poll_fsb_amd64(void) {
@@ -1315,12 +1424,16 @@ static void poll_fsb_amd64(void) {
unsigned long dramchr;
float clockratio;
double dramclock;
+ unsigned int dummy[3];
+ int ram_type;
float coef = 10;
+ cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]);
+
/* First, got the FID by MSR */
/* First look if Cool 'n Quiet is supported to choose the best msr */
- if (((cpu_id.pwrcap >> 1) & 1) == 1) {
+ if (((dummy[3] >> 1) & 1) == 1) {
rdmsr(0xc0010042, mcgsrl, mcgsth);
fid = (mcgsrl & 0x3F);
} else {
@@ -1335,12 +1448,12 @@ static void poll_fsb_amd64(void) {
if (fid & 1) { coef = coef + 0.5; }
/* Next, we need the clock ratio */
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
+ if (cpu_id.vers.bits.extendedModel >= 4) {
/* K8 0FH */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr & 0x7);
clockratio = coef;
+ ram_type = 2;
switch (temp2) {
case 0x0:
@@ -1361,6 +1474,7 @@ static void poll_fsb_amd64(void) {
/* OLD K8 */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr >> 20) & 0x7;
+ ram_type = 1;
clockratio = coef;
switch (temp2) {
@@ -1386,10 +1500,10 @@ static void poll_fsb_amd64(void) {
}
/* Compute the final DRAM Clock */
- dramclock = (extclock /1000) / clockratio;
+ dramclock = (extclock / 1000) / clockratio;
/* ...and print */
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ print_cpu_line(dramclock, (extclock / 1000 / coef), ram_type);
}
@@ -1401,30 +1515,9 @@ static void poll_fsb_k10(void) {
unsigned long dramchr;
unsigned long mainPllId;
double dramclock;
- unsigned long pns_low;
- unsigned long pns_high;
- unsigned long msr_psn;
-
-
- /* If ECC not enabled : display CPU name as IMC */
- if(ctrl.mode == ECC_NONE)
- {
- cprint(LINE_CPU+5, 0, "IMC : ");
- for(msr_psn = 0; msr_psn < 5; msr_psn++)
- {
- rdmsr(0xC0010030+msr_psn, pns_low, pns_high);
- cprint(LINE_CPU+5, 6+(msr_psn*8), convert_hex_to_char(pns_low & 0xff));
- cprint(LINE_CPU+5, 7+(msr_psn*8), convert_hex_to_char((pns_low >> 8) & 0xff));
- cprint(LINE_CPU+5, 8+(msr_psn*8), convert_hex_to_char((pns_low >> 16) & 0xff));
- cprint(LINE_CPU+5, 9+(msr_psn*8), convert_hex_to_char((pns_low >> 24) & 0xff));
- cprint(LINE_CPU+5, 10+(msr_psn*8), convert_hex_to_char(pns_high & 0xff));
- cprint(LINE_CPU+5, 11+(msr_psn*8), convert_hex_to_char((pns_high >> 8) & 0xff));
- cprint(LINE_CPU+5, 12+(msr_psn*8), convert_hex_to_char((pns_high >> 16) & 0xff));
- cprint(LINE_CPU+5, 13+(msr_psn*8), convert_hex_to_char((pns_high >> 24) & 0xff));
- }
- cprint(LINE_CPU+5, 41, "(ECC : Disabled)");
- }
-
+ ulong offset = 0;
+ int ram_type = 2;
+
/* First, we need the clock ratio */
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
temp2 = (dramchr & 0x7);
@@ -1437,16 +1530,14 @@ static void poll_fsb_k10(void) {
default: temp2 += 3;
}
-
/* Compute the final DRAM Clock */
- if (((cpu_id.ext >> 20) & 0xFF) == 1)
+ if (((cpu_id.vers.bits.extendedModel >> 4) & 0xFF) == 1) {
dramclock = ((temp2 * 200) / 3.0) + 0.25;
- else {
+ } else {
unsigned long target;
unsigned long dx;
unsigned divisor;
-
target = temp2 * 400;
/* Get the FID by MSR */
@@ -1470,75 +1561,262 @@ static void poll_fsb_k10(void) {
if ( (dx / divisor) <= target )
break;
+
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ // If Channel A not enabled, switch to channel B
+ if(((dramchr>>14) & 0x1))
+ {
+ offset = 0x100;
+ pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr);
+ }
+
+ //DDR2 or DDR3
+ if ((dramchr >> 8)&1) {
+ ram_type = 3;
+ } else {
+ ram_type = 2;;
+ }
+
dramclock = ((dx / divisor) / 6.0) + 0.25;
-/*
- * dramclock = ((((dx * extclock) / divisor) / (mainPllId+8)) / 600000.0) + 0.25;
- */
}
/* ...and print */
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ print_cpu_line(dramclock, 0, ram_type);
}
-static void poll_fsb_k14(void) {
+static void poll_fsb_k12(void) {
unsigned long temp2;
unsigned long dramchr;
- double dramclock;
- unsigned long pns_low;
- unsigned long pns_high;
- unsigned long msr_psn;
+ double dramratio, dramclock, fsb, did;
+ unsigned int mcgsrl,mcgsth, fid, did_raw;
+
+ // Get current FID & DID
+ rdmsr(0xc0010071, mcgsrl, mcgsth);
+ did_raw = mcgsrl & 0xF;
+ fid = (mcgsrl >> 4) & 0xF;
+
+ switch(did_raw)
+ {
+ default:
+ case 0x0:
+ did = 1.0f;
+ break;
+ case 0x1:
+ did = 1.5f;
+ break;
+ case 0x2:
+ did = 2.0f;
+ break;
+ case 0x3:
+ did = 3.0f;
+ break;
+ case 0x4:
+ did = 4.0f;
+ break;
+ case 0x5:
+ did = 6.0f;
+ break;
+ case 0x6:
+ did = 8.0f;
+ break;
+ case 0x7:
+ did = 12.0f;
+ break;
+ case 0x8:
+ did = 16.0f;
+ break;
+ }
+
+ fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did));
+
+ /* Finaly, we need the clock ratio */
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ if(((dramchr >> 14) & 0x1) == 1)
+ {
+ pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
+ }
+
+ temp2 = (dramchr & 0x1F);
+ switch (temp2) {
+ default:
+ case 0x06:
+ dramratio = 4.0f;
+ break;
+ case 0x0A:
+ dramratio = 16.0f / 3.0f;
+ break;
+ case 0x0E:
+ dramratio = 20.0f / 3.0f;
+ break;
+ case 0x12:
+ dramratio = 8.0f;
+ break;
+ case 0x16:
+ dramratio = 28.0f / 3.0f;
+ break;
+ }
+
+ dramclock = fsb * dramratio;
+
+ /* print */
+ print_cpu_line(dramclock, fsb, 3);
- /* If ECC not enabled : display CPU name as IMC */
- if(ctrl.mode == ECC_NONE)
- {
- cprint(LINE_CPU+5, 0, "IMC : ");
- for(msr_psn = 0; msr_psn < 5; msr_psn++)
- {
- rdmsr(0xC0010030+msr_psn, pns_low, pns_high);
- cprint(LINE_CPU+5, 6+(msr_psn*8), convert_hex_to_char(pns_low & 0xff));
- cprint(LINE_CPU+5, 7+(msr_psn*8), convert_hex_to_char((pns_low >> 8) & 0xff));
- cprint(LINE_CPU+5, 8+(msr_psn*8), convert_hex_to_char((pns_low >> 16) & 0xff));
- cprint(LINE_CPU+5, 9+(msr_psn*8), convert_hex_to_char((pns_low >> 24) & 0xff));
- cprint(LINE_CPU+5, 10+(msr_psn*8), convert_hex_to_char(pns_high & 0xff));
- cprint(LINE_CPU+5, 11+(msr_psn*8), convert_hex_to_char((pns_high >> 8) & 0xff));
- cprint(LINE_CPU+5, 12+(msr_psn*8), convert_hex_to_char((pns_high >> 16) & 0xff));
- cprint(LINE_CPU+5, 13+(msr_psn*8), convert_hex_to_char((pns_high >> 24) & 0xff));
- }
- cprint(LINE_CPU+5, 41, "(ECC : Disabled)");
- }
+}
- /* First, we need the clock ratio */
- pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
- temp2 = (dramchr & 0x1F);
+static void poll_fsb_k16(void)
+{
- switch (temp2) {
- default:
- case 6:
- dramclock = 400;
- break;
- case 10:
- dramclock = 533;
- break;
- case 14:
- dramclock = 667;
- break;
- }
+ unsigned long dramchr;
+ double dramratio, dramclock, fsb;
+
+ // FIXME: Unable to find a real way to detect multiplier.
+ fsb = 100.0f;
+
+ /* Clock ratio */
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ switch (dramchr & 0x1F) {
+ default:
+ case 0x04: /* 333 */
+ dramratio = 10.0f / 3.0f;
+ break;
+ case 0x06: /* 400 */
+ dramratio = 4.0f;
+ break;
+ case 0x0A: /* 533 */
+ dramratio = 16.0f / 3.0f;
+ break;
+ case 0x0E: /* 667 */
+ dramratio = 20.0f / 3.0f;
+ break;
+ case 0x12: /* 800 */
+ dramratio = 8.0f;
+ break;
+ case 0x16: /* 933 */
+ dramratio = 28.0f / 3.0f;
+ break;
+ case 0x19: /* 1050 */
+ dramratio = 21.0f / 2.0f;
+ break;
+ case 0x1A: /* 1066 */
+ dramratio = 32.0f / 3.0f;
+ break;
+ }
+
+ dramclock = fsb * dramratio;
+
+ /* print */
+ print_cpu_line(dramclock, fsb, 3);
+
+}
+
+static void poll_fsb_k15(void) {
+
+ unsigned long temp2;
+ unsigned long dramchr;
+ double dramratio, dramclock, fsb;
+ unsigned int mcgsrl,mcgsth, fid, did;
+
+ // Get current FID & DID
+ rdmsr(0xc0010071, mcgsrl, mcgsth);
+ fid = mcgsrl & 0x3F;
+ did = (mcgsrl >> 6) & 0x7;
+
+ fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2);
+
+ /* Finaly, we need the clock ratio */
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ if(((dramchr >> 14) & 0x1) == 1)
+ {
+ pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
+ }
+
+ temp2 = (dramchr & 0x1F);
+
+ switch (temp2) {
+ case 0x04:
+ dramratio = 10.0f / 3.0f;
+ break;
+ default:
+ case 0x06:
+ dramratio = 4.0f;
+ break;
+ case 0x0A:
+ dramratio = 16.0f / 3.0f;
+ break;
+ case 0x0E:
+ dramratio = 20.0f / 3.0f;
+ break;
+ case 0x12:
+ dramratio = 8.0f;
+ break;
+ case 0x16:
+ dramratio = 28.0f / 3.0f;
+ break;
+ case 0x1A:
+ dramratio = 32.0f / 3.0f;
+ break;
+ case 0x1F:
+ dramratio = 36.0f / 3.0f;
+ break;
+ }
+
+ dramclock = fsb * dramratio;
+
+ /* print */
+ print_cpu_line(dramclock, fsb, 3);
+
+}
+static void poll_fsb_k14(void)
+{
+
+ unsigned long dramchr;
+ double dramratio, dramclock, fsb;
+ // FIXME: Unable to find a real way to detect multiplier.
+ fsb = 100.0f;
+
+ /* Clock ratio */
+ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+
+ switch (dramchr & 0x1F) {
+ default:
+ case 0x06:
+ dramratio = 4.0f;
+ break;
+ case 0x0A:
+ dramratio = 16.0f / 3.0f;
+ break;
+ case 0x0E:
+ dramratio = 20.0f / 3.0f;
+ break;
+ case 0x12:
+ dramratio = 8.0f;
+ break;
+ }
+
+ dramclock = fsb * dramratio;
+
/* print */
- print_fsb_info(dramclock, "RAM : ", "DDR-");
+ print_cpu_line(dramclock, fsb, 3);
}
+
static void poll_fsb_i925(void) {
double dramclock, dramratio, fsb;
unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
float coef = getP4PMmultiplier();
long *ptr;
+ int ddr_type;
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
@@ -1556,8 +1834,10 @@ static void poll_fsb_i925(void) {
if ((drc&3) != 2) {
// We are in DDR1 Mode
if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; }
+ ddr_type = 1;
} else {
// We are in DDR2 Mode
+ ddr_type = 2;
if ((mchcfg >> 2)&1) {
// We are in FSB1066 Mode
if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; }
@@ -1581,16 +1861,8 @@ static void poll_fsb_i925(void) {
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ print_cpu_line(dramclock, fsb, ddr_type);
}
@@ -1617,21 +1889,72 @@ static void poll_fsb_i945(void) {
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
+
dramclock = fsb * dramratio;
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ // Print
+ print_cpu_line(dramclock, fsb, 2);
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+}
+
+static void poll_fsb_i945gme(void) {
+
+ double dramclock, dramratio, fsb;
+ unsigned long mchcfg, dev0, fsb_mch;
+ float coef = getP4PMmultiplier();
+ long *ptr;
+
+ /* Find dramratio */
+ pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
+ dev0 &= 0xFFFFC000;
+ ptr=(long*)(dev0+0xC00);
+ mchcfg = *ptr & 0xFFFF;
+ dramratio = 1;
+
+ switch (mchcfg & 7) {
+ case 0: fsb_mch = 400; break;
+ default:
+ case 1: fsb_mch = 533; break;
+ case 2: fsb_mch = 667; break;
+ }
+
+
+ switch (fsb_mch) {
+ case 400:
+ switch ((mchcfg >> 4)&7) {
+ case 2: dramratio = 1.0f; break;
+ case 3: dramratio = 4.0f/3.0f; break;
+ case 4: dramratio = 5.0f/3.0f; break;
+ }
+ break;
+
+ default:
+ case 533:
+ switch ((mchcfg >> 4)&7) {
+ case 2: dramratio = 3.0f/4.0f; break;
+ case 3: dramratio = 1.0f; break;
+ case 4: dramratio = 5.0f/4.0f; break;
+ }
+ break;
+
+ case 667:
+ switch ((mchcfg >> 4)&7) {
+ case 2: dramratio = 3.0f/5.0f; break;
+ case 3: dramratio = 4.0f/5.0f; break;
+ case 4: dramratio = 1.0f; break;
+ }
+ break;
+ }
+
+ // Compute RAM Frequency
+ fsb = ((extclock / 1000) / coef);
+ dramclock = fsb * dramratio * 2;
+
+ print_cpu_line(dramclock, fsb, 2);
}
+
static void poll_fsb_i975(void) {
double dramclock, dramratio, fsb;
@@ -1681,23 +2004,13 @@ static void poll_fsb_i975(void) {
case 4: dramratio = 1.5; break;
}
break;
-}
-
+ }
// Compute RAM Frequency
fsb = ((extclock / 1000) / coef);
dramclock = fsb * dramratio;
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ print_cpu_line(dramclock, fsb, 2);
}
@@ -1740,7 +2053,7 @@ static void poll_fsb_i965(void) {
case 0: dramratio = 1.0; break;
case 1: dramratio = 5.0f/4.0f; break;
case 2: dramratio = 5.0f/3.0f; break;
- case 3: dramratio = 2.0; break;
+ case 3: dramratio = 2.0f; break;
case 4: dramratio = 8.0f/3.0f; break;
case 5: dramratio = 10.0f/3.0f; break;
}
@@ -1781,15 +2094,127 @@ static void poll_fsb_i965(void) {
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ print_cpu_line(dramclock, fsb, 2);
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+}
+
+static void poll_fsb_p35(void) {
+
+ double dramclock, dramratio, fsb;
+ unsigned long mchcfg, dev0, fsb_mch, Device_ID, Memory_Check, c0ckectrl, offset;
+ float coef = getP4PMmultiplier();
+ long *ptr;
+ int ram_type;
+
+ pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID);
+ Device_ID &= 0xFFFF;
+
+ /* Find dramratio */
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
+ dev0 &= 0xFFFFC000;
+
+ ptr = (long*)(dev0+0x260);
+ c0ckectrl = *ptr & 0xFFFFFFFF;
+
+
+ // If DIMM 0 not populated, check DIMM 1
+ ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400);
+
+ ptr=(long*)(dev0+0xC00);
+ mchcfg = *ptr & 0xFFFF;
+ dramratio = 1;
+
+ switch (mchcfg & 7) {
+ case 0: fsb_mch = 1066; break;
+ case 1: fsb_mch = 533; break;
+ default: case 2: fsb_mch = 800; break;
+ case 3: fsb_mch = 667; break;
+ case 4: fsb_mch = 1333; break;
+ case 6: fsb_mch = 1600; break;
+ }
+
+
+ switch (fsb_mch) {
+ case 533:
+ switch ((mchcfg >> 4)&7) {
+ case 1: dramratio = 2.0; break;
+ case 2: dramratio = 2.5; break;
+ case 3: dramratio = 3.0; break;
+ }
+ break;
+
+ default:
+ case 800:
+ switch ((mchcfg >> 4)&7) {
+ case 0: dramratio = 1.0; break;
+ case 1: dramratio = 5.0f/4.0f; break;
+ case 2: dramratio = 5.0f/3.0f; break;
+ case 3: dramratio = 2.0; break;
+ case 4: dramratio = 8.0f/3.0f; break;
+ case 5: dramratio = 10.0f/3.0f; break;
+ }
+ break;
+
+ case 1066:
+ switch ((mchcfg >> 4)&7) {
+ case 1: dramratio = 1.0f; break;
+ case 2: dramratio = 5.0f/4.0f; break;
+ case 3: dramratio = 3.0f/2.0f; break;
+ case 4: dramratio = 2.0f; break;
+ case 5: dramratio = 5.0f/2.0f; break;
+ }
+ break;
+
+ case 1333:
+ switch ((mchcfg >> 4)&7) {
+ case 2: dramratio = 1.0f; break;
+ case 3: dramratio = 6.0f/5.0f; break;
+ case 4: dramratio = 8.0f/5.0f; break;
+ case 5: dramratio = 2.0f; break;
+ }
+ break;
+
+ case 1600:
+ switch ((mchcfg >> 4)&7) {
+ case 3: dramratio = 1.0f; break;
+ case 4: dramratio = 4.0f/3.0f; break;
+ case 5: dramratio = 3.0f/2.0f; break;
+ case 6: dramratio = 2.0f; break;
+ }
+ break;
+
+ }
+
+ // On P45, check 1A8
+ if(Device_ID > 0x2E00 && imc_type != 8) {
+ ptr = (long*)(dev0+offset+0x1A8);
+ Memory_Check = *ptr & 0xFFFFFFFF;
+ Memory_Check >>= 2;
+ Memory_Check &= 1;
+ Memory_Check = !Memory_Check;
+ } else if (imc_type == 8) {
+ ptr = (long*)(dev0+offset+0x224);
+ Memory_Check = *ptr & 0xFFFFFFFF;
+ Memory_Check &= 1;
+ Memory_Check = !Memory_Check;
+ } else {
+ ptr = (long*)(dev0+offset+0x1E8);
+ Memory_Check = *ptr & 0xFFFFFFFF;
+ }
+
+ //Determine DDR-II or DDR-III
+ if (Memory_Check & 1) {
+ ram_type = 2;
+ } else {
+ ram_type = 3;
+ }
+
+ // Compute RAM Frequency
+ fsb = ((extclock / 1000) / coef);
+ dramclock = fsb * dramratio;
+
+ // Print DRAM Freq
+ print_cpu_line(dramclock, fsb, ram_type);
}
@@ -1856,15 +2281,7 @@ static void poll_fsb_im965(void) {
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ print_cpu_line(dramclock, fsb, 2);
}
@@ -1905,15 +2322,7 @@ static void poll_fsb_5400(void) {
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ print_cpu_line(dramclock, fsb, 2);
}
@@ -1946,16 +2355,8 @@ static void poll_fsb_nf4ie(void) {
fsb = ((extclock /1000) / coef);
dramclock = fsb * dramratio;
- /* Print DRAM Freq */
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* Print FSB */
- cprint(LINE_CPU+5, col, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ // Print DRAM Freq
+ print_cpu_line(dramclock, fsb, 2);
}
@@ -1989,38 +2390,45 @@ static void poll_fsb_i875(void) {
fsb = ((extclock /1000) / coef);
/* Print DRAM Freq */
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* Print FSB (only if ECC is not enabled) */
- if ( ctrl.mode == ECC_NONE ) {
- cprint(LINE_CPU+5, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
- }
+ print_cpu_line(dramclock, fsb, 2);
}
static void poll_fsb_p4(void) {
ulong fsb, idetect;
float coef = getP4PMmultiplier();
+ char *name;
+ int col,temp;
fsb = ((extclock /1000) / coef);
- /* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ FSB : ");
- col += 9;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
-
/* For synchro only chipsets */
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
- if (idetect == 0x2540 || idetect == 0x254C) {
- print_fsb_info(fsb, "RAM : ", "DDR");
+ if (idetect == 0x2540 || idetect == 0x254C)
+ {
+ print_cpu_line(fsb, fsb, 1);
+ } else {
+ /* Print the controller name */
+ col = COL_SPEC;
+ cprint(LINE_CPU, col, "Chipset: ");
+ col += 9;
+ /* Print the controller name */
+ name = controllers[ctrl.index].name;
+ cprint(LINE_CPU, col, name);
+ /* Now figure out how much I just printed */
+ temp = 20;
+ while(name[temp - 20] != '\0') {
+ col++;
+ temp++;
+ }
+
+ if(temp < 36){
+ cprint(LINE_CPU, col +1, "- FSB : ");
+ col += 9;
+ dprint(LINE_CPU, col, fsb, 3,0);
+ col += 3;
+ }
+
}
}
@@ -2029,7 +2437,7 @@ static void poll_fsb_i855(void) {
double dramclock, dramratio, fsb ;
unsigned int msr_lo, msr_hi;
- ulong mchcfg, centri, idetect;
+ ulong mchcfg, idetect;
int coef;
pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
@@ -2037,33 +2445,16 @@ static void poll_fsb_i855(void) {
/* Find multiplier (by MSR) */
/* Is it a Pentium M ? */
- if (cpu_id.type == 6) {
+ if (cpu_id.vers.bits.family == 6) {
rdmsr(0x2A, msr_lo, msr_hi);
coef = (msr_lo >> 22) & 0x1F;
-
- /* Is it an i855GM or PM ? */
- if (idetect == 0x3580) {
- cprint(LINE_CPU+5, col-1, "i855GM/GME ");
- col += 10;
- }
} else {
rdmsr(0x2C, msr_lo, msr_hi);
coef = (msr_lo >> 24) & 0x1F;
- cprint(LINE_CPU+5, col-1, "i852PM/GM ");
- col += 9;
}
fsb = ((extclock /1000) / coef);
- /* Print FSB */
- cprint(LINE_CPU+5, col, "/ FSB : "); col += 8;
- dprint(LINE_CPU+5, col, fsb, 3,0); col += 3;
- cprint(LINE_CPU+5, col +1, "MHz"); col += 4;
-
- /* Is it a Centrino platform or only an i855 platform ? */
- pci_conf_read( 2, 2, 0, 0x02, 2, &centri);
- if (centri == 0x1043) { cprint(LINE_CPU+5, col +1, "/ Centrino Mobile Platform"); }
- else { cprint(LINE_CPU+5, col +1, "/ Mobile Platform"); }
/* Compute DRAM Clock */
@@ -2088,7 +2479,7 @@ static void poll_fsb_i855(void) {
dramclock = fsb * dramratio;
/* ...and print */
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ print_cpu_line(dramclock, fsb, 1);
}
@@ -2099,6 +2490,8 @@ static void poll_fsb_amd32(void) {
unsigned long temp;
double dramclock;
double coef2;
+ int col;
+ char *name;
/* First, got the FID */
rdmsr(0x0c0010015, mcgsrl, mcgsth);
@@ -2112,8 +2505,27 @@ static void poll_fsb_amd32(void) {
/* Compute the final FSB Clock */
dramclock = (extclock /1000) / coef2;
- /* ...and print */
- print_fsb_info(dramclock, "FSB : ", "DDR");
+ /* Print the controller name */
+ col = COL_SPEC;
+ cprint(LINE_CPU, col, "Chipset: ");
+ col += 9;
+ /* Print the controller name */
+ name = controllers[ctrl.index].name;
+ cprint(LINE_CPU, col, name);
+ /* Now figure out how much I just printed */
+ temp = 20;
+ while(name[temp - 20] != '\0') {
+ col++;
+ temp++;
+ }
+
+ if(temp < 36){
+ cprint(LINE_CPU, col +1, "- FSB : ");
+ col += 9;
+ dprint(LINE_CPU, col, dramclock, 3,0);
+ col += 3;
+ }
+
}
@@ -2151,20 +2563,13 @@ static void poll_fsb_nf2(void) {
fsb = ((extclock /1000) / coef);
/* ...and print */
-
- cprint(LINE_CPU+5, col, "/ FSB : ");
- col += 8;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
-
- print_fsb_info(dramclock, "RAM : ", "DDR");
+ print_cpu_line(dramclock, fsb, 1);
}
static void poll_fsb_us15w(void) {
- double dramclock, dramratio, fsb, gfx;
+ double dramclock, dramratio, fsb;
unsigned long msr;
/* Find dramratio */
@@ -2181,7 +2586,8 @@ static void poll_fsb_us15w(void) {
} else {
fsb = 400;
}
-
+
+/*
switch (( msr >> 0 ) & 7) {
case 0:
gfx = 100;
@@ -2205,48 +2611,29 @@ static void poll_fsb_us15w(void) {
gfx = 0;
break;
}
+ */
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR");
-
- /* 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;
-
- cprint(LINE_CPU+4, col +1, "- GFX : ");
- col += 9;
- dprint(LINE_CPU+4, col, gfx, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
+ print_cpu_line(dramclock, fsb, 1);
}
static void poll_fsb_nhm(void) {
double dramclock, dramratio, fsb;
- unsigned long mc_dimm_clk_ratio, qpi_pll_status;
+ unsigned long mc_dimm_clk_ratio;
float coef = getNHMmultiplier();
- float qpi_speed;
+ //unsigned long qpi_pll_status;
+ //float qpi_speed;
- fsb = ((extclock /1000) / coef);
- /* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ BCLK : ");
- col += 10;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ fsb = ((extclock /1000) / coef);
/* Print QPI Speed (if ECC not supported) */
- if(ctrl.mode == ECC_NONE && cpu_id.model == 10) {
+ /*
+ if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 10) {
pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status);
qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2;
cprint(LINE_CPU+5, col +1, "/ QPI : ");
@@ -2261,6 +2648,7 @@ static void poll_fsb_nhm(void) {
cprint(LINE_CPU+5, col +1, "GT/s");
col += 5;
}
+ */
/* Get the clock ratio */
@@ -2272,29 +2660,23 @@ static void poll_fsb_nhm(void) {
dramclock = fsb * dramratio / 2;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR3-");
+ print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_nhm32(void) {
double dramclock, dramratio, fsb;
- unsigned long mc_dimm_clk_ratio, qpi_pll_status;
+ unsigned long mc_dimm_clk_ratio;
float coef = getNHMmultiplier();
- float qpi_speed;
+ //unsigned long qpi_pll_status;
+ //float qpi_speed;
fsb = ((extclock /1000) / coef);
- /* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ BCLK : ");
- col += 10;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
-
/* Print QPI Speed (if ECC not supported) */
- if(ctrl.mode == ECC_NONE && cpu_id.model == 12) {
+ /*
+ if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 12) {
pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status);
qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2;
cprint(LINE_CPU+5, col +1, "/ QPI : ");
@@ -2309,6 +2691,7 @@ static void poll_fsb_nhm32(void) {
cprint(LINE_CPU+5, col +1, "GT/s");
col += 5;
}
+ */
/* Get the clock ratio */
@@ -2320,41 +2703,23 @@ static void poll_fsb_nhm32(void) {
dramclock = fsb * dramratio / 2;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR3-");
+ print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_wmr(void) {
double dramclock, dramratio, fsb;
- unsigned long dev0, mchcfg;
+ unsigned long dev0;
float coef = getNHMmultiplier();
long *ptr;
fsb = ((extclock / 1000) / coef);
- if(ctrl.mode == ECC_NONE)
- {
- col = 0;
- cprint(LINE_CPU+5, col, "IMC : "); col += 6;
- getIntelPNS();
- //cprint(LINE_CPU+5, col, "(ECC : Disabled)");
- //col += 16;
- }
-
- /* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ BCLK : ");
- col += 10;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
-
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
ptr=(long*)(dev0+0x2C20);
- mchcfg = *ptr & 0xFFFF;
dramratio = 1;
/* Get the clock ratio */
@@ -2364,35 +2729,44 @@ static void poll_fsb_wmr(void) {
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR3-");
+ print_cpu_line(dramclock, fsb, 3);
}
static void poll_fsb_snb(void) {
double dramclock, dramratio, fsb;
- unsigned long dev0, mchcfg;
+ unsigned long dev0;
float coef = getSNBmultiplier();
long *ptr;
fsb = ((extclock / 1000) / coef);
- if(ctrl.mode == ECC_NONE)
- {
- col = 0;
- cprint(LINE_CPU+5, col, "IMC : "); col += 6;
- getIntelPNS();
- //cprint(LINE_CPU+5, col, "(ECC : Disabled)");
- //col += 16;
- }
+ /* Find dramratio */
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
+ dev0 &= 0xFFFFC000;
+ ptr=(long*)(dev0+0x5E04);
+ dramratio = 1;
+
+ /* Get the clock ratio */
+ dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f);
+
+ // Compute RAM Frequency
+ dramclock = fsb * dramratio;
- /* Print FSB */
- cprint(LINE_CPU+5, col +1, "/ BCLK : ");
- col += 10;
- dprint(LINE_CPU+5, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+5, col +1, "MHz");
- col += 4;
+ // Print DRAM Freq
+ print_cpu_line(dramclock, fsb, 3);
+
+}
+
+static void poll_fsb_ivb(void) {
+
+ double dramclock, dramratio, fsb;
+ unsigned long dev0, mchcfg;
+ float coef = getSNBmultiplier();
+ long *ptr;
+
+ fsb = ((extclock / 1000) / coef);
/* Find dramratio */
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
@@ -2402,13 +2776,47 @@ static void poll_fsb_snb(void) {
dramratio = 1;
/* Get the clock ratio */
- dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f);
+ switch((mchcfg >> 8) & 0x01)
+ {
+ case 0x0:
+ dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f);
+ break;
+ case 0x1:
+ dramratio = (float)(*ptr & 0x1F) * (100.0f / 100.0f);
+ break;
+ }
+
+ // Compute RAM Frequency
+ dramclock = fsb * dramratio;
+
+ // Print DRAM Freq
+ print_cpu_line(dramclock, fsb, 3);
+
+}
+
+static void poll_fsb_snbe(void) {
+
+ double dramclock, dramratio, fsb;
+ unsigned long dev0;
+ float coef = getSNBmultiplier();
+
+ fsb = ((extclock / 1000) / coef);
+
+ /* Find dramratio */
+ pci_conf_read( 0xFF, 10, 1, 0x98, 4, &dev0);
+ dev0 &= 0xFFFFFFFF;
+ dramratio = 1;
+
+ /* Get the clock ratio */
+ dramratio = (float)(dev0 & 0x3F) * (66.67f / 100.0f);
// Compute RAM Frequency
dramclock = fsb * dramratio;
// Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ", "DDR3-");
+ print_cpu_line(dramclock, fsb, 3);
+
+
}
@@ -2419,9 +2827,7 @@ static void poll_timings_nf4ie(void) {
ulong regd0, reg8c, reg9c, reg80;
- int cas, rcd, rp, ras;
-
- cprint(LINE_CPU+5, col +1, "- Type : DDR-II");
+ int cas, rcd, rp, ras, chan;
//Now, read Registers
pci_conf_read( 0, 1, 1, 0xD0, 4, &regd0);
@@ -2435,14 +2841,12 @@ static void poll_timings_nf4ie(void) {
rp = (reg9c >> 8) & 0xF;
ras = (reg8c >> 16) & 0x3F;
- print_timings_info(cas, rcd, rp, ras);
-
if (reg80 & 0x3) {
- cprint(LINE_CPU+6, col2, "/ Dual Channel (128 bits)");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)");
+ chan = 1;
}
-
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_i875(void) {
@@ -2450,24 +2854,16 @@ static void poll_timings_i875(void) {
ulong dev6, dev62;
ulong temp;
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
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+5, col +1, "- PAT : Enabled");
- } else {
- cprint(LINE_CPU+5, col +1, "- PAT : Disabled");
- }
+ /* Read the MMR Base Address & Define the pointer */
+ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
/* Now, we could check some additionnals timings infos) */
-
ptr=(long*)(dev6+0x60);
// CAS Latency (tCAS)
temp = ((*ptr >> 5)& 0x3);
@@ -2485,20 +2881,20 @@ static void poll_timings_i875(void) {
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+6, col2, "/ Dual Channel (128 bits)");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)");
+ chan = 1;
}
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_i925(void) {
// Thanks for CDH optis
+ float cas;
+ int rcd,rp,ras,chan;
ulong dev0, drt, drc, dcc, idetect, temp;
long *ptr;
@@ -2519,69 +2915,53 @@ static void poll_timings_i925(void) {
ptr=(long*)(dev0+0x200);
dcc = *ptr & 0xFFFFFFFF;
- //Determine DDR or DDR-II
- if ((drc & 3) == 2) {
- cprint(LINE_CPU+5, col +1, "- Type : DDR2");
- } else {
- cprint(LINE_CPU+5, col +1, "- Type : DDR1");
- }
-
- // Now, detect timings
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
-
// CAS Latency (tCAS)
temp = ((drt >> 8)& 0x3);
if ((drc & 3) == 2){
// Timings DDR-II
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "5-"); }
- else if (temp == 0x1) { cprint(LINE_CPU+6, col2, "4-"); }
- else if (temp == 0x2) { cprint(LINE_CPU+6, col2, "3-"); }
- else { cprint(LINE_CPU+6, col2, "6-"); }
+ if (temp == 0x0) { cas = 5; }
+ else if (temp == 0x1) { cas = 4; }
+ else if (temp == 0x2) { cas = 3; }
+ else { cas = 6; }
} else {
// Timings DDR-I
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "3-"); }
- else if (temp == 0x1) { cprint(LINE_CPU+6, col2, "2.5-"); col2 +=2;}
- else { cprint(LINE_CPU+6, col2, "2-"); }
+ if (temp == 0x0) { cas = 3; }
+ else if (temp == 0x1) { cas = 2.5f;}
+ else { cas = 2; }
}
- col2 +=2;
// RAS-To-CAS (tRCD)
- dprint(LINE_CPU+6, col2, ((drt >> 4)& 0x3)+2, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- col2 +=2;
+ rcd = ((drt >> 4)& 0x3)+2;
// RAS Precharge (tRP)
- dprint(LINE_CPU+6, col2, (drt&0x3)+2, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- col2 +=2;
+ rp = (drt&0x3)+2;
// RAS Active to precharge (tRAS)
// If Lakeport, than change tRAS computation (Thanks to CDH, again)
if (idetect > 0x2700)
- temp = ((drt >> 19)& 0x1F);
+ ras = ((drt >> 19)& 0x1F);
else
- temp = ((drt >> 20)& 0x0F);
+ ras = ((drt >> 20)& 0x0F);
- dprint(LINE_CPU+6, col2, temp , 1 ,0);
- (temp < 10)?(col2 += 1):(col2 += 2);
-
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
temp = (dcc&0x3);
- if (temp == 1) { cprint(LINE_CPU+6, col2, " Dual Channel (Asymmetric)"); }
- else if (temp == 2) { cprint(LINE_CPU+6, col2, " Dual Channel (Interleaved)"); }
- else { cprint(LINE_CPU+6, col2, " Single Channel (64 bits)"); }
+ if (temp == 1) { chan = 2; }
+ else if (temp == 2) { chan = 2; }
+ else { chan = 1; }
+
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_i965(void) {
// Thanks for CDH optis
- ulong dev0, temp, c0ckectrl, c1ckectrl, offset;
- ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register;
+ ulong dev0, c0ckectrl, c1ckectrl, offset;
+ ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register;
long *ptr;
+ int rcd,rp,ras,chan;
+ float cas;
//Now, read MMR Base Address
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
@@ -2608,56 +2988,37 @@ static void poll_timings_i965(void) {
ptr = (long*)(dev0+offset+0x258);
Read_Register = *ptr & 0xFFFFFFFF;
- ptr = (long*)(dev0+offset+0x244);
- Misc_Register = *ptr & 0xFFFFFFFF;
-
- //Intel 965 Series only support DDR2
- cprint(LINE_CPU+5, col +1, "- Type : DDR-II");
-
- // Now, detect timings
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
// CAS Latency (tCAS)
- temp = ((ODT_Control_Register >> 17)& 7) + 3.0f;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ cas = ((ODT_Control_Register >> 17)& 7) + 3.0f;
// RAS-To-CAS (tRCD)
- temp = (Read_Register >> 16) & 0xF;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ rcd = (Read_Register >> 16) & 0xF;
// RAS Precharge (tRP)
- temp = (ACT_Register >> 13) & 0xF;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ rp = (ACT_Register >> 13) & 0xF;
// RAS Active to precharge (tRAS)
- temp = (Precharge_Register >> 11) & 0x1F;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- (temp < 10)?(col2 += 1):(col2 += 2);
-
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
+ ras = (Precharge_Register >> 11) & 0x1F;
if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ chan = 1;
}
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_im965(void) {
// Thanks for CDH optis
- ulong dev0, temp, c0ckectrl, c1ckectrl, offset;
+ ulong dev0, c0ckectrl, c1ckectrl, offset;
ulong ODT_Control_Register, Precharge_Register;
long *ptr;
-
+ int rcd,rp,ras,chan;
+ float cas;
+
//Now, read MMR Base Address
pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
dev0 &= 0xFFFFC000;
@@ -2677,55 +3038,36 @@ static void poll_timings_im965(void) {
ptr = (long*)(dev0+offset+0x1214);
Precharge_Register = *ptr & 0xFFFFFFFF;
- //Intel 965 Series only support DDR2
- cprint(LINE_CPU+5, col+1, "- Type : DDR-II");
-
- // Now, detect timings
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
-
// CAS Latency (tCAS)
- temp = ((ODT_Control_Register >> 23)& 7) + 3.0f;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ cas = ((ODT_Control_Register >> 23)& 7) + 3.0f;
// RAS-To-CAS (tRCD)
- temp = ((Precharge_Register >> 5)& 7) + 2.0f;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ rcd = ((Precharge_Register >> 5)& 7) + 2.0f;
// RAS Precharge (tRP)
- temp = (Precharge_Register & 7) + 2.0f;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- (temp < 10)?(col2 += 2):(col2 += 3);
+ rp = (Precharge_Register & 7) + 2.0f;
// RAS Active to precharge (tRAS)
- temp = (Precharge_Register >> 21) & 0x1F;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- (temp < 10)?(col2 += 1):(col2 += 2);
+ ras = (Precharge_Register >> 21) & 0x1F;
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ chan = 1;
}
-
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_p35(void) {
// Thanks for CDH optis
float cas;
- int rcd, rp, ras;
- ulong dev0, Device_ID, Memory_Check, c0ckectrl, c1ckectrl, offset;
- ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register;
+ int rcd, rp, ras, chan;
+ ulong dev0, Device_ID, c0ckectrl, c1ckectrl, offset;
+ ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register;
long *ptr;
-
+
pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID);
Device_ID &= 0xFFFF;
@@ -2754,30 +3096,9 @@ static void poll_timings_p35(void) {
ptr = (long*)(dev0+offset+0x258);
Read_Register = *ptr & 0xFFFFFFFF;
- ptr = (long*)(dev0+offset+0x244);
- Misc_Register = *ptr & 0xFFFFFFFF;
-
- // On P45, check 1A8
- if(Device_ID > 0x2E00) {
- ptr = (long*)(dev0+offset+0x1A8);
- Memory_Check = *ptr & 0xFFFFFFFF;
- Memory_Check >>= 2;
- Memory_Check &= 1;
- Memory_Check = !Memory_Check;
- } else {
- ptr = (long*)(dev0+offset+0x1E8);
- Memory_Check = *ptr & 0xFFFFFFFF;
- }
-
- //Determine DDR-II or DDR-III
- if (Memory_Check & 1) {
- cprint(LINE_CPU+5, col +1, "- Type : DDR2");
- } else {
- cprint(LINE_CPU+5, col +1, "- Type : DDR3");
- }
// CAS Latency (tCAS)
- if(Device_ID > 0x2E00) {
+ if(Device_ID > 0x2E00 && imc_type != 8) {
cas = ((ODT_Control_Register >> 8)& 0x3F) - 6.0f;
} else {
cas = ((ODT_Control_Register >> 8)& 0x3F) - 9.0f;
@@ -2792,22 +3113,18 @@ static void poll_timings_p35(void) {
// RAS Active to precharge (tRAS)
ras = Precharge_Register & 0x3F;
- print_timings_info(cas, rcd, rp, ras);
-
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
-
if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ chan = 1;
}
-
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_wmr(void) {
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
ulong dev0, c0ckectrl, c1ckectrl, offset;
ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, MRC_Register;
long *ptr;
@@ -2856,22 +3173,20 @@ static void poll_timings_wmr(void) {
// RAS Active to precharge (tRAS)
ras = Precharge_Register & 0x3F;
- print_timings_info(cas, rcd, rp, ras);
-
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
-
if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ chan = 1;
}
+ print_ram_line(cas, rcd, rp, ras, chan);
+
}
static void poll_timings_snb(void) {
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
ulong dev0, offset;
ulong IMC_Register, MCMain0_Register, MCMain1_Register;
long *ptr;
@@ -2897,30 +3212,127 @@ static void poll_timings_snb(void) {
// RAS Active to precharge (tRAS)
ras = (IMC_Register >> 16) & 0xFF;
- print_timings_info(cas, rcd, rp, ras);
+ // Channels
+ ptr = (long*)(dev0+offset+0x5004);
+ MCMain0_Register = *ptr & 0xFFFF;
+ ptr = (long*)(dev0+offset+0x5008);
+ MCMain1_Register = *ptr & 0xFFFF;
+
+ if(MCMain0_Register == 0 || MCMain1_Register == 0) {
+ chan = 1;
+ } else {
+ chan = 2;
+ }
+
+ print_ram_line(cas, rcd, rp, ras, chan);
+}
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
+static void poll_timings_hsw(void) {
+
+ float cas;
+ int rcd, rp, ras, chan;
+ ulong dev0, offset = 0;
+ ulong IMC_Register, MCMain0_Register, MCMain1_Register;
+ long *ptr;
+
+ //Now, read MMR Base Address
+ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
+ dev0 &= 0xFFFFC000;
// Channels
ptr = (long*)(dev0+offset+0x5004);
MCMain0_Register = *ptr & 0xFFFF;
+
ptr = (long*)(dev0+offset+0x5008);
MCMain1_Register = *ptr & 0xFFFF;
- if(MCMain0_Register == 0 || MCMain1_Register == 0) {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ if(MCMain0_Register && MCMain1_Register) {
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 1;
}
+
+ if(MCMain0_Register) { offset = 0x0000; } else { offset = 0x0400; }
+
+ // CAS Latency (tCAS)
+ ptr = (long*)(dev0+offset+0x4014);
+ IMC_Register = *ptr & 0xFFFFFFFF;
+ cas = (float)(IMC_Register & 0x1F);
+
+ ptr = (long*)(dev0+offset+0x4000);
+ IMC_Register = *ptr & 0xFFFFFFFF;
+
+ // RAS-To-CAS (tRCD)
+ rcd = IMC_Register & 0x1F;
+
+ // RAS Precharge (tRP)
+ rp = (IMC_Register >> 5) & 0x1F;
+
+ // RAS Active to precharge (tRAS)
+ ras = (IMC_Register >> 10) & 0x3F;
+
+
+ print_ram_line(cas, rcd, rp, ras, chan);
+}
+
+static void poll_timings_snbe(void) {
+
+ float cas;
+ int rcd, rp, ras;
+ int nb_channel = 0, current_channel = 0;
+ ulong temp, IMC_Register;
+ long *ptr;
+
+ //Read Channel #1
+ pci_conf_read(0xFF, 16, 2, 0x80, 4, &temp);
+ temp &= 0x3F;
+ if(temp != 0xB) { current_channel = 0; nb_channel++; }
+
+ //Read Channel #2
+ pci_conf_read(0xFF, 16, 3, 0x80, 4, &temp);
+ temp &= 0x3F;
+ if(temp != 0xB) { current_channel = 1; nb_channel++; }
+
+ //Read Channel #3
+ pci_conf_read(0xFF, 16, 6, 0x80, 4, &temp);
+ temp &= 0x3F;
+ if(temp != 0xB) { current_channel = 4; nb_channel++; }
+
+ //Read Channel #4
+ pci_conf_read(0xFF, 16, 7, 0x80, 4, &temp);
+ temp &= 0x3F;
+ if(temp != 0xB) { current_channel = 5; nb_channel++; }
+
+
+ pci_conf_read(0, 5, 0, 0x84, 4, &temp);
+ ptr = (long*)((temp & 0xFC000000) + (MAKE_PCIE_ADDRESS(0xFF,16,current_channel) | 0x200));
+ IMC_Register = *ptr & 0xFFFFFFFF;
+
+ // CAS Latency (tCAS)
+ cas = (float)((IMC_Register >> 9) & 0x1F);
+
+ // RAS-To-CAS (tRCD)
+ rcd = IMC_Register & 0x1F;
+
+ // RAS Precharge (tRP)
+ rp = (IMC_Register >> 5) & 0x0F;
+
+ // RAS Active to precharge (tRAS)
+ ras = (IMC_Register >> 19) & 0x3F;
+
+
+ print_ram_line(cas, rcd, rp, ras, nb_channel);
}
static void poll_timings_5400(void) {
// Thanks for CDH optis
- ulong ambase, mtr1, mtr2, offset, mca, temp;
+ ulong ambase, mtr1, mtr2, offset, mca;
long *ptr;
-
+ float cas;
+ int rcd, rp, ras, chan;
+
//Hard-coded Ambase value (should not be realocated by software when using Memtest86+
ambase = 0xFE000000;
offset = mtr1 = mtr2 = 0;
@@ -2942,49 +3354,36 @@ static void poll_timings_5400(void) {
//cprint(LINE_CPU+5, col +1, "- Type : FBD");
// Now, detect timings
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
// CAS Latency (tCAS)
- temp = mtr2 & 0xF;
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- col2 += 2;
+ cas = mtr2 & 0xF;
// RAS-To-CAS (tRCD)
- temp = 6 - ((mtr1 >> 10) & 3);
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- col2 += 2;
+ rcd = 6 - ((mtr1 >> 10) & 3);
// RAS Precharge (tRP)
- temp = 6 - ((mtr1 >> 8) & 3);
- dprint(LINE_CPU+6, col2, temp, 1 ,0);
- cprint(LINE_CPU+6, col2+1, "-");
- col2 += 2;
+ rp = 6 - ((mtr1 >> 8) & 3);
// 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+6, col2, temp, 1 ,0);
- (temp < 10)?(col2 += 1):(col2 += 2);
+ ras = 16 - (3 * ((mtr1 >> 29) & 3)) + ((mtr1 >> 12) & 3);
+ if(((mtr1 >> 12) & 3) == 3 && ((mtr1 >> 29) & 3) == 2) { ras = 9; }
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
if ((mca >> 14) & 1) {
- cprint(LINE_CPU+6, col2+1, "Single Channel");
+ chan = 1;
} else {
- cprint(LINE_CPU+6, col2+1, "Dual Channel");
+ chan = 2;
}
+ print_ram_line(cas, rcd, rp, ras, chan);
+
}
static void poll_timings_E7520(void) {
ulong drt, ddrcsr;
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
pci_conf_read( 0, 0, 0, 0x9A, 2, &ddrcsr);
@@ -2993,21 +3392,23 @@ static void poll_timings_E7520(void) {
rcd = ((drt >> 10) & 1) + 3;
rp = ((drt >> 9) & 1) + 3;
ras = ((drt >> 14) & 3) + 11;
-
- print_timings_info(cas, rcd, rp, ras);
if ((ddrcsr & 0xF) >= 0xC) {
- cprint(LINE_CPU+6, col2, "/ Dual Channel (128 bits)");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)");
+ chan = 1;
}
+
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_i855(void) {
ulong drt, temp;
-
+ float cas;
+ int rcd, rp, ras;
+
pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
/* Now, we could print some additionnals timings infos) */
@@ -3016,27 +3417,26 @@ static void poll_timings_i855(void) {
// CAS Latency (tCAS)
temp = ((drt >> 4)&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "2.5-"); col2 += 4; }
- else { cprint(LINE_CPU+6, col2, "2-"); col2 +=2; }
+ if (temp == 0x0) { cas = 2.5; }
+ else { cas = 2; }
// RAS-To-CAS (tRCD)
temp = ((drt >> 2)& 0x1);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "3-"); }
- else { cprint(LINE_CPU+6, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rcd = 3; }
+ else { rcd = 2; }
// RAS Precharge (tRP)
temp = (drt&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "3-"); }
- else { cprint(LINE_CPU+6, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rp = 3 ; }
+ else { rp = 2; }
// RAS Active to precharge (tRAS)
temp = 7-((drt >> 9)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "7"); }
- if (temp == 0x1) { cprint(LINE_CPU+6, col2, "6"); }
- if (temp == 0x2) { cprint(LINE_CPU+6, col2, "5"); }
- col2 +=1;
+ if (temp == 0x0) { ras = 7; }
+ if (temp == 0x1) { ras = 6; }
+ if (temp == 0x2) { ras = 5; }
+
+ print_ram_line(cas, rcd, rp, ras, 1);
}
@@ -3044,7 +3444,7 @@ static void poll_timings_E750x(void) {
ulong drt, drc, temp;
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
pci_conf_read( 0, 0, 0, 0x7C, 4, &drc);
@@ -3056,20 +3456,22 @@ static void poll_timings_E750x(void) {
temp = ((drt >> 9) & 3);
if (temp == 2) { ras = 5; } else if (temp == 1) { ras = 6; } else { ras = 7; }
- print_timings_info(cas, rcd, rp, ras);
-
if (((drc >> 22)&1) == 1) {
- cprint(LINE_CPU+6, col2, "/ Dual Channel (128 bits)");
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)");
+ chan = 1;
}
+ print_ram_line(cas, rcd, rp, ras, chan);
+
}
static void poll_timings_i852(void) {
ulong drt, temp;
-
+ float cas;
+ int rcd, rp, ras;
+
pci_conf_read( 0, 0, 1, 0x60, 4, &drt);
/* Now, we could print some additionnals timings infos) */
@@ -3078,80 +3480,62 @@ static void poll_timings_i852(void) {
// CAS Latency (tCAS)
temp = ((drt >> 5)&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "2.5-"); col2 += 4; }
- else { cprint(LINE_CPU+6, col2, "2-"); col2 +=2; }
+ if (temp == 0x0) { cas = 2.5; }
+ else { cas = 2; }
// RAS-To-CAS (tRCD)
temp = ((drt >> 2)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+6, col2, "3-"); }
- else { cprint(LINE_CPU+6, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rcd = 4; }
+ if (temp == 0x1) { rcd = 3; }
+ else { rcd = 2; }
// RAS Precharge (tRP)
temp = (drt&0x3);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+6, col2, "3-"); }
- else { cprint(LINE_CPU+6, col2, "2-"); }
- col2 +=2;
+ if (temp == 0x0) { rp = 4; }
+ if (temp == 0x1) { rp = 3; }
+ else { rp = 2; }
// RAS Active to precharge (tRAS)
temp = ((drt >> 9)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+6, col2, "8"); col2 +=7; }
- if (temp == 0x1) { cprint(LINE_CPU+6, col2, "7"); col2 +=6; }
- if (temp == 0x2) { cprint(LINE_CPU+6, col2, "6"); col2 +=5; }
- if (temp == 0x3) { cprint(LINE_CPU+6, col2, "5"); col2 +=5; }
- col2 +=1;
+ if (temp == 0x0) { ras = 8; }
+ if (temp == 0x1) { ras = 7; }
+ if (temp == 0x2) { ras = 6; }
+ if (temp == 0x3) { ras = 5; }
+
+ print_ram_line(cas, rcd, rp, ras, 1);
}
static void poll_timings_amd64(void) {
ulong dramtlr, dramclr;
- int temp;
+ int temp, chan;
+ float tcas;
int trcd, trp, tras ;
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
-
pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr);
pci_conf_read(0, 24, 2, 0x90, 4, &dramclr);
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
+
+ if (cpu_id.vers.bits.extendedModel >= 4) {
/* NEW K8 0Fh Family 90 nm (DDR2) */
// CAS Latency (tCAS)
- temp = (dramtlr & 0x7) + 1;
- dprint(LINE_CPU+6, col2, temp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
+ tcas = (dramtlr & 0x7) + 1;
// RAS-To-CAS (tRCD)
trcd = ((dramtlr >> 4) & 0x3) + 3;
- dprint(LINE_CPU+6, col2, trcd , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
// RAS Precharge (tRP)
trp = ((dramtlr >> 8) & 0x3) + 3;
- dprint(LINE_CPU+6, col2, trp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
// RAS Active to precharge (tRAS)
tras = ((dramtlr >> 12) & 0xF) + 3;
- if (tras < 10){
- dprint(LINE_CPU+6, col2, tras , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+6, col2, tras , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
// Print 64 or 128 bits mode
-
if ((dramclr >> 11)&1) {
- cprint(LINE_CPU+6, col2, " DDR2 (128 bits)");
- col2 +=16;
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, " DDR2 (64 bits)");
- col2 +=15;
+ chan = 1;
}
} else {
@@ -3159,48 +3543,41 @@ static void poll_timings_amd64(void) {
// CAS Latency (tCAS)
temp = (dramtlr & 0x7);
- if (temp == 0x1) { cprint(LINE_CPU+6, col2, "2-"); col2 +=2; }
- if (temp == 0x2) { cprint(LINE_CPU+6, col2, "3-"); col2 +=2; }
- if (temp == 0x5) { cprint(LINE_CPU+6, col2, "2.5-"); col2 +=4; }
+ if (temp == 0x1) { tcas = 2; }
+ if (temp == 0x2) { tcas = 3; }
+ if (temp == 0x5) { tcas = 2.5; }
// RAS-To-CAS (tRCD)
trcd = ((dramtlr >> 12) & 0x7);
- dprint(LINE_CPU+6, col2, trcd , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
// RAS Precharge (tRP)
trp = ((dramtlr >> 24) & 0x7);
- dprint(LINE_CPU+6, col2, trp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
// RAS Active to precharge (tRAS)
tras = ((dramtlr >> 20) & 0xF);
- if (tras < 10){
- dprint(LINE_CPU+6, col2, tras , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+6, col2, tras , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
// Print 64 or 128 bits mode
-
if (((dramclr >> 16)&1) == 1) {
- cprint(LINE_CPU+6, col2, " DDR1 (128 bits)");
- col2 +=16;
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, " DDR1 (64 bits)");
- col2 +=15;
+ chan = 1;
}
}
+
+ print_ram_line(tcas, trcd, trp, tras, chan);
+
}
static void poll_timings_k10(void) {
- ulong dramtlr, dramclr, dramchr;
+ ulong dramtlr, dramclr, dramchr, dramchrb;
ulong offset = 0;
- int cas, rcd, rp, rc, ras;
+ int cas, rcd, rp, ras, chan;
pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
+ pci_conf_read(0, 24, 2, 0x194, 4, &dramchrb);
+
+ if(((dramchr>>14) & 0x1) || ((dramchr>>14) & 0x1)) { chan = 1; } else { chan = 2; }
// If Channel A not enabled, switch to channel B
if(((dramchr>>14) & 0x1))
@@ -3218,57 +3595,104 @@ static void poll_timings_k10(void) {
cas = (dramtlr & 0xF) + 4;
rcd = ((dramtlr >> 4) & 0x7) + 5;
rp = ((dramtlr >> 7) & 0x7) + 5;
- ras = ((dramtlr >> 12) & 0xF) + 15;
- rc = ((dramtlr >> 16) & 0x1F) + 11;
+ ras = ((dramtlr >> 12) & 0xF) + 15;
} else {
// DDR2-800 or less
cas = (dramtlr & 0xF) + 1;
rcd = ((dramtlr >> 4) & 0x3) + 3;
rp = ((dramtlr >> 8) & 0x3) + 3;
ras = ((dramtlr >> 12) & 0xF) + 3;
- rc = ((dramtlr >> 16) & 0x1F) + 11;
}
+
+ print_ram_line(cas, rcd, rp, ras, chan);
+}
- print_timings_info(cas, rcd, rp, ras);
-
- cprint(LINE_CPU+6, col2, "/"); col2++;
+static void poll_timings_k12(void) {
+
+ ulong dramt0, dramlow, dimma, dimmb;
+ int cas, rcd, rp, ras, chan = 0;
- //Print DDR2 or DDR3
- if ((dramchr >> 8)&1) {
- cprint(LINE_CPU+6, col2+1, "DDR3");
- } else {
- cprint(LINE_CPU+6, col2+1, "DDR2");
+ pci_conf_read(0, 24, 2, 0x94, 4, &dimma);
+ pci_conf_read(0, 24, 2, 0x194, 4, &dimmb);
+
+ if(((dimma >> 14) & 0x1) == 0)
+ {
+ chan++;
+ pci_conf_read(0, 24, 2, 0x88, 4, &dramlow);
+ pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040);
+ pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0);
}
- col2 += 5;
- // Print 64 or 128 bits mode
- if ((dramclr >> 4)&1) {
- cprint(LINE_CPU+6, col2+1, "(128 bits)");
- } else {
- cprint(LINE_CPU+6, col2+1, "(64 bits)");
- }
+ if(((dimmb >> 14) & 0x1) == 0)
+ {
+ chan++;
+ pci_conf_read(0, 24, 2, 0x188, 4, &dramlow);
+ pci_conf_write(0, 24, 2, 0x1F0, 4, 0x00000040);
+ pci_conf_read(0, 24, 2, 0x1F4, 4, &dramt0);
+ }
+
+ cas = (dramlow & 0xF) + 4;
+ rcd = (dramt0 & 0xF) + 5;
+ rp = ((dramt0 >> 8) & 0xF) + 5;
+ ras = ((dramt0 >> 16) & 0x1F) + 15;
+ print_ram_line(cas, rcd, rp, ras, chan);
}
+
static void poll_timings_k14(void) {
ulong dramt0, dramlow;
- int cas, rcd, rp, rc, ras;
+ int cas, rcd, rp, ras;
- pci_conf_read(0, 24, 2, 0x88, 4, &dramlow);
+ pci_conf_read(0, 24, 2, 0x88, 4, &dramlow);
pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040);
- pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0);
+ pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0);
cas = (dramlow & 0xF) + 4;
rcd = (dramt0 & 0xF) + 5;
rp = ((dramt0 >> 8) & 0xF) + 5;
ras = ((dramt0 >> 16) & 0x1F) + 15;
- rc = ((dramt0 >> 24) & 0x3F) + 16;
+
+ print_ram_line(cas, rcd, rp, ras, 1);
+}
- print_timings_info(cas, rcd, rp, ras);
+static void poll_timings_k15(void) {
- cprint(LINE_CPU+6, col2, "/ DDR3 (64 bits)");
+ ulong dramp1, dramp2, dimma, dimmb;
+ int cas, rcd, rp, ras, chan = 0;
+
+ pci_conf_read(0, 24, 2, 0x94, 4, &dimma);
+ pci_conf_read(0, 24, 2, 0x194, 4, &dimmb);
+ if(((dimma>>14) & 0x1) || ((dimmb>>14) & 0x1)) { chan = 1; } else { chan = 2; }
+
+ pci_conf_read(0, 24, 2, 0x200, 4, &dramp1);
+ pci_conf_read(0, 24, 2, 0x204, 4, &dramp2);
+
+ cas = dramp1 & 0x1F;
+ rcd = (dramp1 >> 8) & 0x1F;
+ rp = (dramp1 >> 16) & 0x1F;
+ ras = (dramp1 >> 24) & 0x3F;
+
+ print_ram_line(cas, rcd, rp, ras, chan);
+}
+static void poll_timings_k16(void) {
+
+ ulong dramt0, dramt1;
+ int cas, rcd, rp, rc, ras;
+
+ pci_conf_read(0, 24, 2, 0x200, 4, &dramt0);
+ pci_conf_read(0, 24, 2, 0x204, 4, &dramt1);
+
+ cas = (dramt0 & 0x1F);
+ rcd = ((dramt0 >> 8) & 0x1F);
+ rp = ((dramt0 >> 16) & 0x1F);
+ ras = ((dramt0 >> 24) & 0x3F);
+
+ rc = (dramt1 & 0x3F);
+
+ print_ram_line(cas, rcd, rp, ras, 1);
}
static void poll_timings_EP80579(void) {
@@ -3285,14 +3709,16 @@ static void poll_timings_EP80579(void) {
rp = ((drt1 >> 6) & 0x7) + 3;
ras = ((drt2 >> 28) & 0xF) + 8;
- print_timings_info(cas, rcd, rp, ras);
+ print_ram_line(cas, rcd, rp, ras, 0);
}
static void poll_timings_nf2(void) {
ulong dramtlr, dramtlr2, dramtlr3, temp;
ulong dimm1p, dimm2p, dimm3p;
-
+ float cas;
+ int rcd, rp, ras, chan;
+
pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr);
pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2);
pci_conf_read(0, 0, 1, 0x84, 4, &dramtlr3);
@@ -3300,77 +3726,54 @@ static void poll_timings_nf2(void) {
pci_conf_read(0, 0, 2, 0x44, 4, &dimm2p);
pci_conf_read(0, 0, 2, 0x48, 4, &dimm3p);
- cprint(LINE_CPU+6, col2 +1, "/ CAS : ");
- col2 += 9;
-
// CAS Latency (tCAS)
temp = ((dramtlr2 >> 4) & 0x7);
- if (temp == 0x2) { cprint(LINE_CPU+6, col2, "2-"); col2 +=2; }
- if (temp == 0x3) { cprint(LINE_CPU+6, col2, "3-"); col2 +=2; }
- if (temp == 0x6) { cprint(LINE_CPU+6, col2, "2.5-"); col2 +=4; }
-
+ if (temp == 0x2) { cas = 2; }
+ if (temp == 0x3) { cas = 3; }
+ if (temp == 0x6) { cas = 2.5; }
+
// RAS-To-CAS (tRCD)
- temp = ((dramtlr >> 20) & 0xF);
- dprint(LINE_CPU+6, col2, temp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
+ rcd = ((dramtlr >> 20) & 0xF);
// RAS Precharge (tRP)
- temp = ((dramtlr >> 28) & 0xF);
- dprint(LINE_CPU+6, col2, temp , 1 ,0);
- cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2;
+ rp = ((dramtlr >> 28) & 0xF);
// RAS Active to precharge (tRAS)
- temp = ((dramtlr >> 15) & 0xF);
- if (temp < 10){
- dprint(LINE_CPU+6, col2, temp , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+6, col2, temp , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+6, col2+1, "/"); col2 +=2;
+ ras = ((dramtlr >> 15) & 0xF);
// Print 64 or 128 bits mode
// If DIMM1 & DIMM3 or DIMM1 & DIMM2 populated, than Dual Channel.
if ((dimm3p&1) + (dimm2p&1) == 2 || (dimm3p&1) + (dimm1p&1) == 2 ) {
- cprint(LINE_CPU+6, col2, " Dual Channel (128 bits)");
- col2 +=24;
+ chan = 2;
} else {
- cprint(LINE_CPU+6, col2, " Single Channel (64 bits)");
- col2 +=15;
+ chan = 1;
}
-
+ print_ram_line(cas, rcd, rp, ras, chan);
}
static void poll_timings_us15w(void) {
// Thanks for CDH optis
- ulong dtr, temp;
-
+ ulong dtr;
+ float cas;
+ int rcd, rp;
+
/* Find dramratio */
/* D0 MsgRd, 01 Dunit, 01 DTR */
pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0010100 );
pci_conf_read(0, 0, 0, 0xD4, 4, &dtr );
- // Now, detect timings
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
// CAS Latency (tCAS)
- temp = ((dtr >> 4) & 0x3) + 3;
- dprint(LINE_CPU+5, col2, temp, 1 ,0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 += 2;
+ cas = ((dtr >> 4) & 0x3) + 3;
// RAS-To-CAS (tRCD)
- temp = ((dtr >> 2) & 0x3) + 3;
- dprint(LINE_CPU+5, col2, temp, 1 ,0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 += 2;
+ rcd = ((dtr >> 2) & 0x3) + 3;
// RAS Precharge (tRP)
- temp = ((dtr >> 0) & 0x3) + 3;
- dprint(LINE_CPU+5, col2, temp, 1 ,0);
- col2 += 1;
+ rp = ((dtr >> 0) & 0x3) + 3;
+
+ print_ram_line(cas, rcd, rp, 9, 1);
}
@@ -3378,7 +3781,7 @@ static void poll_timings_nhm(void) {
ulong mc_channel_bank_timing, mc_control, mc_channel_mrs_value;
float cas;
- int rcd, rp, ras;
+ int rcd, rp, ras, chan;
int fvc_bn = 4;
/* Find which channels are populated */
@@ -3403,200 +3806,233 @@ static void poll_timings_nhm(void) {
ras = (mc_channel_bank_timing >> 4) & 0x1F;
rp = mc_channel_bank_timing & 0xF;
- print_timings_info(cas, rcd, rp, ras);
-
// Print 1, 2 or 3 Channels
if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) {
- cprint(LINE_CPU+6, col2, "/ Single Channel");
- col2 += 16;
+ chan = 1;
} else if (mc_control == 7) {
- cprint(LINE_CPU+6, col2, "/ Triple Channel");
- col2 += 16;
+ chan = 3;
} else {
- cprint(LINE_CPU+6, col2, "/ Dual Channel");
- col2 += 14;
+ chan = 2;
}
-
+ print_ram_line(cas, rcd, rp, ras, chan);
+
}
+static void poll_timings_ct(void)
+{
+
+ unsigned long mcr,mdr;
+ float cas;
+ int rcd, rp, ras;
+
+ /* Build the MCR Message*/
+ mcr = (0x10 << 24); // 10h = Read - 11h = Write
+ mcr += (0x01 << 16); // DRAM Registers located on port 01h
+ mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h
+ mcr &= 0xFFFFFFF0; // bit 03:00 RSVD
+
+ /* Send Message to GMCH */
+ pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
+
+ /* Read Answer from Sideband bus */
+ pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
+
+ // CAS Latency (tCAS)
+ cas = ((mdr >> 12)& 0x7) + 5.0f;
+
+ // RAS-To-CAS (tRCD)
+ rcd = ((mdr >> 8)& 0x7) + 5;
+
+ // RAS Precharge (tRP)
+ rp = ((mdr >> 4)& 0x7) + 5;
+
+ // RAS is in DTR1. Read Again.
+ mcr = 0x10010200; // Quick Mode ! Awesome !
+ pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
+ pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
+
+ // RAS Active to precharge (tRAS)
+ ras = (mdr >> 20) & 0xF;
+
+ // Print
+ print_ram_line(cas, rcd, rp, ras, 1);
+
+}
/* ------------------ Let's continue ------------------ */
/* ---------------------------------------------------- */
-static struct pci_memory_controller controllers[] = {
+struct pci_memory_controller controllers[] = {
/* Default unknown chipset */
- { 0, 0, "", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0, 0, "","", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
/* AMD */
- { 0x1022, 0x7006, "AMD 751", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_amd751 },
- { 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, 0x7006, "AMD 751","SDRAM PC-100", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_nothing },
+ { 0x1022, 0x700c, "AMD 762","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing },
+ { 0x1022, 0x700e, "AMD 761","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing },
/* SiS */
- { 0x1039, 0x0600, "SiS 600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0620, "SiS 620", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x5600, "SiS 5600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0645, "SiS 645", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0646, "SiS 645DX", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0630, "SiS 630", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0650, "SiS 650", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0651, "SiS 651", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0730, "SiS 730", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 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, 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, 0x0656, "SiS 656", 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 },
- { 0x1039, 0x0649, "SiS 649", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0661, "SiS 661", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0671, "SiS 671", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0672, "SiS 672", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0600, "SiS 600","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0620, "SiS 620","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x5600, "SiS 5600","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0645, "SiS 645","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0646, "SiS 645DX","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0630, "SiS 630","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0650, "SiS 650","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0651, "SiS 651","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0730, "SiS 730","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0735, "SiS 735","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0740, "SiS 740","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0745, "SiS 745","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0748, "SiS 748","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0655, "SiS 655","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0656, "SiS 656","DDR/DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0648, "SiS 648","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0649, "SiS 649","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0661, "SiS 661","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0671, "SiS 671","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1039, 0x0672, "SiS 672","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
/* ALi */
- { 0x10b9, 0x1531, "ALi Aladdin 4", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10b9, 0x1541, "ALi 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, 0x1531, "ALi Aladdin 4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x10b9, 0x1541, "ALi Aladdin 5","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x10b9, 0x1644, "ALi Aladdin M1644","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
/* ATi */
- { 0x1002, 0x5830, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5831, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5832, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 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, 0x5830, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1002, 0x5831, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1002, 0x5832, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1002, 0x5833, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1002, 0x5954, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1002, 0x5A41, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
/* 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, 0x0071, "nForce4 SLI Intel Edition", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing },
+ { 0x10de, 0x01A4, "nVidia nForce","DDR-SDRAM", 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, 0x0071, "nForce4 SLI","", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing },
/* VIA */
- { 0x1106, 0x0305, "VIA KT133/KT133A", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0391, "VIA KX133", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0501, "VIA MVP4", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0585, "VIA VP/VPX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0595, "VIA VP2", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0597, "VIA VP3", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0598, "VIA MVP3", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0691, "VIA Apollo Pro/133/133A", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0693, "VIA Apollo Pro+", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0601, "VIA PLE133", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3099, "VIA KT266(A)/KT333", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3189, "VIA KT400(A)/600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0269, "VIA KT880", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3205, "VIA KM400", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3116, "VIA KM266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3156, "VIA KN266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 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, 0x0305, "VIA KT133/KT133A","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0391, "VIA KX133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0501, "VIA MVP4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0585, "VIA VP/VPX","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0595, "VIA VP2","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0597, "VIA VP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0598, "VIA MVP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0691, "VIA Apollo Pro 133(A)","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0693, "VIA Apollo Pro+","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0601, "VIA PLE133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3099, "VIA KT266(A)/KT333","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3189, "VIA KT400(A)/600","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0269, "VIA KT880","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3205, "VIA KM400","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3116, "VIA KM266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3156, "VIA KN266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3123, "VIA CLE266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x0198, "VIA PT800","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x1106, 0x3258, "VIA PT880","DDR2-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
/* Serverworks */
- { 0x1166, 0x0008, "CNB20HE", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
- { 0x1166, 0x0009, "CNB20LE", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
+ { 0x1166, 0x0008, "CNB20HE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
+ { 0x1166, 0x0009, "CNB20LE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
/* Intel */
- { 0x8086, 0x1130, "Intel i815", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x122d, "Intel i430FX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1235, "Intel i430MX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1237, "Intel i440FX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1250, "Intel i430HX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1A21, "Intel i840", 0, poll_fsb_nothing, poll_timings_nothing, setup_i840, poll_i840 },
- { 0x8086, 0x1A30, "Intel i845", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_i845 },
- { 0x8086, 0x2560, "Intel i845E/G/PE/GE",0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_i845 },
- { 0x8086, 0x2500, "Intel i820", 0, poll_fsb_nothing, poll_timings_nothing, setup_i820, poll_i820 },
- { 0x8086, 0x2530, "Intel i850", 0, poll_fsb_p4, poll_timings_nothing, setup_i850, poll_i850 },
- { 0x8086, 0x2531, "Intel i860", 1, poll_fsb_nothing, poll_timings_nothing, setup_i860, poll_i860 },
- { 0x8086, 0x7030, "Intel i430VX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7100, "Intel i430TX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7120, "Intel i810", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7122, "Intel i810", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7124, "Intel i810E", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7180, "Intel i440[LE]X", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7190, "Intel i440BX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7192, "Intel i440BX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x71A0, "Intel i440GX", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
- { 0x8086, 0x71A2, "Intel i440GX", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
- { 0x8086, 0x84C5, "Intel i450GX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x2540, "Intel E7500", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x254C, "Intel E7501", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x255d, "Intel E7205", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x3592, "Intel E7320", 0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_iE7520 },
- { 0x8086, 0x2588, "Intel E7221", 1, poll_fsb_i925, poll_timings_i925, setup_i925, poll_iE7221 },
- { 0x8086, 0x3590, "Intel E7520", 0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing },
- { 0x8086, 0x2600, "Intel E8500", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x2570, "Intel i848/i865", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing },
- { 0x8086, 0x2578, "Intel i875P", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_i875 },
- { 0x8086, 0x2550, "Intel E7505", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x3580, "Intel ", 0, poll_fsb_i855, poll_timings_i852, setup_nothing, poll_nothing },
- { 0x8086, 0x3340, "Intel i855PM", 0, poll_fsb_i855, poll_timings_i855, setup_nothing, poll_nothing },
- { 0x8086, 0x2580, "Intel i915P/G", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x2590, "Intel i915PM/GM", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x2584, "Intel i925X/XE", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_iE7221 },
- { 0x8086, 0x2770, "Intel i945P/G", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x27A0, "Intel i945GM/PM", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x27AC, "Intel i945GME", 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, 0x2970, "Intel i946PL/GZ", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
- { 0x8086, 0x2990, "Intel Q963/Q965", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
- { 0x8086, 0x29A0, "Intel P965/G965", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
- { 0x8086, 0x2A00, "Intel GM965/GL960", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing},
- { 0x8086, 0x2A10, "Intel GME965/GLE960",0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing},
- { 0x8086, 0x2A40, "Intel PM/GM45/47", 0, poll_fsb_im965, poll_timings_im965, setup_p35, 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, 0x29F0, "Intel 3200/3210", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
- { 0x8086, 0x2E10, "Intel Q45/Q43", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
- { 0x8086, 0x2E20, "Intel P45/G45", 0, poll_fsb_i965, poll_timings_p35, setup_p35, poll_nothing},
- { 0x8086, 0x2E30, "Intel G41", 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 5000X", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
- { 0x8086, 0x25D0, "Intel 5000Z", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
- { 0x8086, 0x5020, "Intel EP80579", 0, poll_fsb_p4, poll_timings_EP80579, setup_nothing, poll_nothing },
- { 0x8086, 0x8100, "Intel US15W", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
- { 0x8086, 0x8101, "Intel UL11L/US15L", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
-
- /* Integrated Memory Controllers */
- { 0xFFFF, 0x0001, "Core IMC", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
- { 0xFFFF, 0x0002, "Core IMC 32nm", 0, poll_fsb_nhm32, poll_timings_nhm, setup_nhm32, poll_nothing},
- { 0xFFFF, 0x0003, "Core IMC 32nm", 0, poll_fsb_wmr, poll_timings_wmr, setup_wmr, poll_nothing},
- { 0xFFFF, 0x0004, "SNB IMC 32nm", 0, poll_fsb_snb, poll_timings_snb, setup_wmr, poll_nothing},
- { 0xFFFF, 0x0100, "AMD K8 IMC", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0xFFFF, 0x0101, "AMD K10 IMC", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing },
- { 0xFFFF, 0x0102, "AMD APU IMC", 0, poll_fsb_k14, poll_timings_k14, setup_nothing, poll_nothing },
-
- /* Fail Safe */
- { 0xFFFF, 0xFFFF, "", 0, poll_fsb_failsafe, poll_timings_nothing, setup_nothing, poll_nothing }
+ { 0x8086, 0x1130, "Intel i815","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x122d, "Intel i430FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x1235, "Intel i430MX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x1237, "Intel i440FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x1250, "Intel i430HX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x1A21, "Intel i840","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i840, poll_nothing },
+ { 0x8086, 0x1A30, "Intel i845","SDR/DDR", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing },
+ { 0x8086, 0x2560, "Intel i845E/G/PE/GE","", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing },
+ { 0x8086, 0x2500, "Intel i820","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i820, poll_nothing },
+ { 0x8086, 0x2530, "Intel i850","RDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_i850, poll_nothing },
+ { 0x8086, 0x2531, "Intel i860","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i860, poll_nothing },
+ { 0x8086, 0x7030, "Intel i430VX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7100, "Intel i430TX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7120, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7122, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7124, "Intel i810E","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7180, "Intel i440[LE]X","SDRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7190, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x7192, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x71A0, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing },
+ { 0x8086, 0x71A2, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing },
+ { 0x8086, 0x84C5, "Intel i450GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x2540, "Intel E7500","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing },
+ { 0x8086, 0x254C, "Intel E7501","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing },
+ { 0x8086, 0x255d, "Intel E7205","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing },
+ { 0x8086, 0x3592, "Intel E7320","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing },
+ { 0x8086, 0x2588, "Intel E7221","DDR-SDRAM",0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x3590, "Intel E7520","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing },
+ { 0x8086, 0x2600, "Intel E8500","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
+ { 0x8086, 0x2570, "Intel i848/i865","", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing },
+ { 0x8086, 0x2578, "Intel i875P","", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing },
+ { 0x8086, 0x2550, "Intel E7505","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing },
+ { 0x8086, 0x3580, "Intel i852P/i855G","", 0, poll_fsb_i855, poll_timings_i852, setup_nothing, poll_nothing },
+ { 0x8086, 0x3340, "Intel i855PM","", 0, poll_fsb_i855, poll_timings_i855, setup_nothing, poll_nothing },
+ { 0x8086, 0x2580, "Intel i915P/G","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x2590, "Intel i915PM/GM","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x2584, "Intel i925X/XE","", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x2770, "Intel i945P/G","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x27A0, "Intel i945GM/PM","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
+ { 0x8086, 0x27AC, "Intel i945GME","", 0, poll_fsb_i945gme, 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, 0x2970, "Intel i946PL/GZ","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
+ { 0x8086, 0x2990, "Intel Q963/Q965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
+ { 0x8086, 0x29A0, "Intel P965/G965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing},
+ { 0x8086, 0x2A00, "Intel GM965/GL960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing},
+ { 0x8086, 0x2A10, "Intel GME965/GLE960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing},
+ { 0x8086, 0x2A40, "Intel PM/GM45/47","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing},
+ { 0x8086, 0x29B0, "Intel Q35","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29C0, "Intel P35/G33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29D0, "Intel Q33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29E0, "Intel X38/X48","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x29F0, "Intel 3200/3210","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x2E10, "Intel Q45/Q43","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x2E20, "Intel P45/G45","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0x8086, 0x2E30, "Intel G41","", 0, poll_fsb_p35, 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 5000X","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x25D0, "Intel 5000Z","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing},
+ { 0x8086, 0x5020, "Intel EP80579","", 0, poll_fsb_p4, poll_timings_EP80579, setup_nothing, poll_nothing },
+ { 0x8086, 0x8100, "Intel US15W","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
+ { 0x8086, 0x8101, "Intel UL11L/US15L","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing},
+
+ /* INTEL IMC (Integrated Memory Controllers) */
+ { 0xFFFF, 0x0001, "Core IMC","", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing},
+ { 0xFFFF, 0x0002, "Core IMC","", 0, poll_fsb_nhm32, poll_timings_nhm, setup_nhm32, poll_nothing},
+ { 0xFFFF, 0x0003, "Core IMC","", 0, poll_fsb_wmr, poll_timings_wmr, setup_wmr, poll_nothing},
+ { 0xFFFF, 0x0004, "SNB IMC","", 0, poll_fsb_snb, poll_timings_snb, setup_wmr, poll_nothing},
+ { 0xFFFF, 0x0005, "SNB-E IMC","", 0, poll_fsb_snbe, poll_timings_snbe, setup_wmr, poll_nothing},
+ { 0xFFFF, 0x0006, "IVB IMC","", 0, poll_fsb_ivb, poll_timings_snb, setup_wmr, poll_nothing},
+ { 0xFFFF, 0x0007, "HSW IMC","", 0, poll_fsb_ivb, poll_timings_hsw, setup_wmr, poll_nothing},
+ { 0xFFFF, 0x0008, "PineView IMC","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing},
+ { 0xFFFF, 0x0009, "CedarTrail IMC","", 0, poll_fsb_ct, poll_timings_ct, setup_nothing, poll_nothing},
+
+ /* AMD IMC (Integrated Memory Controllers) */
+ { 0xFFFF, 0x0100, "AMD K8 IMC","", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_nothing },
+ { 0xFFFF, 0x0101, "AMD K10 IMC","", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing },
+ { 0xFFFF, 0x0102, "AMD K12 IMC","", 0, poll_fsb_k12, poll_timings_k12, setup_apu, poll_nothing },
+ { 0xFFFF, 0x0103, "AMD K14 IMC","", 0, poll_fsb_k14, poll_timings_k14, setup_apu, poll_nothing },
+ { 0xFFFF, 0x0104, "AMD K15 IMC","", 0, poll_fsb_k15, poll_timings_k15, setup_apu, poll_nothing },
+ { 0xFFFF, 0x0105, "AMD K16 IMC","", 0, poll_fsb_k16, poll_timings_k16, setup_apu, poll_nothing }
};
static void print_memory_controller(void)
{
- /* Print memory controller info */
-
- int d;
- char *name;
+ /* Print memory controller info */
if (ctrl.index == 0) {
return;
}
- /* Print the controller name */
- name = controllers[ctrl.index].name;
- col = 10;
- cprint(LINE_CPU+5, col, name);
- /* Now figure out how much I just printed */
- while(name[col - 10] != '\0') {
- col++;
- }
/* Now print the memory controller capabilities */
+ /*
cprint(LINE_CPU+5, col, " "); col++;
if (ctrl.cap == ECC_UNKNOWN) {
return;
@@ -3642,15 +4078,16 @@ static void print_memory_controller(void)
cprint(LINE_CPU+5, col +7, on?"+ ":"- ");
col += 9;
}
-
+ */
+
+
+
/* Print advanced caracteristics */
col2 = 0;
- d = get_key();
- /* if F1 is pressed, disable advanced detection */
- if (d != 0x3B) {
+
controllers[ctrl.index].poll_fsb();
controllers[ctrl.index].poll_timings();
- }
+
}
@@ -3658,7 +4095,6 @@ void find_controller(void)
{
unsigned long vendor;
unsigned long device;
- extern struct cpu_ident cpu_id;
int i;
int result;
result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_VENDOR_ID, 2, &vendor);
@@ -3666,10 +4102,12 @@ void find_controller(void)
// Detect IMC by CPUID
if(imc_type) { vendor = 0xFFFF; device = imc_type; }
- if(fail_safe) { vendor = 0xFFFF; device = 0xFFFF; }
-
+ if(v->fail_safe & 1) { vendor = 0xFFFF; device = 0xFFFF; }
+
+ //hprint(11,0,vendor); hprint(11,10,device);
+
ctrl.index = 0;
- if (result == 0) {
+ if (result == 0 || imc_type) {
for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) {
if ((controllers[i].vendor == vendor) && (controllers[i].device == device)) {
ctrl.index = i;
@@ -3682,8 +4120,10 @@ void find_controller(void)
/* Don't enable ECC polling by default unless it has
* been well tested.
*/
- set_ecc_polling(-1);
+ //set_ecc_polling(-1);
print_memory_controller();
+
+ if(imc_type) { print_dmi_startup_info(); }
}
@@ -3694,6 +4134,7 @@ void poll_errors(void)
}
}
+/*
void set_ecc_polling(int val)
{
int tested = controllers[ctrl.index].tested;
@@ -3708,5 +4149,5 @@ void set_ecc_polling(int val)
cprint(LINE_INFO, COL_ECC, "off");
}
}
-
+*/
diff --git a/controller.h b/controller.h
index ff5cb06..da64ef1 100644
--- a/controller.h
+++ b/controller.h
@@ -1,8 +1,23 @@
#ifndef MEMTEST_CONTROLLER_H
#define MEMTEST_CONTROLLER_H
+struct pci_memory_controller {
+ unsigned vendor;
+ unsigned device;
+ char *name;
+ char *ram_type;
+ int tested;
+ void (*poll_fsb)(void);
+ void (*poll_timings)(void);
+ void (*setup_ecc)(void);
+ void (*poll_errors)(void);
+};
+
void find_controller(void);
void poll_errors(void);
void set_ecc_polling(int val);
+void coretemp(void);
+extern struct pci_memory_controller controllers[];
+
#endif /* MEMTEST_CONTROLLER_H */
diff --git a/cpuid.c b/cpuid.c
index 9a0843b..4c25ede 100644
--- a/cpuid.c
+++ b/cpuid.c
@@ -4,255 +4,84 @@
* Implements CPUID querying functions
*
*/
+#include "stdin.h"
#include "cpuid.h"
-cpuid_t cpuid_data0;
-cpuid_t cpuid_data80;
+struct cpu_ident cpu_id;
-unsigned num_logical_cpus = 1; // number of logical cpus per physical package
-unsigned num_cores_per_package = 1; // number of cores in each physical cpu package
-unsigned num_hyper_threads_per_core = 1; // number of hyper-threads per core
-
-void
-cpuid_get(unsigned n, cpuid_t *data)
-{
- data->eax = n;
- GET_CPUID(data->eax, data->ebx, data->ecx, data->edx);
-}
-
-
-/* cpuid_get_vendor_string ---
- *
- * This function gets the vendor string from the processor's cpuid instruction
- * and passes it back to the caller in an easy to use structure.
- */
-cpuid_vendor_string_t
-cpuid_get_vendor_string(void)
-{
- static cpuid_vendor_string_t v;
-
- /* Note: the string gets passed in EBX-EDX-ECX, not the intuitive order. */
- v.uint32_array[0] = cpuid_data0.ebx;
- v.uint32_array[1] = cpuid_data0.edx;
- v.uint32_array[2] = cpuid_data0.ecx;
- v.char_array[CPUID_VENDOR_STR_LENGTH-1] = '\0';
- return v;
-}
-
-
-/* cpuid_get_version ---
- *
- * This function reads the processors version information using CPUID and puts
- * it into a union for easy use by the caller.
- */
-cpuid_version_t
-cpuid_get_version(void)
-{
- cpuid_version_t v;
- uint32_t junkEBX = 0, junkECX = 0, junkEDX = 0;
- v.flat = 0x1;
- GET_CPUID(v.flat, junkEBX, junkECX, junkEDX);
- return v;
-}
-
-
-cpuid_feature_flags_t
-cpuid_get_feature_flags(void)
-{
- cpuid_feature_flags_t f;
- uint32_t junkEAX = 0x1, junkEBX = 0;
- GET_CPUID(junkEAX, junkEBX, f.uint32_array[1], f.uint32_array[0]);
- return f;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * cpuid_get_ext_feature_flags --
- *
- * Passes back the caller the extended feature flags supported by
- * this CPU. This can be used, among other things, to determine if the
- * processor supports long mode.
- *
- * Results:
- * Returns TRUE if the processor supports the extended feature flags
- * CPUID node, and FALSE otherwise.
- *
- * Side effects:
- * Calls CPUID a couple of times.
- *
- *-----------------------------------------------------------------------------
- */
-
-bool
-cpuid_get_ext_feature_flags(cpuid_ext_feature_flags_t *f) // OUT: Flags for this CPU
-{
- uint32_t eax, ebx, ecx;
-
- if (cpuid_data80.eax < 0x80000001) {
- // Extended feature flags not supported on this CPU
- return FALSE;
- }
- eax = CPUID_EXTENDED_FEATURE;
- GET_CPUID(eax, ebx, ecx, f->flat);
- return TRUE;
-}
-
-#define CHAR_TO_INT(a,b,c,d) ((a) + (b) * 0x100 + (c) * 0x10000 + (d) * 0x1000000)
-
-bool
-cpuid_is_vendor_amd(void)
-{
- return cpuid_data0.ebx == CHAR_TO_INT('A', 'u', 't', 'h')
- && cpuid_data0.edx == CHAR_TO_INT('e', 'n', 't', 'i')
- && cpuid_data0.ecx == CHAR_TO_INT('c', 'A', 'M', 'D');
-}
-
-
-bool
-cpuid_is_vendor_intel(void)
-{
- return cpuid_data0.ebx == CHAR_TO_INT('G', 'e', 'n', 'u')
- && cpuid_data0.edx == CHAR_TO_INT('i', 'n', 'e', 'I')
- && cpuid_data0.ecx == CHAR_TO_INT('n', 't', 'e', 'l');
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * cpuid_is_family_p4 --
- *
- * Returns TRUE if the processor we're running on is an Intel processor
- * of the P4 family.
- *
- * Results:
- * The obvious.
- *
- *-----------------------------------------------------------------------------
- */
-
-bool
-cpuid_is_family_p4(void)
-{
- cpuid_version_t v = cpuid_get_version();
-
- return cpuid_is_vendor_intel() && v.bits.family == CPUID_FAMILY_EXTENDED &&
- v.bits.extendedFamily == CPUID_EXTENDED_FAMILY_PENTIUM4;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * cpuid_is_family_p6 --
- *
- * Returns TRUE if the processor we're running on belongs to the P6 family.
- *
- * Results:
- * The obvious.
- *
- *-----------------------------------------------------------------------------
- */
-
-bool
-cpuid_is_family_p6(void)
-{
- cpuid_version_t v = cpuid_get_version();
-
- return cpuid_is_vendor_intel() && v.bits.family == CPUID_FAMILY_P6;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * cpuid_is_family_opteron --
- *
- * Returns TRUE if the processor we're running on belongs to the
- * Opteron family.
- *
- *-----------------------------------------------------------------------------
- */
-
-bool
-cpuid_is_family_opteron(void)
+void get_cpuid()
{
- cpuid_version_t v = cpuid_get_version();
- return cpuid_is_vendor_amd() && CPUID_FAMILY_IS_OPTERON(v.flat);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * cpuid_init --
- *
- * Executes CPUID and caches values in cpuid_data0 abd cpuid_data80.
- *
- *-----------------------------------------------------------------------------
- */
-void
-cpuid_init(void)
-{
- //bool htt = FALSE;
- cpuid_t id1;
-
- /* First get the basic cpuid information on what the
- * type of the processor is , i.e intel or amd etc
- * and how much of extra cpuid information is available
- * with the processor
- */
- cpuid_data0.eax = 0;
- GET_CPUID(cpuid_data0.eax, cpuid_data0.ebx,
- cpuid_data0.ecx, cpuid_data0.edx);
-
-
- /* Find out if hyper-threading is available and there is more than one
- * logical processor. See section 7.6.3 in Intel IA-32 volume III.
- */
- cpuid_get(1, &id1);
+ unsigned int *v, dummy[3];
+ char *p, *q;
+
+ /* Get max std cpuid & vendor ID */
+ cpuid(0x0, &cpu_id.max_cpuid, &cpu_id.vend_id.uint32_array[0],
+ &cpu_id.vend_id.uint32_array[2], &cpu_id.vend_id.uint32_array[1]);
+ cpu_id.vend_id.char_array[11] = 0;
+
+ /* Get processor family information & feature flags */
+ if (cpu_id.max_cpuid >= 1) {
+ cpuid(0x00000001, &cpu_id.vers.flat, &cpu_id.info.flat,
+ &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]);
+ }
+
+ /* Get the digital thermal sensor & power management status bits */
+ if(cpu_id.max_cpuid >= 6) {
+ cpuid(0x00000006, &cpu_id.dts_pmp, &dummy[0], &dummy[1], &dummy[2]);
+ }
+
+ /* Get the max extended cpuid */
+ cpuid(0x80000000, &cpu_id.max_xcpuid, &dummy[0], &dummy[1], &dummy[2]);
+
+ /* Get extended feature flags, only save EDX */
+ if (cpu_id.max_xcpuid >= 0x80000001) {
+ cpuid(0x80000001, &dummy[0], &dummy[1],
+ &dummy[2], &cpu_id.fid.uint32_array[2]);
+ }
+
+ /* Get the brand ID */
+ if (cpu_id.max_xcpuid >= 0x80000004) {
+ v = (unsigned int *)&cpu_id.brand_id;
+ cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+ cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+ cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+ cpu_id.brand_id.char_array[47] = 0;
+ }
+ /*
+ * Intel chips right-justify this string for some dumb reason;
+ * undo that brain damage:
+ */
+ p = q = &cpu_id.brand_id.char_array[0];
+ while (*p == ' ')
+ p++;
+ if (p != q) {
+ while (*p)
+ *q++ = *p++;
+ while (q <= &cpu_id.brand_id.char_array[48])
+ *q++ = '\0'; /* Zero-pad the rest */
+ }
+
+ /* Get cache information */
+ switch(cpu_id.vend_id.char_array[0]) {
+ case 'A':
+ /* AMD Processors */
+ /* The cache information is only in ecx and edx so only save
+ * those registers */
+ if (cpu_id.max_xcpuid >= 0x80000005) {
+ cpuid(0x80000005, &dummy[0], &dummy[1],
+ &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]);
+ }
+ if (cpu_id.max_xcpuid >= 0x80000006) {
+ cpuid(0x80000006, &dummy[0], &dummy[1],
+ &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]);
+ }
+ break;
+ case 'G':
+ /* Intel Processors, Need to do this in init.c */
+ break;
+ }
+
+ /* Turn off mon bit since monitor based spin wait may not be reliable */
+ cpu_id.fid.bits.mon = 0;
- if (cpuid_is_vendor_intel()) {
- if (cpuid_is_family_p6()) {
- // Extended CPUID features not supported on PIII
- return;
- }
- if (cpuid_is_family_p4()) {
- /*
- * Multi-core processors have the HT feature bit set (even if they
- * don't support HT).
- * The number of HT is the total number, not per-core number.
- * The number of cores is off by 1, i.e. single-core reports 0.
- */
- //htt = id1.edx & CPUID_FEATURE_COMMON_ID1EDX_HT;
- if (id1.edx & CPUID_FEATURE_COMMON_ID1EDX_HT) {
- num_hyper_threads_per_core = (id1.ebx >> 16) & 0xff;
- if (cpuid_max_func() >= 4) {
- cpuid_t id4;
- cpuid_get(4, &id4);
- num_cores_per_package = ((id4.eax >> 26) & 0x3f) + 1;
- num_hyper_threads_per_core /= num_cores_per_package;
- }
- }
- }
- } else if (cpuid_is_vendor_amd()) {
- cpuid_data80.eax = 0x80000000;
- GET_CPUID(cpuid_data80.eax, cpuid_data80.ebx,
- cpuid_data80.ecx, cpuid_data80.edx);
- if (cpuid_max_ext_func() >= 0x80000008) {
- /* Number of cores is reported in extended function 0x80000008
- * For legacy multi-core support, AMD CPUs report the number of
- * cores as hyper-threads. Adjust the numbers to reflect that there
- * are no threads.
- */
- cpuid_t id88;
- cpuid_get(0x80000008, &id88);
- num_cores_per_package = id88.ecx & 0xff;
- num_hyper_threads_per_core = 1;
- }
- } else {
- /* Unknown cpu type. we use the defaults */
- }
}
diff --git a/cpuid.h b/cpuid.h
index c35c2ba..caace1e 100644
--- a/cpuid.h
+++ b/cpuid.h
@@ -1,83 +1,76 @@
/*
* cpuid.h --
- *
* contains the data structures required for CPUID
* implementation.
- *
*/
-#ifndef _CPUID_H_
-#define _CPUID_H_
-#include "stdint.h"
-#include "defs.h"
-#include "smp.h"
-
-#define CPUID_EXTENDED_BASE 0x80000000
-#define CPUID_EXTENDED_FEATURE 0x80000001
-#define CPUID_EXTENDED_BRAND1 0x80000002
-#define CPUID_EXTENDED_BRAND2 0x80000003
-#define CPUID_EXTENDED_BRAND3 0x80000004
-
#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */
#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */
#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
-#define CPUID_FAMILY(_eax) (((_eax) >> 8) & 0xf)
-/* Intel CPU Family */
-#define CPUID_FAMILY_486 4
-#define CPUID_FAMILY_P5 5
-#define CPUID_FAMILY_P6 6
-#define CPUID_FAMILY_EXTENDED 15
-
-#define CPUID_EXTENDED_FAMILY(_eax) (((_eax) >> 20) & 0xff)
-#define CPUID_EXTENDED_FAMILY_PENTIUM4 0
-#define CPUID_EXTENDED_FAMILY_OPTERON 0
-
-
-#define CPUID_FAMILY_IS_OPTERON(_eax) \
- (CPUID_FAMILY(_eax) == CPUID_FAMILY_EXTENDED && \
- CPUID_EXTENDED_FAMILY(_eax) == CPUID_EXTENDED_FAMILY_OPTERON)
-#define CPUID_FEATURE_COMMON_ID1EDX_HT 0x10000000 /* 28 */
+extern struct cpu_ident cpu_id;
-
-typedef struct {
- uint32_t eax;
- uint32_t ebx;
- uint32_t ecx;
- uint32_t edx;
-} cpuid_t;
-
-/* cached CPUID data for CPUID(0) and CPUID(0x80000000) */
-extern cpuid_t cpuid_data0;
-extern cpuid_t cpuid_data80;
-
-
-static inline unsigned
-cpuid_max_func()
+static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
- return cpuid_data0.eax;
+ /* ecx is often an input as well as an output. */
+ asm volatile("\t"
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (*eax),
+ "=D" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx));
}
+static inline void cpuid(unsigned int op,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = 0;
+ __cpuid(eax, ebx, ecx, edx);
+}
-static inline unsigned
-cpuid_max_ext_func()
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(unsigned int op, int count,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
- return cpuid_data80.eax;
+ *eax = op;
+ *ecx = count;
+ __cpuid(eax, ebx, ecx, edx);
}
+/* Typedef for storing the Cache Information */
+typedef union {
+ unsigned char ch[48];
+ uint32_t uint[12];
+ struct {
+ uint32_t fill1:24; /* Bit 0 */
+ uint32_t l1_i_sz:8;
+ uint32_t fill2:24;
+ uint32_t l1_d_sz:8;
+ uint32_t fill3:16;
+ uint32_t l2_sz:16;
+ uint32_t fill4:18;
+ uint32_t l3_sz:14;
+ uint32_t fill5[8];
+ } amd;
+} cpuid_cache_info_t;
/* Typedef for storing the CPUID Vendor String */
typedef union {
/* Note: the extra byte in the char array is for '\0'. */
- char char_array[CPUID_VENDOR_STR_LENGTH];
+ char char_array[CPUID_VENDOR_STR_LENGTH];
uint32_t uint32_array[CPUID_VENDOR_LENGTH];
} cpuid_vendor_string_t;
/* Typedef for storing the CPUID Brand String */
typedef union {
/* Note: the extra byte in the char array is for '\0'. */
- char char_array[CPUID_BRAND_STR_LENGTH];
+ char char_array[CPUID_BRAND_STR_LENGTH];
uint32_t uint32_array[CPUID_BRAND_LENGTH];
} cpuid_brand_string_t;
@@ -109,20 +102,27 @@ typedef union {
/* Typedef for storing CPUID Feature flags */
typedef union {
- uint64_t flat;
- uint32_t uint32_array[2];
+ uint32_t flat;
+ struct {
+ uint32_t :1;
+ } bits;
+} cpuid_custom_features;
+
+/* Typedef for storing CPUID Feature flags */
+typedef union {
+ uint32_t uint32_array[3];
struct {
- uint32_t fpu:1; /* Bit 0 */
+ uint32_t fpu:1; /* EDX feature flags, bit 0 */
uint32_t vme:1;
uint32_t de:1;
uint32_t pse:1;
- uint32_t tsc:1;
+ uint32_t rdtsc:1;
uint32_t msr:1;
uint32_t pae:1;
uint32_t mce:1;
uint32_t cx8:1;
uint32_t apic:1;
- uint32_t reserved10:1;
+ uint32_t bit10:1;
uint32_t sep:1;
uint32_t mtrr:1;
uint32_t pge:1;
@@ -132,7 +132,7 @@ typedef union {
uint32_t pse36:1;
uint32_t psn:1;
uint32_t cflush:1;
- uint32_t reserved20:1;
+ uint32_t bit20:1;
uint32_t ds:1;
uint32_t acpi:1;
uint32_t mmx:1;
@@ -142,76 +142,55 @@ typedef union {
uint32_t ss:1;
uint32_t htt:1;
uint32_t tm:1;
- uint32_t reserved30:1;
- uint32_t pbe:1; /* Bit 31 */
- uint32_t sse3:1; /* Bit 32 */
- uint32_t reserved3433:2;
- uint32_t monitor:1;
+ uint32_t bit30:1;
+ uint32_t pbe:1; /* EDX feature flags, bit 31 */
+ uint32_t sse3:1; /* ECX feature flags, bit 0 */
+ uint32_t mulq:1;
+ uint32_t bit2:1;
+ uint32_t mon:1;
uint32_t dscpl:1;
- uint32_t reserved3937:3;
- uint32_t tm2:1;
- uint32_t reserved41:1;
- uint32_t cnxtid:1;
- uint32_t reserved4443:2;
- uint32_t cmpxchg16b:1;
- uint32_t reserved6346:18; /* Bit 63 */
+ uint32_t vmx:1;
+ uint32_t smx:1;
+ uint32_t eist:1;
+ uint32_t tm2:1;
+ uint32_t bits_9_31:23;
+ uint32_t bits0_28:29; /* EDX extended feature flags, bit 0 */
+ uint32_t lm:1; /* Long Mode */
+ uint32_t bits_30_31:2; /* EDX extended feature flags, bit 32 */
} bits;
} cpuid_feature_flags_t;
-/* Feature flags returned by extended CPUID node function 8000_0001. */
-typedef union {
- uint64_t flat;
- uint32_t uint32_array[2];
- struct {
- uint32_t fpu:1; /* Bit 0 */
- uint32_t vme:1;
- uint32_t de:1;
- uint32_t pse:1;
- uint32_t tsc:1;
- uint32_t msr:1;
- uint32_t pae:1;
- uint32_t mce:1;
- uint32_t cx8:1;
- uint32_t apic:1;
- uint32_t reserved10:1;
- uint32_t sep:1;
- uint32_t mtrr:1;
- uint32_t pge:1;
- uint32_t mca:1;
- uint32_t cmov:1;
- uint32_t pat:1;
- uint32_t pse36:1;
- uint32_t reserved1918:2;
- uint32_t nx:1;
- uint32_t reserved21:1;
- uint32_t mmxamd:1;
- uint32_t mmx:1;
- uint32_t fxsr:1;
- uint32_t ffxsr:1;
- uint32_t reserved26:1;
- uint32_t rdtscp:1;
- uint32_t reserved28:1;
- uint32_t lm:1;
- uint32_t threedeenowext:1;
- uint32_t threedeenow:1; /* Bit 31 */
- uint32_t lahf:1; /* Bit 32 */
- uint32_t cmplegacy:1;
- uint32_t reserved3534:2;
- uint32_t cr8avail:1;
- uint32_t reserved6337:27; /* Bit 63 */
- } bits;
-} cpuid_ext_feature_flags_t;
-
-void cpuid_get(unsigned n, cpuid_t *data);
-cpuid_vendor_string_t cpuid_get_vendor_string(void);
-cpuid_version_t cpuid_get_version(void);
-cpuid_feature_flags_t cpuid_get_feature_flags(void);
-bool cpuid_get_ext_feature_flags(cpuid_ext_feature_flags_t *f);
-bool cpuid_is_vendor_amd(void);
-bool cpuid_is_vendor_intel(void);
-bool cpuid_is_family_p6(void);
-bool cpuid_is_family_p4(void);
-bool cpuid_is_family_opteron(void);
-void cpuid_init(void);
-
-#endif
+/* An overall structure to cache all of the CPUID information */
+struct cpu_ident {
+ uint32_t max_cpuid;
+ uint32_t max_xcpuid;
+ uint32_t dts_pmp;
+ cpuid_version_t vers;
+ cpuid_proc_info_t info;
+ cpuid_feature_flags_t fid;
+ cpuid_vendor_string_t vend_id;
+ cpuid_brand_string_t brand_id;
+ cpuid_cache_info_t cache_info;
+ cpuid_custom_features custom;
+};
+
+struct cpuid4_eax {
+ uint32_t ctype:5;
+ uint32_t level:3;
+ uint32_t is_self_initializing:1;
+ uint32_t is_fully_associative:1;
+ uint32_t reserved:4;
+ uint32_t num_threads_sharing:12;
+ uint32_t num_cores_on_die:6;
+};
+
+struct cpuid4_ebx {
+ uint32_t coherency_line_size:12;
+ uint32_t physical_line_partition:10;
+ uint32_t ways_of_associativity:10;
+};
+
+struct cpuid4_ecx {
+ uint32_t number_of_sets:32;
+};
+
diff --git a/defs.h b/defs.h
index e1a3350..3891699 100644
--- a/defs.h
+++ b/defs.h
@@ -1,18 +1,19 @@
-/* defs.h - MemTest-86 assembler/compiler definitions
+/* defs.h - MemTest-86 Version 3.3
+ * assembler/compiler definitions
*
* Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- */
+ * By Chris Brady
+ */
#define SETUPSECS 4 /* Number of setup sectors */
/*
* Caution!! There is magic in the build process. Read
- * README.build-process before you change anything.
+ * README.build-process before you change anything.
* Unlike earlier versions all of the settings are in defs.h
* so the build process should be more robust.
*/
-#define LOW_TEST_ADR 0x00002000 /* Final adrs for test code */
+#define LOW_TEST_ADR 0x00010000 /* Final adrs for test code */
#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 0f05822..1f11008 100644
--- a/dmi.c
+++ b/dmi.c
@@ -40,6 +40,43 @@ struct tstruct_header{
uint16_t handle;
} __attribute__((packed));
+struct system_map {
+ struct tstruct_header header;
+ uint8_t manufacturer;
+ uint8_t productname;
+ uint8_t version;
+ uint8_t serialnumber;
+ uint8_t uuidbytes[16];
+ uint8_t wut;
+} __attribute__((packed));
+
+struct cpu_map {
+ struct tstruct_header header;
+ uint8_t cpu_socket;
+ uint8_t cpu_type;
+ uint8_t cpu_family;
+ uint8_t cpu_manufacturer;
+ uint32_t cpu_id;
+ uint8_t cpu_version;
+ uint8_t cpu_voltage;
+ uint16_t ext_clock;
+ uint16_t max_speed;
+ uint16_t cur_speed;
+ uint8_t cpu_status;
+ uint8_t cpu_upgrade;
+ uint16_t l1_handle;
+ uint16_t l2_handle;
+ uint16_t l3_handle;
+ uint8_t cpu_serial;
+ uint8_t cpu_asset_tag;
+ uint8_t cpu_part_number;
+ uint8_t core_count;
+ uint8_t core_enabled;
+ uint8_t thread_count;
+ uint16_t cpu_specs;
+ uint16_t cpu_family_2;
+} __attribute__((packed));
+
struct mem_dev {
struct tstruct_header header;
uint16_t pma_handle;
@@ -91,7 +128,7 @@ static char *form_factors[] = {
static char *memory_types[] = {
"?",
- "Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
+ "Other", "????", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
"ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM",
"SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB", "RSVD",
"RSVD","RSVD","DDR3","FBD2"
@@ -101,17 +138,12 @@ static char *memory_types[] = {
struct mem_dev * mem_devs[MAX_DMI_MEMDEVS];
int mem_devs_count=0;
struct md_map * md_maps[MAX_DMI_MEMDEVS];
+struct system_map * dmi_system_info;
+struct cpu_map * dmi_cpu_info;
int md_maps_count=0;
int dmi_err_cnts[MAX_DMI_MEMDEVS];
short dmi_initialized=0;
-int strlen(char * string){
- int i=0;
- while(*string++){i++;};
- return i;
-}
-
-
char * get_tstruct_string(struct tstruct_header *header, int n){
if(n<1)
return 0;
@@ -172,13 +204,28 @@ int open_dmi(void){
//look at all structs
while(dmi < table_start + eps->tablelength){
struct tstruct_header *header = (struct tstruct_header *)dmi;
+
if (header->type == 17)
- mem_devs[mem_devs_count++]=(struct mem_dev *)dmi;
+ mem_devs[mem_devs_count++] = (struct mem_dev *)dmi;
// Need fix (SMBIOS/DDR3)
if (header->type == 20 || header->type == 1)
- md_maps[md_maps_count++]=(struct md_map *)dmi;
+ md_maps[md_maps_count++] = (struct md_map *)dmi;
+
+ // MB_SPEC
+ if (header->type == 2)
+ {
+ dmi_system_info = (struct system_map *)dmi;
+ }
+
+ // CPU_SPEC
+ if (header->type == 4)
+ {
+ dmi_cpu_info = (struct cpu_map *)dmi;
+ }
+
dmi+=header->length;
+
while( ! (*dmi == 0 && *(dmi+1) == 0 ) )
dmi++;
dmi+=2;
@@ -197,6 +244,46 @@ void init_dmi(void){
dmi_initialized=1;
}
+void print_dmi_startup_info(void)
+{
+ char *string1;
+ char *string2;
+ char *string3;
+ int dmicol = 78;
+ int slenght;
+ int sl1, sl2, sl3;
+
+ if(!dmi_initialized) { init_dmi(); }
+
+ string1 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->manufacturer);
+ sl1 = strlen(string1);
+ string2 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->productname);
+ sl2 = strlen(string2);
+ string3 = get_tstruct_string(&dmi_cpu_info->header,dmi_cpu_info->cpu_socket);
+ sl3 = strlen(string3);
+
+ slenght = sl1 + sl2;
+ if(sl3 > 2) { slenght += sl3 + 4; } else { slenght++; }
+
+ if(sl1 && sl2)
+ {
+ //dmicol -= slenght; // right align
+ dmicol = 39 - slenght/2; // center align
+ cprint(LINE_DMI, dmicol, string1);
+ dmicol += sl1 + 1;
+ cprint(LINE_DMI, dmicol, string2);
+ dmicol += sl2 + 1;
+
+ if(sl3 > 2){
+ cprint(LINE_DMI, dmicol, "(");
+ dmicol++;
+ cprint(LINE_DMI, dmicol, string3);
+ dmicol += sl3;
+ cprint(LINE_DMI, dmicol, ")");
+ }
+ }
+}
+
void print_dmi_info(void){
int i,j,page;
char * string=0;
@@ -256,22 +343,30 @@ void print_dmi_info(void){
//print mappings
int mapped=0,of=0;
cprint(yof+1, POP2_X+6,"mapped to: ");
- for(j=0; j<md_maps_count; j++){
+ for(j=0; j<md_maps_count; j++)
+ {
if (mem_devs[i]->header.handle != md_maps[j]->md_handle)
continue;
if (mapped++){
cprint(yof+1, POP2_X+17+of, ",");
of++;
}
- hprint3(yof+1, POP2_X+17+of, md_maps[j]->start<<10, 12);
- of += 12;
+ hprint3(yof+1, POP2_X+17+of, md_maps[j]->start>>22, 4);
+ of += 4;
+ hprint3(yof+1, POP2_X+17+of, md_maps[j]->start<<10, 8);
+ of += 8;
cprint(yof+1, POP2_X+17+of, "-");
of++;
- hprint3(yof+1, POP2_X+17+of, md_maps[j]->end<<10, 12);
- of += 12;
+ hprint3(yof+1, POP2_X+17+of, md_maps[j]->end>>22, 4);
+ of += 4;
+ hprint3(yof+1, POP2_X+17+of, ((md_maps[j]->end+1)<<10) - 1, 8);
+ of += 8;
+ if(md_maps[j]->end == 0) { hprint3(yof+1, POP2_X+17+of-8,0,8); }
}
if (!mapped)
+ {
cprint(yof+1, POP2_X+17, "No mapping (Interleaved Device)");
+ }
}
diff --git a/dmi.h b/dmi.h
index a43a21f..c90fedd 100644
--- a/dmi.h
+++ b/dmi.h
@@ -3,4 +3,5 @@
int add_dmi_err(ulong adr);
void print_dmi_err(void);
void print_dmi_info(void);
+void print_dmi_startup_info(void);
#endif
diff --git a/elf.h b/elf.h
index 78b5e9f..72efaac 100644
--- a/elf.h
+++ b/elf.h
@@ -14,7 +14,7 @@
#define EM_NONE 0 /* No machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SUN SPARC */
-#define EM_386 3 /* Intel 80386+*/
+#define EM_386 3 /* Intel 80386+ */
#define EM_68K 4 /* Motorola m68k family */
#define EM_88K 5 /* Motorola m88k family */
#define EM_486 6 /* Perhaps disused */
@@ -61,7 +61,7 @@
#define EM_PDSP 63 /* Sony DSP Processor */
#define EM_FX66 66 /* Siemens FX66 microcontroller */
-#define EM_ST9PLUS 67 /* STMicroelectronics ST9+8/16 mc */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
@@ -145,8 +145,8 @@
#include "stdint.h"
/*
-* ELF definitions common to all 32-bit architectures.
-*/
+ * ELF definitions common to all 32-bit architectures.
+ */
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
@@ -167,8 +167,8 @@ typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
/*
-* ELF header.
-*/
+ * ELF header.
+ */
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
@@ -204,8 +204,8 @@ typedef struct {
} Elf64_Ehdr;
/*
-* Program header.
-*/
+ * Program header.
+ */
typedef struct {
Elf32_Word p_type; /* Entry type. */
Elf32_Off p_offset; /* File offset of contents. */
@@ -295,8 +295,8 @@ typedef struct
#define DT_PROCNUM 0x32 /* Most used by any processor */
/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
- Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
- approach. */
+ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
+ approach. */
#define DT_VALRNGLO 0x6ffffd00
#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
@@ -315,10 +315,10 @@ typedef struct
#define DT_VALNUM 12
/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
- Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
- If any adjustment is made to the ELF object after it has been
- built these entries will need to be adjusted. */
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
#define DT_ADDRRNGLO 0x6ffffe00
#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
@@ -333,7 +333,7 @@ typedef struct
#define DT_ADDRNUM 10
/* The versioning entry types. The next are defined as part of the
- GNU extension. */
+ GNU extension. */
#define DT_VERSYM 0x6ffffff0
#define DT_RELACOUNT 0x6ffffff9
@@ -351,7 +351,7 @@ typedef struct
#define DT_VERSIONTAGNUM 16
/* Sun added these machine-independent extensions in the "processor-specific"
- range. Be compatible. */
+ range. Be compatible. */
#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
#define DT_FILTER 0x7fffffff /* Shared object to get values from */
#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
@@ -365,7 +365,7 @@ typedef struct
#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
- entry in the dynamic section. */
+ entry in the dynamic section. */
#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
@@ -493,8 +493,8 @@ typedef struct
} Elf32_Rel;
/* I have seen two different definitions of the Elf64_Rel and
- Elf64_Rela structures, so we'll leave them out until Novell (or
- whoever) gets their act together. */
+ Elf64_Rela structures, so we'll leave them out until Novell (or
+ whoever) gets their act together. */
/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
typedef struct
@@ -523,11 +523,11 @@ typedef struct
#define ELF32_R_SYM(val) ((val) >> 8)
#define ELF32_R_TYPE(val) ((val) & 0xff)
-#define ELF32_R_INFO(sym, type) (((sym) << 8) +((type) & 0xff))
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
-#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) +(type))
+#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
/* Intel 80386 specific definitions. */
@@ -581,7 +581,8 @@ typedef struct
TLS block */
#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
-#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block *//* Keep this the last entry. */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* Keep this the last entry. */
#define R_386_NUM 38
#endif /* ASSEMBLY */
diff --git a/error.c b/error.c
index 5b63be0..4218d8c 100644
--- a/error.c
+++ b/error.c
@@ -1,42 +1,151 @@
-
-/* error.c - MemTest-86 Version 3.4
+/* error.c - MemTest-86 Version 4.1
*
* Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- * ----------------------------------------------------
- * MemTest86+ V4.00 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.canardpc.com - http://www.memtest.org
+ * By Chris Brady
*/
-
+#include "stddef.h"
+#include "stdint.h"
#include "test.h"
#include "config.h"
-#include <sys/io.h>
+#include "cpuid.h"
+#include "smp.h"
#include "dmi.h"
-#define NULL 0
+#include "controller.h"
-extern int test_ticks, nticks, beepmode;
-extern struct tseq tseq[];
extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
+extern int beepmode;
extern short dmi_initialized;
+extern struct cpu_ident cpu_id;
+extern struct barrier_s *barr;
+extern int test_ticks, nticks;
+extern struct tseq tseq[];
+extern volatile int test;
void poll_errors();
+extern int num_cpus;
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;
+
+ spin_lock(&barr->mutex);
+
+ 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
+
+ /* A sporadic bug exists in test #6, with SMP enabled, that
+ * reports false positives on < 65K-0.5MB range. I was
+ * not able to solve this. After investigations, it seems
+ * related to a BIOS issue similiar to the one solved by
+ * USB_WAR, but for MP Table.
+ */
+ /* Solved
+ if (test == 6 && (ulong)adr <= 0x07FFFF && num_cpus > 1)
+ {
+ cprint(6,78,"-"); // Debug
+ return;
+ }
+ */
+
+ common_err(adr, good, bad, xor, 0);
+ spin_unlock(&barr->mutex);
+}
+
+
+
+/*
+ * 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)
+{
+ spin_lock(&barr->mutex);
+ common_err(adr1, good, bad, (ulong)mask, 1);
+ spin_unlock(&barr->mutex);
+}
+
+/*
+ * 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)
+{
+ spin_lock(&barr->mutex);
+ common_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad, 0);
+ spin_unlock(&barr->mutex);
+}
+
+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[test].errors++;
+
+}
+
+static void print_err_counts(void)
+{
+ int i;
+ char *pp;
+
+ if ((v->ecount > 4096) && (v->ecount % 256 != 0)) return;
+
+ dprint(LINE_INFO, 72, v->ecount, 6, 0);
+/*
+ dprint(LINE_INFO, 56, 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;
+ int i, j, n, x, flag=0;
ulong page, offset;
int patnchg;
ulong mb;
update_err_counts();
- add_dmi_err((ulong)adr);
switch(v->printmode) {
case PRINTMODE_SUMMARY:
@@ -124,8 +233,6 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
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;){
@@ -141,7 +248,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
x += 10;
}
}
-
+
cprint(LINE_HEADER+0, 64, "Test Errors");
v->erri.hdr_flag++;
}
@@ -159,7 +266,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
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 & 0xFF)*10)/256, 1, 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;
@@ -167,7 +274,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
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 & 0xFF)*10)/256, 1, 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);
@@ -186,7 +293,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
}
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);
@@ -206,7 +313,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
if (v->erri.hdr_flag == 0) {
clear_scroll();
cprint(LINE_HEADER, 0,
-"Tst Pass Failing Address Good Bad Err-Bits Count Chan");
+"Tst Pass Failing Address Good Bad Err-Bits Count CPU");
cprint(LINE_HEADER+1, 0,
"--- ---- ----------------------- -------- -------- -------- ----- ----");
v->erri.hdr_flag++;
@@ -223,13 +330,13 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
offset = ((unsigned long)adr) & 0xFFF;
}
mb = page >> 8;
- dprint(v->msg_line, 0, v->test, 3, 0);
+ dprint(v->msg_line, 0, test+1, 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 & 0xFF)*10)/256, 1, 0);
+ dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0);
if (type == 3) {
/* ECC error */
@@ -245,6 +352,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
hprint(v->msg_line, 46, bad);
hprint(v->msg_line, 56, xor);
dprint(v->msg_line, 66, v->ecount, 5, 0);
+ dprint(v->msg_line, 74, smp_my_cpu_num(), 2,1);
v->erri.exor = xor;
}
v->erri.eadr = (ulong)adr;
@@ -257,7 +365,7 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
v->erri.hdr_flag++;
}
/* Do not do badram patterns from test 0 or 5 */
- if (v->test == 0 || v->test == 5) {
+ if (test == 0 || test == 5) {
return;
}
/* Only do patterns for data errors */
@@ -281,86 +389,6 @@ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
}
/*
- * 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 ecc error
*/
void print_ecc_err(unsigned long page, unsigned long offset,
@@ -380,7 +408,7 @@ void parity_err( unsigned long edi, unsigned long esi)
{
unsigned long addr;
- if (v->test == 5) {
+ if (test == 5) {
addr = esi;
} else {
addr = edi;
@@ -427,10 +455,33 @@ void printpatn (void)
/*
* Show progress by displaying elapsed time and update bar graphs
*/
-void do_tick(void)
+short spin_idx[MAX_CPUS];
+char spin[4] = {'|','/','-','\\'};
+
+void do_tick(int me)
{
- int i, n, pct;
- ulong h, l, t;
+ int i, j, pct;
+ ulong h, l, n, t;
+ extern int mstr_cpu;
+
+ if (++spin_idx[me] > 3) {
+ spin_idx[me] = 0;
+ }
+ cplace(8, me+7, spin[spin_idx[me]]);
+
+
+ /* Check for keyboard input */
+ if (me == mstr_cpu) {
+ check_input();
+ }
+ /* A barrier here holds the other CPUs until the configuration
+ * changes are done */
+ s_barrier();
+
+ /* Only the first selected CPU does the update */
+ if (me != mstr_cpu) {
+ return;
+ }
/* FIXME only print serial error messages from the tick handler */
if (v->ecount) {
@@ -448,30 +499,31 @@ void do_tick(void)
} else {
pct = 0;
}
-
- dprint(1, COL_MID+4, pct, 3, 0);
+ dprint(2, 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, "#");
+ cprint(2, COL_MID+9+v->tptr, "#");
v->tptr++;
}
if (v->pass_ticks) {
pct = 100*v->total_ticks/v->pass_ticks;
- if (pct > 100) { pct = 100; }
+ if (pct > 100) {
+ pct = 100;
+ }
} else {
pct = 0;
- }
- dprint(0, COL_MID+4, pct, 3, 0);
+ }
+ dprint(1, 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, "#");
+ cprint(1, COL_MID+9+v->pptr, "#");
v->pptr++;
}
@@ -495,7 +547,7 @@ void do_tick(void)
}
pct += n*3;
} else {
- for (i=0, n=0; i<v->test; i++) {
+ for (i=0, n=0; i<test; i++) {
if (tseq[i].errors == 0) {
n++;
}
@@ -530,7 +582,7 @@ void do_tick(void)
/* We can't do the elapsed time unless the rdtsc instruction
* is supported
*/
- if (v->rdtsc) {
+ if (cpu_id.fid.bits.rdtsc) {
asm __volatile__(
"rdtsc":"=a" (l),"=d" (h));
asm __volatile__ (
@@ -542,20 +594,34 @@ void do_tick(void)
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);
+ j = i % 10;
+
+ if(j != v->each_sec)
+ {
+
+ 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);
+
+ if(v->check_temp > 0 && !(v->fail_safe & 4))
+ {
+ coretemp();
+ }
+ v->each_sec = j;
+ }
+
}
+
- /* Check for keyboard input */
- check_input();
-
/* Poll for ECC errors */
+/*
poll_errors();
+*/
}
+
diff --git a/extra.c b/extra.c
index e7afff2..ff580f2 100644
--- a/extra.c
+++ b/extra.c
@@ -12,7 +12,6 @@
#include "pci.h"
#include "extra.h"
-static int claim = 0;
static int ctrl = -1;
struct memory_controller {
@@ -429,7 +428,6 @@ void get_menu(void)
int menu ;
find_memctr();
- disclaimer();
switch(ctrl)
{
@@ -537,35 +535,6 @@ int get_cas(void)
return (cas);
}
-void disclaimer(void)
-{
- if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0])))
- {
- popclear();
- wait_keyup();
- cprint(POP_Y+3, POP_X+4, " Chipset ");
- cprint(POP_Y+4, POP_X+4, "Not supported !");
- get_key();
- wait_keyup();
- popclear();
- }
- else if (claim == 0)
- {
- ulong j = 0;
-
- while (j<500000)
- {
- cprint(POP_Y+1, POP_X+3, "Disclaimer : ");
- cprint(POP_Y+3, POP_X+3, "Modifying timing may ");
- cprint(POP_Y+4, POP_X+3, "cause system instability");
- cprint(POP_Y+5, POP_X+3, "proceed at your own risk");
- j++;
- }
- claim = 1;
- popclear();
- }
-}
-
/////////////////////////////////////////////////////////
// here we go for the exciting timing change part... //
/////////////////////////////////////////////////////////
diff --git a/head.S b/head.S
index 4a5c872..d551336 100644
--- a/head.S
+++ b/head.S
@@ -17,48 +17,17 @@
#include "config.h"
#include "test.h"
-/*
- * References to members of the boot_cpu_data structure.
- */
-#define CPU_PARAMS cpu_id
-#define X86 0
-#define X86_MODEL 1
-#define X86_MASK 2
-#define X86_CPUID 4
-#define X86_CAPABILITY 8
-#define X86_VENDOR_ID 12
-#define X86_CACHE 24
-#define X86_PWRCAP 40
-#define X86_EXT 44
-#define X86_FFL 48
-#define X86_DCACHE0_EAX 52
-#define X86_DCACHE0_EBX 56
-#define X86_DCACHE0_ECX 60
-#define X86_DCACHE0_EDX 64
-#define X86_DCACHE1_EAX 68
-#define X86_DCACHE1_EBX 72
-#define X86_DCACHE1_ECX 76
-#define X86_DCACHE1_EDX 80
-#define X86_DCACHE2_EAX 84
-#define X86_DCACHE2_EBX 88
-#define X86_DCACHE2_ECX 92
-#define X86_DCACHE2_EDX 96
-#define X86_DCACHE3_EAX 100
-#define X86_DCACHE3_EBX 104
-#define X86_DCACHE3_ECX 108
-#define X86_DCACHE3_EDX 112
-
.code32
.globl startup_32
startup_32:
cld
cli
- /* Ensure I have a stack pointer */
+ /* Ensure I have a boot_stack pointer */
testl %esp, %esp
jnz 0f
movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp
- leal stack_top@GOTOFF(%esp), %esp
+ leal boot_stack_top@GOTOFF(%esp), %esp
0:
/* Load the GOT pointer */
@@ -66,8 +35,8 @@ startup_32:
0: popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx
- /* Pick the appropriate stack address */
- leal stack_top@GOTOFF(%ebx), %esp
+ /* Pick the appropriate boot_stack address */
+ leal boot_stack_top@GOTOFF(%ebx), %esp
/* Reload all of the segment registers */
leal gdt@GOTOFF(%ebx), %eax
@@ -101,23 +70,7 @@ flush: movl $KERNEL_DS, %eax
zerobss_done:
/*
- * Clear the video display
- */
- 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:
-
-
-/*
- * Setup and exception handler
+ * Setup an exception handler
*/
leal idt@GOTOFF(%ebx), %edi
@@ -286,216 +239,14 @@ clear_display_done:
movl %eax, 2 + idt_descr@GOTOFF(%ebx)
lidt idt_descr@GOTOFF(%ebx)
-/* Find out the CPU type */
-
- leal cpu_id@GOTOFF(%ebx), %esi
- movl %ebx, %edi
-
- movl $-1, X86_CPUID(%esi) # -1 for no CPUID initially
-
-/* check if it is 486 or 386. */
-
- movl $3, X86(%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, X86(%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
-
- /* Test for Cyrix CPU types */
- 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, X86(%esi) # Use two to identify as Cyrix
- jmp id_done
-
-have_cpuid:
- /* get vendor info */
- xorl %eax, %eax # call CPUID with 0 -> return vendor ID
- cpuid
- movl %eax, X86_CPUID(%esi) # save CPUID level
- movl %ebx, X86_VENDOR_ID(%esi) # first 4 chars
- movl %edx, X86_VENDOR_ID+4(%esi) # next 4 chars
- movl %ecx, X86_VENDOR_ID+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
-
+ leal _dl_start@GOTOFF(%ebx), %eax
+ call *%eax
- #
- # CDH start
- # Check FPU, initialize if present
- #
- testl $1, %edx # FPU available?
- jz no_fpu
+ /* Never forget to initialize the FPU ... Never ! */
finit
- no_fpu:
- #
- # CDH end
- #
-
- 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)
- andb $0xf0, %al # mask model
- shrb $4, %al
- movb %al, X86_MODEL(%esi)
- andb $0x0f, %cl # mask mask revision
- movb %cl, X86_MASK(%esi)
- movl %edx, X86_CAPABILITY(%esi)
-
- movl $0, X86_CACHE(%esi)
- movl $0, X86_CACHE+4(%esi)
- movl $0, X86_CACHE+8(%esi)
- movl $0, X86_CACHE+12(%esi)
-
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x6c65746e,%eax # Is this an Intel CPU? "GenuineIntel"
- jne not_intel
- movb %bl, X86_PWRCAP(%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, X86_CACHE(%esi)
- movl %ebx, X86_CACHE+4(%esi)
- movl %ecx, X86_CACHE+8(%esi)
- movl %edx, X86_CACHE+12(%esi)
-# Grab deterministic cache information (for 32nm Intel CPU)
- cmpw $0x0000,%dx
- jne id_done
- movl $4, %eax
- movl $0, %ecx
- cpuid
- movl %eax, X86_DCACHE0_EAX(%esi)
- movl %ebx, X86_DCACHE0_EBX(%esi)
- movl %ecx, X86_DCACHE0_ECX(%esi)
- movl %edx, X86_DCACHE0_EDX(%esi)
- movl $4, %eax
- movl $1, %ecx
- cpuid
- movl %eax, X86_DCACHE1_EAX(%esi)
- movl %ebx, X86_DCACHE1_EBX(%esi)
- movl %ecx, X86_DCACHE1_ECX(%esi)
- movl %edx, X86_DCACHE1_EDX(%esi)
- movl $4, %eax
- movl $2, %ecx
- cpuid
- movl %eax, X86_DCACHE2_EAX(%esi)
- movl %ebx, X86_DCACHE2_EBX(%esi)
- movl %ecx, X86_DCACHE2_ECX(%esi)
- movl %edx, X86_DCACHE2_EDX(%esi)
- movl $4, %eax
- movl $3, %ecx
- cpuid
- movl %eax, X86_DCACHE3_EAX(%esi)
- movl %ebx, X86_DCACHE3_EBX(%esi)
- movl %ecx, X86_DCACHE3_ECX(%esi)
- movl %edx, X86_DCACHE3_EDX(%esi)
- jmp id_done
-
-not_intel:
- movl X86_VENDOR_ID+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, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006,%eax # Use the CPUID instruction to get cache info
- cpuid
- movl %ecx,X86_CACHE+8(%esi)
- movl %edx,X86_CACHE+12(%esi)
- movl $0x80000007,%eax # Use the CPUID instruction to get AMD Powercap
- cpuid
- movl %edx,X86_PWRCAP(%esi)
-
-not_amd:
- movl X86_VENDOR_ID+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, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, X86_CACHE+8(%esi)
-
-not_transmeta:
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x64616574, %eax # Is this a Via/Cyrix CPU? "CyrixInstead"
- jne not_cyrix
-
- movl X86_CPUID(%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, X86_CACHE(%esi)
-
-not_cyrix:
- movl X86_VENDOR_ID+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, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, X86_CACHE+8(%esi)
-
-
-not_centaur:
-id_done:
- movl %edi, %ebx /* Restore GOT pointer */
+ call test_start
- leal _dl_start@GOTOFF(%ebx), %eax
- call *%eax
- call do_test
/* In case we return simulate an exception */
pushfl
pushl %cs
@@ -612,11 +363,12 @@ int_hand:
pushl %esi
pushl %ebp
- /* original stack pointer */
- leal 20(%esp), %eax
+ /* original boot_stack pointer */
+ leal 48(%esp), %eax
pushl %eax
-
- pushl %esp /* pointer to structure on the stack */
+ pushl %ds
+ pushl %ss
+ pushl %esp /* pointer to trap regs struct on the boot_stack */
call inter
addl $8, %esp
@@ -650,8 +402,8 @@ gdt_descr:
gdt:
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
- .quad 0x00cf9a000000ffff /* 0x10 main 4gb code at 0x000000 */
- .quad 0x00cf92000000ffff /* 0x18 main 4gb data at 0x000000 */
+ .quad 0x00cf9b000000ffff /* 0x10 main 4gb code at 0x000000 */
+ .quad 0x00cf93000000ffff /* 0x18 main 4gb data at 0x000000 */
.word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB)
.word 0 # base address = SETUPSEG
@@ -690,6 +442,10 @@ maxdepth \depth-1
maxdepth
+# Page Directory Tables:
+# There are 4 tables, the first two map the first 2 GB of memory. The last two are used with # PAE to map
+# the rest of memory in 2 GB segments. The last two tables are changed in vmem.c to map each segment.
+# We use 2 MB pages so only the Page Directory Table is used (no page tables).
.balign 4096
.globl pd0
pd0:
@@ -710,6 +466,8 @@ pd2:
pd3:
ptes64 0x00000000C0000000
+# Legacy Mode Page Directory Pointer Table:
+# 4 Entries, pointing to the Page Directory Tables
.balign 4096
.globl pdp
pdp:
@@ -717,12 +475,31 @@ pdp:
.long 0
.long pd1 + 1
.long 0
-
.long pd2 + 1
.long 0
-
.long pd3 + 1
.long 0
+
+# Long Mode Page Directory Pointer Table:
+# 4 Entries, pointing to the Page Directory Tables
+.balign 4096
+lpdp:
+ .long pd0 + 3
+ .long 0
+ .long pd1 + 3
+ .long 0
+ .long pd2 + 3
+ .long 0
+ .long pd3 + 3
+ .long 0
+
+
+# The long mode level 4 page map table
+.balign 4096
+.globl pml4
+pml4:
+ .long lpdp + 3
+ .long 0
.previous
#define RSTART startup_32
@@ -788,8 +565,8 @@ query_pcbios:
movl %eax, %fs
movl %eax, %gs
- /* Compute the stack base */
- leal stack@GOTOFF(%ebx), %ecx
+ /* Compute the boot_stack base */
+ leal boot_stack@GOTOFF(%ebx), %ecx
/* Compute the address of meminfo */
leal mem_info@GOTOFF(%ebx), %edi
@@ -818,7 +595,7 @@ real:
movw %ax, %gs
movw %ax, %ss
- /* Adjust the stack pointer */
+ /* Adjust the boot_stack pointer */
movl %ecx, %eax
shrl $4, %eax
movw %ax, %ss
@@ -991,8 +768,8 @@ prot:
movl %eax, %gs
movl %eax, %ss
- /* Adjust the stack pointer */
- leal stack@GOTOFF(%ebx), %eax
+ /* Adjust the boot_stack pointer */
+ leal boot_stack@GOTOFF(%ebx), %eax
addl %eax, %esp
/* Restore the caller saved registers */
@@ -1014,9 +791,45 @@ idt_real:
.word 0x400 - 1 # idt limit ( 256 entries)
.word 0, 0 # idt base = 0L
+/* _ap_trampoline_start is the entry point for cpus other than the
+ * bootstrap cpu. The code between _ap_trampoline_start to
+ * _ap_trampoline_protmode is copied to BootCodeStart(0x9000).
+ * The ljmp after turning on CR0.PE will jump to the
+ * relocatable code which usually resides at 0x10000 + _ap_trampoline_protmode.
+ *
+ * The trampoline code uses a temporary GDT. The entries of this temporary
+ * GDT must match the first few entries of the GDT used by the relocatble
+ * memtest code(see 'gdt' sybmol in this file).
+ *
+ */
+ .globl _ap_trampoline_start
+ .globl _ap_trampoline_protmode
+ .code16
+_ap_trampoline_start:
+ lgdt 0x0 /* will be fixed up later, see smp.c:BootAP()*/
+ movl %cr0, %eax
+ orl $1, %eax
+ movl %eax, %cr0
+ data32 ljmp $KERNEL_CS, $_ap_trampoline_protmode
+_ap_trampoline_protmode:
+ .code32
+ movw $KERNEL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp
+ leal boot_stack_top@GOTOFF(%esp), %esp
+ pushl $0
+ popf
+ call startup_32
+ /* if we ever return, we'll just loop forever */
+ cli
+2: hlt
+ jmp 2b
.data
zerobss: .long 1
-clear_display: .long 1
.previous
.data
.balign 16
@@ -1026,7 +839,9 @@ mem_info:
.previous
.bss
.balign 16
-stack:
- . = . + 8192
-stack_top:
+boot_stack:
+ .globl boot_stack
+ . = . + 4096
+boot_stack_top:
+ .globl boot_stack_top
.previous
diff --git a/init.c b/init.c
index f7f43c1..754b8d7 100644
--- a/init.c
+++ b/init.c
@@ -1,59 +1,82 @@
-/* init.c - MemTest-86 Version 3.0
- *
- * Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- * ----------------------------------------------------
- * MemTest86+ V4.20 Specific code (GPL V2.0)
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
+ * ------------------------------------------------
+ * init.c - MemTest-86 Version 3.6
+ *
+ * Released under version 2 of the Gnu Public License.
+ * By Chris Brady
*/
+
+#include "stdin.h"
+#include "stddef.h"
#include "test.h"
#include "defs.h"
#include "config.h"
-#include "controller.h"
-#include "pci.h"
+#include "cpuid.h"
+#include "smp.h"
#include "io.h"
#include "spd.h"
-
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
+#include "pci.h"
+#include "controller.h"
extern struct tseq tseq[];
extern short memsz_mode;
-extern short firmware;
-extern short dmi_initialized;
-extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
-
-struct cpu_ident cpu_id;
-ulong st_low, st_high;
-ulong end_low, end_high;
-ulong cal_low, cal_high;
-ulong extclock;
+extern int num_cpus;
+extern int act_cpus;
+extern int found_cpus;
unsigned long imc_type = 0;
+extern int maxcpus;
+extern char cpu_mask[];
+extern void initialise_cpus();
+
+/* Here we store all of the cpuid data */
+extern struct cpu_ident cpu_id;
-int l1_cache, l2_cache, l3_cache;
+int l1_cache=0, l2_cache=0, l3_cache=0;
int tsc_invariable = 0;
+ulong extclock;
-ulong memspeed(ulong src, ulong len, int iter, int type);
+ulong memspeed(ulong src, ulong len, int iter);
static void cpu_type(void);
-static void cacheable(void);
static int cpuspeed(void);
-int beepmode, fail_safe;
+static void get_cache_size();
+static void cpu_cache_speed();
+void get_cpuid();
+int beepmode;
+extern short dmi_initialized;
+extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
/* Failsafe function */
/* msec: number of ms to wait - scs: scancode expected to stop */
+/* bits: 0 = extended detection - 1: SMP - 2: Temp Check */
+/* 3: MP SMP - 4-7: RSVD */
void failsafe(int msec, int scs)
{
- int ip;
+ int i;
ulong sh, sl, l, h, t;
unsigned char c;
+ volatile char *pp;
- cprint(18, 22, "Press *F1* to enter Fail-Safe Mode");
+ for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) {
+ *pp = 0x1E;
+ }
+ for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<3; i++, pp+=2) {
+ *pp = 0x9E;
+ }
+ for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(55*2)+1); i<3; i++, pp+=2) {
+ *pp = 0x9E;
+ }
- ip = 0;
+ cprint(18, 18, "==> Press F1 to enter Fail-Safe Mode <==");
+
+ if(v->fail_safe & 2)
+ {
+ cprint(19, 15, "==> Press F2 to force Multi-Threading (SMP) <==");
+ }
+
/* save the starting time */
asm __volatile__(
"rdtsc":"=a" (sl),"=d" (sh));
@@ -73,34 +96,63 @@ void failsafe(int msec, int scs)
t += (l / v->clks_msec);
/* Is the time up? */
- if (t >= msec) {
- cprint(18, 22, " ");
- break;
- }
+ if (t >= msec) { break; }
/* Is expected Scan code pressed? */
c = get_key();
c &= 0x7f;
- if(c == scs) {
- fail_safe = 1;
- cprint(18, 22, " ");
+ /* F1 */
+ if(c == scs) { v->fail_safe |= 1; break; }
+
+ /* F2 */
+ if(c == scs+1)
+ {
+ v->fail_safe ^= 2;
break;
- }
+
+ }
+
+ /* F3 */
+ if(c == scs+2)
+ {
+ if(v->fail_safe & 2) { v->fail_safe ^= 2; }
+ v->fail_safe |= 8;
+ break;
+ }
+
}
+
+ cprint(18, 18, " ");
+ cprint(19, 15, " ");
+
+ for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) {
+ *pp = 0x17;
+ }
+
}
+
+
static void display_init(void)
{
int i;
volatile char *pp;
+
+ /* Set HW cursor out of screen boundaries */
+ __outb(0x0F, 0x03D4);
+ __outb(0xFF, 0x03D5);
+
+ __outb(0x0E, 0x03D4);
+ __outb(0xFF, 0x03D5);
+
serial_echo_init();
- serial_echo_print("\x1B[LINE_SCROLL;24r"); /* Set scroll area row 7-23 */
- serial_echo_print("\x1B[H\x1B[2J"); /* Clear Screen */
- serial_echo_print("\x1B[37m\x1B[44m");
- serial_echo_print("\x1B[0m");
- serial_echo_print("\x1B[37m\x1B[44m");
+ serial_echo_print("INE_SCROLL;24r"); /* Set scroll area row 7-23 */
+ serial_echo_print(""); /* Clear Screen */
+ serial_echo_print("");
+ serial_echo_print("");
+ serial_echo_print("");
/* Clear screen & set background to blue */
for(i=0, pp=(char *)(SCREEN_ADR); i<80*24; i++) {
@@ -108,12 +160,13 @@ static void display_init(void)
*pp++ = 0x17;
}
- /* Make the name background red */
+ /* Make the name background green */
for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) {
*pp = 0x20;
}
- cprint(0, 0, " Memtest86 v4.20 ");
+ cprint(0, 0, " Memtest86 5.01 ");
+ /* Set Blinking "+" */
for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) {
*pp = 0xA4;
}
@@ -124,7 +177,7 @@ static void display_init(void)
*pp = 0x71;
}
- serial_echo_print("\x1B[0m");
+ serial_echo_print("");
}
/*
@@ -142,31 +195,49 @@ void init(void)
/* Setup the display */
display_init();
-
- /* Determine the memory map */
- if ((firmware == FIRMWARE_UNKNOWN) &&
- (memsz_mode != SZ_MODE_PROBE)) {
- if (query_linuxbios()) {
- firmware = FIRMWARE_LINUXBIOS;
- }
- else if (query_pcbios()) {
- firmware = FIRMWARE_PCBIOS;
- }
+ cprint(5, 60, "| Time: 0:00:00");
+ cprint(1, COL_MID,"Pass %");
+ cprint(2, COL_MID,"Test %");
+ cprint(3, COL_MID,"Test #");
+ cprint(4, COL_MID,"Testing: ");
+ cprint(5, COL_MID,"Pattern: ");
+ cprint(1, 0, "CLK: (32b Mode)");
+ cprint(2, 0, "L1 Cache: Unknown ");
+ cprint(3, 0, "L2 Cache: Unknown ");
+ cprint(4, 0, "L3 Cache: None ");
+ cprint(5, 0, "Memory : ");
+ cprint(6, 0, "------------------------------------------------------------------------------");
+ cprint(7, 0, "Core#:");
+ cprint(8, 0, "State:");
+ cprint(9, 0, "Cores: Active / Total (Run: All) | Pass: 0 Errors: 0 ");
+ cprint(10, 0, "------------------------------------------------------------------------------");
+
+ /*
+ for(i=0, pp=(char *)(SCREEN_ADR+(5*160)+(53*2)+1); i<20; i++, pp+=2) {
+ *pp = 0x92;
}
- mem_size();
+ for(i=0, pp=(char *)(SCREEN_ADR+0*160+1); i<80; i++, pp+=2) {
+ *pp = 0x47;
+ }
+ */
+
+ cprint(7, 39, "| Chipset : Unknown");
+ cprint(8, 39, "| Memory Type : Unknown");
+
- /* setup pci */
- pci_init();
+ for(i=0; i < 6; i++) {
+ cprint(i, COL_MID-2, "| ");
+ }
+
+ footer();
- /* setup beep mode */
- beepmode = BEEP_MODE;
+ aprint(5, 10, v->test_pages);
- v->test = 0;
- v->pass = 0;
- v->msg_line = 0;
- v->ecount = 0;
- v->ecc_ecount = 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;
@@ -183,7 +254,7 @@ void init(void)
v->erri.ebits = 0;
v->erri.hdr_flag = 0;
v->erri.tbits = 0;
- for (i=0; tseq[i].msg != 0; i++) {
+ for (i=0; tseq[i].msg != NULL; i++) {
tseq[i].errors = 0;
}
if (dmi_initialized) {
@@ -193,984 +264,727 @@ void init(void)
}
}
}
+
+ /* setup beep mode */
+ beepmode = BEEP_MODE;
+
+ /* Get the cpu and cache information */
+ get_cpuid();
+
+ /* setup pci */
+ pci_init();
- cprint(LINE_CPU+1, 0, "L1 Cache: Unknown ");
- cprint(LINE_CPU+2, 0, "L2 Cache: Unknown ");
- cprint(LINE_CPU+3, 0, "L3 Cache: None ");
- cprint(LINE_CPU+4, 0, "Memory : |-------------------------------------------------");
- aprint(LINE_CPU+4, 10, v->test_pages);
- cprint(LINE_CPU+5, 0, "Chipset : ");
+ get_cache_size();
cpu_type();
- /* Check fail safe */
- failsafe(2000, 0x3B);
+ cpu_cache_speed();
- /* Find the memory controller */
- find_controller();
+ /* Check fail safe */
+ failsafe(5000, 0x3B);
- /* Find Memory Specs */
- if(fail_safe == 0) { get_spd_spec(); }
+ /* Initalize SMP */
+ initialise_cpus();
+
+ for (i = 0; i <num_cpus; i++) {
+ dprint(7, i+7, i%10, 1, 0);
+ cprint(8, i+7, "S");
+ }
- if (v->rdtsc) {
- cacheable();
- cprint(LINE_TIME, COL_TIME+4, ": :");
+ dprint(9, 19, num_cpus, 2, 0);
+
+ if((v->fail_safe & 3) == 2)
+ {
+ cprint(LINE_CPU,9, "(SMP: Disabled)");
+ cprint(LINE_RAM,9, "Running...");
}
- cprint(0, COL_MID,"Pass %");
- cprint(1, COL_MID,"Test %");
- cprint(2, COL_MID,"Test #");
- cprint(3, COL_MID,"Testing: ");
- cprint(4, COL_MID,"Pattern: ");
- cprint(LINE_INFO-2, 0, " WallTime Cached RsvdMem MemMap Cache ECC Test Pass Errors ECC Errs");
- cprint(LINE_INFO-1, 0, " --------- ------ ------- -------- ----- --- ---- ---- ------ --------");
- cprint(LINE_INFO, COL_TST, " Std");
- cprint(LINE_INFO, COL_PASS, " 0");
- cprint(LINE_INFO, COL_ERR, " 0");
- cprint(LINE_INFO+1, 0, " -----------------------------------------------------------------------------");
-
+ // dprint(10, 5, found_cpus, 2, 0);
- for(i=0; i < 5; i++) {
- cprint(i, COL_MID-2, "| ");
+ /* Find Memory Specs */
+ if(v->fail_safe & 1)
+ {
+ cprint(LINE_CPU, COL_SPEC, " **** FAIL SAFE **** FAIL SAFE **** ");
+ cprint(LINE_RAM, COL_SPEC, " No detection, same reliability ");
+ } else {
+ find_controller();
+ get_spd_spec();
+ if(num_cpus <= 16 && !(v->fail_safe & 4)) { coretemp(); }
+ }
+
+ if(v->check_temp > 0 && !(v->fail_safe & 4))
+ {
+ cprint(LINE_CPU, 26, "| CPU Temp");
+ cprint(LINE_CPU+1, 26, "| øC");
}
- footer();
- // Default Print Mode
- // v->printmode=PRINTMODE_SUMMARY;
+
+ beep(600);
+ beep(1000);
+
+ /* Record the start time */
+ asm __volatile__ ("rdtsc":"=a" (v->startl),"=d" (v->starth));
+ v->snapl = v->startl;
+ v->snaph = v->starth;
+ if (l1_cache == 0) { l1_cache = 64; }
+ if (l2_cache == 0) { l1_cache = 512; }
v->printmode=PRINTMODE_ADDRESSES;
v->numpatn=0;
-
-}
-
-#define FLAT 0
-
-static unsigned long mapped_window = 1;
-void paging_off(void)
-{
- if (!v->pae)
- return;
- mapped_window = 1;
- __asm__ __volatile__ (
- /* Disable paging */
- "movl %%cr0, %%eax\n\t"
- "andl $0x7FFFFFFF, %%eax\n\t"
- "movl %%eax, %%cr0\n\t"
- /* Disable pae and pse */
- "movl %%cr4, %%eax\n\t"
- "and $0xCF, %%al\n\t"
- "movl %%eax, %%cr4\n\t"
- :
- :
- : "ax"
- );
}
-static void paging_on(void *pdp)
+/* Get cache sizes for most AMD and Intel CPUs, exceptions for old CPUs are
+ * handled in CPU detection */
+void get_cache_size()
{
- if (!v->pae)
- return;
- __asm__ __volatile__(
- /* Load the page table address */
- "movl %0, %%cr3\n\t"
- /* Enable pae */
- "movl %%cr4, %%eax\n\t"
- "orl $0x00000020, %%eax\n\t"
- "movl %%eax, %%cr4\n\t"
- /* Enable paging */
- "movl %%cr0, %%eax\n\t"
- "orl $0x80000000, %%eax\n\t"
- "movl %%eax, %%cr0\n\t"
- :
- : "r" (pdp)
- : "ax"
- );
-}
-
-int map_page(unsigned long page)
-{
- unsigned long i;
- struct pde {
- unsigned long addr_lo;
- unsigned long addr_hi;
- };
- extern unsigned char pdp[];
- extern struct pde pd2[];
- unsigned long window = page >> 19;
- if (FLAT || (window == mapped_window)) {
- return 0;
- }
- if (window == 0) {
- return 0;
- }
- if (!v->pae || (window >= 32)) {
- /* Fail either we don't have pae support
- * or we want an address that is out of bounds
- * even for pae.
- */
- return -1;
- }
- /* Compute the page table entries... */
- for(i = 0; i < 1024; i++) {
- /*-----------------10/30/2004 12:37PM---------------
- * 0xE3 --
- * Bit 0 = Present bit. 1 = PDE is present
- * Bit 1 = Read/Write. 1 = memory is writable
- * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2)
- * Bit 3 = Writethrough. 0 = writeback cache policy
- * Bit 4 = Cache Disable. 0 = page level cache enabled
- * Bit 5 = Accessed. 1 = memory has been accessed.
- * Bit 6 = Dirty. 1 = memory has been written to.
- * Bit 7 = Page Size. 1 = page size is 2 MBytes
- * --------------------------------------------------*/
- pd2[i].addr_lo = ((window & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3;
- pd2[i].addr_hi = (window >> 1);
- }
- paging_off();
- if (window > 1) {
- paging_on(pdp);
- }
- mapped_window = window;
- return 0;
-}
+ int i, j, n, size;
+ unsigned int v[4];
+ unsigned char *dp = (unsigned char *)v;
+ struct cpuid4_eax *eax = (struct cpuid4_eax *)&v[0];
+ struct cpuid4_ebx *ebx = (struct cpuid4_ebx *)&v[1];
+ struct cpuid4_ecx *ecx = (struct cpuid4_ecx *)&v[2];
+
+ switch(cpu_id.vend_id.char_array[0]) {
+ /* AMD Processors */
+ case 'A':
+ //l1_cache = cpu_id.cache_info.amd.l1_i_sz;
+ l1_cache = cpu_id.cache_info.amd.l1_d_sz;
+ l2_cache = cpu_id.cache_info.amd.l2_sz;
+ l3_cache = cpu_id.cache_info.amd.l3_sz;
+ l3_cache *= 512;
+ break;
+ case 'G':
+ /* Intel Processors */
+ l1_cache = 0;
+ l2_cache = 0;
+ l3_cache = 0;
+
+ /* Use CPUID(4) if it is available */
+ if (cpu_id.max_cpuid > 3) {
+
+ /* figure out how many cache leaves */
+ n = -1;
+ do
+ {
+ ++n;
+ /* Do cpuid(4) loop to find out num_cache_leaves */
+ cpuid_count(4, n, &v[0], &v[1], &v[2], &v[3]);
+ } while ((eax->ctype) != 0);
+
+ /* loop through all of the leaves */
+ for (i=0; i<n; i++)
+ {
+ cpuid_count(4, i, &v[0], &v[1], &v[2], &v[3]);
+
+ /* Check for a valid cache type */
+ if (eax->ctype == 1 || eax->ctype == 3)
+ {
+
+ /* Compute the cache size */
+ size = (ecx->number_of_sets + 1) *
+ (ebx->coherency_line_size + 1) *
+ (ebx->physical_line_partition + 1) *
+ (ebx->ways_of_associativity + 1);
+ size /= 1024;
+
+ switch (eax->level)
+ {
+ case 1:
+ l1_cache += size;
+ break;
+ case 2:
+ l2_cache += size;
+ break;
+ case 3:
+ l3_cache += size;
+ break;
+ }
+ }
+ }
+ return;
+ }
-void *mapping(unsigned long page_addr)
-{
- void *result;
- if (FLAT || (page_addr < 0x80000)) {
- /* If the address is less that 1GB directly use the address */
- result = (void *)(page_addr << 12);
- }
- else {
- unsigned long alias;
- alias = page_addr & 0x7FFFF;
- alias += 0x80000;
- result = (void *)(alias << 12);
+ /* No CPUID(4) so we use the older CPUID(2) method */
+ /* Get number of times to iterate */
+ cpuid(2, &v[0], &v[1], &v[2], &v[3]);
+ n = v[0] & 0xff;
+ for (i=0 ; i<n ; i++) {
+ cpuid(2, &v[0], &v[1], &v[2], &v[3]);
+
+ /* If bit 31 is set, this is an unknown format */
+ for (j=0 ; j<3 ; j++) {
+ if (v[j] & (1 << 31)) {
+ v[j] = 0;
+ }
+ }
+
+ /* Byte 0 is level count, not a descriptor */
+ for (j = 1 ; j < 16 ; j++) {
+ switch(dp[j]) {
+ case 0x6:
+ case 0xa:
+ case 0x66:
+ l1_cache += 8;
+ break;
+ case 0x8:
+ case 0xc:
+ case 0xd:
+ case 0x60:
+ case 0x67:
+ l1_cache += 16;
+ break;
+ case 0xe:
+ l1_cache += 24;
+ break;
+ case 0x9:
+ case 0x2c:
+ case 0x30:
+ case 0x68:
+ l1_cache += 32;
+ break;
+ case 0x39:
+ case 0x3b:
+ case 0x41:
+ case 0x79:
+ l2_cache += 128;
+ break;
+ case 0x3a:
+ l2_cache += 192;
+ break;
+ case 0x21:
+ case 0x3c:
+ case 0x3f:
+ case 0x42:
+ case 0x7a:
+ case 0x82:
+ l2_cache += 256;
+ break;
+ case 0x3d:
+ l2_cache += 384;
+ break;
+ case 0x3e:
+ case 0x43:
+ case 0x7b:
+ case 0x7f:
+ case 0x80:
+ case 0x83:
+ case 0x86:
+ l2_cache += 512;
+ break;
+ case 0x44:
+ case 0x78:
+ case 0x7c:
+ case 0x84:
+ case 0x87:
+ l2_cache += 1024;
+ break;
+ case 0x45:
+ case 0x7d:
+ case 0x85:
+ l2_cache += 2048;
+ break;
+ case 0x48:
+ l2_cache += 3072;
+ break;
+ case 0x4e:
+ l2_cache += 6144;
+ break;
+ case 0x23:
+ case 0xd0:
+ l3_cache += 512;
+ break;
+ case 0xd1:
+ case 0xd6:
+ l3_cache += 1024;
+ break;
+ case 0x25:
+ case 0xd2:
+ case 0xd7:
+ case 0xdc:
+ case 0xe2:
+ l3_cache += 2048;
+ break;
+ case 0x29:
+ case 0x46:
+ case 0x49:
+ case 0xd8:
+ case 0xdd:
+ case 0xe3:
+ l3_cache += 4096;
+ break;
+ case 0x4a:
+ l3_cache += 6144;
+ break;
+ case 0x47:
+ case 0x4b:
+ case 0xde:
+ case 0xe4:
+ l3_cache += 8192;
+ break;
+ case 0x4c:
+ case 0xea:
+ l3_cache += 12288;
+ break;
+ case 0x4d:
+ l3_cache += 16384;
+ break;
+ case 0xeb:
+ l3_cache += 18432;
+ break;
+ case 0xec:
+ l3_cache += 24576;
+ break;
+ } /* end switch */
+ } /* end for 1-16 */
+ } /* end for 0 - n */
}
- return result;
}
-void *emapping(unsigned long page_addr)
+/*
+ * Find IMC type and set global variables accordingly
+ */
+void detect_imc(void)
{
- void *result;
- result = mapping(page_addr -1);
- /* The result needs to be 256 byte alinged... */
- result = ((unsigned char *)result) + 0xf00;
- return result;
+ // Check AMD IMC
+ if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF)
+ {
+ switch(cpu_id.vers.bits.extendedFamily)
+ {
+ case 0x0:
+ imc_type = 0x0100; // Old K8
+ break;
+ case 0x1:
+ case 0x2:
+ imc_type = 0x0101; // K10 (Family 10h & 11h)
+ break;
+ case 0x3:
+ imc_type = 0x0102; // A-Series APU (Family 12h)
+ break;
+ case 0x5:
+ imc_type = 0x0103; // C- / E- / Z- Series APU (Family 14h)
+ break;
+ case 0x6:
+ imc_type = 0x0104; // FX Series (Family 15h)
+ break;
+ case 0x7:
+ imc_type = 0x0105; // Kabini & related (Family 16h)
+ break;
+ }
+ return;
+ }
+
+ // Check Intel IMC
+ if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.vers.bits.family == 6 && cpu_id.vers.bits.extendedModel)
+ {
+ switch(cpu_id.vers.bits.model)
+ {
+ case 0x5:
+ if(cpu_id.vers.bits.extendedModel == 2) { imc_type = 0x0003; } // Core i3/i5 1st Gen 45 nm (NHM)
+ if(cpu_id.vers.bits.extendedModel == 3) { v->fail_safe |= 4; } // Atom Clover Trail
+ if(cpu_id.vers.bits.extendedModel == 4) { imc_type = 0x0007; } // HSW-ULT
+ break;
+ case 0x6:
+ if(cpu_id.vers.bits.extendedModel == 3) {
+ imc_type = 0x0009; // Atom Cedar Trail
+ v->fail_safe |= 4; // Disable Core temp
+ }
+ break;
+ case 0xA:
+ switch(cpu_id.vers.bits.extendedModel)
+ {
+ case 0x1:
+ imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHME)
+ break;
+ case 0x2:
+ imc_type = 0x0004; // Core 2nd Gen (SNB)
+ break;
+ case 0x3:
+ imc_type = 0x0006; // Core 3nd Gen (IVB)
+ break;
+ }
+ break;
+ case 0xC:
+ switch(cpu_id.vers.bits.extendedModel)
+ {
+ case 0x1:
+ if(cpu_id.vers.bits.stepping > 9) { imc_type = 0x0008; } // Atom PineView
+ v->fail_safe |= 4; // Disable Core temp
+ break;
+ case 0x2:
+ imc_type = 0x0002; // Core i7 1st Gen 32 nm (WMR)
+ break;
+ case 0x3:
+ imc_type = 0x0007; // Core 4nd Gen (HSW)
+ break;
+ }
+ break;
+ case 0xD:
+ imc_type = 0x0005; // SNB-E
+ break;
+ case 0xE:
+ imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHM)
+ break;
+ }
+
+ if(imc_type) { tsc_invariable = 1; }
+ return;
+ }
}
-unsigned long page_of(void *addr)
+void smp_default_mode(void)
{
- unsigned long page;
- page = ((unsigned long)addr) >> 12;
- if (!FLAT && (page >= 0x80000)) {
- page &= 0x7FFFF;
- page += mapped_window << 19;
- }
-#if 0
- cprint(LINE_SCROLL -2, 0, "page_of( )-> ");
- hprint(LINE_SCROLL -2, 8, ((unsigned long)addr));
- hprint(LINE_SCROLL -2, 20, page);
-#endif
- return page;
+ int i, result;
+ char *cpupsn = cpu_id.brand_id.char_array;
+ char *disabledcpu[] = { "Opteron", "Xeon", "Genuine Intel" };
+
+ for(i = 0; i < 3; i++)
+ {
+ result = strstr(cpupsn , disabledcpu[i]);
+ if(result != -1) { v->fail_safe |= 0b10; }
+ }
+
+ // For 5.01 release, SMP disabled by defualt by config.h toggle
+ if(CONSERVATIVE_SMP) { v->fail_safe |= 0b10; }
+
}
-
/*
- * Find CPU type and cache sizes
+ * Find CPU type
*/
-
-
void cpu_type(void)
{
- int i, off=0;
- int l1_cache=0, l2_cache=0, l3_cache=0;
- ulong speed;
-
- v->rdtsc = 0;
- v->pae = 0;
-
-#ifdef CPUID_DEBUG
- dprint(9,0,cpu_id.type,3,1);
- dprint(10,0,cpu_id.model,3,1);
- dprint(11,0,cpu_id.cpuid,3,1);
-#endif
-
- /* If the CPUID instruction is not supported then this is */
- /* a 386, 486 or one of the early Cyrix CPU's */
- if (cpu_id.cpuid < 1) {
- switch (cpu_id.type) {
- case 2:
- /* This is a Cyrix CPU without CPUID */
- i = getCx86(0xfe);
- i &= 0xf0;
- i >>= 4;
- switch(i) {
- case 0:
- case 1:
- cprint(LINE_CPU, 0, "Cyrix Cx486");
- break;
- case 2:
- cprint(LINE_CPU, 0,"Cyrix 5x86");
- break;
- case 3:
- cprint(LINE_CPU, 0,"Cyrix 6x86");
- break;
- case 4:
- cprint(LINE_CPU, 0,"Cyrix MediaGX");
- break;
- case 5:
- cprint(LINE_CPU, 0,"Cyrix 6x86MX");
- break;
- case 6:
- cprint(LINE_CPU, 0,"Cyrix MII");
- break;
- default:
- cprint(LINE_CPU, 0,"Cyrix ???");
- break;
- }
- break;
- case 3:
- cprint(LINE_CPU, 0, "386");
- break;
-
- case 4:
- cprint(LINE_CPU, 0, "486");
- l1_cache = 8;
- break;
- }
+ /* If we can get a brand string use it, and we are done */
+ if (cpu_id.max_xcpuid >= 0x80000004) {
+ cprint(0, COL_MID, cpu_id.brand_id.char_array);
+ //If we have a brand string, maybe we have an IMC. Check that.
+ detect_imc();
+ smp_default_mode();
return;
}
- /* We have cpuid so we can see if we have pae support */
- if (cpu_id.capability & (1 << X86_FEATURE_PAE)) {
- v->pae = 1;
- }
- switch(cpu_id.vend_id[0]) {
+ /* The brand string is not available so we need to figure out
+ * CPU what we have */
+ switch(cpu_id.vend_id.char_array[0]) {
/* AMD Processors */
case 'A':
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 4:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 3:
- cprint(LINE_CPU, 0, "AMD 486DX2");
+ cprint(0, COL_MID, "AMD 486DX2");
break;
case 7:
- cprint(LINE_CPU, 0, "AMD 486DX2-WB");
+ cprint(0, COL_MID, "AMD 486DX2-WB");
break;
case 8:
- cprint(LINE_CPU, 0, "AMD 486DX4");
+ cprint(0, COL_MID, "AMD 486DX4");
break;
case 9:
- cprint(LINE_CPU, 0, "AMD 486DX4-WB");
+ cprint(0, COL_MID, "AMD 486DX4-WB");
break;
case 14:
- cprint(LINE_CPU, 0, "AMD 5x86-WT");
+ cprint(0, COL_MID, "AMD 5x86-WT");
+ break;
+ case 15:
+ cprint(0, COL_MID, "AMD 5x86-WB");
break;
}
/* Since we can't get CPU speed or cache info return */
return;
case 5:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
case 2:
case 3:
- cprint(LINE_CPU, 0, "AMD K5");
+ cprint(0, COL_MID, "AMD K5");
l1_cache = 8;
- off = 6;
break;
case 6:
case 7:
- cprint(LINE_CPU, 0, "AMD K6");
- off = 6;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
+ cprint(0, COL_MID, "AMD K6");
break;
case 8:
- cprint(LINE_CPU, 0, "AMD K6-2");
- off = 8;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
+ cprint(0, COL_MID, "AMD K6-2");
break;
case 9:
- cprint(LINE_CPU, 0, "AMD K6-III");
- off = 10;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ cprint(0, COL_MID, "AMD K6-III");
break;
- case 10:
- cprint(LINE_CPU, 0, "AMD Geode LX");
- off = 12;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
- break;
- case 13:
- cprint(LINE_CPU, 0, "AMD K6-III+");
- off = 11;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ case 13:
+ cprint(0, COL_MID, "AMD K6-III+");
break;
}
break;
case 6:
- switch(cpu_id.model) {
+
+ switch(cpu_id.vers.bits.model) {
case 1:
- cprint(LINE_CPU, 0, "AMD Athlon (0.25)");
- off = 17;
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ cprint(0, COL_MID, "AMD Athlon (0.25)");
break;
case 2:
case 4:
- cprint(LINE_CPU, 0, "AMD Athlon (0.18)");
- off = 17;
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ cprint(0, COL_MID, "AMD Athlon (0.18)");
break;
case 6:
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
if (l2_cache == 64) {
- cprint(LINE_CPU, 0, "AMD Duron (0.18)");
+ cprint(0, COL_MID, "AMD Duron (0.18)");
} else {
- cprint(LINE_CPU, 0, "Athlon XP (0.18)");
+ cprint(0, COL_MID, "Athlon XP (0.18)");
}
- off = 16;
break;
case 8:
case 10:
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
if (l2_cache == 64) {
- cprint(LINE_CPU, 0, "AMD Duron (0.13)");
+ cprint(0, COL_MID, "AMD Duron (0.13)");
} else {
- cprint(LINE_CPU, 0, "Athlon XP (0.13)");
+ cprint(0, COL_MID, "Athlon XP (0.13)");
}
- off = 16;
break;
case 3:
case 7:
- cprint(LINE_CPU, 0, "AMD Duron");
- off = 9;
+ cprint(0, COL_MID, "AMD Duron");
/* Duron stepping 0 CPUID for L2 is broken */
/* (AMD errata T13)*/
- if (cpu_id.step == 0) { /* stepping 0 */
- /* Hard code the right size*/
+ if (cpu_id.vers.bits.stepping == 0) { /* stepping 0 */
+ /* Hard code the right L2 size */
l2_cache = 64;
} else {
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
}
break;
}
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
break;
- case 15:
- l1_cache = cpu_id.cache_info[3];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
- imc_type = 0x0100;
- if(((cpu_id.ext >> 16) & 0xFF) < 0x10) {
- // Here if CPUID.EXT < 0x10h (old K8/K10)
- switch(cpu_id.model) {
- default:
- cprint(LINE_CPU, 0, "AMD K8");
- off = 6;
- break;
- case 1:
- case 5:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- cprint(LINE_CPU, 0, "AMD Opteron (0.09)");
- } else {
- cprint(LINE_CPU, 0, "AMD Opteron (0.13)");
- }
- off = 18;
- break;
- case 3:
- case 11:
- cprint(LINE_CPU, 0, "Athlon 64 X2");
- off = 12;
- break;
- case 8:
- cprint(LINE_CPU, 0, "Turion 64 X2");
- off = 12;
- break;
- case 4:
- case 7:
- case 12:
- case 14:
- case 15:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.09)");
- } else {
- cprint(LINE_CPU, 0, "Sempron (0.09)");
- }
- } else {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.13)");
- } else {
- cprint(LINE_CPU, 0, "Sempron (0.13)");
- }
- }
- off = 16;
- break;
- }
- break;
- } else {
- // Here if CPUID.EXT >= 0x10h (new K10)
- l3_cache = (cpu_id.cache_info[15] << 8);
- l3_cache += (cpu_id.cache_info[14] >> 2);
- l3_cache *= 512;
- switch(cpu_id.model) {
- case 1:
- imc_type = 0x0102;
- cprint(LINE_CPU, 0, "AMD Fusion @");
- off = 12;
- break;
- default:
- case 2:
- imc_type = 0x0101;
- cprint(LINE_CPU, 0, "AMD K10 (65nm) @");
- off = 16;
- break;
- case 4:
- imc_type = 0x0101;
- cprint(LINE_CPU, 0, "AMD K10 (45nm) @");
- off = 16;
- break;
- case 9:
- imc_type = 0x0101;
- cprint(LINE_CPU, 0, "AMD Magny-Cours");
- off = 15;
- break;
- }
- break;
- }
+
+ /* All AMD family values >= 10 have the Brand ID
+ * feature so we don't need to find the CPU type */
}
break;
/* Intel or Transmeta Processors */
case 'G':
- if ( cpu_id.vend_id[7] == 'T' ) { /* GenuineTMx86 */
- if (cpu_id.type == 5) {
- cprint(LINE_CPU, 0, "TM 5x00");
- off = 7;
- } else if (cpu_id.type == 15) {
- cprint(LINE_CPU, 0, "TM 8x00");
- off = 7;
+ if ( cpu_id.vend_id.char_array[7] == 'T' ) { /* GenuineTMx86 */
+ if (cpu_id.vers.bits.family == 5) {
+ cprint(0, COL_MID, "TM 5x00");
+ } else if (cpu_id.vers.bits.family == 15) {
+ cprint(0, COL_MID, "TM 8x00");
}
- l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11]*256) + cpu_id.cache_info[10];
+ l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7];
+ l2_cache = (cpu_id.cache_info.ch[11]*256) + cpu_id.cache_info.ch[10];
} else { /* GenuineIntel */
- if (cpu_id.type == 4) {
- switch(cpu_id.model) {
- case 0:
- case 1:
- cprint(LINE_CPU, 0, "Intel 486DX");
- off = 11;
- break;
- case 2:
- cprint(LINE_CPU, 0, "Intel 486SX");
- off = 11;
- break;
- case 3:
- cprint(LINE_CPU, 0, "Intel 486DX2");
- off = 12;
- break;
- case 4:
- cprint(LINE_CPU, 0, "Intel 486SL");
- off = 11;
- break;
- case 5:
- cprint(LINE_CPU, 0, "Intel 486SX2");
- off = 12;
- break;
- case 7:
- cprint(LINE_CPU, 0, "Intel 486DX2-WB");
- off = 15;
- break;
- case 8:
- cprint(LINE_CPU, 0, "Intel 486DX4");
- off = 12;
- break;
- case 9:
- cprint(LINE_CPU, 0, "Intel 486DX4-WB");
- off = 15;
- break;
- }
- /* Since we can't get CPU speed or cache info return */
- return;
+ if (cpu_id.vers.bits.family == 4) {
+ switch(cpu_id.vers.bits.model) {
+ case 0:
+ case 1:
+ cprint(0, COL_MID, "Intel 486DX");
+ break;
+ case 2:
+ cprint(0, COL_MID, "Intel 486SX");
+ break;
+ case 3:
+ cprint(0, COL_MID, "Intel 486DX2");
+ break;
+ case 4:
+ cprint(0, COL_MID, "Intel 486SL");
+ break;
+ case 5:
+ cprint(0, COL_MID, "Intel 486SX2");
+ break;
+ case 7:
+ cprint(0, COL_MID, "Intel 486DX2-WB");
+ break;
+ case 8:
+ cprint(0, COL_MID, "Intel 486DX4");
+ break;
+ case 9:
+ cprint(0, COL_MID, "Intel 486DX4-WB");
+ break;
}
+ /* Since we can't get CPU speed or cache info return */
+ return;
+ }
- /* Get the cache info */
- for (i=0; i<16; i++) {
-#ifdef CPUID_DEBUG
- dprint(12,i*3,cpu_id.cache_info[i],2,1);
-#endif
- switch(cpu_id.cache_info[i]) {
- case 0x6:
- case 0xa:
- case 0x66:
+
+ switch(cpu_id.vers.bits.family) {
+ case 5:
+ switch(cpu_id.vers.bits.model) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 7:
+ cprint(0, COL_MID, "Pentium");
+ if (l1_cache == 0) {
l1_cache = 8;
- break;
- case 0x8:
- case 0xc:
- case 0x67:
- case 0x60:
+ }
+ break;
+ case 4:
+ case 8:
+ cprint(0, COL_MID, "Pentium-MMX");
+ if (l1_cache == 0) {
l1_cache = 16;
- break;
- case 0x9:
- case 0xd:
- case 0x68:
- case 0x2c:
- case 0x30:
- l1_cache = 32;
- break;
- case 0x40:
- l2_cache = 0;
- break;
- case 0x41:
- case 0x79:
- case 0x39:
- case 0x3b:
- l2_cache = 128;
- break;
- case 0x3a:
- l2_cache = 192;
- break;
- case 0x21:
- case 0x42:
- case 0x7a:
- case 0x82:
- case 0x3c:
- case 0x3f:
- l2_cache = 256;
- break;
- case 0x3d:
- l2_cache = 384;
- break;
- case 0x43:
- case 0x7b:
- case 0x83:
- case 0x86:
- case 0x3e:
- case 0x7f:
- case 0x80:
- l2_cache = 512;
- break;
- case 0x44:
- case 0x7c:
- case 0x84:
- case 0x87:
- case 0x78:
- l2_cache = 1024;
- break;
- case 0x45:
- case 0x7d:
- case 0x85:
- l2_cache = 2048;
- break;
- case 0x48:
- l2_cache = 3072;
- break;
- case 0x49:
- l2_cache = 4096;
- break;
- case 0x4e:
- l2_cache = 6144;
- break;
- case 0x22:
- case 0xd0:
- l3_cache = 512;
- case 0x23:
- case 0xd1:
- case 0xd6:
- l3_cache = 1024;
- break;
- case 0xdc:
- l3_cache = 1536;
- break;
- case 0x25:
- case 0xd2:
- case 0xd7:
- case 0xe2:
- l3_cache = 2048;
- break;
- case 0xdd:
- l3_cache = 3072;
- break;
- case 0x29:
- case 0x46:
- case 0xd8:
- case 0xe3:
- l3_cache = 4096;
- break;
- case 0x4a:
- case 0xde:
- l3_cache = 6144;
- break;
- case 0x47:
- case 0x4b:
- case 0xe4:
- l3_cache = 8192;
- break;
- case 0x4c:
- case 0xea:
- l3_cache = 12288;
- break;
- case 0x4d:
- l3_cache = 16374;
- break;
- case 0xeb:
- l3_cache = 18432;
- break;
- case 0xec:
- l3_cache = 24576;
- break;
}
+ break;
}
-
- // If no cache found, check if deterministic cache info are available
- if(l1_cache == 0 && ((cpu_id.dcache0_eax >> 5) & 7) == 1)
- {
-
- long dcache[] = { cpu_id.dcache0_eax, cpu_id.dcache0_ebx, cpu_id.dcache0_ecx, cpu_id.dcache0_edx,
- cpu_id.dcache1_eax, cpu_id.dcache1_ebx, cpu_id.dcache1_ecx, cpu_id.dcache1_edx,
- cpu_id.dcache2_eax, cpu_id.dcache2_ebx, cpu_id.dcache2_ecx, cpu_id.dcache2_edx,
- cpu_id.dcache3_eax, cpu_id.dcache3_ebx, cpu_id.dcache3_ecx, cpu_id.dcache3_edx
- };
-
- for(i=0; i<4; i++)
- {
- switch((dcache[i*4] >> 5) & 7)
- {
- case 1:
- // We don't want L1 I-Cache, only L1 D-Cache
- if((dcache[i*4] & 3) != 2)
- {
- l1_cache = (((dcache[i*4+1] >> 22) & 0x3FF) + 1) * (((dcache[i*4+1] >> 12) & 0x3FF) + 1);
- l1_cache *= ((dcache[i*4+1] & 0xFFF) + 1) * (dcache[i*4+2] + 1) / 1024;
- }
- break;
- case 2:
- l2_cache = (((dcache[i*4+1] >> 22) & 0x3FF) + 1) * (((dcache[i*4+1] >> 12) & 0x3FF) + 1);
- l2_cache *= ((dcache[i*4+1] & 0xFFF) + 1) * (dcache[i*4+2] + 1) / 1024;
- break;
- case 3:
- l3_cache = (((dcache[i*4+1] >> 22) & 0x3FF) + 1) * (((dcache[i*4+1] >> 12) & 0x3FF) + 1);
- l3_cache *= ((dcache[i*4+1] & 0xFFF) + 1) * (dcache[i*4+2] + 1) / 1024;
- break;
- }
- }
- }
-
-
- switch(cpu_id.type) {
+ break;
+ case 6:
+ switch(cpu_id.vers.bits.model) {
+ case 0:
+ case 1:
+ cprint(0, COL_MID, "Pentium Pro");
+ break;
+ case 3:
+ case 4:
+ cprint(0, COL_MID, "Pentium II");
+ break;
case 5:
- switch(cpu_id.model) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 7:
- cprint(LINE_CPU, 0, "Pentium");
- if (l1_cache == 0) {
- l1_cache = 8;
- }
- off = 7;
- break;
- case 4:
- case 8:
- cprint(LINE_CPU, 0, "Pentium-MMX");
- if (l1_cache == 0) {
- l1_cache = 16;
- }
- off = 11;
- break;
+ if (l2_cache == 0) {
+ cprint(0, COL_MID, "Celeron");
+ } else {
+ cprint(0, COL_MID, "Pentium II");
}
break;
case 6:
- switch(cpu_id.model) {
- case 0:
- case 1:
- cprint(LINE_CPU, 0, "Pentium Pro");
- off = 11;
- break;
- case 3:
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
- break;
- case 5:
- if ((cpu_id.ext >> 16) & 0xF) {
- if(((cpu_id.ext >> 16) & 0xF) > 1) {
- cprint(LINE_CPU, 0, "Intel Core i3/i5");
- tsc_invariable = 1;
- imc_type = 0x0003;
- off = 16;
- } else {
- cprint(LINE_CPU, 0, "Intel EP80579");
- if (l2_cache == 0) { l2_cache = 256; }
- off = 13;
- }
+ if (l2_cache == 128) {
+ cprint(0, COL_MID, "Celeron");
+ } else {
+ cprint(0, COL_MID, "Pentium II");
+ }
+ }
+ break;
+ case 7:
+ case 8:
+ case 11:
+ if (l2_cache == 128) {
+ cprint(0, COL_MID, "Celeron");
} else {
- if (l2_cache == 0) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
- } else {
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
- }
- }
- break;
- case 6:
- 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 11:
- 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 {
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
- } else {
- cprint(LINE_CPU, 0, "Pentium III");
- off = 11;
- }
- }
- break;
- case 9:
- if (l2_cache == 512) {
- cprint(LINE_CPU, 0, "Celeron M (0.13)");
- } else {
- cprint(LINE_CPU, 0, "Pentium M (0.13)");
- }
- off = 16;
- break;
- case 10:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- tsc_invariable = 1;
- if(((cpu_id.ext >> 16) & 0xF) > 1) {
- cprint(LINE_CPU, 0, "Intel Core Gen2");
- imc_type = 0x0004;
- off = 15;
- } else {
- imc_type = 0x0001;
- cprint(LINE_CPU, 0, "Intel Core i7");
- off = 13;
- }
- } else {
- cprint(LINE_CPU, 0, "Pentium III Xeon");
- off = 16;
- }
- break;
- case 12:
- if (((cpu_id.ext >> 16) & 0xF) > 1) {
- cprint(LINE_CPU, 0, "Core i7 (32nm)");
- tsc_invariable = 1;
- imc_type = 0x0002;
- off = 14;
- } else {
- l1_cache = 24;
- cprint(LINE_CPU, 0, "Atom (0.045)");
- off = 12;
- }
- break;
- case 13:
- if (l2_cache == 1024) {
- cprint(LINE_CPU, 0, "Celeron M (0.09)");
- } else {
- cprint(LINE_CPU, 0, "Pentium M (0.09)");
- }
- off = 16;
- break;
- case 14:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- tsc_invariable = 1;
- imc_type = 0x0001;
- cprint(LINE_CPU, 0, "Intel Core i5/i7");
- off = 16;
- } else {
- cprint(LINE_CPU, 0, "Intel Core");
- off = 10;
- }
- break;
- case 15:
- 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;
+ cprint(0, COL_MID, "Pentium III");
+ }
+ break;
+ case 9:
+ if (l2_cache == 512) {
+ cprint(0, COL_MID, "Celeron M (0.13)");
+ } else {
+ cprint(0, COL_MID, "Pentium M (0.13)");
+ }
+ break;
+ case 10:
+ cprint(0, COL_MID, "Pentium III Xeon");
+ break;
+ case 12:
+ l1_cache = 24;
+ cprint(0, COL_MID, "Atom (0.045)");
+ break;
+ case 13:
+ if (l2_cache == 1024) {
+ cprint(0, COL_MID, "Celeron M (0.09)");
+ } else {
+ cprint(0, COL_MID, "Pentium M (0.09)");
}
break;
+ case 14:
+ cprint(0, COL_MID, "Intel Core");
+ break;
case 15:
- switch(cpu_id.model) {
- case 0:
- case 1:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron (0.18)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.18)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.18)");
- off = 14;
- } else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.18)");
- off = 16;
- }
- break;
- case 2:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron (0.13)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.13)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.13)");
- off = 14;
- } else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.13)");
- off = 16;
- }
- break;
- case 3:
- case 4:
- if (l2_cache == 256) {
- cprint(LINE_CPU, 0, "Celeron (0.09)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.09)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.09)");
- off = 14;
- } else if ((cpu_id.step == 0x4 || cpu_id.step == 0x7) && cpu_id.model == 0x4) {
- cprint(LINE_CPU, 0, "Pentium D (0.09)");
- off = 16;
- } else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.09)");
- off = 16;
- }
- break;
- case 6:
- cprint(LINE_CPU, 0, "Pentium D (65nm)");
- off = 16;
- break;
- default:
- cprint(LINE_CPU, 0, "Unknown Intel");
- off = 13;
- break;
+ if (l2_cache == 1024) {
+ cprint(0, COL_MID, "Pentium E");
+ } else {
+ cprint(0, COL_MID, "Intel Core 2");
}
break;
}
+ break;
+ case 15:
+ switch(cpu_id.vers.bits.model) {
+ case 0:
+ case 1:
+ case 2:
+ if (l2_cache == 128) {
+ cprint(0, COL_MID, "Celeron");
+ } else {
+ cprint(0, COL_MID, "Pentium 4");
+ }
+ break;
+ case 3:
+ case 4:
+ if (l2_cache == 256) {
+ cprint(0, COL_MID, "Celeron (0.09)");
+ } else {
+ cprint(0, COL_MID, "Pentium 4 (0.09)");
+ }
+ break;
+ case 6:
+ cprint(0, COL_MID, "Pentium D (65nm)");
+ break;
+ default:
+ cprint(0, COL_MID, "Unknown Intel");
+ break;
+ break;
+ }
+
}
break;
/* VIA/Cyrix/Centaur Processors with CPUID */
case 'C':
- if ( cpu_id.vend_id[1] == 'e' ) { /* CentaurHauls */
- l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7];
- l2_cache = cpu_id.cache_info[11];
- switch(cpu_id.type){
+ if ( cpu_id.vend_id.char_array[1] == 'e' ) { /* CentaurHauls */
+ l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7];
+ l2_cache = cpu_id.cache_info.ch[11];
+ switch(cpu_id.vers.bits.family){
case 5:
- cprint(LINE_CPU, 0, "Centaur 5x86");
- off = 12;
+ cprint(0, COL_MID, "Centaur 5x86");
break;
case 6: // VIA C3
- 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 C7 (C5J)");
- l1_cache = 64;
- l2_cache = 128;
- off = 16;
- break;
- case 13:
- cprint(LINE_CPU, 0, "VIA C7 (C5R)");
- l1_cache = 64;
- l2_cache = 128;
- off = 12;
- break;
- case 15:
- cprint(LINE_CPU, 0, "VIA Isaiah (CN)");
- l1_cache = 64;
- l2_cache = 1024;
- off = 15;
- break;
+ switch(cpu_id.vers.bits.model){
+ default:
+ if (cpu_id.vers.bits.stepping < 8) {
+ cprint(0, COL_MID, "VIA C3 Samuel2");
+ } else {
+ cprint(0, COL_MID, "VIA C3 Eden");
+ }
+ break;
+ case 10:
+ cprint(0, COL_MID, "VIA C7 (C5J)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
+ case 13:
+ cprint(0, COL_MID, "VIA C7 (C5R)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
+ case 15:
+ cprint(0, COL_MID, "VIA Isaiah (CN)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
}
}
} else { /* CyrixInstead */
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 5:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
- cprint(LINE_CPU, 0, "Cyrix 6x86MX/MII");
- off = 16;
+ cprint(0, COL_MID, "Cyrix 6x86MX/MII");
break;
case 4:
- cprint(LINE_CPU, 0, "Cyrix GXm");
- off = 9;
+ cprint(0, COL_MID, "Cyrix GXm");
break;
}
return;
case 6: // VIA C3
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 6:
- cprint(LINE_CPU, 0, "Cyrix III");
- off = 9;
+ cprint(0, COL_MID, "Cyrix III");
break;
case 7:
- if (cpu_id.step < 8) {
- cprint(LINE_CPU, 0, "VIA C3 Samuel2");
- off = 14;
+ if (cpu_id.vers.bits.stepping < 8) {
+ cprint(0, COL_MID, "VIA C3 Samuel2");
} else {
- cprint(LINE_CPU, 0, "VIA C3 Ezra-T");
- off = 13;
+ cprint(0, COL_MID, "VIA C3 Ezra-T");
}
break;
case 8:
- cprint(LINE_CPU, 0, "VIA C3 Ezra-T");
- off = 13;
+ cprint(0, COL_MID, "VIA C3 Ezra-T");
break;
case 9:
- cprint(LINE_CPU, 0, "VIA C3 Nehemiah");
- off = 15;
+ cprint(0, COL_MID, "VIA C3 Nehemiah");
break;
}
// L1 = L2 = 64 KB from Cyrix III to Nehemiah
@@ -1180,34 +994,40 @@ void cpu_type(void)
}
}
break;
-
/* Unknown processor */
default:
- off = 3;
/* Make a guess at the family */
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 5:
- cprint(LINE_CPU, 0, "586");
- return;
+ cprint(0, COL_MID, "586");
case 6:
- cprint(LINE_CPU, 0, "686");
- return;
+ cprint(0, COL_MID, "686");
+ default:
+ cprint(0, COL_MID, "Unidentified Processor");
}
}
+}
+
+#define STEST_ADDR 0x100000 /* Measure memory speed starting at 1MB */
+
+/* Measure and display CPU and cache sizes and speeds */
+void cpu_cache_speed()
+{
+ int i, off = 4;
+ ulong speed;
- /* We are here only if the CPU type supports the rdtsc instruction */
/* Print CPU speed */
if ((speed = cpuspeed()) > 0) {
- if (speed < 1000000-50) {
+ if (speed < 999499) {
speed += 50; /* for rounding */
- cprint(LINE_CPU, off, " . MHz");
- dprint(LINE_CPU, off+1, speed/1000, 3, 1);
- dprint(LINE_CPU, off+5, (speed/100)%10, 1, 0);
+ cprint(1, off, " . MHz");
+ dprint(1, off+1, speed/1000, 3, 1);
+ dprint(1, off+5, (speed/100)%10, 1, 0);
} else {
speed += 500; /* for rounding */
- cprint(LINE_CPU, off, " MHz");
- dprint(LINE_CPU, off, speed/1000, 5, 0);
+ cprint(1, off, " MHz");
+ dprint(1, off, speed/1000, 5, 0);
}
extclock = speed;
}
@@ -1216,11 +1036,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, 0, "L1 Cache: K ");
- dprint(LINE_CPU+1, 11, l1_cache, 3, 0);
- if ((speed=memspeed((ulong)mapping(0x100), (l1_cache / 4) * 1024, 200, MS_COPY))) {
- cprint(LINE_CPU+1, 16, " MB/s");
- dprint(LINE_CPU+1, 16, speed, 6, 0);
+ cprint(2, 0, "L1 Cache: K ");
+ dprint(2, 11, l1_cache, 3, 0);
+ if ((speed=memspeed(STEST_ADDR, (l1_cache/2)*1024, 200))) {
+ cprint(2, 16, " MB/s");
+ dprint(2, 16, speed, 6, 0);
}
}
@@ -1229,119 +1049,84 @@ 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, 0, "L2 Cache: K ");
- dprint(LINE_CPU+2, 10, l2_cache, 4, 0);
- dprint(LINE_CPU+2, 10, l2_cache, 4, 0);
+ cprint(3, 0, "L2 Cache: K ");
+ dprint(3, 10, l2_cache, 4, 0);
if (l2_cache < l1_cache) {
i = l1_cache / 4 + l2_cache / 4;
} else {
i = l1_cache;
}
- if ((speed=memspeed((ulong)mapping(0x100), i*1024, 200, MS_COPY))) {
- cprint(LINE_CPU+2, 16, " MB/s");
- dprint(LINE_CPU+2, 16, speed, 6, 0);
+ if ((speed=memspeed(STEST_ADDR, i*1024, 200))) {
+ cprint(3, 16, " MB/s");
+ dprint(3, 16, speed, 6, 0);
}
}
-
/* Print out L3 cache info */
/* We measure the L3 cache speed by using a block size that is */
- /* the size of the L2 cache. */
-
- if (l3_cache) {
- cprint(LINE_CPU+3, 0, "L3 Cache: K ");
- dprint(LINE_CPU+3, 10, l3_cache, 4, 0);
- dprint(LINE_CPU+3, 10, l3_cache, 4, 0);
-
- i = l2_cache*2;
+ /* 2X the size of the L2 cache. */
+
+ if (l3_cache)
+ {
+ cprint(4, 0, "L3 Cache: K ");
+ aprint(4, 10, l3_cache/4);
+ //dprint(4, 10, l3_cache, 4, 0);
+
+ i = l2_cache*2;
+
+ if ((speed=memspeed(STEST_ADDR, i*1024, 150))) {
+ cprint(4, 16, " MB/s");
+ dprint(4, 16, speed, 6, 0);
+ }
+ }
+}
- if ((speed=memspeed((ulong)mapping(0x100), i*1024, 150, MS_COPY))) {
- cprint(LINE_CPU+3, 16, " MB/s");
- dprint(LINE_CPU+3, 16, speed, 6, 0);
- }
- }
+/* Measure and display memory speed, multitasked using all CPUs */
+ulong spd[MAX_CPUS];
+void get_mem_speed(int me, int ncpus)
+{
+ int i;
+ ulong speed=0;
+ /* Determine memory speed. To find the memory speed we use
+ * A block size that is the sum of all the L1, L2 & L3 caches
+ * in all cpus * 6 */
+ i = (l3_cache + l2_cache + l1_cache) * 4;
- /* Determine memory speed. To find the memory speed we use */
- /* A block size that is 5x the sum of the L1, L2 & L3 caches */
- i = (l3_cache + l2_cache + l1_cache) * 5;
-
/* Make sure that we have enough memory to do the test */
+ /* If not use all we have */
if ((1 + (i * 2)) > (v->plim_upper << 2)) {
i = ((v->plim_upper <<2) - 1) / 2;
}
- if((speed = memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY))) {
- cprint(LINE_CPU+4, 16, " MB/s");
- dprint(LINE_CPU+4, 16, speed, 6, 0);
- }
-
- /* Record the starting time */
- asm __volatile__ ("rdtsc":"=a" (v->startl),"=d" (v->starth));
- v->snapl = v->startl;
- v->snaph = v->starth;
- v->rdtsc = 1;
- if (l1_cache == 0) { l1_cache = 66; }
- if (l2_cache == 0) { l1_cache = 666; }
-}
-
-/* Find cache-able memory size */
-static void cacheable(void)
-{
- ulong speed, pspeed;
- ulong paddr, mem_top, cached;
-
- mem_top = v->pmap[v->msegs - 1].end;
- cached = v->test_pages;
- pspeed = 0;
- for (paddr=0x200; paddr <= mem_top - 64; paddr+=0x400) {
- int i;
- int found;
- /* See if the paddr is at a testable location */
- found = 0;
- for(i = 0; i < v->msegs; i++) {
- if ((v->pmap[i].start >= paddr) &&
- (v->pmap[i].end <= (paddr + 32))) {
- found = 1;
- break;
- }
- }
- if (!found) {
- continue;
- }
- /* Map the range and perform the test */
- map_page(paddr);
- speed = memspeed((ulong)mapping(paddr), 32*4096, 1, MS_READ);
- if (pspeed) {
- if (speed < pspeed) {
- cached -= 32;
- }
- pspeed = (ulong)((float)speed * 0.7);
- }
- }
- aprint(LINE_INFO, COL_CACHE_TOP, cached);
- /* Ensure the default set of pages are mapped */
- map_page(0);
- map_page(0x80000);
+
+ speed = memspeed(STEST_ADDR, i * 1024, 100);
+ cprint(5, 16, " MB/s");
+ dprint(5, 16, speed, 6, 0);
+
}
-
/* #define TICKS 5 * 11832 (count = 6376)*/
/* #define TICKS (65536 - 12752) */
-/* #define TICKS (65536 - 8271) */
-#define TICKS 59659 /* Program counter to 50 ms = 59659 clks */
+#define TICKS 59659 /* 50 ms */
/* Returns CPU clock in khz */
+ulong stlow, sthigh;
static int cpuspeed(void)
{
int loops;
+ ulong end_low, end_high;
+
+ if (cpu_id.fid.bits.rdtsc == 0 ) {
+ return(-1);
+ }
/* Setup timer */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
- outb(0xb0, 0x43);
+ outb(0xb0, 0x43);
outb(TICKS & 0xff, 0x42);
outb(TICKS >> 8, 0x42);
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ asm __volatile__ ("rdtsc":"=a" (stlow),"=d" (sthigh));
loops = 0;
do {
@@ -1350,8 +1135,8 @@ static int cpuspeed(void)
asm __volatile__ (
"rdtsc\n\t" \
- "subl st_low,%%eax\n\t" \
- "sbbl st_high,%%edx\n\t" \
+ "subl stlow,%%eax\n\t" \
+ "sbbl sthigh,%%edx\n\t" \
:"=a" (end_low), "=d" (end_high)
);
@@ -1359,20 +1144,27 @@ 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); }
+ 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. */
+/* Measure cache speed by copying a block of memory. */
/* Returned value is kbytes/second */
-ulong memspeed(ulong src, ulong len, int iter, int type)
+ulong memspeed(ulong src, ulong len, int iter)
{
- ulong dst;
- ulong wlen;
int i;
+ ulong dst, wlen;
+ ulong st_low, st_high;
+ ulong end_low, end_high;
+ ulong cal_low, cal_high;
+
+ if (cpu_id.fid.bits.rdtsc == 0 ) {
+ return(-1);
+ }
+ if (len == 0) return(-2);
dst = src + len;
wlen = len / 4; /* Length is bytes */
@@ -1382,12 +1174,12 @@ ulong memspeed(ulong src, ulong len, int iter, int type)
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" (0)
+ "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"
);
}
@@ -1404,76 +1196,31 @@ ulong memspeed(ulong src, ulong len, int iter, int type)
/* Now measure the speed */
- switch (type) {
- case MS_COPY:
- /* Do the first copy to prime the cache */
- asm __volatile__ (
+ /* 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"
+ );
+ 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" \
+ "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", "eax"
- );
- }
- 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__ (
@@ -1493,32 +1240,35 @@ ulong memspeed(ulong src, ulong len, int iter, int type)
);
/* Make sure that the result fits in 32 bits */
+ //hprint(11,40,end_high);
if (end_high) {
- return(0);
- }
-
- /* If this was a copy adjust the time */
- if (type == MS_COPY) {
- end_low /= 2;
+ return(-3);
}
+ end_low /= 2;
/* Convert to clocks/KB */
end_low /= len;
end_low *= 1024;
end_low /= iter;
if (end_low == 0) {
- return(0);
+ return(-4);
}
- if(tsc_invariable){ end_low = correct_tsc(end_low); }
-
/* Convert to kbytes/sec */
+
+ if (tsc_invariable) end_low = correct_tsc(end_low);
+
return((v->clks_msec)/end_low);
}
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+
ulong correct_tsc(ulong el_org)
{
-
float coef_now, coef_max;
int msr_lo, msr_hi, is_xe;
@@ -1535,7 +1285,7 @@ ulong correct_tsc(ulong el_org)
if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; }
}
- if((cpu_id.feature_flag >> 7) & 1) {
+ if(cpu_id.fid.bits.eist) {
rdmsr(0x198, msr_lo, msr_hi);
coef_now = ((msr_lo >> 8) & 0x1F);
if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; }
@@ -1543,10 +1293,9 @@ ulong correct_tsc(ulong el_org)
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); }
-
+ if(coef_max && coef_now) {
+ el_org = (ulong)(el_org * coef_now / coef_max);
+ }
return el_org;
-
}
diff --git a/io.h b/io.h
index 5d63437..4fda2de 100644
--- a/io.h
+++ b/io.h
@@ -84,7 +84,6 @@ __OUTS(l)
* - can't use it inside a inline function (it will never be true)
* - you don't have to worry about side effects within the __builtin..
*/
-
#define outb(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outbc((val),(port)) : \
diff --git a/jedec_id.h b/jedec_id.h
index e62b343..b670f96 100644
--- a/jedec_id.h
+++ b/jedec_id.h
@@ -1,6 +1,9 @@
-/* MemTest86+ V4.00 Specific code (GPL V2.0)
+/* MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
+ * ------------------------------------------------
+ * Based on JEDEC JEP106-AG - January 2012
+ * All mo
*/
struct spd_jedec_manufacturer {
@@ -9,879 +12,975 @@ struct spd_jedec_manufacturer {
char *name;
};
-struct spd_jedec_manufacturer jep106[] = {
- { 0, 0x01, "AMD"},
- { 0, 0x02, "AMI"},
- { 0, 0x83, "Fairchild"},
- { 0, 0x04, "Fujitsu"},
- { 0, 0x85, "GTE"},
- { 0, 0x86, "Harris"},
- { 0, 0x07, "Hitachi"},
- { 0, 0x08, "Inmos"},
- { 0, 0x89, "Intel"},
- { 0, 0x8a, "I.T.T."},
- { 0, 0x0b, "Intersil"},
- { 0, 0x8c, "Monolithic Memories"},
- { 0, 0x0d, "Mostek"},
- { 0, 0x0e, "Freescale (Motorola)"},
- { 0, 0x8f, "National"},
- { 0, 0x10, "NEC"},
- { 0, 0x91, "RCA"},
- { 0, 0x92, "Raytheon"},
- { 0, 0x13, "Conexant (Rockwell)"},
- { 0, 0x94, "Seeq"},
- { 0, 0x15, "NXP (Philips)"},
- { 0, 0x16, "Synertek"},
- { 0, 0x97, "Texas Instruments"},
- { 0, 0x98, "Toshiba"},
- { 0, 0x19, "Xicor"},
- { 0, 0x1a, "Zilog"},
- { 0, 0x9b, "Eurotechnique"},
- { 0, 0x1c, "Mitsubishi"},
- { 0, 0x9d, "Lucent (AT&T)"},
- { 0, 0x9e, "Exel"},
- { 0, 0x1f, "Atmel"},
- { 0, 0x20, "SGS/Thomson"},
- { 0, 0xa1, "Lattice Semi."},
- { 0, 0xa2, "NCR"},
- { 0, 0x23, "Wafer Scale Integration"},
- { 0, 0xa4, "IBM"},
- { 0, 0x25, "Tristar"},
- { 0, 0x26, "Visic"},
- { 0, 0xa7, "Intl. CMOS Technology"},
- { 0, 0xa8, "SSSI"},
- { 0, 0x29, "MicrochipTechnology"},
- { 0, 0x2a, "Ricoh"},
- { 0, 0xab, "VLSI"},
- { 0, 0x2c, "Micron Technology"},
- { 0, 0xad, "Hynix Semiconductor"},
- { 0, 0xae, "OKI Semiconductor"},
- { 0, 0x2f, "ACTEL"},
- { 0, 0xb0, "Sharp"},
- { 0, 0x31, "Catalyst"},
- { 0, 0x32, "Panasonic"},
- { 0, 0xb3, "IDT"},
- { 0, 0x34, "Cypress"},
- { 0, 0xb5, "DEC"},
- { 0, 0xb6, "LSI Logic"},
- { 0, 0x37, "Zarlink (Plessey)"},
- { 0, 0x38, "UTMC"},
- { 0, 0xb9, "Thinking Machine"},
- { 0, 0xba, "Thomson CSF"},
- { 0, 0x3b, "Integrated CMOS (Vertex)"},
- { 0, 0xbc, "Honeywell"},
- { 0, 0x3d, "Tektronix"},
- { 0, 0x3e, "Sun Microsystems"},
- { 0, 0xbf, "SST"},
- { 0, 0x40, "ProMos/Mosel Vitelic"},
- { 0, 0xc1, "Infineon (Siemens)"},
- { 0, 0xc2, "Macronix"},
- { 0, 0x43, "Xerox"},
- { 0, 0xc4, "Plus Logic"},
- { 0, 0x45, "SanDisk"},
- { 0, 0x46, "Elan Circuit Tech."},
- { 0, 0xc7, "European Silicon Str."},
- { 0, 0xc8, "Apple Computer"},
- { 0, 0x49, "Xilinx"},
- { 0, 0x4a, "Compaq"},
- { 0, 0xcb, "Protocol Engines"},
- { 0, 0x4c, "SCI"},
- { 0, 0xcd, "Seiko Instruments"},
- { 0, 0xce, "Samsung"},
- { 0, 0x4f, "I3 Design System"},
- { 0, 0xd0, "Klic"},
- { 0, 0x51, "Crosspoint Solutions"},
- { 0, 0x52, "Alliance Semiconductor"},
- { 0, 0xd3, "Tandem"},
- { 0, 0x54, "Hewlett-Packard"},
- { 0, 0xd5, "Intg. Silicon Solutions"},
- { 0, 0xd6, "Brooktree"},
- { 0, 0x57, "New Media"},
- { 0, 0x58, "MHS Electronic"},
- { 0, 0xd9, "Performance Semi."},
- { 0, 0xda, "Winbond Electronic"},
- { 0, 0x5b, "Kawasaki Steel"},
- { 0, 0xdc, "Bright Micro"},
- { 0, 0x5d, "TECMAR"},
- { 0, 0x5e, "Exar"},
- { 0, 0xdf, "PCMCIA"},
- { 0, 0xe0, "LG Semi (Goldstar)"},
- { 0, 0x61, "Northern Telecom"},
- { 0, 0x62, "Sanyo"},
- { 0, 0xe3, "Array Microsystems"},
- { 0, 0x64, "Crystal Semiconductor"},
- { 0, 0xe5, "Analog Devices"},
- { 0, 0xe6, "PMC-Sierra"},
- { 0, 0x67, "Asparix"},
- { 0, 0x68, "Convex Computer"},
- { 0, 0xe9, "Quality Semiconductor"},
- { 0, 0xea, "Nimbus Technology"},
- { 0, 0x6b, "Transwitch"},
- { 0, 0xec, "Micronas (ITT Intermetall)"},
- { 0, 0x6d, "Cannon"},
- { 0, 0x6e, "Altera"},
- { 0, 0xef, "NEXCOM"},
- { 0, 0x70, "QUALCOMM"},
- { 0, 0xf1, "Sony"},
- { 0, 0xf2, "Cray Research"},
- { 0, 0x73, "AMS(Austria Micro)"},
- { 0, 0xf4, "Vitesse"},
- { 0, 0x75, "Aster Electronics"},
- { 0, 0x76, "Bay Networks (Synoptic)"},
- { 0, 0xf7, "Zentrum/ZMD"},
- { 0, 0xf8, "TRW"},
- { 0, 0x79, "Thesys"},
- { 0, 0x7a, "Solbourne Computer"},
- { 0, 0xfb, "Allied-Signal"},
- { 0, 0x7c, "Dialog"},
- { 0, 0xfd, "Media Vision"},
- { 0, 0xfe, "Numonyx"},
- { 1, 0x01, "Cirrus Logic"},
- { 1, 0x02, "National Instruments"},
- { 1, 0x83, "ILC Data Device"},
- { 1, 0x04, "Alcatel Mietec"},
- { 1, 0x85, "Micro Linear"},
- { 1, 0x86, "Univ. of NC"},
- { 1, 0x07, "JTAG Technologies"},
- { 1, 0x08, "BAE Systems (Loral)"},
- { 1, 0x89, "Nchip"},
- { 1, 0x8a, "Galileo Tech"},
- { 1, 0x0b, "Bestlink Systems"},
- { 1, 0x8c, "Graychip"},
- { 1, 0x0d, "GENNUM"},
- { 1, 0x0e, "VideoLogic"},
- { 1, 0x8f, "Robert Bosch"},
- { 1, 0x10, "Chip Express"},
- { 1, 0x91, "DATARAM"},
- { 1, 0x92, "United Microelectronics Corp."},
- { 1, 0x13, "TCSI"},
- { 1, 0x94, "Smart Modular"},
- { 1, 0x15, "Hughes Aircraft"},
- { 1, 0x16, "Lanstar Semiconductor"},
- { 1, 0x97, "Qlogic"},
- { 1, 0x98, "Kingston"},
- { 1, 0x19, "Music Semi"},
- { 1, 0x1a, "Ericsson Components"},
- { 1, 0x9b, "SpaSE"},
- { 1, 0x1c, "Eon Silicon Devices"},
- { 1, 0x9d, "Programmable Micro Corp"},
- { 1, 0x9e, "DoD"},
- { 1, 0x1f, "Integ. Memories Tech."},
- { 1, 0x20, "Corollary"},
- { 1, 0xa1, "Dallas Semiconductor"},
- { 1, 0xa2, "Omnivision"},
- { 1, 0x23, "EIV(Switzerland)"},
- { 1, 0xa4, "Novatel Wireless"},
- { 1, 0x25, "Zarlink (Mitel)"},
- { 1, 0x26, "Clearpoint"},
- { 1, 0xa7, "Cabletron"},
- { 1, 0xa8, "STEC (Silicon Tech)"},
- { 1, 0x29, "Vanguard"},
- { 1, 0x2a, "Hagiwara Sys-Com"},
- { 1, 0xab, "Vantis"},
- { 1, 0x2c, "Celestica"},
- { 1, 0xad, "Century"},
- { 1, 0xae, "Hal Computers"},
- { 1, 0x2f, "Rohm Company"},
- { 1, 0xb0, "Juniper Networks"},
- { 1, 0x31, "Libit Signal Processing"},
- { 1, 0x32, "Mushkin Enhanced Memory"},
- { 1, 0xb3, "Tundra Semiconductor"},
- { 1, 0x34, "Adaptec"},
- { 1, 0xb5, "LightSpeed Semi."},
- { 1, 0xb6, "ZSP Corp."},
- { 1, 0x37, "AMIC Technology"},
- { 1, 0x38, "Adobe Systems"},
- { 1, 0xb9, "Dynachip"},
- { 1, 0xba, "PNY Electronics"},
- { 1, 0x3b, "Newport Digital"},
- { 1, 0xbc, "MMC Networks"},
- { 1, 0x3d, "T Square"},
- { 1, 0x3e, "Seiko Epson"},
- { 1, 0xbf, "Broadcom"},
- { 1, 0x40, "Viking Components"},
- { 1, 0xc1, "V3 Semiconductor"},
- { 1, 0xc2, "Flextronics (Orbit Semiconductor)"},
- { 1, 0x43, "Suwa Electronics"},
- { 1, 0xc4, "Transmeta"},
- { 1, 0x45, "Micron CMS"},
- { 1, 0x46, "American Computer & Digital Components"},
- { 1, 0xc7, "Enhance 3000"},
- { 1, 0xc8, "Tower Semiconductor"},
- { 1, 0x49, "CPU Design"},
- { 1, 0x4a, "Price Point"},
- { 1, 0xcb, "Maxim Integrated Product"},
- { 1, 0x4c, "Tellabs"},
- { 1, 0xcd, "Centaur Technology"},
- { 1, 0xce, "Unigen"},
- { 1, 0x4f, "Transcend Information"},
- { 1, 0xd0, "Memory Card Technology"},
- { 1, 0x51, "CKD"},
- { 1, 0x52, "Capital Instruments"},
- { 1, 0xd3, "Aica Kogyo"},
- { 1, 0x54, "Linvex Technology"},
- { 1, 0xd5, "MSC Vertriebs"},
- { 1, 0xd6, "AKM Company"},
- { 1, 0x57, "Dynamem"},
- { 1, 0x58, "NERA ASA"},
- { 1, 0xd9, "GSI Technology"},
- { 1, 0xda, "Dane-Elec (C Memory)"},
- { 1, 0x5b, "Acorn Computers"},
- { 1, 0xdc, "Lara Technology"},
- { 1, 0x5d, "Oak Technology"},
- { 1, 0x5e, "Itec Memory"},
- { 1, 0xdf, "Tanisys Technology"},
- { 1, 0xe0, "Truevision"},
- { 1, 0x61, "Wintec Industries"},
- { 1, 0x62, "Super PC Memory"},
- { 1, 0xe3, "MGV Memory"},
- { 1, 0x64, "Galvantech"},
- { 1, 0xe5, "Gadzoox Networks"},
- { 1, 0xe6, "Multi Dimensional Cons."},
- { 1, 0x67, "GateField"},
- { 1, 0x68, "Integrated Memory System"},
- { 1, 0xe9, "Triscend"},
- { 1, 0xea, "XaQti"},
- { 1, 0x6b, "Goldenram"},
- { 1, 0xec, "Clear Logic"},
- { 1, 0x6d, "Cimaron Communications"},
- { 1, 0x6e, "Nippon Steel Semi. Corp."},
- { 1, 0xef, "Advantage Memory"},
- { 1, 0x70, "AMCC"},
- { 1, 0xf1, "LeCroy"},
- { 1, 0xf2, "Yamaha"},
- { 1, 0x73, "Digital Microwave"},
- { 1, 0xf4, "NetLogic Microsystems"},
- { 1, 0x75, "MIMOS Semiconductor"},
- { 1, 0x76, "Advanced Fibre"},
- { 1, 0xf7, "BF Goodrich Data."},
- { 1, 0xf8, "Epigram"},
- { 1, 0x79, "Acbel Polytech"},
- { 1, 0x7a, "Apacer Technology"},
- { 1, 0xfb, "Admor Memory"},
- { 1, 0x7c, "FOXCONN"},
- { 1, 0xfd, "Quadratics Superconductor"},
- { 1, 0xfe, "3COM"},
- { 2, 0x01, "Camintonn"},
- { 2, 0x02, "ISOA"},
- { 2, 0x83, "Agate Semiconductor"},
- { 2, 0x04, "ADMtek"},
- { 2, 0x85, "HYPERTEC"},
- { 2, 0x86, "Adhoc Technologies"},
- { 2, 0x07, "MOSAID Technologies"},
- { 2, 0x08, "Ardent Technologies"},
- { 2, 0x89, "Switchcore"},
- { 2, 0x8a, "Cisco Systems"},
- { 2, 0x0b, "Allayer Technologies"},
- { 2, 0x8c, "WorkX AG (Wichman)"},
- { 2, 0x0d, "Oasis Semiconductor"},
- { 2, 0x0e, "Novanet Semiconductor"},
- { 2, 0x8f, "E-M Solutions"},
- { 2, 0x10, "Power General"},
- { 2, 0x91, "Advanced Hardware Arch."},
- { 2, 0x92, "Inova Semiconductors"},
- { 2, 0x13, "Telocity"},
- { 2, 0x94, "Delkin Devices"},
- { 2, 0x15, "Symagery Microsystems"},
- { 2, 0x16, "C-Port"},
- { 2, 0x97, "SiberCore Technologies"},
- { 2, 0x98, "Southland Microsystems"},
- { 2, 0x19, "Malleable Technologies"},
- { 2, 0x1a, "Kendin Communications"},
- { 2, 0x9b, "Great Technology Microcomputer"},
- { 2, 0x1c, "Sanmina"},
- { 2, 0x9d, "HADCO"},
- { 2, 0x9e, "Corsair"},
- { 2, 0x1f, "Actrans System"},
- { 2, 0x20, "ALPHA Technologies"},
- { 2, 0xa1, "Silicon Laboratories (Cygnal)"},
- { 2, 0xa2, "Artesyn Technologies"},
- { 2, 0x23, "Align Manufacturing"},
- { 2, 0xa4, "Peregrine Semiconductor"},
- { 2, 0x25, "Chameleon Systems"},
- { 2, 0x26, "Aplus Flash Technology"},
- { 2, 0xa7, "MIPS Technologies"},
- { 2, 0xa8, "Chrysalis ITS"},
- { 2, 0x29, "ADTEC"},
- { 2, 0x2a, "Kentron Technologies"},
- { 2, 0xab, "Win Technologies"},
- { 2, 0x2c, "Tachyon Semiconductor (ASIC)"},
- { 2, 0xad, "Extreme Packet Devices"},
- { 2, 0xae, "RF Micro Devices"},
- { 2, 0x2f, "Siemens AG"},
- { 2, 0xb0, "Sarnoff"},
- { 2, 0x31, "Itautec SA"},
- { 2, 0x32, "Radiata"},
- { 2, 0xb3, "Benchmark Elect. (AVEX)"},
- { 2, 0x34, "Legend"},
- { 2, 0xb5, "SpecTek"},
- { 2, 0xb6, "Hi/fn"},
- { 2, 0x37, "Enikia"},
- { 2, 0x38, "SwitchOn Networks"},
- { 2, 0xb9, "AANetcom"},
- { 2, 0xba, "Micro Memory Bank"},
- { 2, 0x3b, "ESS Technology"},
- { 2, 0xbc, "Virata"},
- { 2, 0x3d, "Excess Bandwidth"},
- { 2, 0x3e, "West Bay Semiconductor"},
- { 2, 0xbf, "DSP Group"},
- { 2, 0x40, "Newport Communications"},
- { 2, 0xc1, "Chip2Chip"},
- { 2, 0xc2, "Phobos"},
- { 2, 0x43, "Intellitech"},
- { 2, 0xc4, "Nordic VLSI ASA"},
- { 2, 0x45, "Ishoni Networks"},
- { 2, 0x46, "Silicon Spice"},
- { 2, 0xc7, "Alchemy Semiconductor"},
- { 2, 0xc8, "Agilent Technologies"},
- { 2, 0x49, "Centillium Communications"},
- { 2, 0x4a, "W.L. Gore"},
- { 2, 0xcb, "HanBit Electronics"},
- { 2, 0x4c, "GlobeSpan"},
- { 2, 0xcd, "Element 14"},
- { 2, 0xce, "Pycon"},
- { 2, 0x4f, "Saifun Semiconductors"},
- { 2, 0xd0, "Sibyte,"},
- { 2, 0x51, "MetaLink Technologies"},
- { 2, 0x52, "Feiya Technology"},
- { 2, 0xd3, "I & C Technology"},
- { 2, 0x54, "Shikatronics"},
- { 2, 0xd5, "Elektrobit"},
- { 2, 0xd6, "Megic"},
- { 2, 0x57, "Com-Tier"},
- { 2, 0x58, "Malaysia Micro Solutions"},
- { 2, 0xd9, "Hyperchip"},
- { 2, 0xda, "Gemstone Communications"},
- { 2, 0x5b, "Anadigm (Anadyne)"},
- { 2, 0xdc, "3ParData"},
- { 2, 0x5d, "Mellanox Technologies"},
- { 2, 0x5e, "Tenx Technologies"},
- { 2, 0xdf, "Helix AG"},
- { 2, 0xe0, "Domosys"},
- { 2, 0x61, "Skyup Technology"},
- { 2, 0x62, "HiNT"},
- { 2, 0xe3, "Chiaro"},
- { 2, 0x64, "MDT Technologies"},
- { 2, 0xe5, "Exbit Technology A/S"},
- { 2, 0xe6, "Integrated Technology Express"},
- { 2, 0x67, "AVED Memory"},
- { 2, 0x68, "Legerity"},
- { 2, 0xe9, "Jasmine Networks"},
- { 2, 0xea, "Caspian Networks"},
- { 2, 0x6b, "nCUBE"},
- { 2, 0xec, "Silicon Access Networks"},
- { 2, 0x6d, "FDK"},
- { 2, 0x6e, "High Bandwidth Access"},
- { 2, 0xef, "MultiLink Technology"},
- { 2, 0x70, "BRECIS"},
- { 2, 0xf1, "World Wide Packets"},
- { 2, 0xf2, "APW"},
- { 2, 0x73, "Chicory Systems"},
- { 2, 0xf4, "Xstream Logic"},
- { 2, 0x75, "Fast-Chip"},
- { 2, 0x76, "Zucotto Wireless"},
- { 2, 0xf7, "Realchip"},
- { 2, 0xf8, "Galaxy Power"},
- { 2, 0x79, "eSilicon"},
- { 2, 0x7a, "Morphics Technology"},
- { 2, 0xfb, "Accelerant Networks"},
- { 2, 0x7c, "Silicon Wave"},
- { 2, 0xfd, "SandCraft"},
- { 2, 0xfe, "Elpida"},
- { 3, 0x01, "Solectron"},
- { 3, 0x02, "Optosys Technologies"},
- { 3, 0x83, "Buffalo (Formerly Melco)"},
- { 3, 0x04, "TriMedia Technologies"},
- { 3, 0x85, "Cyan Technologies"},
- { 3, 0x86, "Global Locate"},
- { 3, 0x07, "Optillion"},
- { 3, 0x08, "Terago Communications"},
- { 3, 0x89, "Ikanos Communications"},
- { 3, 0x8a, "Preton Technology"},
- { 3, 0x0b, "Nanya Technology"},
- { 3, 0x8c, "Elite Flash Storage"},
- { 3, 0x0d, "Mysticom"},
- { 3, 0x0e, "LightSand Communications"},
- { 3, 0x8f, "ATI Technologies"},
- { 3, 0x10, "Agere Systems"},
- { 3, 0x91, "NeoMagic"},
- { 3, 0x92, "AuroraNetics"},
- { 3, 0x13, "Golden Empire"},
- { 3, 0x94, "Mushkin"},
- { 3, 0x15, "Tioga Technologies"},
- { 3, 0x16, "Netlist"},
- { 3, 0x97, "TeraLogic"},
- { 3, 0x98, "Cicada Semiconductor"},
- { 3, 0x19, "Centon Electronics"},
- { 3, 0x1a, "Tyco Electronics"},
- { 3, 0x9b, "Magis Works"},
- { 3, 0x1c, "Zettacom"},
- { 3, 0x9d, "Cogency Semiconductor"},
- { 3, 0x9e, "Chipcon AS"},
- { 3, 0x1f, "Aspex Technology"},
- { 3, 0x20, "F5 Networks"},
- { 3, 0xa1, "Programmable Silicon Solutions"},
- { 3, 0xa2, "ChipWrights"},
- { 3, 0x23, "Acorn Networks"},
- { 3, 0xa4, "Quicklogic"},
- { 3, 0x25, "Kingmax Semiconductor"},
- { 3, 0x26, "BOPS"},
- { 3, 0xa7, "Flasys"},
- { 3, 0xa8, "BitBlitz Communications"},
- { 3, 0x29, "eMemory Technology"},
- { 3, 0x2a, "Procket Networks"},
- { 3, 0xab, "Purple Ray"},
- { 3, 0x2c, "Trebia Networks"},
- { 3, 0xad, "Delta Electronics"},
- { 3, 0xae, "Onex Communications"},
- { 3, 0x2f, "Ample Communications"},
- { 3, 0xb0, "Memory Experts Intl"},
- { 3, 0x31, "Astute Networks"},
- { 3, 0x32, "Azanda Network Devices"},
- { 3, 0xb3, "Dibcom"},
- { 3, 0x34, "Tekmos"},
- { 3, 0xb5, "API NetWorks"},
- { 3, 0xb6, "Bay Microsystems"},
- { 3, 0x37, "Firecron"},
- { 3, 0x38, "Resonext Communications"},
- { 3, 0xb9, "Tachys Technologies"},
- { 3, 0xba, "Equator Technology"},
- { 3, 0x3b, "Concept Computer"},
- { 3, 0xbc, "SILCOM"},
- { 3, 0x3d, "3Dlabs"},
- { 3, 0x3e, "c?t Magazine"},
- { 3, 0xbf, "Sanera Systems"},
- { 3, 0x40, "Silicon Packets"},
- { 3, 0xc1, "Viasystems Group"},
- { 3, 0xc2, "Simtek"},
- { 3, 0x43, "Semicon Devices Singapore"},
- { 3, 0xc4, "Satron Handelsges"},
- { 3, 0x45, "Improv Systems"},
- { 3, 0x46, "INDUSYS"},
- { 3, 0xc7, "Corrent"},
- { 3, 0xc8, "Infrant Technologies"},
- { 3, 0x49, "Ritek Corp"},
- { 3, 0x4a, "empowerTel Networks"},
- { 3, 0xcb, "Hypertec"},
- { 3, 0x4c, "Cavium Networks"},
- { 3, 0xcd, "PLX Technology"},
- { 3, 0xce, "Massana Design"},
- { 3, 0x4f, "Intrinsity"},
- { 3, 0xd0, "Valence Semiconductor"},
- { 3, 0x51, "Terawave Communications"},
- { 3, 0x52, "IceFyre Semiconductor"},
- { 3, 0xd3, "Primarion"},
- { 3, 0x54, "Picochip Designs"},
- { 3, 0xd5, "Silverback Systems"},
- { 3, 0xd6, "Jade Star Technologies"},
- { 3, 0x57, "Pijnenburg Securealink"},
- { 3, 0x58, "takeMS International AG"},
- { 3, 0xd9, "Cambridge Silicon Radio"},
- { 3, 0xda, "Swissbit"},
- { 3, 0x5b, "Nazomi Communications"},
- { 3, 0xdc, "eWave System"},
- { 3, 0x5d, "Rockwell Collins"},
- { 3, 0x5e, "Picocel Co. (Paion)"},
- { 3, 0xdf, "Alphamosaic"},
- { 3, 0xe0, "Sandburst"},
- { 3, 0x61, "SiCon Video"},
- { 3, 0x62, "NanoAmp Solutions"},
- { 3, 0xe3, "Ericsson Technology"},
- { 3, 0x64, "PrairieComm"},
- { 3, 0xe5, "Mitac International"},
- { 3, 0xe6, "Layer N Networks"},
- { 3, 0x67, "MtekVision (Atsana)"},
- { 3, 0x68, "Allegro Networks"},
- { 3, 0xe9, "Marvell Semiconductors"},
- { 3, 0xea, "Netergy Microelectronic"},
- { 3, 0x6b, "NVIDIA"},
- { 3, 0xec, "Internet Machines"},
- { 3, 0x6d, "Peak Electronics"},
- { 3, 0x6e, "Litchfield Communication"},
- { 3, 0xef, "Accton Technology"},
- { 3, 0x70, "Teradiant Networks"},
- { 3, 0xf1, "Scaleo Chip"},
- { 3, 0xf2, "Cortina Systems"},
- { 3, 0x73, "RAM Components"},
- { 3, 0xf4, "Raqia Networks"},
- { 3, 0x75, "ClearSpeed"},
- { 3, 0x76, "Matsushita Battery"},
- { 3, 0xf7, "Xelerated"},
- { 3, 0xf8, "SimpleTech"},
- { 3, 0x79, "Utron Technology"},
- { 3, 0x7a, "Astec International"},
- { 3, 0xfb, "AVM"},
- { 3, 0x7c, "Redux Communications"},
- { 3, 0xfd, "Dot Hill Systems"},
- { 3, 0xfe, "TeraChip"},
- { 4, 0x01, "T-RAM"},
- { 4, 0x02, "Innovics Wireless"},
- { 4, 0x83, "Teknovus"},
- { 4, 0x04, "KeyEye Communications"},
- { 4, 0x85, "Runcom Technologies"},
- { 4, 0x86, "RedSwitch"},
- { 4, 0x07, "Dotcast"},
- { 4, 0x08, "Silicon Mountain Memory"},
- { 4, 0x89, "Signia Technologies"},
- { 4, 0x8a, "Pixim"},
- { 4, 0x0b, "Galazar Networks"},
- { 4, 0x8c, "White Electronic Designs"},
- { 4, 0x0d, "Patriot Scientific"},
- { 4, 0x0e, "Neoaxiom"},
- { 4, 0x8f, "3Y Power Technology"},
- { 4, 0x10, "Scaleo Chip"},
- { 4, 0x91, "Potentia Power Systems"},
- { 4, 0x92, "C-guys"},
- { 4, 0x13, "Digital Communications Technology"},
- { 4, 0x94, "Silicon-Based Technology"},
- { 4, 0x15, "Fulcrum Microsystems"},
- { 4, 0x16, "Positivo Informatica"},
- { 4, 0x97, "XIOtech"},
- { 4, 0x98, "PortalPlayer"},
- { 4, 0x19, "Zhiying Software"},
- { 4, 0x1a, "ParkerVision"},
- { 4, 0x9b, "Phonex Broadband"},
- { 4, 0x1c, "Skyworks Solutions"},
- { 4, 0x9d, "Entropic Communications"},
- { 4, 0x9e, "Pacific Force Technology"},
- { 4, 0x1f, "Zensys A/S"},
- { 4, 0x20, "Legend Silicon Corp."},
- { 4, 0xa1, "Sci-worx"},
- { 4, 0xa2, "SMSC (Standard Microsystems)"},
- { 4, 0x23, "Renesas Technology"},
- { 4, 0xa4, "Raza Microelectronics"},
- { 4, 0x25, "Phyworks"},
- { 4, 0x26, "MediaTek"},
- { 4, 0xa7, "Non-cents Productions"},
- { 4, 0xa8, "US Modular"},
- { 4, 0x29, "Wintegra"},
- { 4, 0x2a, "Mathstar"},
- { 4, 0xab, "StarCore"},
- { 4, 0x2c, "Oplus Technologies"},
- { 4, 0xad, "Mindspeed"},
- { 4, 0xae, "Just Young Computer"},
- { 4, 0x2f, "Radia Communications"},
- { 4, 0xb0, "OCZ"},
- { 4, 0x31, "Emuzed"},
- { 4, 0x32, "LOGIC Devices"},
- { 4, 0xb3, "Inphi"},
- { 4, 0x34, "Quake Technologies"},
- { 4, 0xb5, "Vixel"},
- { 4, 0xb6, "SolusTek"},
- { 4, 0x37, "Kongsberg Maritime"},
- { 4, 0x38, "Faraday Technology"},
- { 4, 0xb9, "Altium"},
- { 4, 0xba, "Insyte"},
- { 4, 0x3b, "ARM"},
- { 4, 0xbc, "DigiVision"},
- { 4, 0x3d, "Vativ Technologies"},
- { 4, 0x3e, "Endicott Interconnect Technologies"},
- { 4, 0xbf, "Pericom"},
- { 4, 0x40, "Bandspeed"},
- { 4, 0xc1, "LeWiz Communications"},
- { 4, 0xc2, "CPU Technology"},
- { 4, 0x43, "Ramaxel Technology"},
- { 4, 0xc4, "DSP Group"},
- { 4, 0x45, "Axis Communications"},
- { 4, 0x46, "Legacy Electronics"},
- { 4, 0xc7, "Chrontel"},
- { 4, 0xc8, "Powerchip Semiconductor"},
- { 4, 0x49, "MobilEye Technologies"},
- { 4, 0x4a, "Excel Semiconductor"},
- { 4, 0xcb, "A-DATA Technology"},
- { 4, 0x4c, "VirtualDigm"},
- { 4, 0xcd, "G Skill Intl"},
- { 4, 0xce, "Quanta Computer"},
- { 4, 0x4f, "Yield Microelectronics"},
- { 4, 0xd0, "Afa Technologies"},
- { 4, 0x51, "KINGBOX Technology Co."},
- { 4, 0x52, "Ceva"},
- { 4, 0xd3, "iStor Networks"},
- { 4, 0x54, "Advance Modules"},
- { 4, 0xd5, "Microsoft"},
- { 4, 0xd6, "Open-Silicon"},
- { 4, 0x57, "Goal Semiconductor"},
- { 4, 0x58, "ARC International"},
- { 4, 0xd9, "Simmtec"},
- { 4, 0xda, "Metanoia"},
- { 4, 0x5b, "Key Stream"},
- { 4, 0xdc, "Lowrance Electronics"},
- { 4, 0x5d, "Adimos"},
- { 4, 0x5e, "SiGe Semiconductor"},
- { 4, 0xdf, "Fodus Communications"},
- { 4, 0xe0, "Credence Systems Corp."},
- { 4, 0x61, "Genesis Microchip"},
- { 4, 0x62, "Vihana"},
- { 4, 0xe3, "WIS Technologies"},
- { 4, 0x64, "GateChange Technologies"},
- { 4, 0xe5, "High Density Devices AS"},
- { 4, 0xe6, "Synopsys"},
- { 4, 0x67, "Gigaram"},
- { 4, 0x68, "Enigma Semiconductor"},
- { 4, 0xe9, "Century Micro"},
- { 4, 0xea, "Icera Semiconductor"},
- { 4, 0x6b, "Mediaworks Integrated Systems"},
- { 4, 0xec, "O'Neil Product Development"},
- { 4, 0x6d, "Supreme Top Technology"},
- { 4, 0x6e, "MicroDisplay"},
- { 4, 0xef, "Team Group"},
- { 4, 0x70, "Sinett"},
- { 4, 0xf1, "Toshiba"},
- { 4, 0xf2, "Tensilica"},
- { 4, 0x73, "SiRF Technology"},
- { 4, 0xf4, "Bacoc"},
- { 4, 0x75, "SMaL Camera Technologies"},
- { 4, 0x76, "Thomson SC"},
- { 4, 0xf7, "Airgo Networks"},
- { 4, 0xf8, "Wisair"},
- { 4, 0x79, "SigmaTel"},
- { 4, 0x7a, "Arkados"},
- { 4, 0xfb, "Compete IT Co. KG"},
- { 4, 0x7c, "Eudar Technology"},
- { 4, 0xfd, "Focus Enhancements"},
- { 4, 0xfe, "Xyratex"},
- { 5, 0x01, "Specular Networks"},
- { 5, 0x02, "Patriot Memory (PDP Systems)"},
- { 5, 0x83, "U-Chip Technology Corp."},
- { 5, 0x04, "Silicon Optix"},
- { 5, 0x85, "Greenfield Networks"},
- { 5, 0x86, "CompuRAM"},
- { 5, 0x07, "Stargen"},
- { 5, 0x08, "NetCell"},
- { 5, 0x89, "Excalibrus Technologies"},
- { 5, 0x8a, "SCM Microsystems"},
- { 5, 0x0b, "Xsigo Systems"},
- { 5, 0x8c, "CHIPS & Systems"},
- { 5, 0x0d, "Tier"},
- { 5, 0x0e, "CWRL Labs"},
- { 5, 0x8f, "Teradici"},
- { 5, 0x10, "Gigaram"},
- { 5, 0x91, "g2 Microsystems"},
- { 5, 0x92, "PowerFlash Semiconductor"},
- { 5, 0x13, "P.A. Semi"},
- { 5, 0x94, "NovaTech Solutions, S.A."},
- { 5, 0x15, "c2 Microsystems"},
- { 5, 0x16, "Level5 Networks"},
- { 5, 0x97, "COS Memory AG"},
- { 5, 0x98, "Innovasic Semiconductor"},
- { 5, 0x19, "02IC Co."},
- { 5, 0x1a, "Tabula,"},
- { 5, 0x9b, "Crucial Technology"},
- { 5, 0x1c, "Chelsio Communications"},
- { 5, 0x9d, "Solarflare Communications"},
- { 5, 0x9e, "Xambala"},
- { 5, 0x1f, "EADS Astrium"},
- { 5, 0x20, "Terra Semiconductor"},
- { 5, 0xa1, "Imaging Works"},
- { 5, 0xa2, "Astute Networks"},
- { 5, 0x23, "Tzero"},
- { 5, 0xa4, "Emulex"},
- { 5, 0x25, "Power-One"},
- { 5, 0x26, "Pulse~LINK"},
- { 5, 0xa7, "Hon Hai Precision Industry"},
- { 5, 0xa8, "White Rock Networks"},
- { 5, 0x29, "Telegent Systems USA"},
- { 5, 0x2a, "Atrua Technologies"},
- { 5, 0xab, "Acbel Polytech"},
- { 5, 0x2c, "eRide"},
- { 5, 0xad, "ULi Electronics"},
- { 5, 0xae, "Magnum Semiconductor"},
- { 5, 0x2f, "neoOne Technology"},
- { 5, 0xb0, "Connex Technology"},
- { 5, 0x31, "Stream Processors"},
- { 5, 0x32, "Focus Enhancements"},
- { 5, 0xb3, "Telecis Wireless"},
- { 5, 0x34, "uNav Microelectronics"},
- { 5, 0xb5, "Tarari"},
- { 5, 0xb6, "Ambric"},
- { 5, 0x37, "Newport Media"},
- { 5, 0x38, "VMTS"},
- { 5, 0xb9, "Enuclia Semiconductor"},
- { 5, 0xba, "Virtium Technology"},
- { 5, 0x3b, "Solid State System Co."},
- { 5, 0xbc, "Kian Tech LLC"},
- { 5, 0x3d, "Artimi"},
- { 5, 0x3e, "Power Quotient International"},
- { 5, 0xbf, "Avago Technologies"},
- { 5, 0x40, "ADTechnology"},
- { 5, 0xc1, "Sigma Designs"},
- { 5, 0xc2, "SiCortex"},
- { 5, 0x43, "Ventura Technology Group"},
- { 5, 0xc4, "eASIC"},
- { 5, 0x45, "M.H.S. SAS"},
- { 5, 0x46, "Micro Star International"},
- { 5, 0xc7, "Rapport"},
- { 5, 0xc8, "Makway International"},
- { 5, 0x49, "Broad Reach Engineering Co."},
- { 5, 0x4a, "Semiconductor Mfg Intl Corp"},
- { 5, 0xcb, "SiConnect"},
- { 5, 0x4c, "FCI USA"},
- { 5, 0xcd, "Validity Sensors"},
- { 5, 0xce, "Coney Technology Co."},
- { 5, 0x4f, "Spans Logic"},
- { 5, 0xd0, "Neterion"},
- { 5, 0x51, "Qimonda"},
- { 5, 0x52, "New Japan Radio Co."},
- { 5, 0xd3, "Velogix"},
- { 5, 0x54, "Montalvo Systems"},
- { 5, 0xd5, "iVivity"},
- { 5, 0xd6, "Walton Chaintech"},
- { 5, 0x57, "AENEON"},
- { 5, 0x58, "Lorom Industrial Co."},
- { 5, 0xd9, "Radiospire Networks"},
- { 5, 0xda, "Sensio Technologies"},
- { 5, 0x5b, "Nethra Imaging"},
- { 5, 0xdc, "Hexon Technology Pte"},
- { 5, 0x5d, "CompuStocx (CSX)"},
- { 5, 0x5e, "Methode Electronics"},
- { 5, 0xdf, "Connect One"},
- { 5, 0xe0, "Opulan Technologies"},
- { 5, 0x61, "Septentrio NV"},
- { 5, 0x62, "Goldenmars Technology"},
- { 5, 0xe3, "Kreton"},
- { 5, 0x64, "Cochlear"},
- { 5, 0xe5, "Altair Semiconductor"},
- { 5, 0xe6, "NetEffect"},
- { 5, 0x67, "Spansion"},
- { 5, 0x68, "Taiwan Semiconductor Mfg"},
- { 5, 0xe9, "Emphany Systems"},
- { 5, 0xea, "ApaceWave Technologies"},
- { 5, 0x6b, "Mobilygen"},
- { 5, 0xec, "Tego"},
- { 5, 0x6d, "Cswitch"},
- { 5, 0x6e, "Haier (Beijing) IC Design Co."},
- { 5, 0xef, "MetaRAM"},
- { 5, 0x70, "Axel Electronics Co."},
- { 5, 0xf1, "Tilera"},
- { 5, 0xf2, "Aquantia"},
- { 5, 0x73, "Vivace Semiconductor"},
- { 5, 0xf4, "Redpine Signals"},
- { 5, 0x75, "Octalica"},
- { 5, 0x76, "InterDigital Communications"},
- { 5, 0xf7, "Avant Technology"},
- { 5, 0xf8, "Asrock"},
- { 5, 0x79, "Availink"},
- { 5, 0x7a, "Quartics"},
- { 5, 0xfb, "Element CXI"},
- { 5, 0x7c, "Innovaciones Microelectronicas"},
- { 5, 0xfd, "VeriSilicon Microelectronics"},
- { 5, 0xfe, "W5 Networks"},
- { 6, 0x01, "MOVEKING"},
- { 6, 0x02, "Mavrix Technology"},
- { 6, 0x83, "CellGuide"},
- { 6, 0x04, "Faraday Technology"},
- { 6, 0x85, "Diablo Technologies"},
- { 6, 0x86, "Jennic"},
- { 6, 0x07, "Octasic"},
- { 6, 0x08, "Molex"},
- { 6, 0x89, "3Leaf Networks"},
- { 6, 0x8a, "Bright Micron Technology"},
- { 6, 0x0b, "Netxen"},
- { 6, 0x8c, "NextWave Broadband"},
- { 6, 0x0d, "DisplayLink"},
- { 6, 0x0e, "ZMOS Technology"},
- { 6, 0x8f, "Tec-Hill"},
- { 6, 0x10, "Multigig"},
- { 6, 0x91, "Amimon"},
- { 6, 0x92, "Euphonic Technologies"},
- { 6, 0x13, "BRN Phoenix"},
- { 6, 0x94, "InSilica"},
- { 6, 0x15, "Ember"},
- { 6, 0x16, "Avexir Technologies"},
- { 6, 0x97, "Echelon"},
- { 6, 0x98, "Edgewater Computer Systems"},
- { 6, 0x19, "XMOS Semiconductor"},
- { 6, 0x1a, "GENUSION"},
- { 6, 0x9b, "Memory Corp NV"},
- { 6, 0x1c, "SiliconBlue Technologies"},
- { 6, 0x9d, "Rambus"},
- { 6, 0x9e, "Andes Technology"},
- { 6, 0x1f, "Coronis Systems"},
- { 6, 0x20, "Achronix Semiconductor"},
- { 6, 0xa1, "Siano Mobile Silicon"},
- { 6, 0xa2, "Semtech"},
- { 6, 0x23, "Pixelworks"},
- { 6, 0xa4, "Gaisler Research AB"},
- { 6, 0x25, "Teranetics"},
- { 6, 0x26, "Toppan Printing Co."},
- { 6, 0xa7, "Kingxcon"},
- { 6, 0xa8, "Silicon Integrated Systems"},
- { 6, 0x29, "I-O Data Device"},
- { 6, 0x2a, "NDS Americas"},
- { 6, 0xab, "Solomon Systech Limited"},
- { 6, 0x2c, "On Demand Microelectronics"},
- { 6, 0xad, "Amicus Wireless"},
- { 6, 0xae, "SMARDTV SNC"},
- { 6, 0x2f, "Comsys Communication"},
- { 6, 0xb0, "Movidia"},
- { 6, 0x31, "Javad GNSS"},
- { 6, 0x32, "Montage Technology Group"},
- { 6, 0xb3, "Trident Microsystems"},
- { 6, 0x34, "Super Talent"},
- { 6, 0xb5, "Optichron"},
- { 6, 0xb6, "Future Waves UK"},
- { 6, 0x37, "SiBEAM"},
- { 6, 0x38, "Inicore,"},
- { 6, 0xb9, "Virident Systems"},
- { 6, 0xba, "M2000"},
- { 6, 0x3b, "ZeroG Wireless"},
- { 6, 0xbc, "Gingle Technology Co."},
- { 6, 0x3d, "Space Micro"},
- { 6, 0x3e, "Wilocity"},
- { 6, 0xbf, "Novafora, Ic."},
- { 6, 0x40, "iKoa"},
- { 6, 0xc1, "ASint Technology"},
- { 6, 0xc2, "Ramtron"},
- { 6, 0x43, "Plato Networks"},
- { 6, 0xc4, "IPtronics AS"},
- { 6, 0x45, "Infinite-Memories"},
- { 6, 0x46, "Parade Technologies"},
- { 6, 0xc7, "Dune Networks"},
- { 6, 0xc8, "GigaDevice Semiconductor"},
- { 6, 0x49, "Modu"},
- { 6, 0x4a, "CEITEC"},
- { 6, 0xcb, "Northrop Grumman"},
- { 6, 0x4c, "XRONET"},
- { 6, 0xcd, "Sicon Semiconductor AB"},
- { 6, 0xce, "Atla Electronics Co."},
- { 6, 0x4f, "TOPRAM Technology"},
- { 6, 0xd0, "Silego Technology"},
- { 6, 0x51, "Kinglife"},
- { 6, 0x52, "Ability Industries"},
- { 6, 0xd3, "Silicon Power Computer & Communications"},
- { 6, 0x54, "Augusta Technology"},
- { 6, 0xd5, "Nantronics Semiconductors"},
- { 6, 0xd6, "Hilscher Gesellschaft"},
- { 6, 0x57, "Quixant"},
- { 6, 0x58, "Percello"},
- { 6, 0xd9, "NextIO"},
- { 6, 0xda, "Scanimetrics"},
- { 6, 0x5b, "FS-Semi Company"},
- { 6, 0xdc, "Infinera"},
- { 6, 0x5d, "SandForce"},
- { 6, 0x5e, "Lexar Media"},
- { 6, 0xdf, "Teradyne"},
- { 6, 0xe0, "Memory Exchange Corp."},
- { 6, 0x61, "Suzhou Smartek Electronics"},
- { 6, 0x62, "Avantium"},
- { 6, 0xe3, "ATP Electronics"},
- { 6, 0x64, "Valens Semiconductor"},
- { 6, 0xe5, "Agate Logic"},
- { 6, 0xe6, "Netronome"},
- { 6, 0x67, "Zenverge"},
- { 6, 0x68, "N-trig"},
- { 6, 0xe9, "SanMax Technologies"},
- { 6, 0xea, "Contour Semiconductor"},
- { 6, 0x6b, "TwinMOS"},
- { 6, 0xec, "Silicon Systems"},
- { 6, 0x6d, "V-Color Technology"},
- { 6, 0x6e, "Certicom"},
- { 6, 0xef, "JSC ICC Milandr"},
- { 6, 0x70, "PhotoFast Global"},
- { 6, 0xf1, "InnoDisk"},
- { 6, 0xf2, "Muscle Power"},
- { 6, 0x73, "Energy Micro"},
- { 6, 0xf4, "Innofidei"},
- { 9, 0xff, ""}
+static struct spd_jedec_manufacturer jep106[] = {
+ { 0, 0x01, "AMD"},
+ { 0, 0x02, "AMI"},
+ { 0, 0x83, "Fairchild"},
+ { 0, 0x04, "Fujitsu"},
+// { 0, 0x85, "GTE"},
+ { 0, 0x86, "Harris"},
+ { 0, 0x07, "Hitachi"},
+ { 0, 0x08, "Inmos"},
+ { 0, 0x89, "Intel"},
+ { 0, 0x8a, "I.T.T."},
+ { 0, 0x0b, "Intersil"},
+ { 0, 0x8c, "Monolithic Memories"},
+ { 0, 0x0d, "Mostek"},
+ { 0, 0x0e, "Freescale"},
+ { 0, 0x8f, "National"},
+ { 0, 0x10, "NEC"},
+ { 0, 0x91, "RCA"},
+ { 0, 0x92, "Raytheon"},
+ { 0, 0x13, "Conexant"},
+// { 0, 0x94, "Seeq"},
+ { 0, 0x15, "NXP"},
+ { 0, 0x16, "Synertek"},
+ { 0, 0x97, "Texas Instruments"},
+ { 0, 0x98, "Toshiba"},
+ { 0, 0x19, "Xicor"},
+ { 0, 0x1a, "Zilog"},
+// { 0, 0x9b, "Eurotechnique"},
+ { 0, 0x1c, "Mitsubishi"},
+ { 0, 0x9d, "Lucent (AT&T)"},
+// { 0, 0x9e, "Exel"},
+ { 0, 0x1f, "Atmel"},
+ { 0, 0x20, "SGS/Thomson"},
+// { 0, 0xa1, "Lattice Semi."},
+ { 0, 0xa2, "NCR"},
+// { 0, 0x23, "Wafer Scale Integration"},
+ { 0, 0xa4, "IBM"},
+ { 0, 0x25, "Tristar"},
+// { 0, 0x26, "Visic"},
+ { 0, 0xa7, "Intl. CMOS Technology"},
+// { 0, 0xa8, "SSSI"},
+ { 0, 0x29, "MicrochipTechnology"},
+// { 0, 0x2a, "Ricoh"},
+// { 0, 0xab, "VLSI"},
+ { 0, 0x2c, "Micron"},
+ { 0, 0xad, "Hynix"},
+ { 0, 0xae, "OKI Semiconductor"},
+// { 0, 0x2f, "ACTEL"},
+ { 0, 0xb0, "Sharp"},
+ { 0, 0x31, "Catalyst"},
+ { 0, 0x32, "Panasonic"},
+ { 0, 0xb3, "IDT"},
+ { 0, 0x34, "Cypress"},
+ { 0, 0xb5, "DEC"},
+ { 0, 0xb6, "LSI Logic"},
+// { 0, 0x37, "Zarlink (Plessey)"},
+ { 0, 0x38, "UTMC"},
+// { 0, 0xb9, "Thinking Machine"},
+ { 0, 0xba, "Thomson CSF"},
+// { 0, 0x3b, "Integrated CMOS (Vertex)"},
+// { 0, 0xbc, "Honeywell"},
+ { 0, 0x3d, "Tektronix"},
+// { 0, 0x3e, "Oracle"},
+// { 0, 0xbf, "Silicon Storage Technology"},
+ { 0, 0x40, "ProMos/Mosel"},
+ { 0, 0xc1, "Infineon"},
+// { 0, 0xc2, "Macronix"},
+ { 0, 0x43, "Xerox"},
+// { 0, 0xc4, "Plus Logic"},
+ { 0, 0x45, "SanDisk"},
+// { 0, 0x46, "Elan Circuit Tech."},
+// { 0, 0xc7, "European Silicon Str."},
+ { 0, 0xc8, "Apple Computer"},
+ { 0, 0x49, "Xilinx"},
+ { 0, 0x4a, "Compaq"},
+// { 0, 0xcb, "Protocol Engines"},
+// { 0, 0x4c, "SCI"},
+ { 0, 0xcd, "Seiko Instruments"},
+ { 0, 0xce, "Samsung"},
+// { 0, 0x4f, "I3 Design System"},
+// { 0, 0xd0, "Klic"},
+// { 0, 0x51, "Crosspoint Solutions"},
+// { 0, 0x52, "Alliance Semiconductor"},
+// { 0, 0xd3, "Tandem"},
+ { 0, 0x54, "Hewlett-Packard"},
+ { 0, 0xd5, "Integrated Silicon Solutions"},
+// { 0, 0xd6, "Brooktree"},
+// { 0, 0x57, "New Media"},
+// { 0, 0x58, "MHS Electronic"},
+// { 0, 0xd9, "Performance Semi."},
+ { 0, 0xda, "Winbond Electronic"},
+// { 0, 0x5b, "Kawasaki Steel"},
+// { 0, 0xdc, "Bright Micro"},
+// { 0, 0x5d, "TECMAR"},
+ { 0, 0x5e, "Exar"},
+// { 0, 0xdf, "PCMCIA"},
+ { 0, 0xe0, "LG"},
+// { 0, 0x61, "Northern Telecom"},
+ { 0, 0x62, "Sanyo"},
+// { 0, 0xe3, "Array Microsystems"},
+// { 0, 0x64, "Crystal Semiconductor"},
+ { 0, 0xe5, "Analog Devices"},
+// { 0, 0xe6, "PMC-Sierra"},
+// { 0, 0x67, "Asparix"},
+// { 0, 0x68, "Convex Computer"},
+// { 0, 0xe9, "Quality Semiconductor"},
+// { 0, 0xea, "Nimbus Technology"},
+// { 0, 0x6b, "Transwitch"},
+// { 0, 0xec, "Micronas (ITT Intermetall)"},
+ { 0, 0x6d, "Cannon"},
+// { 0, 0x6e, "Altera"},
+// { 0, 0xef, "NEXCOM"},
+// { 0, 0x70, "QUALCOMM"},
+ { 0, 0xf1, "Sony"},
+// { 0, 0xf2, "Cray Research"},
+// { 0, 0x73, "AMS(Austria Micro)"},
+// { 0, 0xf4, "Vitesse"},
+// { 0, 0x75, "Aster Electronics"},
+// { 0, 0x76, "Bay Networks (Synoptic)"},
+// { 0, 0xf7, "Zentrum/ZMD"},
+// { 0, 0xf8, "TRW"},
+// { 0, 0x79, "Thesys"},
+// { 0, 0x7a, "Solbourne Computer"},
+ { 0, 0xfb, "Allied-Signal"},
+ { 0, 0x7c, "Dialog"},
+ { 0, 0xfd, "Media Vision"},
+// { 0, 0xfe, "Numonyx"},
+ { 1, 0x01, "Cirrus Logic"},
+ { 1, 0x02, "National Instruments"},
+// { 1, 0x83, "ILC Data Device"},
+// { 1, 0x04, "Alcatel Mietec"},
+// { 1, 0x85, "Micro Linear"},
+// { 1, 0x86, "Univ. of NC"},
+// { 1, 0x07, "JTAG Technologies"},
+// { 1, 0x08, "BAE Systems (Loral)"},
+// { 1, 0x89, "Nchip"},
+// { 1, 0x8a, "Galileo Tech"},
+// { 1, 0x0b, "Bestlink Systems"},
+// { 1, 0x8c, "Graychip"},
+// { 1, 0x0d, "GENNUM"},
+// { 1, 0x0e, "VideoLogic"},
+// { 1, 0x8f, "Robert Bosch"},
+// { 1, 0x10, "Chip Express"},
+ { 1, 0x91, "DATARAM"},
+// { 1, 0x92, "United Microelectronics Corp."},
+// { 1, 0x13, "TCSI"},
+ { 1, 0x94, "Smart Modular"},
+// { 1, 0x15, "Hughes Aircraft"},
+// { 1, 0x16, "Lanstar Semiconductor"},
+// { 1, 0x97, "Qlogic"},
+ { 1, 0x98, "Kingston"},
+// { 1, 0x19, "Music Semi"},
+// { 1, 0x1a, "Ericsson Components"},
+// { 1, 0x9b, "SpaSE"},
+// { 1, 0x1c, "Eon Silicon Devices"},
+// { 1, 0x9d, "Programmable Micro Corp"},
+// { 1, 0x9e, "DoD"},
+// { 1, 0x1f, "Integ. Memories Tech."},
+// { 1, 0x20, "Corollary"},
+// { 1, 0xa1, "Dallas Semiconductor"},
+// { 1, 0xa2, "Omnivision"},
+// { 1, 0x23, "EIV(Switzerland)"},
+// { 1, 0xa4, "Novatel Wireless"},
+// { 1, 0x25, "Zarlink (Mitel)"},
+// { 1, 0x26, "Clearpoint"},
+// { 1, 0xa7, "Cabletron"},
+// { 1, 0xa8, "STEC (Silicon Tech)"},
+// { 1, 0x29, "Vanguard"},
+// { 1, 0x2a, "Hagiwara Sys-Com"},
+// { 1, 0xab, "Vantis"},
+// { 1, 0x2c, "Celestica"},
+// { 1, 0xad, "Century"},
+// { 1, 0xae, "Hal Computers"},
+// { 1, 0x2f, "Rohm Company"},
+// { 1, 0xb0, "Juniper Networks"},
+// { 1, 0x31, "Libit Signal Processing"},
+ { 1, 0x32, "Mushkin"},
+// { 1, 0xb3, "Tundra Semiconductor"},
+ { 1, 0x34, "Adaptec"},
+// { 1, 0xb5, "LightSpeed Semi."},
+// { 1, 0xb6, "ZSP Corp."},
+// { 1, 0x37, "AMIC Technology"},
+// { 1, 0x38, "Adobe Systems"},
+// { 1, 0xb9, "Dynachip"},
+ { 1, 0xba, "PNY"},
+// { 1, 0x3b, "Newport Digital"},
+// { 1, 0xbc, "MMC Networks"},
+// { 1, 0x3d, "T Square"},
+// { 1, 0x3e, "Seiko Epson"},
+// { 1, 0xbf, "Broadcom"},
+// { 1, 0x40, "Viking Components"},
+// { 1, 0xc1, "V3 Semiconductor"},
+// { 1, 0xc2, "Flextronics (Orbit Semiconductor)"},
+// { 1, 0x43, "Suwa Electronics"},
+ { 1, 0xc4, "Transmeta"},
+ { 1, 0x45, "Micron CMS"},
+// { 1, 0x46, "American Computer & Digital Components"},
+// { 1, 0xc7, "Enhance 3000"},
+ { 1, 0xc8, "Tower Semiconductor"},
+// { 1, 0x49, "CPU Design"},
+// { 1, 0x4a, "Price Point"},
+ { 1, 0xcb, "Maxim Integrated Product"},
+// { 1, 0x4c, "Tellabs"},
+// { 1, 0xcd, "Centaur Technology"},
+ { 1, 0xce, "Unigen"},
+ { 1, 0x4f, "Transcend"},
+ { 1, 0xd0, "Memory Card"},
+// { 1, 0x51, "CKD"},
+// { 1, 0x52, "Capital Instruments"},
+// { 1, 0xd3, "Aica Kogyo"},
+// { 1, 0x54, "Linvex Technology"},
+ { 1, 0xd5, "MSC"},
+// { 1, 0xd6, "AKM Company"},
+// { 1, 0x57, "Dynamem"},
+// { 1, 0x58, "NERA ASA"},
+// { 1, 0xd9, "GSI Technology"},
+ { 1, 0xda, "Dane-Elec"},
+// { 1, 0x5b, "Acorn Computers"},
+// { 1, 0xdc, "Lara Technology"},
+// { 1, 0x5d, "Oak Technology"},
+ { 1, 0x5e, "Itec Memory"},
+// { 1, 0xdf, "Tanisys Technology"},
+// { 1, 0xe0, "Truevision"},
+ { 1, 0x61, "Wintec"},
+// { 1, 0x62, "Super PC Memory"},
+// { 1, 0xe3, "MGV Memory"},
+// { 1, 0x64, "Galvantech"},
+// { 1, 0xe5, "Gadzoox Networks"},
+// { 1, 0xe6, "Multi Dimensional Cons."},
+// { 1, 0x67, "GateField"},
+ { 1, 0x68, "Integrated Memory System"},
+// { 1, 0xe9, "Triscend"},
+// { 1, 0xea, "XaQti"},
+// { 1, 0x6b, "Goldenram"},
+// { 1, 0xec, "Clear Logic"},
+// { 1, 0x6d, "Cimaron Communications"},
+// { 1, 0x6e, "Nippon Steel Semi. Corp."},
+// { 1, 0xef, "Advantage Memory"},
+// { 1, 0x70, "AMCC"},
+ { 1, 0xf1, "LeCroy"},
+// { 1, 0xf2, "Yamaha"},
+// { 1, 0x73, "Digital Microwave"},
+// { 1, 0xf4, "NetLogic Microsystems"},
+// { 1, 0x75, "MIMOS Semiconductor"},
+// { 1, 0x76, "Advanced Fibre"},
+// { 1, 0xf7, "BF Goodrich Data."},
+// { 1, 0xf8, "Epigram"},
+// { 1, 0x79, "Acbel Polytech"},
+ { 1, 0x7a, "Apacer Technology"},
+// { 1, 0xfb, "Admor Memory"},
+ { 1, 0x7c, "FOXCONN"},
+// { 1, 0xfd, "Quadratics Superconductor"},
+// { 1, 0xfe, "3COM"},
+// { 2, 0x01, "Camintonn"},
+// { 2, 0x02, "ISOA"},
+// { 2, 0x83, "Agate Semiconductor"},
+// { 2, 0x04, "ADMtek"},
+// { 2, 0x85, "HYPERTEC"},
+// { 2, 0x86, "Adhoc Technologies"},
+// { 2, 0x07, "MOSAID Technologies"},
+// { 2, 0x08, "Ardent Technologies"},
+// { 2, 0x89, "Switchcore"},
+// { 2, 0x8a, "Cisco Systems"},
+// { 2, 0x0b, "Allayer Technologies"},
+// { 2, 0x8c, "WorkX AG (Wichman)"},
+// { 2, 0x0d, "Oasis Semiconductor"},
+// { 2, 0x0e, "Novanet Semiconductor"},
+// { 2, 0x8f, "E-M Solutions"},
+// { 2, 0x10, "Power General"},
+// { 2, 0x91, "Advanced Hardware Arch."},
+// { 2, 0x92, "Inova Semiconductors"},
+// { 2, 0x13, "Telocity"},
+// { 2, 0x94, "Delkin Devices"},
+// { 2, 0x15, "Symagery Microsystems"},
+// { 2, 0x16, "C-Port"},
+// { 2, 0x97, "SiberCore Technologies"},
+// { 2, 0x98, "Southland Microsystems"},
+// { 2, 0x19, "Malleable Technologies"},
+// { 2, 0x1a, "Kendin Communications"},
+// { 2, 0x9b, "Great Technology Microcomputer"},
+// { 2, 0x1c, "Sanmina"},
+// { 2, 0x9d, "HADCO"},
+ { 2, 0x9e, "Corsair"},
+// { 2, 0x1f, "Actrans System"},
+// { 2, 0x20, "ALPHA Technologies"},
+// { 2, 0xa1, "Silicon Laboratories (Cygnal)"},
+// { 2, 0xa2, "Artesyn Technologies"},
+// { 2, 0x23, "Align Manufacturing"},
+// { 2, 0xa4, "Peregrine Semiconductor"},
+// { 2, 0x25, "Chameleon Systems"},
+// { 2, 0x26, "Aplus Flash Technology"},
+ { 2, 0xa7, "MIPS Technologies"},
+// { 2, 0xa8, "Chrysalis ITS"},
+// { 2, 0x29, "ADTEC"},
+ { 2, 0x2a, "Kentron Technologies"},
+// { 2, 0xab, "Win Technologies"},
+// { 2, 0x2c, "Tachyon Semiconductor (ASIC)"},
+// { 2, 0xad, "Extreme Packet Devices"},
+// { 2, 0xae, "RF Micro Devices"},
+ { 2, 0x2f, "Siemens AG"},
+// { 2, 0xb0, "Sarnoff"},
+// { 2, 0x31, "Itautec SA"},
+// { 2, 0x32, "Radiata"},
+// { 2, 0xb3, "Benchmark Elect. (AVEX)"},
+// { 2, 0x34, "Legend"},
+ { 2, 0xb5, "SpecTek"},
+// { 2, 0xb6, "Hi/fn"},
+// { 2, 0x37, "Enikia"},
+// { 2, 0x38, "SwitchOn Networks"},
+// { 2, 0xb9, "AANetcom"},
+// { 2, 0xba, "Micro Memory Bank"},
+ { 2, 0x3b, "ESS Technology"},
+// { 2, 0xbc, "Virata"},
+// { 2, 0x3d, "Excess Bandwidth"},
+// { 2, 0x3e, "West Bay Semiconductor"},
+// { 2, 0xbf, "DSP Group"},
+// { 2, 0x40, "Newport Communications"},
+// { 2, 0xc1, "Chip2Chip"},
+// { 2, 0xc2, "Phobos"},
+// { 2, 0x43, "Intellitech"},
+// { 2, 0xc4, "Nordic VLSI ASA"},
+// { 2, 0x45, "Ishoni Networks"},
+// { 2, 0x46, "Silicon Spice"},
+// { 2, 0xc7, "Alchemy Semiconductor"},
+ { 2, 0xc8, "Agilent Technologies"},
+// { 2, 0x49, "Centillium Communications"},
+// { 2, 0x4a, "W.L. Gore"},
+// { 2, 0xcb, "HanBit Electronics"},
+// { 2, 0x4c, "GlobeSpan"},
+// { 2, 0xcd, "Element 14"},
+// { 2, 0xce, "Pycon"},
+// { 2, 0x4f, "Saifun Semiconductors"},
+// { 2, 0xd0, "Sibyte,"},
+// { 2, 0x51, "MetaLink Technologies"},
+// { 2, 0x52, "Feiya Technology"},
+// { 2, 0xd3, "I & C Technology"},
+// { 2, 0x54, "Shikatronics"},
+// { 2, 0xd5, "Elektrobit"},
+// { 2, 0xd6, "Megic"},
+// { 2, 0x57, "Com-Tier"},
+// { 2, 0x58, "Malaysia Micro Solutions"},
+// { 2, 0xd9, "Hyperchip"},
+// { 2, 0xda, "Gemstone Communications"},
+// { 2, 0x5b, "Anadigm (Anadyne)"},
+// { 2, 0xdc, "3ParData"},
+// { 2, 0x5d, "Mellanox Technologies"},
+// { 2, 0x5e, "Tenx Technologies"},
+// { 2, 0xdf, "Helix AG"},
+// { 2, 0xe0, "Domosys"},
+// { 2, 0x61, "Skyup Technology"},
+// { 2, 0x62, "HiNT"},
+// { 2, 0xe3, "Chiaro"},
+ { 2, 0x64, "MDT"},
+// { 2, 0xe5, "Exbit Technology A/S"},
+// { 2, 0xe6, "Integrated Technology Express"},
+// { 2, 0x67, "AVED Memory"},
+// { 2, 0x68, "Legerity"},
+// { 2, 0xe9, "Jasmine Networks"},
+// { 2, 0xea, "Caspian Networks"},
+// { 2, 0x6b, "nCUBE"},
+// { 2, 0xec, "Silicon Access Networks"},
+// { 2, 0x6d, "FDK"},
+// { 2, 0x6e, "High Bandwidth Access"},
+// { 2, 0xef, "MultiLink Technology"},
+// { 2, 0x70, "BRECIS"},
+// { 2, 0xf1, "World Wide Packets"},
+// { 2, 0xf2, "APW"},
+// { 2, 0x73, "Chicory Systems"},
+// { 2, 0xf4, "Xstream Logic"},
+// { 2, 0x75, "Fast-Chip"},
+// { 2, 0x76, "Zucotto Wireless"},
+// { 2, 0xf7, "Realchip"},
+// { 2, 0xf8, "Galaxy Power"},
+// { 2, 0x79, "eSilicon"},
+// { 2, 0x7a, "Morphics Technology"},
+// { 2, 0xfb, "Accelerant Networks"},
+// { 2, 0x7c, "Silicon Wave"},
+// { 2, 0xfd, "SandCraft"},
+ { 2, 0xfe, "Elpida"},
+// { 3, 0x01, "Solectron"},
+ { 3, 0x02, "Optosys Technologies"},
+ { 3, 0x83, "Buffalo"},
+// { 3, 0x04, "TriMedia Technologies"},
+// { 3, 0x85, "Cyan Technologies"},
+// { 3, 0x86, "Global Locate"},
+// { 3, 0x07, "Optillion"},
+// { 3, 0x08, "Terago Communications"},
+// { 3, 0x89, "Ikanos Communications"},
+ { 3, 0x8a, "Princeton"},
+ { 3, 0x0b, "Nanya"},
+// { 3, 0x8c, "Elite Flash Storage"},
+// { 3, 0x0d, "Mysticom"},
+// { 3, 0x0e, "LightSand Communications"},
+ { 3, 0x8f, "ATI"},
+// { 3, 0x10, "Agere Systems"},
+// { 3, 0x91, "NeoMagic"},
+// { 3, 0x92, "AuroraNetics"},
+// { 3, 0x13, "Golden Empire"},
+ { 3, 0x94, "Mushkin"},
+// { 3, 0x15, "Tioga Technologies"},
+ { 3, 0x16, "Netlist"},
+// { 3, 0x97, "TeraLogic"},
+// { 3, 0x98, "Cicada Semiconductor"},
+ { 3, 0x19, "Centon"},
+ { 3, 0x1a, "Tyco Electronics"},
+// { 3, 0x9b, "Magis Works"},
+// { 3, 0x1c, "Zettacom"},
+// { 3, 0x9d, "Cogency Semiconductor"},
+// { 3, 0x9e, "Chipcon AS"},
+// { 3, 0x1f, "Aspex Technology"},
+// { 3, 0x20, "F5 Networks"},
+// { 3, 0xa1, "Programmable Silicon Solutions"},
+// { 3, 0xa2, "ChipWrights"},
+// { 3, 0x23, "Acorn Networks"},
+// { 3, 0xa4, "Quicklogic"},
+ { 3, 0x25, "Kingmax"},
+// { 3, 0x26, "BOPS"},
+// { 3, 0xa7, "Flasys"},
+// { 3, 0xa8, "BitBlitz Communications"},
+ { 3, 0x29, "eMemory Technology"},
+// { 3, 0x2a, "Procket Networks"},
+// { 3, 0xab, "Purple Ray"},
+// { 3, 0x2c, "Trebia Networks"},
+// { 3, 0xad, "Delta Electronics"},
+// { 3, 0xae, "Onex Communications"},
+// { 3, 0x2f, "Ample Communications"},
+ { 3, 0xb0, "Memory Experts"},
+// { 3, 0x31, "Astute Networks"},
+// { 3, 0x32, "Azanda Network Devices"},
+// { 3, 0xb3, "Dibcom"},
+// { 3, 0x34, "Tekmos"},
+// { 3, 0xb5, "API NetWorks"},
+// { 3, 0xb6, "Bay Microsystems"},
+// { 3, 0x37, "Firecron"},
+// { 3, 0x38, "Resonext Communications"},
+// { 3, 0xb9, "Tachys Technologies"},
+// { 3, 0xba, "Equator Technology"},
+// { 3, 0x3b, "Concept Computer"},
+// { 3, 0xbc, "SILCOM"},
+// { 3, 0x3d, "3Dlabs"},
+// { 3, 0x3e, "c’t Magazine"},
+// { 3, 0xbf, "Sanera Systems"},
+// { 3, 0x40, "Silicon Packets"},
+ { 3, 0xc1, "Viasystems Group"},
+ { 3, 0xc2, "Simtek"},
+// { 3, 0x43, "Semicon Devices Singapore"},
+// { 3, 0xc4, "Satron Handelsges"},
+// { 3, 0x45, "Improv Systems"},
+// { 3, 0x46, "INDUSYS"},
+// { 3, 0xc7, "Corrent"},
+// { 3, 0xc8, "Infrant Technologies"},
+// { 3, 0x49, "Ritek Corp"},
+// { 3, 0x4a, "empowerTel Networks"},
+// { 3, 0xcb, "Hypertec"},
+// { 3, 0x4c, "Cavium Networks"},
+ { 3, 0xcd, "PLX Technology"},
+// { 3, 0xce, "Massana Design"},
+// { 3, 0x4f, "Intrinsity"},
+// { 3, 0xd0, "Valence Semiconductor"},
+// { 3, 0x51, "Terawave Communications"},
+// { 3, 0x52, "IceFyre Semiconductor"},
+// { 3, 0xd3, "Primarion"},
+// { 3, 0x54, "Picochip Designs"},
+// { 3, 0xd5, "Silverback Systems"},
+ { 3, 0xd6, "Jade Star"},
+// { 3, 0x57, "Pijnenburg Securealink"},
+ { 3, 0x58, "takeMS"},
+// { 3, 0xd9, "Cambridge Silicon Radio"},
+ { 3, 0xda, "Swissbit"},
+// { 3, 0x5b, "Nazomi Communications"},
+// { 3, 0xdc, "eWave System"},
+// { 3, 0x5d, "Rockwell Collins"},
+// { 3, 0x5e, "Picocel (Paion)"},
+// { 3, 0xdf, "Alphamosaic"},
+// { 3, 0xe0, "Sandburst"},
+// { 3, 0x61, "SiCon Video"},
+// { 3, 0x62, "NanoAmp Solutions"},
+// { 3, 0xe3, "Ericsson Technology"},
+// { 3, 0x64, "PrairieComm"},
+ { 3, 0xe5, "Mitac International"},
+// { 3, 0xe6, "Layer N Networks"},
+// { 3, 0x67, "MtekVision (Atsana)"},
+// { 3, 0x68, "Allegro Networks"},
+// { 3, 0xe9, "Marvell Semiconductors"},
+// { 3, 0xea, "Netergy Microelectronic"},
+ { 3, 0x6b, "nVidia"},
+// { 3, 0xec, "Internet Machines"},
+// { 3, 0x6d, "Peak Electronics"},
+// { 3, 0x6e, "Litchfield Communication"},
+ { 3, 0xef, "Accton"},
+// { 3, 0x70, "Teradiant Networks"},
+// { 3, 0xf1, "Scaleo Chip"},
+// { 3, 0xf2, "Cortina Systems"},
+ { 3, 0x73, "RAM Components"},
+// { 3, 0xf4, "Raqia Networks"},
+// { 3, 0x75, "ClearSpeed"},
+// { 3, 0x76, "Matsushita Battery"},
+// { 3, 0xf7, "Xelerated"},
+// { 3, 0xf8, "SimpleTech"},
+ { 3, 0x79, "Utron"},
+// { 3, 0x7a, "Astec International"},
+// { 3, 0xfb, "AVM"},
+// { 3, 0x7c, "Redux Communications"},
+// { 3, 0xfd, "Dot Hill Systems"},
+ { 3, 0xfe, "TeraChip"},
+ { 4, 0x01, "T-RAM"},
+// { 4, 0x02, "Innovics Wireless"},
+// { 4, 0x83, "Teknovus"},
+// { 4, 0x04, "KeyEye Communications"},
+// { 4, 0x85, "Runcom Technologies"},
+// { 4, 0x86, "RedSwitch"},
+// { 4, 0x07, "Dotcast"},
+ { 4, 0x08, "Silicon Mountain Memory"},
+// { 4, 0x89, "Signia Technologies"},
+// { 4, 0x8a, "Pixim"},
+// { 4, 0x0b, "Galazar Networks"},
+// { 4, 0x8c, "White Electronic Designs"},
+// { 4, 0x0d, "Patriot Scientific"},
+// { 4, 0x0e, "Neoaxiom"},
+// { 4, 0x8f, "3Y Power Technology"},
+ { 4, 0x10, "Scaleo Chip"},
+// { 4, 0x91, "Potentia Power Systems"},
+// { 4, 0x92, "C-guys"},
+// { 4, 0x13, "Digital Communications Technology"},
+// { 4, 0x94, "Silicon-Based Technology"},
+// { 4, 0x15, "Fulcrum Microsystems"},
+// { 4, 0x16, "Positivo Informatica"},
+// { 4, 0x97, "XIOtech"},
+// { 4, 0x98, "PortalPlayer"},
+// { 4, 0x19, "Zhiying Software"},
+// { 4, 0x1a, "ParkerVision"},
+// { 4, 0x9b, "Phonex Broadband"},
+// { 4, 0x1c, "Skyworks Solutions"},
+// { 4, 0x9d, "Entropic Communications"},
+// { 4, 0x9e, "Pacific Force Technology"},
+// { 4, 0x1f, "Zensys A/S"},
+// { 4, 0x20, "Legend Silicon Corp."},
+// { 4, 0xa1, "Sci-worx"},
+// { 4, 0xa2, "SMSC (Standard Microsystems)"},
+ { 4, 0x23, "Renesas"},
+// { 4, 0xa4, "Raza Microelectronics"},
+// { 4, 0x25, "Phyworks"},
+// { 4, 0x26, "MediaTek"},
+// { 4, 0xa7, "Non-cents Productions"},
+// { 4, 0xa8, "US Modular"},
+// { 4, 0x29, "Wintegra"},
+// { 4, 0x2a, "Mathstar"},
+// { 4, 0xab, "StarCore"},
+// { 4, 0x2c, "Oplus Technologies"},
+// { 4, 0xad, "Mindspeed"},
+// { 4, 0xae, "Just Young Computer"},
+// { 4, 0x2f, "Radia Communications"},
+ { 4, 0xb0, "OCZ"},
+// { 4, 0x31, "Emuzed"},
+// { 4, 0x32, "LOGIC Devices"},
+// { 4, 0xb3, "Inphi"},
+// { 4, 0x34, "Quake Technologies"},
+// { 4, 0xb5, "Vixel"},
+// { 4, 0xb6, "SolusTek"},
+// { 4, 0x37, "Kongsberg Maritime"},
+// { 4, 0x38, "Faraday Technology"},
+ { 4, 0xb9, "Altium"},
+// { 4, 0xba, "Insyte"},
+ { 4, 0x3b, "ARM"},
+// { 4, 0xbc, "DigiVision"},
+// { 4, 0x3d, "Vativ Technologies"},
+// { 4, 0x3e, "Endicott Interconnect Technologies"},
+ { 4, 0xbf, "Pericom"},
+// { 4, 0x40, "Bandspeed"},
+// { 4, 0xc1, "LeWiz Communications"},
+// { 4, 0xc2, "CPU Technology"},
+ { 4, 0x43, "Ramaxel"},
+// { 4, 0xc4, "DSP Group"},
+// { 4, 0x45, "Axis Communications"},
+ { 4, 0x46, "Legacy Electronics"},
+// { 4, 0xc7, "Chrontel"},
+// { 4, 0xc8, "Powerchip Semiconductor"},
+// { 4, 0x49, "MobilEye Technologies"},
+ { 4, 0x4a, "Excel Semiconductor"},
+ { 4, 0xcb, "A-DATA"},
+// { 4, 0x4c, "VirtualDigm"},
+ { 4, 0xcd, "G.Skill"},
+// { 4, 0xce, "Quanta Computer"},
+// { 4, 0x4f, "Yield Microelectronics"},
+// { 4, 0xd0, "Afa Technologies"},
+ { 4, 0x51, "Kingbox"},
+// { 4, 0x52, "Ceva"},
+// { 4, 0xd3, "iStor Networks"},
+// { 4, 0x54, "Advance Modules"},
+ { 4, 0xd5, "Microsoft"},
+// { 4, 0xd6, "Open-Silicon"},
+// { 4, 0x57, "Goal Semiconductor"},
+// { 4, 0x58, "ARC International"},
+ { 4, 0xd9, "Simmtec"},
+// { 4, 0xda, "Metanoia"},
+// { 4, 0x5b, "Key Stream"},
+// { 4, 0xdc, "Lowrance Electronics"},
+// { 4, 0x5d, "Adimos"},
+// { 4, 0x5e, "SiGe Semiconductor"},
+// { 4, 0xdf, "Fodus Communications"},
+// { 4, 0xe0, "Credence Systems Corp."},
+// { 4, 0x61, "Genesis Microchip"},
+// { 4, 0x62, "Vihana"},
+// { 4, 0xe3, "WIS Technologies"},
+// { 4, 0x64, "GateChange Technologies"},
+// { 4, 0xe5, "High Density Devices AS"},
+// { 4, 0xe6, "Synopsys"},
+// { 4, 0x67, "Gigaram"},
+// { 4, 0x68, "Enigma Semiconductor"},
+// { 4, 0xe9, "Century Micro"},
+// { 4, 0xea, "Icera Semiconductor"},
+// { 4, 0x6b, "Mediaworks Integrated Systems"},
+// { 4, 0xec, "O’Neil Product Development"},
+// { 4, 0x6d, "Supreme Top Technology"},
+// { 4, 0x6e, "MicroDisplay"},
+ { 4, 0xef, "Team Group"},
+// { 4, 0x70, "Sinett"},
+ { 4, 0xf1, "Toshiba"},
+// { 4, 0xf2, "Tensilica"},
+// { 4, 0x73, "SiRF Technology"},
+// { 4, 0xf4, "Bacoc"},
+// { 4, 0x75, "SMaL Camera Technologies"},
+ { 4, 0x76, "Thomson SC"},
+// { 4, 0xf7, "Airgo Networks"},
+// { 4, 0xf8, "Wisair"},
+// { 4, 0x79, "SigmaTel"},
+// { 4, 0x7a, "Arkados"},
+// { 4, 0xfb, "Compete IT KG"},
+// { 4, 0x7c, "Eudar Technology"},
+// { 4, 0xfd, "Focus Enhancements"},
+// { 4, 0xfe, "Xyratex"},
+// { 5, 0x01, "Specular Networks"},
+ { 5, 0x02, "Patriot Memory"},
+// { 5, 0x83, "U-Chip Technology Corp."},
+// { 5, 0x04, "Silicon Optix"},
+// { 5, 0x85, "Greenfield Networks"},
+ { 5, 0x86, "CompuRAM"},
+// { 5, 0x07, "Stargen"},
+// { 5, 0x08, "NetCell"},
+// { 5, 0x89, "Excalibrus Technologies"},
+// { 5, 0x8a, "SCM Microsystems"},
+// { 5, 0x0b, "Xsigo Systems"},
+// { 5, 0x8c, "CHIPS & Systems"},
+// { 5, 0x0d, "Tier"},
+// { 5, 0x0e, "CWRL Labs"},
+// { 5, 0x8f, "Teradici"},
+// { 5, 0x10, "Gigaram"},
+// { 5, 0x91, "g2 Microsystems"},
+// { 5, 0x92, "PowerFlash Semiconductor"},
+// { 5, 0x13, "P.A. Semi"},
+ { 5, 0x94, "NovaTech"},
+// { 5, 0x15, "c2 Microsystems"},
+// { 5, 0x16, "Level5 Networks"},
+ { 5, 0x97, "COS Memory"},
+// { 5, 0x98, "Innovasic Semiconductor"},
+// { 5, 0x19, "02IC"},
+// { 5, 0x1a, "Tabula"},
+ { 5, 0x9b, "Crucial"},
+// { 5, 0x1c, "Chelsio Communications"},
+// { 5, 0x9d, "Solarflare Communications"},
+// { 5, 0x9e, "Xambala"},
+// { 5, 0x1f, "EADS Astrium"},
+// { 5, 0x20, "Terra Semiconductor"},
+// { 5, 0xa1, "Imaging Works"},
+// { 5, 0xa2, "Astute Networks"},
+// { 5, 0x23, "Tzero"},
+// { 5, 0xa4, "Emulex"},
+// { 5, 0x25, "Power-One"},
+// { 5, 0x26, "Pulse~LINK"},
+// { 5, 0xa7, "Hon Hai Precision Industry"},
+// { 5, 0xa8, "White Rock Networks"},
+// { 5, 0x29, "Telegent Systems USA"},
+// { 5, 0x2a, "Atrua Technologies"},
+// { 5, 0xab, "Acbel Polytech"},
+// { 5, 0x2c, "eRide"},
+ { 5, 0xad, "ULi"},
+// { 5, 0xae, "Magnum Semiconductor"},
+// { 5, 0x2f, "neoOne Technology"},
+// { 5, 0xb0, "Connex Technology"},
+// { 5, 0x31, "Stream Processors"},
+// { 5, 0x32, "Focus Enhancements"},
+// { 5, 0xb3, "Telecis Wireless"},
+// { 5, 0x34, "uNav Microelectronics"},
+// { 5, 0xb5, "Tarari"},
+// { 5, 0xb6, "Ambric"},
+// { 5, 0x37, "Newport Media"},
+// { 5, 0x38, "VMTS"},
+// { 5, 0xb9, "Enuclia Semiconductor"},
+// { 5, 0xba, "Virtium Technology"},
+// { 5, 0x3b, "Solid State System"},
+// { 5, 0xbc, "Kian Tech LLC"},
+// { 5, 0x3d, "Artimi"},
+ { 5, 0x3e, "PQI"},
+// { 5, 0xbf, "Avago Technologies"},
+// { 5, 0x40, "ADTechnology"},
+ { 5, 0xc1, "Sigma Designs"},
+// { 5, 0xc2, "SiCortex"},
+// { 5, 0x43, "Ventura Technology Group"},
+// { 5, 0xc4, "eASIC"},
+// { 5, 0x45, "M.H.S. SAS"},
+ { 5, 0x46, "MSI"},
+// { 5, 0xc7, "Rapport"},
+// { 5, 0xc8, "Makway International"},
+// { 5, 0x49, "Broad Reach Engineering"},
+// { 5, 0x4a, "Semiconductor Mfg Intl Corp"},
+// { 5, 0xcb, "SiConnect"},
+// { 5, 0x4c, "FCI USA"},
+// { 5, 0xcd, "Validity Sensors"},
+// { 5, 0xce, "Coney Technology"},
+// { 5, 0x4f, "Spans Logic"},
+// { 5, 0xd0, "Neterion"},
+ { 5, 0x51, "Qimonda"},
+// { 5, 0x52, "New Japan Radio"},
+// { 5, 0xd3, "Velogix"},
+// { 5, 0x54, "Montalvo Systems"},
+// { 5, 0xd5, "iVivity"},
+ { 5, 0xd6, "Walton Chaintech"},
+ { 5, 0x57, "AENEON"},
+// { 5, 0x58, "Lorom Industrial"},
+// { 5, 0xd9, "Radiospire Networks"},
+// { 5, 0xda, "Sensio Technologies"},
+// { 5, 0x5b, "Nethra Imaging"},
+ { 5, 0xdc, "Hexon"},
+// { 5, 0x5d, "CompuStocx (CSX)"},
+// { 5, 0x5e, "Methode Electronics"},
+// { 5, 0xdf, "Connect One"},
+// { 5, 0xe0, "Opulan Technologies"},
+// { 5, 0x61, "Septentrio NV"},
+ { 5, 0x62, "Goldenmars"},
+ { 5, 0xe3, "Kreton"},
+// { 5, 0x64, "Cochlear"},
+// { 5, 0xe5, "Altair Semiconductor"},
+// { 5, 0xe6, "NetEffect"},
+// { 5, 0x67, "Spansion"},
+// { 5, 0x68, "Taiwan Semiconductor Mfg"},
+// { 5, 0xe9, "Emphany Systems"},
+// { 5, 0xea, "ApaceWave Technologies"},
+// { 5, 0x6b, "Mobilygen"},
+// { 5, 0xec, "Tego"},
+// { 5, 0x6d, "Cswitch"},
+// { 5, 0x6e, "Haier (Beijing) IC Design"},
+// { 5, 0xef, "MetaRAM"},
+// { 5, 0x70, "Axel Electronics"},
+// { 5, 0xf1, "Tilera"},
+// { 5, 0xf2, "Aquantia"},
+// { 5, 0x73, "Vivace Semiconductor"},
+// { 5, 0xf4, "Redpine Signals"},
+// { 5, 0x75, "Octalica"},
+// { 5, 0x76, "InterDigital Communications"},
+ { 5, 0xf7, "Avant Technology"},
+ { 5, 0xf8, "Asrock"},
+// { 5, 0x79, "Availink"},
+// { 5, 0x7a, "Quartics"},
+// { 5, 0xfb, "Element CXI"},
+// { 5, 0x7c, "Innovaciones Microelectronicas"},
+// { 5, 0xfd, "VeriSilicon Microelectronics"},
+// { 5, 0xfe, "W5 Networks"},
+// { 6, 0x01, "MOVEKING"},
+// { 6, 0x02, "Mavrix Technology"},
+// { 6, 0x83, "CellGuide"},
+// { 6, 0x04, "Faraday Technology"},
+// { 6, 0x85, "Diablo Technologies"},
+// { 6, 0x86, "Jennic"},
+// { 6, 0x07, "Octasic"},
+ { 6, 0x08, "Molex"},
+// { 6, 0x89, "3Leaf Networks"},
+// { 6, 0x8a, "Bright Micron Technology"},
+// { 6, 0x0b, "Netxen"},
+// { 6, 0x8c, "NextWave Broadband"},
+// { 6, 0x0d, "DisplayLink"},
+// { 6, 0x0e, "ZMOS Technology"},
+// { 6, 0x8f, "Tec-Hill"},
+// { 6, 0x10, "Multigig"},
+// { 6, 0x91, "Amimon"},
+// { 6, 0x92, "Euphonic Technologies"},
+// { 6, 0x13, "BRN Phoenix"},
+// { 6, 0x94, "InSilica"},
+// { 6, 0x15, "Ember"},
+ { 6, 0x16, "Avexir"},
+// { 6, 0x97, "Echelon"},
+// { 6, 0x98, "Edgewater Computer Systems"},
+// { 6, 0x19, "XMOS Semiconductor"},
+// { 6, 0x1a, "GENUSION"},
+ { 6, 0x9b, "Memory Corp NV"},
+// { 6, 0x1c, "SiliconBlue Technologies"},
+// { 6, 0x9d, "Rambus"},
+// { 6, 0x9e, "Andes Technology"},
+// { 6, 0x1f, "Coronis Systems"},
+// { 6, 0x20, "Achronix Semiconductor"},
+// { 6, 0xa1, "Siano Mobile Silicon"},
+// { 6, 0xa2, "Semtech"},
+// { 6, 0x23, "Pixelworks"},
+// { 6, 0xa4, "Gaisler Research AB"},
+// { 6, 0x25, "Teranetics"},
+// { 6, 0x26, "Toppan Printing"},
+// { 6, 0xa7, "Kingxcon"},
+ { 6, 0xa8, "SiS"},
+// { 6, 0x29, "I-O Data Device"},
+// { 6, 0x2a, "NDS Americas"},
+// { 6, 0xab, "Solomon Systech Limited"},
+// { 6, 0x2c, "On Demand Microelectronics"},
+// { 6, 0xad, "Amicus Wireless"},
+// { 6, 0xae, "SMARDTV SNC"},
+// { 6, 0x2f, "Comsys Communication"},
+// { 6, 0xb0, "Movidia"},
+// { 6, 0x31, "Javad GNSS"},
+// { 6, 0x32, "Montage Technology Group"},
+ { 6, 0xb3, "Trident"},
+ { 6, 0x34, "Super Talent"},
+// { 6, 0xb5, "Optichron"},
+// { 6, 0xb6, "Future Waves UK"},
+// { 6, 0x37, "SiBEAM"},
+// { 6, 0x38, "Inicore,"},
+// { 6, 0xb9, "Virident Systems"},
+// { 6, 0xba, "M2000"},
+// { 6, 0x3b, "ZeroG Wireless"},
+ { 6, 0xbc, "Gingle"},
+// { 6, 0x3d, "Space Micro"},
+// { 6, 0x3e, "Wilocity"},
+// { 6, 0xbf, "Novafora, Ic."},
+// { 6, 0x40, "iKoa"},
+ { 6, 0xc1, "ASint"},
+ { 6, 0xc2, "Ramtron"},
+// { 6, 0x43, "Plato Networks"},
+// { 6, 0xc4, "IPtronics AS"},
+// { 6, 0x45, "Infinite-Memories"},
+// { 6, 0x46, "Parade Technologies"},
+// { 6, 0xc7, "Dune Networks"},
+// { 6, 0xc8, "GigaDevice Semiconductor"},
+// { 6, 0x49, "Modu"},
+// { 6, 0x4a, "CEITEC"},
+// { 6, 0xcb, "Northrop Grumman"},
+// { 6, 0x4c, "XRONET"},
+// { 6, 0xcd, "Sicon Semiconductor AB"},
+// { 6, 0xce, "Atla Electronics"},
+ { 6, 0x4f, "TOPRAM"},
+// { 6, 0xd0, "Silego Technology"},
+ { 6, 0x51, "Kinglife"},
+// { 6, 0x52, "Ability Industries"},
+// { 6, 0xd3, "Silicon Power Computer & Communications"},
+// { 6, 0x54, "Augusta Technology"},
+// { 6, 0xd5, "Nantronics Semiconductors"},
+// { 6, 0xd6, "Hilscher Gesellschaft"},
+// { 6, 0x57, "Quixant"},
+// { 6, 0x58, "Percello"},
+// { 6, 0xd9, "NextIO"},
+// { 6, 0xda, "Scanimetrics"},
+// { 6, 0x5b, "FS-Semi Company"},
+// { 6, 0xdc, "Infinera"},
+ { 6, 0x5d, "SandForce"},
+ { 6, 0x5e, "Lexar Media"},
+// { 6, 0xdf, "Teradyne"},
+ { 6, 0xe0, "Memory Exchange Corp."},
+// { 6, 0x61, "Suzhou Smartek Electronics"},
+ { 6, 0x62, "Avantium"},
+// { 6, 0xe3, "ATP Electronics"},
+// { 6, 0x64, "Valens Semiconductor"},
+// { 6, 0xe5, "Agate Logic"},
+// { 6, 0xe6, "Netronome"},
+// { 6, 0x67, "Zenverge"},
+// { 6, 0x68, "N-trig"},
+// { 6, 0xe9, "SanMax Technologies"},
+// { 6, 0xea, "Contour Semiconductor"},
+ { 6, 0x6b, "TwinMOS"},
+ { 6, 0xec, "Silicon Systems"},
+// { 6, 0x6d, "V-Color Technology"},
+// { 6, 0x6e, "Certicom"},
+// { 6, 0xef, "JSC ICC Milandr"},
+// { 6, 0x70, "PhotoFast Global"},
+ { 6, 0xf1, "InnoDisk"},
+ { 6, 0xf2, "Muscle Power"},
+// { 6, 0x73, "Energy Micro"},
+// { 6, 0xf4, "Innofidei"},
+// { 6, 0x75, "CopperGate Communications"},
+// { 6, 0x76, "Holtek Semiconductor"},
+// { 6, 0xf7, "Myson Century"},
+// { 6, 0xf8, "FIDELIX"},
+// { 6, 0x79, "Red Digital Cinema"},
+// { 6, 0x7a, "Densbits Technology"},
+// { 6, 0xfb, "Zempro"},
+// { 6, 0x7c, "MoSys"},
+// { 6, 0xfd, "Provigent"},
+// { 6, 0xfe, "Triad Semiconductor"},
+// { 8, 0x01, "Siklu Communication"},
+// { 8, 0x02, "A Force Manufacturing"},
+ { 8, 0x83, "Strontium"},
+// { 8, 0x04, "Abilis Systems"},
+// { 8, 0x85, "Siglead"},
+// { 8, 0x86, "Ubicom"},
+// { 8, 0x07, "Unifosa"},
+// { 8, 0x08, "Stretch"},
+// { 8, 0x89, "Lantiq Deutschland"},
+// { 8, 0x8a, "Visipro."},
+ { 8, 0x0b, "EKMemory"},
+// { 8, 0x8c, "Microelectronics Institute ZTE"},
+// { 8, 0x0d, "Cognovo"},
+// { 8, 0x0e, "Carry Technology"},
+ { 8, 0x8f, "Nokia"},
+ { 8, 0x10, "King Tiger"},
+// { 8, 0x91, "Sierra Wireless"},
+ { 8, 0x92, "HT Micron"},
+ { 8, 0x13, "Albatron"},
+// { 8, 0x94, "Leica Geosystems AG"},
+// { 8, 0x15, "BroadLight"},
+// { 8, 0x16, "AEXEA"},
+// { 8, 0x97, "ClariPhy Communications"},
+// { 8, 0x98, "Green Plug"},
+// { 8, 0x19, "Design Art Networks"},
+// { 8, 0x1a, "Mach Xtreme Technology"},
+// { 8, 0x9b, "ATO Solutions"},
+// { 8, 0x1c, "Ramsta"},
+// { 8, 0x9d, "Greenliant Systems"},
+// { 8, 0x9e, "Teikon"},
+// { 8, 0x1f, "Antec Hadron"},
+// { 8, 0x20, "NavCom Technology"},
+// { 8, 0xa1, "Shanghai Fudan Microelectronics"},
+// { 8, 0xa2, "Calxeda"},
+// { 8, 0x23, "JSC EDC Electronics"},
+// { 8, 0xa4, "Kandit Technology"},
+// { 8, 0x25, "Ramos Technology"},
+// { 8, 0x26, "Goldenmars Technology"},
+// { 8, 0xa7, "XeL Technology"},
+// { 8, 0xa8, "Newzone"},
+ { 8, 0x29, "MercyPower"},
+// { 8, 0x2a, "Nanjing Yihuo Technology."},
+// { 8, 0xab, "Nethra Imaging"},
+// { 8, 0x2c, "SiTel Semiconductor BV"},
+// { 8, 0xad, "SolidGear"},
+ { 8, 0xae, "Topower"},
+// { 8, 0x2f, "Wilocity"},
+// { 8, 0xb0, "Profichip"},
+// { 8, 0x31, "Gerad Technologies"},
+ { 8, 0x32, "Ritek"},
+// { 8, 0xb3, "Gomos Technology Limited"},
+ { 8, 0x34, "Memoright"},
+// { 8, 0xb5, "D-Broad"},
+// { 8, 0xb6, "HiSilicon Technologies"},
+// { 8, 0x37, "Syndiant ."},
+// { 8, 0x38, "Enverv"},
+// { 8, 0xb9, "Cognex"},
+// { 8, 0xba, "Xinnova Technology"},
+ { 8, 0x3b, "Ultron"},
+// { 8, 0xbc, "Concord Idea"},
+// { 8, 0x3d, "AIM"},
+// { 8, 0x3e, "Lifetime Memory Products"},
+// { 8, 0xbf, "Ramsway"},
+// { 8, 0x40, "Recore Systems B.V."},
+// { 8, 0xc1, "Haotian Jinshibo Science Tech"},
+// { 8, 0xc2, "Being Advanced Memory"},
+// { 8, 0x43, "Adesto Technologies"},
+// { 8, 0xc4, "Giantec Semiconductor"},
+// { 8, 0x45, "HMD Electronics AG"},
+// { 8, 0x46, "Gloway International (HK)"},
+// { 8, 0xc7, "Kingcore"},
+// { 8, 0xc8, "Anucell Technology Holding"},
+// { 8, 0x49, "Accord Software & Systems Pvt."},
+// { 8, 0x4a, "Active-Semi"},
+// { 8, 0xcb, "Denso"},
+// { 8, 0x4c, "TLSI"},
+// { 8, 0xcd, "Shenzhen Daling Electronic"},
+// { 8, 0xce, "Mustang"},
+// { 8, 0x4f, "Orca Systems"},
+// { 8, 0xd0, "Passif Semiconductor"},
+// { 8, 0x51, "GigaDevice Semiconductor (Beijing)"},
+// { 8, 0x52, "Memphis Electronic"},
+// { 8, 0xd3, "Beckhoff Automation"},
+// { 8, 0x54, "Harmony Semiconductor Corp"},
+// { 8, 0xd5, "Air Computers SRL"},
+ { 8, 0xd6, "TMT Memory"},
+ { 9, 0xff, ""}
};
diff --git a/lib.c b/lib.c
index d107039..a2b829d 100644
--- a/lib.c
+++ b/lib.c
@@ -1,30 +1,25 @@
-/* lib.c - MemTest-86 Version 3.0
+/* lib.c - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- * ----------------------------------------------------
- * MemTest86+ V4.00 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, memtest@memtest.org
- * http://www.canardplus.com - http://www.memtest.org
-*/
-
+ * By Chris Brady
+ */
#include "io.h"
#include "serial.h"
#include "test.h"
#include "config.h"
#include "screen_buffer.h"
+#include "stdint.h"
+#include "cpuid.h"
#include "smp.h"
-#define NULL 0
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, 0x3e8, 0x2e8};
+const short serial_base_ports[] = {0x3f8, 0x2f8};
#if ((115200%SERIAL_BAUD_RATE) != 0)
#error Bad default baud rate
@@ -33,53 +28,55 @@ int serial_baud_rate = SERIAL_BAUD_RATE;
unsigned char serial_parity = 0;
unsigned char serial_bits = 8;
-char buf[18];
-
struct ascii_map_str {
- int ascii;
- int keycode;
+ int ascii;
+ int keycode;
};
-char *codes[] = {
- " Divide",
- " Debug",
- " NMI",
- " Brkpnt",
- "Overflow",
- " Bound",
- " Inv_Op",
- " No_Math",
- "Double_Fault",
- "Seg_Over",
- " Inv_TSS",
- " Seg_NP",
- "Stack_Fault",
- "Gen_Prot",
- "Page_Fault",
- " Resvd",
- " FPE",
- "Alignment",
- " Mch_Chk",
- "SIMD FPE"
-};
+inline void reboot(void)
+{
+
+ /* tell the BIOS to do a cold start */
+ *((unsigned short *)0x472) = 0x0;
+
+ while(1)
+ {
+ outb(0xFE, 0x64);
+ outb(0x02, 0xcf9); /* reset that doesn't rely on the keyboard controller */
+ outb(0x04, 0xcf9);
+ outb(0x0E, 0xcf9);
+ }
+}
-struct eregs {
- ulong ss;
- ulong ds;
- ulong esp;
- ulong ebp;
- ulong esi;
- ulong edi;
- ulong edx;
- ulong ecx;
- ulong ebx;
- ulong eax;
- ulong vect;
- ulong code;
- ulong eip;
- ulong cs;
- ulong eflag;
-};
+int strlen(char * string){
+ int i=0;
+ while(*string++){i++;};
+ return i;
+}
+
+int strstr(char *haystack, char * needle)
+{
+ int i=0,j=0;
+ int here=0;
+ while(1){
+ if(needle[i]==haystack[j])
+ {
+ if(here==0)
+ here=j;
+ i++;j++;
+ if(i>=strlen(needle))
+ {
+ return here;
+ }
+ if(j>=strlen(haystack))
+ {
+ return -1;
+ }
+ } else {
+ j++;i=0;here=0;
+ }
+ }
+}
int memcmp(const void *s1, const void *s2, ulong count)
{
@@ -93,19 +90,6 @@ int memcmp(const void *s1, const void *s2, ulong count)
return 0;
}
-void memcpy (void *dst, void *src, int len)
-{
- char *s = (char*)src;
- char *d = (char*)dst;
- int i;
-
- if (len <= 0) {
- return;
- }
- for (i = 0 ; i < len; i++) {
- *d++ = *s++;
- }
-}
int strncmp(const char *s1, const char *s2, ulong n) {
signed char res = 0;
while (n) {
@@ -183,12 +167,11 @@ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) {
return result;
}
-
/*
* Scroll the error message area of the screen as needed
* Starts at line LINE_SCROLL and ends at line 23
*/
-void scroll(void)
+void scroll(void)
{
int i, j;
char *s, tmp;
@@ -201,23 +184,23 @@ void scroll(void)
while (slock) {
check_input();
}
- for (i=LINE_SCROLL; i<23; i++) {
+ for (i=LINE_SCROLL; i<23; i++) {
s = (char *)(SCREEN_ADR + ((i+1) * 160));
for (j=0; j<160; j+=2, s+=2) {
*(s-160) = *s;
- tmp = get_scrn_buf(i+1, j/2);
- set_scrn_buf(i, j/2, tmp);
+ tmp = get_scrn_buf(i+1, j/2);
+ set_scrn_buf(i, j/2, tmp);
}
}
/* Clear the newly opened line */
s = (char *)(SCREEN_ADR + (23 * 160));
for (j=0; j<80; j++) {
*s = ' ';
- set_scrn_buf(23, j, ' ');
+ set_scrn_buf(23, j, ' ');
s += 2;
}
- tty_print_region(LINE_SCROLL, 0, 23, 79);
- }
+ tty_print_region(LINE_SCROLL, 0, 23, 79);
+ }
}
/*
@@ -236,6 +219,17 @@ void clear_scroll(void)
}
/*
+ * Place a single character on screen
+ */
+void cplace(int y, int x, const char c)
+{
+ char *dptr;
+
+ dptr = (char *)(SCREEN_ADR + (160*y) + (2*x));
+ *dptr = c;
+}
+
+/*
* Print characters on screen
*/
void cprint(int y, int x, const char *text)
@@ -247,37 +241,50 @@ void cprint(int y, int x, const char *text)
for (i=0; text[i]; i++) {
*dptr = text[i];
dptr += 2;
- }
- tty_print_line(y, x, text);
+ }
+ tty_print_line(y, x, text);
}
-void itoa(char s[], int n)
+void itoa(char s[], int n)
{
- int i, sign;
-
- if((sign = n) < 0)
- n = -n;
- i=0;
- do {
- s[i++] = n % 10 + '0';
- } while ((n /= 10) > 0);
- if(sign < 0)
- s[i++] = '-';
- s[i] = '\0';
- reverse(s);
+ int i, sign;
+
+ if((sign = n) < 0)
+ n = -n;
+ i=0;
+ do {
+ s[i++] = n % 10 + '0';
+ } while ((n /= 10) > 0);
+ if(sign < 0)
+ s[i++] = '-';
+ s[i] = '\0';
+ reverse(s);
}
void reverse(char s[])
{
- int c, i, j;
- for(j = 0; s[j] != 0; j++)
- ;
-
- for(i=0, j = j - 1; i < j; i++, j--) {
- c = s[i];
- s[i] = s[j];
- s[j] = c;
+ int c, i, j;
+ for(j = 0; s[j] != 0; j++)
+ ;
+
+ for(i=0, j = j - 1; i < j; i++, j--) {
+ c = s[i];
+ s[i] = s[j];
+ s[j] = c;
+ }
+}
+void memcpy (void *dst, void *src, int len)
+{
+ char *s = (char*)src;
+ char *d = (char*)dst;
+ int i;
+
+ if (len <= 0) {
+ return;
}
+ for (i = 0 ; i < len; i++) {
+ *d++ = *s++;
+ }
}
/*
@@ -311,6 +318,7 @@ void dprint(int y, int x, ulong val, int len, int right)
{
ulong j, k;
int i, flag=0;
+ char buf[18];
if (val > 999999999 || len > 9) {
return;
@@ -343,16 +351,16 @@ void dprint(int y, int x, ulong val, int len, int right)
continue;
}
if (k == 0 && flag == 0) {
- continue;
+ continue;
}
buf[i++] = k + '0';
val -= k * j;
} else {
- if (flag == 0 && i < len-1) {
- buf[i++] = '0';
- } else {
- buf[i++] = ' ';
- }
+ if (flag == 0 && i < len-1) {
+ buf[i++] = '0';
+ } else {
+ buf[i++] = ' ';
+ }
}
flag++;
}
@@ -361,56 +369,38 @@ void dprint(int y, int x, ulong val, int len, int right)
cprint(y,x,buf);
}
-
-/*
- * Get_number of digits
- */
-int getnum(ulong val)
-{
- int len = 0;
- int i = 1;
-
- while(i <= val)
- {
- len++;
- i *= 10;
- }
-
- return len;
-
-}
-
/*
* Print a hex number on screen at least digits long
*/
void hprint2(int y,int x, unsigned long val, int digits)
{
- unsigned long j;
- int i, idx, flag = 0;
+ unsigned long j;
+ int i, idx, flag = 0;
+ char buf[18];
for (i=0, idx=0; i<8; i++) {
j = val >> (28 - (4 * i));
- j &= 0xf;
- if (j < 10) {
- if (flag || j || i == 7) {
- buf[idx++] = j + '0';
- flag++;
- } else {
- buf[idx++] = '0';
- }
- } else {
- buf[idx++] = j + 'a' - 10;
- flag++;
- }
- }
- if (digits > 8) {
- digits = 8;
- }
- if (flag > digits) {
- digits = flag;
+ j &= 0xf;
+ if (j < 10) {
+ if (flag || j || i == 7) {
+ buf[idx++] = j + '0';
+ flag++;
+ } else {
+ buf[idx++] = '0';
+ }
+ } else {
+ buf[idx++] = j + 'a' - 10;
+ flag++;
+ }
}
+ if (digits > 8) {
+ digits = 8;
+ }
+ if (flag > digits) {
+ digits = flag;
+ }
buf[idx] = 0;
- cprint(y,x,buf + (idx - digits));
+ cprint(y,x,buf + (idx - digits));
}
/*
@@ -420,7 +410,7 @@ void hprint3(int y,int x, unsigned long val, int digits)
{
unsigned long j;
int i, idx, flag = 0;
-
+ char buf[18];
for (i=0, idx=0; i<digits; i++) {
j = 0xf & val;
@@ -455,7 +445,7 @@ void hprint(int y, int x, unsigned long val)
*/
void xprint(int y,int x, ulong val)
{
- ulong j;
+ ulong j;
j = (val & 0xffc00000) >> 20;
dprint(y, x, j, 4, 0);
@@ -467,12 +457,54 @@ void xprint(int y,int x, ulong val)
dprint(y, x+10, j, 4, 0);
}
+char *codes[] = {
+ " Divide",
+ " Debug",
+ " NMI",
+ " Brkpnt",
+ "Overflow",
+ " Bound",
+ " Inv_Op",
+ " No_Math",
+ "Double_Fault",
+ "Seg_Over",
+ " Inv_TSS",
+ " Seg_NP",
+ "Stack_Fault",
+ "Gen_Prot",
+ "Page_Fault",
+ " Resvd",
+ " FPE",
+ "Alignment",
+ " Mch_Chk",
+ "SIMD FPE"
+};
+
+struct eregs {
+ ulong ss;
+ ulong ds;
+ ulong esp;
+ ulong ebp;
+ ulong esi;
+ ulong edi;
+ ulong edx;
+ ulong ecx;
+ ulong ebx;
+ ulong eax;
+ ulong vect;
+ ulong code;
+ ulong eip;
+ ulong cs;
+ ulong eflag;
+};
+
/* Handle an interrupt */
void inter(struct eregs *trap_regs)
{
int i, line;
unsigned char *pp;
ulong address = 0;
+ int my_cpu_num = smp_my_cpu_num();
/* Get the page fault address */
if (trap_regs->vect == 14) {
@@ -488,13 +520,14 @@ void inter(struct eregs *trap_regs)
#endif
/* clear scrolling region */
- pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2)));
- for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) {
- *pp = ' ';
- }
+ pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2)));
+ for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) {
+ *pp = ' ';
+ }
line = LINE_SCROLL-2;
- cprint(line, 0, "Unexpected Interrupt - Halting");
+ cprint(line, 0, "Unexpected Interrupt - Halting CPU");
+ dprint(line, COL_MID + 4, my_cpu_num, 2, 1);
cprint(line+2, 0, " Type: ");
if (trap_regs->vect <= 19) {
cprint(line+2, 7, codes[trap_regs->vect]);
@@ -509,6 +542,10 @@ void inter(struct eregs *trap_regs)
hprint(line+5, 7, trap_regs->eflag);
cprint(line+6, 0, " Code: ");
hprint(line+6, 7, trap_regs->code);
+ cprint(line+7, 0, " DS: ");
+ hprint(line+7, 7, trap_regs->ds);
+ cprint(line+8, 0, " SS: ");
+ hprint(line+8, 7, trap_regs->ss);
if (trap_regs->vect == 14) {
/* Page fault address */
cprint(line+7, 0, " Addr: ");
@@ -531,21 +568,18 @@ void inter(struct eregs *trap_regs)
hprint(line+8, 25, trap_regs->ebp);
cprint(line+9, 20, "esp: ");
hprint(line+9, 25, trap_regs->esp);
- cprint(line+7, 0, " DS: ");
- hprint(line+7, 7, trap_regs->ds);
- cprint(line+8, 0, " SS: ");
- hprint(line+8, 7, trap_regs->ss);
+
cprint(line+1, 38, "Stack:");
- for (i=0; i<12; i++) {
+ for (i=0; i<10; i++) {
hprint(line+2+i, 38, trap_regs->esp+(4*i));
hprint(line+2+i, 47, *(ulong*)(trap_regs->esp+(4*i)));
- hprint(line+2+i, 57, trap_regs->esp+(4*(i+12)));
- hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+12))));
+ hprint(line+2+i, 57, trap_regs->esp+(4*(i+10)));
+ hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+10))));
}
cprint(line+11, 0, "CS:EIP: ");
pp = (unsigned char *)trap_regs->eip;
- for(i = 0; i < 10; i++) {
+ for(i = 0; i < 9; i++) {
hprint2(line+11, 8+(3*i), pp[i], 2);
}
@@ -554,22 +588,14 @@ void inter(struct eregs *trap_regs)
}
}
-void set_cache(int val)
+void set_cache(int val)
{
- extern struct cpu_ident cpu_id;
- /* 386's don't have a cache */
- if ((cpu_id.cpuid < 1) && (cpu_id.type == 3)) {
- cprint(LINE_INFO, COL_CACHE, "none");
- return;
- }
switch(val) {
case 0:
- cache_off();
- cprint(LINE_INFO, COL_CACHE, "off");
+ cache_off();
break;
case 1:
cache_on();
- cprint(LINE_INFO, COL_CACHE, " on");
break;
}
}
@@ -603,13 +629,10 @@ void check_input(void)
if ((c = get_key())) {
switch(c & 0x7f) {
- case 1:
+ case 1:
/* "ESC" key was pressed, bail out. */
cprint(LINE_RANGE, COL_MID+23, "Halting... ");
-
- /* tell the BIOS to do a warm start */
- *((unsigned short *)0x472) = 0x1234;
- outb(0xfe,0x64);
+ reboot();
break;
case 46:
/* c - Configure */
@@ -635,9 +658,9 @@ void check_input(void)
void footer()
{
- cprint(24, 0, "(ESC)Reboot (c)configuration (SP)scroll_lock (CR)scroll_unlock");
+ cprint(24, 0, "(ESC)exit (c)configuration (SP)scroll_lock (CR)scroll_unlock");
if (slock) {
- cprint(24, 74, "LOCKED");
+ cprint(24, 74, "Locked");
} else {
cprint(24, 74, " ");
}
@@ -657,7 +680,7 @@ ulong getval(int x, int y, int result_shift)
buf[i] = ' ';
}
buf[sizeof(buf)/sizeof(buf[0]) -1] = '\0';
-
+
wait_keyup();
done = 0;
n = 0;
@@ -711,7 +734,7 @@ ulong getval(int x, int y, int result_shift)
}
/* Don't allow anything to be entered after a suffix */
if (n > 0 && (
- (buf[n-1] == 'p') || (buf[n-1] == 'g') ||
+ (buf[n-1] == 'p') || (buf[n-1] == 'g') ||
(buf[n-1] == 'm') || (buf[n-1] == 'k'))) {
buf[n] = ' ';
}
@@ -743,7 +766,7 @@ ulong getval(int x, int y, int result_shift)
shift -= result_shift;
/* Compute our current value */
- val = simple_strtoul(buf, NULL, base);
+ val = simple_strtoul(buf, 0, base);
if (shift > 0) {
if (shift >= 32) {
val = 0xffffffff;
@@ -765,7 +788,7 @@ void ttyprint(int y, int x, const char *p)
{
static char sx[3];
static char sy[3];
-
+
sx[0]='\0';
sy[0]='\0';
x++; y++;
@@ -779,11 +802,10 @@ void ttyprint(int y, int x, const char *p)
serial_echo_print(p);
}
-
void serial_echo_init(void)
{
int comstat, hi, lo, serial_div;
- unsigned char lcr;
+ unsigned char lcr;
/* read the Divisor Latch */
comstat = serial_echo_inb(UART_LCR);
@@ -801,18 +823,36 @@ void serial_echo_init(void)
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 */
comstat = serial_echo_inb(UART_LSR); /* COM? LSR */
comstat = serial_echo_inb(UART_RX); /* COM? RBR */
serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */
- clear_screen_buf();
+ clear_screen_buf();
return;
}
+/*
+ * Get_number of digits
+ */
+int getnum(ulong val)
+{
+ int len = 0;
+ int i = 1;
+
+ while(i <= val)
+ {
+ len++;
+ i *= 10;
+ }
+
+ return len;
+
+}
+
+
void serial_echo_print(const char *p)
{
if (!serial_cons) {
@@ -841,9 +881,9 @@ void serial_echo_print(const char *p)
*/
struct ascii_map_str ser_map[] =
/*ascii keycode ascii keycode*/
-{
+{
/* Special cases come first so I can leave
- * their "normal" mapping in the table,
+ * their ``normal'' mapping in the table,
* without it being activated.
*/
{ 27, 0x01}, /* ^[/ESC -> ESC */
@@ -1026,7 +1066,6 @@ void wait_keyup( void ) {
}
}
-
/*
* Handles "console=<param>" command line option
*
@@ -1053,8 +1092,8 @@ void serial_console_setup(char *param)
if (option == param)
return; /* there were no digits */
- if (tty > 3)
- return; /* only ttyS0 to ttyS3 supported */
+ if (tty > 1)
+ return; /* only ttyS0 and ttyS1 supported */
if (*option == '\0' || *option == ' ')
goto save_tty; /* no options given, just ttyS? */
@@ -1102,76 +1141,59 @@ void serial_console_setup(char *param)
end++;
- if (*end != '\0' && *end != ' ')
+ if (*end != '\0' || *end != ' ')
return; /* garbage at the end */
serial_bits = bits;
- save_parity:
+ save_parity:
serial_parity = parity;
- save_baud_rate:
+ save_baud_rate:
serial_baud_rate = (int) baud_rate;
- save_tty:
+ save_tty:
serial_tty = (short) tty;
serial_cons = 1;
}
-
-#ifdef LP
-#define DATA 0x00
-#define STATUS 0x01
-#define CONTROL 0x02
-
-#define LP_PBUSY 0x80 /* inverted input, active high */
-#define LP_PERRORP 0x08 /* unchanged input, active low */
-
-#define LP_PSELECP 0x08 /* inverted output, active low */
-#define LP_PINITP 0x04 /* unchanged output, active low */
-#define LP_PSTROBE 0x01 /* short high output on raising edge */
-
-#define DELAY 0x10c6ul
-
-void lp_wait(ulong xloops)
-{
- int d0;
- __asm__("mull %0"
- :"=d" (xloops), "=&a" (d0)
- :"1" (xloops),"0" (current_cpu_data.loops_per_sec));
- __delay(xloops);
-}
-static void __delay(ulong loops)
+/* Get a comma seperated list of numbers */
+void get_list(int x, int y, int len, char *buf)
{
- int d0;
- __asm__ __volatile__(
- "\tjmp 1f\n"
- ".align 16\n"
- "1:\tjmp 2f\n"
- ".align 16\n"
- "2:\tdecl %0\n\tjns 2b"
- :"=&a" (d0)
- :"0" (loops));
-}
+ int c, n = 0;
-put_lp(char c, short port)
-{
- unsigned char status;
-
- /* Wait for printer to be ready */
- while (1) {
- status = inb(STATUS(port));
- if (status & LP_PERRORP) {
- if (status & LP_PBUSY) {
- break;
+ len--;
+ wait_keyup();
+ while(1) {
+ /* Read a new character and process it */
+ c = get_key();
+ switch(c) {
+ case 0x1c: /* CR */
+ /* If something has been entered we are done */
+ if(n) {
+ buf[n] = 0;
+ return;
+ }
+ break;
+ case 0x0e: /* BS */
+ if (n > 0) {
+ n -= 1;
+ buf[n] = ' ';
}
+ break;
+ case 0x0B: buf[n++] = '0'; break;
+ case 0x02: buf[n++] = '1'; break;
+ case 0x03: buf[n++] = '2'; break;
+ case 0x04: buf[n++] = '3'; break;
+ case 0x05: buf[n++] = '4'; break;
+ case 0x06: buf[n++] = '5'; break;
+ case 0x07: buf[n++] = '6'; break;
+ case 0x08: buf[n++] = '7'; break;
+ case 0x09: buf[n++] = '8'; break;
+ case 0x0a: buf[n++] = '9'; break;
+ case 0x33: buf[n++] = ','; break;
+ }
+ cprint(x, y, buf);
+ if (n >= len) {
+ buf[n] = 0;
+ return;
}
}
-
- outb(d, DATA(c));
- lp_wait(DELAY);
- outb((LP_PSELECP | LP_PINITP | LP_PSTROBE), CONTROL(port));
- lp_wait(DELAY);
- outb((LP_PSELECP | LP_PINITP), CONTROL(port));
- lp_wait(DELAY);
-}
-
-#endif
-
+} \ No newline at end of file
diff --git a/main.c b/main.c
index ea96f2d..0bc7ca0 100644
--- a/main.c
+++ b/main.c
@@ -1,141 +1,269 @@
-/* main.c - MemTest-86 Version 3.2
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
+ * ------------------------------------------------
+ * main.c - MemTest-86 Version 3.5
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
- * ----------------------------------------------------
- * MemTest86+ V4.00 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.canardpc.com - http://www.memtest.org
*/
-
+
+#include "stdint.h"
+#include "stddef.h"
#include "test.h"
#include "defs.h"
+#include "cpuid.h"
+#include "smp.h"
#include "config.h"
#undef TEST_TIMES
#define DEFTESTS 9
-
-extern void bzero();
-
-const struct tseq tseq[] = {
- {1, 5, 4, 0, "[Address test, walking ones] "},
- {1, 6, 4, 0, "[Address test, own address] "},
- {1, 0, 4, 0, "[Moving inversions, ones & zeros] "},
- {1, 1, 2, 0, "[Moving inversions, 8 bit pattern] "},
- {1, 10, 50, 0, "[Moving inversions, random pattern] "},
- {1, 7, 80, 0, "[Block move, 80 moves] "},
- {1, 2, 2, 0, "[Moving inversions, 32 bit pattern] "},
- {1, 9, 30, 0, "[Random number sequence] "},
- {1, 11, 6, 0, "[Modulo 20, Random pattern] "},
- {1, 8, 1, 0, "[Bit fade test, 90 min, 2 patterns] "},
- {0, 0, 0, 0, NULL}
+#define FIRST_DIVISER 3
+
+/* The main stack is allocated during boot time. The stack size should
+ * preferably be a multiple of page size(4Kbytes)
+*/
+
+extern struct cpu_ident cpu_id;
+extern char toupper(char c);
+extern int isxdigit(char c);
+extern void reboot();
+extern void bzero();
+extern void smp_set_ordinal(int me, int ord);
+extern int smp_my_ord_num(int me);
+extern int smp_ord_to_cpu(int me);
+extern void get_cpuid();
+extern void initialise_cpus();
+extern ulong rand(int cpu);
+extern void get_mem_speed(int cpu, int ncpus);
+extern void rand_seed(unsigned int seed1, unsigned int seed2, int cpu);
+extern struct barrier_s *barr;
+extern int num_cpus;
+extern int act_cpus;
+
+static int find_ticks_for_test(int test);
+void find_ticks_for_pass(void);
+int find_chunks(int test);
+static void test_setup(void);
+static int compute_segments(struct pmap map, int cpu);
+int do_test(int ord);
+struct tseq tseq[] = {
+ {1, -1, 0, 6, 0, "[Address test, walking ones, no cache] "},
+ {1, -1, 1, 6, 0, "[Address test, own address Sequential] "},
+ {1, 32, 2, 6, 0, "[Address test, own address Parallel] "},
+ {1, 32, 3, 6, 0, "[Moving inversions, 1s & 0s Parallel] "},
+ {1, 32, 5, 3, 0, "[Moving inversions, 8 bit pattern] "},
+ {1, 32, 6, 30, 0, "[Moving inversions, random pattern] "},
+ {1, 32, 7, 81, 0, "[Block move] "},
+ {1, 1, 8, 3, 0, "[Moving inversions, 32 bit pattern] "},
+ {1, 32, 9, 48, 0, "[Random number sequence] "},
+ {1, 32, 10, 6, 0, "[Modulo 20, Random pattern] "},
+ {1, 1, 11, 240, 0, "[Bit fade test, 2 patterns] "},
+ {1, 0, 0, 0, 0, NULL}
};
-char firsttime = 0;
-char cmdline_parsed = 0;
-
-struct vars variables = {};
-struct vars * const v = &variables;
-
-volatile ulong *p = 0;
-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 int c_iter;
-static struct pmap windows[] =
+volatile int mstr_cpu;
+volatile int run_cpus;
+volatile int cpu_ord=0;
+int maxcpus=MAX_CPUS;
+volatile short cpu_sel;
+volatile short cpu_mode;
+char cpu_mask[MAX_CPUS];
+long bin_mask=0xffffffff;
+short onepass;
+volatile short btflag = 0;
+volatile int test;
+short restart_flag;
+bool reloc_pending = FALSE;
+uint8_t volatile stacks[MAX_CPUS][STACKSIZE];
+int bitf_seq = 0;
+char cmdline_parsed = 0;
+struct vars variables = {};
+struct vars * const v = &variables;
+volatile int bail;
+int nticks;
+int test_ticks;
+volatile int segs;
+static int ltest;
+static int pass_flag = 0;
+volatile short start_seq = 0;
+static int c_iter;
+ulong high_test_adr;
+volatile static int window;
+volatile static unsigned long win_next;
+volatile static ulong win0_start; /* Start test address for window 0 */
+volatile static ulong win1_end; /* End address for relocation */
+volatile static struct pmap winx; /* Window struct for mapping windows */
+
+/* Find the next selected test to run */
+void next_test()
{
- { 0, 0x080000 },
- { 0, 0 },
-
- { 0x080000, 0x100000 },
- { 0x100000, 0x180000 },
- { 0x180000, 0x200000 },
-
- { 0x200000, 0x280000 },
- { 0x280000, 0x300000 },
-
- { 0x300000, 0x380000 },
- { 0x380000, 0x400000 },
-
- { 0x400000, 0x480000 },
- { 0x480000, 0x500000 },
-
- { 0x500000, 0x580000 },
- { 0x580000, 0x600000 },
-
- { 0x600000, 0x680000 },
- { 0x680000, 0x700000 },
-
- { 0x700000, 0x780000 },
- { 0x780000, 0x800000 },
+ test++;
+ while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) {
+ test++;
+ }
- { 0x800000, 0x880000 },
- { 0x880000, 0x900000 },
+ if (tseq[test].cpu_sel == 0) {
+ /* We hit the end of the list so we completed a pass */
+ pass_flag++;
+ /* Find the next test to run, start searching from 0 */
+ test = 0;
+ while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) {
+ test++;
+ }
+ }
+}
- { 0x900000, 0x980000 },
- { 0x980000, 0xA00000 },
+/* Set default values for all parameters */
+void set_defaults()
+{
+ int i;
- { 0xA00000, 0xA80000 },
- { 0xA80000, 0xB00000 },
+ if (start_seq == 2) {
+ /* This is a restart so we reset everything */
+ onepass = 0;
+ i = 0;
+ while (tseq[i].cpu_sel) {
+ tseq[i].sel = 1;
+ i++;
+ }
+ test = 0;
+ if (tseq[0].sel == 0) {
+ next_test();
+ }
+ }
+ ltest = -1;
+ win_next = 0;
+ window = 0;
+ bail = 0;
+ cpu_mode = CPM_ALL;
+ cpu_sel = 0;
+ v->printmode=PRINTMODE_ADDRESSES;
+ v->numpatn=0;
+ v->plim_lower = 0;
+ v->plim_upper = v->pmap[v->msegs-1].end;
+ v->pass = 0;
+ v->msg_line = 0;
+ v->ecount = 0;
+ v->ecc_ecount = 0;
+ 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;
+ }
+ restart_flag = 0;
+ tseq[10].sel = 0;
+}
- { 0xB00000, 0xB80000 },
- { 0xB80000, 0xC00000 },
+/* Boot trace function */
+short tidx = 25;
+void btrace(int me, int line, char *msg, int wait, long v1, long v2)
+{
+ int y, x;
- { 0xC00000, 0xC80000 },
- { 0xC80000, 0xD00000 },
+ /* Is tracing turned on? */
+ if (btflag == 0) return;
- { 0xD00000, 0xD80000 },
- { 0xD80000, 0xE00000 },
+ spin_lock(&barr->mutex);
+ y = tidx%13;
+ x = tidx/13*40;
+ cplace(y+11, x+1, ' ');
+ if (++tidx > 25) {
+ tidx = 0;
+ }
+ y = tidx%13;
+ x = tidx/13*40;
+
+ cplace(y+11, x+1, '>');
+ dprint(y+11, x+2, me, 2, 0);
+ dprint(y+11, x+5, line, 4, 0);
+ cprint(y+11, x+10, msg);
+ hprint(y+11, x+22, v1);
+ hprint(y+11, x+31, v2);
+ if (wait) {
+ wait_keyup();
+ }
+ spin_unlock(&barr->mutex);
+}
- { 0xE00000, 0xE80000 },
- { 0xE80000, 0xF00000 },
+/* Relocate the test to a new address. Be careful to not overlap! */
+static void run_at(unsigned long addr, int cpu)
+{
+ ulong *ja = (ulong *)(addr + startup_32 - _start);
- { 0xF00000, 0xF80000 },
- { 0xF80000, 0x1000000 },
-};
+ /* CPU 0, Copy memtest86+ code */
+ if (cpu == 0) {
+ memmove((void *)addr, &_start, _end - _start);
+ }
+ /* Wait for the copy */
+ barrier();
-#if (LOW_TEST_ADR > (640*1024))
-#error LOW_TEST_ADR must be below 640K
-#endif
+ /* We use a lock to insure that only one CPU at a time jumps to
+ * the new code. Some of the startup stuff is not thread safe! */
+ spin_lock(&barr->mutex);
-static int find_ticks_for_test(int ch, int test);
-static int compute_segments(int win);
-void find_ticks_for_pass(void);
+ /* Jump to the start address */
+ goto *ja;
+}
-static void __run_at(unsigned long addr)
+/* Switch from the boot stack to the main stack. First the main stack
+ * is allocated, then the contents of the boot stack are copied, then
+ * ESP is adjusted to point to the new stack.
+ */
+static void
+switch_to_main_stack(unsigned cpu_num)
{
- /* Copy memtest86+ code */
- memmove((void *)addr, &_start, _end - _start);
- /* Jump to the start address */
- p = (ulong *)(addr + startup_32 - _start);
- goto *p;
+ extern uintptr_t boot_stack;
+ extern uintptr_t boot_stack_top;
+ uintptr_t *src, *dst;
+ int offs;
+ uint8_t * stackAddr, *stackTop;
+
+ stackAddr = (uint8_t *) &stacks[cpu_num][0];
+
+ stackTop = stackAddr + STACKSIZE;
+
+ src = (uintptr_t*)&boot_stack_top;
+ dst = (uintptr_t*)stackTop;
+ do {
+ src--; dst--;
+ *dst = *src;
+ } while ((uintptr_t *)src > (uintptr_t *)&boot_stack);
+
+ offs = (uint8_t *)&boot_stack_top - stackTop;
+ __asm__ __volatile__ (
+ "subl %%eax, %%esp"
+ : /*no output*/
+ : "a" (offs) : "memory"
+ );
}
-static unsigned long run_at_addr = 0xffffffff;
-static void run_at(unsigned long addr)
+void reloc_internal(int cpu)
{
- unsigned long start;
- unsigned long len;
+ /* clear variables */
+ reloc_pending = FALSE;
- run_at_addr = addr;
+ run_at(LOW_TEST_ADR, cpu);
+}
- start = (unsigned long) &_start;
- len = _end - _start;
- 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);
- }
- else if (start + len < addr) {
- __run_at(LOW_TEST_ADR);
- }
- }
- __run_at(run_at_addr);
+void reloc(void)
+{
+ bail++;
+ reloc_pending = TRUE;
}
/* command line passing using the 'old' boot protocol */
@@ -146,484 +274,927 @@ static void run_at(unsigned long addr)
static void parse_command_line(void)
{
- char *cmdline;
+ long simple_strtoul(char *cmd, char *ptr, int base);
+ char *cp, dummy;
+ int i, j, k;
if (cmdline_parsed)
return;
+ /* Fill in the cpu mask array with the default */
+ for (i=0; i<MAX_CPUS; i++) {
+ cpu_mask[i] = 1;
+ }
+
if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC)
return;
unsigned short offset = *OLD_CL_OFFSET_ADDR;
- cmdline = MK_PTR(INITSEG, offset);
+ cp = MK_PTR(INITSEG, offset);
/* skip leading spaces */
- while (*cmdline == ' ')
- cmdline++;
+ while (*cp == ' ')
+ cp++;
- while (*cmdline) {
- if (!strncmp(cmdline, "console=", 8)) {
- cmdline += 8;
- serial_console_setup(cmdline);
+ while (*cp) {
+ if (!strncmp(cp, "console=", 8)) {
+ cp += 8;
+ serial_console_setup(cp);
+ }
+ /* Enable boot trace? */
+ if (!strncmp(cp, "btrace", 6)) {
+ cp += 6;
+ btflag++;
}
+ /* Limit number of CPUs */
+ if (!strncmp(cp, "maxcpus=", 8)) {
+ cp += 8;
+ maxcpus=(int)simple_strtoul(cp, &dummy, 10);
+ }
+ /* Run one pass and exit if there are no errors */
+ if (!strncmp(cp, "onepass", 7)) {
+ cp += 7;
+ onepass++;
+ }
+ /* Setup a list of tests to run */
+ if (!strncmp(cp, "tstlist=", 8)) {
+ cp += 8;
+ /* Clear all of the tests first */
+ k = 0;
+ while (tseq[k].cpu_sel) {
+ tseq[k].sel = 0;
+ k++;
+ }
+ /* Now enable all of the tests in the list */
+ j = 0;
+ while(*cp && isdigit(*cp)) {
+ i = *cp-'0';
+ j = j*10 + i;
+ cp++;
+ if (*cp == ',' || !isdigit(*cp)) {
+ if (j < k) {
+ tseq[j].sel = 1;
+ }
+ if (*cp != ',') break;
+ j = 0;
+ cp++;
+ }
+ }
+ }
+ /* Set a CPU mask to select CPU's to use for testing */
+ if (!strncmp(cp, "cpumask=", 8)) {
+ cp += 8;
+ if (cp[0] == '0' && toupper(cp[1]) == 'X') cp += 2;
+ while (*cp && *cp != ' ' && isxdigit(*cp)) {
+ i = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10;
+ bin_mask = bin_mask * 16 + i;
+ cp++;
+ }
+ /* Force CPU zero to always be selected */
+ bin_mask |= 1;
+ for (i=0; i<32; i++) {
+ if (((bin_mask>>i) & 1) == 0) {
+ cpu_mask[i] = 0;
+ }
+ }
+ }
/* go to the next parameter */
- while (*cmdline && *cmdline != ' ')
- cmdline++;
- while (*cmdline == ' ')
- cmdline++;
+ while (*cp && *cp != ' ') cp++;
+ while (*cp == ' ') cp++;
}
cmdline_parsed = 1;
}
-
-void do_test(void)
+void clear_screen()
{
- int i = 0, j = 0;
- unsigned long chunks;
- unsigned long lo, hi;
+ int i;
+ char *pp;
- parse_command_line();
+ /* Clear screen & set background to blue */
+ for(i=0, pp=(char *)(SCREEN_ADR); i<80*25; i++) {
+ *pp++ = ' ';
+ *pp++ = 0x17;
+ }
+ if (btflag) {
+ cprint(1, 0, "Boot Trace Enabled");
+ cprint(1, 0, "Press any key to advance to next trace point");
+ cprint(9, 1,"CPU Line Message Param #1 Param #2 CPU Line Message Param #1 Param #2");
+ cprint(10,1,"--- ---- ----------- -------- -------- --- ---- ----------- -------- --------");
+ }
- /* If we have a partial relocation finish it */
- if (run_at_addr == (unsigned long)&_start) {
- run_at_addr = 0xffffffff;
- } else if (run_at_addr != 0xffffffff) {
- __run_at(run_at_addr);
+}
+/* This is the test entry point. We get here on statup and also whenever
+ * we relocate. */
+void test_start(void)
+{
+ int my_cpu_num, my_cpu_ord, run;
+
+ /* If this is the first time here we are CPU 0 */
+ if (start_seq == 0) {
+ my_cpu_num = 0;
+ } else {
+ my_cpu_num = smp_my_cpu_num();
}
+ /* First thing, switch to main stack */
+ switch_to_main_stack(my_cpu_num);
+
+ /* First time (for this CPU) initialization */
+ if (start_seq < 2) {
+
+ /* These steps are only done by the boot cpu */
+ if (my_cpu_num == 0) {
+ my_cpu_ord = cpu_ord++;
+ smp_set_ordinal(my_cpu_num, my_cpu_ord);
+ parse_command_line();
+ clear_screen();
+ /* Initialize the barrier so the lock in btrace will work.
+ * Will get redone later when we know how many CPUs we have */
+ barrier_init(1);
+ btrace(my_cpu_num, __LINE__, "Begin ", 1, 0, 0);
+ /* Find memory size */
+ mem_size(); /* must be called before initialise_cpus(); */
+ /* Fill in the CPUID table */
+ get_cpuid();
+ /* Startup the other CPUs */
+ start_seq = 1;
+ //initialise_cpus();
+ btrace(my_cpu_num, __LINE__, "BeforeInit", 1, 0, 0);
+ /* Draw the screen and get system information */
+ init();
+
+ /* Set defaults and initialize variables */
+ set_defaults();
+
+ /* Setup base address for testing, 1 MB */
+ win0_start = 0x100;
+
+ /* Set relocation address to 32Mb if there is enough
+ * memory. Otherwise set it to 3Mb */
+ /* Large reloc addr allows for more testing overlap */
+ if ((ulong)v->pmap[v->msegs-1].end > 0x2f00) {
+ high_test_adr = 0x2000000;
+ } else {
+ high_test_adr = 0x300000;
+ }
+ win1_end = (high_test_adr >> 12);
+
+ /* Adjust the map to not test the page at 939k,
+ * reserved for locks */
+ v->pmap[0].end--;
- /* If first time, initialize test */
- if (firsttime == 0) {
- if ((ulong)&_start != LOW_TEST_ADR) {
- restart();
- }
-
- init();
-
find_ticks_for_pass();
-
- windows[0].start =
- ( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;
+ } else {
+ /* APs only, Register the APs */
+ btrace(my_cpu_num, __LINE__, "AP_Start ", 0, my_cpu_num,
+ cpu_ord);
+ smp_ap_booted(my_cpu_num);
+ /* Asign a sequential CPU ordinal to each active cpu */
+ spin_lock(&barr->mutex);
+ my_cpu_ord = cpu_ord++;
+ smp_set_ordinal(my_cpu_num, my_cpu_ord);
+ spin_unlock(&barr->mutex);
+ btrace(my_cpu_num, __LINE__, "AP_Done ", 0, my_cpu_num,
+ my_cpu_ord);
+ }
- /* 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;
+ } else {
+ /* Unlock after a relocation */
+ spin_unlock(&barr->mutex);
+ /* Get the CPU ordinal since it is lost during relocation */
+ my_cpu_ord = smp_my_ord_num(my_cpu_num);
+ btrace(my_cpu_num, __LINE__, "Reloc_Done",0,my_cpu_num,my_cpu_ord);
}
- bail = 0;
- /* Find the memory areas I am going to test */
- compute_segments(window);
- if (segs == 0) {
- goto skip_window;
- }
- /* Now map in the window... */
- if (map_page(v->map[0].pbase_addr) < 0) {
- goto skip_window;
- }
+ /* A barrier to insure that all of the CPUs are done with startup */
+ barrier();
+ btrace(my_cpu_num, __LINE__, "1st Barr ", 1, my_cpu_num, my_cpu_ord);
+
- if ((ulong)&_start > LOW_TEST_ADR) {
- /* Relocated so we need to test all selected lower memory */
- v->map[0].start = mapping(v->plim_lower);
-
-#ifdef USB_WAR
- /* We must not touch test below 0x500 memory beacuase
- * BIOS USB support clobbers location 0x410 and 0x4e0
- */
- if ((ulong)v->map[0].start < 0x500) {
- v->map[0].start = (ulong*)0x500;
+ /* Setup Memory Management and measure memory speed, we do it here
+ * because we need all of the available CPUs */
+ if (start_seq < 2) {
+
+ /* Enable floating point processing */
+ if (cpu_id.fid.bits.fpu)
+ __asm__ __volatile__ (
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ : :
+ : "ax"
+ );
+ if (cpu_id.fid.bits.sse)
+ __asm__ __volatile__ (
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000200, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ : :
+ : "ax"
+ );
+
+ btrace(my_cpu_num, __LINE__, "Mem Mgmnt ", 1, cpu_id.fid.bits.pae, cpu_id.fid.bits.lm);
+ /* Setup memory management modes */
+ /* If we have PAE, turn it on */
+ if (cpu_id.fid.bits.pae == 1) {
+ __asm__ __volatile__(
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000020, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ : :
+ : "ax"
+ );
+ cprint(LINE_TITLE+1, COL_MODE, "(PAE Mode)");
+ }
+ /* If this is a 64 CPU enable long mode */
+ if (cpu_id.fid.bits.lm == 1) {
+ __asm__ __volatile__(
+ "movl $0xc0000080, %%ecx\n\t"
+ "rdmsr\n\t"
+ "orl $0x00000100, %%eax\n\t"
+ "wrmsr\n\t"
+ : :
+ : "ax", "cx"
+ );
+ cprint(LINE_TITLE+1, COL_MODE, "(X64 Mode)");
+ }
+ /* Get the memory Speed with all CPUs */
+ get_mem_speed(my_cpu_num, num_cpus);
}
-#endif
- cprint(LINE_RANGE, COL_MID+28, " Relocated");
- } else {
- cprint(LINE_RANGE, COL_MID+28, " ");
- }
+ /* Set the initialized flag only after all of the CPU's have
+ * Reached the barrier. This insures that relocation has
+ * been completed for each CPU. */
+ btrace(my_cpu_num, __LINE__, "Start Done", 1, 0, 0);
+ start_seq = 2;
+
+ /* Loop through all tests */
+ while (1) {
+ /* If the restart flag is set all initial params */
+ if (restart_flag) {
+ set_defaults();
+ continue;
+ }
+ /* Skip single CPU tests if we are using only one CPU */
+ if (tseq[test].cpu_sel == -1 &&
+ (num_cpus == 1 || cpu_mode != CPM_ALL)) {
+ test++;
+ continue;
+ }
+
+ test_setup();
+
+ /* Loop through all possible windows */
+ while (win_next <= ((ulong)v->pmap[v->msegs-1].end + WIN_SZ)) {
+
+ /* Main scheduling barrier */
+ cprint(8, my_cpu_num+7, "W");
+ btrace(my_cpu_num, __LINE__, "Sched_Barr", 1,window,win_next);
+ barrier();
+
+ /* Don't go over the 8TB PAE limit */
+ if (win_next > MAX_MEM) {
+ break;
+ }
- /* Update display of memory segments being tested */
- lo = page_of(v->map[0].start);
- hi = page_of(v->map[segs -1].end);
- aprint(LINE_RANGE, COL_MID+9, lo);
- cprint(LINE_RANGE, COL_MID+14, " - ");
- aprint(LINE_RANGE, COL_MID+17, hi);
- aprint(LINE_RANGE, COL_MID+23, v->selected_pages);
-
-
-#ifdef TEST_TIMES
- {
- ulong l, h, t;
-
- asm __volatile__ (
- "rdtsc\n\t"
- "subl %%ebx,%%eax\n\t"
- "sbbl %%ecx,%%edx\n\t"
- :"=a" (l), "=d" (h)
- :"b" (v->snapl), "c" (v->snaph)
- );
+ /* For the bit fade test, #11, we cannot relocate so bump the
+ * window to 1 */
+ if (tseq[test].pat == 11 && window == 0) {
+ window = 1;
+ }
- cprint(20, 5, ": :");
- t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
- t += (l / v->clks_msec) / 1000;
- i = t % 60;
- dprint(20, 10, i%10, 1, 0);
- dprint(20, 9, i/10, 1, 0);
- t /= 60;
- i = t % 60;
- dprint(20, +7, i % 10, 1, 0);
- dprint(20, +6, i / 10, 1, 0);
- t /= 60;
- dprint(20, 0, t, 5, 0);
-
- asm __volatile__ ("rdtsc":"=a" (v->snapl),"=d" (v->snaph));
- }
-#endif
- /* Now setup the test parameters based on the current test number */
- /* Figure out the next test to run */
+ /* Relocate if required */
+ if (window != 0 && (ulong)&_start != LOW_TEST_ADR) {
+ btrace(my_cpu_num, __LINE__, "Sched_RelL", 1,0,0);
+ run_at(LOW_TEST_ADR, my_cpu_num);
+ }
+ if (window == 0 && v->plim_lower >= win0_start) {
+ window++;
+ }
+ if (window == 0 && (ulong)&_start == LOW_TEST_ADR) {
+ btrace(my_cpu_num, __LINE__, "Sched_RelH", 1,0,0);
+ run_at(high_test_adr, my_cpu_num);
+ }
+
+ /* Decide which CPU(s) to use */
+ btrace(my_cpu_num, __LINE__, "Sched_CPU0",1,cpu_sel,
+ tseq[test].cpu_sel);
+ run = 1;
+ switch(cpu_mode) {
+ case CPM_RROBIN:
+ case CPM_SEQ:
+ /* Select a single CPU */
+ if (my_cpu_ord == cpu_sel) {
+ mstr_cpu = cpu_sel;
+ run_cpus = 1;
+ } else {
+ run = 0;
+ }
+ break;
+ case CPM_ALL:
+ /* Use all CPUs */
+ if (tseq[test].cpu_sel == -1) {
+ /* Round robin through all of the CPUs */
+ if (my_cpu_ord == cpu_sel) {
+ mstr_cpu = cpu_sel;
+ run_cpus = 1;
+ } else {
+ run = 0;
+ }
+ } else {
+ /* Use the number of CPUs specified by the test,
+ * Starting with zero */
+ if (my_cpu_ord >= tseq[test].cpu_sel) {
+ run = 0;
+ }
+ /* Set the master CPU to the highest CPU number
+ * that has been selected */
+ if (act_cpus < tseq[test].cpu_sel) {
+ mstr_cpu = act_cpus-1;
+ run_cpus = act_cpus;
+ } else {
+ mstr_cpu = tseq[test].cpu_sel-1;
+ run_cpus = tseq[test].cpu_sel;
+ }
+ }
+ }
+ btrace(my_cpu_num, __LINE__, "Sched_CPU1",1,run_cpus,run);
+ barrier();
+ dprint(9, 7, run_cpus, 2, 0);
+
+ /* Setup a sub barrier for only the selected CPUs */
+ if (my_cpu_ord == mstr_cpu) {
+ s_barrier_init(run_cpus);
+ }
+
+ /* Make sure the the sub barrier is ready before proceeding */
+ barrier();
+
+ /* Not selected CPUs go back to the scheduling barrier */
+ if (run == 0 ) {
+ continue;
+ }
+ cprint(8, my_cpu_num+7, "-");
+ btrace(my_cpu_num, __LINE__, "Sched_Win0",1,window,win_next);
+
+ /* Do we need to exit */
+ if(reloc_pending) {
+ reloc_internal(my_cpu_num);
+ }
+
+ if (my_cpu_ord == mstr_cpu) {
+ switch (window) {
+ /* Special case for relocation */
+ case 0:
+ winx.start = 0;
+ winx.end = win1_end;
+ window++;
+ break;
+ /* Special case for first segment */
+ case 1:
+ winx.start = win0_start;
+ winx.end = WIN_SZ;
+ win_next += WIN_SZ;
+ window++;
+ break;
+ /* For all other windows */
+ default:
+ winx.start = win_next;
+ win_next += WIN_SZ;
+ winx.end = win_next;
+ }
+ btrace(my_cpu_num,__LINE__,"Sched_Win1",1,winx.start,
+ winx.end);
+
+ /* Find the memory areas to test */
+ segs = compute_segments(winx, my_cpu_num);
+ }
+ s_barrier();
+ btrace(my_cpu_num,__LINE__,"Sched_Win2",1,segs,
+ v->map[0].pbase_addr);
+
+ if (segs == 0) {
+ /* No memory in this window so skip it */
+ continue;
+ }
+
+ /* map in the window... */
+ if (map_page(v->map[0].pbase_addr) < 0) {
+ /* Either there is no PAE or we are at the PAE limit */
+ break;
+ }
+
+ btrace(my_cpu_num, __LINE__, "Strt_Test ",1,my_cpu_num,
+ my_cpu_ord);
+ do_test(my_cpu_ord);
+ btrace(my_cpu_num, __LINE__, "End_Test ",1,my_cpu_num,
+ my_cpu_ord);
+
+ paging_off();
+
+ } /* End of window loop */
+
+ s_barrier();
+ btrace(my_cpu_num, __LINE__, "End_Win ",1,test, window);
+
+ /* Setup for the next set of windows */
+ win_next = 0;
+ window = 0;
+ bail = 0;
+
+ /* Only the master CPU does the end of test housekeeping */
+ if (my_cpu_ord != mstr_cpu) {
+ continue;
+ }
+
+ /* Special handling for the bit fade test #11 */
+ if (tseq[test].pat == 11 && bitf_seq != 6) {
+ /* Keep going until the sequence is complete. */
+ bitf_seq++;
+ continue;
+ } else {
+ bitf_seq = 0;
+ }
+
+ /* Select advancement of CPUs and next test */
+ switch(cpu_mode) {
+ case CPM_RROBIN:
+ if (++cpu_sel >= act_cpus) {
+ cpu_sel = 0;
+ }
+ next_test();
+ break;
+ case CPM_SEQ:
+ if (++cpu_sel >= act_cpus) {
+ cpu_sel = 0;
+ next_test();
+ }
+ break;
+ case CPM_ALL:
+ if (tseq[test].cpu_sel == -1)
+ {
+ /* Do the same test for each CPU */
+ if (++cpu_sel >= act_cpus)
+ {
+ cpu_sel = 0;
+ next_test();
+ } else {
+ continue;
+ }
+ } else {
+ next_test();
+ }
+ } //????
+ btrace(my_cpu_num, __LINE__, "Next_CPU ",1,cpu_sel,test);
+
+ /* If this was the last test then we finished a pass */
+ if (pass_flag)
+ {
+ pass_flag = 0;
+
+ v->pass++;
+
+ dprint(LINE_INFO, 49, v->pass, 5, 0);
+ find_ticks_for_pass();
+ ltest = -1;
+
+ if (v->ecount == 0)
+ {
+ /* If onepass is enabled and we did not get any errors
+ * reboot to exit the test */
+ if (onepass) { reboot(); }
+ if (!btflag) cprint(LINE_MSG, COL_MSG-8, "** Pass complete, no errors, press Esc to exit **");
+ if(BEEP_END_NO_ERROR)
+ {
+ beep(1000);
+ beep(2000);
+ beep(1000);
+ beep(2000);
+ }
+ }
+ }
+
+ bail=0;
+ } /* End test loop */
+}
+
+
+void test_setup()
+{
+ static int ltest = -1;
+
+ /* See if a specific test has been selected */
if (v->testsel >= 0) {
- v->test = v->testsel;
+ test = v->testsel;
+ }
+
+ /* Only do the setup if this is a new test */
+ if (test == ltest) {
+ return;
}
-
+ ltest = test;
+
+ /* Now setup the test parameters based on the current test number */
if (v->pass == 0) {
- c_iter = tseq[v->test].iter/2;
+ /* Reduce iterations for first pass */
+ c_iter = tseq[test].iter/FIRST_DIVISER;
} else {
- c_iter = tseq[v->test].iter;
+ c_iter = tseq[test].iter;
}
-
- dprint(LINE_TST, COL_MID+6, v->test, 2, 1);
- cprint(LINE_TST, COL_MID+9, tseq[v->test].msg);
- set_cache(tseq[v->test].cache);
- /* Compute the number of SPINSZ memory segments */
- chunks = 0;
- for(i = 0; i < segs; i++) {
- unsigned long len;
- len = v->map[i].end - v->map[i].start;
- chunks += (len + SPINSZ -1)/SPINSZ;
- }
- test_ticks = find_ticks_for_test(chunks, v->test);
+ /* Set the number of iterations. We only do half of the iterations */
+ /* on the first pass */
+ //dprint(LINE_INFO, 28, c_iter, 3, 0);
+ test_ticks = find_ticks_for_test(test);
nticks = 0;
v->tptr = 0;
- cprint(1, COL_MID+8, " ");
- switch(tseq[v->test].pat) {
- /* Now do the testing according to the selected pattern */
- case 0: /* Moving inversions, all ones and zeros (test #2) */
+ cprint(LINE_PAT, COL_PAT, " ");
+ cprint(LINE_PAT, COL_PAT-3, " ");
+ dprint(LINE_TST, COL_MID+6, tseq[test].pat, 2, 1);
+ cprint(LINE_TST, COL_MID+9, tseq[test].msg);
+ cprint(2, COL_MID+8, " ");
+}
+
+/* A couple static variables for when all cpus share the same pattern */
+static ulong sp1, sp2;
+
+int do_test(int my_ord)
+{
+ int i=0, j=0;
+ static int bitf_sleep;
+ unsigned long p0=0, p1=0, p2=0;
+
+ if (my_ord == mstr_cpu) {
+ if ((ulong)&_start > LOW_TEST_ADR) {
+ /* Relocated so we need to test all selected lower memory */
+ v->map[0].start = mapping(v->plim_lower);
+
+ /* Good 'ol Legacy USB_WAR */
+ if (v->map[0].start < (ulong*)0x500)
+ {
+ v->map[0].start = (ulong*)0x500;
+ }
+
+ cprint(LINE_PAT, COL_MID+25, " R");
+ } else {
+ cprint(LINE_PAT, COL_MID+25, " ");
+ }
+
+ /* Update display of memory segments being tested */
+ p0 = page_of(v->map[0].start);
+ p1 = page_of(v->map[segs-1].end);
+ aprint(LINE_RANGE, COL_MID+9, p0);
+ cprint(LINE_RANGE, COL_MID+14, " - ");
+ aprint(LINE_RANGE, COL_MID+17, p1);
+ aprint(LINE_RANGE, COL_MID+25, p1-p0);
+ cprint(LINE_RANGE, COL_MID+30, " of ");
+ aprint(LINE_RANGE, COL_MID+34, v->selected_pages);
+ }
+
+ switch(tseq[test].pat) {
+
+ /* Do the testing according to the selected pattern */
+
+ case 0: /* Address test, walking ones (test #0) */
+ /* Run with cache turned off */
+ set_cache(0);
+ addr_tst1(my_ord);
+ set_cache(1);
+ BAILOUT;
+ break;
+
+ case 1:
+ case 2: /* Address test, own address (test #1, 2) */
+ addr_tst2(my_ord);
+ BAILOUT;
+ break;
+
+ case 3:
+ case 4: /* Moving inversions, all ones and zeros (tests #3, 4) */
p1 = 0;
p2 = ~p1;
- movinv1(c_iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p1,p2,my_ord);
BAILOUT;
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- movinv1(c_iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p2,p1,my_ord);
BAILOUT;
break;
- case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */
+ case 5: /* Moving inversions, 8 bit walking ones and zeros (test #5) */
p0 = 0x80;
for (i=0; i<8; i++, p0=p0>>1) {
p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
p2 = ~p1;
- movinv1(c_iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p1,p2, my_ord);
BAILOUT;
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- movinv1(c_iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p2,p1, my_ord);
BAILOUT
}
break;
+
+ case 6: /* Random Data (test #6) */
+ /* Seed the random number generator */
+ if (my_ord == mstr_cpu) {
+ if (cpu_id.fid.bits.rdtsc) {
+ asm __volatile__ ("rdtsc":"=a" (sp1),"=d" (sp2));
+ } else {
+ sp1 = 521288629 + v->pass;
+ sp2 = 362436069 - v->pass;
+ }
+ rand_seed(sp1, sp2, 0);
+ }
+
+ s_barrier();
+ for (i=0; i < c_iter; i++) {
+ if (my_ord == mstr_cpu) {
+ sp1 = rand(0);
+ sp2 = ~p1;
+ }
+ s_barrier();
+ movinv1(2,sp1,sp2, my_ord);
+ BAILOUT;
+ }
+ break;
+
- case 2: /* Moving inversions, 32 bit shifting pattern (test #6) */
+ case 7: /* Block move (test #7) */
+ block_move(c_iter, my_ord);
+ BAILOUT;
+ break;
+
+ case 8: /* Moving inversions, 32 bit shifting pattern (test #8) */
for (i=0, p1=1; p1; p1=p1<<1, i++) {
- movinv32(c_iter,p1, 1, 0x80000000, 0, i);
+ s_barrier();
+ movinv32(c_iter,p1, 1, 0x80000000, 0, i, my_ord);
BAILOUT
+ s_barrier();
movinv32(c_iter,~p1, 0xfffffffe,
- 0x7fffffff, 1, i);
+ 0x7fffffff, 1, i, my_ord);
BAILOUT
}
break;
- case 3: /* Modulo 20 check, all ones and zeros (unused) */
- p1=0;
- for (i=0; i<MOD_SZ; i++) {
- p2 = ~p1;
- modtst(i, c_iter, p1, p2);
- BAILOUT
-
- /* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- modtst(i, c_iter, p1,p2);
- BAILOUT
+ case 9: /* Random Data Sequence (test #9) */
+ for (i=0; i < c_iter; i++) {
+ s_barrier();
+ movinvr(my_ord);
+ BAILOUT;
}
break;
- case 4: /* Modulo 20 check, 8 bit pattern (unused) */
- p0 = 0x80;
- for (j=0; j<8; j++, p0=p0>>1) {
- p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
+ case 10: /* Modulo 20 check, Random pattern (test #10) */
+ for (j=0; j<c_iter; j++) {
+ p1 = rand(0);
for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- modtst(i, c_iter, p1, p2);
+ s_barrier();
+ modtst(i, 2, p1, p2, my_ord);
BAILOUT
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- modtst(i, c_iter, p1, p2);
+ s_barrier();
+ modtst(i, 2, p2, p1, my_ord);
BAILOUT
}
}
break;
- case 5: /* Address test, walking ones (test #0) */
- addr_tst1();
- BAILOUT;
- break;
- case 6: /* Address test, own address (test #1) */
- addr_tst2();
- BAILOUT;
- break;
-
- case 7: /* Block move (test #5) */
- block_move(c_iter);
- BAILOUT;
- break;
- case 8: /* Bit fade test (test #9) */
- if (window == 0 ) {
- bit_fade();
+ case 11: /* Bit fade test, fill (test #11) */
+ /* Use a sequence to process all windows for each stage */
+ switch(bitf_seq) {
+ case 0: /* Fill all of memory 0's */
+ bit_fade_fill(0, my_ord);
+ bitf_sleep = 1;
+ break;
+ case 1: /* Sleep for the specified time */
+ /* Only sleep once */
+ if (bitf_sleep) {
+ sleep(c_iter, 1, my_ord, 0);
+ bitf_sleep = 0;
+ }
+ break;
+ case 2: /* Now check all of memory for changes */
+ bit_fade_chk(0, my_ord);
+ break;
+ case 3: /* Fill all of memory 1's */
+ bit_fade_fill(-1, my_ord);
+ bitf_sleep = 1;
+ break;
+ case 4: /* Sleep for the specified time */
+ /* Only sleep once */
+ if (bitf_sleep) {
+ sleep(c_iter, 1, my_ord, 0);
+ bitf_sleep = 0;
+ }
+ break;
+ case 5: /* Now check all of memory for changes */
+ bit_fade_chk(-1, my_ord);
+ break;
}
BAILOUT;
break;
- case 9: /* Random Data Sequence (test #7) */
- for (i=0; i < c_iter; i++) {
- movinvr();
- BAILOUT;
- }
- break;
- case 10: /* Random Data (test #4) */
- for (i=0; i < c_iter; i++) {
- p1 = rand();
+
+ case 90: /* Modulo 20 check, all ones and zeros (unused) */
+ p1=0;
+ for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- movinv1(2,p1,p2);
- BAILOUT;
+ modtst(i, c_iter, p1, p2, my_ord);
+ BAILOUT
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ modtst(i, c_iter, p1,p2, my_ord);
+ BAILOUT
}
break;
- case 11: /* Modulo 20 check, Random pattern (test #8) */
- for (j=0; j<c_iter; j++) {
- p1 = rand();
+ case 91: /* Modulo 20 check, 8 bit pattern (unused) */
+ p0 = 0x80;
+ for (j=0; j<8; j++, p0=p0>>1) {
+ p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- modtst(i, 2, p1, p2);
+ modtst(i, c_iter, p1, p2, my_ord);
BAILOUT
/* Switch patterns */
p2 = p1;
p1 = ~p2;
- modtst(i, 2, p1, p2);
+ modtst(i, c_iter, p1, p2, my_ord);
BAILOUT
}
}
break;
}
- skip_window:
- if (bail) {
- goto bail_test;
- }
- /* Rever to the default mapping and enable the cache */
- paging_off();
- set_cache(1);
- window++;
- if (window >= sizeof(windows)/sizeof(windows[0])) {
- window = 0;
- }
- /* We finished the test so clear the pattern */
- cprint(LINE_PAT, COL_PAT, " ");
- if (window != 0) {
- /* Relocate and run the high copy if:
- * - The window overwrites us.
- * The lower limit is less than START_ADR
- * - There is more than 1 meg of memory
- */
- 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 {
- /* We can't use this window so skip it */
- goto skip_window;
- }
- } else {
- /* We don't need the high copy for this test */
- run_at(LOW_TEST_ADR);
- }
- }
- else {
- /* We have run this test in all of the windows
- * advance to the next test.
- */
- skip_test:
- v->test++;
- bail_test:
- /* Revert to the default mapping
- * and enable the cache.
- */
- paging_off();
- set_cache(1);
- check_input();
- window = 0;
- cprint(LINE_PAT, COL_PAT-3, " ");
- /* If this was the last test then we finished a pass */
- if (v->test >= 9 || v->testsel >= 0) {
- v->pass++;
- dprint(LINE_INFO, COL_PASS, v->pass, 5, 0);
- v->test = 0;
- v->total_ticks = 0;
- v->pptr = 0;
- cprint(0, COL_MID+8,
- " ");
- if (v->ecount == 0 && v->testsel < 0) {
- cprint(LINE_MSG+5, 0,
- " *****Pass complete, no errors, press Esc to exit***** ");
- if(BEEP_END_NO_ERROR) {
- beep(1000);
- beep(2000);
- beep(1000);
- beep(2000);
- }
- }
- }
-
- /* We always start a pass with the low copy */
- run_at(LOW_TEST_ADR);
- }
+ return(0);
}
-void restart()
+/* Compute number of SPINSZ chunks being tested */
+int find_chunks(int tst)
{
- int i;
- volatile char *pp;
+ int i, j, sg, wmax, ch;
+ struct pmap twin={0,0};
+ unsigned long wnxt = WIN_SZ;
+ unsigned long len;
- /* clear variables */
- firsttime = 0;
- v->test = 0;
- v->pass = 0;
- v->msg_line = 0;
- v->ecount = 0;
- v->ecc_ecount = 0;
+ wmax = MAX_MEM/WIN_SZ+2; /* The number of 2 GB segments +2 */
+ /* Compute the number of SPINSZ memory segments */
+ ch = 0;
+ for(j = 0; j < wmax; j++) {
+ /* special case for relocation */
+ if (j == 0) {
+ twin.start = 0;
+ twin.end = win1_end;
+ }
+
+ /* special case for first 2 GB */
+ if (j == 1) {
+ twin.start = win0_start;
+ twin.end = WIN_SZ;
+ }
+
+ /* For all other windows */
+ if (j > 1) {
+ twin.start = wnxt;
+ wnxt += WIN_SZ;
+ twin.end = wnxt;
+ }
+
+ /* Find the memory areas I am going to test */
+ sg = compute_segments(twin, -1);
+ for(i = 0; i < sg; i++) {
+ len = v->map[i].end - v->map[i].start;
- /* Clear the screen */
- for(i=0, pp=(char *)(SCREEN_ADR+0); i<80*24; i++, pp+=2) {
- *pp = ' ';
+ if (cpu_mode == CPM_ALL && num_cpus > 1) {
+ switch(tseq[tst].pat) {
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 9:
+ case 10:
+ len /= act_cpus;
+ break;
+ case 7:
+ case 8:
+ len /= act_cpus;
+ break;
+ }
+ }
+ ch += (len + SPINSZ -1)/SPINSZ;
+ }
}
- run_at(LOW_TEST_ADR);
+ return(ch);
}
+/* Compute the total number of ticks per pass */
void find_ticks_for_pass(void)
{
- int i, j, chunks;
+ int i;
v->pptr = 0;
-
- /* Compute the number of SPINSZ memory segments in one pass */
- chunks = 0;
- for(j = 0; j < sizeof(windows)/sizeof(windows[0]); j++) {
- compute_segments(j);
- for(i = 0; i < segs; i++) {
- unsigned long len;
- len = v->map[i].end - v->map[i].start;
- chunks += (len + SPINSZ -1)/SPINSZ;
- }
- }
- compute_segments(window);
- window = 0;
- for (v->pass_ticks=0, i=0; ((i<DEFTESTS) && (DEFTESTS != NULL)); i++) {
-
- /* Test to see if this test is selected for execution */
- if (v->testsel >= 0) {
- if (i != v->testsel) {
- continue;
- }
+ v->pass_ticks = 0;
+ v->total_ticks = 0;
+ cprint(1, COL_MID+8, " ");
+ i = 0;
+ while (tseq[i].cpu_sel != 0) {
+ /* Skip tests 2 and 4 if we are using 1 cpu */
+ if (act_cpus == 1 && (i == 2 || i == 4)) {
+ i++;
+ continue;
}
- v->pass_ticks += find_ticks_for_test(chunks, i);
+ v->pass_ticks += find_ticks_for_test(i);
+ i++;
}
}
-
-static int find_ticks_for_test(int ch, int test)
+static int find_ticks_for_test(int tst)
{
- int ticks=0, c;
+ int ticks=0, c, ch;
- /* Set the number of iterations. We only do half of the iterations */
+ if (tseq[tst].sel == 0) {
+ return(0);
+ }
+
+ /* Determine the number of chunks for this test */
+ ch = find_chunks(tst);
+
+ /* Set the number of iterations. We only do 1/2 of the iterations */
/* on the first pass */
- if (v->pass == 0 && FIRST_PASS_HALF_ITERATIONS) {
- c = tseq[test].iter/2;
+ if (v->pass == 0) {
+ c = tseq[tst].iter/FIRST_DIVISER;
} else {
- c = tseq[test].iter;
+ c = tseq[tst].iter;
}
- switch(tseq[test].pat) {
- case 0: /* Moving inversions, all ones and zeros (test #2) */
- ticks = 2 + 4 * c;
+ switch(tseq[tst].pat) {
+ case 0: /* Address test, walking ones */
+ ticks = 2;
break;
- case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */
- ticks = 24 + 24 * c;
+ case 1: /* Address test, own address */
+ case 2:
+ ticks = 2;
break;
- case 2: /* Moving inversions, 32 bit shifting pattern, very long */
- ticks = (1 + c * 2) * 80;
+ case 3: /* Moving inversions, all ones and zeros */
+ case 4:
+ ticks = 2 + 4 * c;
break;
- case 3: /* Modulo 20 check, all ones and zeros (unused) */
- ticks = (2 + c) * 40;
+ case 5: /* Moving inversions, 8 bit walking ones and zeros */
+ ticks = 24 + 24 * c;
break;
- case 4: /* Modulo 20 check, 8 bit pattern (unused) */
- ticks = (2 + c) * 40 * 8;
+ case 6: /* Random Data */
+ ticks = c + 4 * c;
break;
- case 5: /* Address test, walking ones (test #0) */
- ticks = 4;
+ case 7: /* Block move */
+ ticks = (ch + ch/act_cpus + c*ch);
break;
- case 6: /* Address test, own address (test #1) */
- ticks = 2;
+ case 8: /* Moving inversions, 32 bit shifting pattern */
+ ticks = (1 + c * 2) * 64;
break;
- case 7: /* Block move (test #5) */
- ticks = 2 + c;
+ case 9: /* Random Data Sequence */
+ ticks = 3 * c;
break;
- case 8: /* Bit fade test (test #9) */
- ticks = 1;
+ case 10: /* Modulo 20 check, Random pattern */
+ ticks = 4 * 40 * c;
break;
- case 9: /* Random Data Sequence (test #7) */
- ticks = 3 * c;
+ case 11: /* Bit fade test */
+ ticks = c * 2 + 4 * ch;
break;
- case 10: /* Random Data (test #4) */
- ticks = c + 4 * c;
+ case 90: /* Modulo 20 check, all ones and zeros (unused) */
+ ticks = (2 + c) * 40;
break;
- case 11: /* Modulo 20 check, Random pattern (test #8) */
- ticks = 4 * 40 * c;
+ case 91: /* Modulo 20 check, 8 bit pattern (unused) */
+ ticks = (2 + c) * 40 * 8;
break;
}
-
+ if (cpu_mode == CPM_SEQ || tseq[tst].cpu_sel == -1) {
+ ticks *= act_cpus;
+ }
+ if (tseq[tst].pat == 7 || tseq[tst].pat == 11) {
+ return ticks;
+ }
return ticks*ch;
}
-static int compute_segments(int win)
+static int compute_segments(struct pmap win, int me)
{
unsigned long wstart, wend;
- int i;
+ int i, sg;
/* Compute the window I am testing memory in */
- wstart = windows[win].start;
- wend = windows[win].end;
- segs = 0;
+ wstart = win.start;
+ wend = win.end;
+ sg = 0;
/* Now reduce my window to the area of memory I want to test */
if (wstart < v->plim_lower) {
@@ -666,9 +1237,9 @@ static int compute_segments(int win)
cprint(LINE_SCROLL+(2*i), 64, ") ");
cprint(LINE_SCROLL+(2*i+1), 0, "w(");
- hprint(LINE_SCROLL+(2*i+1), 2, windows[win].start);
+ hprint(LINE_SCROLL+(2*i+1), 2, win.start);
cprint(LINE_SCROLL+(2*i+1), 10, ", ");
- hprint(LINE_SCROLL+(2*i+1), 12, windows[win].end);
+ hprint(LINE_SCROLL+(2*i+1), 12, win.end);
cprint(LINE_SCROLL+(2*i+1), 20, ") ");
cprint(LINE_SCROLL+(2*i+1), 22, "m(");
@@ -688,16 +1259,27 @@ static int compute_segments(int win)
" ");
#endif
if ((start < end) && (start < wend) && (end > wstart)) {
- v->map[segs].pbase_addr = start;
- v->map[segs].start = mapping(start);
- v->map[segs].end = emapping(end);
+ v->map[sg].pbase_addr = start;
+ v->map[sg].start = mapping(start);
+ v->map[sg].end = emapping(end);
+#if 0
+ hprint(LINE_SCROLL+(sg+1), 0, sg);
+ hprint(LINE_SCROLL+(sg+1), 12, v->map[sg].pbase_addr);
+ hprint(LINE_SCROLL+(sg+1), 22, start);
+ hprint(LINE_SCROLL+(sg+1), 32, end);
+ hprint(LINE_SCROLL+(sg+1), 42, mapping(start));
+ hprint(LINE_SCROLL+(sg+1), 52, emapping(end));
+ cprint(LINE_SCROLL+(sg+2), 0,
+ " "
+ " ");
+#endif
#if 0
- cprint(LINE_SCROLL+(2*i+1), 54, " sg: ");
- hprint(LINE_SCROLL+(2*i+1), 61, sg);
+ cprint(LINE_SCROLL+(2*i+1), 54, ", sg=");
+ hprint(LINE_SCROLL+(2*i+1), 59, sg);
#endif
- segs++;
+ sg++;
}
}
- return (segs);
+ return (sg);
}
diff --git a/major_version b/major_version
new file mode 100644
index 0000000..c6aaf52
--- /dev/null
+++ b/major_version
@@ -0,0 +1 @@
+4.99
diff --git a/make_buildnum.sh b/make_buildnum.sh
new file mode 100755
index 0000000..93927cd
--- /dev/null
+++ b/make_buildnum.sh
@@ -0,0 +1,20 @@
+#!sh
+# FILE: make_buildnum.sh
+version="`sed 's/^ *//' major_version`"
+old="`sed 's/^ *//' build.number` +1"
+echo $old | bc > build.number.temp
+mv build.number.temp build.number
+#versión..
+echo "$version`sed 's/^ *//' build.number` - `date`" > version.number
+#header
+echo "#ifndef BUILD_NUMBER_STR" > build_number.h
+echo "#define BUILD_NUMBER_STR \"`sed 's/^ *//' build.number`\"" >> build_number.h
+echo "#endif" >> build_number.h
+
+echo "#ifndef VERSION_STR" >> build_number.h
+echo "#define VERSION_STR \"$version`sed 's/^ *//' build.number` - `date`\"" >> build_number.h
+echo "#endif" >> build_number.h
+
+echo "#ifndef VERSION_STR_SHORT" >> build_number.h
+echo "#define VERSION_STR_SHORT \"$version`sed 's/^ *//' build.number`\"" >> build_number.h
+echo "#endif" >> build_number.h
diff --git a/makeiso.sh b/makeiso.sh
index 0ed373e..ae5a8c9 100755
--- a/makeiso.sh
+++ b/makeiso.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# check to see if the correct tools are installed
-for X in wc mkisofs
+for X in wc genisoimage
do
if [ "$(which $X)" = "" ]; then
echo "makeiso.sh error: $X is not in your path." >&2
@@ -37,9 +37,9 @@ cd cd
echo -e "There is nothing to do here\r\r\nMemtest86+ is located on the bootsector of this CD\r\r\n" > README.TXT
echo -e "Just boot from this CD and Memtest86+ will launch" >> README.TXT
-mkisofs -A "MKISOFS 1.1.2" -p "Memtest86+ 4.20" -publisher "Samuel D. <sdemeule@memtest.org>" -b boot/memtest.img -c boot/boot.catalog -V "MT410" -o memtest.iso .
-mv memtest.iso ../mt420.iso
+genisoimage -A "MKISOFS 1.1.2" -p "Memtest86+ 5.01" -publisher "Samuel D. <sdemeule@memtest.org>" -b boot/memtest.img -c boot/boot.catalog -V "MT501" -o memtest.iso .
+mv memtest.iso ../mt501.iso
cd ..
rm -rf cd
-echo "Done! Memtest86+ 4.20 ISO is mt420.iso"
+echo "Done! Memtest86+ 5.01 ISO is mt501.iso"
diff --git a/memsize.c b/memsize.c
index 3916538..0fea141 100644
--- a/memsize.c
+++ b/memsize.c
@@ -10,35 +10,38 @@
short e820_nr;
short memsz_mode = SZ_MODE_BIOS;
-short firmware = FIRMWARE_UNKNOWN;
static ulong alt_mem_k;
static ulong ext_mem_k;
static struct e820entry e820[E820MAX];
-extern ulong p1, p2;
-extern volatile ulong *p;
+ulong p1, p2;
+ulong *p;
static void sort_pmap(void);
-static int check_ram(void);
-static void memsize_bios(void);
+//static void memsize_bios(void);
static void memsize_820(void);
static void memsize_801(void);
static int sanitize_e820_map(struct e820entry *orig_map,
- struct e820entry *new_bios, short old_nr);
+struct e820entry *new_bios, short old_nr);
static void memsize_linuxbios();
-static void memsize_probe(void);
-static int check_ram(void);
/*
* Find out how much memory there is.
*/
void mem_size(void)
{
- int i;
- v->reserved_pages = 0;
+ int i, flag=0;
v->test_pages = 0;
+ /* Get the memory size from the BIOS */
+ /* Determine the memory map */
+ if (query_linuxbios()) {
+ flag = 1;
+ } else if (query_pcbios()) {
+ flag = 2;
+ }
+
/* On the first time thru only */
/* Make a copy of the memory info table so that we can re-evaluate */
/* The memory map later */
@@ -52,35 +55,18 @@ void mem_size(void)
e820[i].type = mem_info.e820[i].type;
}
}
-
- switch (memsz_mode) {
- case SZ_MODE_BIOS:
- /* Get the memory size from the BIOS */
- memsize_bios();
- break;
- case SZ_MODE_PROBE:
- /* Probe to find memory */
- memsize_probe();
- cprint(LINE_INFO, COL_MMAP, "Probed");
- break;
+ if (flag == 1) {
+ memsize_linuxbios();
+ } else if (flag == 2) {
+ memsize_820();
}
+
/* Guarantee that pmap entries are in ascending order */
sort_pmap();
v->plim_lower = 0;
v->plim_upper = v->pmap[v->msegs-1].end;
adj_mem();
- aprint(LINE_INFO, COL_RESERVED, v->reserved_pages);
-}
-
-static void memsize_bios()
-{
- if (firmware == FIRMWARE_PCBIOS) {
- memsize_820();
- }
- else if (firmware == FIRMWARE_LINUXBIOS) {
- memsize_linuxbios();
- }
}
static void sort_pmap(void)
@@ -114,6 +100,7 @@ static void memsize_linuxbios(void)
n = 0;
for (i=0; i < e820_nr; i++) {
unsigned long long end;
+
if (e820[i].type != E820_RAM) {
continue;
}
@@ -125,12 +112,13 @@ static void memsize_linuxbios(void)
n++;
}
v->msegs = n;
- cprint(LINE_INFO, COL_MMAP, "LxBIOS");
}
static void memsize_820()
{
int i, n, nr;
struct e820entry nm[E820MAX];
+ unsigned long long start;
+ unsigned long long end;
/* Clean up, adjust and copy the BIOS-supplied E820-map. */
nr = sanitize_e820_map(e820, nm, e820_nr);
@@ -145,8 +133,6 @@ static void memsize_820()
n = 0;
for (i=0; i<nr; i++) {
if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) {
- unsigned long long start;
- unsigned long long end;
start = nm[i].addr;
end = start + nm[i].size;
@@ -164,12 +150,18 @@ static void memsize_820()
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
- } else if (nm[i].type == E820_NVS) {
- v->reserved_pages += nm[i].size >> 12;
+#if 0
+ int epmap = 0;
+ int lpmap = 0;
+ if(n > 12) { epmap = 34; lpmap = -12; }
+ hprint (11+n+lpmap,0+epmap,v->pmap[n-1].start);
+ hprint (11+n+lpmap,10+epmap,v->pmap[n-1].end);
+ hprint (11+n+lpmap,20+epmap,v->pmap[n-1].end - v->pmap[n-1].start);
+ dprint (11+n+lpmap,30+epmap,nm[i].type,0,0);
+#endif
}
}
v->msegs = n;
- cprint(LINE_INFO, COL_MMAP, " e820");
}
static void memsize_801(void)
@@ -181,10 +173,8 @@ static void memsize_801(void)
if (alt_mem_k < ext_mem_k) {
mem_size = ext_mem_k;
- cprint(LINE_INFO, COL_MMAP, " e88");
} else {
mem_size = alt_mem_k;
- cprint(LINE_INFO, COL_MMAP, " e801");
}
/* First we map in the first 640k */
v->pmap[0].start = 0;
@@ -355,130 +345,3 @@ static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_b
}
return(new_bios_entry);
}
-
-static void memsize_probe(void)
-{
- int i, n;
- ulong m_lim;
- static unsigned long magic = 0x1234569;
-
- /* Since all address bits may not be decoded, the search for memory
- * must be limited. The max address is found by checking for
- * memory wrap from 1MB to 4GB. */
- p1 = (ulong)&magic;
- m_lim = 0xfffffffc;
- for (p2 = 0x100000; p2; p2 <<= 1) {
- p = (ulong *)(p1 + p2);
- if (*p == 0x1234569) {
- m_lim = --p2;
- break;
- }
- }
-
- /* Turn on cache */
- set_cache(1);
-
- /* Find all segments of RAM */
-
- i = 0;
- v->pmap[i].start = ((ulong)&_end + (1 << 12) - 1) >> 12;
- p = (ulong *)(v->pmap[i].start << 12);
-
- /* Limit search for memory to m_lim and make sure we don't
- * overflow the 32 bit size of p. */
- while ((ulong)p < m_lim && (ulong)p >= (ulong)&_end) {
- /*
- * Skip over reserved memory
- */
- if ((ulong)p < RES_END && (ulong)p >= RES_START) {
- v->pmap[i].end = RES_START >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- p = (ulong *)RES_END;
- i++;
- v->pmap[i].start = 0;
- goto fstart;
- }
-
- if (check_ram() == 0) {
- /* ROM or nothing at this address, record end addrs */
- v->pmap[i].end = ((ulong)p) >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- i++;
- v->pmap[i].start = 0;
-fstart:
-
- /* We get here when there is a gap in memory.
- * Loop until we find more ram, the gap is more
- * than 32768k or we hit m_lim */
- n = 32768 >> 2;
- while ((ulong)p < m_lim && (ulong)p >= (ulong)&_end) {
-
- /* Skip over video memory */
- if ((ulong)p < RES_END &&
- (ulong)p >= RES_START) {
- p = (ulong *)RES_END;
- }
- if (check_ram() == 1) {
- /* More RAM, record start addrs */
- v->pmap[i].start = (ulong)p >> 12;
- break;
- }
-
- /* If the gap is 32768k or more then there
- * is probably no more memory so bail out */
- if (--n <= 0) {
- p = (ulong *)m_lim;
- break;
- }
- p += 0x1000;
- }
- }
- p += 0x1000;
- }
-
- /* If there is ram right up to the memory limit this will record
- * the last address. */
- if (v->pmap[i].start) {
- v->pmap[i].end = m_lim >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- i++;
- }
- v->msegs = i;
-}
-
-/* check_ram - Determine if this address points to memory by checking
- * for a wrap pattern and then reading and then writing the complement.
- * We then check that at least one bit changed in each byte before
- * believing that it really is memory. */
-
-static int check_ram(void)
-{
- int s;
-
- p1 = *p;
-
- /* write the complement */
- *p = ~p1;
- p2 = *p;
- s = 0;
-
- /* Now make sure a bit changed in each byte */
- if ((0xff & p1) != (0xff & p2)) {
- s++;
- }
- if ((0xff00 & p1) != (0xff00 & p2)) {
- s++;
- }
- if ((0xff0000 & p1) != (0xff0000 & p2)) {
- s++;
- }
- if ((0xff000000 & p1) != (0xff000000 & p2)) {
- s++;
- }
- if (s == 4) {
- /* RAM at this address */
- return 1;
- }
-
- return 0;
-}
diff --git a/memtest.bin.lds b/memtest.bin.lds
index 699d2aa..702cdb1 100644
--- a/memtest.bin.lds
+++ b/memtest.bin.lds
@@ -1,15 +1,15 @@
-OUTPUT_FORMAT("binary")
-OUTPUT_ARCH("i386")
-
-ENTRY(_main);
-SECTIONS {
- . = 0;
- .bootsect : { *(.bootsect) }
- .setup : { *(.setup) }
- .memtest : {
- _start = . ;
- *(.data)
- _end = . ;
- }
- _syssize = (_end - _start + 15) >> 4;
-}
+OUTPUT_FORMAT("binary")
+OUTPUT_ARCH("i386")
+
+ENTRY(_main);
+SECTIONS {
+ . = 0;
+ .bootsect : { *(.bootsect) }
+ .setup : { *(.setup) }
+ .memtest : {
+ _start = . ;
+ *(.data)
+ _end = . ;
+ }
+ _syssize = (_end - _start + 15) >> 4;
+}
diff --git a/memtest.lds b/memtest.lds
index 2906a24..bbb190a 100644
--- a/memtest.lds
+++ b/memtest.lds
@@ -1,11 +1,11 @@
-OUTPUT_FORMAT("elf32-i386");
-OUTPUT_ARCH(i386);
-
-ENTRY(_start);
-SECTIONS {
- . = 0x5000;
- _start = . ;
- .data : {
- *(.data)
- }
-}
+OUTPUT_FORMAT("elf32-i386");
+OUTPUT_ARCH(i386);
+
+ENTRY(_start);
+SECTIONS {
+ . = 0x10000;
+ _start = . ;
+ .data : {
+ *(.data)
+ }
+}
diff --git a/memtest_shared.lds b/memtest_shared.lds
index 453916c..603f012 100644
--- a/memtest_shared.lds
+++ b/memtest_shared.lds
@@ -1,53 +1,53 @@
-OUTPUT_FORMAT("elf32-i386");
-OUTPUT_ARCH(i386);
-
-ENTRY(startup_32);
-SECTIONS {
- . = 0;
- .text : {
- _start = .;
- *(.text)
- *(.text.*)
- *(.plt)
- _etext = . ;
- } = 0x9090
- .rodata : {
- *(.rodata)
- *(.rodata.*)
- }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .hash : { *(.hash) }
- .gnu.hash : { *(.gnu.hash) }
- .dynamic : { *(.dynamic) }
-
- .rel.text : { *(.rel.text .rel.text.*) }
- .rel.rodata : { *(.rel.rodata .rel.rodata.*) }
- .rel.data : { *(.rel.data .rel.data.*) }
- .rel.got : { *(.rel.got .rel.got.*) }
- .rel.plt : { *(.rel.plt .rel.plt.*) }
-
- . = ALIGN(4);
- .data : {
- _data = .;
- *(.data)
- *(.data.*)
- }
- .got : {
- *(.got.plt)
- *(.got)
- _edata = . ;
- }
- . = ALIGN(4);
- .bss : {
- _bss = .;
- *(.dynbss)
- *(.bss)
- *(.bss.*)
- *(COMMON)
- /* _end must be at least 256 byte aligned */
- . = ALIGN(256);
- _end = .;
- }
- /DISCARD/ : { *(*) }
-}
+OUTPUT_FORMAT("elf32-i386");
+OUTPUT_ARCH(i386);
+
+ENTRY(startup_32);
+SECTIONS {
+ . = 0;
+ .text : {
+ _start = .;
+ *(.text)
+ *(.text.*)
+ *(.plt)
+ _etext = . ;
+ } = 0x9090
+ .rodata : {
+ *(.rodata)
+ *(.rodata.*)
+ }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynamic : { *(.dynamic) }
+
+ .rel.text : { *(.rel.text .rel.text.*) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.*) }
+ .rel.data : { *(.rel.data .rel.data.*) }
+ .rel.got : { *(.rel.got .rel.got.*) }
+ .rel.plt : { *(.rel.plt .rel.plt.*) }
+
+ . = ALIGN(4);
+ .data : {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ }
+ .got : {
+ *(.got.plt)
+ *(.got)
+ _edata = . ;
+ }
+ . = ALIGN(4);
+ .bss : {
+ _bss = .;
+ *(.dynbss)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ /* _end must be at least 256 byte aligned */
+ . = ALIGN(256);
+ _end = .;
+ }
+ /DISCARD/ : { *(*) }
+}
diff --git a/msr.h b/msr.h
index c904d50..af873a0 100644
--- a/msr.h
+++ b/msr.h
@@ -6,11 +6,31 @@
* Note: the rd* operations modify the parameters directly (without using
* pointer indirection), this allows gcc to optimize better
*/
+
+#define __FIXUP_ALIGN ".align 8"
+#define __FIXUP_WORD ".quad"
+#define EFAULT 14 /* Bad address */
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
- : "c" (msr))
+ : "c" (msr) : "edi")
+
+/*
+#define rdmsr_safe(msr,val1,val2) ({\
+ int _rc; \
+ __asm__ __volatile__( \
+ "1: rdmsr\n2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: movl %5,%2\n; jmp 2b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " "__FIXUP_ALIGN"\n" \
+ ".previous\n" \
+ : "=a" (val1), "=d" (val2), "=&r" (_rc) \
+ : "c" (msr), "2" (0), "i" (-EFAULT)); \
+ _rc; })
+*/
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
@@ -58,6 +78,7 @@
#define MSR_IA32_THERM_INTERRUPT 0x19b
#define MSR_IA32_THERM_STATUS 0x19c
#define MSR_IA32_MISC_ENABLE 0x1a0
+#define MSR_IA32_TEMPERATURE_TARGET 0x1a2
#define MSR_IA32_DEBUGCTLMSR 0x1d9
#define MSR_IA32_LASTBRANCHFROMIP 0x1db
diff --git a/mt86+_loader b/mt86+_loader
index 6c77a6f..030ea1a 100644
--- a/mt86+_loader
+++ b/mt86+_loader
Binary files differ
diff --git a/mt86+_loader.asm b/mt86+_loader.asm
index 600ebfa..8472262 100644
--- a/mt86+_loader.asm
+++ b/mt86+_loader.asm
@@ -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 (164504 + buffer - exeh)
- ; 164504 is the size of memtest86+ V4.20, adjust as needed!
+%define fullsize (150024 + buffer - exeh)
+ ; 150024 is the size of memtest86+ V5.01, adjust as needed!
%define stacksize 2048
%define stackpara ((stacksize + 15) / 16)
diff --git a/patn.c b/patn.c
index 8240333..0c5b490 100644
--- a/patn.c
+++ b/patn.c
@@ -7,7 +7,7 @@
*
* By Rick van Rein, vanrein@zonnet.nl
* ----------------------------------------------------
- * MemTest86+ V2.00 Specific code (GPL V2.0)
+ * MemTest86+ V1.60 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 e6c2cf6..075a07f 100644
--- a/pci.c
+++ b/pci.c
@@ -3,7 +3,7 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V4.00 Specific code (GPL V2.0)
+ * MemTest86+ V5.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.x86-secret.com - http://www.memtest.org
*/
@@ -11,6 +11,8 @@
#include "io.h"
#include "pci.h"
#include "test.h"
+#include "stdint.h"
+#include "cpuid.h"
#define PCI_CONF_TYPE_NONE 0
#define PCI_CONF_TYPE_1 1
@@ -68,30 +70,36 @@ int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsign
{
int result;
- if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1))
return -1;
result = -1;
- switch(pci_conf_type) {
- case PCI_CONF_TYPE_1:
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
- switch(len) {
- case 1: outb(value, 0xCFC + (reg & 3)); result = 0; break;
- case 2: outw(value, 0xCFC + (reg & 2)); result = 0; break;
- case 4: outl(value, 0xCFC); result = 0; break;
- }
- break;
- case PCI_CONF_TYPE_2:
- outb(0xF0 | (fn << 1), 0xCF8);
- outb(bus, 0xCFA);
-
- switch(len) {
- case 1: outb(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 2: outw(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 4: outl(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- }
- outb(0, 0xCF8);
- break;
+
+ switch(pci_conf_type)
+ {
+ case PCI_CONF_TYPE_1:
+ if(reg < 256){
+ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
+ }else{
+ outl(PCI_CONF3_ADDRESS(bus, dev, fn, reg), 0xCF8);
+ }
+ switch(len) {
+ case 1: outb(value, 0xCFC + (reg & 3)); result = 0; break;
+ case 2: outw(value, 0xCFC + (reg & 2)); result = 0; break;
+ case 4: outl(value, 0xCFC); result = 0; break;
+ }
+ break;
+ case PCI_CONF_TYPE_2:
+ outb(0xF0 | (fn << 1), 0xCF8);
+ outb(bus, 0xCFA);
+
+ switch(len) {
+ case 1: outb(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
+ case 2: outw(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
+ case 4: outl(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
+ }
+ outb(0, 0xCF8);
+ break;
}
return result;
}
@@ -120,9 +128,9 @@ static int pci_check_direct(void)
unsigned char tmpCFB;
unsigned int tmpCF8;
- if (cpu_id.vend_id[0] == 'A' && cpu_id.type == 15) {
+ if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF) {
pci_conf_type = PCI_CONF_TYPE_1;
- return 0;
+ return 0;
} else {
/* Check if configuration type 1 works. */
pci_conf_type = PCI_CONF_TYPE_1;
@@ -138,6 +146,7 @@ static int pci_check_direct(void)
outl(tmpCF8, 0xCF8);
/* Check if configuration type 2 works. */
+
pci_conf_type = PCI_CONF_TYPE_2;
outb(0x00, 0xCFB);
outb(0x00, 0xCF8);
@@ -145,6 +154,7 @@ static int pci_check_direct(void)
if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && (pci_sanity_check() == 0)) {
outb(tmpCFB, 0xCFB);
return 0;
+
}
outb(tmpCFB, 0xCFB);
diff --git a/pci.h b/pci.h
index 3629a6a..f21c478 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);
+#define MAKE_PCIE_ADDRESS(bus, device, function) (((bus) & 0xFF)<<20) | (((device) & 0x1F)<<15) | (((function) & 0x7)<<12)
/*
* Under PCI, each device has 256 bytes of configuration address space,
diff --git a/precomp.bin b/precomp.bin
index 293e15d..affaaab 100755
--- a/precomp.bin
+++ b/precomp.bin
Binary files differ
diff --git a/random.c b/random.c
index a0a19c7..69dd140 100644
--- a/random.c
+++ b/random.c
@@ -1,31 +1,38 @@
+/******************************************************************/
+/* Random number generator */
/* concatenation of following two 16-bit multiply with carry generators */
/* x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16, */
/* number and carry packed within the same 32 bit integer. */
/******************************************************************/
+#include "stdint.h"
+#include "cpuid.h"
+#include "smp.h"
-unsigned int rand( void ); /* returns a random 32-bit integer */
-void rand_seed( unsigned int, unsigned int ); /* seed the generator */
+/* Keep a separate seed for each CPU */
+/* Space the seeds by at least a cache line or performance suffers big time! */
+static unsigned int SEED_X[MAX_CPUS*16];
+static unsigned int SEED_Y[MAX_CPUS*16];
-/* return a random float >= 0 and < 1 */
-#define rand_float ((double)rand() / 4294967296.0)
+unsigned long rand (int cpu)
+{
+ static unsigned int a = 18000, b = 30903;
+ int me;
-static unsigned int SEED_X = 521288629;
-static unsigned int SEED_Y = 362436069;
+ me = cpu*16;
+ SEED_X[me] = a*(SEED_X[me]&65535) + (SEED_X[me]>>16);
+ SEED_Y[me] = b*(SEED_Y[me]&65535) + (SEED_Y[me]>>16);
-unsigned int rand ()
- {
- static unsigned int a = 18000, b = 30903;
+ return ((SEED_X[me]<<16) + (SEED_Y[me]&65535));
+}
- SEED_X = a*(SEED_X&65535) + (SEED_X>>16);
- SEED_Y = b*(SEED_Y&65535) + (SEED_Y>>16);
- return ((SEED_X<<16) + (SEED_Y&65535));
- }
+void rand_seed( unsigned int seed1, unsigned int seed2, int cpu)
+{
+ int me;
+ me = cpu*16;
+ SEED_X[me] = seed1;
+ SEED_Y[me] = seed2;
+}
-void rand_seed( unsigned int seed1, unsigned int seed2 )
- {
- if (seed1) SEED_X = seed1; /* use default seeds if parameter is 0 */
- if (seed2) SEED_Y = seed2;
- }
diff --git a/reloc.c b/reloc.c
index 374b495..1b80731 100644
--- a/reloc.c
+++ b/reloc.c
@@ -1,7 +1,12 @@
-#include <stddef.h>
+/* reloc.c - MemTest-86 Version 3.3
+ *
+ * Released under version 2 of the Gnu Public License.
+ * By Eric Biederman
+ */
+
+#include "stddef.h"
#include "stdint.h"
#include "elf.h"
-#include <string.h>
#define __ELF_NATIVE_CLASS 32
#define ELF_MACHINE_NO_RELA 1
@@ -22,7 +27,7 @@
bootstrap relocation instead of general-purpose relocation. */
#define RTLD_BOOTSTRAP
-struct link_map
+struct link_map
{
ElfW(Addr) l_addr; /* Current load address */
ElfW(Addr) ll_addr; /* Last load address */
@@ -127,7 +132,7 @@ elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
{
if (! dyn)
return;
-
+
while (dyn->d_tag != DT_NULL)
{
if (dyn->d_tag < DT_NUM)
@@ -142,8 +147,8 @@ elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
assert (! "bad dynamic tag");
++dyn;
}
-
- if (info[DT_PLTGOT] != NULL)
+
+ if (info[DT_PLTGOT] != NULL)
info[DT_PLTGOT]->d_un.d_ptr += l_addr;
if (info[DT_STRTAB] != NULL)
info[DT_STRTAB]->d_un.d_ptr += l_addr;
@@ -194,7 +199,7 @@ elf_dynamic_do_rel (struct link_map *map,
const ElfW(Sym) *const symtab =
(const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr;
-
+
for (; r < end; ++r) {
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
(void *) (map->l_addr + r->r_offset));
@@ -221,32 +226,32 @@ void _dl_start(void)
/* Figure out the run-time load address of the dynamic linker itself. */
last_load_address = map.l_addr = elf_machine_load_address();
-
+
/* Read our own dynamic section and fill in the info array. */
map.l_ld = (void *)map.l_addr + elf_machine_dynamic();
elf_get_dynamic_info (map.l_ld, map.l_addr - map.ll_addr, map.l_info);
/* Relocate ourselves so we can do normal function calls and
- * data access using the global offset table.
+ * data access using the global offset table.
*/
#if !ELF_MACHINE_NO_REL
- elf_dynamic_do_rel(&map,
+ elf_dynamic_do_rel(&map,
map.l_info[DT_REL]->d_un.d_ptr,
map.l_info[DT_RELSZ]->d_un.d_val);
if (map.l_info[DT_PLTREL]->d_un.d_val == DT_REL) {
- elf_dynamic_do_rel(&map,
+ elf_dynamic_do_rel(&map,
map.l_info[DT_JMPREL]->d_un.d_ptr,
map.l_info[DT_PLTRELSZ]->d_un.d_val);
}
#endif
#if !ELF_MACHINE_NO_RELA
- elf_dynamic_do_rela(&map,
+ elf_dynamic_do_rela(&map,
map.l_info[DT_RELA]->d_un.d_ptr,
map.l_info[DT_RELASZ]->d_un.d_val);
if (map.l_info[DT_PLTREL]->d_un.d_val == DT_RELA) {
- elf_dynamic_do_rela(&map,
+ elf_dynamic_do_rela(&map,
map.l_info[DT_JMPREL]->d_un.d_ptr,
map.l_info[DT_PLTRELSZ]->d_un.d_val);
}
diff --git a/screen_buffer.c b/screen_buffer.c
index 44635a7..f9e01be 100644
--- a/screen_buffer.c
+++ b/screen_buffer.c
@@ -1,24 +1,17 @@
-/* --*- C -*--
- *
- * By Jani Averbach, Jaa@iki.fi, 2001
+/* screen_buffer.c - MemTest-86 Version 3.3
*
* Released under version 2 of the Gnu Public License.
- *
- * $Author: jaa $
- * $Revision: 1.10 $
- * $Date: 2001/03/29 09:00:30 $
- * $Source: /home/raid/cvs/memtest86/screen_buffer.c,v $ (for CVS)
- *
+ * By Jani Averbach, Jaa@iki.fi, 2001
*/
+
#include "test.h"
#include "screen_buffer.h"
-
#define SCREEN_X 80
#define SCREEN_Y 25
#define Y_SIZE SCREEN_Y
/*
- * X-size should by one of by screen size,
+ * X-size should by one of by screen size,
* so that there is room for ending '\0'
*/
#define X_SIZE SCREEN_X+1
@@ -41,8 +34,8 @@ char
get_scrn_buf(const int y,
const int x)
{
- CHECK_BOUNDS(y,x);
- return screen_buf[y][x];
+ CHECK_BOUNDS(y,x);
+ return screen_buf[y][x];
}
@@ -51,43 +44,43 @@ set_scrn_buf(const int y,
const int x,
const char val)
{
- CHECK_BOUNDS(y,x);
- screen_buf[y][x] = val;
+ CHECK_BOUNDS(y,x);
+ screen_buf[y][x] = val;
}
void clear_screen_buf()
{
- int y, x;
-
- for (y=0; y < SCREEN_Y; ++y){
- for (x=0; x < SCREEN_X; ++x){
- CHECK_BOUNDS(y,x);
- screen_buf[y][x] = ' ';
- }
- CHECK_BOUNDS(y,SCREEN_X);
- screen_buf[y][SCREEN_X] = '\0';
- }
+ int y, x;
+
+ for (y=0; y < SCREEN_Y; ++y){
+ for (x=0; x < SCREEN_X; ++x){
+ CHECK_BOUNDS(y,x);
+ screen_buf[y][x] = ' ';
+ }
+ CHECK_BOUNDS(y,SCREEN_X);
+ screen_buf[y][SCREEN_X] = '\0';
+ }
}
-void tty_print_region(const int pi_top,
+void tty_print_region(const int pi_top,
const int pi_left,
const int pi_bottom,
const int pi_right)
{
- int y;
- char tmp;
+ int y;
+ char tmp;
- for (y=pi_top; y < pi_bottom; ++y){
- CHECK_BOUNDS(y, pi_right);
+ for (y=pi_top; y < pi_bottom; ++y){
+ CHECK_BOUNDS(y, pi_right);
+
+ tmp = screen_buf[y][pi_right];
+ screen_buf[y][pi_right] = '\0';
- tmp = screen_buf[y][pi_right];
- screen_buf[y][pi_right] = '\0';
+ CHECK_BOUNDS(y, pi_left);
+ ttyprint(y, pi_left, &(screen_buf[y][pi_left]));
- CHECK_BOUNDS(y, pi_left);
- ttyprint(y, pi_left, &(screen_buf[y][pi_left]));
-
- screen_buf[y][pi_right] = tmp;
- }
+ screen_buf[y][pi_right] = tmp;
+ }
}
void tty_print_line(
@@ -112,23 +105,23 @@ void tty_print_line(
void tty_print_screen(void)
{
#ifdef SCRN_DEBUG
- int i;
+ int i;
- for (i=0; i < SCREEN_Y; ++i)
- ttyprint(i,0, padding);
+ for (i=0; i < SCREEN_Y; ++i)
+ ttyprint(i,0, padding);
#endif /* SCRN_DEBUG */
- tty_print_region(0, 0, SCREEN_Y, SCREEN_X);
+ tty_print_region(0, 0, SCREEN_Y, SCREEN_X);
}
void print_error(char *pstr)
{
#ifdef SCRN_DEBUG
- ttyprint(0,0, padding);
+ ttyprint(0,0, padding);
#endif /* SCRN_DEBUG */
- ttyprint(0,35, pstr);
-
- while(1);
+ ttyprint(0,35, pstr);
+
+ while(1);
}
diff --git a/screen_buffer.h b/screen_buffer.h
index a843acc..8ceba03 100644
--- a/screen_buffer.h
+++ b/screen_buffer.h
@@ -4,11 +4,6 @@
*
* Released under version 2 of the Gnu Public License.
*
- * $Author: jaa $
- * $Revision: 1.6 $
- * $Date: 2001/03/29 09:00:30 $
- * $Source: /home/raid/cvs/memtest86/screen_buffer.h,v $ (for CVS)
- *
*/
#ifndef SCREEN_BUFFER_H_1D10F83B_INCLUDED
#define SCREEN_BUFFER_H_1D10F83B_INCLUDED
diff --git a/setup.S b/setup.S
index 056217f..f80875b 100644
--- a/setup.S
+++ b/setup.S
@@ -1,147 +1,154 @@
-/*
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86.
- */
-
-#define __ASSEMBLY__
-#include "defs.h"
-
-.code16
-.section ".setup", "ax", @progbits
-.globl start
-start:
-# ok, the read went well
-# now we want to move to protected mode ...
-
-
- cli # no interrupts allowed #
- movb $0x80, %al # disable NMI for the bootup sequence
- outb %al, $0x70
-
-
-# The system will move itself to its rightful place.
-
- push %cs
- pop %ds
- lidt idt_48 - start # load idt with 0,0
- lgdt gdt_48 - start # load gdt with whatever appropriate
-
-# that was painless, now we enable A20
-# start from grub-a20.patch
- /*
- * try to switch gateA20 using PORT92, the "Fast A20 and Init"
- * register
- */
- mov $0x92, %dx
- inb %dx, %al
- /* skip the port92 code if it's unimplemented (read returns 0xff) */
- cmpb $0xff, %al
- jz alt_a20_done
-
- /* set or clear bit1, the ALT_A20_GATE bit */
- movb 4(%esp), %ah
- testb %ah, %ah
- jz alt_a20_cont1
- orb $2, %al
- jmp alt_a20_cont2
-alt_a20_cont1:
- and $0xfd, %al
-
- /* clear the INIT_NOW bit; don't accidently reset the machine */
-alt_a20_cont2:
- and $0xfe, %al
- outb %al, %dx
-
-alt_a20_done:
-# end from grub-a20.patch
-
- call empty_8042
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
-/*
- * Note that the short jump isn't strictly needed, althought there are
- * reasons why it might be a good idea. It won't hurt in any case.
- */
- movw $0x0001, %ax # protected mode (PE) bit
- lmsw %ax # This is it#
- jmp flush_instr
-flush_instr:
- movw $KERNEL_DS, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw %ax, %fs
- movw %ax, %gs
-
-data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs)
-
-/*
- * This routine checks that the keyboard command queue is empty
- * (after emptying the output buffers)
- *
- * No timeout is used - if this hangs there is something wrong with
- * the machine, and we probably couldn't proceed anyway.
- */
-empty_8042:
- call delay
- inb $0x64, %al # 8042 status port
- cmpb $0xff, %al # from grub-a20-patch, skip if not impl
- jz empty_8042_ret
-
- testb $1, %al # output buffer?
- jz no_output
- call delay
- inb $0x60, %al # read it
- jmp empty_8042
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042 # yes - loop
-empty_8042_ret:
- ret
-#
-# Delay is needed after doing i/o
-#
-delay:
- .word 0x00eb # jmp $+2
- ret
-
-gdt:
- .word 0,0,0,0 # dummy
-
- .word 0,0,0,0 # unused
-
- .word 0x7FFF # limit 128mb
- .word 0x0000 # base address=0
- .word 0x9A00 # code read/exec
- .word 0x00C0 # granularity=4096, 386
-
- .word 0x7FFF # limit 128mb
- .word 0x0000 # base address=0
- .word 0x9200 # data read/write
- .word 0x00C0 # granularity=4096, 386
-
-idt_48:
- .word 0 # idt limit=0
- .long 0 # idt base=0L
-
-gdt_48:
- .word 0x800 # gdt limit=2048, 256 GDT entries
- .word 512+gdt - start,0x9 # gdt base = 0X9xxxx
-
-msg1:
- .asciz "Setup.S\r\n"
-
- /* Pad setup to the proper size */
- .org (SETUPSECS*512)
-
+/*
+ * setup.s is responsible for getting the system data from the BIOS,
+ * and putting them into the appropriate places in system memory.
+ * both setup.s and system has been loaded by the bootblock.
+ *
+ * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86.
+ */
+
+#define __ASSEMBLY__
+#include "defs.h"
+
+.code16
+.section ".setup", "ax", @progbits
+.globl start
+start:
+# ok, the read went well
+# now we want to move to protected mode ...
+
+
+ cli # no interrupts allowed #
+ movb $0x80, %al # disable NMI for the bootup sequence
+ outb %al, $0x70
+
+# The system will move itself to its rightful place.
+# reload the segment registers and the stack since the
+# APs also execute this code
+#ljmp $INITSEG, $(reload - start + 0x200)
+reload:
+ movw $INITSEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %ss # reset the stack to INITSEG:0x4000-12.
+ movw %dx, %sp
+ push %cs
+ pop %ds
+ lidt idt_48 - start # load idt with 0,0
+ lgdt gdt_48 - start # load gdt with whatever appropriate
+
+# that was painless, now we enable A20
+# start from grub-a20.patch
+ /*
+ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
+ * register
+ */
+ mov $0x92, %dx
+ inb %dx, %al
+ /* skip the port92 code if it's unimplemented (read returns 0xff) */
+ cmpb $0xff, %al
+ jz alt_a20_done
+
+ /* set or clear bit1, the ALT_A20_GATE bit */
+ movb 4(%esp), %ah
+ testb %ah, %ah
+ jz alt_a20_cont1
+ orb $2, %al
+ jmp alt_a20_cont2
+alt_a20_cont1:
+ and $0xfd, %al
+
+ /* clear the INIT_NOW bit; don't accidently reset the machine */
+alt_a20_cont2:
+ and $0xfe, %al
+ outb %al, %dx
+
+alt_a20_done:
+# end from grub-a20.patch
+
+ call empty_8042
+
+ movb $0xD1, %al # command write
+ outb %al, $0x64
+ call empty_8042
+
+ movb $0xDF, %al # A20 on
+ outb %al, $0x60
+ call empty_8042
+
+/*
+ * Note that the short jump isn't strictly needed, althought there are
+ * reasons why it might be a good idea. It won't hurt in any case.
+ */
+ movw $0x0001, %ax # protected mode (PE) bit
+ lmsw %ax # This is it#
+ jmp flush_instr
+flush_instr:
+ movw $KERNEL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs)
+
+/*
+ * This routine checks that the keyboard command queue is empty
+ * (after emptying the output buffers)
+ *
+ * No timeout is used - if this hangs there is something wrong with
+ * the machine, and we probably couldn't proceed anyway.
+ */
+empty_8042:
+ call delay
+ inb $0x64, %al # 8042 status port
+ cmpb $0xff, %al # from grub-a20-patch, skip if not impl
+ jz empty_8042_ret
+ testb $1, %al # output buffer?
+ jz no_output
+ call delay
+ inb $0x60, %al # read it
+ jmp empty_8042
+
+no_output:
+ testb $2, %al # is input buffer full?
+ jnz empty_8042 # yes - loop
+empty_8042_ret:
+ ret
+#
+# Delay is needed after doing i/o
+#
+delay:
+ .word 0x00eb # jmp $+2
+ ret
+
+gdt:
+ .word 0,0,0,0 # dummy
+
+ .word 0,0,0,0 # unused
+
+ .word 0x7FFF # limit 128mb
+ .word 0x0000 # base address=0
+ .word 0x9A00 # code read/exec
+ .word 0x00C0 # granularity=4096, 386
+
+ .word 0x7FFF # limit 128mb
+ .word 0x0000 # base address=0
+ .word 0x9200 # data read/write
+ .word 0x00C0 # granularity=4096, 386
+
+idt_48:
+ .word 0 # idt limit=0
+ .long 0 # idt base=0L
+
+gdt_48:
+ .word 0x800 # gdt limit=2048, 256 GDT entries
+ .word 512+gdt - start,0x9 # gdt base = 0X9xxxx
+
+msg1:
+ .asciz "Setup.S\r\n"
+
+ /* Pad setup to the proper size */
+ .org (SETUPSECS*512)
+
diff --git a/smp.c b/smp.c
index e49f52c..48fbb09 100644
--- a/smp.c
+++ b/smp.c
@@ -1,136 +1,113 @@
/*
- * smp.c --
+ * MemTest86+ V5 Specific code (GPL V2.0)
+ * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
+ * http://www.canardpc.com - http://www.memtest.org
+ * ------------------------------------------------
+ * smp.c - MemTest-86 Version 3.5
*
- * Implements support for SMP machines. For reasons of
- * simplicity, we do not handle all possible cases allowed by the
- * MP spec. For example, we expect an explicit MP configuration
- * table and do not handle default configurations. We also expect
- * an on-chip local apic and do not support an external 82489DX
- * apic controller.
- *
+ * Released under version 2 of the Gnu Public License.
+ * By Chris Brady
*/
#include "stddef.h"
-#include "smp.h"
+#include "stdint.h"
#include "cpuid.h"
+#include "smp.h"
#include "test.h"
+
#define DELAY_FACTOR 1
+unsigned num_cpus = 1; // There is at least one cpu, the BSP
+int act_cpus;
+unsigned found_cpus = 0;
+
extern void memcpy(void *dst, void *src , int len);
extern void test_start(void);
+extern int run_cpus;
+extern int maxcpus;
+extern char cpu_mask[];
+extern struct cpu_ident cpu_id;
-typedef struct {
- bool started;
-} ap_info_t;
+struct barrier_s *barr;
-volatile apic_register_t *APIC = NULL;
-unsigned number_of_cpus = 1; // There is at least one cpu, the BSP
-/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */
-static unsigned cpu_num_to_apic_id[MAX_CPUS];
-volatile ap_info_t AP[MAX_CPUS];
+void smp_find_cpus();
-uint8_t
-checksum(uint8_t *data, unsigned len)
+void barrier_init(int max)
{
- uint32_t sum = 0;
- uint8_t *end = data + len;
- while (data < end) {
- sum += *data;
- data++;
- }
- return (uint8_t)(sum % 0x100);
+ /* Set the adddress of the barrier structure */
+ barr = (struct barrier_s *)0x9ff00;
+ barr->lck.slock = 1;
+ barr->mutex.slock = 1;
+ barr->maxproc = max;
+ barr->count = max;
+ barr->st1.slock = 1;
+ barr->st2.slock = 0;
}
-
-bool
-read_mp_config_table(uintptr_t addr)
+void s_barrier_init(int max)
{
- mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
- uint8_t *tab_entry_ptr;
- uint8_t *mpc_table_end;
- extern unsigned num_hyper_threads_per_core;
-
- if (mpc->signature != MPCSignature) {
- return FALSE;
- }
- if (checksum((uint8_t*)mpc, mpc->length) != 0) {
- return FALSE;
- }
-
-
- /* FIXME: the uintptr_t cast here works around a compilation problem on
- * AMD64, but it ignores the real problem, which is that lapic_addr
- * is only 32 bits. Maybe that's OK, but it should be investigated.
- */
- APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
-
- tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
- mpc_table_end = ((uint8_t*)mpc) + mpc->length;
- while (tab_entry_ptr < mpc_table_end) {
- switch (*tab_entry_ptr) {
- case MP_PROCESSOR: {
- mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr;
-
- if (pe->cpu_flag & CPU_BOOTPROCESSOR) {
- // BSP is CPU 0
- cpu_num_to_apic_id[0] = pe->apic_id;
- } else if (number_of_cpus < MAX_CPUS) {
- cpu_num_to_apic_id[number_of_cpus] = pe->apic_id;
- number_of_cpus++;
- }
- if (num_hyper_threads_per_core > 1 ) {
- cpu_num_to_apic_id[number_of_cpus] = pe->apic_id | 1;
- number_of_cpus++;
- }
-
- // we cannot handle non-local 82489DX apics
- if ((pe->apic_ver & 0xf0) != 0x10) {
- return 0;
- }
-
- // we don't know what to do with disabled cpus
-
- tab_entry_ptr += sizeof(mp_processor_entry_t);
- break;
- }
- case MP_BUS: {
- tab_entry_ptr += sizeof(mp_bus_entry_t);
- break;
- }
- case MP_IOAPIC: {
- tab_entry_ptr += sizeof(mp_io_apic_entry_t);
- break;
- }
- case MP_INTSRC:
- tab_entry_ptr += sizeof(mp_interrupt_entry_t);
- case MP_LINTSRC:
- tab_entry_ptr += sizeof(mp_local_interrupt_entry_t);
- break;
- default:
- return FALSE;
- }
- }
- return TRUE;
+ barr->s_lck.slock = 1;
+ barr->s_maxproc = max;
+ barr->s_count = max;
+ barr->s_st1.slock = 1;
+ barr->s_st2.slock = 0;
}
+void barrier()
+{
+ if (num_cpus == 1 || v->fail_safe & 3) {
+ return;
+ }
+ spin_wait(&barr->st1); /* Wait if the barrier is active */
+ spin_lock(&barr->lck); /* Get lock for barr struct */
+ if (--barr->count == 0) { /* Last process? */
+ barr->st1.slock = 0; /* Hold up any processes re-entering */
+ barr->st2.slock = 1; /* Release the other processes */
+ barr->count++;
+ spin_unlock(&barr->lck);
+ } else {
+ spin_unlock(&barr->lck);
+ spin_wait(&barr->st2); /* wait for peers to arrive */
+ spin_lock(&barr->lck);
+ if (++barr->count == barr->maxproc) {
+ barr->st1.slock = 1;
+ barr->st2.slock = 0;
+ }
+ spin_unlock(&barr->lck);
+ }
+}
-floating_pointer_struct_t *
-scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length)
+void s_barrier()
{
- floating_pointer_struct_t *fp;
- uintptr_t end = addr + length;
+ if (run_cpus == 1 || v->fail_safe & 3) {
+ return;
+ }
+ spin_wait(&barr->s_st1); /* Wait if the barrier is active */
+ spin_lock(&barr->s_lck); /* Get lock for barr struct */
+ if (--barr->s_count == 0) { /* Last process? */
+ barr->s_st1.slock = 0; /* Hold up any processes re-entering */
+ barr->s_st2.slock = 1; /* Release the other processes */
+ barr->s_count++;
+ spin_unlock(&barr->s_lck);
+ } else {
+ spin_unlock(&barr->s_lck);
+ spin_wait(&barr->s_st2); /* wait for peers to arrive */
+ spin_lock(&barr->s_lck);
+ if (++barr->s_count == barr->s_maxproc) {
+ barr->s_st1.slock = 1;
+ barr->s_st2.slock = 0;
+ }
+ spin_unlock(&barr->s_lck);
+ }
+}
+typedef struct {
+ bool started;
+} ap_info_t;
- fp = (floating_pointer_struct_t*)addr;
- while ((uintptr_t)fp < end) {
- if (fp->signature == FPSignature) {
- if (fp->length == 1 && checksum((uint8_t*)fp, 16) == 0) {
- return fp;
- }
- }
- fp++;
- }
- return NULL;
-}
+volatile apic_register_t *APIC = NULL;
+/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */
+static unsigned cpu_num_to_apic_id[MAX_CPUS];
+volatile ap_info_t AP[MAX_CPUS];
void PUT_MEM16(uintptr_t addr, uint16_t val)
{
@@ -199,7 +176,40 @@ memset (void *dst,
*((char *) dst + i) = value;
}
}
+void initialise_cpus(void)
+{
+ int i;
+
+ act_cpus = 0;
+
+ if (maxcpus > 1) {
+ smp_find_cpus();
+ /* The total number of CPUs may be limited */
+ if (num_cpus > maxcpus) {
+ num_cpus = maxcpus;
+ }
+ /* Determine how many cpus have been selected */
+ for(i = 0; i < num_cpus; i++) {
+ if (cpu_mask[i]) {
+ act_cpus++;
+ }
+ }
+ } else {
+ act_cpus = found_cpus = num_cpus = 1;
+ }
+
+ /* Initialize the barrier before starting AP's */
+ barrier_init(act_cpus);
+
+ /* let the BSP initialise the APs. */
+ for(i = 1; i < num_cpus; i++) {
+ /* Only start this CPU if it is selected by the mask */
+ if (cpu_mask[i]) {
+ smp_boot_ap(i);
+ }
+ }
+}
void kick_cpu(unsigned cpu_num)
{
unsigned num_sipi, apic_id;
@@ -223,7 +233,7 @@ void kick_cpu(unsigned cpu_num)
APIC_WRITE(APICR_ESR, 0);
- SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (uint32_t)startup_32 >> 12);
+ SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (unsigned)startup_32 >> 12);
timeout = 0;
do {
@@ -233,15 +243,15 @@ void kick_cpu(unsigned cpu_num)
} while (send_pending && timeout < 1000);
if (send_pending) {
- //cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent");
}
delay(100000 / DELAY_FACTOR);
err = APIC_READ(APICR_ESR) & 0xef;
if (err) {
- //cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
- //hprint(LINE_STATUS+1, COL_MID, err);
+ cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x");
+ hprint(LINE_STATUS+3, COL_MID, err);
}
}
}
@@ -304,91 +314,330 @@ void boot_ap(unsigned cpu_num)
} while (send_pending && timeout < 1000);
if (send_pending) {
- //cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent");
}
delay(100000 / DELAY_FACTOR);
err = APIC_READ(APICR_ESR) & 0xef;
if (err) {
- //cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
- // hprint(LINE_STATUS+1, COL_MID, err);
+ cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x");
+ hprint(LINE_STATUS+3, COL_MID, err);
}
}
}
-void
-smp_init_bsp()
+static int checksum(unsigned char *mp, int len)
{
- floating_pointer_struct_t *fp;
- /* gets the details about the cpu, the type, the brand
- * whether it is a multi-core package etc.
- */
- cpuid_init();
-
- memset(&AP, 0, sizeof AP);
+ int sum = 0;
- fp = scan_for_floating_ptr_struct(0x0, 0x400);
- if (fp == NULL) {
- fp = scan_for_floating_ptr_struct(639*0x400, 0x400);
+ while (len--) {
+ sum += *mp++;
}
- if (fp == NULL) {
- fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
+ return (sum & 0xFF);
+}
+
+/* Parse an MP config table for CPU information */
+bool read_mp_config_table(uintptr_t addr)
+{
+ mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
+ uint8_t *tab_entry_ptr;
+ uint8_t *mpc_table_end;
+
+ if (mpc->signature != MPCSignature) {
+ return FALSE;
}
- if (fp == NULL) {
- /*
- * If it is an SMP machine we should know now, unless the
- * configuration is in an EISA/MCA bus machine with an
- * extended bios data area.
- *
- * there is a real-mode segmented pointer pointing to the
- * 4K EBDA area at 0x40E, calculate and scan it here.
- */
- unsigned int address = *(unsigned short *)0x40E;
- address <<= 4;
- if (address) {
- fp = scan_for_floating_ptr_struct(address, 0x400);
- }
+ if (checksum((unsigned char*)mpc, mpc->length) != 0) {
+ return FALSE;
}
- if (fp != NULL && fp->phys_addr != 0) {
- if (!read_mp_config_table(fp->phys_addr)) {
- //cprint(LINE_STATUS+1,0, "SMP: Error while parsing MP config table");
+ /* FIXME: the uintptr_t cast here works around a compilation problem on
+ * AMD64, but it ignores the real problem, which is that lapic_addr
+ * is only 32 bits. Maybe that's OK, but it should be investigated.
+ */
+ APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
+
+ tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
+ mpc_table_end = ((uint8_t*)mpc) + mpc->length;
+
+ while (tab_entry_ptr < mpc_table_end) {
+ switch (*tab_entry_ptr) {
+ case MP_PROCESSOR: {
+ mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr;
+
+ if (pe->cpu_flag & CPU_BOOTPROCESSOR) {
+ // BSP is CPU 0
+ cpu_num_to_apic_id[0] = pe->apic_id;
+ } else if (num_cpus < MAX_CPUS) {
+ cpu_num_to_apic_id[num_cpus] = pe->apic_id;
+ num_cpus++;
+ }
+ found_cpus++;
+
+ // we cannot handle non-local 82489DX apics
+ if ((pe->apic_ver & 0xf0) != 0x10) {
+ return 0;
+ }
+
+ tab_entry_ptr += sizeof(mp_processor_entry_t);
+ break;
+ }
+ case MP_BUS: {
+ tab_entry_ptr += sizeof(mp_bus_entry_t);
+ break;
+ }
+ case MP_IOAPIC: {
+ tab_entry_ptr += sizeof(mp_io_apic_entry_t);
+ break;
+ }
+ case MP_INTSRC:
+ tab_entry_ptr += sizeof(mp_interrupt_entry_t);
+ break;
+ case MP_LINTSRC:
+ tab_entry_ptr += sizeof(mp_local_interrupt_entry_t);
+ break;
+ default:
+ return FALSE;
}
}
-/*
- if (fp == NULL) {
- cprint(LINE_STATUS+1,0,"SMP: No floating pointer structure found");
+ return TRUE;
+}
+
+/* Search for a Floating Pointer structure */
+floating_pointer_struct_t *
+scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length)
+{
+ floating_pointer_struct_t *fp;
+ uintptr_t end = addr + length;
+
+
+ while ((uintptr_t)addr < end) {
+ fp = (floating_pointer_struct_t*)addr;
+ if (*(unsigned int *)addr == FPSignature && fp->length == 1 && checksum((unsigned char*)addr, 16) == 0 && ((fp->spec_rev == 1) || (fp->spec_rev == 4))) {
+ return fp;
+ }
+ addr += 4;
}
-*/
+ return NULL;
}
-void
-smp_init_aps()
+/* Search for a Root System Descriptor Pointer */
+rsdp_t *scan_for_rsdp(uintptr_t addr, uint32_t length)
{
- int cpuNum;
- for(cpuNum = 0 ; cpuNum < MAX_CPUS ; cpuNum++) {
- AP[cpuNum].started = FALSE;
+ rsdp_t *rp;
+ uintptr_t end = addr + length;
+
+
+ while ((uintptr_t)addr < end) {
+ rp = (rsdp_t*)addr;
+ if (*(unsigned int *)addr == RSDPSignature &&
+ checksum((unsigned char*)addr, rp->length) == 0) {
+ return rp;
+ }
+ addr += 4;
}
+ return NULL;
}
-unsigned
-my_apic_id()
+/* Parse a MADT table for processor entries */
+int parse_madt(uintptr_t addr) {
+
+ mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
+ uint8_t *tab_entry_ptr;
+ uint8_t *mpc_table_end;
+
+ if (checksum((unsigned char*)mpc, mpc->length) != 0) {
+ return FALSE;
+ }
+
+ APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
+
+ tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
+ mpc_table_end = ((uint8_t*)mpc) + mpc->length;
+ while (tab_entry_ptr < mpc_table_end) {
+
+ madt_processor_entry_t *pe = (madt_processor_entry_t*)tab_entry_ptr;
+ if (pe->type == MP_PROCESSOR) {
+ if (pe->enabled) {
+ if (num_cpus < MAX_CPUS) {
+ cpu_num_to_apic_id[num_cpus] = pe->apic_id;
+
+ /* the first CPU is the BSP, don't increment */
+ if (found_cpus) {
+ num_cpus++;
+ }
+ }
+ found_cpus++;
+ }
+ }
+ tab_entry_ptr += pe->length;
+ }
+ return TRUE;
+}
+
+/* This is where we search for SMP information in the following order
+ * look for a floating MP pointer
+ * found:
+ * check for a default configuration
+ * found:
+ * setup config, return
+ * check for a MP config table
+ * found:
+ * validate:
+ * good:
+ * parse the MP config table
+ * good:
+ * setup config, return
+ *
+ * find & validate ACPI RSDP (Root System Descriptor Pointer)
+ * found:
+ * find & validate RSDT (Root System Descriptor Table)
+ * found:
+ * find & validate MSDT
+ * found:
+ * parse the MADT table
+ * good:
+ * setup config, return
+ */
+void smp_find_cpus()
+{
+ floating_pointer_struct_t *fp;
+ rsdp_t *rp;
+ rsdt_t *rt;
+ uint8_t *tab_ptr, *tab_end;
+ unsigned int *ptr;
+ unsigned int uiptr;
+
+ if(v->fail_safe & 3) { return; }
+
+ memset(&AP, 0, sizeof AP);
+
+ if(v->fail_safe & 8)
+ {
+ // Search for the Floating MP structure pointer
+ fp = scan_for_floating_ptr_struct(0x0, 0x400);
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(639*0x400, 0x400);
+ }
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
+ }
+ if (fp == NULL) {
+ // Search the BIOS ESDS area
+ unsigned int address = *(unsigned short *)0x40E;
+ address <<= 4;
+ if (address) {
+ fp = scan_for_floating_ptr_struct(address, 0x400);
+ }
+ }
+
+ if (fp != NULL) {
+ // We have a floating MP pointer
+ // Is this a default configuration?
+
+ if (fp->feature[0] > 0 && fp->feature[0] <=7) {
+ // This is a default config so plug in the numbers
+ num_cpus = 2;
+ APIC = (volatile apic_register_t*)0xFEE00000;
+ cpu_num_to_apic_id[0] = 0;
+ cpu_num_to_apic_id[1] = 1;
+ return;
+ }
+
+ // Do we have a pointer to a MP configuration table?
+ if ( fp->phys_addr != 0) {
+ if (read_mp_config_table(fp->phys_addr)) {
+ // Found a good MP table, done
+ return;
+ }
+ }
+ }
+ }
+
+
+ /* No MP table so far, try to find an ACPI MADT table
+ * We try to use the MP table first since there is no way to distinguish
+ * real cores from hyper-threads in the MADT */
+
+ /* Search for the RSDP */
+ rp = scan_for_rsdp(0xE0000, 0x20000);
+ if (rp == NULL) {
+ /* Search the BIOS ESDS area */
+ unsigned int address = *(unsigned short *)0x40E;
+ address <<= 4;
+ if (address) {
+ rp = scan_for_rsdp(address, 0x400);
+ }
+ }
+
+ if (rp == NULL) {
+ /* RSDP not found, give up */
+ return;
+ }
+
+ /* Found the RSDP, now get either the RSDT or XSDT */
+ if (rp->revision >= 2) {
+ rt = (rsdt_t *)rp->xrsdt[0];
+
+ if (rt == 0) {
+ return;
+ }
+ // Validate the XSDT
+ if (*(unsigned int *)rt != XSDTSignature) {
+ return;
+ }
+ if ( checksum((unsigned char*)rt, rt->length) != 0) {
+ return;
+ }
+
+ } else {
+ rt = (rsdt_t *)rp->rsdt;
+ if (rt == 0) {
+ return;
+ }
+ /* Validate the RSDT */
+ if (*(unsigned int *)rt != RSDTSignature) {
+ return;
+ }
+ if ( checksum((unsigned char*)rt, rt->length) != 0) {
+ return;
+ }
+ }
+
+ /* Scan the RSDT or XSDT for a pointer to the MADT */
+ tab_ptr = ((uint8_t*)rt) + sizeof(rsdt_t);
+ tab_end = ((uint8_t*)rt) + rt->length;
+
+ while (tab_ptr < tab_end) {
+
+ uiptr = *((unsigned int *)tab_ptr);
+ ptr = (unsigned int *)uiptr;
+
+ /* Check for the MADT signature */
+ if (ptr && *ptr == MADTSignature) {
+ /* Found it, now parse it */
+ if (parse_madt((uintptr_t)ptr)) {
+ return;
+ }
+ }
+ tab_ptr += 4;
+ }
+}
+
+unsigned my_apic_id()
{
return (APIC[APICR_ID][0]) >> 24;
}
-void
-smp_ap_booted(unsigned cpu_num)
+void smp_ap_booted(unsigned cpu_num)
{
AP[cpu_num].started = TRUE;
}
-void
-smp_boot_ap(unsigned cpu_num)
+void smp_boot_ap(unsigned cpu_num)
{
unsigned timeout;
- extern bool smp_mode;
+
boot_ap(cpu_num);
timeout = 0;
do {
@@ -397,21 +646,13 @@ smp_boot_ap(unsigned cpu_num)
} while (!AP[cpu_num].started && timeout < 100000 / DELAY_FACTOR);
if (!AP[cpu_num].started) {
- //cprint(LINE_STATUS+1, 0, "SMP: Boot timeout for");
- //dprint(LINE_STATUS+1, COL_MID, cpu_num,2,1);
- //cprint(LINE_STATUS+1, 26, "Turning off SMP");
- smp_mode = FALSE;
+ cprint(LINE_STATUS+3, 0, "SMP: Boot timeout for");
+ dprint(LINE_STATUS+3, COL_MID, cpu_num,2,1);
+ cprint(LINE_STATUS+3, 26, "Turning off SMP");
}
}
-unsigned
-smp_num_cpus()
-{
- return number_of_cpus;
-}
-
-unsigned
-smp_my_cpu_num()
+unsigned smp_my_cpu_num()
{
unsigned apicid = my_apic_id();
unsigned i;
@@ -427,14 +668,25 @@ smp_my_cpu_num()
return i;
}
-volatile spinlock_t barr_lk={1};
-void barrier(volatile int *barr, int n)
+/* A set of simple functions used to preserve assigned CPU ordinals since
+ * they are lost after relocation (the stack is reloaded).
+ */
+int num_to_ord[MAX_CPUS];
+void smp_set_ordinal(int me, int ord)
{
- spin_lock(&barr_lk);
- barr++;
- spin_unlock(&barr_lk);
- while((uint32_t)barr<n);
- barr = 0;
- return;
+ num_to_ord[me] = ord;
}
+int smp_my_ord_num(int me)
+{
+ return num_to_ord[me];
+}
+
+int smp_ord_to_cpu(int me)
+{
+ int i;
+ for (i=0; i<MAX_CPUS; i++) {
+ if (num_to_ord[i] == me) return i;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/smp.h b/smp.h
index 152068c..5d07ce7 100644
--- a/smp.h
+++ b/smp.h
@@ -7,10 +7,9 @@
#define _SMP_H_
#include "stdint.h"
#include "defs.h"
-#define MAX_CPUS 16 // "16 CPUs ought to be enough for everybody."
+#define MAX_CPUS 32
-
-#define FPSignature ('_' | 'M' << 8 | 'P' << 16 | '_' << 24)
+#define FPSignature ('_' | ('M' << 8) | ('P' << 16) | ('_' << 24))
typedef struct {
uint32_t signature; // "_MP_"
@@ -21,7 +20,7 @@ typedef struct {
uint8_t feature[5];
} floating_pointer_struct_t;
-#define MPCSignature ('P' | 'C' << 8 | 'M' << 16 | 'P' << 24)
+#define MPCSignature ('P' | ('C' << 8) | ('M' << 16) | ('P' << 24))
typedef struct {
uint32_t signature; // "PCMP"
uint16_t length;
@@ -59,21 +58,12 @@ typedef struct {
uint32_t reserved[2];
} mp_processor_entry_t;
-
typedef struct {
uint8_t type; // has value MP_BUS
uint8_t busid;
char bustype[6];
} mp_bus_entry_t;
-#define BUSTYPE_EISA "EISA"
-#define BUSTYPE_ISA "ISA"
-#define BUSTYPE_INTERN "INTERN"
-#define BUSTYPE_MCA "MCA"
-#define BUSTYPE_VL "VL"
-#define BUSTYPE_PCI "PCI"
-#define BUSTYPE_PCMCIA "PCMCIA"
-
/* We don't understand the others */
typedef struct {
@@ -117,6 +107,39 @@ typedef struct {
uint8_t destapiclint;
} mp_local_interrupt_entry_t;
+#define RSDPSignature ('R' | ('S' << 8) | ('D' << 16) | (' ' << 24))
+typedef struct {
+ char signature[8]; // "RSD "
+ uint8_t checksum;
+ char oemid[6];
+ uint8_t revision;
+ uint32_t rsdt;
+ uint32_t length;
+ uint32_t xrsdt[2];
+ uint8_t xsum;
+} rsdp_t;
+
+#define RSDTSignature ('R' | ('S' << 8) | ('D' << 16) | ('T' << 24))
+#define XSDTSignature ('X' | ('S' << 8) | ('D' << 16) | ('T' << 24))
+typedef struct {
+ char signature[4]; // "RSDT"
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ char oemid[18];
+ char cid[4];
+ char cver[4];
+} rsdt_t;
+
+#define MADTSignature ('A' | ('P' << 8) | ('I' << 16) | ('C' << 24))
+typedef struct {
+ uint8_t type;
+ uint8_t length;
+ uint8_t acpi_id;
+ uint8_t apic_id; /* Local APIC number */
+ uint32_t enabled;
+} madt_processor_entry_t;
+
/* APIC definitions */
/*
* APIC registers
@@ -169,7 +192,6 @@ typedef uint32_t apic_register_t[4];
extern volatile apic_register_t *APIC;
-unsigned smp_num_cpus();
unsigned smp_my_cpu_num();
void smp_init_bsp(void);
@@ -178,6 +200,30 @@ void smp_init_aps(void);
void smp_boot_ap(unsigned cpu_num);
void smp_ap_booted(unsigned cpu_num);
+typedef struct {
+ unsigned int slock;
+} spinlock_t;
+
+struct barrier_s
+{
+ spinlock_t mutex;
+ spinlock_t lck;
+ int maxproc;
+ volatile int count;
+ spinlock_t st1;
+ spinlock_t st2;
+ spinlock_t s_lck;
+ int s_maxproc;
+ volatile int s_count;
+ spinlock_t s_st1;
+ spinlock_t s_st2;
+};
+
+void barrier();
+void s_barrier();
+void barrier_init(int max);
+void s_barrier_init(int max);
+
static inline void
__GET_CPUID(int ax, uint32_t *regs)
{
@@ -239,24 +285,79 @@ static inline uint64_t __GET_MSR(int cx)
} while (0)
#define OUTB(port, val) __GCC_OUT(b, b, port, val)
-typedef struct {
- unsigned int slock;
-} spinlock_t;
+static inline void spin_wait(spinlock_t *lck)
+{
+ if (cpu_id.fid.bits.mon) {
+ /* Use monitor/mwait for a low power, low contention spin */
+ asm volatile(
+ "movl $0,%%ecx\n\t"
+ "movl %%ecx, %%edx\n\t"
+ "1:\n\t"
+ "movl %%edi,%%eax\n\t"
+ "monitor\n\t"
+ "cmpb $0,(%%edi)\n\t"
+ "jne 2f\n\t"
+ "movl %%ecx, %%eax\n\t"
+ "mwait\n\t"
+ "jmp 1b\n"
+ "2:"
+ : : "D" (lck): "%eax", "%ecx", "%edx"
+ );
+ } else {
+ /* No monitor/mwait so just spin with a lot of nop's */
+ int inc = 0x400;
+ asm volatile(
+ "1:\t"
+ "cmpb $0,%1\n\t"
+ "jne 2f\n\t"
+ "rep ; nop\n\t"
+ "jmp 1b\n"
+ "2:"
+ : : "c" (inc), "m" (lck->slock): "memory"
+ );
+ }
+}
-static inline void spin_lock(volatile spinlock_t *lock)
+static inline void spin_lock(spinlock_t *lck)
{
- asm volatile("\n1:\t"
- " ; lock;decb %0\n\t"
- "jns 3f\n"
- "2:\t"
- "rep;nop\n\t"
- "cmpb $0,%0\n\t"
- "jle 2b\n\t"
- "jmp 1b\n"
- "3:\n\t"
- : "+m" (lock->slock) : : "memory");
+ if (cpu_id.fid.bits.mon) {
+ /* Use monitor/mwait for a low power, low contention spin */
+ asm volatile(
+ "\n1:\t"
+ " ; lock;decb (%%edi)\n\t"
+ "jns 3f\n"
+ "movl $0,%%ecx\n\t"
+ "movl %%ecx, %%edx\n\t"
+ "2:\t"
+ "movl %%edi,%%eax\n\t"
+ "monitor\n\t"
+ "movl %%ecx, %%eax\n\t"
+ "mwait\n\t"
+ "cmpb $0,(%%edi)\n\t"
+ "jle 2b\n\t"
+ "jmp 1b\n"
+ "3:\n\t"
+ : : "D" (lck): "%eax", "%ecx", "%edx"
+ );
+ } else {
+ /* No monitor/mwait so just spin with a lot of nop's */
+ int inc = 0x400;
+ asm volatile(
+ "\n1:\t"
+ " ; lock;decb %0\n\t"
+ "jns 3f\n"
+ "2:\t"
+ "rep;nop\n\t"
+ "cmpb $0,%0\n\t"
+ "jle 2b\n\t"
+ "jmp 1b\n"
+ "3:\n\t"
+ : "+m" (lck->slock) : "c" (inc) : "memory"
+ );
+ }
}
-static inline void spin_unlock(volatile spinlock_t *lock)
+
+static inline void spin_unlock(spinlock_t *lock)
{
asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory");
}
diff --git a/spd.c b/spd.c
index cef93f0..fd3db9f 100644
--- a/spd.c
+++ b/spd.c
@@ -1,9 +1,5 @@
-/* Memtest86 SPD extension
- * added by Reto Sonderegger, 2004, reto@swissbit.com
- *
- * Released under version 2 of the Gnu Puclic License
- * ----------------------------------------------------
- * MemTest86+ V4.20 Specific code (GPL V2.0)
+/*
+ * MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
@@ -29,7 +25,7 @@ extern void wait_keyup();
int smbdev, smbfun;
unsigned short smbusbase;
-unsigned char spd[256];
+unsigned char spd_raw[256];
char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0};
static void ich5_get_smb(void)
@@ -40,6 +36,40 @@ static void ich5_get_smb(void)
if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
}
+static void piix4_get_smb(void)
+{
+ unsigned long x;
+ int result;
+
+ result = pci_conf_read(0, smbdev, smbfun, 0x08, 1, &x);
+
+ if(x < 0x40){
+ // SB600/700
+ result = pci_conf_read(0, smbdev, smbfun, 0x90, 2, &x);
+ if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
+ } else {
+ // SB800
+ sb800_get_smb();
+ }
+}
+
+void sb800_get_smb(void)
+{
+ int lbyte, hbyte;
+
+ __outb(AMD_SMBUS_BASE_REG + 1, AMD_INDEX_IO_PORT);
+ lbyte = __inb(AMD_DATA_IO_PORT);
+ __outb(AMD_SMBUS_BASE_REG, AMD_INDEX_IO_PORT);
+ hbyte = __inb(AMD_DATA_IO_PORT);
+
+ smbusbase = lbyte;
+ smbusbase <<= 8;
+ smbusbase += hbyte;
+ smbusbase &= 0xFFE0;
+
+ if (smbusbase == 0xFFE0) { smbusbase = 0; }
+}
+
unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
{
int l1, h1, l2, h2;
@@ -53,9 +83,9 @@ unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
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
+ rdtsc(l2, h2);
+ t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
+ if (t > 10) break; // break after 10ms
}
return __inb(SMBHSTDAT);
}
@@ -63,10 +93,10 @@ unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
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
+ spd_raw[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd_raw[0] == 0xff) return -1; // no spd here
for (x = 1; x < 256; x++) {
- spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ spd_raw[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
}
return 0;
}
@@ -106,10 +136,10 @@ unsigned char us15w_smb_read_byte(unsigned char adr, unsigned char cmd)
static int us15w_read_spd(int dimmadr)
{
int x;
- spd[0] = us15w_smb_read_byte(0x50 + dimmadr, 0);
- if (spd[0] == 0xff) return -1; // no spd here
+ spd_raw[0] = us15w_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd_raw[0] == 0xff) return -1; // no spd here
for (x = 1; x < 256; x++) {
- spd[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ spd_raw[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
}
return 0;
}
@@ -123,21 +153,29 @@ struct pci_smbus_controller {
};
static struct pci_smbus_controller smbcontrollers[] = {
-{0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd},
-{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, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd},
-{0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd},
-{0, 0, "", NULL, NULL}
+ // Intel SMBUS
+ {0x8086, 0x9C22, "Intel HSW-ULT", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x8C22, "Intel HSW", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x1E22, "Intel Z77", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd},
+ {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, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
+ {0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd},
+ {0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd},
+
+ // AMD SMBUS
+ {0x1002, 0x4385, "AMD SB600/700", piix4_get_smb, ich5_read_spd},
+ {0x1022, 0x780B, "AMD SB800/900", sb800_get_smb, ich5_read_spd},
+ {0, 0, "", NULL, NULL}
};
@@ -145,6 +183,7 @@ 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);
@@ -173,6 +212,7 @@ void get_spd_spec(void)
int module_size;
int curcol;
int temp_nbd;
+ int tck;
index = find_smb_controller();
@@ -184,59 +224,75 @@ void get_spd_spec(void)
smbcontrollers[index].get_adr();
cprint(LINE_SPD-2, 0, "Memory SPD Informations");
- cprint(LINE_SPD-1, 0, "-----------------------------------");
+ cprint(LINE_SPD-1, 0, "--------------------------");
for (j = 0; j < 8; j++) {
if (smbcontrollers[index].read_spd(j) == 0) {
curcol = 1;
- if(spd[2] == 0x0b){
+ if(spd_raw[2] == 0x0b){
// We are here if DDR3 present
// First print slot#, module capacity
cprint(LINE_SPD+k, curcol, " - Slot :");
dprint(LINE_SPD+k, curcol+8, k, 1, 0);
- module_size = get_ddr3_module_size(spd[4] & 0xF, spd[8] & 0x7, spd[7] & 0x7, spd[7] >> 3);
+ module_size = get_ddr3_module_size(spd_raw[4] & 0xF, spd_raw[8] & 0x7, spd_raw[7] & 0x7, spd_raw[7] >> 3);
temp_nbd = getnum(module_size); curcol += 12;
dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd;
cprint(LINE_SPD+k, curcol, " MB"); curcol += 4;
+ // If XMP is supported, check Tck in XMP reg
+ if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A && spd_raw[12])
+ {
+ tck = spd_raw[186];
+ } else {
+ tck = spd_raw[12];
+ }
+
// Then module jedec speed
- switch(spd[12])
+ switch(tck)
{
default:
+ cprint(LINE_SPD+k, curcol, "DDR3-????");
+ break;
case 20:
- cprint(LINE_SPD+k, curcol, "PC3-6400");
- curcol += 8;
+ cprint(LINE_SPD+k, curcol, "DDR3-800");
+ curcol--;
break;
case 15:
- cprint(LINE_SPD+k, curcol, "PC3-8500");
- curcol += 8;
+ cprint(LINE_SPD+k, curcol, "DDR3-1066");
break;
case 12:
- cprint(LINE_SPD+k, curcol, "PC3-10600");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-1333");
break;
case 10:
- cprint(LINE_SPD+k, curcol, "PC3-12800");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-1600");
+ break;
+ case 9:
+ cprint(LINE_SPD+k, curcol, "DDR3-1866");
break;
case 8:
- cprint(LINE_SPD+k, curcol, "PC3-15000");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-2133");
+ break;
+ case 7:
+ cprint(LINE_SPD+k, curcol, "DDR3-2400");
break;
case 6:
- cprint(LINE_SPD+k, curcol, "PC3-16000");
- curcol += 9;
+ cprint(LINE_SPD+k, curcol, "DDR3-2533");
+ break;
+ case 5:
+ cprint(LINE_SPD+k, curcol, "DDR3-2666");
break;
}
- curcol++;
+ curcol += 10;
+
+ if((spd_raw[8] >> 3) == 1) { cprint(LINE_SPD+k, curcol, "ECC"); curcol += 4; }
// Then print module infos (manufacturer & part number)
- spd[117] &= 0x0F; // Parity odd or even
+ spd_raw[117] &= 0x0F; // Parity odd or even
for (i = 0; jep106[i].cont_code < 9; i++) {
- if (spd[117] == jep106[i].cont_code && spd[118] == jep106[i].hex_byte) {
+ if (spd_raw[117] == jep106[i].cont_code && spd_raw[118] == jep106[i].hex_byte) {
// We are here if a Jedec manufacturer is detected
cprint(LINE_SPD+k, curcol, "-"); curcol += 2;
cprint(LINE_SPD+k, curcol, jep106[i].name);
@@ -244,12 +300,25 @@ void get_spd_spec(void)
curcol++;
// Display module serial number
for (h = 128; h < 146; h++) {
- cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h]));
curcol++;
}
+
+ // Detect Week and Year of Manufacturing (Think to upgrade after 2015 !!!)
+ if(curcol <= 72 && spd_raw[120] > 3 && spd_raw[120] < 16 && spd_raw[121] < 55)
+ {
+ cprint(LINE_SPD+k, curcol, "(W");
+ dprint(LINE_SPD+k, curcol+2, spd_raw[121], 2, 0);
+ if(spd_raw[121] < 10) { cprint(LINE_SPD+k, curcol+2, "0"); }
+ cprint(LINE_SPD+k, curcol+4, "'");
+ dprint(LINE_SPD+k, curcol+5, spd_raw[120], 2, 0);
+ if(spd_raw[120] < 10) { cprint(LINE_SPD+k, curcol+5, "0"); }
+ cprint(LINE_SPD+k, curcol+7, ")");
+ curcol += 9;
+ }
// Detect XMP Memory
- if(spd[176] == 0x0C && spd[177] == 0x4A)
+ if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A)
{
cprint(LINE_SPD+k, curcol, "*XMP*");
}
@@ -257,12 +326,12 @@ void get_spd_spec(void)
}
}
// We enter this function if DDR2 is detected
- if(spd[2] == 0x08){
+ if(spd_raw[2] == 0x08){
// First print slot#, module capacity
cprint(LINE_SPD+k, curcol, " - Slot :");
dprint(LINE_SPD+k, curcol+8, k, 1, 0);
- module_size = get_ddr2_module_size(spd[31], spd[5]);
+ module_size = get_ddr2_module_size(spd_raw[31], spd_raw[5]);
temp_nbd = getnum(module_size); curcol += 12;
dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd;
cprint(LINE_SPD+k, curcol, " MB"); curcol += 4;
@@ -270,27 +339,29 @@ void get_spd_spec(void)
// Then module jedec speed
float ddr2_speed, byte1, byte2;
- byte1 = (spd[9] >> 4) * 10;
- byte2 = spd[9] & 0xF;
+ byte1 = (spd_raw[9] >> 4) * 10;
+ byte2 = spd_raw[9] & 0xF;
- ddr2_speed = 1 / (byte1 + byte2) * 10000;
+ ddr2_speed = 1 / (byte1 + byte2) * 10000 * 2;
temp_nbd = getnum(ddr2_speed);
cprint(LINE_SPD+k, curcol, "DDR2-"); curcol += 5;
dprint(LINE_SPD+k, curcol, ddr2_speed, temp_nbd, 0); curcol += temp_nbd;
+
+ if((spd_raw[11] >> 1) == 1) { cprint(LINE_SPD+k, curcol+1, "ECC"); curcol += 4; }
// Then print module infos (manufacturer & part number)
int ccode = 0;
for(i = 64; i < 72; i++)
{
- if(spd[i] == 0x7F) { ccode++; }
+ if(spd_raw[i] == 0x7F) { ccode++; }
}
curcol++;
for (i = 0; jep106[i].cont_code < 9; i++) {
- if (ccode == jep106[i].cont_code && spd[64+ccode] == jep106[i].hex_byte) {
+ if (ccode == jep106[i].cont_code && spd_raw[64+ccode] == jep106[i].hex_byte) {
// We are here if a Jedec manufacturer is detected
cprint(LINE_SPD+k, curcol, "-"); curcol += 2;
cprint(LINE_SPD+k, curcol, jep106[i].name);
@@ -298,7 +369,7 @@ void get_spd_spec(void)
curcol++;
// Display module serial number
for (h = 73; h < 91; h++) {
- cprint(16+k, curcol, convert_hex_to_char(spd[h]));
+ cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h]));
curcol++;
}
@@ -333,7 +404,7 @@ void show_spd(void)
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);
+ hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd_raw[i], 2);
}
flag = 0;
while(!flag) {
diff --git a/spd.h b/spd.h
index 7150381..55f164f 100644
--- a/spd.h
+++ b/spd.h
@@ -1,13 +1,17 @@
/*
- * MemTest86+ V3.00 Specific code (GPL V2.0)
+ * MemTest86+ V5.00 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
*/
+
+#define AMD_INDEX_IO_PORT 0xCD6
+#define AMD_DATA_IO_PORT 0xCD7
+#define AMD_SMBUS_BASE_REG 0x2C
void get_spd_spec(void);
int get_ddr2_module_size(int rank_density_byte, int rank_num_byte);
int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks);
char* convert_hex_to_char(unsigned hex_org);
-#define LINE_SPD 16
+void sb800_get_smb(void);
diff --git a/stddef.h b/stddef.h
new file mode 100644
index 0000000..213c89b
--- /dev/null
+++ b/stddef.h
@@ -0,0 +1,8 @@
+#ifndef I386_STDDEF_H
+#define I386_STDDEF_H
+
+#define NULL ((void *)0)
+
+typedef unsigned long size_t;
+
+#endif /* I386_STDDEF_H */
diff --git a/stdin.h b/stdin.h
new file mode 100644
index 0000000..e3a08e1
--- /dev/null
+++ b/stdin.h
@@ -0,0 +1,52 @@
+#ifndef I386_STDINT_H
+#define I386_STDINT_H
+
+/* Exact integral types */
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+
+typedef unsigned long long uint64_t;
+typedef signed long long int64_t;
+
+/* Small types */
+typedef unsigned char uint_least8_t;
+typedef signed char int_least8_t;
+
+typedef unsigned short uint_least16_t;
+typedef signed short int_least16_t;
+
+typedef unsigned int uint_least32_t;
+typedef signed int int_least32_t;
+
+typedef unsigned long long uint_least64_t;
+typedef signed long long int_least64_t;
+
+/* Fast Types */
+typedef unsigned char uint_fast8_t;
+typedef signed char int_fast8_t;
+
+typedef unsigned int uint_fast16_t;
+typedef signed int int_fast16_t;
+
+typedef unsigned int uint_fast32_t;
+typedef signed int int_fast32_t;
+
+typedef unsigned long long uint_fast64_t;
+typedef signed long long int_fast64_t;
+
+/* Types for `void *' pointers. */
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+
+/* Largest integral types */
+typedef long long int intmax_t;
+typedef unsigned long long uintmax_t;
+
+
+#endif /* I386_STDINT_H */ \ No newline at end of file
diff --git a/test.c b/test.c
index f30f3c4..a56d293 100644
--- a/test.c
+++ b/test.c
@@ -1,53 +1,94 @@
-
-/* test.c - MemTest-86 Version 3.2
+/* test.c - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
+ * By Chris Brady
* ----------------------------------------------------
- * MemTest86+ V3.00 Specific code (GPL V2.0)
+ * MemTest86+ V5 Specific code (GPL V2.0)
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
* http://www.canardpc.com - http://www.memtest.org
+ * Thanks to Passmark for calculate_chunk() and various comments !
*/
-
+
#include "test.h"
#include "config.h"
+#include "stdint.h"
+#include "cpuid.h"
+#include "smp.h"
#include <sys/io.h>
-#include "dmi.h"
-#include <inttypes.h>
-extern int segs, bail;
-extern volatile ulong *p;
-extern ulong p1, p2;
+extern struct cpu_ident cpu_id;
+extern volatile int mstr_cpu;
+extern volatile int run_cpus;
+extern volatile int test;
+extern volatile int segs, bail;
extern int test_ticks, nticks;
extern struct tseq tseq[];
extern void update_err_counts(void);
extern void print_err_counts(void);
+void rand_seed( unsigned int seed1, unsigned int seed2, int me);
+ulong rand(int me);
void poll_errors();
-int ecount = 0;
-
static inline ulong roundup(ulong value, ulong mask)
{
return (value + mask) & ~mask;
}
+
+// start / end - return values for range to test
+// me - this threads CPU number
+// j - index into v->map for current segment we are testing
+// align - number of bytes to align each block to
+void calculate_chunk(ulong** start, ulong** end, int me, int j, int makeMultipleOf)
+{
+ ulong chunk;
+
+
+ // If we are only running 1 CPU then test the whole block
+ if (run_cpus == 1) {
+ *start = v->map[j].start;
+ *end = v->map[j].end;
+ }
+ else{
+
+ // Divide the current segment by the number of CPUs
+ chunk = (ulong)v->map[j].end-(ulong)v->map[j].start;
+ chunk /= run_cpus;
+
+ // Round down to the nearest desired bitlength multiple
+ chunk = (chunk + (makeMultipleOf-1)) & ~(makeMultipleOf-1);
+
+ // Figure out chunk boundaries
+ *start = (ulong*)((ulong)v->map[j].start+(chunk*me));
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ // Also rounds down to boundary if needed, may miss some ram but better than crashing or producing false errors.
+ // This rounding probably will never happen as the segments should be in 4096 bytes pages if I understand correctly.
+ if (me == mstr_cpu) {
+ *end = (ulong*)(v->map[j].end);
+ } else {
+ *end = (ulong*)((ulong)(*start) + chunk);
+ (*end)--;
+ }
+ }
+}
+
/*
* Memory address test, walking ones
*/
-void addr_tst1()
+void addr_tst1(int me)
{
int i, j, k;
- volatile ulong *pt;
- volatile ulong *end;
- ulong bad, mask, bank;
+ volatile ulong *p, *pt, *end;
+ ulong bad, mask, bank, p1;
/* Test the global address bits */
for (p1=0, j=0; j<2; j++) {
- hprint(LINE_PAT, COL_PAT, p1);
+ hprint(LINE_PAT, COL_PAT, p1);
/* Set pattern in our lowest multiple of 0x20000 */
p = (ulong *)roundup((ulong)v->map[0].start, 0x1ffff);
*p = p1;
-
+
/* Now write pattern compliment */
p1 = ~p1;
end = v->map[segs-1].end;
@@ -55,23 +96,23 @@ void addr_tst1()
mask = 4;
do {
pt = (ulong *)((ulong)p | mask);
- if ((uintptr_t)pt == (uintptr_t)p) {
+ if (pt == p) {
mask = mask << 1;
continue;
}
- if ((uintptr_t)pt >= (uintptr_t)end) {
+ if (pt >= end) {
break;
}
*pt = p1;
- if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) {
+ if ((bad = *p) != ~p1) {
ad_err1((ulong *)p, (ulong *)mask,
- bad, ~p1);
+ bad, ~p1);
i = 1000;
}
mask = mask << 1;
} while(mask);
}
- do_tick();
+ do_tick(me);
BAILR
}
@@ -84,48 +125,49 @@ void addr_tst1()
bank = 0x40000;
}
for (p1=0, k=0; k<2; k++) {
- hprint(LINE_PAT, COL_PAT, p1);
+ hprint(LINE_PAT, COL_PAT, p1);
for (j=0; j<segs; j++) {
p = v->map[j].start;
/* Force start address to be a multiple of 256k */
p = (ulong *)roundup((ulong)p, bank - 1);
end = v->map[j].end;
- while ((uintptr_t)p < (uintptr_t)end) {
+ /* Redundant checks for overflow */
+ while (p < end && p > v->map[j].start && p != 0) {
*p = p1;
p1 = ~p1;
- for (i=0; i<200; i++) {
+ for (i=0; i<50; i++) {
mask = 4;
do {
pt = (ulong *)
((ulong)p | mask);
- if ((uintptr_t)pt == (uintptr_t)p) {
+ if (pt == p) {
mask = mask << 1;
continue;
}
- if ((uintptr_t)pt >= (uintptr_t)end) {
+ if (pt >= end) {
break;
}
*pt = p1;
- if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) {
+ if ((bad = *p) != ~p1) {
ad_err1((ulong *)p,
- (ulong *)mask,
- bad,~p1);
+ (ulong *)mask,
+ bad,~p1);
i = 200;
}
mask = mask << 1;
} while(mask);
}
- if ((uintptr_t)(p + bank/4) > (uintptr_t)p) {
- p += bank/4;
+ if (p + bank > p) {
+ p += bank;
} else {
p = end;
}
p1 = ~p1;
}
}
- do_tick();
+ do_tick(me);
BAILR
p1 = ~p1;
}
@@ -134,13 +176,12 @@ void addr_tst1()
/*
* Memory address test, own address
*/
-void addr_tst2()
+void addr_tst2(int me)
{
int j, done;
- volatile ulong *pe;
- volatile ulong *end, *start;
+ ulong *p, *pe, *end, *start;
- cprint(LINE_PAT, COL_PAT, " ");
+ cprint(LINE_PAT, COL_PAT, "address ");
/* Write each address with it's own address */
for (j=0; j<segs; j++) {
@@ -150,39 +191,40 @@ void addr_tst2()
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* *p = (ulong)p;
* }
*/
asm __volatile__ (
- "jmp L90\n\t"
-
+ "jmp L91\n\t"
".p2align 4,,7\n\t"
"L90:\n\t"
- "movl %%edi,(%%edi)\n\t"
"addl $4,%%edi\n\t"
+ "L91:\n\t"
+ "movl %%edi,(%%edi)\n\t"
"cmpl %%edx,%%edi\n\t"
"jb L90\n\t"
- : "=D" (p)
- : "D" (p), "d" (pe)
+ : : "D" (p), "d" (pe)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
@@ -194,41 +236,44 @@ void addr_tst2()
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
- pe += SPINSZ;
- } else {
- pe = end;
- }
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe ) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* if((bad = *p) != (ulong)p) {
* ad_err2((ulong)p, bad);
* }
* }
*/
asm __volatile__ (
- "jmp L91\n\t"
-
+ "jmp L95\n\t"
".p2align 4,,7\n\t"
- "L91:\n\t"
+ "L99:\n\t"
+ "addl $4,%%edi\n\t"
+ "L95:\n\t"
"movl (%%edi),%%ecx\n\t"
"cmpl %%edi,%%ecx\n\t"
- "jne L93\n\t"
- "L92:\n\t"
- "addl $4,%%edi\n\t"
+ "jne L97\n\t"
+ "L96:\n\t"
"cmpl %%edx,%%edi\n\t"
- "jb L91\n\t"
- "jmp L94\n\t"
-
- "L93:\n\t"
+ "jb L99\n\t"
+ "jmp L98\n\t"
+
+ "L97:\n\t"
"pushl %%edx\n\t"
"pushl %%ecx\n\t"
"pushl %%edi\n\t"
@@ -236,15 +281,13 @@ void addr_tst2()
"popl %%edi\n\t"
"popl %%ecx\n\t"
"popl %%edx\n\t"
- "jmp L92\n\t"
+ "jmp L96\n\t"
- "L94:\n\t"
- : "=D" (p)
- : "D" (p), "d" (pe)
+ "L98:\n\t"
+ : : "D" (p), "d" (pe)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
@@ -255,16 +298,17 @@ void addr_tst2()
* produce random numbers in reverse order testing is only done in the forward
* direction.
*/
-void movinvr()
+void movinvr(int me)
{
int i, j, done, seed1, seed2;
- volatile ulong *pe;
- volatile ulong *start,*end;
- ulong num;
- uintptr_t seg_start;
+ ulong *p;
+ ulong *pe;
+ ulong *start,*end;
+ ulong xorVal;
+ //ulong num, bad;
/* Initialize memory with initial sequence of random numbers. */
- if (v->rdtsc) {
+ if (cpu_id.fid.bits.rdtsc) {
asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2));
} else {
seed1 = 521288629 + v->pass;
@@ -272,85 +316,87 @@ void movinvr()
}
/* Display the current seed */
- hprint(LINE_PAT, COL_PAT, seed1);
- rand_seed(seed1, seed2);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, seed1);
+ rand_seed(seed1, seed2, me);
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
pe = start;
p = start;
- seg_start = (uintptr_t)p;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if (seg_start == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code */
/*
- for (; p < pe; p++) {
- *p = rand();
+ for (; p <= pe; p++) {
+ *p = rand(me);
}
*/
- asm __volatile__ (
- "jmp L200\n\t"
- ".p2align 4,,7\n\t"
- "L200:\n\t"
- "call rand\n\t"
+ asm __volatile__ (
+ "jmp L200\n\t"
+ ".p2align 4,,7\n\t"
+ "L201:\n\t"
+ "addl $4,%%edi\n\t"
+ "L200:\n\t"
+ "pushl %%ecx\n\t" \
+ "call rand\n\t"
+ "popl %%ecx\n\t" \
"movl %%eax,(%%edi)\n\t"
- "addl $4,%%edi\n\t"
- "cmpl %%ebx,%%edi\n\t"
- "jb L200\n\t"
- : "=D" (p)
- : "D" (p), "b" (pe)
- : "eax", "edx"
- );
-
- do_tick();
- BAILR
+ "cmpl %%ebx,%%edi\n\t"
+ "jb L201\n\t"
+ : : "D" (p), "b" (pe), "c" (me)
+ : "eax"
+ );
+ p = pe + 1;
} while (!done);
}
/* Do moving inversions test. Check for initial pattern and then
- * write the complement for each memory location. Test from bottom
- * up and then from the top down. */
+ * write the complement for each memory location.
+ */
for (i=0; i<2; i++) {
- rand_seed(seed1, seed2);
+ rand_seed(seed1, seed2, me);
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
pe = start;
p = start;
- seg_start = (uintptr_t)p;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if (seg_start == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code */
-/*
- for (; p < pe; p++) {
- num = rand();
+
+ /*for (; p <= pe; p++) {
+ num = rand(me);
if (i) {
num = ~num;
}
@@ -358,51 +404,85 @@ void movinvr()
error((ulong*)p, num, bad);
}
*p = ~num;
- }
-*/
+ }*/
+
if (i) {
- num = 0xffffffff;
+ xorVal = 0xffffffff;
} else {
- num = 0;
+ xorVal = 0;
}
asm __volatile__ (
- "jmp L26\n\t" \
+
+ "pushl %%ebp\n\t"
- ".p2align 4,,7\n\t" \
- "L26:\n\t" \
+ // Skip first increment
+ "jmp L26\n\t"
+ ".p2align 4,,7\n\t"
+
+ // increment 4 bytes (32-bits)
+ "L27:\n\t"
+ "addl $4,%%edi\n\t"
+
+ // Check this byte
+ "L26:\n\t"
+
+ // Get next random number, pass in me(edx), random value returned in num(eax)
+ // num = rand(me);
+ // cdecl call maintains all registers except eax, ecx, and edx
+ // We maintain edx with a push and pop here using it also as an input
+ // we don't need the current eax value and want it to change to the return value
+ // we overwrite ecx shortly after this discarding its current value
+ "pushl %%edx\n\t" // Push function inputs onto stack
"call rand\n\t"
- "xorl %%ebx,%%eax\n\t" \
- "movl (%%edi),%%ecx\n\t" \
- "cmpl %%eax,%%ecx\n\t" \
- "jne L23\n\t" \
- "L25:\n\t" \
- "movl $0xffffffff,%%edx\n\t" \
- "xorl %%edx,%%eax\n\t" \
- "movl %%eax,(%%edi)\n\t" \
- "addl $4,%%edi\n\t" \
- "cmpl %%esi,%%edi\n\t" \
- "jb L26\n\t" \
- "jmp L24\n" \
+ "popl %%edx\n\t" // Remove function inputs from stack
- "L23:\n\t" \
- "pushl %%esi\n\t" \
- "pushl %%ecx\n\t" \
- "pushl %%eax\n\t" \
- "pushl %%edi\n\t" \
- "call error\n\t" \
- "popl %%edi\n\t" \
- "popl %%eax\n\t" \
- "popl %%ecx\n\t" \
- "popl %%esi\n\t" \
- "jmp L25\n" \
+ // XOR the random number with xorVal(ebx), which is either 0xffffffff or 0 depending on the outer loop
+ // if (i) { num = ~num; }
+ "xorl %%ebx,%%eax\n\t"
+
+ // Move the current value of the current position p(edi) into bad(ecx)
+ // (bad=*p)
+ "movl (%%edi),%%ecx\n\t"
+
+ // Compare bad(ecx) to num(eax)
+ "cmpl %%eax,%%ecx\n\t"
- "L24:\n\t" \
- : "=D" (p)
- : "D" (p), "S" (pe), "b" (num)
- : "eax", "ecx", "edx"
+ // If not equal jump the error case
+ "jne L23\n\t"
+
+ // Set a new value or not num(eax) at the current position p(edi)
+ // *p = ~num;
+ "L25:\n\t"
+ "movl $0xffffffff,%%ebp\n\t"
+ "xorl %%ebp,%%eax\n\t"
+ "movl %%eax,(%%edi)\n\t"
+
+ // Loop until current position p(edi) equals the end position pe(esi)
+ "cmpl %%esi,%%edi\n\t"
+ "jb L27\n\t"
+ "jmp L24\n"
+
+ // Error case
+ "L23:\n\t"
+ // Must manually maintain eax, ecx, and edx as part of cdecl call convention
+ "pushl %%edx\n\t"
+ "pushl %%ecx\n\t" // Next three pushes are functions input
+ "pushl %%eax\n\t"
+ "pushl %%edi\n\t"
+ "call error\n\t"
+ "popl %%edi\n\t" // Remove function inputs from stack and restore register values
+ "popl %%eax\n\t"
+ "popl %%ecx\n\t"
+ "popl %%edx\n\t"
+ "jmp L25\n"
+
+ "L24:\n\t"
+ "popl %%ebp\n\t"
+ :: "D" (p), "S" (pe), "b" (xorVal),
+ "d" (me)
+ : "eax", "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
@@ -412,51 +492,54 @@ void movinvr()
* Test all of memory using a "moving inversions" algorithm using the
* pattern in p1 and it's complement in p2.
*/
-void movinv1(int iter, ulong p1, ulong p2)
+void movinv1 (int iter, ulong p1, ulong p2, int me)
{
int i, j, done;
- volatile ulong *pe;
- volatile ulong len;
- volatile ulong *start,*end;
+ ulong *p, *pe, len, *start, *end;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1);
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
+
+
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- len = pe - p;
- if ((uintptr_t)p == (uintptr_t)pe) {
+ len = pe - p + 1;
+ if (p == pe ) {
break;
}
-/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
- * *p = p1;
- * }
- */
+
+ //Original C code replaced with hand tuned assembly code
+ // seems broken
+ /*for (; p <= pe; p++) {
+ *p = p1;
+ }*/
+
asm __volatile__ (
"rep\n\t" \
"stosl\n\t"
- : "=D" (p)
- : "c" (len), "0" (p), "a" (p1)
+ : : "c" (len), "D" (p), "a" (p1)
);
- do_tick();
- BAILR
+
+ p = pe + 1;
} while (!done);
}
@@ -465,46 +548,50 @@ void movinv1(int iter, ulong p1, ulong p2)
* up and then from the top down. */
for (i=0; i<iter; i++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
-/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
- * if ((bad=*p) != p1) {
- * error((ulong*)p, p1, bad);
- * }
- * *p = p2;
- * }
- */
+
+ // Original C code replaced with hand tuned assembly code
+ // seems broken
+ /*for (; p <= pe; p++) {
+ if ((bad=*p) != p1) {
+ error((ulong*)p, p1, bad);
+ }
+ *p = p2;
+ }*/
+
asm __volatile__ (
"jmp L2\n\t" \
-
".p2align 4,,7\n\t" \
+ "L0:\n\t" \
+ "addl $4,%%edi\n\t" \
"L2:\n\t" \
"movl (%%edi),%%ecx\n\t" \
"cmpl %%eax,%%ecx\n\t" \
"jne L3\n\t" \
"L5:\n\t" \
"movl %%ebx,(%%edi)\n\t" \
- "addl $4,%%edi\n\t" \
"cmpl %%edx,%%edi\n\t" \
- "jb L2\n\t" \
+ "jb L0\n\t" \
"jmp L4\n" \
"L3:\n\t" \
@@ -522,57 +609,61 @@ void movinv1(int iter, ulong p1, ulong p2)
"jmp L5\n" \
"L4:\n\t" \
- : "=D" (p)
- : "a" (p1), "0" (p), "d" (pe), "b" (p2)
+ :: "a" (p1), "D" (p), "d" (pe), "b" (p2)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
for (j=segs-1; j>=0; j--) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = end -1;
- p = end -1;
+ calculate_chunk(&start, &end, me, j, 4);
+ pe = end;
+ p = end;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for underflow */
- if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) {
+ if (pe - SPINSZ < pe && pe != 0) {
pe -= SPINSZ;
} else {
pe = start;
+ done++;
}
- if ((uintptr_t)pe <= (uintptr_t)start) {
+
+ /* Since we are using unsigned addresses a
+ * redundent check is required */
+ if (pe < start || pe > end) {
pe = start;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
-/* Original C code replaced with hand tuned assembly code
- * do {
- * if ((bad=*p) != p2) {
- * error((ulong*)p, p2, bad);
- * }
- * *p = p1;
- * } while (p-- > pe);
- */
+
+ //Original C code replaced with hand tuned assembly code
+ // seems broken
+ /*do {
+ if ((bad=*p) != p2) {
+ error((ulong*)p, p2, bad);
+ }
+ *p = p1;
+ } while (--p >= pe);*/
+
asm __volatile__ (
- "addl $4, %%edi\n\t"
"jmp L9\n\t"
-
".p2align 4,,7\n\t"
- "L9:\n\t"
+ "L11:\n\t"
"subl $4, %%edi\n\t"
+ "L9:\n\t"
"movl (%%edi),%%ecx\n\t"
"cmpl %%ebx,%%ecx\n\t"
"jne L6\n\t"
"L10:\n\t"
"movl %%eax,(%%edi)\n\t"
"cmpl %%edi, %%edx\n\t"
- "jne L9\n\t"
- "subl $4, %%edi\n\t"
+ "jne L11\n\t"
"jmp L7\n\t"
"L6:\n\t"
@@ -590,58 +681,52 @@ void movinv1(int iter, ulong p1, ulong p2)
"jmp L10\n"
"L7:\n\t"
- : "=D" (p)
- : "a" (p1), "0" (p), "d" (pe), "b" (p2)
+ :: "a" (p1), "D" (p), "d" (pe), "b" (p2)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe - 1;
} while (!done);
}
}
}
-void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
+void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off,int me)
{
- int i, j, k=0, done;
- volatile ulong *pe;
- volatile ulong *start, *end;
- ulong pat = 0;
-
-/* CDH start
- * ulong p3 = sval << 31;
- * CDH end
- */
+ int i, j, k=0, n=0, done;
+ ulong *p, *pe, *start, *end, pat = 0, p3;
+ p3 = sval << 31;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1);
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 64);
pe = start;
p = start;
done = 0;
k = off;
pat = p1;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Do a SPINSZ section of memory */
/* Original C code replaced with hand tuned assembly code
- * while (p < pe) {
+ * while (p <= pe) {
* *p = pat;
* if (++k >= 32) {
* pat = lb;
@@ -654,24 +739,29 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
* }
*/
asm __volatile__ (
- "jmp L20\n\t"
- ".p2align 4,,7\n\t"
-
-/* CDH start */
- "L20:\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "incb %%bl\n\t"
- "addl $4,%%edi\n\t"
- "roll $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "jb L20\n\t"
- "andb $31,%%bl\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "jmp L20\n\t"
+ ".p2align 4,,7\n\t"
+ "L923:\n\t"
+ "addl $4,%%edi\n\t"
+ "L20:\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "addl $1,%%ebx\n\t"
+ "cmpl $32,%%ebx\n\t"
+ "jne L21\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "xorl %%ebx,%%ebx\n\t"
+ "jmp L22\n"
+ "L21:\n\t"
+ "shll $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L22:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "jb L923\n\t"
+ : "=b" (k), "=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (sval), "S" (lb)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
@@ -680,33 +770,38 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
* up and then from the top down. */
for (i=0; i<iter; i++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 64);
pe = start;
p = start;
done = 0;
k = off;
pat = p1;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * while (p < pe) {
+ * while (1) {
* if ((bad=*p) != pat) {
* error((ulong*)p, pat, bad);
* }
* *p = ~pat;
+ * if (p >= pe) break;
+ * p++;
+ *
* if (++k >= 32) {
* pat = lb;
* k = 0;
@@ -714,112 +809,108 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
* pat = pat << 1;
* pat |= sval;
* }
- * p++;
* }
*/
asm __volatile__ (
- "pushl %%ebp\n\t"
- "jmp L30\n\t"
-
- ".p2align 4,,7\n\t"
- "L30:\n\t"
- "movl (%%edi),%%ebp\n\t"
- "cmpl %%ecx,%%ebp\n\t"
- "jne L34\n\t"
-
-/* CDH start */
- "L35:\n\t"
- "notl %%ecx\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "notl %%ecx\n\t"
- "addl $4,%%edi\n\t"
- "incb %%bl\n\t"
- "roll $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "jb L30\n\t"
- "jmp L33\n\t"
-/* CDH end */
-
- "L34:\n\t" \
- "pushl %%esi\n\t"
- "pushl %%eax\n\t"
- "pushl %%ebx\n\t"
- "pushl %%edx\n\t"
- "pushl %%ebp\n\t"
- "pushl %%ecx\n\t"
- "pushl %%edi\n\t"
- "call error\n\t"
- "popl %%edi\n\t"
- "popl %%ecx\n\t"
- "popl %%ebp\n\t"
- "popl %%edx\n\t"
- "popl %%ebx\n\t"
- "popl %%eax\n\t"
- "popl %%esi\n\t"
- "jmp L35\n"
-
-/* CDH start */
- "L33:\n\t"
- "andb $31,%%bl\n\t"
- "popl %%ebp\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "pushl %%ebp\n\t"
+ "jmp L30\n\t"
+ ".p2align 4,,7\n\t"
+ "L930:\n\t"
+ "addl $4,%%edi\n\t"
+ "L30:\n\t"
+ "movl (%%edi),%%ebp\n\t"
+ "cmpl %%ecx,%%ebp\n\t"
+ "jne L34\n\t"
+
+ "L35:\n\t"
+ "notl %%ecx\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "notl %%ecx\n\t"
+ "incl %%ebx\n\t"
+ "cmpl $32,%%ebx\n\t"
+ "jne L31\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "xorl %%ebx,%%ebx\n\t"
+ "jmp L32\n"
+ "L31:\n\t"
+ "shll $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L32:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "jb L930\n\t"
+ "jmp L33\n\t"
+
+ "L34:\n\t" \
+ "pushl %%esi\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ebx\n\t"
+ "pushl %%edx\n\t"
+ "pushl %%ebp\n\t"
+ "pushl %%ecx\n\t"
+ "pushl %%edi\n\t"
+ "call error\n\t"
+ "popl %%edi\n\t"
+ "popl %%ecx\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%eax\n\t"
+ "popl %%esi\n\t"
+ "jmp L35\n"
+
+ "L33:\n\t"
+ "popl %%ebp\n\t"
+ : "=b" (k),"=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (sval), "S" (lb)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
- /* Since we already adjusted k and the pattern this
- * code backs both up one step
- */
-/* CDH start */
-/* Original C code replaced with hand tuned assembly code
- * pat = lb;
- * if ( 0 != (k = (k-1) & 31) ) {
- * pat = (pat << k);
- * if ( sval )
- * pat |= ((sval << k) - 1);
- * }
- * k++;
- */
- asm __volatile__ (
- "decl %%ecx\n\t"
- "andl $31,%%ecx\n\t"
- "roll %%cl,%%ebx\n\t"
- "incb %%cl\n\t"
- : "=c" (k), "=b" (pat)
- : "c" (k), "b" (lb)
- );
-/* CDH end */
+ if (--k < 0) {
+ k = 31;
+ }
+ for (pat = lb, n = 0; n < k; n++) {
+ pat = pat << 1;
+ pat |= sval;
+ }
+ k++;
for (j=segs-1; j>=0; j--) {
- start = v->map[j].start;
- end = v->map[j].end;
- p = end -1;
- pe = end -1;
+ calculate_chunk(&start, &end, me, j, 64);
+ p = end;
+ pe = end;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for underflow */
- if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) {
- pe -= SPINSZ;
- } else {
- pe = start;
- }
- if ((uintptr_t)pe <= (uintptr_t)start) {
+ if (pe - SPINSZ < pe && pe != 0) {
+ pe -= SPINSZ;
+ } else {
+ pe = start;
+ done++;
+ }
+ /* We need this redundant check because we are
+ * using unsigned longs for the address.
+ */
+ if (pe < start || pe > end) {
pe = start;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * do {
+ * while(1) {
* if ((bad=*p) != ~pat) {
* error((ulong*)p, ~pat, bad);
* }
* *p = pat;
+ if (p >= pe) break;
+ p++;
* if (--k <= 0) {
* pat = hb;
* k = 32;
@@ -827,61 +918,62 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
* pat = pat >> 1;
* pat |= p3;
* }
- * } while (p-- > pe);
+ * };
*/
asm __volatile__ (
- "pushl %%ebp\n\t"
- "addl $4,%%edi\n\t"
- "jmp L40\n\t"
-
- ".p2align 4,,7\n\t"
- "L40:\n\t"
- "subl $4,%%edi\n\t"
- "movl (%%edi),%%ebp\n\t"
- "notl %%ecx\n\t"
- "cmpl %%ecx,%%ebp\n\t"
- "jne L44\n\t"
-
-/* CDH start */
- "L45:\n\t"
- "notl %%ecx\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "decb %%bl\n\t"
- "rorl $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "ja L40\n\t"
- "jmp L43\n\t"
-/* CDH end */
-
- "L44:\n\t" \
- "pushl %%esi\n\t"
- "pushl %%eax\n\t"
- "pushl %%ebx\n\t"
- "pushl %%edx\n\t"
- "pushl %%ebp\n\t"
- "pushl %%ecx\n\t"
- "pushl %%edi\n\t"
- "call error\n\t"
- "popl %%edi\n\t"
- "popl %%ecx\n\t"
- "popl %%ebp\n\t"
- "popl %%edx\n\t"
- "popl %%ebx\n\t"
- "popl %%eax\n\t"
- "popl %%esi\n\t"
- "jmp L45\n"
-
-/* CDH start */
- "L43:\n\t"
- "andb $31,%%bl\n\t"
- "subl $4,%%edi\n\t"
- "popl %%ebp\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "pushl %%ebp\n\t"
+ "jmp L40\n\t"
+ ".p2align 4,,7\n\t"
+ "L49:\n\t"
+ "subl $4,%%edi\n\t"
+ "L40:\n\t"
+ "movl (%%edi),%%ebp\n\t"
+ "notl %%ecx\n\t"
+ "cmpl %%ecx,%%ebp\n\t"
+ "jne L44\n\t"
+
+ "L45:\n\t"
+ "notl %%ecx\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "decl %%ebx\n\t"
+ "cmpl $0,%%ebx\n\t"
+ "jg L41\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "movl $32,%%ebx\n\t"
+ "jmp L42\n"
+ "L41:\n\t"
+ "shrl $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L42:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "ja L49\n\t"
+ "jmp L43\n\t"
+
+ "L44:\n\t" \
+ "pushl %%esi\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ebx\n\t"
+ "pushl %%edx\n\t"
+ "pushl %%ebp\n\t"
+ "pushl %%ecx\n\t"
+ "pushl %%edi\n\t"
+ "call error\n\t"
+ "popl %%edi\n\t"
+ "popl %%ecx\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%eax\n\t"
+ "popl %%esi\n\t"
+ "jmp L45\n"
+
+ "L43:\n\t"
+ "popl %%ebp\n\t"
+ : "=b" (k), "=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (p3), "S" (hb)
);
- do_tick();
- BAILR
+ p = pe - 1;
} while (!done);
}
}
@@ -890,40 +982,46 @@ void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
/*
* Test all of memory using modulo X access pattern.
*/
-void modtst(int offset, int iter, ulong p1, ulong p2)
+void modtst(int offset, int iter, ulong p1, ulong p2, int me)
{
int j, k, l, done;
- volatile ulong *pe;
- volatile ulong *start, *end;
+ ulong *p;
+ ulong *pe;
+ ulong *start, *end;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT-2, p1);
- cprint(LINE_PAT, COL_PAT+6, "-");
- dprint(LINE_PAT, COL_PAT+7, offset, 2, 1);
+ if (mstr_cpu == me) {
+ hprint(LINE_PAT, COL_PAT-2, p1);
+ cprint(LINE_PAT, COL_PAT+6, "-");
+ dprint(LINE_PAT, COL_PAT+7, offset, 2, 1);
+ }
/* Write every nth location with pattern */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
+ end -= MOD_SZ; /* adjust the ending address */
pe = (ulong *)start;
p = start+offset;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p += MOD_SZ) {
+ * for (; p <= pe; p += MOD_SZ) {
* *p = p1;
* }
*/
@@ -939,36 +1037,36 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
: "=D" (p)
: "D" (p), "d" (pe), "a" (p1)
);
- do_tick();
- BAILR
} while (!done);
}
/* Write the rest of memory "iter" times with the pattern complement */
for (l=0; l<iter; l++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
pe = (ulong *)start;
p = start;
done = 0;
k = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* if (k != offset) {
* *p = p2;
* }
@@ -981,6 +1079,8 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
"jmp L50\n\t" \
".p2align 4,,7\n\t" \
+ "L54:\n\t" \
+ "addl $4,%%edi\n\t" \
"L50:\n\t" \
"cmpl %%ebx,%%ecx\n\t" \
"je L52\n\t" \
@@ -991,43 +1091,43 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
"jle L53\n\t" \
"xorl %%ebx,%%ebx\n\t" \
"L53:\n\t" \
- "addl $4,%%edi\n\t" \
"cmpl %%edx,%%edi\n\t" \
- "jb L50\n\t" \
- : "=D" (p), "=b" (k)
+ "jb L54\n\t" \
+ : "=b" (k)
: "D" (p), "d" (pe), "a" (p2),
"b" (k), "c" (offset)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
/* Now check every nth location */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 4);
pe = (ulong *)start;
p = start+offset;
done = 0;
+ end -= MOD_SZ; /* adjust the ending address */
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
-
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p += MOD_SZ) {
+ * for (; p <= pe; p += MOD_SZ) {
* if ((bad=*p) != p1) {
* error((ulong*)p, p1, bad);
* }
@@ -1064,211 +1164,231 @@ void modtst(int offset, int iter, ulong p1, ulong p2)
: "D" (p), "d" (pe), "a" (p1)
: "ecx"
);
- do_tick();
- BAILR
} while (!done);
}
- cprint(LINE_PAT, COL_PAT, " ");
}
-
-
/*
- * Test memory using block moves
+ * Test memory using block moves
* Adapted from Robert Redelmeier's burnBX test
*/
-void block_move(int iter)
+void block_move(int iter, int me)
{
int i, j, done;
ulong len;
- volatile ulong p, pe, pp;
- volatile ulong start, end;
+ ulong *p, *pe, pp;
+ ulong *start, *end;
- cprint(LINE_PAT, COL_PAT-2, " ");
+ cprint(LINE_PAT, COL_PAT-2, " ");
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
-#ifdef USB_WAR
- /* We can't do the block move test on low memory beacuase
- * BIOS USB support clobbers location 0x410 and 0x4e0
- */
- if (start < 0x4f0) {
- start = 0x4f0;
- }
-#endif
- end = (ulong)v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 64);
+
+ // end is always xxxxxffc, so increment so that length calculations are correct
+ end = end + 1;
+
pe = start;
p = start;
+
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
-
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
-
+ if (p == pe ) {
break;
}
len = ((ulong)pe - (ulong)p) / 64;
+ //len++;
asm __volatile__ (
"jmp L100\n\t"
".p2align 4,,7\n\t"
"L100:\n\t"
+
+ // First loop eax is 0x00000001, edx is 0xfffffffe
"movl %%eax, %%edx\n\t"
"notl %%edx\n\t"
- "movl %%eax,0(%%edi)\n\t"
- "movl %%eax,4(%%edi)\n\t"
- "movl %%eax,8(%%edi)\n\t"
- "movl %%eax,12(%%edi)\n\t"
- "movl %%edx,16(%%edi)\n\t"
- "movl %%edx,20(%%edi)\n\t"
- "movl %%eax,24(%%edi)\n\t"
- "movl %%eax,28(%%edi)\n\t"
- "movl %%eax,32(%%edi)\n\t"
- "movl %%eax,36(%%edi)\n\t"
- "movl %%edx,40(%%edi)\n\t"
- "movl %%edx,44(%%edi)\n\t"
- "movl %%eax,48(%%edi)\n\t"
- "movl %%eax,52(%%edi)\n\t"
- "movl %%edx,56(%%edi)\n\t"
- "movl %%edx,60(%%edi)\n\t"
- "rcll $1, %%eax\n\t"
+
+ // Set a block of 64-bytes // First loop DWORDS are
+ "movl %%eax,0(%%edi)\n\t" // 0x00000001
+ "movl %%eax,4(%%edi)\n\t" // 0x00000001
+ "movl %%eax,8(%%edi)\n\t" // 0x00000001
+ "movl %%eax,12(%%edi)\n\t" // 0x00000001
+ "movl %%edx,16(%%edi)\n\t" // 0xfffffffe
+ "movl %%edx,20(%%edi)\n\t" // 0xfffffffe
+ "movl %%eax,24(%%edi)\n\t" // 0x00000001
+ "movl %%eax,28(%%edi)\n\t" // 0x00000001
+ "movl %%eax,32(%%edi)\n\t" // 0x00000001
+ "movl %%eax,36(%%edi)\n\t" // 0x00000001
+ "movl %%edx,40(%%edi)\n\t" // 0xfffffffe
+ "movl %%edx,44(%%edi)\n\t" // 0xfffffffe
+ "movl %%eax,48(%%edi)\n\t" // 0x00000001
+ "movl %%eax,52(%%edi)\n\t" // 0x00000001
+ "movl %%edx,56(%%edi)\n\t" // 0xfffffffe
+ "movl %%edx,60(%%edi)\n\t" // 0xfffffffe
+
+ // rotate left with carry,
+ // second loop eax is 0x00000002
+ // second loop edx is (~eax) 0xfffffffd
+ "rcll $1, %%eax\n\t"
+
+ // Move current position forward 64-bytes (to start of next block)
"leal 64(%%edi), %%edi\n\t"
+
+ // Loop until end
"decl %%ecx\n\t"
"jnz L100\n\t"
+
: "=D" (p)
: "D" (p), "c" (len), "a" (1)
: "edx"
);
- do_tick();
- BAILR
} while (!done);
}
+ s_barrier();
- /* Now move the data around
+ /* Now move the data around
* First move the data up half of the segment size we are testing
* Then move the data to the original location + 32 bytes
*/
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
-#ifdef USB_WAR
- /* We can't do the block move test on low memory beacuase
- * BIOS USB support clobbers location 0x410 and 0x4e0
- */
- if (start < 0x4f0) {
- start = 0x4f0;
- }
-#endif
- end = (ulong)v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 64);
+
+ // end is always xxxxxffc, so increment so that length calculations are correct
+ end = end + 1;
pe = start;
p = start;
done = 0;
+
do {
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
- pp = p + ((pe - p) / 2);
- len = ((ulong)pe - (ulong)p) / 8;
+ pp = (ulong)p + (((ulong)pe - (ulong)p) / 2); // Mid-point of this block
+ len = ((ulong)pe - (ulong)p) / 8; // Half the size of this block in DWORDS
for(i=0; i<iter; i++) {
+ do_tick(me);
+ BAILR
asm __volatile__ (
"cld\n"
"jmp L110\n\t"
".p2align 4,,7\n\t"
"L110:\n\t"
- "movl %1,%%edi\n\t"
- "movl %0,%%esi\n\t"
- "movl %2,%%ecx\n\t"
+
+ //
+ // At the end of all this
+ // - the second half equals the inital value of the first half
+ // - the first half is right shifted 32-bytes (with wrapping)
+ //
+
+ // Move first half to second half
+ "movl %1,%%edi\n\t" // Destionation, pp (mid point)
+ "movl %0,%%esi\n\t" // Source, p (start point)
+ "movl %2,%%ecx\n\t" // Length, len (size of a half in DWORDS)
"rep\n\t"
"movsl\n\t"
+
+ // Move the second half, less the last 32-bytes. To the first half, offset plus 32-bytes
"movl %0,%%edi\n\t"
- "addl $32,%%edi\n\t"
- "movl %1,%%esi\n\t"
+ "addl $32,%%edi\n\t" // Destination, p(start-point) plus 32 bytes
+ "movl %1,%%esi\n\t" // Source, pp(mid-point)
"movl %2,%%ecx\n\t"
- "subl $8,%%ecx\n\t"
+ "subl $8,%%ecx\n\t" // Length, len(size of a half in DWORDS) minus 8 DWORDS (32 bytes)
"rep\n\t"
"movsl\n\t"
- "movl %0,%%edi\n\t"
- "movl $8,%%ecx\n\t"
+
+ // Move last 8 DWORDS (32-bytes) of the second half to the start of the first half
+ "movl %0,%%edi\n\t" // Destination, p(start-point)
+ // Source, 8 DWORDS from the end of the second half, left over by the last rep/movsl
+ "movl $8,%%ecx\n\t" // Length, 8 DWORDS (32-bytes)
"rep\n\t"
"movsl\n\t"
+
:: "g" (p), "g" (pp), "g" (len)
: "edi", "esi", "ecx"
);
- do_tick();
- BAILR
}
p = pe;
} while (!done);
}
+ s_barrier();
- /* Now check the data
+ /* Now check the data
* The error checking is rather crude. We just check that the
* adjacent words are the same.
*/
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
-#ifdef USB_WAR
- /* We can't do the block move test on low memory beacuase
- * BIOS USB support clobbers location 0x4e0 and 0x410
- */
- if (start < 0x4f0) {
- start = 0x4f0;
- }
-#endif
- end = (ulong)v->map[j].end;
+ calculate_chunk(&start, &end, me, j, 64);
+
+ // end is always xxxxxffc, so increment so that length calculations are correct
+ end = end + 1;
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
pe = end;
}
- if ((uintptr_t)pe >= (uintptr_t)end) {
+ if (pe >= end) {
pe = end;
done++;
}
- if ((uintptr_t)p == (uintptr_t)pe) {
+ if (p == pe ) {
break;
}
+ pe-=2; /* the last dwords to test are pe[0] and pe[1] */
asm __volatile__ (
"jmp L120\n\t"
".p2align 4,,7\n\t"
+ "L124:\n\t"
+ "addl $8,%%edi\n\t" // Next QWORD
"L120:\n\t"
+
+ // Compare adjacent DWORDS
"movl (%%edi),%%ecx\n\t"
"cmpl 4(%%edi),%%ecx\n\t"
- "jnz L121\n\t"
+ "jnz L121\n\t" // Print error if they don't match
+ // Loop until end of block
"L122:\n\t"
- "addl $8,%%edi\n\t"
"cmpl %%edx,%%edi\n\t"
- "jb L120\n"
+ "jb L124\n"
"jmp L123\n\t"
"L121:\n\t"
+ // eax not used so we don't need to save it as per cdecl
+ // ecx is used but not restored, however we don't need it's value anymore after this point
"pushl %%edx\n\t"
"pushl 4(%%edi)\n\t"
"pushl %%ecx\n\t"
@@ -1283,79 +1403,104 @@ void block_move(int iter)
: "D" (p), "d" (pe)
: "ecx"
);
- do_tick();
- BAILR
} while (!done);
}
}
/*
- * Test memory for bit fade.
+ * Test memory for bit fade, fill memory with pattern.
*/
-#define STIME 5400
-void bit_fade()
+void bit_fade_fill(ulong p1, int me)
{
- int j;
- volatile ulong *pe;
- volatile ulong bad;
- volatile ulong *start,*end;
-
- test_ticks += (STIME * 2);
- v->pass_ticks += (STIME * 2);
+ int j, done;
+ ulong *p, *pe;
+ ulong *start,*end;
- /* Do -1 and 0 patterns */
- p1 = 0;
- while (1) {
+ /* Display the current pattern */
+ hprint(LINE_PAT, COL_PAT, p1);
- /* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ /* Initialize memory with the initial pattern. */
+ for (j=0; j<segs; j++) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ pe = (ulong *)start;
+ p = start;
+ done = 0;
+ do {
+ do_tick(me);
+ BAILR
- /* Initialize memory with the initial pattern. */
- for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = start;
- p = start;
- for (p=start; p<end; p++) {
+ /* Check for overflow */
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
+ if (pe >= end) {
+ pe = end;
+ done++;
+ }
+ if (p == pe ) {
+ break;
+ }
+ for (; p < pe;) {
*p = p1;
+ p++;
}
- do_tick();
+ p = pe + 1;
+ } while (!done);
+ }
+}
+
+void bit_fade_chk(ulong p1, int me)
+{
+ int j, done;
+ ulong *p, *pe, bad;
+ ulong *start,*end;
+
+ /* Make sure that nothing changed while sleeping */
+ for (j=0; j<segs; j++) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ pe = (ulong *)start;
+ p = start;
+ done = 0;
+ do {
+ do_tick(me);
BAILR
- }
- /* Snooze for 90 minutes */
- sleep (STIME, 0);
- /* Make sure that nothing changed while sleeping */
- for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = start;
- p = start;
- for (p=start; p<end; p++) {
- if ((bad=*p) != p1) {
+ /* Check for overflow */
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
+ if (pe >= end) {
+ pe = end;
+ done++;
+ }
+ if (p == pe ) {
+ break;
+ }
+ for (; p < pe;) {
+ if ((bad=*p) != p1) {
error((ulong*)p, p1, bad);
}
+ p++;
}
- do_tick();
- BAILR
- }
- if (p1 == 0) {
- p1=-1;
- } else {
- break;
- }
+ p = pe + 1;
+ } while (!done);
}
}
-/* Sleep function */
-void sleep(int n, int sms)
+
+/* Sleep for N seconds */
+void sleep(long n, int flag, int me, int sms)
{
- int i, ip;
- ulong sh, sl, l, h, t;
+ ulong sh, sl, l, h, t, ip=0;
- ip = 0;
/* save the starting time */
asm __volatile__(
"rdtsc":"=a" (sl),"=d" (sh));
@@ -1363,6 +1508,7 @@ void sleep(int n, int sms)
/* loop for n seconds */
while (1) {
asm __volatile__(
+ "rep ; nop\n\t"
"rdtsc":"=a" (l),"=d" (h));
asm __volatile__ (
"subl %2,%0\n\t"
@@ -1378,31 +1524,21 @@ void sleep(int n, int sms)
t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
t += (l / v->clks_msec) / 1000;
}
-
+
/* Is the time up? */
if (t >= n) {
break;
}
- /* Display the elapsed time on the screen */
- if (sms == 0) {
-
- i = t % 60;
- dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0);
- dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0);
-
- if (i != ip) {
- check_input();
- ip = i;
- }
+ /* Only display elapsed time if flag is set */
+ if (flag == 0) {
+ continue;
+ }
- 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);
+ if (t != ip) {
+ do_tick(me);
BAILR
+ ip = t;
}
}
}
@@ -1411,6 +1547,7 @@ void sleep(int n, int sms)
void beep(unsigned int frequency)
{
+
unsigned int count = 1193180 / frequency;
// Switch on the speaker
@@ -1424,7 +1561,7 @@ void beep(unsigned int frequency)
outb((count >> 8) & 0xff, 0x42);
// Block for 100 microseconds
- sleep(100, 1);
+ sleep(100, 0, 0, 1);
// Switch off the speaker
outb(inb_p(0x61)&0xFC, 0x61);
diff --git a/test.h b/test.h
index 294c297..862da15 100644
--- a/test.h
+++ b/test.h
@@ -1,11 +1,7 @@
-/* test.h - MemTest-86 Version 3.2
+/* test.h - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
- * ----------------------------------------------------
- * MemTest86+ V2.00 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.canardpc.com - http://www.memtest.org
*/
#ifndef _TEST_H_
@@ -14,10 +10,9 @@
#define E801 0x04
#define E820NR 0x08 /* # entries in E820MAP */
#define E820MAP 0x0c /* our map */
-#define E820MAX 64 /* number of entries in E820MAP */
+#define E820MAX 127 /* number of entries in E820MAP */
#define E820ENTRY_SIZE 20
#define MEMINFO_SIZE (E820MAP + E820MAX * E820ENTRY_SIZE)
-#define MAX_DMI_MEMDEVS 16
#ifndef __ASSEMBLY__
@@ -41,55 +36,65 @@ struct mem_info_t {
};
typedef unsigned long ulong;
-#define SPINSZ 0x2000000
+#define STACKSIZE (8*1024)
+#define MAX_MEM 0x7FF00000 /* 8 TB */
+#define WIN_SZ 0x80000 /* 2 GB */
+#define UNMAP_SZ (0x100000-WIN_SZ) /* Size of umappped first segment */
+
+#define SPINSZ 0x4000000 /* 256 MB */
#define MOD_SZ 20
-#define BAILOUT if (bail) goto skip_test;
+#define BAILOUT if (bail) return(1);
#define BAILR if (bail) return;
-#define NULL 0
-
-#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
#define SCREEN_END_ADR (SCREEN_ADR + 80*25*2)
-#define TITLE_WIDTH 28
-#define LINE_TIME 11
-#define COL_TIME 0
-#define LINE_TST 2
-#define LINE_RANGE 3
-#define LINE_CPU 1
+#define DMI_SEARCH_START 0x0000F000
+#define DMI_SEARCH_LENGTH 0x000F0FFF
+#define MAX_DMI_MEMDEVS 16
+
+#define TITLE_WIDTH 28
+#define LINE_TITLE 0
+#define LINE_TST 3
+#define LINE_RANGE 4
+#define LINE_PAT 5
+#define LINE_TIME 5
+#define LINE_STATUS 8
+#define LINE_INFO 9
+#define LINE_HEADER 12
+#define LINE_SCROLL 14
+#define LINE_SPD 14
+#define LINE_MSG 22
+#define LINE_CPU 7
+#define LINE_RAM 8
+#define LINE_DMI 23
+#define COL_INF1 15
+#define COL_INF2 32
+#define COL_INF3 51
+#define COL_INF4 70
+#define COL_MODE 15
#define COL_MID 30
-#define LINE_PAT 4
#define COL_PAT 41
-#define LINE_INFO 11
-#define COL_CACHE_TOP 13
-#define COL_RESERVED 22
-#define COL_MMAP 29
-#define COL_CACHE 40
-#define COL_ECC 46
-#define COL_TST 51
-#define COL_PASS 56
-#define COL_ERR 63
-#define COL_ECC_ERR 72
-#define LINE_HEADER 13
-#define LINE_SCROLL 15
#define BAR_SIZE (78-COL_MID-9)
-#define LINE_MSG 18
-#define COL_MSG 18
+#define COL_MSG 23
+#define COL_TIME 67
+#define COL_SPEC 41
-#define POP_W 30
+#define POP_W 34
#define POP_H 15
-#define POP_X 16
+#define POP_X 11
#define POP_Y 8
-#define POP2_W 74
-#define POP2_H 21
-#define POP2_X 3
-#define POP2_Y 2
-//#define NULL 0
+#define POP2_W 74
+#define POP2_H 21
+#define POP2_X 3
+#define POP2_Y 2
+
+/* CPU mode types */
+#define CPM_ALL 1
+#define CPM_RROBIN 2
+#define CPM_SEQ 3
/* memspeed operations */
#define MS_COPY 1
@@ -97,19 +102,21 @@ typedef unsigned long ulong;
#define MS_READ 3
#define SZ_MODE_BIOS 1
-#define SZ_MODE_BIOS_RES 2
-#define SZ_MODE_PROBE 3
+#define SZ_MODE_PROBE 2
#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 strncmp(const char *s1, const char *s2, ulong n);
+int strstr(char *str1, char *str2);
+int strlen(char *string);
int query_linuxbios(void);
int query_pcbios(void);
int insertaddress(ulong);
void printpatn(void);
void printpatn(void);
-void itoa(char s[], int n);
+void itoa(char s[], int n);
void reverse(char *p);
void serial_console_setup(char *param);
void serial_echo_init(void);
@@ -117,22 +124,22 @@ void serial_echo_print(const char *s);
void ttyprint(int y, int x, const char *s);
void ttyprintc(int y, int x, char c);
void cprint(int y,int x, const char *s);
-void hprint(int y,int x,ulong val);
+void cplace(int y,int x, const char s);
+void hprint(int y,int x, ulong val);
void hprint2(int y,int x, ulong val, int len);
void hprint3(int y,int x, ulong val, int len);
void xprint(int y,int x,ulong val);
void aprint(int y,int x,ulong page);
void dprint(int y,int x,ulong val,int len, int right);
-void movinv1(int iter, ulong p1, ulong p2);
-void movinvr();
-void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off);
-void modtst(int off, int iter, ulong p1, ulong p2);
+void movinv1(int iter, ulong p1, ulong p2, int cpu);
+void movinvr(int cpu);
+void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off,
+ int cpu);
+void modtst(int off, int iter, ulong p1, ulong p2, int cpu);
void error(ulong* adr, ulong good, ulong bad);
void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad);
void ad_err2(ulong *adr, ulong bad);
-void do_tick(void);
-void rand_seed(int seed1, int seed2);
-ulong rand();
+void do_tick();
void init(void);
struct eregs;
void inter(struct eregs *trap_regs);
@@ -150,16 +157,14 @@ void pop2clear(void);
void get_config(void);
void get_menu(void);
void get_printmode(void);
-void addr_tst1(void);
-void addr_tst2(void);
-void bit_fade(void);
-void sleep(int sec, int sms);
-void beep(unsigned int frequency);
+void addr_tst1(int cpu);
+void addr_tst2(int cpu);
int getnum(ulong val);
-void block_move(int iter);
+void sleep(long sec, int flag, int cpu, int sms);
+void block_move(int iter, int cpu);
void find_ticks(void);
void print_err(ulong *adr, ulong good, ulong bad, ulong xor);
-void print_ecc_err(ulong page, ulong offset, int corrected,
+void print_ecc_err(ulong page, ulong offset, int corrected,
unsigned short syndrome, int channel);
void mem_size(void);
void adj_mem(void);
@@ -177,15 +182,19 @@ void show_spd(void);
int map_page(unsigned long page);
void *mapping(unsigned long page_address);
void *emapping(unsigned long page_address);
+int isdigit(char c);
+ulong memspeed(ulong src, ulong len, int iter);
unsigned long page_of(void *ptr);
-ulong memspeed(ulong src, ulong len, int iter, int type);
ulong correct_tsc(ulong el_org);
+void bit_fade_fill(unsigned long n, int cpu);
+void bit_fade_chk(unsigned long n, int cpu);
+void find_ticks_for_pass(void);
+void beep(unsigned int frequency);
-#define PRINTMODE_SUMMARY 1
-#define PRINTMODE_ADDRESSES 0
+#define PRINTMODE_SUMMARY 0
+#define PRINTMODE_ADDRESSES 1
#define PRINTMODE_PATTERNS 2
#define PRINTMODE_NONE 3
-#define PRINTMODE_DMI 4
#define BADRAM_MAXPATNS 10
@@ -194,50 +203,27 @@ struct pair {
ulong mask;
};
-
static inline void cache_off(void)
{
asm(
"push %eax\n\t"
"movl %cr0,%eax\n\t"
- "orl $0x40000000,%eax\n\t" /* Set CD */
- "movl %eax,%cr0\n\t"
+ "orl $0x40000000,%eax\n\t" /* Set CD */
+ "movl %eax,%cr0\n\t"
"wbinvd\n\t"
"pop %eax\n\t");
}
+
static inline void cache_on(void)
{
asm(
"push %eax\n\t"
"movl %cr0,%eax\n\t"
- "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */
- "movl %eax,%cr0\n\t"
+ "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */
+ "movl %eax,%cr0\n\t"
"pop %eax\n\t");
}
-static inline void reboot(void)
-{
- asm(
- "movl %cr0,%eax\n\t"
- "andl $0x00000011,%eax\n\t"
- "orl $0x60000000,%eax\n\t"
- "movl %eax,%cr0\n\t"
- "movl %eax,%cr3\n\t"
- "movl %cr0,%ebx\n\t"
- "andl $0x60000000,%ebx\n\t"
- "jz f\n\t"
- ".byte 0x0f,0x09\n\t" /* Invalidate and flush cache */
- "f: andb $0x10,%al\n\t"
- "movl %eax,%cr0\n\t"
- "movw $0x0010,%ax\n\t"
- "movw %ax,%ds\n\t"
- "movw %ax,%es\n\t"
- "movw %ax,%fs\n\t"
- "movw %ax,%gs\n\t"
- "movw %ax,%ss\n\t"
- "ljmp $0xffff,$0x0000\n\t");
-}
-
struct mmap {
ulong pbase_addr;
ulong *start;
@@ -250,43 +236,14 @@ struct pmap {
};
struct tseq {
- short cache;
+ short sel;
+ short cpu_sel;
short pat;
short iter;
short errors;
char *msg;
};
-struct cpu_ident {
- char type;
- char model;
- char step;
- char fill;
- long cpuid;
- long capability;
- char vend_id[12];
- unsigned char cache_info[16];
- long pwrcap;
- long ext;
- long feature_flag;
- long dcache0_eax;
- long dcache0_ebx;
- long dcache0_ecx;
- long dcache0_edx;
- long dcache1_eax;
- long dcache1_ebx;
- long dcache1_ecx;
- long dcache1_edx;
- long dcache2_eax;
- long dcache2_ebx;
- long dcache2_ecx;
- long dcache2_edx;
- long dcache3_eax;
- long dcache3_ebx;
- long dcache3_ecx;
- long dcache3_edx;
-};
-
struct xadr {
ulong page;
ulong offset;
@@ -306,31 +263,28 @@ struct err_info {
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+ */
+/* Define common variables accross relocations of memtest86 */
struct vars {
- volatile int test;
int pass;
- unsigned long *eadr;
- unsigned long exor;
int msg_line;
int ecount;
int ecc_ecount;
int msegs;
int testsel;
int scroll_start;
- int rdtsc;
- int pae;
int pass_ticks;
int total_ticks;
int pptr;
int tptr;
- int beepmode;
struct err_info erri;
struct pmap pmap[MAX_MEM_SEGMENTS];
- struct mmap map[MAX_MEM_SEGMENTS];
+ volatile struct mmap map[MAX_MEM_SEGMENTS];
ulong plim_lower;
ulong plim_upper;
ulong clks_msec;
@@ -338,14 +292,16 @@ struct vars {
ulong startl;
ulong snaph;
ulong snapl;
- ulong extclock;
- unsigned long imc_type;
int printmode;
int numpatn;
struct pair patn [BADRAM_MAXPATNS];
ulong test_pages;
ulong selected_pages;
ulong reserved_pages;
+ int check_temp;
+ int fail_safe;
+ int each_sec;
+ int beepmode;
};
#define FIRMWARE_UNKNOWN 0
@@ -358,10 +314,5 @@ extern unsigned char _size, _pages;
extern struct mem_info_t mem_info;
-/* CPU mode types */
-#define CPM_SINGLE 1
-#define CPM_RROBIN 2
-#define CPM_SEQ 3
-
#endif /* __ASSEMBLY__ */
-#endif /* _TEST_H_ */ \ No newline at end of file
+#endif /* _TEST_H_ */
diff --git a/version.number b/version.number
new file mode 100644
index 0000000..6b0b9f8
--- /dev/null
+++ b/version.number
@@ -0,0 +1 @@
+4.99617 - Thu May 3 11:45:57 CEST 2012
diff --git a/vmem.c b/vmem.c
new file mode 100644
index 0000000..413d737
--- /dev/null
+++ b/vmem.c
@@ -0,0 +1,154 @@
+/* vmem.c - MemTest-86
+ *
+ * Virtual memory handling (PAE)
+ *
+ * Released under version 2 of the Gnu Public License.
+ * By Chris Brady
+ */
+#include "stdint.h"
+#include "test.h"
+#include "cpuid.h"
+
+extern struct cpu_ident cpu_id;
+
+static unsigned long mapped_win = 1;
+void paging_off(void)
+{
+ if (!cpu_id.fid.bits.pae)
+ return;
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7FFFFFFF, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ : :
+ : "ax"
+ );
+}
+
+static void paging_on(void *pdp)
+{
+ if (!cpu_id.fid.bits.pae)
+ return;
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pdp)
+ : "ax"
+ );
+}
+
+static void paging_on_lm(void *pml)
+{
+ if (!cpu_id.fid.bits.pae)
+ return;
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pml)
+ : "ax"
+ );
+}
+
+int map_page(unsigned long page)
+{
+ unsigned long i;
+ struct pde {
+ unsigned long addr_lo;
+ unsigned long addr_hi;
+ };
+ extern unsigned char pdp[];
+ extern unsigned char pml4[];
+ extern struct pde pd2[];
+ unsigned long win = page >> 19;
+
+ /* Less than 2 GB so no mapping is required */
+ if (win == 0) {
+ return 0;
+ }
+ if (cpu_id.fid.bits.pae == 0) {
+ /* Fail, we don't have PAE */
+ return -1;
+ }
+ if (cpu_id.fid.bits.lm == 0 && (page > 0x1000000)) {
+ /* Fail, we want an address that is out of bounds (> 64GB)
+ * for PAE and no long mode (ie. 32 bit CPU).
+ */
+ return -1;
+ }
+ /* Compute the page table entries... */
+ for(i = 0; i < 1024; i++) {
+ /*-----------------10/30/2004 12:37PM---------------
+ * 0xE3 --
+ * Bit 0 = Present bit. 1 = PDE is present
+ * Bit 1 = Read/Write. 1 = memory is writable
+ * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2)
+ * Bit 3 = Writethrough. 0 = writeback cache policy
+ * Bit 4 = Cache Disable. 0 = page level cache enabled
+ * Bit 5 = Accessed. 1 = memory has been accessed.
+ * Bit 6 = Dirty. 1 = memory has been written to.
+ * Bit 7 = Page Size. 1 = page size is 2 MBytes
+ * --------------------------------------------------*/
+ pd2[i].addr_lo = ((win & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3;
+ pd2[i].addr_hi = (win >> 1);
+ }
+ paging_off();
+ if (cpu_id.fid.bits.lm == 1) {
+ paging_on_lm(pml4);
+ } else {
+ paging_on(pdp);
+ }
+ mapped_win = win;
+ return 0;
+}
+
+void *mapping(unsigned long page_addr)
+{
+ void *result;
+ if (page_addr < 0x80000) {
+ /* If the address is less than 1GB directly use the address */
+ result = (void *)(page_addr << 12);
+ }
+ else {
+ unsigned long alias;
+ alias = page_addr & 0x7FFFF;
+ alias += 0x80000;
+ result = (void *)(alias << 12);
+ }
+ return result;
+}
+
+void *emapping(unsigned long page_addr)
+{
+ void *result;
+ result = mapping(page_addr -1);
+ /* Fill in the low address bits */
+ result = ((unsigned char *)result) + 0xffc;
+ return result;
+}
+
+unsigned long page_of(void *addr)
+{
+ unsigned long page;
+ page = ((unsigned long)addr) >> 12;
+ if (page >= 0x80000) {
+ page &= 0x7FFFF;
+ page += mapped_win << 19;
+ }
+#if 0
+ cprint(LINE_SCROLL -2, 0, "page_of( )-> ");
+ hprint(LINE_SCROLL -2, 8, ((unsigned long)addr));
+ hprint(LINE_SCROLL -2, 20, page);
+#endif
+ return page;
+}