memtest86+-4.20/0000755000000000000000000000000011517067616012056 5ustar rootrootmemtest86+-4.20/linuxbios_tables.h0000644000000000000000000000511011517067470015570 0ustar rootroot#ifndef LINUXBIOS_TABLES_H #define LINUXBIOS_TABLES_H #include "stdint.h" /* The linuxbios table information is for conveying information * from the firmware to the loaded OS image. Primarily this * is expected to be information that cannot be discovered by * other means, such as quering the hardware directly. * * All of the information should be Position Independent Data. * That is it should be safe to relocated any of the information * without it's meaning/correctnes changing. For table that * can reasonably be used on multiple architectures the data * size should be fixed. This should ease the transition between * 32 bit and 64 bit architectures etc. * * The completeness test for the information in this table is: * - Can all of the hardware be detected? * - Are the per motherboard constants available? * - Is there enough to allow a kernel to run that was written before * a particular motherboard is constructed? (Assuming the kernel * has drivers for all of the hardware but it does not have * assumptions on how the hardware is connected together). * * With this test it should be straight forward to determine if a * table entry is required or not. This should remove much of the * long term compatibility burden as table entries which are * irrelevant or have been replaced by better alternatives may be * dropped. Of course it is polite and expidite to include extra * table entries and be backwards compatible, but it is not required. */ struct lb_header { uint8_t signature[4]; /* LBIO */ uint32_t header_bytes; uint32_t header_checksum; uint32_t table_bytes; uint32_t table_checksum; uint32_t table_entries; }; /* Every entry in the boot enviroment list will correspond to a boot * info record. Encoding both type and size. The type is obviously * so you can tell what it is. The size allows you to skip that * boot enviroment record if you don't know what it easy. This allows * forward compatibility with records not yet defined. */ struct lb_record { uint32_t tag; /* tag ID */ uint32_t size; /* size of record (in bytes) */ }; #define LB_TAG_UNUSED 0x0000 #define LB_TAG_MEMORY 0x0001 #define LB_TAG_FORWARD 0x0011 struct lb_memory_range { uint64_t start; uint64_t size; uint32_t type; #define LB_MEM_RAM 1 #define LB_MEM_RESERVED 2 }; struct lb_memory { uint32_t tag; uint32_t size; struct lb_memory_range map[0]; }; #define LB_TAG_HWRPB 0x0002 struct lb_hwrpb { uint32_t tag; uint32_t size; uint64_t hwrpb; }; struct lb_forward { uint32_t tag; uint32_t size; uint64_t forward; }; #endif /* LINUXBIOS_TABLES_H */ memtest86+-4.20/msr.h0000644000000000000000000000653611517067470013040 0ustar rootroot#ifndef __ASM_MSR_H #define __ASM_MSR_H /* * Access to machine-specific registers (available on 586 and better only) * Note: the rd* operations modify the parameters directly (without using * pointer indirection), this allows gcc to optimize better */ #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \ : "c" (msr)) #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : /* no outputs */ \ : "c" (msr), "a" (val1), "d" (val2)) #define rdtsc(low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) #define rdtscl(low) \ __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) #define write_tsc(val1,val2) wrmsr(0x10, val1, val2) #define rdpmc(counter,low,high) \ __asm__ __volatile__("rdpmc" \ : "=a" (low), "=d" (high) \ : "c" (counter)) /* symbolic names for some interesting MSRs */ /* Intel defined MSRs. */ #define MSR_IA32_P5_MC_ADDR 0 #define MSR_IA32_P5_MC_TYPE 1 #define MSR_IA32_PLATFORM_ID 0x17 #define MSR_IA32_EBL_CR_POWERON 0x2a #define MSR_IA32_APICBASE 0x1b #define MSR_IA32_APICBASE_BSP (1<<8) #define MSR_IA32_APICBASE_ENABLE (1<<11) #define MSR_IA32_APICBASE_BASE (0xfffff<<12) #define MSR_IA32_UCODE_WRITE 0x79 #define MSR_IA32_UCODE_REV 0x8b #define MSR_IA32_BBL_CR_CTL 0x119 #define MSR_IA32_MCG_CAP 0x179 #define MSR_IA32_MCG_STATUS 0x17a #define MSR_IA32_MCG_CTL 0x17b #define MSR_IA32_THERM_CONTROL 0x19a #define MSR_IA32_THERM_INTERRUPT 0x19b #define MSR_IA32_THERM_STATUS 0x19c #define MSR_IA32_MISC_ENABLE 0x1a0 #define MSR_IA32_DEBUGCTLMSR 0x1d9 #define MSR_IA32_LASTBRANCHFROMIP 0x1db #define MSR_IA32_LASTBRANCHTOIP 0x1dc #define MSR_IA32_LASTINTFROMIP 0x1dd #define MSR_IA32_LASTINTTOIP 0x1de #define MSR_IA32_MC0_CTL 0x400 #define MSR_IA32_MC0_STATUS 0x401 #define MSR_IA32_MC0_ADDR 0x402 #define MSR_IA32_MC0_MISC 0x403 #define MSR_P6_PERFCTR0 0xc1 #define MSR_P6_PERFCTR1 0xc2 #define MSR_P6_EVNTSEL0 0x186 #define MSR_P6_EVNTSEL1 0x187 #define MSR_IA32_PERF_STATUS 0x198 #define MSR_IA32_PERF_CTL 0x199 /* AMD Defined MSRs */ #define MSR_K6_EFER 0xC0000080 #define MSR_K6_STAR 0xC0000081 #define MSR_K6_WHCR 0xC0000082 #define MSR_K6_UWCCR 0xC0000085 #define MSR_K6_EPMR 0xC0000086 #define MSR_K6_PSOR 0xC0000087 #define MSR_K6_PFIR 0xC0000088 #define MSR_K7_EVNTSEL0 0xC0010000 #define MSR_K7_PERFCTR0 0xC0010004 #define MSR_K7_HWCR 0xC0010015 #define MSR_K7_CLK_CTL 0xC001001b #define MSR_K7_FID_VID_CTL 0xC0010041 #define MSR_K7_VID_STATUS 0xC0010042 /* Centaur-Hauls/IDT defined MSRs. */ #define MSR_IDT_FCR1 0x107 #define MSR_IDT_FCR2 0x108 #define MSR_IDT_FCR3 0x109 #define MSR_IDT_FCR4 0x10a #define MSR_IDT_MCR0 0x110 #define MSR_IDT_MCR1 0x111 #define MSR_IDT_MCR2 0x112 #define MSR_IDT_MCR3 0x113 #define MSR_IDT_MCR4 0x114 #define MSR_IDT_MCR5 0x115 #define MSR_IDT_MCR6 0x116 #define MSR_IDT_MCR7 0x117 #define MSR_IDT_MCR_CTRL 0x120 /* VIA Cyrix defined MSRs*/ #define MSR_VIA_FCR 0x1107 #define MSR_VIA_LONGHAUL 0x110a #define MSR_VIA_BCR2 0x1147 /* Transmeta defined MSRs */ #define MSR_TMTA_LONGRUN_CTRL 0x80868010 #define MSR_TMTA_LONGRUN_FLAGS 0x80868011 #define MSR_TMTA_LRTI_READOUT 0x80868018 #define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a #endif /* __ASM_MSR_H */ memtest86+-4.20/changelog0000644000000000000000000000044411517067470013730 0ustar rootrootMemtest86+ V4.20 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 fixesmemtest86+-4.20/pci.c0000644000000000000000000001040311517067470012771 0ustar rootroot/* pci.c - MemTest-86 Version 3.2 * * 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.x86-secret.com - http://www.memtest.org */ #include "io.h" #include "pci.h" #include "test.h" #define PCI_CONF_TYPE_NONE 0 #define PCI_CONF_TYPE_1 1 #define PCI_CONF_TYPE_2 2 extern struct cpu_ident cpu_id; static unsigned char pci_conf_type = PCI_CONF_TYPE_NONE; #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) #define PCI_CONF2_ADDRESS(dev, reg) (unsigned short)(0xC000 | (dev << 8) | reg) #define PCI_CONF3_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (((reg >> 8) & 0xF) << 24) | (bus << 16) | ((dev & 0x1F) << 11) | (fn << 8) | (reg & 0xFF)) int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value) { int result; 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: 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: *value = inb(0xCFC + (reg & 3)); result = 0; break; case 2: *value = inw(0xCFC + (reg & 2)); result = 0; break; case 4: *value = inl(0xCFC); result = 0; break; } break; case PCI_CONF_TYPE_2: outb(0xF0 | (fn << 1), 0xCF8); outb(bus, 0xCFA); switch(len) { case 1: *value = inb(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; case 2: *value = inw(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; case 4: *value = inl(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break; } outb(0, 0xCF8); break; } return result; } int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long value) { int result; if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 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; } return result; } static int pci_sanity_check(void) { unsigned long value; int result; /* Do a trivial check to make certain we can see a host bridge. * There are reportedly some buggy chipsets from intel and * compaq where this test does not work, I will worry about * that when we support them. */ result = pci_conf_read(0, 0, 0, PCI_CLASS_DEVICE, 2, &value); if (result == 0) { result = -1; if (value == PCI_CLASS_BRIDGE_HOST) { result = 0; } } return result; } static int pci_check_direct(void) { unsigned char tmpCFB; unsigned int tmpCF8; if (cpu_id.vend_id[0] == 'A' && cpu_id.type == 15) { pci_conf_type = PCI_CONF_TYPE_1; return 0; } else { /* Check if configuration type 1 works. */ pci_conf_type = PCI_CONF_TYPE_1; tmpCFB = inb(0xCFB); outb(0x01, 0xCFB); tmpCF8 = inl(0xCF8); outl(0x80000000, 0xCF8); if ((inl(0xCF8) == 0x80000000) && (pci_sanity_check() == 0)) { outl(tmpCF8, 0xCF8); outb(tmpCFB, 0xCFB); return 0; } outl(tmpCF8, 0xCF8); /* Check if configuration type 2 works. */ pci_conf_type = PCI_CONF_TYPE_2; outb(0x00, 0xCFB); outb(0x00, 0xCF8); outb(0x00, 0xCFA); if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && (pci_sanity_check() == 0)) { outb(tmpCFB, 0xCFB); return 0; } outb(tmpCFB, 0xCFB); /* Nothing worked return an error */ pci_conf_type = PCI_CONF_TYPE_NONE; return -1; } } int pci_init(void) { int result; /* For now just make certain we can directly * use the pci functions. */ result = pci_check_direct(); return result; } memtest86+-4.20/screen_buffer.c0000644000000000000000000000456111517067470015036 0ustar rootroot/* --*- C -*-- * * By Jani Averbach, Jaa@iki.fi, 2001 * * 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) * */ #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, * so that there is room for ending '\0' */ #define X_SIZE SCREEN_X+1 static char screen_buf[Y_SIZE][X_SIZE]; #ifdef SCRN_DEBUG char *padding = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; #define CHECK_BOUNDS(y,x) do {if (y < 0 || Y_SIZE <= y || x < 0 || X_SIZE <= x) print_error("out of index");}while(0) #else /* ! SCRN_DEBUG */ #define CHECK_BOUNDS(y,x) #endif /* SCRN_DEBUG */ char get_scrn_buf(const int y, const int x) { CHECK_BOUNDS(y,x); return screen_buf[y][x]; } void set_scrn_buf(const int y, const int x, const char 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'; } } void tty_print_region(const int pi_top, const int pi_left, const int pi_bottom, const int pi_right) { int y; char tmp; 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'; CHECK_BOUNDS(y, pi_left); ttyprint(y, pi_left, &(screen_buf[y][pi_left])); screen_buf[y][pi_right] = tmp; } } void tty_print_line( int y, int x, const char *text) { for(; *text && (x < SCREEN_X); x++, text++) { if (*text != screen_buf[y][x]) { break; } } /* If there is nothing to do return */ if (*text == '\0') { return; } ttyprint(y, x, text); for(; *text && (x < SCREEN_X); x++, text++) { screen_buf[y][x] = *text; } } void tty_print_screen(void) { #ifdef SCRN_DEBUG int i; for (i=0; i < SCREEN_Y; ++i) ttyprint(i,0, padding); #endif /* SCRN_DEBUG */ tty_print_region(0, 0, SCREEN_Y, SCREEN_X); } void print_error(char *pstr) { #ifdef SCRN_DEBUG ttyprint(0,0, padding); #endif /* SCRN_DEBUG */ ttyprint(0,35, pstr); while(1); } memtest86+-4.20/serial.h0000644000000000000000000001416511517067470013513 0ustar rootroot/* * include/linux/serial.h * * Copyright (C) 1992, 1994 by Theodore Ts'o. * * Redistribution of this file is permitted under the terms of the GNU * Public License (GPL) * * These are the UART port assignments, expressed as offsets from the base * register. These assignments should hold for any serial port based on * a 8250, 16450, or 16550(A). */ #ifndef _LINUX_SERIAL_REG_H #define _LINUX_SERIAL_REG_H #define UART_RX 0 /* In: Receive buffer (DLAB=0) */ #define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ #define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ #define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ #define UART_IER 1 /* Out: Interrupt Enable Register */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_EFR 2 /* I/O: Extended Features Register */ /* (DLAB=1, 16C660 only) */ #define UART_LCR 3 /* Out: Line Control Register */ #define UART_MCR 4 /* Out: Modem Control Register */ #define UART_LSR 5 /* In: Line Status Register */ #define UART_MSR 6 /* In: Modem Status Register */ #define UART_SCR 7 /* I/O: Scratch Register */ /* * These are the definitions for the FIFO Control Register * (16650 only) */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ #define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ #define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ #define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ /* 16650 redefinitions */ #define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ #define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ #define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ #define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ #define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ #define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ #define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ #define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ /* * These are the definitions for the Line Control Register * * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. */ #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ #define UART_LCR_SBC 0x40 /* Set break control */ #define UART_LCR_SPAR 0x20 /* Stick parity (?) */ #define UART_LCR_EPAR 0x10 /* Even parity select */ #define UART_LCR_PARITY 0x08 /* Parity Enable */ #define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ #define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ #define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ #define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ #define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ /* * These are the definitions for the Line Status Register */ #define UART_LSR_TEMT 0x40 /* Transmitter empty */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ #define UART_LSR_BI 0x10 /* Break interrupt indicator */ #define UART_LSR_FE 0x08 /* Frame error indicator */ #define UART_LSR_PE 0x04 /* Parity error indicator */ #define UART_LSR_OE 0x02 /* Overrun error indicator */ #define UART_LSR_DR 0x01 /* Receiver data ready */ /* * These are the definitions for the Interrupt Identification Register */ #define UART_IIR_NO_INT 0x01 /* No interrupts pending */ #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ #define UART_IIR_MSI 0x00 /* Modem status interrupt */ #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ /* * These are the definitions for the Interrupt Enable Register */ #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ /* * These are the definitions for the Modem Control Register */ #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ #define UART_MCR_OUT2 0x08 /* Out2 complement */ #define UART_MCR_OUT1 0x04 /* Out1 complement */ #define UART_MCR_RTS 0x02 /* RTS complement */ #define UART_MCR_DTR 0x01 /* DTR complement */ /* * These are the definitions for the Modem Status Register */ #define UART_MSR_DCD 0x80 /* Data Carrier Detect */ #define UART_MSR_RI 0x40 /* Ring Indicator */ #define UART_MSR_DSR 0x20 /* Data Set Ready */ #define UART_MSR_CTS 0x10 /* Clear to Send */ #define UART_MSR_DDCD 0x08 /* Delta DCD */ #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ #define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ /* * These are the definitions for the Extended Features Register * (StarTech 16C660 only, when DLAB=1) */ #define UART_EFR_CTS 0x80 /* CTS flow control */ #define UART_EFR_RTS 0x40 /* RTS flow control */ #define UART_EFR_SCD 0x20 /* Special character detect */ #define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ /* * the low four bits control software flow control */ #include "io.h" #define serial_echo_outb(v,a) outb((v),(a)+serial_base_ports[serial_tty]) #define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty]) #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* Wait for transmitter & holding register to empty */ #define WAIT_FOR_XMITR \ do { \ lsr = serial_echo_inb(UART_LSR); \ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) #if 0 static inline void serial_echo(int ch) { int lsr; WAIT_FOR_XMITR; serial_echo_outb(ch, UART_TX); } static inline void serial_debug(int ch) { serial_echo(ch); serial_echo('\r'); serial_echo('\n'); } #endif #endif /* _LINUX_SERIAL_REG_H */ memtest86+-4.20/precomp.bin0000755000000000000000000050123011517067470014217 0ustar rootrootظ))Ⱥ?؎Љjxd7׹eEd?dGȎ001ҹsP/4X001ҹ s s .0   u1ی-;v.+ s t1) 4.;u+u1 s1``.aAՋցRQSPraP 00 aQ:sE(X:Yø  ùV$0<9vR0Zô  Loading'UpET$)T$4D$4Ef+L$HMTt&D$HD$L$4D$EE빋D$+D$EEL$D|$pD$X@D$,D$h@D$(;t$,L$DD$0͋FЃtetS|$(NjGD$ fuPD$8D$w$@D$8D$ E&'9t$,w+L$HMD$HD$L$8벋T$8T$ T$$Ot11ҍt&D$$DA;Or뫋D$HuVD$ +D$0EEL$DT$HT$8T$)T$8D$8)ȉEsT$Hu#D$ EET$)T$8D$8EME뷋E␐WVS[8kljы@u`RTffЍIf| v1t&[^_Ív'fD%`t&'RT뫍<뵐t&D륐t&<B뎍&'Po PN&'-'& 'Bt&<t&<t&UWVS [ôitL$9sT$xT$9vD$L$9L$P1E9hPtHxD$9sЋ|$9v9s9D$v9|$s14v4t P!x1<$!4v|E9hi' [^_]1 [^_]ÍUWVS [dhE811|D$fy~6T$ |L&+Bƃ 9uG!ut'&ǃt'E0E D$f1G t L$x9|$ulE0G u [^_]Ít&'WVS[ÈgNjP)PVWFl) WVS[Hg)9v7:9w 4 9v6|[^_bfs49w狃9wʍ:9vԸ :Ȑ&Yf@@@@ &' = u 'UWVS[Df}uf= ?^;`g>u` t+#q/+ E|p  t'2+4 L$t&'  j1Rt'@t' v ǃt'RD$ Pj)jsLt'9 W)+ @9Dpsȃ[^_]Ut& T jzQPǃt' Pj&jKEE xfE@E jjPj8j WEE4E8Pj&jvKEuE yPPjjTK [^_]o ǃ tQ @ tRax=$PPj:jJXxPXD@|Psǃ Vj'jDY Pj,jqJ Wj/j$Y Wj5jYE xEuiE@Dx'E jjPj$jVE@LQj'jIE@$uO|1ɍ@|+B 9uȋUXE<RPj&jqIE@f| dfD%f" % < u'F< tvt3PjWVR@u _'Ft< uF> tuE.E@Tffx'Džx V^D뚋E@E~x'tD$xHT$ l1&ЋL$ PRjV%uT$ ҉PRjVmFuD$D$9x't&x'1xHD$ &'F9x'ҋL$ QRPjtx'a1fF9x'Nq9tt'u  x'P dJ0D$D$xHT$ L$  ‰1'ЋL$ PRx'PV@T$ ҉PRx'QVFuD$D$(|$ax1HD$ ЋL$ PRx'PV T$ ҉PRx'PVz Fulx1LVjhjPx'Q  FVjhjPx'P tOT$1xHL$ D$  ЉҋL$ QRPx'PT$ ҉QPRx'PSFD$(y/xHPjjx'Pe҉QPRx'W091 PUWVS<1T$0D$4D$,1+D$4T$0ӉD$8|$T;|t1؋D$811؉1ËD$811;\$P|$Tu<1׃ jj ЙRj j NjjVjj N ;|$,tG<1D$1ƃ jj ЙRjj NjjSjj NjjVjj N|$L =<[^_]Ã41t$a怃a怰C怈BBjjda%aUWVS@t$Xj)jI-;D$$D$(x|ܞD$dD$T$ T$TT$ T$ ;T$ vT$ t$ D$9t$ r t$ D$=ܞ;|$ tPT$ \$L$ &Ã9rL$ \$=ܞM=?|$pD$ D$;3D$x|ܞL$dL$T$ \$T\$4T$ ;T$ vT$ t$ D$,9t$ r t$ D$,=ܞ;|$ tlT$ \$L$4U/9uщу9rVPSRUQW _Y]Z[X^؀]L$4\$=ܞW=I|$,TD$$ 9D$$L$\$XI\$8L$HD$(k ;xuED$ ܞT$ sT$ t$ D$09t$ w t$ D$0=ܞ;|$ tuT$ \$L$8U&/9uщ9wVPSRUQW _Y]Z[X^݀]L$8\$=ܞH=u>|$0OL$( |$(+D$D$P9D$}-;D$$<[^_]UWVS@t$Xj)jF-;D$$~x|ܞÍ9vD$9r D$=ܞ)D$89t)L$8D$T=ܞo=|$tD$ T$;rD$x|ܞT$ T$ ;T$ vT$ t$ D$$9t$ r t$ D$$=ܞ;|$ tVD$TT$ \$Xv9u 9rRSQPW _XY[Z=ܞ=|$$jD$ 9D$>HD$ k ;xuED$ ܞT$ sT$ t$ D$(9t$ w t$ D$(=ܞ;|$ tUD$TT$ \$X9u 9uRPQSW._[YXZ=ܞ=u>|$(oL$ |$ KD$D$P9D$}-;D$<[^_]UWVSl0*-;E00*R5j)jD18|x 9rܞ =F;5|PPjhL1ۃ\x|ܞ-D$D$ 9tD$PQRܞܞ9r =u!C;|=u[^_]UWVS@h2Dj'jL;;D$(1xD$,D$,=wD$,|D$(D$,D$4D$,D$8D$4T$49v D$4D$(D$4T$4D$(19r D$(D$4T$8D$49tqL$4D$8)|$8҉GGG WWGGG G$W(W,G0G4W8W<Ѝ@Iuʼn|$8Y=?DE ;-T$T$ D$T$ xD$,D$,=wD$,T$ |D$(D$,D$4D$,D$8D$4T$49v D$4D$(D$4T$4D$(D$9rD$(D$4D$T$8D$49t}L$8D$4T$8)ȉD$0\$4D$8)1=T$8D$0lj։׃ Ɖك׹6=E;l$P|D$4D$8|$/D$D$ D$;1T$xD$,D$,=wD$,T$|D$(D$,D$4D$,D$8D$4T$49v D$4D$(D$4T$4D$(19r D$(D$4T$8D$49tF|$8T$4;Ou 9rRwQW_Z|$80=uoFD$ ;5<[^_]UWVS@D$TD$T$XT$L$\L$\$`\$ Qj'j? h(Uj/j7$jt$(j0jCD$4D$8;T$XD$< x|L$ ܞӍ9vD$(9r D$(=ܞ9t4ڋD$ t&P9r=ܞ=|$(tD$ L$; kD$$x|ܞT$D$ T$;T$vT$t$D$09t$r t$D$0=ܞ;|$tR\$ T$D$L$t&9tC~1ۃ9r\$ =ܞL=|$0nD$, D$,;9D$$T$9T$$|1l$8D$,͋L$8x|\$ܞӍ9vD$49r D$4=ܞ9tEڋD$ t&9u P9rRQPW_XYZ=ܞw=u=|$4tED$8 ;-[D$X2DD$T)D$P<[^_]15<[^_]UWVS h4Dj)j5;D$(D${x|ܞӍ9vD$9r D$=ܞ9t0t&?9r=ܞ=|$tD$ D$ ;u1D$x|ܞӍ9vD$9r D$=ܞ9t;9u 9r RQW_YZ=ܞ=u|$tED$ ;-k[^_]UWVS,;x(t 1T$D$;B;T$D$U)D$Wt$j)jB;[^t$t$;D$8D$T$(x|-ܞ덃9vD$ 9r D$ 9t5=ܞ+9r=ܞ="|$ tD$D$( D$;pD$QQt$t$S;T$(D$,D$xD$$T$|ܞƍ9vD$ 9r D$ 9t$$t^|$Ӌ=ܞX1؋9u1Љ9rVQPWe_XY^߉=ܞ=u3|$ vD$D$ D$;>D$|$,[^_]UWVS1P5j)j]9;x%ܞHk ;|1 ܞ 9t)9v+9tPRSQEۅuFc~ =RGH;B |%D$D$HD$ ЉD$U5j)jd8-;D$$D$ x#D$ܞ|~1 ܞ 9t)9s+9tPRSQPۅuF~ܞL$9vܞ=ܞܞ9tD$ D$;B=uD$|$[^_]ÐYH@,tǁ %" $"Í&UWVS [Gt$ ;tu 1 [^_]ËD$H,uރwD$l$ 1ɋPt&%D$:l:Au&t(D$P,t" " "1TD$=v% Í& ÍS[FD$HP[Ít&'YFD$ =vÐVS[fFt$(22P$@dx02P$@E@tCڀE@tC1RV,$|$fD$ fD$l$|$l$D$ &؉[^Ít&2P$@?؃dx09*2P$?f؃2t&UWVS [$El$$l$ D$$D$1`D$(~%1&'t$ @9D$(1`+h<|$,~|$,|$,\`+Uh<+U|$,o1t$$ 1t$(p8K|16 [^_]Ð&t$ L$1`D$(~1&t$ L$@9D$(1\t&1 [^_]Ít$ L$1`l$(~1Ґ&t$ L$B9T$(1\1`D$(~1ҍt&L$B9T$(1\Yt& QNt&UWVS [äBPjj *1T$$D$((v1+D$T$щD$1|ȋD$1|9D$0v:(;D$4uPPjj),[^_]ÍUWVS[Aj.(S$&e$z&m4$l&x<$^&4$V& &' @= uft&' =9 uQ}Pjj(  Pjj( 'q= u W%f>uf8vWq`(EEEEE EE$EDEHELEPfE\ fE^E`ElETfEpEXPtPffB uf8t(,P@8~9uVPjj\' PjjI' Pjj6' Pjj#' Qj j5 Pjj&E(E,dPdA@dF 0f 1P9sVǍ,F P1t: Puǃ PPɃ9r&'L$$tD$$0 [^_]Ð&g>0^ FPq&'~ FP@tN(fu[^_]Ð&1҈‰Ѓ``uU Ґt&WVS[Øƃ'ƃ'D$@P'WXZD$@P'V$ 4$$<$*$XD$$P[^_Í&'S[duf8u1҉Ѓ[Ðt&`1҈‰Ѓ[Ív(f PQtlj% PƒÍ'VS[v'[xf>tY[^Í'UWVS [4(f Pjjk D$$@Pjj PjjD T$$BPjj Pjj D$$@Pjj Pjj T$$jUjj Pjj D$$x Wjj{ Pjj T$$rVjjT &Pjj D$$HQjj- .PjjZ T$$Rjj 6Pj&j41v'PT$$BPj&W T$$B(Pj/Wu0 T$$BPj9W T$$B0PjBWG0uP`PjjD$0x0'j1PVjqG&u0+RPjjX Vjj yvPRjjD$(HQPRY[^_] ''UWVS[t l$8|$<ɚ; D$v'T$D$A9uD$@1D$T$ =t&1t$ -T$D$G9}Od$T$D$uD$G9D$ 00F D$9|T$ 2UR|$uD$ &D$@D$1t&/ /` VL$Q PVT$RuŠ|$t D$D$1&Ƅ6` Pj VjFPujOjjj' [^_]@B [^_]UWV|$t$L$l$$!!!! #D$E D$ #M^_]ÍvL$JuuÐWVS[Et$0VXZD$PD$PD$LJtGDpxt& 9 j6&' 9' j&';PPjj Pjj tPjj d Pjj j jj@;xtPVjjYPPjj @.VPjj 'UWVS[Äljը1D$f%ƁvJuT$Wu։%[^_]ÍvfD$RjPD$&P;fD$*%ƃv븍fD$QjPD$&PfD$*ƁMGEt&UWVS [äT$9xƍ$9t$PjD$PVuك~uӺuËV ;FuF DD$9sQWtJ9D$rA1Pt9D$rA;D$r9Ft9t$sv1 [^_]1UWVS[1…&rz B D9N9s(t&9J9>u܋VT$@h 1D$t&@tDGWD$T$ AGW EUD$T$ EU MD$F9t$D$B[^_]Í&[^_]ÍvVt!r…1ɐS[Z xЉH31Ɉ0f%u1҉[f1҈‰[fUWVSl[D$ H1$h/D$$T$ ,t&//7T7L$$AQ D7T7 AD79uɋ$h$lƉ$p$t9r4$|1E9l$ QƉqy 9//9+R*Pjj lBtBxǂB|Bl[^_]Ð&T9qGL$ ɉL$X~0T$h1$ht$&'|$@ ;D$X|D$ ~K$h1$hl$vT$NPH0l$DVN PH0G9|$ ̃|$X?$ht$$l|$l$Xl$ L$D$@D$D$ D$%w9T$,r013T$, ;L$t/9GD$,oqVF9sȉ1yD$@;L$uыD$@uD$D1D$TD$4D$`D$d$h'T$DL$PHT$HL$LT$L3QD$H3 .~1B9~;LuhDB9ꐍt&p11t&D@9sB9|t$\;t$TD$Tt:D$HT$L+D$`T$dL$4 p t tD$4|$4?T$4h T$HL$LHpD$DT$X9T$DL$\L$TD$HT$LD$`T$d&3P3D$, A3h1T$, l$,,1yD$@It&D$`T$dD$HT$Lt$\D$DT$X9T$DtD$4H?[t$4L$()$h D$0t$4D$ t&t8;L$Au݋QƉqy t$8|$<Ɖׁw  ƋD$8T$<=D$0tT)D$0;L$aT$(L$0HP1Pjj l[^_]Éh~1D$\'|$<w|$8:D$8T$< LAQ  Q#Pjj A9k~D$X$hL$fD$> fD$D$0ƃ jjPQjD$P@Pj D$1RP,$؃ |$2fD$2 fD$0l$0|$$l$2D$$jjPPj褤D$P@Pj葘 D$1RP,$؃ |$2fD$2 fD$0l$0|$$l$2D$$jjPQj:T$R@Pj' t$ jjVPj wTP[P@PjߗQt D$ugPPBPj贗<[^_]É'멍t&'p&&y&PPAPjM<[^_]fUWVSD[ôD$fD$> fD$D$0ƃ jjPQjCD$P@Pj* t$ jjVPjD$P@Pj t$  jjVQjT$R@Pj讕 t$  jjVPj胡 wKP[P@PjfQt D$u^PPBPj;<[^_]Ã벍t&'y&+&&PPAPjݔ<[^_]fUWVS$[DD$ PjjDjjjD$PjjjjjD$8%D$8T$(  PP@PjG JP@Pj,P HQAPRj jjPRj؟V@PjÓ$jPRj袟V@Pj蓓|$' jjVPjc wkP[P@PjFPD$POPRj,[^_]Ít&'PKt&뒍t&'`vPP@Pj跒 JP@Pj蜒P thtszPh&'P8t&VSPRj@;t&Pt&PUt&PXt&WVS([uD$$PjhjjjD$ PjhjjjD$PjhjjjD$Pjj@jjjD$PjjDjjjD$PjjHjjj~JP@PjCP D$(f}4 jjD$0PPjV@Pj$jD$0PRjÜV@Pj贐T$,  jjRPj臜 P[P@PjoHT$D$Ѓt0D$Ѓt"ROPQj2 [^_Ðt&V5PQj [^_Ív jjRPj ct&PSPRjЏt&PAPRj谏t&PKލ&WVS[|$,PQjc  T$(RPjL$j|$"fD$" fD$ D$4l$ |$l$"D$PQjBPRj WPj?tBBuكD$ Eta jjD$4|$"fD$" fD$ l$ |$l$"D$PQjy RPPja [^_Ð& jjD$4|$"fD$" fD$ l$ |$l$"D$P>Wj UWVS[Ä|tsD$ Pjhjjj D$ t*t5CV.P3PR,[^_]Ív@Dى'&Dɉ'UPjjoD$0L$2׉ƃ %P= PUj;Ɖ$= PEPj%$}= PEPj4$c= PEPj%$E= PEPjƌʼn$)= PEPj誌%$= PEPj艌<$< PEPjoD$|$5WPj)jFK&'UWVS[ä|D$ PjhjjjD$8 Pd@, 4q2׃D$PjhjjjD$4 @a?D$?t ;D$T$ҍB%'Edf19r1RW,$س؃P:P3P\$D$$b,[^_]Ív' @Pd@,1RP,$س؃y'PPjjoD$0 L$2׉ƃ %P: PUj,Ɖ$: PEPj%$n: PEPj4$T: PEPjՉ%$6: PEPj跉ʼn$: PEPj蛉%$9 PEPjz<$9 PEPj`D$|$5PPj)j7 D$v=&D$q&Q'VS4[&dF(B2?1RP,$؃\$D$t؃F,D$4Pjhjjj\$ L D$,$|$fD$ fD$l$\$l$D$P$P:P3PMb$1RP,$$"D[^Í2? D$4Pjhjjj\$ 肽 D$,$&E'؋؋ ؋(س,؃$''؋؋؃$'؋س؃$'؋س ؃$i'؋سO ؋س / S[ç2tjلـE@uR:P^PMb$1RP,$\$D$$[É'ل딍&VS4[21RP,$كEuع2%1RP,$Mb$1RP,$\$|P>P@Pj $j|$.fD$. fD$,D$l$,|$$l$.D$$PQj蹐BPRj蝄Y^D$4PjjHjjj褺T$LT$LHP3P^ك0P $D$\$,D$,$D[^ÍPPjjvVS4[v2u21RP,$Mb$1RP,$\$|Q>P@Pj肃 $j|$.fD$. fD$,D$l$,|$$l$.D$$PQjEBPRj)XZD$4PjjHjjj0T$LT$LHP3P ,كP $L$T$\$,D$,$6D[^ËPPjj裂;vUWVSL[2u21RP,$\$$Mbe1RP,$t$>P@Pj\$ $j|$>fD$> fD$D$4PQjݍBPRj|udx 8D$DPjjPjjP裷HP3PMbe1RP,$t$$D$H1RP,$؋\$fD$> fD$D$4PQj\$ sBY PRj\A$j|$>fD$> fD$D$0P$$؋(l$<|$4l$>D$4PQjBWPRjB'UWVSL[D2u21RP,$\$$Mbe1RP,$t$>P@Pj\$Z $j|$>fD$> fD$D$4PQjBPRj|udx 8D$DPjjTjjPHP3PMbe1RP,$t$$D$H1RP,$؋\$fD$> fD$D$4PQj\$ 賉BY PRj}A$j|$>fD$> fD$D$0P$$؋(l$<|$4l$>D$4PQjDBWPRj(}B'UWVS$[Ähjhjjj膱D$ PjhjjjD$8 HC1퐍t&V:P3PR \P@Pjp| $jWPjWBWRj;|B ePRj| $jUPjBWRj{,[^_]Ðt&t&@C dVS4[֓:\$ D$4PjjHjjjOd$LD$0PjjLjjj0d$HD$,PjjVjjjL$D Mb$1RP,$t$\$L$(:P3PL$ \$(D$($ \P@Pj`z $j|$.fD$. fD$,D$l$,|$$l$.D$$PQj#BPRjzD[^Í&'ك8t&ك< t&VS4[F誳\$ D$4PjjHjjj迯D$L%D$L Ѓ j1HHMb$1RP,$t$\$:P3PL$ \$(D$($c \P@Pjx $j|$.fD$. fD$,D$l$,|$$l$.D$$PQj蛄BPRjxD[^Ít0Hك8 &tSك t3waكD'ك@t&كHt&كTwt&كPgt&mNكLEvt2C'كXt&VS4[Ə*\$ D$4PjjHjjj?D$L%D$L Ѓ Z{Mb$1RP,$t$\$:P3PL$ \$(D$($ \P@Pjiv $j|$.fD$. fD$,D$l$,|$$l$.D$$PQj,BPRjvD[^Í&ك8t&t:كTtqHvك t&tctރكD{v't&tQك\H&ك@6t&كH&t&كt&كdt&ك`t&كXt&VS4[&芮\$ D$4PjjDjjj蟪D$L%D$L Ѓ *"JHSMb$1RP,$t$\$:P3PL$ \$(D$($V \P@Pjs $j|$.fD$. fD$,D$l$,|$$l$.D$$PQjBPRjrsD[^É'tzt> ݃pt3sك8ك ك@t&كht&݃xt&VS4[6蚬\$ D$4PjjDjjj诨D$L%D$L  Mb$1RP,$t$\$:P3PL$ \$(D$(${ \P@Pjq $j|$.fD$. fD$,D$l$,|$$l$.D$$PQj}BPRjqD[^Í&'݃pt&ك t&݃xt&UWVS4[ĉD$$PjjjjjI d8u+*2|$54,2VzPHPjp Mb$!11RP,$\$PQjp$j|$&fD$& fD$$D$l$$|$l$&D$PQjL|BPRj0pXZD$(Pjjjjj7 |$ CUP@Pjo|$5D$,PjhjjjD$D tIH݃W:P3PL$ T$ \$ D$ $<[^_]Ív'D$,PjhjjjfD$DD$D ~uubك8k&Pt&UnPHPjn ݃t&G݃VS4[z\$ D$4Pjhjjj茤D$L  كhMb$1RP,$t$\$:P3PD$ \$(D$($]|uxP\P@Pjm $j|$.fD$. fD$,D$l$,|$$l$.D$$PQjyBPRjnm4[^ft;Jt(t;uك@݃t&݃t&ك8t&VS4[vڦ\$ D$0PjjjjjD$4PjjDjjjآD$L%D$L   JMb$1RP,$t$\$:P3PL$ \$(D$($ \P@Pjl $j|$.fD$. fD$,D$l$,|$$l$.D$$PQjwBPRjkD[^Í&݃&t&u+tftAJ ݃ كht+|$(%t,ك@|$(%݃pك v'VS4[vڤ\$ D$4PjjtjjjD$0Pjj`jjjؠL$Lȃ1RP,$1RQ,$(ڀE@u كlـE@uكlD$*@Mb$1RP,$t$\$:P3PL$ \$(D$($w \PPji $j|$.fD$. fD$,D$l$,|$$l$.D$$PQjuBPRjiD[^Ít&'#t&VSD[2ل\$t$DVjjpjjjCL$\ȃ1RP,$\$0(D$E@t*1RQ,$T$E@t H&؃Vjj|jjj۞L$\ȃ1RP,$\$(1RQ,$\$8(Mb$1RP,$t$ \$PPjSh$j|$>fD$> fD$D$4PQjtBPRjg :P3PD$t$D$ T$ \$8D$8$4T[^Í&'ل\$fUWVS,[xMb$1RP,$|$fD$ fD$l$|$ l$|$ |$P@Pj,g $jWPjsBPRjfXZD$,PjjjjjD$D =@%t=L%t ,[^_]ÐP:P3PD$1RP,$$ ,[^_]UWVS [l$8JP@PjafH ك@D$0E@ك\D$0E@ك(D$0E jj|$*fD$* fD$(D$Dl$(|$l$*D$PQjq PWPje@  jjUPjq PW.Uje@|$8 ~ jjL$LQPjjq PW.UjYe@|$<  jjL$PQPj2q [^_]Ít&PPQje4t& jjT$LRPjp | jjUPjp ,t& jj|$PWPjp [^_]Í&'Pkt& jj|$*fD$* fD$(D$Dl$(|$l$*D$PQjLp pS [÷|D$Pjhjjj9j@jhjjj袘D$PjhjjjT$4 PPRD$P$$ PPjc([Í'VS[{t$Vjhjjjx D$ @JD$PjRjjjOD$Pjhjjj5D$( u9t1T$ЃpHЃ/t&T$ЃpHЃRPQV$$ [PPj|bBD$ tKPPBPjXbBD$ u7QPBPj4b$[^Í&'P볍&VǍ&Vjhjjj  'WVS[EzD$PjjHjjjʗD$,%D$, @@%PPЃP1RP,$$ [P@PjDa>OD$PfPtfu!PPAPja[^_Ít&PPGPj`[^_ÍvUWVS$[TyD$ PjjHjjjٖT$8T$8`D$(` %Ћe]RX@1RP,$؃?W QV$ [P@Pj`Qt D$u?PPBPj_[^_]Ð?1RP,$أ tvRPAPj_[^_]fWVS[xD$PjjHjj8P蓕D$( ut t&L$D$PjhjVRED$ PjjpjVP.T$, PЃP RD$1RP,$؃$?T$Bv0t+tVVPQj^[^_ÐPP>Wjx^[^_Ít&'P΍&S [÷vD$Pjjxjjj<D$Pjjdjjj%T$4 D$PP P1RP,$$.([É'UWVS$[$vD$Pjjjjj詓d$4D$ PjjHjjj芓T$8T$8`D$$`D$ %Ћe]T$RX|$. 1҈ƒPP@Pj\|$.?1RV,$أd$?D$P WU$ [P@Pjt\Q4$t D$uiPPBPjF\[^_]Ít&'?1RV,$أ,ct&Pt&t&PPAPj[[^_]fWVS[EtD$PjjjjjʑD$Pjj@jjj賑D$,xh D$u @i@R#P@Pj_[D$ P`ukك\unЃuw )PQV$`tsP4PPjZ [^_Ít&Ht]كtH%ƃЃtH1Ɉ끍t&'Q#t&PN닍&ك 0t&S [rD$PjjxjjjlD$PjhjjjRT$4  P P P1RP,$$ZD$  w+PNPPjY([Í&'P4Ӎ&VS[rD$Pjjxjjj蛏D$Pjj|jjj脏T$0 uxك\Ѓփуك tlH1҈ƒRQV$D$@u9PNPPjX$[^Ít&'ك 놐&P4ō&똉'S['qP@PjXXZD$Pjhjjj菎D$PjhjjjuD$Pjhjjj[D$PjhjjjAT$0 Ѓ?PD$PRD$ P$$YD$uQNPRjW([fP4ߍ&UWVS$[$pD$ PjjtPpUlW蚍D$PjjtVpQlRt‹ t D$D$tD$D$ǃdu8L$t$t&'B t9u9pu뉓ddD j豑du[^_]Í PVj joV|tABBuPPQjEVPxtE|t xxuD^T;1dDTdDT[^_]Ë|PPQjU(RPPjpU vPPPjSU PPj6U3PqP7VjUxQPPjT ||PiPRjTt VPPjT {P$PPjT[RPPjnT |GPuPPj@Tu&PP Pj#T|QP PjS|VS[Yl% )э ȍ 񉋀%P)%[^Í&YkD$T$ttÐUWVS [äkt$ D$$D$ fAfD$ fT$ fuQD$ 6QQH1׉ŋ0vu1$)),$$1| vfT$ [^_] UWVS[jD$(P%jP'tEt1f%PW.Fu1 [^_]ø [^_]É'VS[yjT$L$|$ vS&'t{t@ut;tHuT$B[^Ðt&t$ PuT$B[^Ív'T$B[^f듍t&'f V@F6&8T$B[^Ív'S[*iD$L$ @vAЉ[Ít&lt&AЉ[Í&'AЉ[Í&'AЉ[Í&'AЉ[Í&' AЉ[Í&'@AЉ[Í&'AЉ[Í&'Y hT$B_vƁ Ív'ÍvUWVS@[gD$XD$fQD$QD$TQ1׉ŋD$PjjNffD$>Ft&tt1D$))l$D$1| vfT$.<[^_]Ít&UWVS[gD$(P%jPtEt1f%PW.Fu1 [^_]ø [^_]É'S [ÇfD$Pjj@jjj uD$f[S [GfD$Pjj TRPj较 uD$f[fUWVS[eTT$T$$E1T$RjjPPjC |$tf4$1T$T$ fGtF;D$uD$ PjjEPQj F;D$uĉ[^_]Ív'E@E`@Bt&UWVS [decKƃQPjjBL43 T0T$1tv'Et~v' UT$u jjUjjW1 t&'j1>PD@PPRFuԍt&JtJEuc [^_]VPjjnKIt]JXc [^_]UWVS\[c43 WPjjK xPjjJT0T$@D$4D$8L$D$ ' L$0QT$@utB< t0<CD$(D$$|$$uă\[^_]ÍL$(L$ RD$PjQWJ$jD$PD$DP|$DWKG} $L$PQVWT$TR0S@D$L &'@Htt<uD$,@HuꋋPT$@t͍L$'E ;D$,u닋tT$,1D@;EuPD$ PVD$DPF EPVD$DPpFE8tvFBBuFt$DI' t1P PVD$DPFFG[uӋt$DG1ЋpUBQPVD$,PEF 6RP$P.Ί@VS[^0F=~uW jjPj?j hQjjVRjHj TQ u7F1ҍ&ƄP GBLuX[^Í&'tX[^Í&UWVS[t](uJE4X0:11 jjQj"jPE< 9~;&6|&'&QV'PjnDE<@E<9|M01 jjQj"jBPE8 9}8&3|t&'&RV'PjDE8@E89|Et M(1+׉D$|1MbD$1׍R) jjgfff)ƍ)Qj j XOjjVjj GOՍR)jjgfff)ƍ)Qjj OjjVjj NjjUjj N G}[^_] E4d|4)οQ)1t&d/4)οQ)&dʉ'dz{<EDp}Dv-;EL+1EEH11'f9BE 9648MTȃ<%%f%%%)ЍF jj颋.)Rjj M pt4P1ɍf:B uI1 UWVS [$YXE8u [^_]Í&'+PRPjGPX@~ž1퍃D$D$ $&PD$ PVGP@ PFPOQG T$RF PGP? PF PGPGE;5PD$PFPGP?9:mHO^&'UWVS,[Wl$@D$DD$T$HT$ t$L|$PD$Pu^@@T$B@fD U T$tI,[^_]Ð&T$BuPPjj>L$,Azt&T$fzpT$ttu UQt념t& hX$ L$fypA<8|$fGp/ wv|$ RL$|$;GDGDOHWLD$911҉'A uL$QXA^9}fQ^D$|$G\9~fW\D$T$BT9tD$ ƋL$qTǃQdB9rB9g|$;G`vG`D$D$hdfxpD$|$WT11퐍&A uD$pDxHPVjjhDjWj!jCT$ Rj$j<$jPj'jmHjj4Vj-jPHL$PjDGP7$j4PjJGPC P'1P Pjj 7 pPjj7T$,fBpL$AlD$5~1QPjj =7 Pjj*7 Pjj7 Pjj7 ,Pjj6 DPjj6 YPjj6 qPjj6 Pjj6f8tq1D$,T$ $1~.T$x, jjPD$,PWSBD$PD$PW=6FutD$ PPj@j 6L$,fApWPj$D$(pV5xT$;JH>JHJPRLD$fS[7Nt!T$ jjj%PR([ÐT$ݍv'S[M@D$(%4D$,4jjD$,PD$,PD$,P([ S[ÇMD$L$ j1RQPPy([Ít&S[WMjT$$RD$,PD$4PD$,PE([S['MT$t)t! jD$(3D$$PD$,PL$,QR [ÐT$:t1t&@<u1Ðt&VL$T$ ~C1A4Buu$Ft 獴&u1^Ív'UWVS[WL':_uzSuzMuz_uډ1B49v1ɰ_B9ruivSO1fG%,9<t{<t[tW1AHut&'t$AtAuv'[^_]FfG%9A듋@ @@덋 @d1멍t&S['K,P@&9uf[Í&'UWVS [Jf8@D$$1T$ A ;D$ w[A 9D$ wOT$~G1 v9t9*f@f;A u拃,t9$9uҍt&';t$u$ [^_]Í,*$$&UWVS [ôI@D$QPjD$PR1D$1$T&1FPVƉ$gPmD$PVUD$HQ04$AŃ@tT,t닃4D$tPD$PUD$@Pb0w& @뇍t& [^_]Ð&UWVSL[äHf8u\D$4D$HL$([D$$T$ L$D$$3GPD$,Pjj/_]t$TD$PjbT$JL1#ՒllU%`pЕ 0P\ҠwS YL?L2%L% Ys L% %%% % YfYii]QE9-==1% 'P^^RxHMgssr W rWr mm*pUA%PPPPPPPPPPPPPPPP%PPPPPPPPPPPPPPPPPPPPPPPPPPPP%pP0    `_`_````kkkllkpqrrrrCB|BCB|BAAAAAAAAAA A0A@APA`ApA@AA@AAPAXA`AApAAAAAAAA0A8A@AHA@@@@@@AAAA A(AP`p@0PpЗġϝϝϝϝϝconsole= Relocated - *****Pass complete, no errors, press Esc to exit***** [Address test, walking ones] [Address test, own address] [Moving inversions, ones & zeros] [Moving inversions, 8 bit pattern] [Moving inversions, random pattern] [Block move, 80 moves] [Moving inversions, 32 bit pattern] [Random number sequence] [Modulo 20, Random pattern] [Bit fade test, 90 min, 2 patterns] Press *F1* to enter Fail-Safe Mode Memory : |------------------------------------------------- WallTime Cached RsvdMem MemMap Cache ECC Test Pass Errors ECC Errs --------- ------ ------- -------- ----- --- ---- ---- ------ -------- -----------------------------------------------------------------------------INE_SCROLL;24r Memtest86 v4.20 L1 Cache: Unknown L2 Cache: Unknown L3 Cache: None Chipset : Cyrix Cx486Cyrix 5x86Cyrix 6x86Cyrix MediaGXCyrix 6x86MXCyrix MIICyrix ???386AMD 486DX2AMD 486DX2-WBAMD 486DX4AMD 486DX4-WBAMD 5x86-WTAMD K5AMD K6AMD K6-2AMD K6-IIIAMD Geode LXAMD K6-III+AMD Athlon (0.25)AMD Athlon (0.18)AMD Duron (0.18)Athlon XP (0.18)AMD Duron (0.13)Athlon XP (0.13)AMD DuronAMD K8AMD Opteron (0.09)AMD Opteron (0.13)Athlon 64 X2Turion 64 X2Athlon 64 (0.09)Sempron (0.09)Athlon 64 (0.13)Sempron (0.13)AMD Fusion @AMD K10 (65nm) @AMD K10 (45nm) @AMD Magny-CoursTM 5x00TM 8x00Intel 486DXIntel 486SXIntel 486DX2Intel 486SLIntel 486SX2Intel 486DX2-WBIntel 486DX4Intel 486DX4-WBPentiumPentium-MMXPentium ProPentium IIIntel Core i3/i5Intel EP80579CeleronIntel Core 2Pentium IIICeleron M (0.13)Pentium M (0.13)Intel Core Gen2Intel Core i7Pentium III XeonCore i7 (32nm)Atom (0.045)Celeron M (0.09)Pentium M (0.09)Intel Core i5/i7Intel CorePentium ECeleron (0.18)Xeon DP (0.18)Xeon MP (0.18)Pentium 4 (0.18)Celeron (0.13)Xeon DP (0.13)Xeon MP (0.13)Pentium 4 (0.13)Celeron (0.09)Xeon DP (0.09)Xeon MP (0.09)Pentium D (0.09)Pentium 4 (0.09)Pentium D (65nm)Unknown IntelCentaur 5x86VIA C3 Samuel2VIA C3 EdenVIA C7 (C5J)VIA C7 (C5R)VIA Isaiah (CN)Cyrix 6x86MX/MIICyrix GXmCyrix IIIVIA C3 Ezra-TVIA C3 Nehemiah586686 . MHz MHzL1 Cache: K MB/sL2 Cache: K L3 Cache: K : :Pass %Test %Test #Testing: Pattern: 0| ?ttySOCKEDHalting... none on Type: PC: CS: Eflag: Code: Addr: eax: ebx: ecx: edx: edi: esi: ebp: esp: DS: SS: Stack: Divide Debug NMI BrkpntOverflow Bound Inv_Op No_MathDouble_FaultSeg_Over Inv_TSS Seg_NPStack_FaultGen_ProtPage_Fault Resvd FPEAlignment Mch_ChkSIMD FPE(ESC)Reboot (c)configuration (SP)scroll_lock (CR)scroll_unlockUnexpected Interrupt - HaltingCS:EIP: Settings:(1) Test Selection(2) Address Range(3) Memory Sizing(4) Error Report Mode(5) Show DMI Memory Info(6) ECC Mode(7) Restart(8) Refresh Screen(9) Display SPD Data(0) ContinueTest Selection:(1) Default Tests(2) Skip Current Test(3) Select Test(4) Select Bit Fade Test>Test Number [0-9]: Test Address Range:(1) Set Lower Limit(2) Set Upper Limit(3) Test All MemoryLower Limit: Current: New: Upper Limit: Memory Sizing:(1) BIOS - Std(2) ProbePrinting Mode:(1) Error Summary(2) Individual Errors(3) BadRAM Patterns(4) Error Counts Only(5) DMI Device Name(6) Beep on Error(0) CancelECC Polling Mode:(1) Recommended(2) On(3) OffLBIO e88 e801 e820LxBIOSProbed ON/ CAS : 2.5-4-/ DDR2 (128 bits) DDR2 (64 bits) DDR1 (128 bits) DDR1 (64 bits)- Type : DDR-II- Type : DDR2- Type : DDR16- Dual Channel (Asymmetric) Dual Channel (Interleaved)Settings: MHz (IMC : (ECC : Disabled)DDR-RAM : DDR/ BCLK : DDR3-/ QPI : GT/s- FSB : - GFX : i855GM/GME i852PM/GM / FSB : / Centrino Mobile Platform/ Mobile Platform1.52.5/ DDR3 (64 bits)/ Single Channel/ Triple Channel/ Dual Channel- Type : DDR3- PAT : Enabled- PAT : Disabled/ Dual Channel (128 bits)/ Single Channel (64 bits)(ECC : / Chipkill : Off) Scrub+ UnknownDetectCorrect -Correct)On)AMD 751AMD 762AMD 761SiS 600SiS 620SiS 5600SiS 645SiS 645DXSiS 630SiS 650SiS 651SiS 730SiS 735SiS 740SiS 745SiS 748SiS 655SiS 656SiS 648SiS 649SiS 661SiS 671SiS 672ALi Aladdin 4ALi Aladdin 5ALi Aladdin M1644ATi Radeon 9100 IGPATi Radeon Xpress 200nVidia nForcenVidia nForce2 SPPnForce4 SLI Intel EditionVIA KT133/KT133AVIA KX133VIA MVP4VIA VP/VPXVIA VP2VIA VP3VIA MVP3VIA Apollo Pro/133/133AVIA Apollo Pro+VIA PLE133VIA KT266(A)/KT333VIA KT400(A)/600VIA KT880VIA KM400VIA KM266VIA KN266VIA CLE266VIA PT800VIA PT880CNB20HECNB20LEIntel i815Intel i430FXIntel i430MXIntel i440FXIntel i430HXIntel i840Intel i845Intel i845E/G/PE/GEIntel i820Intel i850Intel i860Intel i430VXIntel i430TXIntel i810Intel i810EIntel i440[LE]XIntel i440BXIntel i440GXIntel i450GXIntel E7500Intel E7501Intel E7205Intel E7320Intel E7221Intel E7520Intel E8500Intel i848/i865Intel i875PIntel E7505Intel Intel i855PMIntel i915P/GIntel i915PM/GMIntel i925X/XEIntel i945P/GIntel i945GM/PMIntel i945GMEIntel i955XIntel i975XIntel i946PL/GZIntel Q963/Q965Intel P965/G965Intel GM965/GL960Intel GME965/GLE960Intel PM/GM45/47Intel Q35Intel P35/G33Intel Q33Intel X38/X48Intel 3200/3210Intel Q45/Q43Intel P45/G45Intel G41Intel 5400AIntel 5400BIntel 5000PIntel 5000VIntel 5000XIntel 5000ZIntel US15WIntel UL11L/US15LCore IMCCore IMC 32nmSNB IMC 32nmAMD K8 IMCAMD K10 IMCAMD APU IMCChipset/IMC : ***FAIL SAFE***FAIL SAFE***FAIL SAFE***FAIL SAFE***FAIL SAFE****** Memtest86+ is running in fail safe mode. Same reliability, less details ***@@@C>@@@)\O? AAڬ?zD?L????@UUU??UU? @*@UUU@@?A-R\U?іs)??Em>UUU?(%??+LUUU?-R\U?SMBus Controller not knownSPD Data: SlotMemory SPD Informations - Slot :PC3-6400PC3-8500PC3-10600PC3-12800PC3-15000PC3-16000*XMP*DDR2-AMDAMIFairchildFujitsuGTEHarrisHitachiInmosI.T.T.IntersilMonolithic MemoriesMostekFreescale (Motorola)NationalNECRCARaytheonConexant (Rockwell)SeeqNXP (Philips)SynertekTexas InstrumentsToshibaXicorZilogEurotechniqueMitsubishiLucent (AT&T)ExelAtmelSGS/ThomsonLattice Semi.NCRWafer Scale IntegrationIBMTristarVisicIntl. CMOS TechnologySSSIMicrochipTechnologyRicohVLSIHynix SemiconductorOKI SemiconductorACTELSharpCatalystPanasonicIDTCypressDECLSI LogicZarlink (Plessey)UTMCThinking MachineThomson CSFIntegrated CMOS (Vertex)HoneywellTektronixSun MicrosystemsSSTProMos/Mosel VitelicInfineon (Siemens)MacronixXeroxPlus LogicSanDiskElan Circuit Tech.European Silicon Str.Apple ComputerXilinxCompaqProtocol EnginesSCISeiko InstrumentsSamsungI3 Design SystemKlicCrosspoint SolutionsAlliance SemiconductorTandemHewlett-PackardIntg. Silicon SolutionsBrooktreeNew MediaMHS ElectronicPerformance Semi.Winbond ElectronicKawasaki SteelBright MicroTECMARExarPCMCIALG Semi (Goldstar)Northern TelecomSanyoArray MicrosystemsCrystal SemiconductorAnalog DevicesPMC-SierraAsparixConvex ComputerQuality SemiconductorNimbus TechnologyTranswitchMicronas (ITT Intermetall)CannonAlteraNEXCOMQUALCOMMSonyCray ResearchAMS(Austria Micro)VitesseAster ElectronicsBay Networks (Synoptic)Zentrum/ZMDTRWThesysSolbourne ComputerAllied-SignalDialogMedia VisionNumonyxCirrus LogicNational InstrumentsILC Data DeviceAlcatel MietecMicro LinearUniv. of NCJTAG TechnologiesBAE Systems (Loral)NchipGalileo TechBestlink SystemsGraychipGENNUMVideoLogicRobert BoschChip ExpressDATARAMUnited Microelectronics Corp.TCSISmart ModularHughes AircraftLanstar SemiconductorQlogicKingstonMusic SemiEricsson ComponentsSpaSEEon Silicon DevicesProgrammable Micro CorpDoDInteg. Memories Tech.CorollaryDallas SemiconductorOmnivisionEIV(Switzerland)Novatel WirelessZarlink (Mitel)ClearpointCabletronSTEC (Silicon Tech)VanguardHagiwara Sys-ComVantisCelesticaCenturyHal ComputersRohm CompanyJuniper NetworksLibit Signal ProcessingMushkin Enhanced MemoryTundra SemiconductorAdaptecLightSpeed Semi.ZSP Corp.AMIC TechnologyAdobe SystemsDynachipPNY ElectronicsNewport DigitalMMC NetworksT SquareSeiko EpsonBroadcomViking ComponentsV3 SemiconductorSuwa ElectronicsTransmetaMicron CMSEnhance 3000Tower SemiconductorCPU DesignPrice PointMaxim Integrated ProductTellabsCentaur TechnologyUnigenTranscend InformationMemory Card TechnologyCKDCapital InstrumentsAica KogyoLinvex TechnologyMSC VertriebsAKM CompanyDynamemNERA ASAGSI TechnologyDane-Elec (C Memory)Acorn ComputersLara TechnologyOak TechnologyItec MemoryTanisys TechnologyTruevisionWintec IndustriesSuper PC MemoryMGV MemoryGalvantechGadzoox NetworksMulti Dimensional Cons.GateFieldIntegrated Memory SystemTriscendXaQtiGoldenramClear LogicCimaron CommunicationsNippon Steel Semi. Corp.Advantage MemoryAMCCLeCroyYamahaDigital MicrowaveNetLogic MicrosystemsMIMOS SemiconductorAdvanced FibreBF Goodrich Data.EpigramAcbel PolytechApacer TechnologyAdmor MemoryFOXCONNQuadratics Superconductor3COMCamintonnISOAAgate SemiconductorADMtekHYPERTECAdhoc TechnologiesMOSAID TechnologiesArdent TechnologiesSwitchcoreCisco SystemsAllayer TechnologiesWorkX AG (Wichman)Oasis SemiconductorNovanet SemiconductorE-M SolutionsPower GeneralAdvanced Hardware Arch.Inova SemiconductorsTelocityDelkin DevicesSymagery MicrosystemsC-PortSiberCore TechnologiesSouthland MicrosystemsMalleable TechnologiesKendin CommunicationsSanminaHADCOCorsairActrans SystemALPHA TechnologiesSilicon Laboratories (Cygnal)Artesyn TechnologiesAlign ManufacturingPeregrine SemiconductorChameleon SystemsAplus Flash TechnologyMIPS TechnologiesChrysalis ITSADTECKentron TechnologiesWin TechnologiesTachyon Semiconductor (ASIC)Extreme Packet DevicesRF Micro DevicesSiemens AGSarnoffItautec SARadiataBenchmark Elect. (AVEX)LegendSpecTekHi/fnEnikiaSwitchOn NetworksAANetcomMicro Memory BankESS TechnologyVirataExcess BandwidthWest Bay SemiconductorDSP GroupNewport CommunicationsChip2ChipPhobosIntellitechNordic VLSI ASAIshoni NetworksSilicon SpiceAlchemy SemiconductorAgilent TechnologiesCentillium CommunicationsW.L. GoreHanBit ElectronicsGlobeSpanElement 14PyconSaifun SemiconductorsSibyte,MetaLink TechnologiesFeiya TechnologyI & C TechnologyShikatronicsElektrobitMegicCom-TierMalaysia Micro SolutionsHyperchipGemstone CommunicationsAnadigm (Anadyne)3ParDataMellanox TechnologiesTenx TechnologiesHelix AGDomosysSkyup TechnologyHiNTChiaroMDT TechnologiesExbit Technology A/SIntegrated Technology ExpressAVED MemoryLegerityJasmine NetworksCaspian NetworksnCUBESilicon Access NetworksFDKHigh Bandwidth AccessMultiLink TechnologyBRECISWorld Wide PacketsAPWChicory SystemsXstream LogicFast-ChipZucotto WirelessRealchipGalaxy PowereSiliconMorphics TechnologyAccelerant NetworksSilicon WaveSandCraftElpidaSolectronOptosys TechnologiesBuffalo (Formerly Melco)TriMedia TechnologiesCyan TechnologiesGlobal LocateOptillionTerago CommunicationsIkanos CommunicationsPreton TechnologyNanya TechnologyElite Flash StorageMysticomLightSand CommunicationsATI TechnologiesAgere SystemsNeoMagicAuroraNeticsGolden EmpireMushkinTioga TechnologiesNetlistTeraLogicCicada SemiconductorCenton ElectronicsTyco ElectronicsMagis WorksZettacomCogency SemiconductorChipcon ASAspex TechnologyF5 NetworksChipWrightsAcorn NetworksQuicklogicKingmax SemiconductorBOPSFlasysBitBlitz CommunicationseMemory TechnologyProcket NetworksPurple RayTrebia NetworksDelta ElectronicsOnex CommunicationsAmple CommunicationsMemory Experts IntlAstute NetworksAzanda Network DevicesDibcomTekmosAPI NetWorksBay MicrosystemsFirecronResonext CommunicationsTachys TechnologiesEquator TechnologyConcept ComputerSILCOM3Dlabsc?t MagazineSanera SystemsSilicon PacketsViasystems GroupSimtekSemicon Devices SingaporeSatron HandelsgesImprov SystemsINDUSYSCorrentInfrant TechnologiesRitek CorpempowerTel NetworksHypertecCavium NetworksPLX TechnologyMassana DesignIntrinsityValence SemiconductorTerawave CommunicationsIceFyre SemiconductorPrimarionPicochip DesignsSilverback SystemsJade Star TechnologiesPijnenburg SecurealinktakeMS International AGCambridge Silicon RadioSwissbitNazomi CommunicationseWave SystemRockwell CollinsPicocel Co. (Paion)AlphamosaicSandburstSiCon VideoNanoAmp SolutionsEricsson TechnologyPrairieCommMitac InternationalLayer N NetworksMtekVision (Atsana)Allegro NetworksMarvell SemiconductorsNetergy MicroelectronicNVIDIAInternet MachinesPeak ElectronicsLitchfield CommunicationAccton TechnologyTeradiant NetworksScaleo ChipCortina SystemsRAM ComponentsRaqia NetworksClearSpeedMatsushita BatteryXeleratedSimpleTechUtron TechnologyAstec InternationalAVMRedux CommunicationsDot Hill SystemsTeraChipT-RAMInnovics WirelessTeknovusKeyEye CommunicationsRuncom TechnologiesRedSwitchDotcastSilicon Mountain MemorySignia TechnologiesPiximGalazar NetworksWhite Electronic DesignsPatriot ScientificNeoaxiom3Y Power TechnologyPotentia Power SystemsC-guysSilicon-Based TechnologyFulcrum MicrosystemsPositivo InformaticaXIOtechPortalPlayerZhiying SoftwareParkerVisionPhonex BroadbandSkyworks SolutionsEntropic CommunicationsPacific Force TechnologyZensys A/SLegend Silicon Corp.Sci-worxSMSC (Standard Microsystems)Renesas TechnologyRaza MicroelectronicsPhyworksMediaTekNon-cents ProductionsUS ModularWintegraMathstarStarCoreOplus TechnologiesMindspeedJust Young ComputerRadia CommunicationsOCZEmuzedLOGIC DevicesInphiQuake TechnologiesVixelSolusTekKongsberg MaritimeFaraday TechnologyAltiumInsyteARMDigiVisionVativ TechnologiesPericomBandspeedLeWiz CommunicationsCPU TechnologyRamaxel TechnologyAxis CommunicationsLegacy ElectronicsChrontelPowerchip SemiconductorMobilEye TechnologiesExcel SemiconductorA-DATA TechnologyVirtualDigmG Skill IntlQuanta ComputerYield MicroelectronicsAfa TechnologiesKINGBOX Technology Co.CevaiStor NetworksAdvance ModulesMicrosoftOpen-SiliconGoal SemiconductorARC InternationalSimmtecMetanoiaKey StreamLowrance ElectronicsAdimosSiGe SemiconductorFodus CommunicationsCredence Systems Corp.Genesis MicrochipVihanaWIS TechnologiesGateChange TechnologiesHigh Density Devices ASSynopsysGigaramEnigma SemiconductorCentury MicroIcera SemiconductorMediaworks Integrated SystemsO'Neil Product DevelopmentSupreme Top TechnologyMicroDisplayTeam GroupSinettTensilicaSiRF TechnologyBacocSMaL Camera TechnologiesThomson SCAirgo NetworksWisairSigmaTelArkadosCompete IT Co. KGEudar TechnologyFocus EnhancementsXyratexSpecular NetworksPatriot Memory (PDP Systems)U-Chip Technology Corp.Silicon OptixGreenfield NetworksCompuRAMStargenNetCellExcalibrus TechnologiesSCM MicrosystemsXsigo SystemsCHIPS & SystemsCWRL LabsTeradicig2 MicrosystemsPowerFlash SemiconductorP.A. SemiNovaTech Solutions, S.A.c2 MicrosystemsLevel5 NetworksCOS Memory AGInnovasic Semiconductor02IC Co.Tabula,Crucial TechnologyChelsio CommunicationsSolarflare CommunicationsXambalaEADS AstriumTerra SemiconductorImaging WorksTzeroEmulexPower-OnePulse~LINKHon Hai Precision IndustryWhite Rock NetworksTelegent Systems USAAtrua TechnologieseRideULi ElectronicsMagnum SemiconductorneoOne TechnologyConnex TechnologyStream ProcessorsTelecis WirelessuNav MicroelectronicsTarariAmbricNewport MediaVMTSEnuclia SemiconductorVirtium TechnologySolid State System Co.Kian Tech LLCArtimiPower Quotient InternationalAvago TechnologiesADTechnologySigma DesignsSiCortexVentura Technology GroupeASICM.H.S. SASMicro Star InternationalRapportMakway InternationalBroad Reach Engineering Co.Semiconductor Mfg Intl CorpSiConnectFCI USAValidity SensorsConey Technology Co.Spans LogicNeterionQimondaNew Japan Radio Co.VelogixMontalvo SystemsiVivityWalton ChaintechAENEONLorom Industrial Co.Radiospire NetworksSensio TechnologiesNethra ImagingHexon Technology PteCompuStocx (CSX)Methode ElectronicsConnect OneOpulan TechnologiesSeptentrio NVGoldenmars TechnologyKretonCochlearAltair SemiconductorNetEffectSpansionTaiwan Semiconductor MfgEmphany SystemsApaceWave TechnologiesMobilygenTegoCswitchHaier (Beijing) IC Design Co.MetaRAMAxel Electronics Co.TileraAquantiaVivace SemiconductorRedpine SignalsOctalicaInterDigital CommunicationsAvant TechnologyAsrockAvailinkQuarticsElement CXIVeriSilicon MicroelectronicsW5 NetworksMOVEKINGMavrix TechnologyCellGuideDiablo TechnologiesJennicOctasicMolex3Leaf NetworksBright Micron TechnologyNetxenNextWave BroadbandDisplayLinkZMOS TechnologyTec-HillMultigigAmimonEuphonic TechnologiesBRN PhoenixInSilicaEmberAvexir TechnologiesEchelonEdgewater Computer SystemsXMOS SemiconductorGENUSIONMemory Corp NVSiliconBlue TechnologiesRambusAndes TechnologyCoronis SystemsAchronix SemiconductorSiano Mobile SiliconSemtechPixelworksGaisler Research ABTeraneticsToppan Printing Co.KingxconSilicon Integrated SystemsI-O Data DeviceNDS AmericasSolomon Systech LimitedOn Demand MicroelectronicsAmicus WirelessSMARDTV SNCComsys CommunicationMovidiaJavad GNSSMontage Technology GroupTrident MicrosystemsSuper TalentOptichronFuture Waves UKSiBEAMInicore,Virident SystemsM2000ZeroG WirelessGingle Technology Co.Space MicroWilocityNovafora, Ic.iKoaASint TechnologyRamtronPlato NetworksIPtronics ASInfinite-MemoriesParade TechnologiesDune NetworksGigaDevice SemiconductorModuCEITECNorthrop GrummanXRONETSicon Semiconductor ABAtla Electronics Co.TOPRAM TechnologySilego TechnologyKinglifeAbility IndustriesAugusta TechnologyNantronics SemiconductorsHilscher GesellschaftQuixantPercelloNextIOScanimetricsFS-Semi CompanyInfineraSandForceLexar MediaTeradyneMemory Exchange Corp.Suzhou Smartek ElectronicsAvantiumATP ElectronicsValens SemiconductorAgate LogicNetronomeZenvergeN-trigSanMax TechnologiesContour SemiconductorTwinMOSSilicon SystemsV-Color TechnologyCerticomJSC ICC MilandrPhotoFast GlobalInnoDiskMuscle PowerEnergy MicroInnofideiIntel P67Intel P55Intel ICH10BIntel ICH10RIntel ICH9Intel ICH8Intel ICH7Intel ICH6Intel ICH5Intel ICH4Intel 6300ESBIntel ESB2-----------------------------------Flextronics (Orbit Semiconductor)American Computer & Digital ComponentsGreat Technology MicrocomputerProgrammable Silicon SolutionsDigital Communications TechnologyEndicott Interconnect TechnologiesInnovaciones MicroelectronicasSilicon Power Computer & Communications?@Fbadram=,0xError Confidence Value: Lowest Error Address: Highest Error Address: Bits in Error Mask: Bits in Error - Total:Min: Max: Avg: Max Contiguous Errors:ECC Correctable Errors:Errors per Memory Slot:: 0Test Errors - . MBuncorrected corrected ECC Tst Pass Failing Address Good Bad Err-Bits Count Chan--- ---- ----------------------- -------- -------- -------- ----- ----Parity error detected Bad Memory Devices: , Emptymapped to: OtherEDRAMVRAMSRAMFLASHEEPROMFEPROMCDRAM3DRAMSDRAMSGRAMRDRAMDDR2 FBRSVDFBD2SIMMSIPDIPZIPProprietary CardTSOPRow of chipsSODIMMSRIMMFB-DIMMNo valid DMI Memory Devices info foundDMI Memory Device Info (page Location Size(MB) Speed(MHz) Type FormNo mapping (Interleaved Device). /%h  ) 4`4#P0Y"t`s&`@ RlJ@^@> Pcfܞ   pvlq\@ 6 Vsz  : ]`YZmb. P pqO;P L P<7; 9yJHP2` mD  ! V.  ^  (`9l eY 6N54[ |H   4X40z sJg0s"t 8pWko= tt#\ `u"@-  D@ 1;PI p=k@r < 0/5?(0 -  ; )\p? ek" yyx u  HO y_^,PVW4W),j; GeVnUT ,xs#5< [@\5=^4GL0 `60U@)F4@ P54  ,$0pU&0, PX    6 J@  ?0e@ c3+ L  f ^3.f*V T wD c  P/43$P*JS; v: F4#@ q $  qZD,   +,C +; 3@5 L( lAWC0PWp@; )Q{0$Ix `/9jPZ!7 ]00 Jttm  pO $ gt`_ *04Zmu* (0Wz0%f+#`xlw8]sdu"P2|68 P,B\( 5P@ T&pwstartup_32gdt_bsscpu_id_dl_startdo_testintergdt_endpd0pd1pd2pd3pdpquery_pcbiosmem_infovariablestseqsegsemappingfind_ticks_for_passmemmovehigh_test_adrrestartfirsttimecmdline_parsedbailpaging_offset_cachecprintcheck_inputdprintmap_pagepage_ofaprinttest_ticksnticksstrncmpserial_console_setupp1p2randmodtstmovinv1movinvrbit_fadeblock_moveaddr_tst2addr_tst1p0movinv32sleepbeephprintdo_tickad_err2rand_seedad_err1ecountcorrect_tscmemspeedst_lowst_highcal_lowcal_highend_lowend_hightsc_invariablefailsafeget_keyfail_safeserial_echo_initserial_echo_printfirmwarememsz_modemem_sizepci_initbeepmodedmi_initializeddmi_err_cntsextclockquery_linuxbiosfind_controllerfooterget_spd_specimc_typel1_cachel2_cachel3_cachememcmpmemcpytoupperisdigitisxdigitsimple_strtoulclear_scrollreverseitoagetnumascii_to_keycodeser_mapserial_bitsserial_parityserial_baud_rateserial_ttyserial_consserial_base_portslsrttyprintwait_keyupclear_screen_buftty_print_linegetvaltty_print_screenslockget_confighprint3hprint2codesparity_errxprintget_scrn_bufset_scrn_buftty_print_regioncombineaddressescombicostcheapindexrelocateidxrelocateiffreeinsertaddressprint_errorclear_screenadj_mempop2clearpop2downsave2pop2uppopclearpopdownsavepopupshow_spdprintpatnset_ecc_pollingprint_dmi_infoe820_nrpci_conf_writepci_conf_readpoll_errorsnhm_buscol2getIntelPNScolconvert_hex_to_charprint_ecc_errprint_fsb_infoprint_timings_infoich5_smb_read_bytesmbusbaseget_ddr3_module_sizeget_ddr2_module_sizeus15w_smb_read_bytesmbfunsmbdevfind_smb_controllerjep106common_erradd_dmi_errstrlenget_tstruct_stringopen_dmimd_maps_countmd_mapsmem_devs_countmem_devsinit_dmiprint_dmi_errcpuid_getcpuid_get_vendor_stringcpuid_data0cpuid_get_versioncpuid_get_feature_flagscpuid_get_ext_feature_flagscpuid_data80cpuid_is_vendor_amdcpuid_is_vendor_intelcpuid_is_family_p4cpuid_is_family_p6cpuid_is_family_opteroncpuid_initnum_cores_per_packagenum_hyper_threads_per_corenum_logical_cpus_etext_data_edata>v}im/Bnur %E;G@Va3]Ul^+0TPD4gcRKdSf7b2:xYJyFXQ9|o #* &)$(651'CZ\[Akt.e=WIh`q- !j_<pLw NO8zs,~H?" M{ ПВ P 9#qKM ; i     !T!_!}!!!!+"6"j""""""""#(#:#V#]#o#y#####$$%&&&0'`'''''(*(p(((()L)))))))*@*[*f****+ +!+;+S++++, ,,,O,,,,,-I-V-e-z--------- .-.O.^.........// /&/7/@/880000H;T;`;l;x;;;;;;H<P<T<X<\<h<p<t<x<|<<<<<<<<<<<<<<<<<<<<<=====(=0=4=8=<=H=P=T=X=\=h=p=t=x=|=====================>>>>>(>0>4>8><>H>P>T>X>\>h>p>t>x>|>>>>>>>>>>>>>>>>>>>>>?????(?0?4?8? >@>`>>>>>? ?@?`?????@ @@@`@@@@@A A@A`AAAAAB B@B`BBBBBC C@C`CCCCCD D@D`DDDDDE E@E`EEEEEF F@F`FFFFFG G@G`GGGGGH H@H`HHHHHI I@I`IIIIIJ J@J`JJJJJK K@K`KKKKKL L@L`LLLLLM M@M`MMMMMN N@N`NNNNNO O@O`OOOOOP P@P`PPPPPQ Q@Q`QQQQQR R@R`RRRRRS S@S`SSSSST T@T`TTTTTU U@U`UUUUUV V@V`VVVVVW W@W`WWWWWX X@X`XXXXXY Y@Y`YYYYYZ Z@Z`ZZZZZ[ [@[`[[[[[\ \@\`\\\\\] ]@]`]]]]]^ ^@^`^^^^^_ _@_`_____` `@```````a a@a`aaaaab b@b`bbbbbc c@c`cccccd d@d`ddddde e@e`eeeeef f@f`fffffg g@g`gggggh h@h`hhhhhi i@i`iiiiij j@j`jjjjjk k@k`kkkkkl l@l`lllllm m@m`mmmmmn n@n`nnnnno o@o`ooooop p@p`pppppq q@q`qqqqqr r@r`rrrrrs s@s`ssssst t@t`tttttu u@u`uuuuuv v@v`vvvvvw w@w`wwwwwx x@x`xxxxxy y@y`yyyyyz z@z`zzzzz{ {@{`{{{{{| |@|`|||||} }@}`}}}}}~ ~@~`~~~~~ @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @`   ((0088@@HHPPXX``hhppxx%   9 9aAb0B00c.C..d D  eEf!F!!g"G""h#H##iI j$J$ $k%K% %l&L& &m2M2 2n1N11oOpPqQrRsStTuUv/V//wWx-X--yYz,Z,,- _  = + [{]};':''("(`)~)\+|++,3<3.4>4/5?51!2@3#4$5%6^7&8 * 9 ( 0 ) iE#?;U/-\| DD E4E 2\EPEE E E$FNNNNNNNNOOO$O-O9OBOMOVO_OiOrO_,_@0_E_X_Ca_g_Er_Fz___I_J__L___O_`Q`R`1`T8`H```Wj`Xt```[``]`^```a`b`ada*a9agDahLa\arakaamanaapaaasaauavb b,by0bz7bJb|Xb_blbtbbbbbbbbbb cc !c(c3c@cMcUcscxcccccccccc dd 'd1dFd#Qdbd%sd&ddd)d*dd,ddd/dd1 e2#e;e4PeXeie7se8eee;ee=e>ee@eeCffE#fF@.f;fIOfJZfffLfffOffQfRffTfggWgX%g.g=g[Rgbg]rg^gggagbggdgggg hhh/h8hk>hHhmThnkhhphhhshhuhvhhiy izi.i|;iCi]ibiliqiiiiiiii ii j%j;jIjWjojjjjjjjjjhkk"k*k 9kLkjk#kk%k&kkk)k*kl, l=lTl/elpl1xl2ll4lll7l8lll;ll=m>m*m@4mKmUmC\mhmExmFmmmImJmmLmn nOn)nQ1nRGnXnTinvnnWnXnnn[nn]n^nooaob0o5odatnt@}tttCttEtFtttIuJu$uL-u=uLuO[ufuQ|uRuuTuuuWuXvv6v[?vUv]bv^svvvavbvvdvvvgwhw%w̎{@{{|C#|*mE6|FJ|]|f|I~|J||L|||O||Q }R"}'}T6}F}P}W]}Xp}}}[}}]}^}}}a}b ~~d#~;~S~g\~hd~y~~k~~m~n~~p] s$u*vCN]ydzmu|%-5M ^l n|\~€ۀ !*2E\v~ s#%&āρ)* i,&,</Qc1u2478ʂς;=>$A@TaoCxEFÃI؃JL"3OHTQ]ReyTWXDŽۄ[]^$8DaXbf|dgh݅ͅkmn )p1FMsVku{vyzʆ|ֆ{$8?GM\ u| ćڇ ,?HWpw Ĉ#̈׈%& ).*>K,c~/12‰ۉ478'8;>M=c>ox@CEFҊI JL*1HO]oQRTʋWX[]^(4=aSbnwdghŒ֌kmn p0AJsWd (0 '0 j&0 $ȍ0 $Ӎ0 %ލ0 &0 Zp2PK0 ܞ6 :P;; l@0 ;;0@  6 @LTD;:,@5L@;00 $6(memtest86+-4.20/smp.c0000644000000000000000000002422711517067470013026 0ustar rootroot/* * smp.c -- * * 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. * */ #include "stddef.h" #include "smp.h" #include "cpuid.h" #include "test.h" #define DELAY_FACTOR 1 extern void memcpy(void *dst, void *src , int len); extern void test_start(void); typedef struct { bool started; } ap_info_t; 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]; uint8_t checksum(uint8_t *data, unsigned len) { uint32_t sum = 0; uint8_t *end = data + len; while (data < end) { sum += *data; data++; } return (uint8_t)(sum % 0x100); } 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; 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; } 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; 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; } void PUT_MEM16(uintptr_t addr, uint16_t val) { *((volatile uint16_t *)addr) = val; } void PUT_MEM32(uintptr_t addr, uint32_t val) { *((volatile uint32_t *)addr) = val; } static void inline APIC_WRITE(unsigned reg, uint32_t val) { APIC[reg][0] = val; } static inline uint32_t APIC_READ(unsigned reg) { return APIC[reg][0]; } static void SEND_IPI(unsigned apic_id, unsigned trigger, unsigned level, unsigned mode, uint8_t vector) { uint32_t v; v = APIC_READ(APICR_ICRHI) & 0x00ffffff; APIC_WRITE(APICR_ICRHI, v | (apic_id << 24)); v = APIC_READ(APICR_ICRLO) & ~0xcdfff; v |= (APIC_DEST_DEST << APIC_ICRLO_DEST_OFFSET) | (trigger << APIC_ICRLO_TRIGGER_OFFSET) | (level << APIC_ICRLO_LEVEL_OFFSET) | (mode << APIC_ICRLO_DELMODE_OFFSET) | (vector); APIC_WRITE(APICR_ICRLO, v); } // Silly way of busywaiting, but we don't have a timer void delay(unsigned us) { unsigned freq = 1000; // in MHz, assume 1GHz CPU speed uint64_t cycles = us * freq; uint64_t t0 = RDTSC(); uint64_t t1; volatile unsigned k; do { for (k = 0; k < 1000; k++) continue; t1 = RDTSC(); } while (t1 - t0 < cycles); } static inline void memset (void *dst, char value, int len) { int i; for (i = 0 ; i < len ; i++ ) { *((char *) dst + i) = value; } } void kick_cpu(unsigned cpu_num) { unsigned num_sipi, apic_id; apic_id = cpu_num_to_apic_id[cpu_num]; // clear the APIC ESR register APIC_WRITE(APICR_ESR, 0); APIC_READ(APICR_ESR); // asserting the INIT IPI SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); delay(100000 / DELAY_FACTOR); // de-assert the INIT IPI SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); for (num_sipi = 0; num_sipi < 2; num_sipi++) { unsigned timeout; bool send_pending; unsigned err; APIC_WRITE(APICR_ESR, 0); SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (uint32_t)startup_32 >> 12); timeout = 0; do { delay(10); timeout++; send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; } while (send_pending && timeout < 1000); if (send_pending) { //cprint(LINE_STATUS+1, 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); } } } // These memory locations are used for the trampoline code and data. #define BOOTCODESTART 0x9000 #define GDTPOINTERADDR 0x9100 #define GDTADDR 0x9110 void boot_ap(unsigned cpu_num) { unsigned num_sipi, apic_id; extern uint8_t gdt; extern uint8_t _ap_trampoline_start; extern uint8_t _ap_trampoline_protmode; unsigned len = &_ap_trampoline_protmode - &_ap_trampoline_start; apic_id = cpu_num_to_apic_id[cpu_num]; memcpy((uint8_t*)BOOTCODESTART, &_ap_trampoline_start, len); // Fixup the LGDT instruction to point to GDT pointer. PUT_MEM16(BOOTCODESTART + 3, GDTPOINTERADDR); // Copy a pointer to the temporary GDT to addr GDTPOINTERADDR. // The temporary gdt is at addr GDTADDR PUT_MEM16(GDTPOINTERADDR, 4 * 8); PUT_MEM32(GDTPOINTERADDR + 2, GDTADDR); // Copy the first 4 gdt entries from the currently used GDT to the // temporary GDT. memcpy((uint8_t *)GDTADDR, &gdt, 32); // clear the APIC ESR register APIC_WRITE(APICR_ESR, 0); APIC_READ(APICR_ESR); // asserting the INIT IPI SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); delay(100000 / DELAY_FACTOR); // de-assert the INIT IPI SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); for (num_sipi = 0; num_sipi < 2; num_sipi++) { unsigned timeout; bool send_pending; unsigned err; APIC_WRITE(APICR_ESR, 0); SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, BOOTCODESTART >> 12); timeout = 0; do { delay(10); timeout++; send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; } while (send_pending && timeout < 1000); if (send_pending) { //cprint(LINE_STATUS+1, 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); } } } void smp_init_bsp() { 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); 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) { /* * 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 (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"); } } /* if (fp == NULL) { cprint(LINE_STATUS+1,0,"SMP: No floating pointer structure found"); } */ } void smp_init_aps() { int cpuNum; for(cpuNum = 0 ; cpuNum < MAX_CPUS ; cpuNum++) { AP[cpuNum].started = FALSE; } } unsigned my_apic_id() { return (APIC[APICR_ID][0]) >> 24; } void smp_ap_booted(unsigned cpu_num) { AP[cpu_num].started = TRUE; } void smp_boot_ap(unsigned cpu_num) { unsigned timeout; extern bool smp_mode; boot_ap(cpu_num); timeout = 0; do { delay(1000 / DELAY_FACTOR); timeout++; } 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; } } unsigned smp_num_cpus() { return number_of_cpus; } unsigned smp_my_cpu_num() { unsigned apicid = my_apic_id(); unsigned i; for (i = 0; i < MAX_CPUS; i++) { if (apicid == cpu_num_to_apic_id[i]) { break; } } if (i == MAX_CPUS) { i = 0; } return i; } volatile spinlock_t barr_lk={1}; void barrier(volatile int *barr, int n) { spin_lock(&barr_lk); barr++; spin_unlock(&barr_lk); while((uint32_t)barrclks_msec); t += (l / v->clks_msec); /* Is the time up? */ if (t >= msec) { cprint(18, 22, " "); break; } /* Is expected Scan code pressed? */ c = get_key(); c &= 0x7f; if(c == scs) { fail_safe = 1; cprint(18, 22, " "); break; } } } static void display_init(void) { int i; volatile char *pp; 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"); /* Clear screen & set background to blue */ for(i=0, pp=(char *)(SCREEN_ADR); i<80*24; i++) { *pp++ = ' '; *pp++ = 0x17; } /* Make the name background red */ for(i=0, pp=(char *)(SCREEN_ADR+1); itest = 0; v->pass = 0; v->msg_line = 0; v->ecount = 0; v->ecc_ecount = 0; v->testsel = -1; v->msg_line = LINE_SCROLL-1; v->scroll_start = v->msg_line * 160; v->erri.low_addr.page = 0x7fffffff; v->erri.low_addr.offset = 0xfff; v->erri.high_addr.page = 0; v->erri.high_addr.offset = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.maxl = 0; v->erri.cor_err = 0; v->erri.ebits = 0; v->erri.hdr_flag = 0; v->erri.tbits = 0; for (i=0; tseq[i].msg != 0; i++) { tseq[i].errors = 0; } if (dmi_initialized) { for (i=0; i < MAX_DMI_MEMDEVS; i++){ if (dmi_err_cnts[i] > 0) { dmi_err_cnts[i] = 0; } } } cprint(LINE_CPU+1, 0, "L1 Cache: Unknown "); cprint(LINE_CPU+2, 0, "L2 Cache: Unknown "); 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 : "); cpu_type(); /* Check fail safe */ failsafe(2000, 0x3B); /* Find the memory controller */ find_controller(); /* Find Memory Specs */ if(fail_safe == 0) { get_spd_spec(); } if (v->rdtsc) { cacheable(); cprint(LINE_TIME, COL_TIME+4, ": :"); } 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, " -----------------------------------------------------------------------------"); for(i=0; i < 5; i++) { cprint(i, COL_MID-2, "| "); } footer(); // Default Print Mode // v->printmode=PRINTMODE_SUMMARY; 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) { 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; } 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); } return result; } void *emapping(unsigned long page_addr) { void *result; result = mapping(page_addr -1); /* The result needs to be 256 byte alinged... */ result = ((unsigned char *)result) + 0xf00; return result; } unsigned long page_of(void *addr) { 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; } /* * Find CPU type and cache sizes */ 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; } 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]) { /* AMD Processors */ case 'A': switch(cpu_id.type) { case 4: switch(cpu_id.model) { case 3: cprint(LINE_CPU, 0, "AMD 486DX2"); break; case 7: cprint(LINE_CPU, 0, "AMD 486DX2-WB"); break; case 8: cprint(LINE_CPU, 0, "AMD 486DX4"); break; case 9: cprint(LINE_CPU, 0, "AMD 486DX4-WB"); break; case 14: cprint(LINE_CPU, 0, "AMD 5x86-WT"); break; } /* Since we can't get CPU speed or cache info return */ return; case 5: switch(cpu_id.model) { case 0: case 1: case 2: case 3: cprint(LINE_CPU, 0, "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]; 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]; 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]; 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]; break; } break; case 6: switch(cpu_id.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]; 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]; 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)"); } else { cprint(LINE_CPU, 0, "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)"); } else { cprint(LINE_CPU, 0, "Athlon XP (0.13)"); } off = 16; break; case 3: case 7: cprint(LINE_CPU, 0, "AMD Duron"); off = 9; /* Duron stepping 0 CPUID for L2 is broken */ /* (AMD errata T13)*/ if (cpu_id.step == 0) { /* stepping 0 */ /* Hard code the right 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; } } 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; } 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]; } 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; } /* 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: l1_cache = 8; break; case 0x8: case 0xc: case 0x67: case 0x60: 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; } } // 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) { 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; } 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; } } 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; } 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; } 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){ case 5: cprint(LINE_CPU, 0, "Centaur 5x86"); off = 12; 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; } } } else { /* CyrixInstead */ switch(cpu_id.type) { case 5: switch(cpu_id.model) { case 0: cprint(LINE_CPU, 0, "Cyrix 6x86MX/MII"); off = 16; break; case 4: cprint(LINE_CPU, 0, "Cyrix GXm"); off = 9; break; } return; case 6: // VIA C3 switch(cpu_id.model) { case 6: cprint(LINE_CPU, 0, "Cyrix III"); off = 9; break; case 7: if (cpu_id.step < 8) { cprint(LINE_CPU, 0, "VIA C3 Samuel2"); off = 14; } else { cprint(LINE_CPU, 0, "VIA C3 Ezra-T"); off = 13; } break; case 8: cprint(LINE_CPU, 0, "VIA C3 Ezra-T"); off = 13; break; case 9: cprint(LINE_CPU, 0, "VIA C3 Nehemiah"); off = 15; break; } // L1 = L2 = 64 KB from Cyrix III to Nehemiah l1_cache = 64; l2_cache = 64; break; } } break; /* Unknown processor */ default: off = 3; /* Make a guess at the family */ switch(cpu_id.type) { case 5: cprint(LINE_CPU, 0, "586"); return; case 6: cprint(LINE_CPU, 0, "686"); return; } } /* We are here only if the CPU type supports the rdtsc instruction */ /* Print CPU speed */ if ((speed = cpuspeed()) > 0) { if (speed < 1000000-50) { 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); } else { speed += 500; /* for rounding */ cprint(LINE_CPU, off, " MHz"); dprint(LINE_CPU, off, speed/1000, 5, 0); } extclock = speed; } /* Print out L1 cache info */ /* 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); } } /* Print out L2 cache info */ /* We measure the L2 cache speed by using a block size that is */ /* 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); 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); } } /* 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; 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); } } /* 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 ((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); } /* #define TICKS 5 * 11832 (count = 6376)*/ /* #define TICKS (65536 - 12752) */ /* #define TICKS (65536 - 8271) */ #define TICKS 59659 /* Program counter to 50 ms = 59659 clks */ /* Returns CPU clock in khz */ static int cpuspeed(void) { int loops; /* Setup timer */ outb((inb(0x61) & ~0x02) | 0x01, 0x61); outb(0xb0, 0x43); outb(TICKS & 0xff, 0x42); outb(TICKS >> 8, 0x42); asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); loops = 0; do { loops++; } while ((inb(0x61) & 0x20) == 0); asm __volatile__ ( "rdtsc\n\t" \ "subl st_low,%%eax\n\t" \ "sbbl st_high,%%edx\n\t" \ :"=a" (end_low), "=d" (end_high) ); /* Make sure we have a credible result */ if (loops < 4 || end_low < 50000) { return(-1); } if(tsc_invariable){ end_low = correct_tsc(end_low); } v->clks_msec = end_low/50; return(v->clks_msec); } /* Measure cache/memory speed by copying a block of memory. */ /* Returned value is kbytes/second */ ulong memspeed(ulong src, ulong len, int iter, int type) { ulong dst; ulong wlen; int i; dst = src + len; wlen = len / 4; /* Length is bytes */ /* Calibrate the overhead with a zero word copy */ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; iclks_msec)/end_low); } ulong correct_tsc(ulong el_org) { float coef_now, coef_max; int msr_lo, msr_hi, is_xe; rdmsr(0x198, msr_lo, msr_hi); is_xe = (msr_lo >> 31) & 0x1; if(is_xe){ rdmsr(0x198, msr_lo, msr_hi); coef_max = ((msr_hi >> 8) & 0x1F); if ((msr_hi >> 14) & 0x1) { coef_max = coef_max + 0.5f; } } else { rdmsr(0x17, msr_lo, msr_hi); coef_max = ((msr_lo >> 8) & 0x1F); if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; } } if((cpu_id.feature_flag >> 7) & 1) { rdmsr(0x198, msr_lo, msr_hi); coef_now = ((msr_lo >> 8) & 0x1F); if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; } } else { rdmsr(0x2A, msr_lo, msr_hi); coef_now = (msr_lo >> 22) & 0x1F; } if(coef_max && coef_now) { el_org = (ulong)(el_org * coef_now / coef_max); } return el_org; } memtest86+-4.20/defs.h0000644000000000000000000000173511517067470013154 0ustar rootroot/* defs.h - MemTest-86 assembler/compiler definitions * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com */ #define SETUPSECS 4 /* Number of setup sectors */ /* * Caution!! There is magic in the build process. Read * 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 BOOTSEG 0x07c0 /* Segment adrs for inital boot */ #define INITSEG 0x9000 /* Segment adrs for relocated boot */ #define SETUPSEG (INITSEG+0x20) /* Segment adrs for relocated setup */ #define TSTLOAD 0x1000 /* Segment adrs for load of test */ #define KERNEL_CS 0x10 /* 32 bit segment adrs for code */ #define KERNEL_DS 0x18 /* 32 bit segment adrs for data */ #define REAL_CS 0x20 /* 16 bit segment adrs for code */ #define REAL_DS 0x28 /* 16 bit segment adrs for data */ memtest86+-4.20/stdint.h0000644000000000000000000000264611517067470013542 0ustar rootroot#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; typedef char bool; #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #endif /* I386_STDINT_H */ memtest86+-4.20/head.S0000644000000000000000000005440611517067470013112 0ustar rootroot/* * linux/boot/head.S * Copyright (C) 1991, 1992 Linus Torvalds */ /* * head.S contains the 32-bit startup code. * * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for MemTest-86. * Setup the memory management for flat non-paged linear addressing. * 17 May 2004 : Added X86_PWRCAP for AMD64 (Memtest86+ - Samuel D.) */ .text #define __ASSEMBLY__ #include "defs.h" #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 */ testl %esp, %esp jnz 0f movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp leal stack_top@GOTOFF(%esp), %esp 0: /* Load the GOT pointer */ call 0f 0: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx /* Pick the appropriate stack address */ leal stack_top@GOTOFF(%ebx), %esp /* Reload all of the segment registers */ leal gdt@GOTOFF(%ebx), %eax movl %eax, 2 + gdt_descr@GOTOFF(%ebx) lgdt gdt_descr@GOTOFF(%ebx) leal flush@GOTOFF(%ebx), %eax pushl $KERNEL_CS pushl %eax lret flush: movl $KERNEL_DS, %eax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* * Zero BSS */ cmpl $1, zerobss@GOTOFF(%ebx) jnz zerobss_done xorl %eax, %eax leal _bss@GOTOFF(%ebx), %edi leal _end@GOTOFF(%ebx), %ecx subl %edi, %ecx 1: movl %eax, (%edi) addl $4, %edi subl $4, %ecx jnz 1b movl $0, zerobss@GOTOFF(%ebx) zerobss_done: /* * 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 */ leal idt@GOTOFF(%ebx), %edi leal vec0@GOTOFF(%ebx), %edx movl $(KERNEL_CS << 16),%eax movw %dx, %ax /* selector = 0x0010 = cs */ movw $0x8E00, %dx /* interrupt gate - dpl=0, present */ movl %eax, (%edi) movl %edx, 4(%edi) addl $8, %edi leal vec1@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec2@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec3@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec4@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec5@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec6@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec7@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec8@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec9@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec10@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec11@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec12@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec13@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec14@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec15@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec16@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec17@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec18@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec19@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi /* Now that it is initialized load the interrupt descriptor table */ leal idt@GOTOFF(%ebx), %eax 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 # # CDH start # Check FPU, initialize if present # testl $1, %edx # FPU available? jz no_fpu 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 */ leal _dl_start@GOTOFF(%ebx), %eax call *%eax call do_test /* In case we return simulate an exception */ pushfl pushl %cs call 0f 0: pushl $0 /* error code */ pushl $257 /* vector */ jmp int_hand vec0: pushl $0 /* error code */ pushl $0 /* vector */ jmp int_hand vec1: pushl $0 /* error code */ pushl $1 /* vector */ jmp int_hand vec2: pushl $0 /* error code */ pushl $2 /* vector */ jmp int_hand vec3: pushl $0 /* error code */ pushl $3 /* vector */ jmp int_hand vec4: pushl $0 /* error code */ pushl $4 /* vector */ jmp int_hand vec5: pushl $0 /* error code */ pushl $5 /* vector */ jmp int_hand vec6: pushl $0 /* error code */ pushl $6 /* vector */ jmp int_hand vec7: pushl $0 /* error code */ pushl $7 /* vector */ jmp int_hand vec8: /* error code */ pushl $8 /* vector */ jmp int_hand vec9: pushl $0 /* error code */ pushl $9 /* vector */ jmp int_hand vec10: /* error code */ pushl $10 /* vector */ jmp int_hand vec11: /* error code */ pushl $11 /* vector */ jmp int_hand vec12: /* error code */ pushl $12 /* vector */ jmp int_hand vec13: /* error code */ pushl $13 /* vector */ jmp int_hand vec14: /* error code */ pushl $14 /* vector */ jmp int_hand vec15: pushl $0 /* error code */ pushl $15 /* vector */ jmp int_hand vec16: pushl $0 /* error code */ pushl $16 /* vector */ jmp int_hand vec17: /* error code */ pushl $17 /* vector */ jmp int_hand vec18: pushl $0 /* error code */ pushl $18 /* vector */ jmp int_hand vec19: pushl $0 /* error code */ pushl $19 /* vector */ jmp int_hand int_hand: pushl %eax pushl %ebx pushl %ecx pushl %edx pushl %edi pushl %esi pushl %ebp /* original stack pointer */ leal 20(%esp), %eax pushl %eax pushl %esp /* pointer to structure on the stack */ call inter addl $8, %esp popl %ebp popl %esi popl %edi popl %edx popl %ecx popl %ebx popl %eax iret /* * The interrupt descriptor table has room for 32 idt's */ .align 4 .word 0 idt_descr: .word 20*8-1 # idt contains 32 entries .long 0 idt: .fill 20,8,0 # idt is uninitialized gdt_descr: .word gdt_end - gdt - 1 .long 0 .align 4 .globl gdt, gdt_end gdt: .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* not used */ .quad 0x00cf9a000000ffff /* 0x10 main 4gb code at 0x000000 */ .quad 0x00cf92000000ffff /* 0x18 main 4gb data at 0x000000 */ .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .byte 0x00, 0x9b # code read/exec/accessed .byte 0x00, 0x00 # granularity = bytes .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .byte 0x00, 0x93 # data read/write/accessed .byte 0x00, 0x00 # granularity = bytes gdt_end: .data .macro ptes64 start, count=64 .quad \start + 0x0000000 + 0xE3 .quad \start + 0x0200000 + 0xE3 .quad \start + 0x0400000 + 0xE3 .quad \start + 0x0600000 + 0xE3 .quad \start + 0x0800000 + 0xE3 .quad \start + 0x0A00000 + 0xE3 .quad \start + 0x0C00000 + 0xE3 .quad \start + 0x0E00000 + 0xE3 .if \count-1 ptes64 "(\start+0x01000000)",\count-1 .endif .endm .macro maxdepth depth=1 .if \depth-1 maxdepth \depth-1 .endif .endm maxdepth .balign 4096 .globl pd0 pd0: ptes64 0x0000000000000000 .balign 4096 .globl pd1 pd1: ptes64 0x0000000040000000 .balign 4096 .globl pd2 pd2: ptes64 0x0000000080000000 .balign 4096 .globl pd3 pd3: ptes64 0x00000000C0000000 .balign 4096 .globl pdp pdp: .long pd0 + 1 .long 0 .long pd1 + 1 .long 0 .long pd2 + 1 .long 0 .long pd3 + 1 .long 0 .previous #define RSTART startup_32 .globl query_pcbios query_pcbios: /* Save the caller save registers */ pushl %ebx pushl %esi pushl %edi pushl %ebp call 1f 1: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* Compute the reloc address */ leal RSTART@GOTOFF(%ebx), %esi /* Fixup real code pointer */ movl %esi, %eax shrl $4, %eax movw %ax, 2 + realptr@GOTOFF(%ebx) /* Fixup protected code pointer */ leal prot@GOTOFF(%ebx), %eax movl %eax, protptr@GOTOFF(%ebx) /* Compute the gdt fixup */ movl %esi, %eax shll $16, %eax # Base low movl %esi, %ecx shrl $16, %ecx andl $0xff, %ecx movl %esi, %edx andl $0xff000000, %edx orl %edx, %ecx /* Fixup the gdt */ andl $0x0000ffff, REAL_CS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_CS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_CS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_CS + 4 + gdt@GOTOFF(%ebx) andl $0x0000ffff, REAL_DS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_DS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_DS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_DS + 4 + gdt@GOTOFF(%ebx) /* Fixup the gdt_descr */ leal gdt@GOTOFF(%ebx), %eax movl %eax, 2 + gdt_descr@GOTOFF(%ebx) lidt idt_real@GOTOFF(%ebx) /* Don't disable the a20 line */ /* Load 16bit data segments, to ensure the segment limits are set */ movl $REAL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs /* Compute the stack base */ leal stack@GOTOFF(%ebx), %ecx /* Compute the address of meminfo */ leal mem_info@GOTOFF(%ebx), %edi /* switch to 16bit mode */ ljmp $REAL_CS, $1f - RSTART 1: .code16 /* Disable Paging and protected mode */ /* clear the PG & PE bits of CR0 */ movl %cr0,%eax andl $~((1 << 31)|(1<<0)),%eax movl %eax,%cr0 /* make intersegment jmp to flush the processor pipeline * and reload %cs:%eip (to clear upper 16 bits of %eip). */ ljmp *(realptr - RSTART) real: /* we are in real mode now * set up the real mode segment registers : %ds, %ss, %es, %gs, %fs */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* Adjust the stack pointer */ movl %ecx, %eax shrl $4, %eax movw %ax, %ss subl %ecx, %esp /* Save my base pointer */ pushl %ebx /* Setup %ds to point to my data area */ shrl $4, %edi movl %edi, %ds /* Enable interrupts or BIOS's go crazy */ sti # Get memory size (extended mem, kB) #define SMAP 0x534d4150 xorl %eax, %eax movl %eax, (E88) movl %eax, (E801) movl %eax, (E820NR) # Try three different memory detection schemes. First, try # e820h, which lets us assemble a memory map, then try e801h, # which returns a 32-bit memory size, and finally 88h, which # returns 0-64m # method E820H: # the memory map from hell. e820h returns memory classified into # a whole bunch of different types, and allows memory holes and # everything. We scan through this memory map and build a list # of the first 32 memory areas, which we return at [E820MAP]. # This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm meme820: xorl %ebx, %ebx # continuation counter movw $E820MAP, %di # point into the whitelist # so we can have the bios # directly write into it. jmpe820: movl $0x0000e820, %eax # e820, upper word zeroed movl $SMAP, %edx # ascii 'SMAP' movl $20, %ecx # size of the e820rec pushw %ds # data record. popw %es int $0x15 # make the call jc bail820 # fall to e801 if it fails cmpl $SMAP, %eax # check the return is `SMAP' jne bail820 # fall to e801 if it fails # cmpl $1, 16(%di) # is this usable memory? # jne again820 # If this is usable memory, we save it by simply advancing %di by # sizeof(e820rec). # good820: movb (E820NR), %al # up to 32 entries cmpb $E820MAX, %al jnl bail820 incb (E820NR) movw %di, %ax addw $E820ENTRY_SIZE, %ax movw %ax, %di again820: cmpl $0, %ebx # check to see if jne jmpe820 # %ebx is set to EOF bail820: # method E801H: # memory size is in 1k chunksizes, to avoid confusing loadlin. # we store the 0xe801 memory size in a completely different place, # because it will most likely be longer than 16 bits. meme801: stc # fix to work around buggy xorw %cx,%cx # BIOSes which dont clear/set xorw %dx,%dx # carry on pass/error of # e801h memory size call # or merely pass cx,dx though # without changing them. movw $0xe801, %ax int $0x15 jc mem88 cmpw $0x0, %cx # Kludge to handle BIOSes jne e801usecxdx # which report their extended cmpw $0x0, %dx # memory in AX/BX rather than jne e801usecxdx # CX/DX. The spec I have read movw %ax, %cx # seems to indicate AX/BX movw %bx, %dx # are more reasonable anyway... e801usecxdx: andl $0xffff, %edx # clear sign extend shll $6, %edx # and go from 64k to 1k chunks movl %edx, (E801) # store extended memory size andl $0xffff, %ecx # clear sign extend addl %ecx, (E801) # and add lower memory into # total size. # Ye Olde Traditional Methode. Returns the memory size (up to 16mb or # 64mb, depending on the bios) in ax. mem88: movb $0x88, %ah int $0x15 movw %ax, (E88) #ifdef APM_OFF # check for APM BIOS movw $0x5300, %ax # APM BIOS installation check xorw %bx, %bx int $0x15 jc done_apm_bios # error -> no APM BIOS cmpw $0x504d, %bx # check for "PM" signature jne done_apm_bios # no signature -> no APM BIOS movw $0x5304, %ax # Disconnect first just in case xorw %bx, %bx int $0x15 # ignore return code movw $0x5301, %ax # Real Mode connect xorw %bx, %bx int $0x15 jc done_apm_bios # error movw $0x5308, %ax # Disable APM mov $0xffff, %bx xorw %cx, %cx int $0x15 done_apm_bios: #endif /* O.k. the BIOS query is done switch back to protected mode */ cli /* Restore my saved variables */ popl %ebx /* Get an convinient %ds */ movw %cs, %ax movw %ax, %ds /* Load the global descriptor table */ addr32 lgdt gdt_descr - RSTART /* Turn on protected mode */ /* Set the PE bit in CR0 */ movl %cr0,%eax orl $(1<<0),%eax movl %eax,%cr0 /* flush the prefetch queue, and relaod %cs:%eip */ data32 ljmp *(protptr - RSTART) prot: .code32 /* Reload other segment registers */ movl $KERNEL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %fs movl %eax, %gs movl %eax, %ss /* Adjust the stack pointer */ leal stack@GOTOFF(%ebx), %eax addl %eax, %esp /* Restore the caller saved registers */ popl %ebp popl %edi popl %esi popl %ebx movl $1, %eax ret realptr: .word real - RSTART .word 0x0000 protptr: .long 0 .long KERNEL_CS idt_real: .word 0x400 - 1 # idt limit ( 256 entries) .word 0, 0 # idt base = 0L .data zerobss: .long 1 clear_display: .long 1 .previous .data .balign 16 .globl mem_info mem_info: . = . + MEMINFO_SIZE .previous .bss .balign 16 stack: . = . + 8192 stack_top: .previous memtest86+-4.20/bootsect.S0000644000000000000000000002004211517067470014020 0ustar rootroot/* * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds * * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves * itself out of the way to address 0x90000, and jumps there. * * It then loads 'setup' directly after itself (0x90200), and the system * at 0x10000, using BIOS interrupts. * * The loader has been made as simple as possible, and continuos * read errors will result in a unbreakable loop. Reboot by hand. It * loads pretty fast by getting whole tracks at a time whenever possible. * * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86. */ #include "defs.h" ROOT_DEV = 0 .code16 .section ".bootsect", "ax", @progbits _boot: # ld86 requires an entry symbol. This may as well be the usual one. .globl _main _main: movw $BOOTSEG, %ax movw %ax, %ds movw $INITSEG, %ax movw %ax, %es movw $256, %cx subw %si, %si subw %di, %di cld rep movsw ljmp $INITSEG, $go - _boot go: movw %cs, %ax movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of # bootsect + length of setup + room for stack # 12 is disk parm size # bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We # wouldn't have to worry about this if we checked the top of memory. Also # my BIOS can be configured to put the wini drive tables in high memory # instead of in the vector table. The old stack might have clobbered the # drive table. movw %ax, %ds movw %ax, %es movw %ax, %ss # put stack at INITSEG:0x4000-12. movw %dx, %sp /* * Many BIOS's default disk parameter tables will not * recognize multi-sector reads beyond the maximum sector number * specified in the default diskette parameter tables - this may * mean 7 sectors in some cases. * * Since single sector reads are slow and out of the question, * we must take care of this by creating new parameter tables * (for the first disk) in RAM. We will set the maximum sector * count to 18 - the most we will encounter on an HD 1.44. * * High doesn't hurt. Low does. * * Segments are as follows: ds=es=ss=cs - INITSEG, * fs = 0, gs = parameter table segment */ pushw $0 popw %fs movw $0x78, %bx # fs:bx is parameter table address lgs %fs:(%bx),%si # gs:si is source movw %dx, %di # es:di is destination movw $6, %cx # copy 12 bytes cld rep movsw %gs:(%si), (%di) movw %dx, %di movb $18, 4(%di) # patch sector count movw %di, %fs:(%bx) movw %es, %fs:2(%bx) movw %cs, %ax movw %ax, %fs movw %ax, %gs xorb %ah, %ah # reset FDC xorb %dl, %dl int $0x13 # load the setup-sectors directly after the bootblock. # Note that 'es' is already set up. load_setup: xorw %dx, %dx # drive 0, head 0 movw $0x0002, %cx # sector 2, track 0 movw $0x0200, %bx # address = 512, in INITSEG movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors # (assume all on head 0, track 0) int $0x13 # read it jnc ok_load_setup # ok - continue pushw %ax # dump error code call print_nl movw %sp, %bp call print_hex popw %ax xorb %dl, %dl # reset FDC xorb %ah, %ah int $0x13 jmp load_setup ok_load_setup: # Get disk drive parameters, specifically nr of sectors/track /* It seems that there is no BIOS call to get the number of sectors. Guess * 18 sectors if sector 18 can be read, 15 if sector 15 can be read. * Otherwise guess 9 */ xorw %dx, %dx # drive 0, head 0 movw $0x0012, %cx # sector 18, track 0 movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs) movw $0x0201, %ax # service 2, 1 sector int $0x13 jnc got_sectors movb $0x0f, %cl # sector 15 movw $0x0201, %ax # service 2, 1 sector int $0x13 jnc got_sectors movb $0x09, %cl got_sectors: movw %cx, %cs:sectors - _boot movw $INITSEG, %ax movw %ax, %es # Print some inane message movb $0x03, %ah # read cursor pos xorb %bh, %bh int $0x10 movw $9, %cx movw $0x0007, %bx # page 0, attribute 7 (normal) movw $msg1 - _boot, %bp movw $0x1301, %ax # write string, move cursor int $0x10 # ok, we've written the message, now # we want to load the system (at 0x10000) movw $TSTLOAD, %ax movw %ax, %es # segment of 0x010000 call read_it call kill_motor call turnoffcursor call print_nl # after that (everyting loaded), we jump to # the setup-routine loaded directly after # the bootblock: ljmp $SETUPSEG,$0 # This routine loads the system at address 0x10000, making sure # no 64kB boundaries are crossed. We try to load it as fast as # possible, loading whole tracks whenever we can. # # in: es - starting address segment (normally 0x1000) # sread: .word 1+SETUPSECS # sectors read of current track head: .word 0 # current head track: .word 0 # current track read_it: movw %es, %ax testw $0x0fff, %ax die: jne die # es must be at 64kB boundary xorw %bx,%bx # bx is starting address within segment rp_read: movw %es, %ax subw $TSTLOAD, %ax # have we loaded all yet? cmpw syssize - _boot, %ax jbe ok1_read ret ok1_read: movw %cs:sectors - _boot, %ax subw sread - _boot, %ax movw %ax, %cx shlw $9, %cx addw %bx, %cx jnc ok2_read je ok2_read xorw %ax, %ax subw %bx, %ax shrw $9, %ax ok2_read: call read_track movw %ax, %cx add sread - _boot, %ax cmpw %cs:sectors - _boot, %ax jne ok3_read movw $1, %ax subw head - _boot, %ax jne ok4_read incw track - _boot ok4_read: movw %ax, head - _boot xorw %ax, %ax ok3_read: movw %ax, sread - _boot shlw $9, %cx addw %cx, %bx jnc rp_read movw %es, %ax addb $0x10, %ah movw %ax, %es xorw %bx, %bx jmp rp_read read_track: pusha pusha movw $0xe2e, %ax # loading... message 2e = . movw $7, %bx int $0x10 popa movw track - _boot, %dx movw sread - _boot, %cx incw %cx movb %dl, %ch movw head - _boot, %dx movb %dl, %dh andw $0x0100, %dx movb $2, %ah pushw %dx # save for error dump pushw %cx pushw %bx pushw %ax int $0x13 jc bad_rt addw $8, %sp popa ret bad_rt: pushw %ax # save error code call print_all # ah = error, al = read xorb %ah, %ah xorb %dl, %dl int $0x13 addw $10, %sp popa jmp read_track /* * print_all is for debugging purposes. * It will print out all of the registers. The assumption is that this is * called from a routine, with a stack frame like * dx * cx * bx * ax * error * ret <- sp * */ print_all: movw $5, %cx # error code + 4 registers movw %sp, %bp print_loop: pushw %cx # save count left call print_nl # nl for readability cmpb 5, %cl # see if register name is needed jae no_reg movw $(0xe05 + 'A' - 1), %ax subb %cl, %al int $0x10 movb $'X', %al int $0x10 movb $':', %al int $0x10 no_reg: addw $2, %bp # next register call print_hex # print it popw %cx loop print_loop ret print_nl: movw $0xe0d, %ax # CR int $0x10 movb $0x0a, %al # LF int $0x10 ret /* * print_hex is for debugging purposes, and prints the word * pointed to by ss:bp in hexadecmial. */ print_hex: movw $4, %cx # 4 hex digits movw (%bp), %dx # load word into dx print_digit: rolw $4, %dx # rotate so that lowest 4 bits are used movb $0xe, %ah movb %dl, %al # mask off so we have only next nibble andb $0xf, %al addb $'0', %al # convert to 0-based digit cmpb $'9', %al # check for overflow jbe good_digit addb $('A' - '0' - 10), %al good_digit: int $0x10 loop print_digit ret /* * This procedure turns off the floppy drive motor, so * that we enter the kernel in a known state, and * don't have to worry about it later. */ kill_motor: pushw %dx movw $0x3f2, %dx xorb %al, %al outb %al, %dx popw %dx ret turnoffcursor: movb $0x01, %ah # turn off the cursor movb $0x00, %bh movw $0x2000, %cx int $0x10 ret sectors: .word 0 msg1: .byte 13,10 .ascii "Loading" .org 497 setup_sects: .byte SETUPSECS .org 500 syssize: .word _syssize .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xAA55 _eboot: memtest86+-4.20/test.c0000644000000000000000000007016111517067470013204 0ustar rootroot /* test.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- * MemTest86+ V3.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #include "test.h" #include "config.h" #include #include "dmi.h" #include extern int segs, bail; extern volatile ulong *p; extern ulong p1, p2; extern int test_ticks, nticks; extern struct tseq tseq[]; extern void update_err_counts(void); extern void print_err_counts(void); void poll_errors(); int ecount = 0; static inline ulong roundup(ulong value, ulong mask) { return (value + mask) & ~mask; } /* * Memory address test, walking ones */ void addr_tst1() { int i, j, k; volatile ulong *pt; volatile ulong *end; ulong bad, mask, bank; /* Test the global address bits */ for (p1=0, j=0; j<2; j++) { 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; for (i=0; i<100; i++) { mask = 4; do { pt = (ulong *)((ulong)p | mask); if ((uintptr_t)pt == (uintptr_t)p) { mask = mask << 1; continue; } if ((uintptr_t)pt >= (uintptr_t)end) { break; } *pt = p1; if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) { ad_err1((ulong *)p, (ulong *)mask, bad, ~p1); i = 1000; } mask = mask << 1; } while(mask); } do_tick(); BAILR } /* Now check the address bits in each bank */ /* If we have more than 8mb of memory then the bank size must be */ /* bigger than 256k. If so use 1mb for the bank size. */ if (v->pmap[v->msegs - 1].end > (0x800000 >> 12)) { bank = 0x100000; } else { bank = 0x40000; } for (p1=0, k=0; k<2; k++) { hprint(LINE_PAT, COL_PAT, p1); for (j=0; jmap[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) { *p = p1; p1 = ~p1; for (i=0; i<200; i++) { mask = 4; do { pt = (ulong *) ((ulong)p | mask); if ((uintptr_t)pt == (uintptr_t)p) { mask = mask << 1; continue; } if ((uintptr_t)pt >= (uintptr_t)end) { break; } *pt = p1; if ((uintptr_t)(bad = *p) != (uintptr_t)~p1) { ad_err1((ulong *)p, (ulong *)mask, bad,~p1); i = 200; } mask = mask << 1; } while(mask); } if ((uintptr_t)(p + bank/4) > (uintptr_t)p) { p += bank/4; } else { p = end; } p1 = ~p1; } } do_tick(); BAILR p1 = ~p1; } } /* * Memory address test, own address */ void addr_tst2() { int j, done; volatile ulong *pe; volatile ulong *end, *start; cprint(LINE_PAT, COL_PAT, " "); /* Write each address with it's own address */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * *p = (ulong)p; * } */ asm __volatile__ ( "jmp L90\n\t" ".p2align 4,,7\n\t" "L90:\n\t" "movl %%edi,(%%edi)\n\t" "addl $4,%%edi\n\t" "cmpl %%edx,%%edi\n\t" "jb L90\n\t" : "=D" (p) : "D" (p), "d" (pe) ); do_tick(); BAILR } while (!done); } /* Each address should have its own address */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * if((bad = *p) != (ulong)p) { * ad_err2((ulong)p, bad); * } * } */ asm __volatile__ ( "jmp L91\n\t" ".p2align 4,,7\n\t" "L91:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl %%edi,%%ecx\n\t" "jne L93\n\t" "L92:\n\t" "addl $4,%%edi\n\t" "cmpl %%edx,%%edi\n\t" "jb L91\n\t" "jmp L94\n\t" "L93:\n\t" "pushl %%edx\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" "call ad_err2\n\t" "popl %%edi\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" "jmp L92\n\t" "L94:\n\t" : "=D" (p) : "D" (p), "d" (pe) : "ecx" ); do_tick(); BAILR } while (!done); } } /* * Test all of memory using a "half moving inversions" algorithm using random * numbers and their complment as the data pattern. Since we are not able to * produce random numbers in reverse order testing is only done in the forward * direction. */ void movinvr() { int i, j, done, seed1, seed2; volatile ulong *pe; volatile ulong *start,*end; ulong num; uintptr_t seg_start; /* Initialize memory with initial sequence of random numbers. */ if (v->rdtsc) { asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2)); } else { seed1 = 521288629 + v->pass; seed2 = 362436069 - v->pass; } /* Display the current seed */ hprint(LINE_PAT, COL_PAT, seed1); rand_seed(seed1, seed2); for (j=0; jmap[j].start; end = v->map[j].end; pe = start; p = start; seg_start = (uintptr_t)p; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if (seg_start == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code */ /* for (; p < pe; p++) { *p = rand(); } */ asm __volatile__ ( "jmp L200\n\t" ".p2align 4,,7\n\t" "L200:\n\t" "call rand\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 } 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. */ for (i=0; i<2; i++) { rand_seed(seed1, seed2); for (j=0; jmap[j].start; end = v->map[j].end; pe = start; p = start; seg_start = (uintptr_t)p; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if (seg_start == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code */ /* for (; p < pe; p++) { num = rand(); if (i) { num = ~num; } if ((bad=*p) != num) { error((ulong*)p, num, bad); } *p = ~num; } */ if (i) { num = 0xffffffff; } else { num = 0; } asm __volatile__ ( "jmp L26\n\t" \ ".p2align 4,,7\n\t" \ "L26:\n\t" \ "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" \ "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" \ "L24:\n\t" \ : "=D" (p) : "D" (p), "S" (pe), "b" (num) : "eax", "ecx", "edx" ); do_tick(); BAILR } while (!done); } } } /* * 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) { int i, j, done; volatile ulong *pe; volatile ulong len; volatile ulong *start,*end; /* Display the current pattern */ hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; jmap[j].start; end = v->map[j].end; pe = start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } len = pe - p; if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * *p = p1; * } */ asm __volatile__ ( "rep\n\t" \ "stosl\n\t" : "=D" (p) : "c" (len), "0" (p), "a" (p1) ); do_tick(); BAILR } 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. */ for (i=0; imap[j].start; end = v->map[j].end; pe = start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)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; * } */ asm __volatile__ ( "jmp L2\n\t" \ ".p2align 4,,7\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" \ "jmp L4\n" \ "L3:\n\t" \ "pushl %%edx\n\t" \ "pushl %%ebx\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 %%ebx\n\t" \ "popl %%edx\n\t" \ "jmp L5\n" \ "L4:\n\t" \ : "=D" (p) : "a" (p1), "0" (p), "d" (pe), "b" (p2) : "ecx" ); do_tick(); BAILR } 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; done = 0; do { /* Check for underflow */ if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) { pe -= SPINSZ; } else { pe = start; } if ((uintptr_t)pe <= (uintptr_t)start) { pe = start; done++; } if ((uintptr_t)p == (uintptr_t)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); */ asm __volatile__ ( "addl $4, %%edi\n\t" "jmp L9\n\t" ".p2align 4,,7\n\t" "L9:\n\t" "subl $4, %%edi\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" "jmp L7\n\t" "L6:\n\t" "pushl %%edx\n\t" "pushl %%eax\n\t" "pushl %%ecx\n\t" "pushl %%ebx\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "popl %%ebx\n\t" "popl %%ecx\n\t" "popl %%eax\n\t" "popl %%edx\n\t" "jmp L10\n" "L7:\n\t" : "=D" (p) : "a" (p1), "0" (p), "d" (pe), "b" (p2) : "ecx" ); do_tick(); BAILR } while (!done); } } } void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off) { int i, j, k=0, done; volatile ulong *pe; volatile ulong *start, *end; ulong pat = 0; /* CDH start * ulong p3 = sval << 31; * CDH end */ /* Display the current pattern */ hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; jmap[j].start; end = v->map[j].end; pe = start; p = start; done = 0; k = off; pat = p1; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Do a SPINSZ section of memory */ /* Original C code replaced with hand tuned assembly code * while (p < pe) { * *p = pat; * if (++k >= 32) { * pat = lb; * k = 0; * } else { * pat = pat << 1; * pat |= sval; * } * p++; * } */ 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 */ ); do_tick(); BAILR } 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. */ for (i=0; imap[j].start; end = v->map[j].end; pe = start; p = start; done = 0; k = off; pat = p1; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * while (p < pe) { * if ((bad=*p) != pat) { * error((ulong*)p, pat, bad); * } * *p = ~pat; * if (++k >= 32) { * pat = lb; * k = 0; * } else { * 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 */ ); do_tick(); BAILR } 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 */ for (j=segs-1; j>=0; j--) { start = v->map[j].start; end = v->map[j].end; p = end -1; pe = end -1; done = 0; do { /* Check for underflow */ if ((uintptr_t)(pe - SPINSZ) < (uintptr_t)pe) { pe -= SPINSZ; } else { pe = start; } if ((uintptr_t)pe <= (uintptr_t)start) { pe = start; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * do { * if ((bad=*p) != ~pat) { * error((ulong*)p, ~pat, bad); * } * *p = pat; * if (--k <= 0) { * pat = hb; * k = 32; * } else { * 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 */ ); do_tick(); BAILR } while (!done); } } } /* * Test all of memory using modulo X access pattern. */ void modtst(int offset, int iter, ulong p1, ulong p2) { int j, k, l, done; volatile ulong *pe; volatile 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); /* Write every nth location with pattern */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start+offset; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p += MOD_SZ) { * *p = p1; * } */ asm __volatile__ ( "jmp L60\n\t" \ ".p2align 4,,7\n\t" \ "L60:\n\t" \ "movl %%eax,(%%edi)\n\t" \ "addl $80,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ "jb L60\n\t" \ : "=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; lmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; k = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p++) { * if (k != offset) { * *p = p2; * } * if (++k > MOD_SZ-1) { * k = 0; * } * } */ asm __volatile__ ( "jmp L50\n\t" \ ".p2align 4,,7\n\t" \ "L50:\n\t" \ "cmpl %%ebx,%%ecx\n\t" \ "je L52\n\t" \ "movl %%eax,(%%edi)\n\t" \ "L52:\n\t" \ "incl %%ebx\n\t" \ "cmpl $19,%%ebx\n\t" \ "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) : "D" (p), "d" (pe), "a" (p2), "b" (k), "c" (offset) ); do_tick(); BAILR } while (!done); } } /* Now check every nth location */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start+offset; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ) > (uintptr_t)pe) { pe += SPINSZ; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } /* Original C code replaced with hand tuned assembly code * for (; p < pe; p += MOD_SZ) { * if ((bad=*p) != p1) { * error((ulong*)p, p1, bad); * } * } */ asm __volatile__ ( "jmp L70\n\t" \ ".p2align 4,,7\n\t" \ "L70:\n\t" \ "movl (%%edi),%%ecx\n\t" \ "cmpl %%eax,%%ecx\n\t" \ "jne L71\n\t" \ "L72:\n\t" \ "addl $80,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ "jb L70\n\t" \ "jmp L73\n\t" \ "L71:\n\t" \ "pushl %%edx\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 %%edx\n\t" "jmp L72\n" "L73:\n\t" \ : "=D" (p) : "D" (p), "d" (pe), "a" (p1) : "ecx" ); do_tick(); BAILR } while (!done); } cprint(LINE_PAT, COL_PAT, " "); } /* * Test memory using block moves * Adapted from Robert Redelmeier's burnBX test */ void block_move(int iter) { int i, j, done; ulong len; volatile ulong p, pe, pp; volatile ulong start, end; cprint(LINE_PAT, COL_PAT-2, " "); /* Initialize memory with the initial pattern. */ for (j=0; jmap[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; pe = start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { pe += SPINSZ*4; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } len = ((ulong)pe - (ulong)p) / 64; asm __volatile__ ( "jmp L100\n\t" ".p2align 4,,7\n\t" "L100:\n\t" "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" "leal 64(%%edi), %%edi\n\t" "decl %%ecx\n\t" "jnz L100\n\t" : "=D" (p) : "D" (p), "c" (len), "a" (1) : "edx" ); do_tick(); BAILR } while (!done); } /* 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; jmap[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; pe = start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { pe += SPINSZ*4; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } pp = p + ((pe - p) / 2); len = ((ulong)pe - (ulong)p) / 8; for(i=0; imap[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; pe = start; p = start; done = 0; do { /* Check for overflow */ if ((uintptr_t)(pe + SPINSZ*4) > (uintptr_t)pe) { pe += SPINSZ*4; } else { pe = end; } if ((uintptr_t)pe >= (uintptr_t)end) { pe = end; done++; } if ((uintptr_t)p == (uintptr_t)pe) { break; } asm __volatile__ ( "jmp L120\n\t" ".p2align 4,,7\n\t" "L120:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl 4(%%edi),%%ecx\n\t" "jnz L121\n\t" "L122:\n\t" "addl $8,%%edi\n\t" "cmpl %%edx,%%edi\n\t" "jb L120\n" "jmp L123\n\t" "L121:\n\t" "pushl %%edx\n\t" "pushl 4(%%edi)\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "addl $8,%%esp\n\t" "popl %%edx\n\t" "jmp L122\n" "L123:\n\t" : "=D" (p) : "D" (p), "d" (pe) : "ecx" ); do_tick(); BAILR } while (!done); } } /* * Test memory for bit fade. */ #define STIME 5400 void bit_fade() { int j; volatile ulong *pe; volatile ulong bad; volatile ulong *start,*end; test_ticks += (STIME * 2); v->pass_ticks += (STIME * 2); /* Do -1 and 0 patterns */ p1 = 0; while (1) { /* Display the current pattern */ hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; jmap[j].start; end = v->map[j].end; pe = start; p = start; for (p=start; pmap[j].start; end = v->map[j].end; pe = start; p = start; for (p=start; pclks_msec); t += (l / v->clks_msec); } else { 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; } 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); BAILR } } } /* Beep function */ void beep(unsigned int frequency) { unsigned int count = 1193180 / frequency; // Switch on the speaker outb_p(inb_p(0x61)|3, 0x61); // Set command for counter 2, 2 byte write outb_p(0xB6, 0x43); // Select desired Hz outb_p(count & 0xff, 0x42); outb((count >> 8) & 0xff, 0x42); // Block for 100 microseconds sleep(100, 1); // Switch off the speaker outb(inb_p(0x61)&0xFC, 0x61); } memtest86+-4.20/config.c0000644000000000000000000003267611517067470013503 0ustar rootroot/* config.c - MemTest-86 Version 3.4 * * 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.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(); 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; ulong page; popup(); wait_keyup(); while(!flag) { 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"); /* Wait for key release */ /* Fooey! This nuts'es up the serial input. */ sflag = 0; switch(get_key()) { case 2: /* 1 - Test Selection */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Selection:"); 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"); if (v->testsel < 0) { cprint(POP_Y+3, POP_X+5, ">"); } else { cprint(POP_Y+5, POP_X+5, ">"); } wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Default */ if (v->testsel >= 9) { bail++; } v->testsel = -1; find_ticks_for_pass(); sflag++; cprint(LINE_INFO, COL_TST, "Std"); break; case 3: /* Skip test */ bail++; sflag++; break; case 4: /* Select test */ popclear(); 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; } 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; } 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; } v->testsel = 9+1; find_ticks_for_pass(); sflag++; bail++; cprint(LINE_INFO, COL_TST, "#"); dprint(LINE_INFO, COL_TST+1, 10, 3, 1); break; */ case 11: case 57: sflag++; break; } } popclear(); break; case 3: /* 2 - Address Range */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Address Range:"); 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"); wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Lower Limit */ popclear(); cprint(POP_Y+2, POP_X+4, "Lower Limit: "); cprint(POP_Y+4, POP_X+4, "Current: "); aprint(POP_Y+4, POP_X+13, v->plim_lower); cprint(POP_Y+6, POP_X+4, "New: "); page = getval(POP_Y+6, POP_X+9, 12); if (page + 1 <= v->plim_upper) { v->plim_lower = page; v->test--; bail++; } adj_mem(); find_ticks_for_pass(); sflag++; break; case 3: /* Upper Limit */ popclear(); cprint(POP_Y+2, POP_X+4, "Upper Limit: "); cprint(POP_Y+4, POP_X+4, "Current: "); aprint(POP_Y+4, POP_X+13, v->plim_upper); cprint(POP_Y+6, POP_X+4, "New: "); page = getval(POP_Y+6, POP_X+9, 12); if (page - 1 >= v->plim_lower) { v->plim_upper = page; v->test--; bail++; } adj_mem(); 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--; bail++; adj_mem(); find_ticks_for_pass(); sflag++; break; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } 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 */ 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+3+v->printmode, POP_X+5, ">"); if (beepmode) { cprint(POP_Y+8, POP_X+5, ">"); } wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Error Summary */ v->printmode=PRINTMODE_SUMMARY; v->erri.eadr = 0; v->erri.hdr_flag = 0; sflag++; break; case 3: /* Separate Addresses */ v->printmode=PRINTMODE_ADDRESSES; v->erri.eadr = 0; v->erri.hdr_flag = 0; v->msg_line = LINE_SCROLL-1; sflag++; break; case 4: /* BadRAM Patterns */ v->printmode=PRINTMODE_PATTERNS; v->erri.hdr_flag = 0; sflag++; prt++; break; case 5: /* Error Counts Only */ v->printmode=PRINTMODE_NONE; v->erri.hdr_flag = 0; 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; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } popclear(); break; case 6: /* Display DMI Memory Info */ pop2up(); print_dmi_info(); pop2down(); break; case 7: /* 6 - ECC Polling Mode */ 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"); wait_keyup(); while(!sflag) { switch(get_key()) { case 2: set_ecc_polling(-1); sflag++; break; case 3: set_ecc_polling(1); sflag++; break; case 4: set_ecc_polling(0); sflag++; break; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } popclear(); break; case 8: wait_keyup(); restart(); break; case 9: reprint_screen = 1; flag++; break; case 10: popdown(); show_spd(); popup(); sflag++; break; case 11: case 57: case 28: /* 0/CR/SP - Continue */ flag++; break; } } popdown(); if (prt) { printpatn(); } if (reprint_screen){ tty_print_screen(); } } void popup() { int i, j; char *pp; for (i=POP_Y; iselected_pages = 0; for (i=0; i< v->msegs; i++) { /* Segment inside limits ? */ if (v->pmap[i].start >= v->plim_lower && v->pmap[i].end <= v->plim_upper) { v->selected_pages += (v->pmap[i].end - v->pmap[i].start); continue; } /* Segment starts below limit? */ if (v->pmap[i].start < v->plim_lower) { /* Also ends below limit? */ if (v->pmap[i].end < v->plim_lower) { continue; } /* Ends past upper limit? */ if (v->pmap[i].end > v->plim_upper) { v->selected_pages += v->plim_upper - v->plim_lower; } else { /* Straddles lower limit */ v->selected_pages += (v->pmap[i].end - v->plim_lower); } continue; } /* Segment ends above limit? */ if (v->pmap[i].end > v->plim_upper) { /* Also starts above limit? */ if (v->pmap[i].start > v->plim_upper) { continue; } /* Straddles upper limit */ v->selected_pages += (v->plim_upper - v->pmap[i].start); } } } /* 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(); } */ memtest86+-4.20/io.h0000644000000000000000000000660611517067470012644 0ustar rootroot#ifndef _ASM_IO_H #define _ASM_IO_H /* * This file contains the definitions for the x86 IO instructions * inb/inw/inl/outb/outw/outl and the "string versions" of the same * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" * versions of the single-IO instructions (inb_p/inw_p/..). * * This file is not meant to be obfuscating: it's just complicated * to (a) handle it all in a way that makes gcc able to optimize it * as well as possible and (b) trying to avoid writing the same thing * over and over again with slight variations and possibly making a * mistake somewhere. */ #ifdef SLOW_IO_BY_JUMPING #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") #else #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") #endif #ifdef REALLY_SLOW_IO #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } #else #define SLOW_DOWN_IO __SLOW_DOWN_IO #endif /* * Talk about misusing macros.. */ #define __OUT1(s,x) \ extern inline void __out##s(unsigned x value, unsigned short port) { #define __OUT2(s,s1,s2) \ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" #define __OUT(s,s1,x) \ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } #define __IN1(s) \ extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; #define __IN2(s,s1,s2) \ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" #define __IN(s,s1,i...) \ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ __IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } #define __OUTS(s) \ extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ { __asm__ __volatile__ ("cld ; rep ; outs" #s \ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } #define RETURN_TYPE unsigned char /* __IN(b,"b","0" (0)) */ __IN(b,"") #undef RETURN_TYPE #define RETURN_TYPE unsigned short /* __IN(w,"w","0" (0)) */ __IN(w,"") #undef RETURN_TYPE #define RETURN_TYPE unsigned int __IN(l,"") #undef RETURN_TYPE __OUT(b,"b",char) __OUT(w,"w",short) __OUT(l,,int) __OUTS(b) __OUTS(w) __OUTS(l) /* * Note that due to the way __builtin_constant_p() works, you * - 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)) : \ __outb((val),(port))) #define inb(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inbc(port) : \ __inb(port)) #define outw(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outwc((val),(port)) : \ __outw((val),(port))) #define inw(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inwc(port) : \ __inw(port)) #define outl(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outlc((val),(port)) : \ __outl((val),(port))) #define inl(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inlc(port) : \ __inl(port)) #endif memtest86+-4.20/setup.S0000644000000000000000000000633711517067470013351 0ustar rootroot/* * 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) memtest86+-4.20/patn.c0000644000000000000000000000731311517067470013166 0ustar rootroot/* Pattern extension for memtest86 * * Generates patterns for the Linux kernel's BadRAM extension that avoids * allocation of faulty pages. * * Released under version 2 of the Gnu Public License. * * By Rick van Rein, vanrein@zonnet.nl * ---------------------------------------------------- * MemTest86+ V2.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ #include "test.h" /* * DEFAULT_MASK covers a longword, since that is the testing granularity. */ #define DEFAULT_MASK ((~0L) << 2) /* extern struct vars *v; */ /* What it does: * - Keep track of a number of BadRAM patterns in an array; * - Combine new faulty addresses with it whenever possible; * - Keep masks as selective as possible by minimising resulting faults; * - Print a new pattern only when the pattern array is changed. */ #define COMBINE_MASK(a,b,c,d) ((a & b & c & d) | (~a & b & ~c & d)) /* Combine two adr/mask pairs to one adr/mask pair. */ void combine (ulong adr1, ulong mask1, ulong adr2, ulong mask2, ulong *adr, ulong *mask) { *mask = COMBINE_MASK (adr1, mask1, adr2, mask2); *adr = adr1 | adr2; *adr &= *mask; // Normalise, no fundamental need for this } /* Count the number of addresses covered with a mask. */ ulong addresses (ulong mask) { ulong ctr=1; int i=32; while (i-- > 0) { if (! (mask & 1)) { ctr += ctr; } mask >>= 1; } return ctr; } /* Count how much more addresses would be covered by adr1/mask1 when combined * with adr2/mask2. */ ulong combicost (ulong adr1, ulong mask1, ulong adr2, ulong mask2) { ulong cost1=addresses (mask1); ulong tmp, mask; combine (adr1, mask1, adr2, mask2, &tmp, &mask); return addresses (mask) - cost1; } /* Find the cheapest array index to extend with the given adr/mask pair. * Return -1 if nothing below the given minimum cost can be found. */ int cheapindex (ulong adr1, ulong mask1, ulong mincost) { int i=v->numpatn; int idx=-1; while (i-- > 0) { ulong tmpcost=combicost(v->patn[i].adr, v->patn[i].mask, adr1, mask1); if (tmpcost < mincost) { mincost=tmpcost; idx=i; } } return idx; } /* Try to find a relocation index for idx if it costs nothing. * Return -1 if no such index exists. */ int relocateidx (int idx) { ulong adr =v->patn[idx].adr; ulong mask=v->patn[idx].mask; int new; v->patn[idx].adr ^= ~0L; // Never select idx new=cheapindex (adr, mask, 1+addresses (mask)); v->patn[idx].adr = adr; return new; } /* Relocate the given index idx only if free of charge. * This is useful to combine to `neighbouring' sections to integrate. * Inspired on the Buddy memalloc principle in the Linux kernel. */ void relocateiffree (int idx) { int newidx=relocateidx (idx); if (newidx>=0) { ulong cadr, cmask; combine (v->patn [newidx].adr, v->patn[newidx].mask, v->patn [ idx].adr, v->patn[ idx].mask, &cadr, &cmask); v->patn[newidx].adr =cadr; v->patn[newidx].mask=cmask; if (idx < --v->numpatn) { v->patn[idx].adr =v->patn[v->numpatn].adr; v->patn[idx].mask=v->patn[v->numpatn].mask; } relocateiffree (newidx); } } /* Insert a single faulty address in the pattern array. * Return 1 only if the array was changed. */ int insertaddress (ulong adr) { if (cheapindex (adr, DEFAULT_MASK, 1L) != -1) return 0; if (v->numpatn < BADRAM_MAXPATNS) { v->patn[v->numpatn].adr =adr; v->patn[v->numpatn].mask=DEFAULT_MASK; v->numpatn++; relocateiffree (v->numpatn-1); } else { int idx=cheapindex (adr, DEFAULT_MASK, ~0L); ulong cadr, cmask; combine (v->patn [idx].adr, v->patn[idx].mask, adr, DEFAULT_MASK, &cadr, &cmask); v->patn[idx].adr =cadr; v->patn[idx].mask=cmask; relocateiffree (idx); } return 1; } memtest86+-4.20/lib.c0000644000000000000000000005703711517067470013002 0ustar rootroot/* lib.c - MemTest-86 Version 3.0 * * 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 */ #include "io.h" #include "serial.h" #include "test.h" #include "config.h" #include "screen_buffer.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}; #if ((115200%SERIAL_BAUD_RATE) != 0) #error Bad default baud rate #endif int serial_baud_rate = SERIAL_BAUD_RATE; unsigned char serial_parity = 0; unsigned char serial_bits = 8; char buf[18]; struct ascii_map_str { 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" }; 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 memcmp(const void *s1, const void *s2, ulong count) { const unsigned char *src1 = s1, *src2 = s2; int i; for(i = 0; i < count; i++) { if (src1[i] != src2[i]) { return (int)src1[i] - (int)src2[i]; } } 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) { res = *s1 - *s2; if (res != 0) return res; if (*s1 == '\0') return 0; ++s1, ++s2; --n; } return res; } void *memmove(void *dest, const void *src, ulong n) { long i; char *d = (char *)dest, *s = (char *)src; /* If src == dest do nothing */ if (dest < src) { for(i = 0; i < n; i++) { d[i] = s[i]; } } else if (dest > src) { for(i = n -1; i >= 0; i--) { d[i] = s[i]; } } return dest; } char toupper(char c) { if (c >= 'a' && c <= 'z') return c + 'A' -'a'; else return c; } int isdigit(char c) { return c >= '0' && c <= '9'; } int isxdigit(char c) { return isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F'); } unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { unsigned long result = 0, value; if (!base) { base = 10; if (*cp == '0') { base = 8; cp++; if (toupper(*cp) == 'X' && isxdigit(cp[1])) { cp++; base = 16; } } } else if (base == 16) { if (cp[0] == '0' && toupper(cp[1]) == 'X') cp += 2; } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { result = result*base + value; cp++; } if (endp) *endp = (char *)cp; return result; } /* * Scroll the error message area of the screen as needed * Starts at line LINE_SCROLL and ends at line 23 */ void scroll(void) { int i, j; char *s, tmp; /* Only scroll if at the bottom of the screen */ if (v->msg_line < 23) { v->msg_line++; } else { /* If scroll lock is on, loop till it is cleared */ while (slock) { check_input(); } 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); } } /* Clear the newly opened line */ s = (char *)(SCREEN_ADR + (23 * 160)); for (j=0; j<80; j++) { *s = ' '; set_scrn_buf(23, j, ' '); s += 2; } tty_print_region(LINE_SCROLL, 0, 23, 79); } } /* * Clear scroll region */ void clear_scroll(void) { int i; char *s; s = (char*)(SCREEN_ADR+LINE_HEADER*160); for(i=0; i<80*(24-LINE_HEADER); i++) { *s++ = ' '; *s++ = 0x17; } } /* * Print characters on screen */ void cprint(int y, int x, const char *text) { register int i; char *dptr; dptr = (char *)(SCREEN_ADR + (160*y) + (2*x)); for (i=0; text[i]; i++) { *dptr = text[i]; dptr += 2; } tty_print_line(y, x, text); } 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); } 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; } } /* * Print a people friendly address */ void aprint(int y, int x, ulong page) { /* page is in multiples of 4K */ if ((page << 2) < 9999) { dprint(y, x, page << 2, 4, 0); cprint(y, x+4, "K"); } else if ((page >>8) < 9999) { dprint(y, x, (page + (1 << 7)) >> 8, 4, 0); cprint(y, x+4, "M"); } else if ((page >>18) < 9999) { dprint(y, x, (page + (1 << 17)) >> 18, 4, 0); cprint(y, x+4, "G"); } else { dprint(y, x, (page + (1 << 27)) >> 28, 4, 0); cprint(y, x+4, "T"); } } /* * Print a decimal number on screen */ void dprint(int y, int x, ulong val, int len, int right) { ulong j, k; int i, flag=0; if (val > 999999999 || len > 9) { return; } for(i=0, j=1; i0; j/=10) { k = val/j; if (k > 9) { j *= 100; continue; } if (flag || k || j == 1) { buf[i++] = k + '0'; flag++; } else { buf[i++] = ' '; } val -= k * j; } } else { for(i=0; i 9) { j *= 100; len++; continue; } if (k == 0 && flag == 0) { continue; } buf[i++] = k + '0'; val -= k * j; } else { if (flag == 0 && i < len-1) { buf[i++] = '0'; } else { buf[i++] = ' '; } } flag++; } } buf[i] = 0; 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; 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; } buf[idx] = 0; cprint(y,x,buf + (idx - digits)); } /* * Print a hex number on screen exactly digits long */ void hprint3(int y,int x, unsigned long val, int digits) { unsigned long j; int i, idx, flag = 0; for (i=0, idx=0; i> 20; dprint(y, x, j, 4, 0); cprint(y, x+4, "m"); j = (val & 0xffc00) >> 10; dprint(y, x+5, j, 4, 0); cprint(y, x+9, "k"); j = val & 0x3ff; dprint(y, x+10, j, 4, 0); } /* Handle an interrupt */ void inter(struct eregs *trap_regs) { int i, line; unsigned char *pp; ulong address = 0; /* Get the page fault address */ if (trap_regs->vect == 14) { __asm__("movl %%cr2,%0":"=r" (address)); } #ifdef PARITY_MEM /* Check for a parity error */ if (trap_regs->vect == 2) { parity_err(trap_regs->edi, trap_regs->esi); return; } #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 = ' '; } line = LINE_SCROLL-2; cprint(line, 0, "Unexpected Interrupt - Halting"); cprint(line+2, 0, " Type: "); if (trap_regs->vect <= 19) { cprint(line+2, 7, codes[trap_regs->vect]); } else { hprint(line+2, 7, trap_regs->vect); } cprint(line+3, 0, " PC: "); hprint(line+3, 7, trap_regs->eip); cprint(line+4, 0, " CS: "); hprint(line+4, 7, trap_regs->cs); cprint(line+5, 0, "Eflag: "); hprint(line+5, 7, trap_regs->eflag); cprint(line+6, 0, " Code: "); hprint(line+6, 7, trap_regs->code); if (trap_regs->vect == 14) { /* Page fault address */ cprint(line+7, 0, " Addr: "); hprint(line+7, 7, address); } cprint(line+2, 20, "eax: "); hprint(line+2, 25, trap_regs->eax); cprint(line+3, 20, "ebx: "); hprint(line+3, 25, trap_regs->ebx); cprint(line+4, 20, "ecx: "); hprint(line+4, 25, trap_regs->ecx); cprint(line+5, 20, "edx: "); hprint(line+5, 25, trap_regs->edx); cprint(line+6, 20, "edi: "); hprint(line+6, 25, trap_regs->edi); cprint(line+7, 20, "esi: "); hprint(line+7, 25, trap_regs->esi); cprint(line+8, 20, "ebp: "); 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++) { 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)))); } cprint(line+11, 0, "CS:EIP: "); pp = (unsigned char *)trap_regs->eip; for(i = 0; i < 10; i++) { hprint2(line+11, 8+(3*i), pp[i], 2); } while(1) { check_input(); } } 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"); break; case 1: cache_on(); cprint(LINE_INFO, COL_CACHE, " on"); break; } } int get_key() { int c; c = inb(0x64); if ((c & 1) == 0) { if (serial_cons) { int comstat; comstat = serial_echo_inb(UART_LSR); if (comstat & UART_LSR_DR) { c = serial_echo_inb(UART_RX); /* Pressing '.' has same effect as 'c' on a keyboard. Oct 056 Dec 46 Hex 2E Ascii . */ return (ascii_to_keycode(c)); } } return(0); } c = inb(0x60); return((c)); } void check_input(void) { unsigned char c; if ((c = get_key())) { switch(c & 0x7f) { 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); break; case 46: /* c - Configure */ get_config(); break; case 28: /* CR - clear scroll lock */ slock = 0; footer(); break; case 57: /* SP - set scroll lock */ slock = 1; footer(); break; case 0x26: /* ^L/L - redraw the display */ tty_print_screen(); break; } } } void footer() { cprint(24, 0, "(ESC)Reboot (c)configuration (SP)scroll_lock (CR)scroll_unlock"); if (slock) { cprint(24, 74, "LOCKED"); } else { cprint(24, 74, " "); } } ulong getval(int x, int y, int result_shift) { unsigned long val; int done; int c; int i, n; int base; int shift; char buf[16]; for(i = 0; i < sizeof(buf)/sizeof(buf[0]); i++ ) { buf[i] = ' '; } buf[sizeof(buf)/sizeof(buf[0]) -1] = '\0'; wait_keyup(); done = 0; n = 0; base = 10; while(!done) { /* Read a new character and process it */ c = get_key(); switch(c) { case 0x26: /* ^L/L - redraw the display */ tty_print_screen(); break; case 0x1c: /* CR */ /* If something has been entered we are done */ if(n) done = 1; break; case 0x19: /* p */ buf[n] = 'p'; break; case 0x22: /* g */ buf[n] = 'g'; break; case 0x32: /* m */ buf[n] = 'm'; break; case 0x25: /* k */ buf[n] = 'k'; break; case 0x2d: /* x */ /* Only allow 'x' after an initial 0 */ if (n == 1 && (buf[0] == '0')) { buf[n] = 'x'; } break; case 0x0e: /* BS */ if (n > 0) { n -= 1; buf[n] = ' '; } break; /* Don't allow entering a number not in our current base */ case 0x0B: if (base >= 1) buf[n] = '0'; break; case 0x02: if (base >= 2) buf[n] = '1'; break; case 0x03: if (base >= 3) buf[n] = '2'; break; case 0x04: if (base >= 4) buf[n] = '3'; break; case 0x05: if (base >= 5) buf[n] = '4'; break; case 0x06: if (base >= 6) buf[n] = '5'; break; case 0x07: if (base >= 7) buf[n] = '6'; break; case 0x08: if (base >= 8) buf[n] = '7'; break; case 0x09: if (base >= 9) buf[n] = '8'; break; case 0x0A: if (base >= 10) buf[n] = '9'; break; case 0x1e: if (base >= 11) buf[n] = 'a'; break; case 0x30: if (base >= 12) buf[n] = 'b'; break; case 0x2e: if (base >= 13) buf[n] = 'c'; break; case 0x20: if (base >= 14) buf[n] = 'd'; break; case 0x12: if (base >= 15) buf[n] = 'e'; break; case 0x21: if (base >= 16) buf[n] = 'f'; break; default: break; } /* Don't allow anything to be entered after a suffix */ if (n > 0 && ( (buf[n-1] == 'p') || (buf[n-1] == 'g') || (buf[n-1] == 'm') || (buf[n-1] == 'k'))) { buf[n] = ' '; } /* If we have entered a character increment n */ if (buf[n] != ' ') { n++; } buf[n] = ' '; /* Print the current number */ cprint(x, y, buf); /* Find the base we are entering numbers in */ base = 10; if ((buf[0] == '0') && (buf[1] == 'x')) { base = 16; } else if (buf[0] == '0') { base = 8; } } /* Compute our current shift */ shift = 0; switch(buf[n-1]) { case 'g': /* gig */ shift = 30; break; case 'm': /* meg */ shift = 20; break; case 'p': /* page */ shift = 12; break; case 'k': /* kilo */ shift = 10; break; } shift -= result_shift; /* Compute our current value */ val = simple_strtoul(buf, NULL, base); if (shift > 0) { if (shift >= 32) { val = 0xffffffff; } else { val <<= shift; } } else { if (-shift >= 32) { val = 0; } else { val >>= -shift; } } return val; } 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++; itoa(sx, x); itoa(sy, y); serial_echo_print("["); serial_echo_print(sy); serial_echo_print(";"); serial_echo_print(sx); serial_echo_print("H"); serial_echo_print(p); } void serial_echo_init(void) { int comstat, hi, lo, serial_div; unsigned char lcr; /* read the Divisor Latch */ comstat = serial_echo_inb(UART_LCR); serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR); hi = serial_echo_inb(UART_DLM); lo = serial_echo_inb(UART_DLL); serial_echo_outb(comstat, UART_LCR); /* now do hardwired init */ lcr = serial_parity | (serial_bits - 5); serial_echo_outb(lcr, UART_LCR); /* No parity, 8 data bits, 1 stop */ serial_div = 115200 / serial_baud_rate; serial_echo_outb(0x80|lcr, UART_LCR); /* Access divisor latch */ serial_echo_outb(serial_div & 0xff, UART_DLL); /* baud rate divisor */ serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM); serial_echo_outb(lcr, UART_LCR); /* Done with divisor */ /* Prior to disabling interrupts, read the LSR and RBR * registers */ 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(); return; } void serial_echo_print(const char *p) { if (!serial_cons) { return; } /* Now, do each character */ while (*p) { WAIT_FOR_XMITR; /* Send the character out. */ serial_echo_outb(*p, UART_TX); if(*p==10) { WAIT_FOR_XMITR; serial_echo_outb(13, UART_TX); } p++; } } /* Except for multi-character key sequences this mapping * table is complete. So it should not need to be updated * when new keys are searched for. However the key handling * should really be turned around and only in get_key should * we worry about the exact keycode that was pressed. Everywhere * else we should switch on the character... */ struct ascii_map_str ser_map[] = /*ascii keycode ascii keycode*/ { /* Special cases come first so I can leave * their "normal" mapping in the table, * without it being activated. */ { 27, 0x01}, /* ^[/ESC -> ESC */ { 127, 0x0e}, /* DEL -> BS */ { 8, 0x0e}, /* ^H/BS -> BS */ { 10, 0x1c}, /* ^L/NL -> CR */ { 13, 0x1c}, /* ^M/CR -> CR */ { 9, 0x0f}, /* ^I/TAB -> TAB */ { 19, 0x39}, /* ^S -> SP */ { 17, 28}, /* ^Q -> CR */ { ' ', 0x39}, /* SP -> SP */ { 'a', 0x1e}, { 'A', 0x1e}, { 1, 0x1e}, /* ^A -> A */ { 'b', 0x30}, { 'B', 0x30}, { 2, 0x30}, /* ^B -> B */ { 'c', 0x2e}, { 'C', 0x2e}, { 3, 0x2e}, /* ^C -> C */ { 'd', 0x20}, { 'D', 0x20}, { 4, 0x20}, /* ^D -> D */ { 'e', 0x12}, { 'E', 0x12}, { 5, 0x12}, /* ^E -> E */ { 'f', 0x21}, { 'F', 0x21}, { 6, 0x21}, /* ^F -> F */ { 'g', 0x22}, { 'G', 0x22}, { 7, 0x22}, /* ^G -> G */ { 'h', 0x23}, { 'H', 0x23}, { 8, 0x23}, /* ^H -> H */ { 'i', 0x17}, { 'I', 0x17}, { 9, 0x17}, /* ^I -> I */ { 'j', 0x24}, { 'J', 0x24}, { 10, 0x24}, /* ^J -> J */ { 'k', 0x25}, { 'K', 0x25}, { 11, 0x25}, /* ^K -> K */ { 'l', 0x26}, { 'L', 0x26}, { 12, 0x26}, /* ^L -> L */ { 'm', 0x32}, { 'M', 0x32}, { 13, 0x32}, /* ^M -> M */ { 'n', 0x31}, { 'N', 0x31}, { 14, 0x31}, /* ^N -> N */ { 'o', 0x18}, { 'O', 0x18}, { 15, 0x18}, /* ^O -> O */ { 'p', 0x19}, { 'P', 0x19}, { 16, 0x19}, /* ^P -> P */ { 'q', 0x10}, { 'Q', 0x10}, { 17, 0x10}, /* ^Q -> Q */ { 'r', 0x13}, { 'R', 0x13}, { 18, 0x13}, /* ^R -> R */ { 's', 0x1f}, { 'S', 0x1f}, { 19, 0x1f}, /* ^S -> S */ { 't', 0x14}, { 'T', 0x14}, { 20, 0x14}, /* ^T -> T */ { 'u', 0x16}, { 'U', 0x16}, { 21, 0x16}, /* ^U -> U */ { 'v', 0x2f}, { 'V', 0x2f}, { 22, 0x2f}, /* ^V -> V */ { 'w', 0x11}, { 'W', 0x11}, { 23, 0x11}, /* ^W -> W */ { 'x', 0x2d}, { 'X', 0x2d}, { 24, 0x2d}, /* ^X -> X */ { 'y', 0x15}, { 'Y', 0x15}, { 25, 0x15}, /* ^Y -> Y */ { 'z', 0x2c}, { 'Z', 0x2c}, { 26, 0x2c}, /* ^Z -> Z */ { '-', 0x0c}, { '_', 0x0c}, { 31, 0x0c}, /* ^_ -> _ */ { '=', 0x0c}, { '+', 0x0c}, { '[', 0x1a}, { '{', 0x1a}, { 27, 0x1a}, /* ^[ -> [ */ { ']', 0x1b}, { '}', 0x1b}, { 29, 0x1b}, /* ^] -> ] */ { ';', 0x27}, { ':', 0x27}, { '\'', 0x28}, { '"', 0x28}, { '`', 0x29}, { '~', 0x29}, { '\\', 0x2b}, { '|', 0x2b}, { 28, 0x2b}, /* ^\ -> \ */ { ',', 0x33}, { '<', 0x33}, { '.', 0x34}, { '>', 0x34}, { '/', 0x35}, { '?', 0x35}, { '1', 0x02}, { '!', 0x02}, { '2', 0x03}, { '@', 0x03}, { '3', 0x04}, { '#', 0x04}, { '4', 0x05}, { '$', 0x05}, { '5', 0x06}, { '%', 0x06}, { '6', 0x07}, { '^', 0x07}, { 30, 0x07}, /* ^^ -> 6 */ { '7', 0x08}, { '&', 0x08}, { '8', 0x09}, { '*', 0x09}, { '9', 0x0a}, { '(', 0x0a}, { '0', 0x0b}, { ')', 0x0b}, { 0, 0} }; /* * Given an ascii character, return the keycode * * Uses ser_map definition above. * * It would be more efficient to use an array of 255 characters * and directly index into it. */ int ascii_to_keycode (int in) { struct ascii_map_str *p; for (p = ser_map; p->ascii; p++) { if (in ==p->ascii) return p->keycode; } return 0; } /* * Call this when you want to wait for the user to lift the * finger off of a key. It is a noop if you are using a * serial console. */ void wait_keyup( void ) { /* Check to see if someone lifted the keyboard key */ while (1) { if ((get_key() & 0x80) != 0) { return; } /* Trying to simulate waiting for a key release with * the serial port is to nasty to let live. * In particular some menus don't even display until * you release the key that caused to to get there. * With the serial port this results in double pressing * or something worse for just about every key. */ if (serial_cons) { return; } } } /* * Handles "console=" command line option * * Examples of accepted params: * ttyS0 * ttyS1 * ttyS0,115200 * ttyS0,9600e8 */ void serial_console_setup(char *param) { char *option, *end; unsigned long tty; unsigned long baud_rate; unsigned char parity, bits; if (strncmp(param, "ttyS", 4)) return; /* not a serial port */ param += 4; tty = simple_strtoul(param, &option, 10); if (option == param) return; /* there were no digits */ if (tty > 3) return; /* only ttyS0 to ttyS3 supported */ if (*option == '\0' || *option == ' ') goto save_tty; /* no options given, just ttyS? */ if (*option != ',') return; /* missing the comma separator */ /* baud rate must follow */ option++; baud_rate = simple_strtoul(option, &end, 10); if (end == option) return; /* no baudrate after comma */ if (baud_rate == 0 || (115200 % baud_rate) != 0) return; /* wrong baud rate */ if (*end == '\0' || *end == ' ') goto save_baud_rate; /* no more options given */ switch (toupper(*end)) { case 'N': parity = 0; break; case 'O': parity = UART_LCR_PARITY; break; case 'E': parity = UART_LCR_PARITY | UART_LCR_EPAR; break; default: /* Unknown parity */ return; } end++; if (*end == '\0' || *end == ' ') goto save_parity; /* word length (bits) */ if (*end < '7' || *end > '8') return; /* invalid number of bits */ bits = *end - '0'; end++; if (*end != '\0' && *end != ' ') return; /* garbage at the end */ serial_bits = bits; save_parity: serial_parity = parity; save_baud_rate: serial_baud_rate = (int) baud_rate; save_tty: serial_tty = (short) tty; serial_cons = 1; } #ifdef LP #define DATA 0x00 #define STATUS 0x01 #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) { 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)); } 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; } } } 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 memtest86+-4.20/makeiso.sh0000755000000000000000000000226711517067470014052 0ustar rootroot#!/bin/sh # check to see if the correct tools are installed for X in wc mkisofs do if [ "$(which $X)" = "" ]; then echo "makeiso.sh error: $X is not in your path." >&2 exit 1 elif [ ! -x $(which $X) ]; then echo "makeiso.sh error: $X is not executable." >&2 exit 1 fi done #check to see if memtest.bin is present if [ ! -w memtest.bin ]; then echo "makeiso.sh error: cannot find memtest.bin, did you compile it?" >&2 exit 1 fi # enlarge the size of memtest.bin SIZE=$(wc -c memtest.bin | awk '{print $1}') FILL=$((1474560 - $SIZE)) dd if=/dev/zero of=fill.tmp bs=$FILL count=1 cat memtest.bin fill.tmp > memtest.img rm -f fill.tmp echo "Generating iso image ..." mkdir "cd" mkdir "cd/boot" mv memtest.img cd/boot cd cd # Create the cd.README 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. " -b boot/memtest.img -c boot/boot.catalog -V "MT410" -o memtest.iso . mv memtest.iso ../mt420.iso cd .. rm -rf cd echo "Done! Memtest86+ 4.20 ISO is mt420.iso" memtest86+-4.20/FAQ0000644000000000000000000003714311517067470012416 0ustar rootroot- What is memtest86+, what do I use it for? Memtest86+ is a utility designed to test whether your memory is in working order. It repeatedly writes an enormous amount of different patterns to all memory locations and reads them back again and verifies whether the result of the read is the same as what was written to memory. There can be a multitude of reasons for running memtest, but foremost of all is of course to test whether your memory modules might be bad. Whenever you suspect your modules to be bad because of system crashes, lockups or reboots it would be nice to know whether the modules are in working order. Memtest86+ is a utility which tries to answer that question for you. Another common use exists in the overclocking scene. When overclocking a system you are essentially pushing your system to the limits and at some point it will simply give way and break. Unfortunately there isn't a clear cut way of deciding whether a system is still working correctly. Because of the complexity of a computer a system which is pushed to the limits doesn't just break completely when it starts to fail, instead little errors start showing up in many different places in the system growing more frequent and widespread the more the system is pushed. Each one of these little errors can lead to a crash of your system but can also go unnoticed for days or weeks in a running system. The art so to speak of overclocking is thus to push the system as far as it can go without introducing any such errors. As memory is usually one of the first places these such errors start coming up a memory test is very useful. - How do I get it to run? There are several ways to use memtest, which are described below: + Run from floppydisk Memtest86+ is directly executable by any modern x86 compatible machine, by writing the bootable binary to a floppy disk one can boot from the disk to run memtest. Simply download the appropriate package, the Pre-Compiled Bootable Binary (.gz) package for Linux users and the Pre-Compiled package for Floppy (DOS - Win) for Windows users. For Windows, unzip the package into a directory like C:\memtest, insert a blank floppy into your a: disk drive and run the install.bat file. As the install prompts you, to use memtest directly, leave the disk in the drive and reboot your machine. For Linux, unpack the package into your home directory, insert a blank floppy into your floppy drive and execute 'dd if=~/memtest+-1.xx.bin.gz of=/dev/fd0 conv=osync' replacing 1.xx with the correct version number of the memtest86+ you downloaded. To run memtest immediately reboot your machine. Your machine should now boot from the disk, display the word Loading folowed by a series of periods and then show a screen much like the screenshots on the memtest86+ web page. The test is automatically started. If your machine simply boots back into Windows/Linux you will most likely have to configure your BIOS to attempt to boot from floppy disk on startup, refer to your computer's/mainboard's manual how to do this. When you are done testing simply remove the floppy and reset your computer, if ever you want to execure the test again simply reinsert the disk and reboot/start your computer. + Run from CD Memtest86+ is directly executable by any modern x86 compatible machine, by writing the iso to a CD one can boot from the CD to run memtest. Simply download the appropriate package, the Download - Pre-Compiled Bootable ISO (.gz) for Linux users and the Pre-Compiled Bootable ISO (.zip) for Windows users. For Windows, unzip the package into a directory like C:\memtest. You will now see a file called memtest86+-1.xx.iso in this directory. You will need to burn this file to a CD with a CD recording program. Do note however that you should not make a regular data CD on which you for instance write your text documents and holiday photographs. Instead the iso file is a so called image of a CD, it is a direct copy of a CD. Your CD recording program will most likely have a feature called burn image or something to that effect which you should use to burn the CD. For linux, unzip the package into your home directory. and execute 'cdrecord dev= ~/memtest86+-1.xx.iso' where you replace with the scsi address of your CD burner and replace 1.xx with the correct version number of the memtest86+ your downloaded. When the burning completed your drive will most likely have ejected the CD and you should have a bootable memtest86+ CD. To run the test directly reinsert the CD and reboot your machine. Your machine should now boot from the CD, display the word Loading folowed by a series of periods and then show a screen much like the screenshots on the memtest86+ web page. The test is automatically started. If your machine simply boots back into Windows/Linux you will most likely have to configure your BIOS to attempt to boot from CD-ROM drive on startup, refer to your computer's/mainboard's manual how to do this. When you are done testing simply remove the CD and reset your computer, if ever you want to execure the test again simply reinsert the CD and reboot/start your computer. + Run from USB Flash drive FIXME + Run from boot manager FIXME - How long does memtest86+ run? How do I stop it? Memtest86+ runs indefinately unless you stop it. It does however repeat the same tests over and over again. Memtest86+ contains a number of different tests which each take different approaches in trying to expose any errors in your memory. In the top right of your screen you can see the progress of each test in the lower of the two progress bars. The topmost progress bar shows the progress of a pass, each pass consists of all the tests in the memtest suite. Thus all tests are executed in one pass, so does that mean that no errors will show after the first pass if that pass didn't reveal any errors? Well no, there are several reasons why errors might only show up after a number of passes. Firstly as of this writing, the latest version of memtest also includes a test which uses random test patterns, each pass these patterns will of course be different. Secondly some types of errors simply don't show up until the system has been running for a while or are very critical on a certain timing condition, or other such conditions. To conclude, one successful pass of memtest will give you a pretty good idea that your memory is ok, only in rare cases will there be errors showing after the first pass. To be sure though simply have the test run overnight or even for a couple of days depending on the level of importance of the system. - How many errors are acceptable? No errors are acceptable. Even if there is just one error, something is amiss which can cause your system to crash. Of course what the cause of the errors is you will still have to determine. - What do I do when I get errors? Firstly, don't start drawing any conclusions. You only know that memtest86+ is giving your errors, not what the cause is. Unfortunately it is not a straightforward exercise to decisively test the memory in an actual system. This is because a computer is not just built up of some memory, but also includes many other elements such as a memory controller, cache, a cache controller, algorithmic and logic units, etc, all of which contribute to the machine. If there are faults in any of these other parts of the computer you will likely also see errors showing up in memtest. So what to do? First verify that the BIOS settings of your machine are correctly configured. Look up the memory timing settings applicable to the brand and type of memory modules you have and check they match your BIOS settings, correct them if they don't and run memtest again Ok, you have all the settings correctly set and you're still getting errors. Well of course a very likely cause are the memory modules and the logical course of action is to look into them further. If you are well stocked, have a few other machines at your disposal, or just want to spend the cash for some new modules the best way to test if the cause are your memory modules is just to replace them and test again. If you are less fortunate though there is still something you can do. If you have more then one module in your system, test them one by one, if one is consistently giving errors and another is consistently showing no errors it's a pretty good bet that the module giving the errors is simply defective. To exclude the possibility that a defective slot is throwing your results, use the same slot to test each different module. If each module by itself shows no errors, but when you place two or more modules into the machine at the same time you do get errors, you are most likely stuck with a compatibility issue and unfortunately there isn't a whole lot you can do about it. Be sure to check your computer/motherboard manual to see if the setup you are trying is allowed, some boards require special restrictions in the sizes of modules, the order of modules, the placement of double sided and single sides modules and more of such things. If you have only one module in your system, or all modules are giving errors, there are only very few options left. The only thing you can do really is to try the module(s) in another slot. Finally simply try out different orders of the memory modules, although your manual might not mention anything on the matter sometimes there simply exist timing or other issues which can be resolved by changing the order of your modules. And of course test each slot by putting a single module into that slot and running memtest on it. In the end if you still have not been able to localize the problem you will have to find a replacement module to establish whether the problem lies in your modules. See if you can borrow a module from someone else. When you have replaced the memory by new memory and the errors still persist, first check if you can rule out any compatibility issues or timing issues. If you are sure the memory should work in the system the cause of the errors must obviously lie someplace else in the system. The only way to find out where, is by trial and error really. Simply start replacing and/or removing parts of your computer one by one, running memtest each time you changed anything, until the errors are resolved. - I'm getting errors in test #x, what doest that mean? Interpreting memtest results is as scientific an endeavour as testing whether a person is a witch by the methods used in Monty Python's Holy Grail. In short, don't even start, it's not going to get you anywhere. Just interpret any error as you should any other and use the methods descibed in the previous question to determine the cause. - I'm getting errors in test #5 and/or #8 and have read a lot about it. Yes there are just about enough discussions on the topic to fill a book, but it all boils down to the answer given above. The only thing that can be said is that many a times, when memory latencies are incorrectly set in the BIOS you will experience errors in test #5 and #8. (Though #8 does not exist anymore as of version 1.40 and might be reinstated as a different test in a later version.) This does however NOT mean that errors in these tests are always the cause of incorrect settings, your memory might just as well be defective. - I'm getting errors in memtest on one machine, but not when I put the same memory in another, what does that mean? It can mean one of two things: - The machine that is giving the errors is defective. Errors don't just orginate from the memory module itself, but can also be caused by defects in the cpu, chipset, motherboard, PSU and even by timing issues introduced by any other component in the machine. - The machine giving the errors is imposing stricter timing than the other which the memory module simply can't cope with. If the module should work with the machine according to its specifications then it most likely is defective. - Which memory is tested? As much as possible of the system memory is tested. Unfortunately memtest86+ can usually not test all of the memory. The reason for this is that todays processors have become so complex that they require a small amount of memory to keep accounting data of the processor state. If memtest were to write over these areas the state of the processor becomes invalid and it's behaviour unpredictable. Alas it is also impossible to relocate these areas in the memory. This means that a small area of your memory can not be tested by memtest. If this part of the memory is defective you will know soon enough though as the processor, or parts of the processor simply won't work correctly if this part of your memory is defective. Do realise though that in very rare cases memtest will show no errors even though the module is defective, not because memtest can't detect the error, but because memtest can't test the area the error is located in. - When I select BIOS-ALL I get many errors / my machine crashes. This is normal. With todays computers this option should never be selected. See the previous question about the reason for the errors. - I want to use memtest on a multiboot CD, how do I do this? This is of course very dependent on which boot loader you use for your CD. Below is a description of how to set up a multiboot CD including memtest+ with isolinux, if you have experience with any other bootloader(s) please consider writing a small description of using memtest with that bootloader for the FAQ. -isolinux For general instructions on how to make a bootable CD with isolinux see the syslinux website and the manual. What you need to do to get memtest working is as follows. Download the Pre-Compiled Bootable Binary, the .gz if you are working under linux, the .zip if you are working under windows. Unpack the file from the package and rename it to an 8.3 filename with an extension other than .bin, renaming to memtest. (without an extension) is a good choice. Put the file somewhere in your CD directory structure, for example in images/memtest and edit your config file to include the following: label memtest kernel /images/memtest If you want to boot memtest automatically insert or change a line at the top to: default memtest If you want to display a prompt from which you can start memtest add or change the lines at the top to: (Change the timeout to suit your needs) prompt 1 timeout 200 - If memtest86+ shows no errors does that mean my memory is not defective? Of course no answers are definitive, no matter how good memtest86+ will eventually become there is always the possibility that a particular type of error will go unnoticed. As long as you are having no problems with the system it will be pretty safe to say that the modules are good. If you are having problems with the system however you will just have to check by trial and error, ie swapping the modules for new ones and/or testing with modules of a different brand/type. - When I run install.bat it doesn't write anything to floppy. You most likely have unpacked the memtest+-2.xx.floppy.zip file into a folder with a long pathname and/or containing + and - signs. It seems rawrite doesn't like that. Just move the files you unpacked to a directory like c:\memtest and execure it from there. memtest86+-4.20/makedos.sh0000755000000000000000000000043211517067470014035 0ustar rootroot#!/bin/bash if [ -f memtest.bin ] then CSIZE="$(awk 'NR==16' mt86+_loader.asm | awk '{print $2}')"; NSIZE="$(ls -l memtest.bin | awk '{print $5}')"; sed "s/$CSIZE/$NSIZE/" mt86+_loader.asm > mt86+_loader.asm.new; mv mt86+_loader.asm.new mt86+_loader.asm; nasm mt86+_loader.asm; fi memtest86+-4.20/config.h0000644000000000000000000000270511517067470013476 0ustar rootroot/* config.h - MemTest-86 Version 3.0 * * Compile time configuration options * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com */ /* PARITY_MEM - Enables support for reporting memory parity errors */ /* Experimental, normally enabled */ #define PARITY_MEM /* SERIAL_CONSOLE_DEFAULT - The default state of the serial console. */ /* This is normally off since it slows down testing. Change to a 1 */ /* to enable. */ #define SERIAL_CONSOLE_DEFAULT 0 /* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */ #define SERIAL_TTY 0 /* SERIAL_BAUD_RATE - Baud rate for the serial console */ #define SERIAL_BAUD_RATE 9600 /* 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 */ /* APM - Turns off APM at boot time to avoid blanking the screen */ /* Normally enabled */ #define APM_OFF /* USB_WAR - Enables a workaround for errors caused by BIOS USB keyboard */ /* and mouse support*/ /* Normally enabled */ #define USB_WAR memtest86+-4.20/extra.h0000644000000000000000000000154111517067470013351 0ustar rootroot// This is the extra stuff added to the memtest+ from memtest.org // Code from Eric Nelson and Wee /* extra.c * * Released under version 2 of the Gnu Public License. * */ #ifndef MEMTEST_EXTRA_H #define MEMTEST_EXTRA_H void change_timing(int cas, int rcd, int rp, int ras); void find_memctr(void); void disclaimer(void); void get_option(void); void get_menu(void); void a64_parameter(void); int get_cas(void); void change_timing_i852(int cas, int rcd, int rp, int ras); void change_timing_i925(int cas, int rcd, int rp, int ras); void change_timing_i875(int cas, int rcd, int rp, int ras); void change_timing_nf2(int cas, int rcd, int rp, int ras); void change_timing_amd64(int cas, int rcd, int rp, int ras); void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr); void __delay(ulong loops); #endif /* MEMTEST_EXTRA_H */ memtest86+-4.20/pci.h0000644000000000000000000001007711517067470013005 0ustar rootroot#ifndef MEMTEST_PCI_H #define MEMTEST_PCI_H int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value); int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long value); int pci_init(void); /* * Under PCI, each device has 256 bytes of configuration address space, * of which the first 64 bytes are standardized as follows: */ #define PCI_VENDOR_ID 0x00 /* 16 bits */ #define PCI_DEVICE_ID 0x02 /* 16 bits */ #define PCI_COMMAND 0x04 /* 16 bits */ #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ #define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ #define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ #define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ #define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ #define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ #define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ #define PCI_COMMAND_SERR 0x100 /* Enable SERR */ #define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ #define PCI_STATUS 0x06 /* 16 bits */ #define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ #define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ #define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ #define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ #define PCI_STATUS_PARITY 0x100 /* Detected parity error */ #define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ #define PCI_STATUS_DEVSEL_FAST 0x000 #define PCI_STATUS_DEVSEL_MEDIUM 0x200 #define PCI_STATUS_DEVSEL_SLOW 0x400 #define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ #define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ #define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ #define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ #define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ #define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */ #define PCI_REVISION_ID 0x08 /* Revision ID */ #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ #define PCI_CLASS_DEVICE 0x0a /* Device class */ #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ #define PCI_HEADER_TYPE 0x0e /* 8 bits */ #define PCI_HEADER_TYPE_NORMAL 0 #define PCI_HEADER_TYPE_BRIDGE 1 #define PCI_HEADER_TYPE_CARDBUS 2 #define PCI_BIST 0x0f /* 8 bits */ #define PCI_BIST_CODE_MASK 0x0f /* Return result */ #define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ #define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ /* * Base addresses specify locations in memory or I/O space. * Decoded size can be determined by writing a value of * 0xffffffff to the register, and reading it back. Only * 1 bits are decoded. */ #define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ #define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ #define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ #define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ #define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ #define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ #define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ #define PCI_BASE_ADDRESS_SPACE_IO 0x01 #define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 #define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 #define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ #define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) #define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) /* bit 1 is reserved if address_space = 1 */ /* Device classes and subclasses */ #define PCI_CLASS_NOT_DEFINED 0x0000 #define PCI_CLASS_NOT_DEFINED_VGA 0x0001 #define PCI_BASE_CLASS_BRIDGE 0x06 #define PCI_CLASS_BRIDGE_HOST 0x0600 #endif /* MEMTEST_PCI_H */ memtest86+-4.20/smp.h0000644000000000000000000001463511517067470013035 0ustar rootroot/* ********************************************************** * Copyright 2002 VMware, Inc. All rights reserved. -- VMware Confidential * **********************************************************/ #ifndef _SMP_H_ #define _SMP_H_ #include "stdint.h" #include "defs.h" #define MAX_CPUS 16 // "16 CPUs ought to be enough for everybody." #define FPSignature ('_' | 'M' << 8 | 'P' << 16 | '_' << 24) typedef struct { uint32_t signature; // "_MP_" uint32_t phys_addr; uint8_t length; uint8_t spec_rev; uint8_t checksum; uint8_t feature[5]; } floating_pointer_struct_t; #define MPCSignature ('P' | 'C' << 8 | 'M' << 16 | 'P' << 24) typedef struct { uint32_t signature; // "PCMP" uint16_t length; uint8_t spec_rev; uint8_t checksum; char oem[8]; char productid[12]; uint32_t oem_ptr; uint16_t oem_size; uint16_t oem_count; uint32_t lapic_addr; uint32_t reserved; } mp_config_table_header_t; /* Followed by entries */ #define MP_PROCESSOR 0 #define MP_BUS 1 #define MP_IOAPIC 2 #define MP_INTSRC 3 #define MP_LINTSRC 4 typedef struct { uint8_t type; /* MP_PROCESSOR */ uint8_t apic_id; /* Local APIC number */ uint8_t apic_ver; /* Its versions */ uint8_t cpu_flag; #define CPU_ENABLED 1 /* Processor is available */ #define CPU_BOOTPROCESSOR 2 /* Processor is the BP */ uint32_t cpu_signature; #define CPU_STEPPING_MASK 0x0F #define CPU_MODEL_MASK 0xF0 #define CPU_FAMILY_MASK 0xF00 uint32_t featureflag; /* CPUID feature value */ 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 { uint8_t type; // set to MP_IOAPIC uint8_t apicid; uint8_t apicver; uint8_t flags; #define MPC_APIC_USABLE 0x01 uint32_t apicaddr; } mp_io_apic_entry_t; typedef struct { uint8_t type; uint8_t irqtype; uint16_t irqflag; uint8_t srcbus; uint8_t srcbusirq; uint8_t dstapic; uint8_t dstirq; } mp_interrupt_entry_t; #define MP_INT_VECTORED 0 #define MP_INT_NMI 1 #define MP_INT_SMI 2 #define MP_INT_EXTINT 3 #define MP_IRQDIR_DEFAULT 0 #define MP_IRQDIR_HIGH 1 #define MP_IRQDIR_LOW 3 typedef struct { uint8_t type; uint8_t irqtype; uint16_t irqflag; uint8_t srcbusid; uint8_t srcbusirq; uint8_t destapic; #define MP_APIC_ALL 0xFF uint8_t destapiclint; } mp_local_interrupt_entry_t; /* APIC definitions */ /* * APIC registers */ #define APICR_ID 0x02 #define APICR_ESR 0x28 #define APICR_ICRLO 0x30 #define APICR_ICRHI 0x31 /* APIC destination shorthands */ #define APIC_DEST_DEST 0 #define APIC_DEST_LOCAL 1 #define APIC_DEST_ALL_INC 2 #define APIC_DEST_ALL_EXC 3 /* APIC IPI Command Register format */ #define APIC_ICRHI_RESERVED 0x00ffffff #define APIC_ICRHI_DEST_MASK 0xff000000 #define APIC_ICRHI_DEST_OFFSET 24 #define APIC_ICRLO_RESERVED 0xfff32000 #define APIC_ICRLO_DEST_MASK 0x000c0000 #define APIC_ICRLO_DEST_OFFSET 18 #define APIC_ICRLO_TRIGGER_MASK 0x00008000 #define APIC_ICRLO_TRIGGER_OFFSET 15 #define APIC_ICRLO_LEVEL_MASK 0x00004000 #define APIC_ICRLO_LEVEL_OFFSET 14 #define APIC_ICRLO_STATUS_MASK 0x00001000 #define APIC_ICRLO_STATUS_OFFSET 12 #define APIC_ICRLO_DESTMODE_MASK 0x00000800 #define APIC_ICRLO_DESTMODE_OFFSET 11 #define APIC_ICRLO_DELMODE_MASK 0x00000700 #define APIC_ICRLO_DELMODE_OFFSET 8 #define APIC_ICRLO_VECTOR_MASK 0x000000ff #define APIC_ICRLO_VECTOR_OFFSET 0 /* APIC trigger types (edge/level) */ #define APIC_TRIGGER_EDGE 0 #define APIC_TRIGGER_LEVEL 1 /* APIC delivery modes */ #define APIC_DELMODE_FIXED 0 #define APIC_DELMODE_LOWEST 1 #define APIC_DELMODE_SMI 2 #define APIC_DELMODE_NMI 4 #define APIC_DELMODE_INIT 5 #define APIC_DELMODE_STARTUP 6 #define APIC_DELMODE_EXTINT 7 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); void smp_init_aps(void); void smp_boot_ap(unsigned cpu_num); void smp_ap_booted(unsigned cpu_num); static inline void __GET_CPUID(int ax, uint32_t *regs) { __asm__ __volatile__("\t" /* save ebx in case -fPIC is being used */ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "a" (ax) : "memory" ); } #define GET_CPUID(_ax,_bx,_cx,_dx) { \ uint32_t regs[4]; \ __GET_CPUID(_ax,regs); \ _ax = regs[0]; \ _bx = regs[1]; \ _cx = regs[2]; \ _dx = regs[3]; \ } /* * Checked against the Intel manual and GCC --hpreg * * volatile because the tsc always changes without the compiler knowing it. */ static inline uint64_t RDTSC(void) { uint64_t tim; __asm__ __volatile__( "rdtsc" : "=A" (tim) ); return tim; } static inline uint64_t __GET_MSR(int cx) { uint64_t msr; __asm__ __volatile__( "rdmsr" : "=A" (msr) : "c" (cx) ); return msr; } #define __GCC_OUT(s, s2, port, val) do { \ __asm__( \ "out" #s " %" #s2 "1, %w0" \ : \ : "Nd" (port), "a" (val) \ ); \ } while (0) #define OUTB(port, val) __GCC_OUT(b, b, port, val) typedef struct { unsigned int slock; } spinlock_t; static inline void spin_lock(volatile spinlock_t *lock) { 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"); } static inline void spin_unlock(volatile spinlock_t *lock) { asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory"); } #endif /* _SMP_H_ */ memtest86+-4.20/extra.c0000644000000000000000000006266211517067470013357 0ustar rootroot// This is the extra stuff added to the memtest+ from memtest.org // Code from Eric Nelson and Wee // (Checked without vendor-specific optimization before adding) /* extra.c - * * Released under version 2 of the Gnu Public License. * */ #include "test.h" #include "screen_buffer.h" #include "pci.h" #include "extra.h" static int claim = 0; static int ctrl = -1; struct memory_controller { unsigned vendor; unsigned device; int worked; void (*change_timing)(int cas, int rcd, int rp, int ras); }; static struct memory_controller mem_ctr[] = { /* AMD 64*/ { 0x1022, 0x1100, 1, change_timing_amd64}, //AMD64 hypertransport link /* nVidia */ { 0x10de, 0x01E0, 0, change_timing_nf2}, // nforce2 /* Intel */ { 0x8086, 0x2570, 0, change_timing_i875}, //Intel i848/i865 { 0x8086, 0x2578, 0, change_timing_i875}, //Intel i875P { 0x8086, 0x2580, 0, change_timing_i925}, //Intel i915P/G { 0x8086, 0x2584, 0, change_timing_i925}, //Intel i925X { 0x8086, 0x2770, 0, change_timing_i925}, //Intel Lakeport { 0x8086, 0x3580, 0, change_timing_i852}, //Intel i852GM - i855GM/GME (But not i855PM) }; struct drc { unsigned t_rwt; unsigned t_wrt; unsigned t_ref; unsigned t_en2t; unsigned t_rwqb; unsigned t_rct; unsigned t_rrd; unsigned t_wr; }; static struct drc a64; void find_memctr(void) // Basically copy from the find_controller function { unsigned long vendor; unsigned long device; unsigned long a64; int i= 0; int result; result = pci_conf_read(0, 0, 0, PCI_VENDOR_ID, 2, &vendor); result = pci_conf_read(0, 0, 0, PCI_DEVICE_ID, 2, &device); pci_conf_read(0, 24, 0, 0x00, 4, &a64); if( a64 == 0x11001022) { ctrl = 0; return; } if (result == 0) { for(i = 1; i < sizeof(mem_ctr)/sizeof(mem_ctr[0]); i++) { if ((mem_ctr[i].vendor == vendor) && (mem_ctr[i].device == device)) { ctrl = i; return; } } } ctrl = -1; } void a64_parameter(void) { ulong dramtlr; if ( 0 == pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr) ) { a64.t_rct = 7 + ((dramtlr>>4) & 0x0F); a64.t_rrd = 0 + ((dramtlr>>16) & 0x7); a64.t_wr = 2 + ((dramtlr>>28) & 0x1); } if ( 0 == pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr) ) { a64.t_rwt = 1 + ((dramtlr>>4) & 0x07); a64.t_wrt = 1 + (dramtlr & 0x1); a64.t_ref = 1 + ((dramtlr>>11) & 0x3); } if ( 0 == pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr) ) { a64.t_en2t = 1 + ((dramtlr>>28) & 0x1); a64.t_rwqb = 2 << ((dramtlr>>14) & 0x3); } } void change_timing(int cas, int rcd, int rp, int ras) { find_memctr(); if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) { return; } mem_ctr[ctrl].change_timing(cas, rcd, rp, ras); restart(); } void amd64_option() { int rwt=0, wrt=0, ref=0, en2t=0, rct=0, rrd=0, rwqb=0, wr = 0, flag=0; if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) { return; } if (mem_ctr[ctrl].worked) { a64_parameter(); cprint(POP_Y+1, POP_X+4, "AMD64 options"); cprint(POP_Y+3, POP_X+4, "(1) Rd-Wr Delay : "); dprint(POP_Y+3, POP_X+24, a64.t_rwt, 2, 0); cprint(POP_Y+4, POP_X+4, "(2) Wr-Rd Delay : "); dprint(POP_Y+4, POP_X+24, a64.t_wrt, 2, 0); cprint(POP_Y+5, POP_X+4, "(3) Rd/Wr Bypass : "); dprint(POP_Y+5, POP_X+24, a64.t_rwqb, 2, 0); cprint(POP_Y+6, POP_X+4, "(4) Refresh Rate : "); switch ( a64.t_ref) { case 1 : cprint(POP_Y+6, POP_X+23, "15.6us"); break; case 2 : cprint(POP_Y+6, POP_X+23, " 7.8us"); break; case 3 : cprint(POP_Y+6, POP_X+23, " 3.9us"); break; } cprint(POP_Y+7, POP_X+4, "(5) Command Rate :"); dprint(POP_Y+7, POP_X+24, a64.t_en2t, 2, 0); cprint(POP_Y+7, POP_X+26, "T "); cprint(POP_Y+8, POP_X+4, "(6) Row Cycle Time: "); dprint(POP_Y+8, POP_X+24, a64.t_rct, 2, 0); cprint(POP_Y+9, POP_X+4, "(7) RAS-RAS Delay : "); dprint(POP_Y+9, POP_X+24, a64.t_rrd, 2, 0); cprint(POP_Y+10, POP_X+4, "(8) Write Recovery: "); dprint(POP_Y+10, POP_X+24, a64.t_wr, 2, 0); cprint(POP_Y+11, POP_X+4,"(0) Cancel "); while(!flag) { switch(get_key()) { case 2: popclear(); // read-to-write delay cprint(POP_Y+3, POP_X+4, "Rd-Wr delay "); cprint(POP_Y+4, POP_X+4, " (2 - 6 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rwt, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); rwt = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 3: popclear(); // read-to-write delay cprint(POP_Y+3, POP_X+4, "Wr-Rd delay "); cprint(POP_Y+4, POP_X+4, " (1 - 2 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_wrt, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); wrt = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 4: popclear(); // Read write queue bypass count cprint(POP_Y+3, POP_X+4, "Rd/Wr bypass "); cprint(POP_Y+4, POP_X+4, " (2, 4 or 8 )"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rwqb, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); rwqb = getval(POP_Y+7, POP_X+11, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 5: popclear(); // refresh rate cprint(POP_Y+3, POP_X+4, "Refresh rate "); cprint(POP_Y+4, POP_X+4, "Current: "); switch ( a64.t_ref){ case 1 : cprint(POP_Y+4, POP_X+14, "15.6us"); break; case 2 : cprint(POP_Y+4, POP_X+14, "7.8us "); break; case 3 : cprint(POP_Y+4, POP_X+14, "3.9us "); break; } cprint(POP_Y+6, POP_X+4, "New: "); cprint(POP_Y+7, POP_X+4, "(1) 15.6us"); cprint(POP_Y+8, POP_X+4, "(2) 7.8us "); cprint(POP_Y+9, POP_X+4, "(3) 3.9us "); ref = getval(POP_Y+6, POP_X+11, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 6: popclear(); //Enable 2T command and addressing cprint(POP_Y+3, POP_X+4, "Command rate:"); cprint(POP_Y+5, POP_X+4, "(1) 1T "); //only supoprted by CG revision and later cprint(POP_Y+6, POP_X+4, "(2) 2T "); en2t = getval(POP_Y+3, POP_X+22, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 7: popclear(); //Row cycle time cprint(POP_Y+3, POP_X+4, "Row cycle time: "); cprint(POP_Y+4, POP_X+4, " (7 - 20 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rct, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); rct = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 8: popclear(); //Active-to-Active RAS Delay cprint(POP_Y+3, POP_X+4, "RAS-RAS Delay: "); cprint(POP_Y+4, POP_X+4, " (2 - 4 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rrd, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); rrd = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 9: popclear(); //Active-to-Active RAS Delay cprint(POP_Y+3, POP_X+4, "Write Recovery: "); cprint(POP_Y+4, POP_X+4, " (2 - 3 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_wr, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); wr = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 11: case 57: flag++; /* 0/CR - Cancel */ break; } } } } void get_option() { int cas =0, rp=0, rcd=0, ras=0, sflag = 0 ; while(!sflag) { switch(get_key()) { case 2: popclear(); cas = get_cas(); popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras = getval(POP_Y+3, POP_X+15, 0); popclear(); change_timing(cas, rcd, rp, ras); break; case 3: popclear(); cas = get_cas(); change_timing(cas, 0, 0, 0); sflag++; break; case 4: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd =getval(POP_Y+3, POP_X+15, 0); change_timing(0, rcd, 0, 0); sflag++; break; case 5: popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, rp, 0); sflag++; break; case 6: popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, 0, ras); sflag++; break; case 7: popclear(); amd64_option(); sflag++; popclear(); break; case 8: break; case 11: case 57: sflag++; /* 0/CR - Cancel */ break; } } } void get_option_1() { int rp=0, rcd=0, ras=0, sflag = 0 ; while(!sflag) { switch(get_key()) { case 2: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras = getval(POP_Y+3, POP_X+15, 0); popclear(); change_timing(0, rcd, rp, ras); break; case 3: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd =getval(POP_Y+3, POP_X+15, 0); change_timing(0, rcd, 0, 0); break; case 4: popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, rp, 0); break; case 5: popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, 0, ras); break; case 6: popclear(); amd64_option(); sflag++; popclear(); break; case 7: break; case 11: case 57: sflag++; /* 0/CR - Cancel */ break; } } } void get_menu(void) { int menu ; find_memctr(); disclaimer(); switch(ctrl) { case 0: menu = 2; break; case 1: case 2: case 3: case 4: menu = 0; break; case 5: menu = 1; break; case 6: menu = 0; break; default: menu = -1; break; } if (menu == -1) { popclear(); } else if (menu == 0) { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tCAS "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRCD "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRP "); cprint(POP_Y+7, POP_X+5, "(5) Modify tRAS "); cprint(POP_Y+8, POP_X+5, "(0) Cancel"); wait_keyup(); get_option(); } else if (menu == 1) { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); cprint(POP_Y+7, POP_X+5, "(0) Cancel"); wait_keyup(); get_option(); } else // AMD64 special menu { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); cprint(POP_Y+7, POP_X+5, "(5) AMD64 Options"); cprint(POP_Y+8, POP_X+5, "(0) Cancel"); wait_keyup(); get_option_1(); } } int get_cas(void) { int i852=0, cas=0; ulong drc, ddr; long *ptr; switch(ctrl) { case 0: ddr = 1; break; case 1: case 2: case 3: ddr = 1; break; case 4: pci_conf_read( 0, 0, 0, 0x44, 4, &ddr); ddr &= 0xFFFFC000; ptr=(long*)(ddr+0x120); drc = *ptr; if ((drc & 3) == 2) ddr = 2; else ddr = 1; break; case 5: ddr = 2; break; case 6: ddr = 1; i852 = 1; break; default: ddr = 1; } if (ddr == 1) { cprint(POP_Y+3, POP_X+8, "tCAS: "); cprint(POP_Y+5, POP_X+8, "(1) CAS 2.5 "); cprint(POP_Y+6, POP_X+8, "(2) CAS 2 "); if(!i852) { cprint(POP_Y+7, POP_X+8, "(3) CAS 3 "); } cas = getval(POP_Y+3, POP_X+15, 0); } else if (ddr == 2) { cprint(POP_Y+3, POP_X+8, "tCAS: "); cprint(POP_Y+5, POP_X+8, "(1) CAS 4 "); cprint(POP_Y+6, POP_X+8, "(2) CAS 3 "); cprint(POP_Y+7, POP_X+8, "(3) CAS 5 "); cas = getval(POP_Y+3, POP_X+15, 0); } else { cas = -1; } popclear(); 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... // ///////////////////////////////////////////////////////// void change_timing_i852(int cas, int rcd, int rp, int ras) { ulong dramtlr; ulong int1, int2; pci_conf_read(0, 0, 1, 0x60, 4, &dramtlr); // CAS Latency (tCAS) int1 = dramtlr & 0xFF9F; if (cas == 2) { int2 = int1 ^ 0x20; } else if (cas == 1) { int2 = int1; } else { int2 = dramtlr; } // RAS-To-CAS (tRCD) int1 = int2 & 0xFFF3; if (rcd == 2) { int2 = int1 ^ 0x8; } else if (rcd == 3) { int2 = int1 ^ 0x4; } else if (rcd == 4) { int2 = int1; } // else { int2 = int2; } // RAS Precharge (tRP) int1 = int2 & 0xFFFC; if (rp == 2) { int2 = int1 ^ 0x2; } else if (rp == 3) { int2 = int1 ^ 0x1; } else if (rp == 4) { int2 = int1; } // else { int2 = int2; } // RAS Active to precharge (tRAS) int1 = int2 & 0xF9FF; if (ras == 5) { int2 = int1 ^ 0x0600; } else if (ras == 6) { int2 = int1 ^ 0x0400; } else if (ras == 7) { int2 = int1 ^ 0x0200; } else if (ras == 8) { int2 = int1; } // else { int2 = int2; } pci_conf_write(0, 0, 1, 0x60, 4, int2); __delay(500); } void change_timing_i925(int cas, int rcd, int rp, int ras) { ulong int1, dev0, temp; long *ptr; //read MMRBAR pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x114); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0x70; if (rcd == 2) { temp = int1 ^ 0x70; } else if (rcd == 3) { temp = int1 ^ 0x60; } else if (rcd == 4) { temp = int1 ^ 0x50; } else if (rcd == 5) { temp = int1 ^ 0x40; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x7; if (rp == 2) { temp = int1 ^ 0x7; } else if (rp == 3) { temp = int1 ^ 0x6; } else if (rp == 4) { temp = int1 ^ 0x5; } else if (rp == 5) { temp = int1 ^ 0x4; } // else { temp = temp;} if (mem_ctr[ctrl].device == 0x2770 ) // Lakeport? { // RAS Active to precharge (tRAS) int1 = temp | 0xF80000; // bits 23:19 if (ras == 4) { temp = int1 ^ 0xD80000; } else if (ras == 5) { temp = int1 ^ 0xD00000; } else if (ras == 6) { temp = int1 ^ 0xC80000; } else if (ras == 7) { temp = int1 ^ 0xC00000; } else if (ras == 8) { temp = int1 ^ 0xB80000; } else if (ras == 9) { temp = int1 ^ 0xB00000; } else if (ras == 10) { temp = int1 ^ 0xA80000; } else if (ras == 11) { temp = int1 ^ 0xA00000; } else if (ras == 12) { temp = int1 ^ 0x980000; } else if (ras == 13) { temp = int1 ^ 0x900000; } else if (ras == 14) { temp = int1 ^ 0x880000; } else if (ras == 15) { temp = int1 ^ 0x800000; } // else { temp = temp;} } else { // RAS Active to precharge (tRAS) int1 = temp | 0xF00000; // bits 23:20 if (ras == 4) { temp = int1 ^ 0xB00000; } else if (ras == 5) { temp = int1 ^ 0xA00000; } else if (ras == 6) { temp = int1 ^ 0x900000; } else if (ras == 7) { temp = int1 ^ 0x800000; } else if (ras == 8) { temp = int1 ^ 0x700000; } else if (ras == 9) { temp = int1 ^ 0x600000; } else if (ras == 10) { temp = int1 ^ 0x500000; } else if (ras == 11) { temp = int1 ^ 0x400000; } else if (ras == 12) { temp = int1 ^ 0x300000; } else if (ras == 13) { temp = int1 ^ 0x200000; } else if (ras == 14) { temp = int1 ^ 0x100000; } else if (ras == 15) { temp = int1 ^ 0x000000; } // else { temp = temp;} } // CAS Latency (tCAS) int1 = temp | 0x0300; if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x100; } else if (cas == 3) { temp = int1 ^ 0x300; } // else { temp = temp;} *ptr = temp; __delay(500); return; } void change_timing_Lakeport(int cas, int rcd, int rp, int ras) { ulong int1, dev0, temp; long *ptr; //read MMRBAR pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x114); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0x70; if (rcd == 2) { temp = int1 ^ 0x70; } else if (rcd == 3) { temp = int1 ^ 0x60; } else if (rcd == 4) { temp = int1 ^ 0x50; } else if (rcd == 5) { temp = int1 ^ 0x40; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x7; if (rp == 2) { temp = int1 ^ 0x7; } else if (rp == 3) { temp = int1 ^ 0x6; } else if (rp == 4) { temp = int1 ^ 0x5; } else if (rp == 5) { temp = int1 ^ 0x4; } // else { temp = temp;} // CAS Latency (tCAS) int1 = temp | 0x0300; if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x100; } else if (cas == 3) { temp = int1 ^ 0x300; } // else { temp = temp;} *ptr = temp; __delay(500); return; } void change_timing_i875(int cas, int rcd, int rp, int ras){ ulong int1, dev6, temp; long *ptr; /* Read the MMR Base Address & Define the pointer from the BAR6 overflow register */ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); ptr=(long*)(dev6+0x60); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0xC; if (rcd == 2) { temp = int1 ^ 0x4; } else if (rcd == 3) { temp = int1 ^ 0x8; } else if (rcd == 4) { temp = int1 ^ 0xC; } else if (rcd == 5) { temp = int1 ^ 0xC; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x3; if (rp == 2) { temp = int1 ^ 0x1; } else if (rp == 3) { temp = int1 ^ 0x2; } else if (rp == 4) { temp = int1 ^ 0x3; } else if (rp == 5) { temp = int1 ^ 0x3; } // else { temp = temp;} // RAS Active to precharge (tRAS) int1 = temp | 0x380; if (ras == 5) { temp = int1 ^ 0x100; } else if (ras == 6) { temp = int1 ^ 0x180; } else if (ras == 7) { temp = int1 ^ 0x200; } else if (ras == 8) { temp = int1 ^ 0x280; } else if (ras == 9) { temp = int1 ^ 0x300; } else if (ras == 10) { temp = int1 ^ 0x380; } // else { temp = temp;} // CAS Latency (tCAS) int1 = temp | 0x60; if (cas == 1) { temp = int1 ^ 0x60; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x40; } else if (cas == 3) { temp = int1 ^ 0x20; } // else { temp = temp; } *ptr = temp; __delay(500); return; } void change_timing_nf2(int cas, int rcd, int rp, int ras) { ulong dramtlr, dramtlr2; ulong int1, int2; pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr); pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2); // CAS Latency (tCAS) int1 = dramtlr2 | 0x0070; if (cas == 1) { int2 = int1 ^ 0x10; } // cas = 2.5 else if (cas == 2) { int2 = int1 ^ 0x50; } else if (cas == 3) { int2 = int1 ^ 0x40; } else { int2 = dramtlr2; } pci_conf_write(0, 0, 1, 0xA0, 4, int2); // RAS-To-CAS (tRCD) int1 = dramtlr | 0x700000; if (rcd == 2) { int2 = int1 ^ 0x500000; } else if (rcd == 3) { int2 = int1 ^ 0x400000; } else if (rcd == 4) { int2 = int1 ^ 0x300000; } else if (rcd == 5) { int2 = int1 ^ 0x200000; } else if (rcd == 6) { int2 = int1 ^ 0x100000; } else { int2 = dramtlr;} // RAS Precharge (tRP) int1 = int2 | 0x70000000; if (rp == 2) { int2 = int1 ^ 0x50000000; } else if (rp == 3) { int2 = int1 ^ 0x40000000; } else if (rp == 4) { int2 = int1 ^ 0x30000000; } else if (rp == 5) { int2 = int1 ^ 0x20000000; } else if (rp == 6) { int2 = int1 ^ 0x10000000; } // else { int2 = int2;} // RAS Active to precharge (tRAS) int1 = int2 | 0x78000; if (ras == 4) { int2 = int1 ^ 0x58000; } else if (ras == 5) { int2 = int1 ^ 0x50000; } else if (ras == 6) { int2 = int1 ^ 0x48000; } else if (ras == 7) { int2 = int1 ^ 0x40000; } else if (ras == 8) { int2 = int1 ^ 0x38000; } else if (ras == 9) { int2 = int1 ^ 0x30000; } else if (ras == 10) { int2 = int1 ^ 0x28000; } else if (ras == 11) { int2 = int1 ^ 0x20000; } else if (ras == 12) { int2 = int1 ^ 0x18000; } else if (ras == 13) { int2 = int1 ^ 0x10000; } else if (ras == 14) { int2 = int1 ^ 0x08000; } // else { int2 = int2;} pci_conf_write(0, 0, 1, 0x90, 4, int2); __delay(500); } void change_timing_amd64(int cas, int rcd, int rp, int ras) { ulong dramtlr; ulong int1= 0x0; pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); // RAS-To-CAS (tRCD) int1 = dramtlr | 0x7000; if (rcd == 2) { dramtlr = int1 ^ 0x5000; } else if (rcd == 3) { dramtlr = int1 ^ 0x4000; } else if (rcd == 4) { dramtlr = int1 ^ 0x3000; } else if (rcd == 5) { dramtlr = int1 ^ 0x2000; } else if (rcd == 6) { dramtlr = int1 ^ 0x1000; } else if (rcd == 1) { dramtlr = int1 ^ 0x6000; } // else { dramtlr = dramtlr;} //RAS precharge (tRP) int1 = dramtlr | 0x7000000; if (rp == 2) { dramtlr = int1 ^ 0x5000000; } else if (rp == 3) { dramtlr = int1 ^ 0x4000000; } else if (rp == 1) { dramtlr = int1 ^ 0x6000000; } else if (rp == 4) { dramtlr = int1 ^ 0x3000000; } else if (rp == 5) { dramtlr = int1 ^ 0x2000000; } else if (rp == 6) { dramtlr = int1 ^ 0x1000000; } // else { dramtlr = dramtlr;} // RAS Active to precharge (tRAS) int1 = dramtlr | 0xF00000; if (ras == 5) { dramtlr = int1 ^ 0xA00000; } else if (ras == 6) { dramtlr = int1 ^ 0x900000; } else if (ras == 7) { dramtlr = int1 ^ 0x800000; } else if (ras == 8) { dramtlr = int1 ^ 0x700000; } else if (ras == 9) { dramtlr = int1 ^ 0x600000; } else if (ras == 10) { dramtlr = int1 ^ 0x500000; } else if (ras == 11) { dramtlr = int1 ^ 0x400000; } else if (ras == 12) { dramtlr = int1 ^ 0x300000; } else if (ras == 13) { dramtlr = int1 ^ 0x200000; } else if (ras == 14) { dramtlr = int1 ^ 0x100000; } // else { dramtlr = dramtlr;} // CAS Latency (tCAS) int1 = dramtlr | 0x7; // some changes will cause the system hang, tried Draminit to no avail if (cas == 1) { dramtlr = int1 ^ 0x2; } // cas 2.5 else if (cas == 2) { dramtlr = int1 ^ 0x6; } else if (cas == 3) { dramtlr = int1 ^ 0x5; } else if (cas == 4) { dramtlr = int1 ^ 0x7; } //cas 1.5 on a64 // else { dramtlr = dramtlr; } // pci_conf_read(0, 24, 2, 0x90, 4, &dramcr);// use dram init pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); __delay(500); //////////////////////////////////////////////////////////////// // trying using the draminit, but do not work } // copy from lib.c code to add delay to chipset timing modification void __delay(ulong loops) { 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)); } void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr) { ulong dramtlr; ulong int1= 0x0; pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); // Row Cycle time int1 = dramtlr | 0xF0; if (rct == 7 ) { dramtlr = int1 ^ 0xF0; } else if (rct == 8 ) { dramtlr = int1 ^ 0xE0; } else if (rct == 9 ) { dramtlr = int1 ^ 0xD0; } else if (rct == 10) { dramtlr = int1 ^ 0xC0; } else if (rct == 11) { dramtlr = int1 ^ 0xB0; } else if (rct == 12) { dramtlr = int1 ^ 0xA0; } else if (rct == 13) { dramtlr = int1 ^ 0x90; } else if (rct == 14) { dramtlr = int1 ^ 0x80; } else if (rct == 15) { dramtlr = int1 ^ 0x70; } else if (rct == 16) { dramtlr = int1 ^ 0x60; } else if (rct == 17) { dramtlr = int1 ^ 0x50; } else if (rct == 18) { dramtlr = int1 ^ 0x40; } else if (rct == 19) { dramtlr = int1 ^ 0x30; } else if (rct == 20) { dramtlr = int1 ^ 0x20; } // else { dramtlr = dramtlr;} //Active-avtive ras-ras delay int1 = dramtlr | 0x70000; if (rrd == 2) { dramtlr = int1 ^ 0x50000; } // 2 bus clocks else if (rrd == 3) { dramtlr = int1 ^ 0x40000; } // 3 bus clocks else if (rrd == 4) { dramtlr = int1 ^ 0x30000; } // 4 bus clocks // else { dramtlr = dramtlr;} //Write recovery time int1 = dramtlr | 0x10000000; if (wr == 2) { dramtlr = int1 ^ 0x10000000; } // 2 bus clocks else if (wr == 3) { dramtlr = int1 ^ 0x00000000; } // 3 bus clocks // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); __delay(500); ////////////////////////////////////////////// pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr); // Write-to read delay int1 = dramtlr | 0x1; if (wrt == 2) { dramtlr = int1 ^ 0x0; } else if (wrt == 1) { dramtlr = int1 ^ 0x1; } // else { dramtlr = dramtlr;} // Read-to Write delay int1 = dramtlr | 0x70; if (rwt == 1) { dramtlr = int1 ^ 0x70; } else if (rwt == 2) { dramtlr = int1 ^ 0x60; } else if (rwt == 3) { dramtlr = int1 ^ 0x50; } else if (rwt == 4) { dramtlr = int1 ^ 0x40; } else if (rwt == 5) { dramtlr = int1 ^ 0x30; } else if (rwt == 6) { dramtlr = int1 ^ 0x20; } // else { dramtlr = dramtlr;} //Refresh Rate int1 = dramtlr | 0x1800; if (ref == 1) { dramtlr = int1 ^ 0x1800; } // 15.6us else if (ref == 2) { dramtlr = int1 ^ 0x1000; } // 7.8us else if (ref == 3) { dramtlr = int1 ^ 0x0800; } // 3.9us // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x8c, 4, dramtlr); __delay(500); ///////////////////////////////////// pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr); // Enable 2t command int1 = dramtlr | 0x10000000; if (en2t == 2) { dramtlr = int1 ^ 0x00000000; } // 2T else if (en2t == 1) { dramtlr = int1 ^ 0x10000000; } // 1T // else { dramtlr = dramtlr;} // Read Write queue bypass count int1 = dramtlr | 0xC000; if (rwqb == 2) { dramtlr = int1 ^ 0xC000; } else if (rwqb == 4) { dramtlr = int1 ^ 0x8000; } else if (rwqb == 8) { dramtlr = int1 ^ 0x4000; } else if (rwqb == 16) { dramtlr = int1 ^ 0x0000; } // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x90, 4, dramtlr); __delay(500); restart(); } memtest86+-4.20/screen_buffer.h0000644000000000000000000000140011517067470015030 0ustar rootroot/* --*- C -*-- * * By Jani Averbach, Jaa@iki.fi, 2001 * * 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 #include "config.h" char get_scrn_buf(const int y, const int x); void set_scrn_buf(const int y, const int x, const char val); void clear_screen_buf(void); void tty_print_region(const int pi_top,const int pi_left, const int pi_bottom,const int pi_right); void tty_print_line(int y, int x, const char *text); void tty_print_screen(void); void print_error(char *pstr); #endif /* SCREEN_BUFFER_H_1D10F83B_INCLUDED */ memtest86+-4.20/elf.h0000644000000000000000000005662611517067470013012 0ustar rootroot#ifndef ELF_H #define ELF_H #define EI_NIDENT 16 /* Size of e_ident array. */ /* Values for e_type. */ #define ET_NONE 0 /* No file type */ #define ET_REL 1 /* Relocatable file */ #define ET_EXEC 2 /* Executable file */ #define ET_DYN 3 /* Shared object file */ #define ET_CORE 4 /* Core file */ /* Values for e_machine (architecute). */ #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_68K 4 /* Motorola m68k family */ #define EM_88K 5 /* Motorola m88k family */ #define EM_486 6 /* Perhaps disused */ #define EM_860 7 /* Intel 80860 */ #define EM_MIPS 8 /* MIPS R3000 big-endian */ #define EM_S370 9 /* IBM System/370 */ #define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ #define EM_PARISC 15 /* HPPA */ #define EM_VPP500 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ #define EM_960 19 /* Intel 80960 */ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* PowerPC 64-bit */ #define EM_S390 22 /* IBM S390 */ #define EM_V800 36 /* NEC V800 series */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH-32 */ #define EM_RCE 39 /* Motorola RCE */ #define EM_ARM 40 /* ARM */ #define EM_FAKE_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Hitachi SH */ #define EM_SPARCV9 43 /* SPARC v9 64-bit */ #define EM_TRICORE 44 /* Siemens Tricore */ #define EM_ARC 45 /* Argonaut RISC Core */ #define EM_H8_300 46 /* Hitachi H8/300 */ #define EM_H8_300H 47 /* Hitachi H8/300H */ #define EM_H8S 48 /* Hitachi H8S */ #define EM_H8_500 49 /* Hitachi H8/500 */ #define EM_IA_64 50 /* Intel Merced */ #define EM_MIPS_X 51 /* Stanford MIPS-X */ #define EM_COLDFIRE 52 /* Motorola Coldfire */ #define EM_68HC12 53 /* Motorola M68HC12 */ #define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ #define EM_PCP 55 /* Siemens PCP */ #define EM_NCPU 56 /* Sony nCPU embeeded RISC */ #define EM_NDR1 57 /* Denso NDR1 microprocessor */ #define EM_STARCORE 58 /* Motorola Start*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ #define EM_ST100 60 /* STMicroelectronic ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ #define EM_X86_64 62 /* AMD x86-64 architecture */ #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_ST7 68 /* STmicroelectronics ST7 8 bit mc */ #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ #define EM_SVX 73 /* Silicon Graphics SVx */ #define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */ #define EM_VAX 75 /* Digital VAX */ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ #define EM_HUANY 81 /* Harvard University machine-independent object files */ #define EM_PRISM 82 /* SiTera Prism */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ #define EM_FR30 84 /* Fujitsu FR30 */ #define EM_D10V 85 /* Mitsubishi D10V */ #define EM_D30V 86 /* Mitsubishi D30V */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Mitsubishi M32R */ #define EM_MN10300 89 /* Matsushita MN10300 */ #define EM_MN10200 90 /* Matsushita MN10200 */ #define EM_PJ 91 /* picoJava */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_NUM 95 /* Values for p_type. */ #define PT_NULL 0 /* Unused entry. */ #define PT_LOAD 1 /* Loadable segment. */ #define PT_DYNAMIC 2 /* Dynamic linking information segment. */ #define PT_INTERP 3 /* Pathname of interpreter. */ #define PT_NOTE 4 /* Auxiliary information. */ #define PT_SHLIB 5 /* Reserved (not used). */ #define PT_PHDR 6 /* Location of program header itself. */ /* Values for p_flags. */ #define PF_X 0x1 /* Executable. */ #define PF_W 0x2 /* Writable. */ #define PF_R 0x4 /* Readable. */ #define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */ #define EI_MAG0 0 #define ELFMAG0 0x7f #define EI_MAG1 1 #define ELFMAG1 'E' #define EI_MAG2 2 #define ELFMAG2 'L' #define EI_MAG3 3 #define ELFMAG3 'F' #define ELFMAG "\177ELF" #define EI_CLASS 4 /* File class byte index */ #define ELFCLASSNONE 0 /* Invalid class */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encodeing byte index */ #define ELFDATANONE 0 /* Invalid data encoding */ #define ELFDATA2LSB 1 /* 2's complement little endian */ #define ELFDATA2MSB 2 /* 2's complement big endian */ #define EI_VERSION 6 /* File version byte index */ /* Value must be EV_CURRENT */ #define EV_NONE 0 /* Invalid ELF Version */ #define EV_CURRENT 1 /* Current version */ #define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */ #ifndef ASSEMBLY #include "stdint.h" /* * ELF definitions common to all 32-bit architectures. */ typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef uint16_t Elf32_Section; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Size; typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Half; typedef uint64_t Elf64_Off; typedef uint16_t Elf64_Section; typedef int32_t Elf64_Sword; typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Size; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; /* * ELF header. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf32_Half e_type; /* File type. */ Elf32_Half e_machine; /* Machine architecture. */ Elf32_Word e_version; /* ELF format version. */ Elf32_Addr e_entry; /* Entry point. */ Elf32_Off e_phoff; /* Program header file offset. */ Elf32_Off e_shoff; /* Section header file offset. */ Elf32_Word e_flags; /* Architecture-specific flags. */ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ Elf32_Half e_phentsize; /* Size of program header entry. */ Elf32_Half e_phnum; /* Number of program header entries. */ Elf32_Half e_shentsize; /* Size of section header entry. */ Elf32_Half e_shnum; /* Number of section header entries. */ Elf32_Half e_shstrndx; /* Section name strings section. */ } Elf32_Ehdr; typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf64_Half e_type; /* File type. */ Elf64_Half e_machine; /* Machine architecture. */ Elf64_Word e_version; /* ELF format version. */ Elf64_Addr e_entry; /* Entry point. */ Elf64_Off e_phoff; /* Program header file offset. */ Elf64_Off e_shoff; /* Section header file offset. */ Elf64_Word e_flags; /* Architecture-specific flags. */ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ Elf64_Half e_phentsize; /* Size of program header entry. */ Elf64_Half e_phnum; /* Number of program header entries. */ Elf64_Half e_shentsize; /* Size of section header entry. */ Elf64_Half e_shnum; /* Number of section header entries. */ Elf64_Half e_shstrndx; /* Section name strings section. */ } Elf64_Ehdr; /* * Program header. */ typedef struct { Elf32_Word p_type; /* Entry type. */ Elf32_Off p_offset; /* File offset of contents. */ Elf32_Addr p_vaddr; /* Virtual address (not used). */ Elf32_Addr p_paddr; /* Physical address. */ Elf32_Size p_filesz; /* Size of contents in file. */ Elf32_Size p_memsz; /* Size of contents in memory. */ Elf32_Word p_flags; /* Access permission flags. */ Elf32_Size p_align; /* Alignment in memory and file. */ } Elf32_Phdr; typedef struct { Elf64_Word p_type; /* Entry type. */ Elf64_Word p_flags; /* Access permission flags. */ Elf64_Off p_offset; /* File offset of contents. */ Elf64_Addr p_vaddr; /* Virtual address (not used). */ Elf64_Addr p_paddr; /* Physical address. */ Elf64_Size p_filesz; /* Size of contents in file. */ Elf64_Size p_memsz; /* Size of contents in memory. */ Elf64_Size p_align; /* Alignment in memory and file. */ } Elf64_Phdr; /* Dynamic section entry. */ typedef struct { Elf32_Sword d_tag; /* Dynamic entry type */ union { Elf32_Word d_val; /* Integer value */ Elf32_Addr d_ptr; /* Address value */ } d_un; } Elf32_Dyn; typedef struct { Elf64_Sxword d_tag; /* Dynamic entry type */ union { Elf64_Xword d_val; /* Integer value */ Elf64_Addr d_ptr; /* Address value */ } d_un; } Elf64_Dyn; /* Legal values for d_tag (dynamic entry type). */ #define DT_NULL 0 /* Marks end of dynamic section */ #define DT_NEEDED 1 /* Name of needed library */ #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ #define DT_PLTGOT 3 /* Processor defined value */ #define DT_HASH 4 /* Address of symbol hash table */ #define DT_STRTAB 5 /* Address of string table */ #define DT_SYMTAB 6 /* Address of symbol table */ #define DT_RELA 7 /* Address of Rela relocs */ #define DT_RELASZ 8 /* Total size of Rela relocs */ #define DT_RELAENT 9 /* Size of one Rela reloc */ #define DT_STRSZ 10 /* Size of string table */ #define DT_SYMENT 11 /* Size of one symbol table entry */ #define DT_INIT 12 /* Address of init function */ #define DT_FINI 13 /* Address of termination function */ #define DT_SONAME 14 /* Name of shared object */ #define DT_RPATH 15 /* Library search path (deprecated) */ #define DT_SYMBOLIC 16 /* Start symbol search here */ #define DT_REL 17 /* Address of Rel relocs */ #define DT_RELSZ 18 /* Total size of Rel relocs */ #define DT_RELENT 19 /* Size of one Rel reloc */ #define DT_PLTREL 20 /* Type of reloc in PLT */ #define DT_DEBUG 21 /* For debugging; unspecified */ #define DT_TEXTREL 22 /* Reloc might modify .text */ #define DT_JMPREL 23 /* Address of PLT relocs */ #define DT_BIND_NOW 24 /* Process relocations of object */ #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ #define DT_RUNPATH 29 /* Library search path */ #define DT_FLAGS 30 /* Flags for the object being loaded */ #define DT_ENCODING 32 /* Start of encoded range */ #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ #define DT_NUM 34 /* Number used */ #define DT_LOOS 0x6000000d /* Start of OS-specific */ #define DT_HIOS 0x6ffff000 /* End of OS-specific */ #define DT_LOPROC 0x70000000 /* Start of processor-specific */ #define DT_HIPROC 0x7fffffff /* End of processor-specific */ #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. */ #define DT_VALRNGLO 0x6ffffd00 #define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ #define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ #define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ #define DT_CHECKSUM 0x6ffffdf8 #define DT_PLTPADSZ 0x6ffffdf9 #define DT_MOVEENT 0x6ffffdfa #define DT_MOVESZ 0x6ffffdfb #define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting the following DT_* entry. */ #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ #define DT_VALRNGHI 0x6ffffdff #define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ #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. 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 */ #define DT_CONFIG 0x6ffffefa /* Configuration information. */ #define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ #define DT_AUDIT 0x6ffffefc /* Object auditing. */ #define DT_PLTPAD 0x6ffffefd /* PLT padding. */ #define DT_MOVETAB 0x6ffffefe /* Move table. */ #define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ #define DT_ADDRRNGHI 0x6ffffeff #define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ #define DT_ADDRNUM 10 /* The versioning entry types. The next are defined as part of the GNU extension. */ #define DT_VERSYM 0x6ffffff0 #define DT_RELACOUNT 0x6ffffff9 #define DT_RELCOUNT 0x6ffffffa /* These were chosen by Sun. */ #define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ #define DT_VERDEF 0x6ffffffc /* Address of version definition table */ #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ #define DT_VERNEED 0x6ffffffe /* Address of table with needed versions */ #define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define DT_VERSIONTAGNUM 16 /* Sun added these machine-independent extensions in the "processor-specific" 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) #define DT_EXTRANUM 3 /* Values of `d_un.d_val' in the DT_FLAGS entry. */ #define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ #define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ #define DF_TEXTREL 0x00000004 /* Object contains text relocations */ #define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ #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. */ #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. */ #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ #define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ #define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ #define DF_1_TRANS 0x00000200 #define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ #define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ #define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ #define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ #define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ #define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ #define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ /* Flags for the feature selection in DT_FEATURE_1. */ #define DTF_1_PARINIT 0x00000001 #define DTF_1_CONFEXP 0x00000002 /* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ #define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ #define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not generally available. */ /* Special section indices. */ #define SHN_UNDEF 0 /* Undefined section */ #define SHN_LORESERVE 0xff00 /* Start of reserved indices */ #define SHN_LOPROC 0xff00 /* Start of processor-specific */ #define SHN_HIPROC 0xff1f /* End of processor-specific */ #define SHN_LOOS 0xff20 /* Start of OS-specific */ #define SHN_HIOS 0xff3f /* End of OS-specific */ #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ #define SHN_COMMON 0xfff2 /* Associated symbol is common */ #define SHN_XINDEX 0xffff /* Index is in extra table. */ #define SHN_HIRESERVE 0xffff /* End of reserved indices */ /* Legal values for sh_type (section type). */ #define SHT_NULL 0 /* Section header table entry unused */ #define SHT_PROGBITS 1 /* Program data */ #define SHT_SYMTAB 2 /* Symbol table */ #define SHT_STRTAB 3 /* String table */ #define SHT_RELA 4 /* Relocation entries with addends */ #define SHT_HASH 5 /* Symbol hash table */ #define SHT_DYNAMIC 6 /* Dynamic linking information */ #define SHT_NOTE 7 /* Notes */ #define SHT_NOBITS 8 /* Program space with no data (bss) */ #define SHT_REL 9 /* Relocation entries, no addends */ #define SHT_SHLIB 10 /* Reserved */ #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ #define SHT_INIT_ARRAY 14 /* Array of constructors */ #define SHT_FINI_ARRAY 15 /* Array of destructors */ #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ #define SHT_GROUP 17 /* Section group */ #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ #define SHT_NUM 19 /* Number of defined types. */ #define SHT_LOOS 0x60000000 /* Start OS-specific */ #define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ #define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ #define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_COMDAT 0x6ffffffb #define SHT_SUNW_syminfo 0x6ffffffc #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ #define SHT_HIOS 0x6fffffff /* End OS-specific type */ #define SHT_LOPROC 0x70000000 /* Start of processor-specific */ #define SHT_HIPROC 0x7fffffff /* End of processor-specific */ #define SHT_LOUSER 0x80000000 /* Start of application-specific */ #define SHT_HIUSER 0x8fffffff /* End of application-specific */ /* Legal values for sh_flags (section flags). */ #define SHF_WRITE (1 << 0) /* Writable */ #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ #define SHF_EXECINSTR (1 << 2) /* Executable */ #define SHF_MERGE (1 << 4) /* Might be merged */ #define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ #define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ #define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ #define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling required */ #define SHF_GROUP (1 << 9) /* Section is member of a group. */ #define SHF_TLS (1 << 10) /* Section hold thread-local data. */ #define SHF_MASKOS 0x0ff00000 /* OS-specific. */ #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ /* Section group handling. */ #define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ /* Symbol table entry. */ typedef struct { Elf32_Word st_name; /* Symbol name (string tbl index) */ Elf32_Addr st_value; /* Symbol value */ Elf32_Word st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf32_Section st_shndx; /* Section index */ } Elf32_Sym; typedef struct { Elf64_Word st_name; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf64_Section st_shndx; /* Section index */ Elf64_Addr st_value; /* Symbol value */ Elf64_Xword st_size; /* Symbol size */ } Elf64_Sym; /* Relocation table entry without addend (in section of type SHT_REL). */ typedef struct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ } 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. */ /* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ typedef struct { Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ } Elf64_Rel; /* Relocation table entry with addend (in section of type SHT_RELA). */ typedef struct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ Elf32_Sword r_addend; /* Addend */ } Elf32_Rela; typedef struct { Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ Elf64_Sxword r_addend; /* Addend */ } Elf64_Rela; /* How to extract and insert information held in the r_info field. */ #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 ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) #define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) +(type)) /* Intel 80386 specific definitions. */ /* i386 relocs. */ #define R_386_NONE 0 /* No reloc */ #define R_386_32 1 /* Direct 32 bit */ #define R_386_PC32 2 /* PC relative 32 bit */ #define R_386_GOT32 3 /* 32 bit GOT entry */ #define R_386_PLT32 4 /* 32 bit PLT address */ #define R_386_COPY 5 /* Copy symbol at runtime */ #define R_386_GLOB_DAT 6 /* Create GOT entry */ #define R_386_JMP_SLOT 7 /* Create PLT entry */ #define R_386_RELATIVE 8 /* Adjust by program base */ #define R_386_GOTOFF 9 /* 32 bit offset to GOT */ #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ #define R_386_32PLT 11 #define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ #define R_386_TLS_IE 15 /* Address of GOT entry for static TLS block offset */ #define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block offset */ #define R_386_TLS_LE 17 /* Offset relative to static TLS block */ #define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of general dynamic thread local data */ #define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of local dynamic thread local data in LE code */ #define R_386_16 20 #define R_386_PC16 21 #define R_386_8 22 #define R_386_PC8 23 #define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic thread local data */ #define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ #define R_386_TLS_GD_CALL 26 /* Relocation for call to __tls_get_addr() */ #define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ #define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic thread local data in LE code */ #define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ #define R_386_TLS_LDM_CALL 30 /* Relocation for call to __tls_get_addr() in LDM code */ #define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ #define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ #define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS block offset */ #define R_386_TLS_LE_32 34 /* Negated offset relative to static 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_NUM 38 #endif /* ASSEMBLY */ #endif /* ELF_H */ memtest86+-4.20/cpuid.h0000644000000000000000000001414311517067470013334 0ustar rootroot/* * 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 */ 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() { return cpuid_data0.eax; } static inline unsigned cpuid_max_ext_func() { return cpuid_data80.eax; } /* 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]; 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]; uint32_t uint32_array[CPUID_BRAND_LENGTH]; } cpuid_brand_string_t; /* Typedef for storing CPUID Version */ typedef union { uint32_t flat; struct { uint32_t stepping:4; /* Bit 0 */ uint32_t model:4; uint32_t family:4; uint32_t processorType:2; uint32_t reserved1514:2; uint32_t extendedModel:4; uint32_t extendedFamily:8; uint32_t reserved3128:4; /* Bit 31 */ } bits; } cpuid_version_t; /* Typedef for storing CPUID Processor Information */ typedef union { uint32_t flat; struct { uint32_t brandIndex:8; /* Bit 0 */ uint32_t cflushLineSize:8; uint32_t logicalProcessorCount:8; uint32_t apicID:8; /* Bit 31 */ } bits; } cpuid_proc_info_t; /* Typedef for storing CPUID Feature flags */ 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 psn:1; uint32_t cflush:1; uint32_t reserved20:1; uint32_t ds:1; uint32_t acpi:1; uint32_t mmx:1; uint32_t fxsr:1; uint32_t sse:1; uint32_t sse2:1; 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 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 */ } 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 memtest86+-4.20/linuxbios.c0000644000000000000000000000744711517067470014250 0ustar rootroot#include "linuxbios_tables.h" #include "test.h" static unsigned long ip_compute_csum(void *addr, unsigned long length) { uint16_t *ptr; unsigned long sum; unsigned long len; unsigned long laddr; /* compute an ip style checksum */ laddr = (unsigned long )addr; sum = 0; if (laddr & 1) { uint16_t buffer; unsigned char *ptr; /* copy the first byte into a 2 byte buffer. * This way automatically handles the endian question * of which byte (low or high) the last byte goes in. */ buffer = 0; ptr = addr; memmove(&buffer, ptr, 1); sum += buffer; if (sum > 0xFFFF) sum -= 0xFFFF; length -= 1; addr = ptr +1; } len = length >> 1; ptr = addr; while (len--) { sum += *(ptr++); if (sum > 0xFFFF) sum -= 0xFFFF; } addr = ptr; if (length & 1) { uint16_t buffer; unsigned char *ptr; /* copy the last byte into a 2 byte buffer. * This way automatically handles the endian question * of which byte (low or high) the last byte goes in. */ buffer = 0; ptr = addr; memmove(&buffer, ptr, 1); sum += buffer; if (sum > 0xFFFF) sum -= 0xFFFF; } return (~sum) & 0xFFFF; } #define for_each_lbrec(head, rec) \ for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ (rec->size >= 1) && \ ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \ rec = (struct lb_record *)(((char *)rec) + rec->size)) static int count_lb_records(struct lb_header *head) { struct lb_record *rec; int count; count = 0; for_each_lbrec(head, rec) { count++; } return count; } static struct lb_header * __find_lb_table(unsigned long start, unsigned long end) { unsigned long addr; /* For now be stupid.... */ for(addr = start; addr < end; addr += 16) { struct lb_header *head = (struct lb_header *)addr; struct lb_record *recs = (struct lb_record *)(addr + sizeof(*head)); if (memcmp(head->signature, "LBIO", 4) != 0) continue; if (head->header_bytes != sizeof(*head)) continue; if (ip_compute_csum((unsigned char *)head, sizeof(*head)) != 0) continue; if (ip_compute_csum((unsigned char *)recs, head->table_bytes) != head->table_checksum) continue; if (count_lb_records(head) != head->table_entries) continue; return head; }; return 0; } static struct lb_header * find_lb_table(void) { struct lb_header *head; head = 0; if (!head) { /* First try at address 0 */ head = __find_lb_table(0x00000, 0x1000); } if (!head) { /* Then try at address 0xf0000 */ head = __find_lb_table(0xf0000, 0x100000); } return head; } int query_linuxbios(void) { struct lb_header *head; struct lb_record *rec; struct lb_memory *mem; struct lb_forward *forward; int i, entries; head = find_lb_table(); if (!head) { return 0; } /* coreboot also can forward the table to the high tables area. */ rec = (struct lb_record *)(((char *)head) + sizeof(*head)); if (rec->tag == LB_TAG_FORWARD) { forward = (struct lb_forward *)rec; head = (struct lb_header *)(unsigned long)(forward->forward); if (!head) { return 0; } } mem = 0; for_each_lbrec(head, rec) { if (rec->tag == LB_TAG_MEMORY) { mem = (struct lb_memory *)rec; break; } } if (!mem) { return 1; } entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); if (entries == 0) return 1; mem_info.e820_nr = 0; for(i = 0; i < entries; i++) { unsigned long long start; unsigned long long size; unsigned long type; if (i >= E820MAX) { break; } start = mem->map[i].start; size = mem->map[i].size; type = (mem->map[i].type == LB_MEM_RAM)?E820_RAM: E820_RESERVED; mem_info.e820[mem_info.e820_nr].addr = start; mem_info.e820[mem_info.e820_nr].size = size; mem_info.e820[mem_info.e820_nr].type = type; mem_info.e820_nr++; } return 1; } memtest86+-4.20/random.c0000644000000000000000000000175411517067470013507 0ustar rootroot/* 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. */ /******************************************************************/ unsigned int rand( void ); /* returns a random 32-bit integer */ void rand_seed( unsigned int, unsigned int ); /* seed the generator */ /* return a random float >= 0 and < 1 */ #define rand_float ((double)rand() / 4294967296.0) static unsigned int SEED_X = 521288629; static unsigned int SEED_Y = 362436069; unsigned int rand () { static unsigned int a = 18000, b = 30903; 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 ) { if (seed1) SEED_X = seed1; /* use default seeds if parameter is 0 */ if (seed2) SEED_Y = seed2; } memtest86+-4.20/spd.c0000644000000000000000000003022611517067470013011 0ustar rootroot/* 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) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #include "test.h" #include "io.h" #include "pci.h" #include "msr.h" #include "spd.h" #include "screen_buffer.h" #include "jedec_id.h" #define NULL 0 #define SMBHSTSTS smbusbase #define SMBHSTCNT smbusbase + 2 #define SMBHSTCMD smbusbase + 3 #define SMBHSTADD smbusbase + 4 #define SMBHSTDAT smbusbase + 5 extern void wait_keyup(); int smbdev, smbfun; unsigned short smbusbase; unsigned char spd[256]; char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0}; static void ich5_get_smb(void) { unsigned long x; int result; result = pci_conf_read(0, smbdev, smbfun, 0x20, 2, &x); if (result == 0) smbusbase = (unsigned short) x & 0xFFFE; } unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd) { int l1, h1, l2, h2; unsigned long long t; __outb(0x1f, SMBHSTSTS); // reset SMBus Controller __outb(0xff, SMBHSTDAT); while(__inb(SMBHSTSTS) & 0x01); // wait until ready __outb(cmd, SMBHSTCMD); __outb((adr << 1) | 0x01, SMBHSTADD); __outb(0x48, SMBHSTCNT); rdtsc(l1, h1); //cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished rdtsc(l2, h2); t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec; if (t > 10) break; // break after 10ms } return __inb(SMBHSTDAT); } static int ich5_read_spd(int dimmadr) { int x; spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0); if (spd[0] == 0xff) return -1; // no spd here for (x = 1; x < 256; x++) { spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x); } return 0; } static void us15w_get_smb(void) { unsigned long x; int result; result = pci_conf_read(0, 0x1f, 0, 0x40, 2, &x); if (result == 0) smbusbase = (unsigned short) x & 0xFFC0; } unsigned char us15w_smb_read_byte(unsigned char adr, unsigned char cmd) { int l1, h1, l2, h2; unsigned long long t; //__outb(0x00, smbusbase + 1); // reset SMBus Controller //__outb(0x00, smbusbase + 6); //while((__inb(smbusbase + 1) & 0x08) != 0); // wait until ready __outb(0x02, smbusbase + 0); // Byte read __outb(cmd, smbusbase + 5); // Command __outb(0x07, smbusbase + 1); // Clear status __outb((adr << 1) | 0x01, smbusbase + 4); // DIMM address __outb(0x12, smbusbase + 0); // Start //while (((__inb(smbusbase + 1) & 0x08) == 0)) {} // wait til busy rdtsc(l1, h1); cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar while (((__inb(smbusbase + 1) & 0x01) == 0) || ((__inb(smbusbase + 1) & 0x08) != 0)) { // wait til command finished rdtsc(l2, h2); t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec; if (t > 10) break; // break after 10ms } return __inb(smbusbase + 6); } 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 for (x = 1; x < 256; x++) { spd[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x); } return 0; } struct pci_smbus_controller { unsigned vendor; unsigned device; char *name; void (*get_adr)(void); int (*read_spd)(int dimmadr); }; static struct pci_smbus_controller smbcontrollers[] = { {0x8086, 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} }; int find_smb_controller(void) { int i = 0; unsigned long valuev, valued; for (smbdev = 0; smbdev < 32; smbdev++) { for (smbfun = 0; smbfun < 8; smbfun++) { pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev); if (valuev != 0xFFFF) { // if there is something look what's it.. for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller if (valuev == smbcontrollers[i].vendor) { pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id if (valued == smbcontrollers[i].device) { return i; } } } } } } return -1; } void get_spd_spec(void) { int index; int h, i, j, z; int k = 0; int module_size; int curcol; int temp_nbd; index = find_smb_controller(); if (index == -1) { // Unknown SMBUS Controller, exit return; } smbcontrollers[index].get_adr(); cprint(LINE_SPD-2, 0, "Memory SPD Informations"); cprint(LINE_SPD-1, 0, "-----------------------------------"); for (j = 0; j < 8; j++) { if (smbcontrollers[index].read_spd(j) == 0) { curcol = 1; if(spd[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); 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; // Then module jedec speed switch(spd[12]) { default: case 20: cprint(LINE_SPD+k, curcol, "PC3-6400"); curcol += 8; break; case 15: cprint(LINE_SPD+k, curcol, "PC3-8500"); curcol += 8; break; case 12: cprint(LINE_SPD+k, curcol, "PC3-10600"); curcol += 9; break; case 10: cprint(LINE_SPD+k, curcol, "PC3-12800"); curcol += 9; break; case 8: cprint(LINE_SPD+k, curcol, "PC3-15000"); curcol += 9; break; case 6: cprint(LINE_SPD+k, curcol, "PC3-16000"); curcol += 9; break; } curcol++; // Then print module infos (manufacturer & part number) spd[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) { // We are here if a Jedec manufacturer is detected cprint(LINE_SPD+k, curcol, "-"); curcol += 2; cprint(LINE_SPD+k, curcol, jep106[i].name); for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } curcol++; // Display module serial number for (h = 128; h < 146; h++) { cprint(16+k, curcol, convert_hex_to_char(spd[h])); curcol++; } // Detect XMP Memory if(spd[176] == 0x0C && spd[177] == 0x4A) { cprint(LINE_SPD+k, curcol, "*XMP*"); } } } } // We enter this function if DDR2 is detected if(spd[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]); 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; // Then module jedec speed float ddr2_speed, byte1, byte2; byte1 = (spd[9] >> 4) * 10; byte2 = spd[9] & 0xF; ddr2_speed = 1 / (byte1 + byte2) * 10000; 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; // Then print module infos (manufacturer & part number) int ccode = 0; for(i = 64; i < 72; i++) { if(spd[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) { // We are here if a Jedec manufacturer is detected cprint(LINE_SPD+k, curcol, "-"); curcol += 2; cprint(LINE_SPD+k, curcol, jep106[i].name); for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } curcol++; // Display module serial number for (h = 73; h < 91; h++) { cprint(16+k, curcol, convert_hex_to_char(spd[h])); curcol++; } } } } k++; } } } void show_spd(void) { int index; int i, j; int flag = 0; pop2up(); wait_keyup(); index = find_smb_controller(); if (index == -1) { cprint(POP2_Y, POP2_X+1, "SMBus Controller not known"); while (!get_key()); wait_keyup(); pop2down(); return; } else cprint(POP2_Y, POP2_X+1, "SPD Data: Slot"); smbcontrollers[index].get_adr(); for (j = 0; j < 16; j++) { if (smbcontrollers[index].read_spd(j) == 0) { dprint(POP2_Y, POP2_X + 15, j, 2, 0); for (i = 0; i < 256; i++) { hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd[i], 2); } flag = 0; while(!flag) { if (get_key()) flag++; } wait_keyup(); } } pop2down(); } int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks) { int module_size; switch(sdram_capacity) { case 0: module_size = 256; break; case 1: module_size = 512; break; default: case 2: module_size = 1024; break; case 3: module_size = 2048; break; case 4: module_size = 4096; break; case 5: module_size = 8192; break; case 6: module_size = 16384; break; } module_size /= 8; switch(prim_bus_width) { case 0: module_size *= 8; break; case 1: module_size *= 16; break; case 2: module_size *= 32; break; case 3: module_size *= 64; break; } switch(sdram_width) { case 0: module_size /= 4; break; case 1: module_size /= 8; break; case 2: module_size /= 16; break; case 3: module_size /= 32; break; } module_size *= (ranks + 1); return module_size; } int get_ddr2_module_size(int rank_density_byte, int rank_num_byte) { int module_size; switch(rank_density_byte) { case 1: module_size = 1024; break; case 2: module_size = 2048; break; case 4: module_size = 4096; break; case 8: module_size = 8192; break; case 16: module_size = 16384; break; case 32: module_size = 128; break; case 64: module_size = 256; break; default: case 128: module_size = 512; break; } module_size *= (rank_num_byte & 7) + 1; return module_size; } struct ascii_map { unsigned hex_code; char *name; }; char* convert_hex_to_char(unsigned hex_org) { static char buf[2] = " "; if (hex_org >= 0x20 && hex_org < 0x80) { buf[0] = hex_org; } else { //buf[0] = '\0'; buf[0] = ' '; } return buf; }memtest86+-4.20/main.c0000644000000000000000000003723011517067470013151 0ustar rootroot/* main.c - MemTest-86 Version 3.2 * * 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 "test.h" #include "defs.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} }; 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[] = { { 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 }, { 0x800000, 0x880000 }, { 0x880000, 0x900000 }, { 0x900000, 0x980000 }, { 0x980000, 0xA00000 }, { 0xA00000, 0xA80000 }, { 0xA80000, 0xB00000 }, { 0xB00000, 0xB80000 }, { 0xB80000, 0xC00000 }, { 0xC00000, 0xC80000 }, { 0xC80000, 0xD00000 }, { 0xD00000, 0xD80000 }, { 0xD80000, 0xE00000 }, { 0xE00000, 0xE80000 }, { 0xE80000, 0xF00000 }, { 0xF00000, 0xF80000 }, { 0xF80000, 0x1000000 }, }; #if (LOW_TEST_ADR > (640*1024)) #error LOW_TEST_ADR must be below 640K #endif static int find_ticks_for_test(int ch, int test); static int compute_segments(int win); void find_ticks_for_pass(void); static void __run_at(unsigned long addr) { /* Copy memtest86+ code */ memmove((void *)addr, &_start, _end - _start); /* Jump to the start address */ p = (ulong *)(addr + startup_32 - _start); goto *p; } static unsigned long run_at_addr = 0xffffffff; static void run_at(unsigned long addr) { unsigned long start; unsigned long len; run_at_addr = addr; 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); } /* command line passing using the 'old' boot protocol */ #define MK_PTR(seg,off) ((void*)(((unsigned long)(seg) << 4) + (off))) #define OLD_CL_MAGIC_ADDR ((unsigned short*) MK_PTR(INITSEG,0x20)) #define OLD_CL_MAGIC 0xA33F #define OLD_CL_OFFSET_ADDR ((unsigned short*) MK_PTR(INITSEG,0x22)) static void parse_command_line(void) { char *cmdline; if (cmdline_parsed) return; if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC) return; unsigned short offset = *OLD_CL_OFFSET_ADDR; cmdline = MK_PTR(INITSEG, offset); /* skip leading spaces */ while (*cmdline == ' ') cmdline++; while (*cmdline) { if (!strncmp(cmdline, "console=", 8)) { cmdline += 8; serial_console_setup(cmdline); } /* go to the next parameter */ while (*cmdline && *cmdline != ' ') cmdline++; while (*cmdline == ' ') cmdline++; } cmdline_parsed = 1; } void do_test(void) { int i = 0, j = 0; unsigned long chunks; unsigned long lo, hi; parse_command_line(); /* If we have a partial relocation finish it */ if (run_at_addr == (unsigned long)&_start) { run_at_addr = 0xffffffff; } else if (run_at_addr != 0xffffffff) { __run_at(run_at_addr); } /* 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; /* Set relocation address at 16Mb if there is enough memory */ if (v->pmap[v->msegs-1].end > 0x1100) { high_test_adr = 0x01000000; } windows[1].end = (high_test_adr >> 12); firsttime = 1; } bail = 0; /* 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; } 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; } #endif cprint(LINE_RANGE, COL_MID+28, " Relocated"); } else { cprint(LINE_RANGE, COL_MID+28, " "); } /* Update display of memory segments being tested */ lo = page_of(v->map[0].start); hi = page_of(v->map[segs -1].end); 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) ); 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 */ if (v->testsel >= 0) { v->test = v->testsel; } if (v->pass == 0) { c_iter = tseq[v->test].iter/2; } else { c_iter = tseq[v->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); 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) */ p1 = 0; p2 = ~p1; movinv1(c_iter,p1,p2); BAILOUT; /* Switch patterns */ p2 = p1; p1 = ~p2; movinv1(c_iter,p1,p2); BAILOUT; break; case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */ 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); BAILOUT; /* Switch patterns */ p2 = p1; p1 = ~p2; movinv1(c_iter,p1,p2); BAILOUT } break; case 2: /* Moving inversions, 32 bit shifting pattern (test #6) */ for (i=0, p1=1; p1; p1=p1<<1, i++) { movinv32(c_iter,p1, 1, 0x80000000, 0, i); BAILOUT movinv32(c_iter,~p1, 0xfffffffe, 0x7fffffff, 1, i); BAILOUT } break; case 3: /* Modulo 20 check, all ones and zeros (unused) */ p1=0; for (i=0; i>1) { p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24); for (i=0; i= 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); } } void restart() { int i; volatile char *pp; /* clear variables */ firsttime = 0; v->test = 0; v->pass = 0; v->msg_line = 0; v->ecount = 0; v->ecc_ecount = 0; /* Clear the screen */ for(i=0, pp=(char *)(SCREEN_ADR+0); i<80*24; i++, pp+=2) { *pp = ' '; } run_at(LOW_TEST_ADR); } void find_ticks_for_pass(void) { int i, j, chunks; 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; ((itestsel >= 0) { if (i != v->testsel) { continue; } } v->pass_ticks += find_ticks_for_test(chunks, i); } } static int find_ticks_for_test(int ch, int test) { int ticks=0, c; /* Set the number of iterations. We only do half of the iterations */ /* on the first pass */ if (v->pass == 0 && FIRST_PASS_HALF_ITERATIONS) { c = tseq[test].iter/2; } else { c = tseq[test].iter; } switch(tseq[test].pat) { case 0: /* Moving inversions, all ones and zeros (test #2) */ ticks = 2 + 4 * c; break; case 1: /* Moving inversions, 8 bit walking ones and zeros (test #3) */ ticks = 24 + 24 * c; break; case 2: /* Moving inversions, 32 bit shifting pattern, very long */ ticks = (1 + c * 2) * 80; break; case 3: /* Modulo 20 check, all ones and zeros (unused) */ ticks = (2 + c) * 40; break; case 4: /* Modulo 20 check, 8 bit pattern (unused) */ ticks = (2 + c) * 40 * 8; break; case 5: /* Address test, walking ones (test #0) */ ticks = 4; break; case 6: /* Address test, own address (test #1) */ ticks = 2; break; case 7: /* Block move (test #5) */ ticks = 2 + c; break; case 8: /* Bit fade test (test #9) */ ticks = 1; break; case 9: /* Random Data Sequence (test #7) */ ticks = 3 * c; break; case 10: /* Random Data (test #4) */ ticks = c + 4 * c; break; case 11: /* Modulo 20 check, Random pattern (test #8) */ ticks = 4 * 40 * c; break; } return ticks*ch; } static int compute_segments(int win) { unsigned long wstart, wend; int i; /* Compute the window I am testing memory in */ wstart = windows[win].start; wend = windows[win].end; segs = 0; /* Now reduce my window to the area of memory I want to test */ if (wstart < v->plim_lower) { wstart = v->plim_lower; } if (wend > v->plim_upper) { wend = v->plim_upper; } if (wstart >= wend) { return(0); } /* List the segments being tested */ for (i=0; i< v->msegs; i++) { unsigned long start, end; start = v->pmap[i].start; end = v->pmap[i].end; if (start <= wstart) { start = wstart; } if (end >= wend) { end = wend; } #if 0 cprint(LINE_SCROLL+(2*i), 0, " ("); hprint(LINE_SCROLL+(2*i), 2, start); cprint(LINE_SCROLL+(2*i), 10, ", "); hprint(LINE_SCROLL+(2*i), 12, end); cprint(LINE_SCROLL+(2*i), 20, ") "); cprint(LINE_SCROLL+(2*i), 22, "r("); hprint(LINE_SCROLL+(2*i), 24, wstart); cprint(LINE_SCROLL+(2*i), 32, ", "); hprint(LINE_SCROLL+(2*i), 34, wend); cprint(LINE_SCROLL+(2*i), 42, ") "); cprint(LINE_SCROLL+(2*i), 44, "p("); hprint(LINE_SCROLL+(2*i), 46, v->plim_lower); cprint(LINE_SCROLL+(2*i), 54, ", "); hprint(LINE_SCROLL+(2*i), 56, v->plim_upper); cprint(LINE_SCROLL+(2*i), 64, ") "); cprint(LINE_SCROLL+(2*i+1), 0, "w("); hprint(LINE_SCROLL+(2*i+1), 2, windows[win].start); cprint(LINE_SCROLL+(2*i+1), 10, ", "); hprint(LINE_SCROLL+(2*i+1), 12, windows[win].end); cprint(LINE_SCROLL+(2*i+1), 20, ") "); cprint(LINE_SCROLL+(2*i+1), 22, "m("); hprint(LINE_SCROLL+(2*i+1), 24, v->pmap[i].start); cprint(LINE_SCROLL+(2*i+1), 32, ", "); hprint(LINE_SCROLL+(2*i+1), 34, v->pmap[i].end); cprint(LINE_SCROLL+(2*i+1), 42, ") "); cprint(LINE_SCROLL+(2*i+1), 44, "i="); hprint(LINE_SCROLL+(2*i+1), 46, i); cprint(LINE_SCROLL+(2*i+2), 0, " " " "); cprint(LINE_SCROLL+(2*i+3), 0, " " " "); #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); #if 0 cprint(LINE_SCROLL+(2*i+1), 54, " sg: "); hprint(LINE_SCROLL+(2*i+1), 61, sg); #endif segs++; } } return (segs); } memtest86+-4.20/reloc.c0000644000000000000000000001671411517067470013335 0ustar rootroot#include #include "stdint.h" #include "elf.h" #include #define __ELF_NATIVE_CLASS 32 #define ELF_MACHINE_NO_RELA 1 /* We use this macro to refer to ELF types independent of the native wordsize. `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ #define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) #define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) #define _ElfW_1(e,w,t) e##w##t /* We use this macro to refer to ELF types independent of the native wordsize. `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) #define assert(expr) ((void) 0) /* This #define produces dynamic linking inline functions for bootstrap relocation instead of general-purpose relocation. */ #define RTLD_BOOTSTRAP struct link_map { ElfW(Addr) l_addr; /* Current load address */ ElfW(Addr) ll_addr; /* Last load address */ ElfW(Dyn) *l_ld; /* Indexed pointers to dynamic section. [0,DT_NUM) are indexed by the processor-independent tags. [DT_NUM,DT_NUM+DT_PROCNUM) are indexed by the tag minus DT_LOPROC. [DT_NUM+DT_PROCNUM,DT_NUM+DT_PROCNUM+DT_EXTRANUM) are indexed by DT_EXTRATAGIDX(tagvalue) and [DT_NUM+DT_PROCNUM, DT_NUM+DT_PROCNUM+DT_EXTRANUM) are indexed by DT_EXTRATAGIDX(tagvalue) (see ). */ ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]; }; /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_dynamic (void) { register Elf32_Addr *got asm ("%ebx"); return *got; } /* Return the run-time load address of the shared object. */ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_load_address (void) { Elf32_Addr addr; asm volatile ("leal _start@GOTOFF(%%ebx), %0\n" : "=r" (addr) : : "cc"); return addr; } /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ static inline void elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, const Elf32_Sym *sym, Elf32_Addr *const reloc_addr) { Elf32_Addr ls_addr, s_addr; Elf32_Addr value; if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE) { *reloc_addr += map->l_addr - map->ll_addr; return; } if (ELF32_R_TYPE(reloc->r_info) == R_386_NONE) { return; } value = sym->st_value; /* Every section except the undefined section has a base of map->l_addr */ ls_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->ll_addr; s_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->l_addr; switch (ELF32_R_TYPE (reloc->r_info)) { case R_386_COPY: { /* Roll memcpy by hand as we don't have function calls yet. */ unsigned char *dest, *src; long i; dest = (unsigned char *)reloc_addr; src = (unsigned char *)(value + s_addr); for(i = 0; i < sym->st_size; i++) { dest[i] = src[i]; } } break; case R_386_GLOB_DAT: *reloc_addr = s_addr + value; break; case R_386_JMP_SLOT: *reloc_addr = s_addr + value; break; case R_386_32: if (map->ll_addr == 0) { *reloc_addr += value; } *reloc_addr += s_addr - ls_addr; break; case R_386_PC32: if (map->ll_addr == 0) { *reloc_addr += value - reloc->r_offset; } *reloc_addr += (s_addr - map->l_addr) - (ls_addr - map->ll_addr); break; default: assert (! "unexpected dynamic reloc type"); break; } } /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ static inline void __attribute__ ((unused)) elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]) { if (! dyn) return; while (dyn->d_tag != DT_NULL) { if (dyn->d_tag < DT_NUM) info[dyn->d_tag] = dyn; else if (dyn->d_tag >= DT_LOPROC && dyn->d_tag < DT_LOPROC + DT_PROCNUM) info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn; else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM) info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM ] = dyn; else assert (! "bad dynamic tag"); ++dyn; } 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; if (info[DT_SYMTAB] != NULL) info[DT_SYMTAB]->d_un.d_ptr += l_addr; #if ! ELF_MACHINE_NO_RELA if (info[DT_RELA] != NULL) { assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela))); info[DT_RELA]->d_un.d_ptr += l_addr; } #endif #if ! ELF_MACHINE_NO_REL if (info[DT_REL] != NULL) { assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); info[DT_REL]->d_un.d_ptr += l_addr; } #endif if (info[DT_PLTREL] != NULL) { #if ELF_MACHINE_NO_RELA assert (info[DT_PLTREL]->d_un.d_val == DT_REL); #elif ELF_MACHINE_NO_REL assert (info[DT_PLTREL]->d_un.d_val == DT_RELA); #else assert (info[DT_PLTREL]->d_un.d_val == DT_REL || info[DT_PLTREL]->d_un.d_val == DT_RELA); #endif } if (info[DT_JMPREL] != NULL) info[DT_JMPREL]->d_un.d_ptr += l_addr; } /* Perform the relocations in MAP on the running program image as specified by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT relocations; they should be set up to call _dl_runtime_resolve, rather than fully resolved now. */ static inline void elf_dynamic_do_rel (struct link_map *map, ElfW(Addr) reladdr, ElfW(Addr) relsize) { const ElfW(Rel) *r = (const void *) reladdr; const ElfW(Rel) *end = (const void *) (reladdr + relsize); 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)); } } void _dl_start(void) { static Elf32_Addr last_load_address = 0; struct link_map map; size_t cnt; /* Partly clean the `map' structure up. Don't use `memset' since it might nor be built in or inlined and we cannot make function calls at this point. */ for (cnt = 0; cnt < sizeof(map.l_info) / sizeof(map.l_info[0]); ++cnt) { map.l_info[cnt] = 0; } /* Get the last load address */ map.ll_addr = last_load_address; /* 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. */ #if !ELF_MACHINE_NO_REL 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, 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, 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, map.l_info[DT_JMPREL]->d_un.d_ptr, map.l_info[DT_PLTRELSZ]->d_un.d_val); } #endif /* Now life is sane; we can call functions and access global data. Set up to use the operating system facilities, and find out from the operating system's program loader where to find the program header table in core. Put the rest of _dl_start into a separate function, that way the compiler cannot put accesses to the GOT before ELF_DYNAMIC_RELOCATE. */ return; } memtest86+-4.20/controller.h0000644000000000000000000000026111517067470014407 0ustar rootroot#ifndef MEMTEST_CONTROLLER_H #define MEMTEST_CONTROLLER_H void find_controller(void); void poll_errors(void); void set_ecc_polling(int val); #endif /* MEMTEST_CONTROLLER_H */ memtest86+-4.20/controller.c0000644000000000000000000030361611517067470014414 0ustar rootroot/* 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) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #include "defs.h" #include "config.h" #include "test.h" #include "pci.h" #include "controller.h" #include "spd.h" #include "test.h" int col, col2; 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)) #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : /* no outputs */ \ : "c" (msr), "a" (val1), "d" (val2)) /* controller ECC capabilities and mode */ #define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */ #define __ECC_DETECT 2 /* Can detect ECC errors */ #define __ECC_CORRECT 4 /* Can correct some ECC errors */ #define __ECC_SCRUB 8 /* Can scrub corrected ECC errors */ #define __ECC_CHIPKILL 16 /* Can corrected multi-errors */ #define ECC_UNKNOWN (~0UL) /* Unknown error correcting ability/status */ #define ECC_NONE 0 /* Doesnt support ECC (or is BIOS disabled) */ #define ECC_RESERVED __ECC_UNEXPECTED /* Reserved ECC type */ #define ECC_DETECT __ECC_DETECT #define ECC_CORRECT (__ECC_DETECT | __ECC_CORRECT) #define ECC_CHIPKILL (__ECC_DETECT | __ECC_CORRECT | __ECC_CHIPKILL) #define ECC_SCRUB (__ECC_DETECT | __ECC_CORRECT | __ECC_SCRUB) static struct ecc_info { int index; int poll; unsigned bus; unsigned dev; unsigned fn; unsigned cap; unsigned mode; } ctrl = { .index = 0, /* I know of no case where the memory controller is not on the * host bridge, and the host bridge is not on bus 0 device 0 * fn 0. But just in case leave these as variables. */ .bus = 0, .dev = 0, .fn = 0, /* Properties of the current memory controller */ .cap = ECC_UNKNOWN, .mode = ECC_UNKNOWN, }; struct pci_memory_controller { unsigned vendor; unsigned device; char *name; int tested; void (*poll_fsb)(void); void (*poll_timings)(void); void (*setup_ecc)(void); void (*poll_errors)(void); }; void print_timings_info(float cas, int rcd, int rp, int ras) { /* Now, we could print some additionnals timings infos) */ cprint(LINE_CPU+6, col2 +1, "/ CAS : "); col2 += 9; // CAS Latency (tCAS) if (cas == 1.5) { cprint(LINE_CPU+6, col2, "1.5"); col2 += 3; } else if (cas == 2.5) { cprint(LINE_CPU+6, col2, "2.5"); col2 += 3; } else if (cas < 10) { dprint(LINE_CPU+6, col2, cas, 1, 0); col2 += 1; } else { dprint(LINE_CPU+6, col2, cas, 2, 0); col2 += 2; } cprint(LINE_CPU+6, col2, "-"); col2 += 1; // RAS-To-CAS (tRCD) if (rcd < 10) { dprint(LINE_CPU+6, col2, rcd, 1, 0); col2 += 1; } else { dprint(LINE_CPU+6, col2, rcd, 2, 0); col2 += 2; } cprint(LINE_CPU+6, col2, "-"); col2 += 1; // RAS Precharge (tRP) if (rp < 10) { dprint(LINE_CPU+6, col2, rp, 1, 0); col2 += 1; } else { dprint(LINE_CPU+6, col2, rp, 2, 0); col2 += 2; } cprint(LINE_CPU+6, col2, "-"); col2 += 1; // RAS Active to precharge (tRAS) if (ras < 10) { dprint(LINE_CPU+6, col2, ras, 1, 0); col2 += 2; } else { dprint(LINE_CPU+6, col2, ras, 2, 0); col2 += 3; } } 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; } cprint(LINE_CPU+6, col2, ")"); col2 += 1; } static void poll_fsb_nothing(void) { /* Code to run for no specific fsb detection */ return; } static void poll_timings_nothing(void) { /* Code to run for no specific timings detection */ return; } static void 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; ctrl.mode = ECC_NONE; } static void poll_nothing(void) { /* Code to run when we don't know how, or can't ask the memory * controller about memory errors. */ return; } static void setup_wmr(void) { // Activate MMR I/O ulong dev0; ctrl.cap = ECC_CORRECT; 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; } static void setup_nhm(void) { static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; unsigned long did, vid, mc_control, mc_ssrcontrol; int i; //Nehalem supports Scrubbing */ ctrl.cap = ECC_SCRUB; 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); vid &= 0xFFFF; did &= 0xFF00; 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 */ pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control); if((mc_control >> 4) & 1) { ctrl.mode = ECC_CORRECT; pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); if(mc_ssrcontrol & 3) { ctrl.mode = ECC_SCRUB; } } } static void setup_nhm32(void) { static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; unsigned long did, vid, mc_control, mc_ssrcontrol; int i; //Nehalem supports Scrubbing */ ctrl.cap = ECC_SCRUB; 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); vid &= 0xFFFF; did &= 0xFF00; 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 */ pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); if((mc_control >> 1) & 1) { ctrl.mode = ECC_CORRECT; pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); if(mc_ssrcontrol & 1) { ctrl.mode = ECC_SCRUB; } } } static void setup_amd64(void) { static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL }; unsigned long nbxcfg; unsigned int mcgsrl; unsigned int mcgsth; unsigned long mcanb; unsigned long dramcl; /* All AMD64 support Chipkill */ ctrl.cap = ECC_CHIPKILL; /* Check First if ECC DRAM Modules are used */ pci_conf_read(0, 24, 2, 0x90, 4, &dramcl); if (((cpu_id.ext >> 16) & 0xF) >= 4) { /* NEW K8 0Fh Family 90 nm */ if ((dramcl >> 19)&1){ /* Fill in the correct memory capabilites */ pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); ctrl.mode = ddim[(nbxcfg >> 22)&3]; } else { ctrl.mode = ECC_NONE; } /* Enable NB ECC Logging by MSR Write */ rdmsr(0x017B, mcgsrl, mcgsth); wrmsr(0x017B, 0x10, mcgsth); /* Clear any previous error */ pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); } else { /* OLD K8 130 nm */ if ((dramcl >> 17)&1){ /* Fill in the correct memory capabilites */ pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); ctrl.mode = ddim[(nbxcfg >> 22)&3]; } else { ctrl.mode = ECC_NONE; } /* Enable NB ECC Logging by MSR Write */ rdmsr(0x017B, mcgsrl, mcgsth); wrmsr(0x017B, 0x10, mcgsth); /* Clear any previous error */ pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC ); } } static void setup_k10(void) { static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL }; unsigned long nbxcfg; unsigned int mcgsrl; unsigned int mcgsth; unsigned long mcanb; unsigned long dramcl; ulong msr_low, msr_high; /* All AMD64 support Chipkill */ ctrl.cap = ECC_CHIPKILL; /* Check First if ECC DRAM Modules are used */ pci_conf_read(0, 24, 2, 0x90, 4, &dramcl); if ((dramcl >> 19)&1){ /* Fill in the correct memory capabilites */ pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg); ctrl.mode = ddim[(nbxcfg >> 22)&3]; } else { ctrl.mode = ECC_NONE; } /* Enable NB ECC Logging by MSR Write */ rdmsr(0x017B, mcgsrl, mcgsth); wrmsr(0x017B, 0x10, mcgsth); /* Clear any previous error */ pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); /* 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) { unsigned long mcanb; unsigned long page, offset; unsigned long celog_syndrome; unsigned long mcanb_add; pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb); if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) { /* Find out about the first correctable error */ /* Syndrome code -> bits use a complex matrix. Will add this later */ /* Read the error location */ pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add); /* Read the syndrome */ celog_syndrome = (mcanb >> 15)&0xFF; /* Parse the error location */ page = (mcanb_add >> 12); offset = (mcanb_add >> 3) & 0xFFF; /* Report the error */ print_ecc_err(page, offset, 1, celog_syndrome, 0); /* Clear the error registers */ pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF ); } if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) { /* Found out about the first uncorrectable error */ /* Read the error location */ pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add); /* Parse the error location */ page = (mcanb_add >> 12); offset = (mcanb_add >> 3) & 0xFFF; /* Report the error */ print_ecc_err(page, offset, 0, 0, 0); /* Clear the error registers */ pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF ); } } static void setup_amd751(void) { unsigned long dram_status; /* Fill in the correct memory capabilites */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status); ctrl.cap = ECC_CORRECT; ctrl.mode = (dram_status & (1 << 2))?ECC_CORRECT: ECC_NONE; } static void poll_amd751(void) { unsigned long ecc_status; unsigned long bank_addr; unsigned long bank_info; unsigned long page; int bits; int i; /* Read the error status */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status); if (ecc_status & (3 << 8)) { for(i = 0; i < 6; i++) { if (!(ecc_status & (1 << i))) { continue; } /* Find the bank the error occured on */ bank_addr = 0x40 + (i << 1); /* Now get the information on the erroring bank */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info); /* Parse the error location and error type */ page = (bank_info & 0xFF80) << 4; bits = (((ecc_status >> 8) &3) == 2)?1:2; /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, 0, 0); } /* Clear the error status */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0); } } /* Still waiting for the CORRECT intel datasheet static void setup_i85x(void) { unsigned long drc; ctrl.cap = ECC_CORRECT; pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc); ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE; } */ static void setup_amd76x(void) { static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT }; unsigned long ecc_mode_status; /* Fill in the correct memory capabilites */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status); ctrl.cap = ECC_CORRECT; ctrl.mode = ddim[(ecc_mode_status >> 10)&3]; } static void poll_amd76x(void) { unsigned long ecc_mode_status; unsigned long bank_addr; unsigned long bank_info; unsigned long page; /* Read the error status */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status); /* Multibit error */ if (ecc_mode_status & (1 << 9)) { /* Find the bank the error occured on */ bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2); /* Now get the information on the erroring bank */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info); /* Parse the error location and error type */ page = (bank_info & 0xFF800000) >> 12; /* Report the error */ print_ecc_err(page, 0, 1, 0, 0); } /* Singlebit error */ if (ecc_mode_status & (1 << 8)) { /* Find the bank the error occured on */ bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2); /* Now get the information on the erroring bank */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info); /* Parse the error location and error type */ page = (bank_info & 0xFF800000) >> 12; /* Report the error */ print_ecc_err(page, 0, 0, 0, 0); } /* Clear the error status */ if (ecc_mode_status & (3 << 8)) { pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status); } } static void setup_cnb20(void) { /* Fill in the correct memory capabilites */ ctrl.cap = ECC_CORRECT; /* FIXME add ECC error polling. I don't have the documentation * do it right now. */ } static void setup_E5400(void) { unsigned long mcs; /* Read the hardware capabilities */ pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs); /* Fill in the correct memory capabilities */ ctrl.mode = 0; ctrl.cap = ECC_SCRUB; /* Checking and correcting enabled */ if (((mcs >> 5) & 1) == 1) { ctrl.mode |= ECC_CORRECT; } /* scrub enabled */ if (((mcs >> 7) & 1) == 1) { ctrl.mode |= __ECC_SCRUB; } } static void setup_iE7xxx(void) { unsigned long mchcfgns; unsigned long drc; unsigned long device; unsigned long dvnp; /* Read the hardare capabilities */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns); pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc); /* This is a check for E7205 */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device); /* Fill in the correct memory capabilities */ ctrl.mode = 0; ctrl.cap = ECC_CORRECT; /* checking and correcting enabled */ if (((drc >> 20) & 3) == 2) { ctrl.mode |= ECC_CORRECT; } /* E7205 doesn't support scrubbing */ if (device != 0x255d) { /* scrub enabled */ /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */ ctrl.cap = ECC_SCRUB; if (mchcfgns & 1) { ctrl.mode |= __ECC_SCRUB; } /* Now, we can active Dev1/Fun1 */ /* Thanks to Tyan for providing us the board to solve this */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp); pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xE0, 2, (dvnp & 0xFE)); /* Clear any routing of ECC errors to interrupts that the BIOS might have set up */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0); pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0); pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0); } /* Clear any prexisting error reports */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3); pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3); } static void setup_iE7520(void) { unsigned long mchscrb; unsigned long drc; unsigned long dvnp1; /* Read the hardare capabilities */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb); pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc); /* Fill in the correct memory capabilities */ ctrl.mode = 0; ctrl.cap = ECC_CORRECT; /* Checking and correcting enabled */ if (((drc >> 20) & 3) != 0) { ctrl.mode |= ECC_CORRECT; } /* scrub enabled */ ctrl.cap = ECC_SCRUB; if ((mchscrb & 3) == 2) { ctrl.mode |= __ECC_SCRUB; } /* Now, we can activate Fun1 */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1); pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xF4, 1, (dvnp1 | 0x20)); /* 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; unsigned long nerr; pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr); pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr); if (ferr & 1) { /* Find out about the first correctable error */ unsigned long celog_add; unsigned long celog_syndrome; unsigned long page; /* Read the error location */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add); /* Read the syndrome */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome); /* Parse the error location */ page = (celog_add & 0x0FFFFFC0) >> 6; /* Report the error */ print_ecc_err(page, 0, 1, celog_syndrome, 0); /* Clear Bit */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3); } if (ferr & 2) { /* Found out about the first uncorrectable error */ unsigned long uccelog_add; unsigned long page; /* Read the error location */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add); /* Parse the error location */ page = (uccelog_add & 0x0FFFFFC0) >> 6; /* Report the error */ print_ecc_err(page, 0, 0, 0, 0); /* Clear Bit */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3); } /* 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) { static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT }; unsigned long nbxcfg; /* Fill in the correct memory capabilites */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg); ctrl.cap = ECC_CORRECT; ctrl.mode = ddim[(nbxcfg >> 7)&3]; } static void poll_i440gx(void) { unsigned long errsts; unsigned long page; int bits; /* 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 */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap); /* Parse the error location and error type */ page = (eap & 0xFFFFF000) >> 12; bits = 0; if (eap &3) { bits = ((eap & 3) == 1)?1:2; } if (bits) { /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, 0, 0); } /* Clear the error status */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 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 }; unsigned long mchcfg; /* 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_i840(void) { unsigned long errsts; unsigned long page; unsigned long syndrome; int channel; int bits; /* 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 */ 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 */ page = (eap & 0xFFFFF800) >> 11; channel = eap & 1; syndrome = derrctl_sts & 0xFF; bits = ((errsts & 3) == 1)?1:2; /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); /* 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) { long *ptr; ulong dev0, dev6 ; /* Fill in the correct memory capabilites */ ctrl.cap = ECC_CORRECT; ctrl.mode = ECC_NONE; /* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */ /* Activate Device 6 */ pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0); pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2)); /* Activate Device 6 MMR */ pci_conf_read( 0, 6, 0, 0x04, 2, &dev6); pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2)); /* Read the MMR Base Address & Define the pointer*/ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); ptr=(long*)(dev6+0x68); if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; } /* Reseting state */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81); } static void setup_i925(void) { // Activate MMR I/O ulong dev0, drc; unsigned long tolm; long *ptr; pci_conf_read( 0, 0, 0, 0x54, 4, &dev0); dev0 = dev0 | 0x10000000; pci_conf_write( 0, 0, 0, 0x54, 4, dev0); // CDH start pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); if (!(dev0 & 0xFFFFC000)) { pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm); pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8); } // CDH end // ECC Checking ctrl.cap = ECC_CORRECT; dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x120); drc = *ptr & 0xFFFFFFFF; if (((drc >> 20) & 3) == 2) { pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3); ctrl.mode = ECC_CORRECT; } else { ctrl.mode = ECC_NONE; } } static void setup_p35(void) { // Activate MMR I/O ulong dev0, capid0; pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); if (!(dev0 & 0x1)) { pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1); } // ECC Checking (No poll on X38/48 for now) pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0); if ((capid0 >> 8) & 1) { ctrl.cap = ECC_NONE; } else { ctrl.cap = ECC_CORRECT; } ctrl.mode = ECC_NONE; } static void poll_i875(void) { unsigned long errsts; unsigned long page; unsigned long des; unsigned long syndrome; int channel; int bits; /* 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 */ 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 */ page = (eap & 0xFFFFF000) >> 12; syndrome = derrsyn; channel = des & 1; bits = (errsts & 0x80)?0:1; /* Report the error */ print_ecc_err(page, 0, bits, syndrome, channel); /* 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 */ 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 */ 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 */ 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 */ offset = (eap & 0xFE) << 4; page = (eap & 0x3FFFFFFE) >> 8; syndrome = derrsyn; bits = ((errsts & 3) == 1)?1:2; /* Report the error */ print_ecc_err(page, offset, bits==1?1:0, syndrome, 0); /* 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 */ 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 */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); if (errsts & 3) { unsigned long eap; /* Read the error location */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap); /* Parse the error location and error type */ page = (eap & 0xFFFFF000) >> 4; syndrome = eap & 0xFF; bits = ((errsts & 3) == 1)?1:2; /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, syndrome, 0); /* 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 */ 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; unsigned long page; unsigned long syndrome; int channel; int bits; /* 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 */ 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 */ page = (eap & 0xFFFFF800) >> 11; channel = eap & 1; syndrome = derrctl_sts & 0xFF; bits = ((errsts & 3) == 1)?1:2; /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); /* Clear the error status */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); } } static void setup_i860(void) { static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED }; unsigned long mchcfg; unsigned long errsts; /* 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 */ 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; unsigned long page; unsigned char syndrome; int channel; int bits; /* 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 */ 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 */ page = (eap & 0xFFFFFE00) >> 9; channel = eap & 1; syndrome = derrctl_sts & 0xFF; bits = ((errsts & 3) == 1)?1:2; /* Report the error */ print_ecc_err(page, 0, bits==1?1:0, syndrome, channel); /* 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; unsigned long page; unsigned char syndrome; int channel; int bits; int errocc; pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts); errocc = errsts & 3; if ((errocc == 1) || (errocc == 2)) { unsigned long eap, offset; unsigned long derrctl_sts; /* 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 */ channel = eap & 1; eap = eap & 0xFFFFFF80; page = eap >> 12; offset = eap & 0xFFF; syndrome = derrctl_sts & 0xFF; bits = errocc & 1; /* Report the error */ print_ecc_err(page, offset, bits, syndrome, channel); /* Clear the error status */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); } else if (errocc == 3) { pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3); } } static void poll_iE7520(void) { unsigned long ferr; unsigned long nerr; pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr); pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr); if (ferr & 0x0101) { /* Find out about the first correctable error */ unsigned long celog_add; unsigned long celog_syndrome; unsigned long page; /* Read the error location */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add); /* Read the syndrome */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome); /* Parse the error location */ page = (celog_add & 0x7FFFFFFC) >> 2; /* Report the error */ print_ecc_err(page, 0, 1, celog_syndrome, 0); /* Clear Bit */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101); } if (ferr & 0x4646) { /* Found out about the first uncorrectable error */ unsigned long uccelog_add; unsigned long page; /* Read the error location */ pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add); /* Parse the error location */ page = (uccelog_add & 0x7FFFFFFC) >> 2; /* Report the error */ print_ecc_err(page, 0, 0, 0, 0); /* Clear Bit */ pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646); } /* 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 ------------------ */ /* --------------------------------------------------------------------- */ static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5}; static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0}; static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15}; static float getP4PMmultiplier(void) { unsigned int msr_lo, msr_hi; float coef; /* Find multiplier (by MSR) */ if (cpu_id.type == 6) { if((cpu_id.feature_flag >> 7) & 1) { rdmsr(0x198, msr_lo, msr_hi); coef = ((msr_lo >> 8) & 0x1F); if ((msr_lo >> 14) & 0x1) { coef = coef + 0.5f; } } else { rdmsr(0x2A, msr_lo, msr_hi); coef = (msr_lo >> 22) & 0x1F; } } else { if (cpu_id.model < 2) { rdmsr(0x2A, msr_lo, msr_hi); coef = (msr_lo >> 8) & 0xF; coef = p4model1ratios[(int)coef]; } else { rdmsr(0x2C, msr_lo, msr_hi); coef = (msr_lo >> 24) & 0x1F; } } return coef; } static float getNHMmultiplier(void) { unsigned int msr_lo, msr_hi; float coef; /* Find multiplier (by MSR) */ /* First, check if Flexible Ratio is Enabled */ rdmsr(0x194, msr_lo, msr_hi); if((msr_lo >> 16) & 1){ coef = (msr_lo >> 8) & 0xFF; } else { rdmsr(0xCE, msr_lo, msr_hi); coef = (msr_lo >> 8) & 0xFF; } 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; } return coef; } void getIntelPNS(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" ); 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)); 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++; } col -= 16; } static void poll_fsb_amd64(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long fid, temp2; unsigned long dramchr; float clockratio; double dramclock; float coef = 10; /* 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) { rdmsr(0xc0010042, mcgsrl, mcgsth); fid = (mcgsrl & 0x3F); } else { rdmsr(0xc0010015, mcgsrl, mcgsth); fid = ((mcgsrl >> 24)& 0x3F); } /* Extreme simplification. */ coef = ( fid / 2 ) + 4.0; /* Support for .5 coef */ if (fid & 1) { coef = coef + 0.5; } /* Next, we need the clock ratio */ if (((cpu_id.ext >> 16) & 0xF) >= 4) { /* K8 0FH */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr & 0x7); clockratio = coef; switch (temp2) { case 0x0: clockratio = (int)(coef); break; case 0x1: clockratio = (int)(coef * 3.0f/4.0f); break; case 0x2: clockratio = (int)(coef * 3.0f/5.0f); break; case 0x3: clockratio = (int)(coef * 3.0f/6.0f); break; } } else { /* OLD K8 */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr >> 20) & 0x7; clockratio = coef; switch (temp2) { case 0x0: clockratio = (int)(coef * 2.0f); break; case 0x2: clockratio = (int)((coef * 3.0f/2.0f) + 0.81f); break; case 0x4: clockratio = (int)((coef * 4.0f/3.0f) + 0.81f); break; case 0x5: clockratio = (int)((coef * 6.0f/5.0f) + 0.81f); break; case 0x6: clockratio = (int)((coef * 10.0f/9.0f) + 0.81f); break; case 0x7: clockratio = (int)(coef + 0.81f); break; } } /* Compute the final DRAM Clock */ dramclock = (extclock /1000) / clockratio; /* ...and print */ print_fsb_info(dramclock, "RAM : ", "DDR"); } static void poll_fsb_k10(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long temp2; 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)"); } /* First, we need the clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr & 0x7); switch (temp2) { case 0x7: temp2++; case 0x6: temp2++; case 0x5: temp2++; case 0x4: temp2++; default: temp2 += 3; } /* Compute the final DRAM Clock */ if (((cpu_id.ext >> 20) & 0xFF) == 1) dramclock = ((temp2 * 200) / 3.0) + 0.25; else { unsigned long target; unsigned long dx; unsigned divisor; target = temp2 * 400; /* Get the FID by MSR */ rdmsr(0xc0010071, mcgsrl, mcgsth); pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId); if ( mainPllId & 0x40 ) mainPllId &= 0x3F; else mainPllId = 8; /* FID for 1600 */ mcgsth = (mcgsth >> 17) & 0x3F; if ( mcgsth ) { if ( mainPllId > mcgsth ) mainPllId = mcgsth; } dx = (mainPllId + 8) * 1200; for ( divisor = 3; divisor < 100; divisor++ ) if ( (dx / divisor) <= target ) break; 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"); } static void poll_fsb_k14(void) { unsigned long temp2; unsigned long dramchr; 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)"); } /* First, we need the clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr & 0x1F); switch (temp2) { default: case 6: dramclock = 400; break; case 10: dramclock = 533; break; case 14: dramclock = 667; break; } /* print */ print_fsb_info(dramclock, "RAM : ", "DDR-"); } static void poll_fsb_i925(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, mchcfg2, dev0, drc, idetect; float coef = getP4PMmultiplier(); long *ptr; pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); dev0 = dev0 & 0xFFFFC000; ptr=(long*)(dev0+0xC00); mchcfg = *ptr & 0xFFFF; ptr=(long*)(dev0+0x120); drc = *ptr & 0xFFFF; dramratio = 1; mchcfg2 = (mchcfg >> 4)&3; if ((drc&3) != 2) { // We are in DDR1 Mode if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; } } else { // We are in DDR2 Mode if ((mchcfg >> 2)&1) { // We are in FSB1066 Mode if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; } } else { switch (mchcfg2) { case 1: dramratio = 0.66667; break; case 2: if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; } break; case 3: // Checking for FSB533 Mode & Alviso if ((mchcfg & 1) == 0) { dramratio = 1.33334; } else if (idetect == 0x2590) { dramratio = 2; } else { dramratio = 1.5; } } } } // 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; } static void poll_fsb_i945(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0; 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 >> 4)&7) { case 1: dramratio = 1.0; break; case 2: dramratio = 1.33334; break; case 3: dramratio = 1.66667; break; case 4: dramratio = 2.0; 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; } static void poll_fsb_i975(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 1: fsb_mch = 533; break; case 2: fsb_mch = 800; break; case 3: fsb_mch = 667; break; default: fsb_mch = 1066; break; } switch (fsb_mch) { case 533: switch ((mchcfg >> 4)&7) { case 0: dramratio = 1.25; break; case 1: dramratio = 1.5; break; case 2: dramratio = 2.0; break; } break; default: case 800: switch ((mchcfg >> 4)&7) { case 1: dramratio = 1.0; break; case 2: dramratio = 1.33334; break; case 3: dramratio = 1.66667; break; case 4: dramratio = 2.0; break; } break; case 1066: switch ((mchcfg >> 4)&7) { case 1: dramratio = 0.75; break; case 2: dramratio = 1.0; break; case 3: dramratio = 1.25; break; 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; } static void poll_fsb_i965(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float coef = getP4PMmultiplier(); long *ptr; /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; 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; } // 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; } static void poll_fsb_im965(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float coef = getP4PMmultiplier(); long *ptr; /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0xC00); mchcfg = *ptr & 0xFFFF; dramratio = 1; switch (mchcfg & 7) { case 1: fsb_mch = 533; break; default: case 2: fsb_mch = 800; break; case 3: fsb_mch = 667; break; case 6: fsb_mch = 1066; break; } switch (fsb_mch) { case 533: switch ((mchcfg >> 4)&7) { case 1: dramratio = 5.0f/4.0f; break; case 2: dramratio = 3.0f/2.0f; break; case 3: dramratio = 2.0f; break; } break; case 667: switch ((mchcfg >> 4)&7) { case 1: dramratio = 1.0f; break; case 2: dramratio = 6.0f/5.0f; break; case 3: dramratio = 8.0f/5.0f; break; case 4: dramratio = 2.0f; break; case 5: dramratio = 12.0f/5.0f; break; } break; default: case 800: switch ((mchcfg >> 4)&7) { case 1: dramratio = 5.0f/6.0f; break; case 2: dramratio = 1.0f; break; case 3: dramratio = 4.0f/3.0f; break; case 4: dramratio = 5.0f/3.0f; break; case 5: dramratio = 2.0f; break; } break; case 1066: switch ((mchcfg >> 4)&7) { case 5: dramratio = 3.0f/2.0f; break; case 6: dramratio = 2.0f; 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; } static void poll_fsb_5400(void) { double dramclock, dramratio, fsb; unsigned long ambase_low, ambase_high, ddrfrq; float coef = getP4PMmultiplier(); /* Find dramratio */ pci_conf_read( 0, 16, 0, 0x48, 4, &ambase_low); ambase_low &= 0xFFFE0000; pci_conf_read( 0, 16, 0, 0x4C, 4, &ambase_high); ambase_high &= 0xFF; pci_conf_read( 0, 16, 1, 0x56, 1, &ddrfrq); ddrfrq &= 7; dramratio = 1; switch (ddrfrq) { case 0: case 1: case 4: dramratio = 1.0; break; case 2: dramratio = 5.0f/4.0f; break; case 3: case 7: dramratio = 4.0f/5.0f; break; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq print_fsb_info(dramclock, "RAM : ", "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; } static void poll_fsb_nf4ie(void) { double dramclock, dramratio, fsb; float mratio, nratio; unsigned long reg74, reg60; float coef = getP4PMmultiplier(); /* Find dramratio */ pci_conf_read(0, 0, 2, 0x74, 2, ®74); pci_conf_read(0, 0, 2, 0x60, 4, ®60); mratio = reg74 & 0xF; nratio = (reg74 >> 4) & 0xF; // If M or N = 0, then M or N = 16 if (mratio == 0) { mratio = 16; } if (nratio == 0) { nratio = 16; } // Check if synchro or pseudo-synchro mode if((reg60 >> 22) & 1) { dramratio = 1; } else { dramratio = nratio / mratio; } /* Compute RAM Frequency */ 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; } static void poll_fsb_i875(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, smfs; float coef = getP4PMmultiplier(); /* Find dramratio */ pci_conf_read(0, 0, 0, 0xC6, 2, &mchcfg); smfs = (mchcfg >> 10)&3; dramratio = 1; if ((mchcfg&3) == 3) { dramratio = 1; } if ((mchcfg&3) == 2) { if (smfs == 2) { dramratio = 1; } if (smfs == 1) { dramratio = 1.25; } if (smfs == 0) { dramratio = 1.5; } } if ((mchcfg&3) == 1) { if (smfs == 2) { dramratio = 0.6666666666; } if (smfs == 1) { dramratio = 0.8; } if (smfs == 0) { dramratio = 1; } } if ((mchcfg&3) == 0) { dramratio = 0.75; } /* Compute RAM Frequency */ dramclock = ((extclock /1000) / coef) / dramratio; 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; } } static void poll_fsb_p4(void) { ulong fsb, idetect; float coef = getP4PMmultiplier(); 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"); } } static void poll_fsb_i855(void) { double dramclock, dramratio, fsb ; unsigned int msr_lo, msr_hi; ulong mchcfg, centri, idetect; int coef; pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); /* Find multiplier (by MSR) */ /* Is it a Pentium M ? */ if (cpu_id.type == 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, ¢ri); if (centri == 0x1043) { cprint(LINE_CPU+5, col +1, "/ Centrino Mobile Platform"); } else { cprint(LINE_CPU+5, col +1, "/ Mobile Platform"); } /* Compute DRAM Clock */ dramratio = 1; if (idetect == 0x3580) { pci_conf_read( 0, 0, 3, 0xC0, 2, &mchcfg); mchcfg = mchcfg & 0x7; if (mchcfg == 1 || mchcfg == 2 || mchcfg == 4 || mchcfg == 5) { dramratio = 1; } if (mchcfg == 0 || mchcfg == 3) { dramratio = 1.333333333; } if (mchcfg == 6) { dramratio = 1.25; } if (mchcfg == 7) { dramratio = 1.666666667; } } else { pci_conf_read( 0, 0, 0, 0xC6, 2, &mchcfg); if (((mchcfg >> 10)&3) == 0) { dramratio = 1; } else if (((mchcfg >> 10)&3) == 1) { dramratio = 1.666667; } else { dramratio = 1.333333333; } } dramclock = fsb * dramratio; /* ...and print */ print_fsb_info(dramclock, "RAM : ", "DDR"); } static void poll_fsb_amd32(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long temp; double dramclock; double coef2; /* First, got the FID */ rdmsr(0x0c0010015, mcgsrl, mcgsth); temp = (mcgsrl >> 24)&0x0F; if ((mcgsrl >> 19)&1) { coef2 = athloncoef2[temp]; } else { coef2 = athloncoef[temp]; } if (coef2 == 0) { coef2 = 1; }; /* Compute the final FSB Clock */ dramclock = (extclock /1000) / coef2; /* ...and print */ print_fsb_info(dramclock, "FSB : ", "DDR"); } static void poll_fsb_nf2(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long temp, mempll; double dramclock, fsb; double mem_m, mem_n; float coef; coef = 10; /* First, got the FID */ rdmsr(0x0c0010015, mcgsrl, mcgsth); temp = (mcgsrl >> 24)&0x0F; if ((mcgsrl >> 19)&1) { coef = athloncoef2[temp]; } else { coef = athloncoef[temp]; } /* Get the coef (COEF = N/M) - Here is for Crush17 */ pci_conf_read(0, 0, 3, 0x70, 4, &mempll); mem_m = (mempll&0x0F); mem_n = ((mempll >> 4) & 0x0F); /* If something goes wrong, the chipset is probably a Crush18 */ if ( mem_m == 0 || mem_n == 0 ) { pci_conf_read(0, 0, 3, 0x7C, 4, &mempll); mem_m = (mempll&0x0F); mem_n = ((mempll >> 4) & 0x0F); } /* Compute the final FSB Clock */ dramclock = ((extclock /1000) / coef) * (mem_n/mem_m); 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"); } static void poll_fsb_us15w(void) { double dramclock, dramratio, fsb, gfx; unsigned long msr; /* Find dramratio */ /* D0 MsgRd, 05 Zunit, 03 MSR */ pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0050300 ); pci_conf_read(0, 0, 0, 0xD4, 4, &msr ); fsb = ( msr >> 3 ) & 1; dramratio = 0.5; // Compute RAM Frequency if (( msr >> 3 ) & 1) { fsb = 533; } else { fsb = 400; } switch (( msr >> 0 ) & 7) { case 0: gfx = 100; break; case 1: gfx = 133; break; case 2: gfx = 150; break; case 3: gfx = 178; break; case 4: gfx = 200; break; case 5: gfx = 266; break; default: 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; } static void poll_fsb_nhm(void) { double dramclock, dramratio, fsb; unsigned long mc_dimm_clk_ratio, qpi_pll_status; float coef = getNHMmultiplier(); 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 == 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 : "); col += 9; dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); col += 1; cprint(LINE_CPU+5, col, "."); col += 1; qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; dprint(LINE_CPU+5, col, qpi_speed, 1,0); col += 1; cprint(LINE_CPU+5, col +1, "GT/s"); col += 5; } /* Get the clock ratio */ pci_conf_read(nhm_bus, 3, 4, 0x54, 2, &mc_dimm_clk_ratio); dramratio = (mc_dimm_clk_ratio & 0x1F); // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio / 2; // Print DRAM Freq print_fsb_info(dramclock, "RAM : ", "DDR3-"); } static void poll_fsb_nhm32(void) { double dramclock, dramratio, fsb; unsigned long mc_dimm_clk_ratio, qpi_pll_status; float coef = getNHMmultiplier(); 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) { 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 : "); col += 9; dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); col += 1; cprint(LINE_CPU+5, col, "."); col += 1; qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; dprint(LINE_CPU+5, col, qpi_speed, 1,0); col += 1; cprint(LINE_CPU+5, col +1, "GT/s"); col += 5; } /* Get the clock ratio */ pci_conf_read(nhm_bus, 3, 4, 0x50, 2, &mc_dimm_clk_ratio); dramratio = (mc_dimm_clk_ratio & 0x1F); // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio / 2; // Print DRAM Freq print_fsb_info(dramclock, "RAM : ", "DDR3-"); } static void poll_fsb_wmr(void) { double dramclock, dramratio, fsb; unsigned long dev0, mchcfg; 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 */ dramratio = 0.25 * (float)(*ptr & 0x1F); // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_fsb_info(dramclock, "RAM : ", "DDR3-"); } static void poll_fsb_snb(void) { double dramclock, dramratio, fsb; unsigned long dev0, mchcfg; 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; } /* 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+0x5E04); mchcfg = *ptr & 0xFFFF; dramratio = 1; /* Get the clock ratio */ dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f); // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_fsb_info(dramclock, "RAM : ", "DDR3-"); } /* ------------------ Here the code for Timings detection ------------------ */ /* ------------------------------------------------------------------------- */ 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"); //Now, read Registers pci_conf_read( 0, 1, 1, 0xD0, 4, ®d0); pci_conf_read( 0, 1, 1, 0x80, 1, ®80); pci_conf_read( 0, 1, 0, 0x8C, 4, ®8c); pci_conf_read( 0, 1, 0, 0x9C, 4, ®9c); // Then, detect timings cas = (regd0 >> 4) & 0x7; rcd = (reg8c >> 24) & 0xF; 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)"); } else { cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)"); } } static void poll_timings_i875(void) { ulong dev6, dev62; ulong temp; float cas; int rcd, rp, ras; long *ptr, *ptr2; /* Read the MMR Base Address & Define the pointer */ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); /* Now, the PAT ritual ! (Kant and Luciano will love this) */ pci_conf_read( 0, 6, 0, 0x40, 4, &dev62); ptr2=(long*)(dev6+0x68); if ((dev62&0x3) == 0 && ((*ptr2 >> 14)&1) == 1) { cprint(LINE_CPU+5, col +1, "- PAT : Enabled"); } else { cprint(LINE_CPU+5, col +1, "- PAT : Disabled"); } /* Now, we could check some additionnals timings infos) */ ptr=(long*)(dev6+0x60); // CAS Latency (tCAS) temp = ((*ptr >> 5)& 0x3); if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; } // RAS-To-CAS (tRCD) temp = ((*ptr >> 2)& 0x3); if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; } // RAS Precharge (tRP) temp = (*ptr&0x3); if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; } // RAS Active to precharge (tRAS) temp = ((*ptr >> 7)& 0x7); ras = 10 - temp; // Print timings print_timings_info(cas, rcd, rp, ras); // Print 64 or 128 bits mode if (((*ptr2 >> 21)&3) > 0) { cprint(LINE_CPU+6, col2, "/ Dual Channel (128 bits)"); } else { cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)"); } } static void poll_timings_i925(void) { // Thanks for CDH optis ulong dev0, drt, drc, dcc, idetect, temp; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); dev0 &= 0xFFFFC000; //Set pointer for DRT ptr=(long*)(dev0+0x114); drt = *ptr & 0xFFFFFFFF; //Set pointer for DRC ptr=(long*)(dev0+0x120); drc = *ptr & 0xFFFFFFFF; //Set pointer for DCC 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-"); } } 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-"); } } 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; // RAS Precharge (tRP) dprint(LINE_CPU+6, col2, (drt&0x3)+2, 1 ,0); cprint(LINE_CPU+6, col2+1, "-"); col2 +=2; // RAS Active to precharge (tRAS) // If Lakeport, than change tRAS computation (Thanks to CDH, again) if (idetect > 0x2700) temp = ((drt >> 19)& 0x1F); else temp = ((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)"); } } 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; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x29C); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x250); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; 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); // 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); // 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); // 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; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { cprint(LINE_CPU+6, col2+1, "Dual Channel"); } else { cprint(LINE_CPU+6, col2+1, "Single Channel"); } } static void poll_timings_im965(void) { // Thanks for CDH optis ulong dev0, temp, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x1200); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x1300); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x100); ptr = (long*)(dev0+offset+0x121C); ODT_Control_Register = *ptr & 0xFFFFFFFF; 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); // 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); // 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); // RAS Active to precharge (tRAS) temp = (Precharge_Register >> 21) & 0x1F; dprint(LINE_CPU+6, col2, temp, 1 ,0); (temp < 10)?(col2 += 1):(col2 += 2); cprint(LINE_CPU+6, col2+1, "/"); col2 +=2; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { cprint(LINE_CPU+6, col2+1, "Dual Channel"); } else { cprint(LINE_CPU+6, col2+1, "Single Channel"); } } 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; long *ptr; pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID); Device_ID &= 0xFFFF; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x265); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x25D); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; 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) { cas = ((ODT_Control_Register >> 8)& 0x3F) - 6.0f; } else { cas = ((ODT_Control_Register >> 8)& 0x3F) - 9.0f; } // RAS-To-CAS (tRCD) rcd = (Read_Register >> 17) & 0xF; // RAS Precharge (tRP) rp = (ACT_Register >> 13) & 0xF; // 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"); } else { cprint(LINE_CPU+6, col2+1, "Single Channel"); } } static void poll_timings_wmr(void) { float cas; int rcd, rp, ras; ulong dev0, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, MRC_Register; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x265); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x25D); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x258); Read_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x240); MRC_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) if(MRC_Register & 0xF) { cas = (MRC_Register & 0xF) + 3.0f; } else { cas = ((ODT_Control_Register >> 8)& 0x3F) - 5.0f; } // RAS-To-CAS (tRCD) rcd = (Read_Register >> 17) & 0xF; // RAS Precharge (tRP) rp = (ACT_Register >> 13) & 0xF; // 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"); } else { cprint(LINE_CPU+6, col2+1, "Single Channel"); } } static void poll_timings_snb(void) { float cas; int rcd, rp, ras; ulong dev0, offset; 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; offset = 0x0000; ptr = (long*)(dev0+offset+0x4000); IMC_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) cas = (float)((IMC_Register >> 8) & 0x0F); // RAS-To-CAS (tRCD) rcd = IMC_Register & 0x0F; // RAS Precharge (tRP) rp = (IMC_Register >> 4) & 0x0F; // RAS Active to precharge (tRAS) ras = (IMC_Register >> 16) & 0xFF; print_timings_info(cas, rcd, rp, ras); cprint(LINE_CPU+6, col2+1, "/"); col2 +=2; // 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"); } else { cprint(LINE_CPU+6, col2+1, "Dual Channel"); } } static void poll_timings_5400(void) { // Thanks for CDH optis ulong ambase, mtr1, mtr2, offset, mca, temp; long *ptr; //Hard-coded Ambase value (should not be realocated by software when using Memtest86+ ambase = 0xFE000000; offset = mtr1 = mtr2 = 0; // Will loop until a valid populated channel is found // Bug : DIMM 0 must be populated or it will fall in an endless loop while(((mtr2 & 0xF) < 3) || ((mtr2 & 0xF) > 6)) { ptr = (long*)(ambase+0x378+offset); mtr1 = *ptr & 0xFFFFFFFF; ptr = (long*)(ambase+0x37C+offset); mtr2 = *ptr & 0xFFFFFFFF; offset += 0x8000; } pci_conf_read( 0, 16, 1, 0x58, 4, &mca); //This chipset only supports FB-DIMM (Removed => too long) //cprint(LINE_CPU+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; // 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; // RAS Precharge (tRP) temp = 6 - ((mtr1 >> 8) & 3); dprint(LINE_CPU+6, col2, temp, 1 ,0); cprint(LINE_CPU+6, col2+1, "-"); col2 += 2; // RAS Active to precharge (tRAS) temp = 16 - (3 * ((mtr1 >> 29) & 3)) + ((mtr1 >> 12) & 3); if(((mtr1 >> 12) & 3) == 3 && ((mtr1 >> 29) & 3) == 2) { temp = 9; } dprint(LINE_CPU+6, col2, temp, 1 ,0); (temp < 10)?(col2 += 1):(col2 += 2); cprint(LINE_CPU+6, col2+1, "/"); col2 +=2; if ((mca >> 14) & 1) { cprint(LINE_CPU+6, col2+1, "Single Channel"); } else { cprint(LINE_CPU+6, col2+1, "Dual Channel"); } } static void poll_timings_E7520(void) { ulong drt, ddrcsr; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 0, 0x78, 4, &drt); pci_conf_read( 0, 0, 0, 0x9A, 2, &ddrcsr); cas = ((drt >> 2) & 3) + 2; 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)"); } else { cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)"); } } static void poll_timings_i855(void) { ulong drt, temp; pci_conf_read( 0, 0, 0, 0x78, 4, &drt); /* Now, we could print some additionnals timings infos) */ cprint(LINE_CPU+6, col2 +1, "/ CAS : "); col2 += 9; // 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; } // 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; // RAS Precharge (tRP) temp = (drt&0x1); if (temp == 0x0) { cprint(LINE_CPU+6, col2, "3-"); } else { cprint(LINE_CPU+6, col2, "2-"); } col2 +=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; } static void poll_timings_E750x(void) { ulong drt, drc, temp; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 0, 0x78, 4, &drt); pci_conf_read( 0, 0, 0, 0x7C, 4, &drc); if ((drt >> 4) & 1) { cas = 2; } else { cas = 2.5; }; if ((drt >> 1) & 1) { rcd = 2; } else { rcd = 3; }; if (drt & 1) { rp = 2; } else { rp = 3; }; 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)"); } else { cprint(LINE_CPU+6, col2, "/ Single Channel (64 bits)"); } } static void poll_timings_i852(void) { ulong drt, temp; pci_conf_read( 0, 0, 1, 0x60, 4, &drt); /* Now, we could print some additionnals timings infos) */ cprint(LINE_CPU+6, col2 +1, "/ CAS : "); col2 += 9; // 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; } // 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; // 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; // 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; } static void poll_timings_amd64(void) { ulong dramtlr, dramclr; int temp; 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) { /* 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; // 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; } else { cprint(LINE_CPU+6, col2, " DDR2 (64 bits)"); col2 +=15; } } else { /* OLD K8 (DDR1) */ // 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; } // 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; } else { cprint(LINE_CPU+6, col2, " DDR1 (64 bits)"); col2 +=15; } } } static void poll_timings_k10(void) { ulong dramtlr, dramclr, dramchr; ulong offset = 0; int cas, rcd, rp, rc, ras; 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); } pci_conf_read(0, 24, 2, 0x88+offset, 4, &dramtlr); pci_conf_read(0, 24, 2, 0x110, 4, &dramclr); // CAS Latency (tCAS) if(((dramchr >> 8)&1) || ((dramchr & 0x7) == 0x4)){ // DDR3 or DDR2-1066 cas = (dramtlr & 0xF) + 4; rcd = ((dramtlr >> 4) & 0x7) + 5; rp = ((dramtlr >> 7) & 0x7) + 5; ras = ((dramtlr >> 12) & 0xF) + 15; rc = ((dramtlr >> 16) & 0x1F) + 11; } 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_timings_info(cas, rcd, rp, ras); cprint(LINE_CPU+6, col2, "/"); col2++; //Print DDR2 or DDR3 if ((dramchr >> 8)&1) { cprint(LINE_CPU+6, col2+1, "DDR3"); } else { cprint(LINE_CPU+6, col2+1, "DDR2"); } 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)"); } } static void poll_timings_k14(void) { ulong dramt0, dramlow; int cas, rcd, rp, rc, ras; 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); cas = (dramlow & 0xF) + 4; rcd = (dramt0 & 0xF) + 5; rp = ((dramt0 >> 8) & 0xF) + 5; ras = ((dramt0 >> 16) & 0x1F) + 15; rc = ((dramt0 >> 24) & 0x3F) + 16; print_timings_info(cas, rcd, rp, ras); cprint(LINE_CPU+6, col2, "/ DDR3 (64 bits)"); } static void poll_timings_EP80579(void) { ulong drt1, drt2; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 0, 0x78, 4, &drt1); pci_conf_read( 0, 0, 0, 0x64, 4, &drt2); cas = ((drt1 >> 3) & 0x7) + 3; rcd = ((drt1 >> 9) & 0x7) + 3; rp = ((drt1 >> 6) & 0x7) + 3; ras = ((drt2 >> 28) & 0xF) + 8; print_timings_info(cas, rcd, rp, ras); } static void poll_timings_nf2(void) { ulong dramtlr, dramtlr2, dramtlr3, temp; ulong dimm1p, dimm2p, dimm3p; 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); pci_conf_read(0, 0, 2, 0x40, 4, &dimm1p); 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; } // RAS-To-CAS (tRCD) temp = ((dramtlr >> 20) & 0xF); dprint(LINE_CPU+6, col2, temp , 1 ,0); cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2; // RAS Precharge (tRP) temp = ((dramtlr >> 28) & 0xF); dprint(LINE_CPU+6, col2, temp , 1 ,0); cprint(LINE_CPU+6, col2 +1, "-"); col2 +=2; // 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; // 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; } else { cprint(LINE_CPU+6, col2, " Single Channel (64 bits)"); col2 +=15; } } static void poll_timings_us15w(void) { // Thanks for CDH optis ulong dtr, temp; /* 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; // 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; // RAS Precharge (tRP) temp = ((dtr >> 0) & 0x3) + 3; dprint(LINE_CPU+5, col2, temp, 1 ,0); col2 += 1; } static void poll_timings_nhm(void) { ulong mc_channel_bank_timing, mc_control, mc_channel_mrs_value; float cas; int rcd, rp, ras; int fvc_bn = 4; /* Find which channels are populated */ pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); mc_control = (mc_control >> 8) & 0x7; /* Get the first valid channel */ if(mc_control & 1) { fvc_bn = 4; } else if(mc_control & 2) { fvc_bn = 5; } else if(mc_control & 4) { fvc_bn = 6; } // Now, detect timings // CAS Latency (tCAS) / RAS-To-CAS (tRCD) / RAS Precharge (tRP) / RAS Active to precharge (tRAS) pci_conf_read(nhm_bus, fvc_bn, 0, 0x88, 4, &mc_channel_bank_timing); pci_conf_read(nhm_bus, fvc_bn, 0, 0x70, 4, &mc_channel_mrs_value); cas = ((mc_channel_mrs_value >> 4) & 0xF ) + 4.0f; rcd = (mc_channel_bank_timing >> 9) & 0xF; 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; } else if (mc_control == 7) { cprint(LINE_CPU+6, col2, "/ Triple Channel"); col2 += 16; } else { cprint(LINE_CPU+6, col2, "/ Dual Channel"); col2 += 14; } } /* ------------------ Let's continue ------------------ */ /* ---------------------------------------------------- */ static struct pci_memory_controller controllers[] = { /* Default unknown chipset */ { 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 }, /* 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 }, /* 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 }, /* 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 }, /* 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 }, /* 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 }, /* 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 }, /* 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 } }; static void print_memory_controller(void) { /* Print memory controller info */ int d; char *name; 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; } if (ctrl.cap & __ECC_DETECT) { int on; on = ctrl.mode & __ECC_DETECT; cprint(LINE_CPU+5, col, "(ECC : "); cprint(LINE_CPU+5, col +7, on?"Detect":"Disabled)"); on?(col += 13):(col += 16); } if (ctrl.mode & __ECC_CORRECT) { int on; on = ctrl.mode & __ECC_CORRECT; cprint(LINE_CPU+5, col, " / "); if (ctrl.cap & __ECC_CHIPKILL) { cprint(LINE_CPU+5, col +3, on?"Correct -":""); on?(col += 12):(col +=3); } else { cprint(LINE_CPU+5, col +3, on?"Correct)":""); on?(col += 11):(col +=3); } } if (ctrl.mode & __ECC_DETECT) { if (ctrl.cap & __ECC_CHIPKILL) { int on; on = ctrl.mode & __ECC_CHIPKILL; cprint(LINE_CPU+5, col, " Chipkill : "); cprint(LINE_CPU+5, col +12, on?"On)":"Off)"); on?(col += 15):(col +=16); }} if (ctrl.mode & __ECC_SCRUB) { int on; on = ctrl.mode & __ECC_SCRUB; cprint(LINE_CPU+5, col, " Scrub"); cprint(LINE_CPU+5, col +6, on?"+ ":"- "); col += 7; } if (ctrl.cap & __ECC_UNEXPECTED) { int on; on = ctrl.mode & __ECC_UNEXPECTED; cprint(LINE_CPU+5, col, "Unknown"); 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(); } } 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); result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_DEVICE_ID, 2, &device); // Detect IMC by CPUID if(imc_type) { vendor = 0xFFFF; device = imc_type; } if(fail_safe) { vendor = 0xFFFF; device = 0xFFFF; } ctrl.index = 0; if (result == 0) { for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) { if ((controllers[i].vendor == vendor) && (controllers[i].device == device)) { ctrl.index = i; break; } } } controllers[ctrl.index].setup_ecc(); /* Don't enable ECC polling by default unless it has * been well tested. */ set_ecc_polling(-1); print_memory_controller(); } void poll_errors(void) { if (ctrl.poll) { controllers[ctrl.index].poll_errors(); } } void set_ecc_polling(int val) { int tested = controllers[ctrl.index].tested; if (val == -1) { val = tested; } if (val && (ctrl.mode & __ECC_DETECT)) { ctrl.poll = 1; cprint(LINE_INFO, COL_ECC, tested? " on": " ON"); } else { ctrl.poll = 0; cprint(LINE_INFO, COL_ECC, "off"); } } memtest86+-4.20/test.h0000644000000000000000000002051311517067470013205 0ustar rootroot/* test.h - MemTest-86 Version 3.2 * * 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_ #define _TEST_H_ #define E88 0x00 #define E801 0x04 #define E820NR 0x08 /* # entries in E820MAP */ #define E820MAP 0x0c /* our map */ #define E820MAX 64 /* number of entries in E820MAP */ #define E820ENTRY_SIZE 20 #define MEMINFO_SIZE (E820MAP + E820MAX * E820ENTRY_SIZE) #define MAX_DMI_MEMDEVS 16 #ifndef __ASSEMBLY__ #define E820_RAM 1 #define E820_RESERVED 2 #define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ #define E820_NVS 4 struct e820entry { unsigned long long addr; /* start of memory segment */ unsigned long long size; /* size of memory segment */ unsigned long type; /* type of memory segment */ }; struct mem_info_t { unsigned long e88_mem_k; /* 0x00 */ unsigned long e801_mem_k; /* 0x04 */ unsigned long e820_nr; /* 0x08 */ struct e820entry e820[E820MAX]; /* 0x0c */ /* 0x28c */ }; typedef unsigned long ulong; #define SPINSZ 0x2000000 #define MOD_SZ 20 #define BAILOUT if (bail) goto skip_test; #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 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 POP_W 30 #define POP_H 15 #define POP_X 16 #define POP_Y 8 #define POP2_W 74 #define POP2_H 21 #define POP2_X 3 #define POP2_Y 2 //#define NULL 0 /* memspeed operations */ #define MS_COPY 1 #define MS_WRITE 2 #define MS_READ 3 #define SZ_MODE_BIOS 1 #define SZ_MODE_BIOS_RES 2 #define SZ_MODE_PROBE 3 #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) int memcmp(const void *s1, const void *s2, ulong count); int strncmp(const char *s1, const char *s2, ulong n); void *memmove(void *dest, const void *src, ulong n); int query_linuxbios(void); int query_pcbios(void); int insertaddress(ulong); void printpatn(void); void printpatn(void); void itoa(char s[], int n); void reverse(char *p); void serial_console_setup(char *param); void serial_echo_init(void); void serial_echo_print(const char *s); void ttyprint(int y, int x, const char *s); 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 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 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 init(void); struct eregs; void inter(struct eregs *trap_regs); void set_cache(int val); void check_input(void); void footer(void); void scroll(void); void clear_scroll(void); void popup(void); void popdown(void); void popclear(void); void pop2up(void); void pop2down(void); 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); int getnum(ulong val); void block_move(int iter); 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, unsigned short syndrome, int channel); void mem_size(void); void adj_mem(void); ulong getval(int x, int y, int result_shift); int get_key(void); int ascii_to_keycode(int in); void wait_keyup(void); void print_hdr(void); void restart(void); void parity_err(ulong edi, ulong esi); void start_config(void); void clear_screen(void); void paging_off(void); void show_spd(void); int map_page(unsigned long page); void *mapping(unsigned long page_address); void *emapping(unsigned long page_address); unsigned long page_of(void *ptr); ulong memspeed(ulong src, ulong len, int iter, int type); ulong correct_tsc(ulong el_org); #define PRINTMODE_SUMMARY 1 #define PRINTMODE_ADDRESSES 0 #define PRINTMODE_PATTERNS 2 #define PRINTMODE_NONE 3 #define PRINTMODE_DMI 4 #define BADRAM_MAXPATNS 10 struct pair { ulong adr; 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" "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" "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; ulong *end; }; struct pmap { ulong start; ulong end; }; struct tseq { short cache; 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; }; struct err_info { struct xadr low_addr; struct xadr high_addr; unsigned long ebits; long tbits; short min_bits; short max_bits; unsigned long maxl; unsigned long eadr; unsigned long exor; unsigned long cor_err; short hdr_flag; }; #define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ #define MAX_MEM_SEGMENTS E820MAX /* Define common variables accross relocations of memtest86+ */ 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]; ulong plim_lower; ulong plim_upper; ulong clks_msec; ulong starth; 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; }; #define FIRMWARE_UNKNOWN 0 #define FIRMWARE_PCBIOS 1 #define FIRMWARE_LINUXBIOS 2 extern struct vars * const v; extern unsigned char _start[], _end[], startup_32[]; 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_ */memtest86+-4.20/README.build-process0000644000000000000000000000367711517067470015523 0ustar rootrootDuring 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 memtest86+-4.20/dmi.c0000644000000000000000000001657211517067470013004 0ustar rootroot/* dmi.c using the DMI from SMBIOS to read information about the hardware's * memory devices capabilities and where they are mapped into the address space * * Copyright (c) Joachim Deguara, AMD 2006 * * Release under the GPL version 2 * ---------------------------------------------------- * Memtest86+ V4.00 - Added compliance with SMBIOS Spec V2.6.1 */ #include "test.h" #include #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) #define round_down(x,y) ((x) & ~((y)-1)) struct dmi_eps { uint8_t anchor[4]; int8_t checksum; uint8_t length; uint8_t majorversion; uint8_t minorversion; uint16_t maxstructsize; uint8_t revision; uint8_t pad[5]; uint8_t intanchor[5]; int8_t intchecksum; uint16_t tablelength; uint32_t tableaddress; uint16_t numstructs; uint8_t SMBIOSrev; } __attribute__((packed)); struct tstruct_header{ uint8_t type; uint8_t length; uint16_t handle; } __attribute__((packed)); struct mem_dev { struct tstruct_header header; uint16_t pma_handle; uint16_t err_handle; uint16_t tot_width; uint16_t dat_width; uint16_t size; uint8_t form; uint8_t set; uint8_t dev_locator; uint8_t bank_locator; uint8_t type; uint16_t typedetail; uint16_t speed; uint8_t manufacturer; uint8_t serialnum; uint8_t asset; uint8_t partnum; } __attribute__((packed)); struct md_map{ struct tstruct_header header; uint32_t start; uint32_t end; uint16_t md_handle; uint16_t mama_handle; uint8_t row_pos; uint8_t interl_pos; uint8_t interl_depth; } __attribute__((packed)); struct pma{ struct tstruct_header header; uint8_t location; uint8_t use; uint8_t ecc; uint32_t capacity; uint16_t errhandle; uint16_t numdevs; } __attribute__((packed)); static char *form_factors[] = { "?", "Other", "Unknown", "SIMM", "SIP", "Chip", "DIP", "ZIP", "Proprietary Card", "DIMM", "TSOP", "Row of chips", "RIMM", "SODIMM", "SRIMM", "FB-DIMM" }; static char *memory_types[] = { "?", "Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM", "ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB", "RSVD", "RSVD","RSVD","DDR3","FBD2" }; struct mem_dev * mem_devs[MAX_DMI_MEMDEVS]; int mem_devs_count=0; struct md_map * md_maps[MAX_DMI_MEMDEVS]; int md_maps_count=0; int 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; char * a = (char *)header + header->length; n--; do{ if (!*a) n--; if (!n && *a) return a; a++; }while (!(*a==0 && *(a-1)==0)); return 0; } int open_dmi(void){ char *dmi, *dmi_search_start, *dmi_start; int found=0; struct dmi_eps *eps; char *table_start; int tstruct_count=0; dmi_search_start = (char *)DMI_SEARCH_START; //find anchor for(dmi = dmi_search_start; dmi < dmi_search_start + 0xf0000; dmi +=16){ if( *dmi == '_' && *(dmi+1) == 'S' && *(dmi+2) == 'M' && *(dmi+3) == '_'){ found =1; break; } } if (!found) { return -1; } dmi_start=dmi; eps=(struct dmi_eps *)dmi; //check checksum int8_t checksum=0; for (; dmi < dmi_start + eps->length; dmi++) checksum += *dmi; if (checksum){ return -1; } //we need at least revision 2.1 of SMBIOS if ( eps->majorversion < 2 && eps->minorversion < 1){ return -1; } table_start=(char *)eps->tableaddress; dmi=table_start; //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; // Need fix (SMBIOS/DDR3) if (header->type == 20 || header->type == 1) md_maps[md_maps_count++]=(struct md_map *)dmi; dmi+=header->length; while( ! (*dmi == 0 && *(dmi+1) == 0 ) ) dmi++; dmi+=2; if (++tstruct_count > eps->numstructs) return -1; } return 0; } void init_dmi(void){ int i; for(i=0; i < MAX_DMI_MEMDEVS; i++) dmi_err_cnts[i]=0; open_dmi(); dmi_initialized=1; } void print_dmi_info(void){ int i,j,page; char * string=0; if(!dmi_initialized) init_dmi(); if (mem_devs_count == 0){ cprint(POP2_Y+1, POP2_X+2, "No valid DMI Memory Devices info found"); while (get_key() == 0); return; } for(page=1; page <= 1 + (mem_devs_count-1)/8; page++){ pop2clear(); cprint(POP2_Y+1, POP2_X+2, "DMI Memory Device Info (page "); itoa(string,page); cprint(POP2_Y+1, POP2_X+32, string); cprint(POP2_Y+1, POP2_X+33, "/"); itoa(string,1 + (mem_devs_count-1)/8); cprint(POP2_Y+1, POP2_X+34, string); cprint(POP2_Y+1, POP2_X+35, ")"); cprint(POP2_Y+3, POP2_X+4, "Location Size(MB) Speed(MHz) Type Form"); cprint(POP2_Y+4, POP2_X+4, "--------------------------------------------------------------"); for(i=8*(page-1); iheader), mem_devs[i]->dev_locator)); if (mem_devs[i]->size == 0){ cprint(yof, POP2_X+4+18, "Empty"); }else if (mem_devs[i]->size == 0xFFFF){ cprint(yof, POP2_X+4+18, "Unknown"); }else{ size_in_mb = 0xEFFF & mem_devs[i]->size; if (mem_devs[i]->size & 0x8000) size_in_mb = size_in_mb<<10; itoa(string, size_in_mb); cprint(yof, POP2_X+4+18, string); } //this is the only field that needs to be SMBIOS 2.3+ if ( mem_devs[i]->speed && mem_devs[i]->header.length > 21){ itoa(string, mem_devs[i]->speed); cprint(yof, POP2_X+4+27, string); }else{ cprint(yof, POP2_X+4+27, "Unknown"); } cprint(yof, POP2_X+4+37, memory_types[mem_devs[i]->type]); cprint(yof, POP2_X+4+44, form_factors[mem_devs[i]->form]); //print mappings int mapped=0,of=0; cprint(yof+1, POP2_X+6,"mapped to: "); for(j=0; jheader.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; cprint(yof+1, POP2_X+17+of, "-"); of++; hprint3(yof+1, POP2_X+17+of, md_maps[j]->end<<10, 12); of += 12; } if (!mapped) cprint(yof+1, POP2_X+17, "No mapping (Interleaved Device)"); } wait_keyup(); while (get_key() == 0); } } //return 1 if the list of bad memory devices changes, 0 otherwise, -1 if no mapped int add_dmi_err(ulong adr){ int i,j,found=-1; if(!dmi_initialized) init_dmi(); for(i=0; i < md_maps_count; i++){ if ( adr < (md_maps[i]->start<<10) || adr > (md_maps[i]->end<<10) ) continue; //matching map found, now check find corresponding dev for(j=0; j < mem_devs_count; j++){ if (mem_devs[j]->header.handle != md_maps[i]->md_handle) continue; if (dmi_err_cnts[j]){ found=0; }else{ found = dmi_err_cnts[j] = 1; } } } return found; } void print_dmi_err(void){ int i,count,of; char *string; scroll(); cprint(v->msg_line, 0,"Bad Memory Devices: "); of=20; for ( i=count=0; i < MAX_DMI_MEMDEVS; i++){ if (!dmi_err_cnts[i]) continue; struct mem_dev *md = mem_devs[i]; if(count++){ cprint(v->msg_line, of, ", "); of+=2; } string=get_tstruct_string((struct tstruct_header *)md,md->dev_locator); if (strlen(string) + of > 80){ scroll(); of=7; } cprint(v->msg_line, of, string); of += strlen(string); } } memtest86+-4.20/error.c0000644000000000000000000003123411517067470013354 0ustar rootroot /* error.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, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #include "test.h" #include "config.h" #include #include "dmi.h" #define NULL 0 extern int test_ticks, nticks, beepmode; extern struct tseq tseq[]; extern int dmi_err_cnts[MAX_DMI_MEMDEVS]; extern short dmi_initialized; void poll_errors(); static void update_err_counts(void); static void print_err_counts(void); static int syn, chan, len=1; /* * Print an individual error */ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type) { int i, n, x, j, flag=0; ulong page, offset; int patnchg; ulong mb; update_err_counts(); add_dmi_err((ulong)adr); switch(v->printmode) { case PRINTMODE_SUMMARY: /* Don't do anything for a parity error. */ if (type == 3) { return; } /* Address error */ if (type == 1) { xor = good ^ bad; } /* Ecc correctable errors */ if (type == 2) { /* the bad value is the corrected flag */ if (bad) { v->erri.cor_err++; } page = (ulong)adr; offset = good; } else { page = page_of(adr); offset = (ulong)adr & 0xFFF; } /* Calc upper and lower error addresses */ if (v->erri.low_addr.page > page) { v->erri.low_addr.page = page; v->erri.low_addr.offset = offset; flag++; } else if (v->erri.low_addr.page == page && v->erri.low_addr.offset > offset) { v->erri.low_addr.offset = offset; v->erri.high_addr.offset = offset; flag++; } else if (v->erri.high_addr.page < page) { v->erri.high_addr.page = page; flag++; } if (v->erri.high_addr.page == page && v->erri.high_addr.offset < offset) { v->erri.high_addr.offset = offset; flag++; } /* Calc bits in error */ for (i=0, n=0; i<32; i++) { if (xor>>i & 1) { n++; } } v->erri.tbits += n; if (n > v->erri.max_bits) { v->erri.max_bits = n; flag++; } if (n < v->erri.min_bits) { v->erri.min_bits = n; flag++; } if (v->erri.ebits ^ xor) { flag++; } v->erri.ebits |= xor; /* Calc max contig errors */ len = 1; if ((ulong)adr == (ulong)v->erri.eadr+4 || (ulong)adr == (ulong)v->erri.eadr-4 ) { len++; } if (len > v->erri.maxl) { v->erri.maxl = len; flag++; } v->erri.eadr = (ulong)adr; if (v->erri.hdr_flag == 0) { clear_scroll(); cprint(LINE_HEADER+0, 1, "Error Confidence Value:"); cprint(LINE_HEADER+1, 1, " Lowest Error Address:"); cprint(LINE_HEADER+2, 1, " Highest Error Address:"); cprint(LINE_HEADER+3, 1, " Bits in Error Mask:"); cprint(LINE_HEADER+4, 1, " Bits in Error - Total:"); cprint(LINE_HEADER+4, 29, "Min: Max: Avg:"); cprint(LINE_HEADER+5, 1, " Max Contiguous Errors:"); cprint(LINE_HEADER+6, 1, "ECC Correctable Errors:"); cprint(LINE_HEADER+7, 1, "Errors per Memory Slot:"); x = 24; if (dmi_initialized) { for ( i=0; i < MAX_DMI_MEMDEVS;){ n = LINE_HEADER+7; for (j=0; j<4; j++) { if (dmi_err_cnts[i] >= 0) { dprint(n, x, i, 2, 0); cprint(n, x+2, ": 0"); } i++; n++; } x += 10; } } cprint(LINE_HEADER+0, 64, "Test Errors"); v->erri.hdr_flag++; } if (flag) { /* Calc bits in error */ for (i=0, n=0; i<32; i++) { if (v->erri.ebits>>i & 1) { n++; } } page = v->erri.low_addr.page; offset = v->erri.low_addr.offset; mb = page >> 8; hprint(LINE_HEADER+1, 25, page); hprint2(LINE_HEADER+1, 33, offset, 3); cprint(LINE_HEADER+1, 36, " - . MB"); dprint(LINE_HEADER+1, 39, mb, 5, 0); dprint(LINE_HEADER+1, 45, ((page & 0xFF)*10)/256, 1, 0); page = v->erri.high_addr.page; offset = v->erri.high_addr.offset; mb = page >> 8; hprint(LINE_HEADER+2, 25, page); hprint2(LINE_HEADER+2, 33, offset, 3); cprint(LINE_HEADER+2, 36, " - . MB"); dprint(LINE_HEADER+2, 39, mb, 5, 0); dprint(LINE_HEADER+2, 45, ((page & 0xFF)*10)/256, 1, 0); hprint(LINE_HEADER+3, 25, v->erri.ebits); dprint(LINE_HEADER+4, 25, n, 2, 1); dprint(LINE_HEADER+4, 34, v->erri.min_bits, 2, 1); dprint(LINE_HEADER+4, 42, v->erri.max_bits, 2, 1); dprint(LINE_HEADER+4, 50, v->erri.tbits/v->ecount, 2, 1); dprint(LINE_HEADER+5, 25, v->erri.maxl, 7, 1); x = 28; for ( i=0; i < MAX_DMI_MEMDEVS;){ n = LINE_HEADER+7; for (j=0; j<4; j++) { if (dmi_err_cnts[i] > 0) { dprint (n, x, dmi_err_cnts[i], 7, 1); } i++; n++; } x += 10; } for (i=0; tseq[i].msg != NULL; i++) { dprint(LINE_HEADER+1+i, 66, i, 2, 0); dprint(LINE_HEADER+1+i, 68, tseq[i].errors, 8, 0); } } if (v->erri.cor_err) { dprint(LINE_HEADER+6, 25, v->erri.cor_err, 8, 1); } break; case PRINTMODE_ADDRESSES: /* Don't display duplicate errors */ if ((ulong)adr == (ulong)v->erri.eadr && xor == v->erri.exor) { return; } if (v->erri.hdr_flag == 0) { clear_scroll(); cprint(LINE_HEADER, 0, "Tst Pass Failing Address Good Bad Err-Bits Count Chan"); cprint(LINE_HEADER+1, 0, "--- ---- ----------------------- -------- -------- -------- ----- ----"); v->erri.hdr_flag++; } /* Check for keyboard input */ check_input(); scroll(); if ( type == 2 || type == 3) { page = (ulong)adr; offset = good; } else { page = page_of(adr); offset = ((unsigned long)adr) & 0xFFF; } mb = page >> 8; dprint(v->msg_line, 0, v->test, 3, 0); dprint(v->msg_line, 4, v->pass, 5, 0); hprint(v->msg_line, 11, page); hprint2(v->msg_line, 19, offset, 3); cprint(v->msg_line, 22, " - . MB"); dprint(v->msg_line, 25, mb, 5, 0); dprint(v->msg_line, 31, ((page & 0xFF)*10)/256, 1, 0); if (type == 3) { /* ECC error */ cprint(v->msg_line, 36, bad?"corrected ": "uncorrected "); hprint2(v->msg_line, 60, syn, 4); cprint(v->msg_line, 68, "ECC"); dprint(v->msg_line, 74, chan, 2, 0); } else if (type == 2) { cprint(v->msg_line, 36, "Parity error detected "); } else { hprint(v->msg_line, 36, good); hprint(v->msg_line, 46, bad); hprint(v->msg_line, 56, xor); dprint(v->msg_line, 66, v->ecount, 5, 0); v->erri.exor = xor; } v->erri.eadr = (ulong)adr; print_err_counts(); break; case PRINTMODE_PATTERNS: if (v->erri.hdr_flag == 0) { clear_scroll(); v->erri.hdr_flag++; } /* Do not do badram patterns from test 0 or 5 */ if (v->test == 0 || v->test == 5) { return; } /* Only do patterns for data errors */ if ( type != 0) { return; } /* Process the address in the pattern administration */ patnchg=insertaddress ((ulong) adr); if (patnchg) { printpatn(); } break; case PRINTMODE_NONE: if (v->erri.hdr_flag == 0) { clear_scroll(); v->erri.hdr_flag++; } break; } } /* * 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, int corrected, unsigned short syndrome, int channel) { ++(v->ecc_ecount); syn = syndrome; chan = channel; common_err((ulong *)page, offset, corrected, 0, 2); } #ifdef PARITY_MEM /* * Print a parity error message */ void parity_err( unsigned long edi, unsigned long esi) { unsigned long addr; if (v->test == 5) { addr = esi; } else { addr = edi; } common_err((ulong *)addr, addr & 0xFFF, 0, 0, 3); } #endif /* * Print the pattern array as a LILO boot option addressing BadRAM support. */ void printpatn (void) { int idx=0; int x; /* Check for keyboard input */ check_input(); if (v->numpatn == 0) return; scroll(); cprint (v->msg_line, 0, "badram="); x=7; for (idx = 0; idx < v->numpatn; idx++) { if (x > 80-22) { scroll(); x=7; } cprint (v->msg_line, x, "0x"); hprint (v->msg_line, x+2, v->patn[idx].adr ); cprint (v->msg_line, x+10, ",0x"); hprint (v->msg_line, x+13, v->patn[idx].mask); if (idx+1 < v->numpatn) cprint (v->msg_line, x+21, ","); x+=22; } } /* * Show progress by displaying elapsed time and update bar graphs */ void do_tick(void) { int i, n, pct; ulong h, l, t; /* FIXME only print serial error messages from the tick handler */ if (v->ecount) { print_err_counts(); } nticks++; v->total_ticks++; if (test_ticks) { pct = 100*nticks/test_ticks; if (pct > 100) { pct = 100; } } else { pct = 0; } dprint(1, COL_MID+4, pct, 3, 0); i = (BAR_SIZE * pct) / 100; while (i > v->tptr) { if (v->tptr >= BAR_SIZE) { break; } cprint(1, COL_MID+9+v->tptr, "#"); v->tptr++; } if (v->pass_ticks) { pct = 100*v->total_ticks/v->pass_ticks; if (pct > 100) { pct = 100; } } else { pct = 0; } dprint(0, COL_MID+4, pct, 3, 0); i = (BAR_SIZE * pct) / 100; while (i > v->pptr) { if (v->pptr >= BAR_SIZE) { break; } cprint(0, COL_MID+9+v->pptr, "#"); v->pptr++; } if (v->ecount && v->printmode == PRINTMODE_SUMMARY) { /* Compute confidence score */ pct = 0; /* If there are no errors within 1mb of start - end addresses */ h = v->pmap[v->msegs - 1].end - 0x100; if (v->erri.low_addr.page > 0x100 && v->erri.high_addr.page < h) { pct += 8; } /* Errors for only some tests */ if (v->pass) { for (i=0, n=0; tseq[i].msg != NULL; i++) { if (tseq[i].errors == 0) { n++; } } pct += n*3; } else { for (i=0, n=0; itest; i++) { if (tseq[i].errors == 0) { n++; } } pct += n*2; } /* Only some bits in error */ n = 0; if (v->erri.ebits & 0xf) n++; if (v->erri.ebits & 0xf0) n++; if (v->erri.ebits & 0xf00) n++; if (v->erri.ebits & 0xf000) n++; if (v->erri.ebits & 0xf0000) n++; if (v->erri.ebits & 0xf00000) n++; if (v->erri.ebits & 0xf000000) n++; if (v->erri.ebits & 0xf0000000) n++; pct += (8-n)*2; /* Adjust the score */ pct = pct*100/22; /* if (pct > 100) { pct = 100; } */ dprint(LINE_HEADER+0, 25, pct, 3, 1); } /* We can't do the elapsed time unless the rdtsc instruction * is supported */ if (v->rdtsc) { asm __volatile__( "rdtsc":"=a" (l),"=d" (h)); asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (l), "=d" (h) :"g" (v->startl), "g" (v->starth), "0" (l), "1" (h)); t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000; t += (l / v->clks_msec) / 1000; i = t % 60; dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0); dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0); t /= 60; i = t % 60; dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0); dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0); t /= 60; dprint(LINE_TIME, COL_TIME, t, 4, 0); } /* Check for keyboard input */ check_input(); /* Poll for ECC errors */ poll_errors(); } memtest86+-4.20/spd.h0000644000000000000000000000063211517067470013014 0ustar rootroot/* * MemTest86+ V3.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ 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 memtest86+-4.20/memtest.bin.lds0000644000000000000000000000036611517067470015012 0ustar rootrootOUTPUT_FORMAT("binary") OUTPUT_ARCH("i386") ENTRY(_main); SECTIONS { . = 0; .bootsect : { *(.bootsect) } .setup : { *(.setup) } .memtest : { _start = . ; *(.data) _end = . ; } _syssize = (_end - _start + 15) >> 4; } memtest86+-4.20/Makefile0000644000000000000000000000354611517067470013524 0ustar rootroot# Makefile for MemTest86+ # # Author: Chris Brady # Created: January 1, 1996 # # Path for the floppy disk device # FDISK=/dev/fd0 AS=as -32 CC=gcc CFLAGS= -Wall -march=i486 -m32 -O2 -fomit-frame-pointer -fno-builtin -ffreestanding -fPIC -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 all: memtest.bin memtest # Link it statically once so I know I don't have undefined # symbols and then link it dynamically so I have full # relocation information memtest_shared: $(OBJS) memtest_shared.lds Makefile $(LD) --warn-constructors --warn-common -static -T memtest_shared.lds \ -o $@ $(OBJS) && \ $(LD) -shared -Bsymbolic -T memtest_shared.lds -o $@ $(OBJS) memtest_shared.bin: memtest_shared objcopy -O binary $< memtest_shared.bin memtest: memtest_shared.bin memtest.lds $(LD) -s -T memtest.lds -b binary memtest_shared.bin -o $@ head.s: head.S config.h defs.h test.h $(CC) -E -traditional $< -o $@ bootsect.s: bootsect.S config.h defs.h $(CC) -E -traditional $< -o $@ setup.s: setup.S config.h defs.h $(CC) -E -traditional $< -o $@ memtest.bin: memtest_shared.bin bootsect.o setup.o memtest.bin.lds $(LD) -T memtest.bin.lds bootsect.o setup.o -b binary \ memtest_shared.bin -o memtest.bin reloc.o: reloc.c $(CC) -c $(CFLAGS) -fno-strict-aliasing reloc.c test.o: test.c $(CC) -c -Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin -ffreestanding test.c clean: rm -f *.o *.s *.iso memtest.bin memtest memtest_shared memtest_shared.bin asm: @./makedos.sh iso: make all ./makeiso.sh rm -f *.o *.s memtest.bin memtest memtest_shared memtest_shared.bin install: all dd $(FDISK) bs=8192 install-precomp: dd $(FDISK) bs=8192 dos: all cat mt86+_loader memtest.bin > memtest.exe memtest86+-4.20/memsize.c0000644000000000000000000003112111517067470013667 0ustar rootroot/* memsize.c - MemTest-86 Version 3.3 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "test.h" #include "defs.h" #include "config.h" 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; static void sort_pmap(void); static int check_ram(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); 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; v->test_pages = 0; /* On the first time thru only */ /* Make a copy of the memory info table so that we can re-evaluate */ /* The memory map later */ if (e820_nr == 0 && alt_mem_k == 0 && ext_mem_k == 0) { ext_mem_k = mem_info.e88_mem_k; alt_mem_k = mem_info.e801_mem_k; e820_nr = mem_info.e820_nr; for (i=0; i< mem_info.e820_nr; i++) { e820[i].addr = mem_info.e820[i].addr; e820[i].size = mem_info.e820[i].size; 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; } /* 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) { int i, j; /* Do an insertion sort on the pmap, on an already sorted * list this should be a O(1) algorithm. */ for(i = 0; i < v->msegs; i++) { /* Find where to insert the current element */ for(j = i -1; j >= 0; j--) { if (v->pmap[i].start > v->pmap[j].start) { j++; break; } } /* Insert the current element */ if (i != j) { struct pmap temp; temp = v->pmap[i]; memmove(&v->pmap[j], &v->pmap[j+1], (i -j)* sizeof(temp)); v->pmap[j] = temp; } } } static void memsize_linuxbios(void) { int i, n; /* Build the memory map for testing */ n = 0; for (i=0; i < e820_nr; i++) { unsigned long long end; if (e820[i].type != E820_RAM) { continue; } end = e820[i].addr; end += e820[i].size; v->pmap[n].start = (e820[i].addr + 4095) >> 12; v->pmap[n].end = end >> 12; v->test_pages += v->pmap[n].end - v->pmap[n].start; n++; } v->msegs = n; cprint(LINE_INFO, COL_MMAP, "LxBIOS"); } static void memsize_820() { int i, n, nr; struct e820entry nm[E820MAX]; /* Clean up, adjust and copy the BIOS-supplied E820-map. */ nr = sanitize_e820_map(e820, nm, e820_nr); /* If there is not a good 820 map use the BIOS 801/88 info */ if (nr < 1 || nr > E820MAX) { memsize_801(); return; } /* Build the memory map for testing */ n = 0; for (i=0; i RES_START && start < RES_END) { if (end < RES_END) { continue; } start = RES_END; } if (end > RES_START && end < RES_END) { end = RES_START; } v->pmap[n].start = (start + 4095) >> 12; 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; } } v->msegs = n; cprint(LINE_INFO, COL_MMAP, " e820"); } static void memsize_801(void) { ulong mem_size; /* compare results from 88 and 801 methods and take the greater */ /* These sizes are for extended memory in 1k units. */ 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; v->pmap[0].end = RES_START >> 12; v->test_pages = RES_START >> 12; /* Now the extended memory */ v->pmap[1].start = (RES_END + 4095) >> 12; v->pmap[1].end = (mem_size + 1024) >> 2; v->test_pages += mem_size >> 2; v->msegs = 2; } /* * Sanitize the BIOS e820 map. * * Some e820 responses include overlapping entries. The following * replaces the original e820 map with a new one, removing overlaps. * */ static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, short old_nr) { struct change_member { struct e820entry *pbios; /* pointer to original bios entry */ unsigned long long addr; /* address for this change point */ }; struct change_member change_point_list[2*E820MAX]; struct change_member *change_point[2*E820MAX]; struct e820entry *overlap_list[E820MAX]; struct e820entry biosmap[E820MAX]; struct change_member *change_tmp; ulong current_type, last_type; unsigned long long last_addr; int chgidx, still_changing; int overlap_entries; int new_bios_entry; int i; /* Visually we're performing the following (1,2,3,4 = memory types)... Sample memory map (w/overlaps): ____22__________________ ______________________4_ ____1111________________ _44_____________________ 11111111________________ ____________________33__ ___________44___________ __________33333_________ ______________22________ ___________________2222_ _________111111111______ _____________________11_ _________________4______ Sanitized equivalent (no overlap): 1_______________________ _44_____________________ ___1____________________ ____22__________________ ______11________________ _________1______________ __________3_____________ ___________44___________ _____________33_________ _______________2________ ________________1_______ _________________4______ ___________________2____ ____________________33__ ______________________4_ */ /* First make a copy of the map */ for (i=0; iaddr = biosmap[i].addr; change_point[chgidx++]->pbios = &biosmap[i]; change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; change_point[chgidx++]->pbios = &biosmap[i]; } /* sort change-point list by memory addresses (low -> high) */ still_changing = 1; while (still_changing) { still_changing = 0; for (i=1; i < 2*old_nr; i++) { /* if > , swap */ /* or, if current= & last=, swap */ if ((change_point[i]->addr < change_point[i-1]->addr) || ((change_point[i]->addr == change_point[i-1]->addr) && (change_point[i]->addr == change_point[i]->pbios->addr) && (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) ) { change_tmp = change_point[i]; change_point[i] = change_point[i-1]; change_point[i-1] = change_tmp; still_changing=1; } } } /* create a new bios memory map, removing overlaps */ overlap_entries=0; /* number of entries in the overlap table */ new_bios_entry=0; /* index for creating new bios map entries */ last_type = 0; /* start with undefined memory type */ last_addr = 0; /* start with 0 as last starting address */ /* loop through change-points, determining affect on the new bios map */ for (chgidx=0; chgidx < 2*old_nr; chgidx++) { /* keep track of all overlapping bios entries */ if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) { /* add map entry to overlap list (> 1 entry implies an overlap) */ overlap_list[overlap_entries++]=change_point[chgidx]->pbios; } else { /* remove entry from list (order independent, so swap with last) */ for (i=0; ipbios) overlap_list[i] = overlap_list[overlap_entries-1]; } overlap_entries--; } /* if there are overlapping entries, decide which "type" to use */ /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ current_type = 0; for (i=0; itype > current_type) current_type = overlap_list[i]->type; /* continue building up new bios map based on this information */ if (current_type != last_type) { if (last_type != 0) { new_bios[new_bios_entry].size = change_point[chgidx]->addr - last_addr; /* move forward only if the new size was non-zero */ if (new_bios[new_bios_entry].size != 0) if (++new_bios_entry >= E820MAX) break; /* no more space left for new bios entries */ } if (current_type != 0) { new_bios[new_bios_entry].addr = change_point[chgidx]->addr; new_bios[new_bios_entry].type = current_type; last_addr=change_point[chgidx]->addr; } last_type = current_type; } } 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; } memtest86+-4.20/mt86+_loader.asm0000644000000000000000000001440611517067470014762 0ustar rootroot; A loader for www.memtest.org images, by Eric Auer 2003. ; This assumes that the image starts with the boot sector, ; which has the size of setup.S in sectors in a byte at offset ; 1f1h (497). Further, I assume setup.S directly after the boot ; sector and the actual memtest head.S after setup.S ... ; This version is derived from memtestL loader, which loads ; memtest.bin from a separate file. This version is meant to ; be used like (DOS / Unix variants): ; copy /b memteste.bin + memtest.bin memtest.exe ; cat memteste.bin memtest.bin > memtest.exe ; 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 stacksize 2048 %define stackpara ((stacksize + 15) / 16) ; the trick is that NASM believes the header would be part ; of the loaded image, so we "org 20h bytes too early" to fix: org 0e0h ; NASM thinks after header we have 100h ; which is what we want it to think. exeh: db "MZ" dw fullsize % 512 ; how much to load from dw (fullsize + 511) / 512 ; .exe to RAM dw 0 ; no relocations used dw 2 ; header size is 2 * 16 bytes dw stackpara ; minimum heap is 128 * 16 bytes, for stack dw stackpara ; we do not need more heap either dw (fullsize + 15) / 16 ; SS is after file ; segment offsets are relative to PSPseg+10h ; initial DS and ES point to PSPseg, and file ; except headers is loaded to PSPseg+10h. dw stacksize-4 ; initial SP value dw 0 ; no checksum dw 100h ; initial IP dw -10h ; initial CS relative to PSPseg+10h dw 0 ; no relocation table, "offset 0 in file" dw 0 ; this is not an overlay db "MEMT" ; padding to a multiple of 16 bytes ; loaded part begins here (set CS so that IP is 100h here) start: ; entry point ; if you use obj + linker, use "..start:" mov ah, 01h mov bh, 00h mov cx, 2000h int 10h mov ax,cs ; *** mov ds,ax ; *** mov es,ax ; *** ; test if we have 386 or better: pushf ; save flags xor ax,ax push ax popf ; try to clear all bits pushf pop ax and ax,0f000h cmp ax,0f000h jz noinst1 ; 4 msb stuck to 1: 808x or 80186 mov ax,0f000h push ax popf ; try to set 4 msb pushf pop ax test ax,0f000h jz noinst1 ; 4 msb stuck to 0: 80286 popf ; restore flags jmp short found386 noinst1: popf ; restore flags mov dx,need386 jmp generror found386: ; now test if the system is in real mode: smsw ax ; MSW is the low half of CR0 ; (smsw is not priv'd, unlike mov eax,cr0) test al,1 ; if the PE (protected mode) flag on? %ifndef DEBUG ; ignore findings in debug mode jnz foundprotected %endif jmp foundreal foundprotected: mov dx,noreal jmp generror ; ------------ need386 db "Sorry, you need at least a 386 CPU to use Memtest86+." db 13,10,"$" noreal db "You cannot run Memtest86+ if the system already is in" db " protected mode.",13,10,"$" ; ------------ generror: ; generic error exit push cs pop ds push cs pop es mov ah,9 int 21h mov ax,4c01h int 21h ; ------------ foundreal: mov cx,buffer+15 shr cx,4 ; buffer offset in paragraphs mov ax,cs add ax,cx ; buffer offset in paragraphs ; now AX is the buffer segment mov [cs:bufsetup+2],ax ; far pointer to boot sector now mov cx,20h ; size of boot sector in paragraphs add [cs:bufsetup+2],cx ; far pointer to setup now movzx eax,ax shl eax,4 ; linear buffer offset mov [cs:buflinear],eax findpoint: ; now patch the loader! mov al,[buffer+1f1h] ; size of setup.S in sectors ; should be 4 ... inc al ; the boot sector itself movzx eax,al shl eax,9 ; log 2 of sector size add [cs:buflinear],eax ; linear address of head.S now mov ax,[buffer+251h] ; should be jmp far dword (ofs, seg) cmp ax,0ea66h jz foundpatch patchbug: ; could not patch the jump mov dx,nopatch jmp generror gdtbug: mov dx,nogdt jmp generror foundpatch: mov eax,[cs:buflinear] mov [buffer+253h],eax ; patch the protected mode entry jump ; (offset only - segment selector unchanged: flat linear CS) findgdt: mov eax,[cs:buffer+20ch] ; should be lgdt offset and eax,00ffffffh cmp eax,0016010fh ; lgdt ... jnz gdtbug mov ax,[cs:buffer+20fh] ; GDTR contents pointer mov bx,ax mov eax,[cs:buffer+200h+bx+2] ; GDT linear offset and eax,1ffh ; assume GDT in first sector of setup.S ; *** WARNING: this is needed because setup.S contains ; *** HARDCODED offset of setup.S on linear 90200h, which ; *** is 90000h + bootsect.S ... flaw in Memtest86! mov cx,[cs:bufsetup+2] ; setup.S segment movzx ecx,cx shl ecx,4 ; linear setup.S address add eax,ecx ; fixed GDT linear offset mov [cs:buffer+200h+bx+2],eax ; patch it ;mov dx,trying ;mov ah,9 ;int 21h ;xor ax,ax ;int 16h ; wait for a keypress from the user mov ax,[cs:bufsetup+2] ; setup segment mov ds,ax ; set nice data segments for setup.S ... mov es,ax xor ax,ax mov fs,ax mov gs,ax cli lss sp,[cs:newstack] ; stack in first 64k now! movzx esp,sp ; ensure 16bit stack pointer ; Memtest86 head.S assumes that it can just turn SS to ; linear. This would put the stack at 0:200h or so for us ; if we fail to move the stack around ... %ifdef DEBUG mov ebp,[cs:buflinear] ; will show up in debugging logs mov esi,[cs:bufsetup] ; will show up in debugging logs %endif jmp far [cs:bufsetup] ; setup.S will enable the A20 (ignoring HIMEM, just using ; the classic 8042 programming trick) and turn on protected ; mode. Then it will jump to head.S, which luckily can run ; from any offset inside the linear 4 GB CS ... ; ------------ buflinear dd 0 ; linear address of head.S entry point bufsetup dw 0,0 ; far pointer to setup.S entry point newstack dw 03fch,0 ; beware, stack will overwrite IDT. ; ------------ nopatch db "jmp far dword not found at setup.S offset 37h,",13,10 db "(file offset 237h is not 66h, 0eah)",13,10 db "please adjust and recompile memtestl...",13,10,"$" nogdt db "lgdt [...] not found at setup.S offset 0ch,",13,10 db "(file offset 20ch is not 0fh, 01h, 16h)",13,10 db "please adjust and recompile memtestl...",13,10,"$" trying db "Now trying to start Memtest86...",13,10 db "You have to reboot to leave Memtest86 again.",13,10 db "Press a key to go on.",13,10,"$" ; ------------ align 16 buffer: ; a label pointing to where in the file memtest.bin will be. memtest86+-4.20/memtest.lds0000644000000000000000000000021511517067470014234 0ustar rootrootOUTPUT_FORMAT("elf32-i386"); OUTPUT_ARCH(i386); ENTRY(_start); SECTIONS { . = 0x5000; _start = . ; .data : { *(.data) } } memtest86+-4.20/README0000644000000000000000000005333111517067470012741 0ustar rootrootMemtest86++ 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. memtest86+-4.20/jedec_id.h0000644000000000000000000007033711517067470013765 0ustar rootroot/* MemTest86+ V4.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ struct spd_jedec_manufacturer { unsigned cont_code; unsigned hex_byte; 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, ""} }; memtest86+-4.20/dmi.h0000644000000000000000000000017411517067470013000 0ustar rootroot#ifndef __DMI_H__ #define __DMI_H__ int add_dmi_err(ulong adr); void print_dmi_err(void); void print_dmi_info(void); #endif memtest86+-4.20/mt86+_loader0000644000000000000000000000142011517067470014173 0ustar rootrootMZC[(MEMT Ȏ؎1PX%=tPXtDu|Sorry, you need at least a 386 CPU to use Memtest86+. $You cannot run Memtest86+ if the system already is in protected mode. $ !L!. .ff.f{ff .f{A=ft 밺.f{fC.ff%f=u..ff%.fff.f.؎1.&f..jmp far dword not found at setup.S offset 37h, (file offset 237h is not 66h, 0eah) please adjust and recompile memtestl... $lgdt [...] not found at setup.S offset 0ch, (file offset 20ch is not 0fh, 01h, 16h) please adjust and recompile memtestl... $Now trying to start Memtest86... You have to reboot to leave Memtest86 again. Press a key to go on. $memtest86+-4.20/memtest_shared.lds0000644000000000000000000000171711517067470015572 0ustar rootrootOUTPUT_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/ : { *(*) } } memtest86+-4.20/cpuid.c0000644000000000000000000001541711517067470013334 0ustar rootroot/* * cpuid.c -- * * Implements CPUID querying functions * */ #include "cpuid.h" cpuid_t cpuid_data0; cpuid_t cpuid_data80; 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) { 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); 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 */ } }