📄 init.c
字号:
/* init.c - MemTest-86 Version 3.0 * * Released under version 2 of the Gnu Public License. * By Chris Brady, cbrady@sgi.com * ---------------------------------------------------- * MemTest86+ V1.70 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */#include "test.h"#include "defs.h"#include "config.h"#include "controller.h"#include "pci.h"#include "io.h"extern short memsz_mode;extern short firmware;int beepmode;struct cpu_ident cpu_id;ulong st_low, st_high;ulong end_low, end_high;ulong cal_low, cal_high;ulong extclock;static ulong memspeed(ulong src, ulong len, int iter);static void cpu_type(void);static void cacheable(void);static int cpuspeed(void);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); i<TITLE_WIDTH; i++, pp+=2) { *pp = 0x20; } cprint(0, 0, " Memtest86 v1.70 "); for(i=0, pp=(char *)(SCREEN_ADR+1); i<2; i++, pp+=30) { *pp = 0xA4; } cprint(0, 15, "+"); /* Do reverse video for the bottom display line */ for(i=0, pp=(char *)(SCREEN_ADR+1+(24 * 160)); i<80; i++, pp+=2) { *pp = 0x71; } serial_echo_print("\x1B[0m");}/* * Initialize test, setup screen and find out how much memory there is. */void init(void){ int i; outb(0x8, 0x3f2); /* Kill Floppy Motor */ /* Turn on cache */ set_cache(1); /* Setup the display */ display_init(); /* Determine the memory map */ if ((firmware == FIRMWARE_UNKNOWN) && (memsz_mode != SZ_MODE_PROBE)) { if (query_linuxbios()) { firmware = FIRMWARE_LINUXBIOS; } else if (query_pcbios()) { firmware = FIRMWARE_PCBIOS; } } mem_size(); /* setup pci */ pci_init(); /* setup beep mode */ beepmode = BEEP_MODE; v->test = 0; v->testsel = -1; v->msg_line = LINE_SCROLL-1; v->scroll_start = v->msg_line * 160; cprint(LINE_CPU+1, 0, "L1 Cache: Unknown "); cprint(LINE_CPU+2, 0, "L2 Cache: Unknown "); cprint(LINE_CPU+3, 0, "Memory : "); aprint(LINE_CPU+3, 10, v->test_pages); cprint(LINE_CPU+4, 0, "Chipset : "); cpu_type(); /* Find the memory controller (inverted from standard) */ find_controller(); 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(); v->printmode=PRINTMODE_ADDRESSES; v->numpatn=0; find_ticks();}#define FLAT 0static 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; 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 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]; l1_cache += cpu_id.cache_info[7]; l2_cache = (cpu_id.cache_info[11] << 8); l2_cache += cpu_id.cache_info[10]; 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 9: 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; } 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -