diff options
author | Tobias Weingartner <weingart@cvs.openbsd.org> | 2002-06-20 20:22:59 +0000 |
---|---|---|
committer | Tobias Weingartner <weingart@cvs.openbsd.org> | 2002-06-20 20:22:59 +0000 |
commit | e1ff28eeda5ba208f890eee363ea02698428e9f4 (patch) | |
tree | a96b3d1c80001d36fa55d7759e3436a923ed07df | |
parent | ee8982b34af448814c8d6cb1ffd156515693c3f2 (diff) |
Fix 4GB memory probing and other memory probing issues.
Outstanding issue is with Compaq 16MB detection problem.
ok deraadt@, and various people from the 'net.
-rw-r--r-- | sys/arch/i386/stand/libsa/Makefile | 6 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/apmprobe.c | 11 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/biosprobe.c | 83 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/libsa.h | 7 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/memprobe.c | 61 |
5 files changed, 140 insertions, 28 deletions
diff --git a/sys/arch/i386/stand/libsa/Makefile b/sys/arch/i386/stand/libsa/Makefile index 0d568eeaa67..9072d80f629 100644 --- a/sys/arch/i386/stand/libsa/Makefile +++ b/sys/arch/i386/stand/libsa/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.38 2000/10/25 17:12:07 mickey Exp $ +# $OpenBSD: Makefile,v 1.39 2002/06/20 20:22:58 weingart Exp $ .include "${.CURDIR}/../Makefile.inc" @@ -17,12 +17,12 @@ SRCS+= unixdev.c unixsys.S nullfs.c memprobe.c CLEANFILES+= gidt.o debug_i386.o alloca.o \ biosdev.o bioscons.o gateA20.o apmprobe.o \ memprobe.o diskprobe.o smpprobe.o \ - time.o + time.o biosprobe.o .else SRCS+= gidt.S debug_i386.S alloca.S \ biosdev.c bioscons.c gateA20.c apmprobe.c \ memprobe.c diskprobe.c pciprobe.c smpprobe.c \ - time.c + time.c biosprobe.c CLEANFILES+= unixdev.o unixsys.o nullfs.o .endif diff --git a/sys/arch/i386/stand/libsa/apmprobe.c b/sys/arch/i386/stand/libsa/apmprobe.c index cdc9d600d4d..16b0abf3634 100644 --- a/sys/arch/i386/stand/libsa/apmprobe.c +++ b/sys/arch/i386/stand/libsa/apmprobe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apmprobe.c,v 1.8 2000/01/29 21:49:36 mickey Exp $ */ +/* $OpenBSD: apmprobe.c,v 1.9 2002/06/20 20:22:58 weingart Exp $ */ /* * Copyright (c) 1997-2000 Michael Shalayeff @@ -186,12 +186,13 @@ apmprobe() } void -apmcheck() +apmfixmem(void) { #ifdef DEBUG - printf("apm"); + printf("apmremove (%d)", ai.apm_detail); #endif - mem_delete(i386_trunc_page(ai.apm_data_base), - i386_round_page(ai.apm_data_base + ai.apm_data_len)); + if (ai.apm_detail) + mem_delete(i386_trunc_page(ai.apm_data_base), + i386_round_page(ai.apm_data_base + ai.apm_data_len)); } diff --git a/sys/arch/i386/stand/libsa/biosprobe.c b/sys/arch/i386/stand/libsa/biosprobe.c new file mode 100644 index 00000000000..fddf1b2ed57 --- /dev/null +++ b/sys/arch/i386/stand/libsa/biosprobe.c @@ -0,0 +1,83 @@ +/* $OpenBSD: biosprobe.c,v 1.1 2002/06/20 20:22:58 weingart Exp $ */ + +/* + * Copyright (c) 2002 Tobias Weingartner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <machine/biosvar.h> +#include <machine/pio.h> +#include <dev/cons.h> +#include <lib/libsa/stand.h> +#include "debug.h" + + +void * +getSYSCONFaddr() +{ + u_int32_t status; + u_int8_t *vers; + + __asm __volatile(DOINT(0x15) "\n\t" + "setc %%al\n\t" + : "=a" (status) + : "0" (0xC000) + : "%ebx", "%ecx", "%edx", "%esi", "%edi", "cc"); + + /* On failure we go for a NULL */ + if(status) + return(NULL); + + /* Calculate where the version bytes are */ + vers = (void*)((BIOS_regs.biosr_es << 4) | BIOS_regs.biosr_bx); + return(vers); +} + +void * +getEBDAaddr() +{ + u_int32_t status; + u_int8_t *info; + + info = getSYSCONFaddr(); + if(!info) return(NULL); + + __asm __volatile(DOINT(0x15) "\n\t" + "setc %%al" + : "=a" (status) + : "0" (0xC100) + : "%ebx", "%ecx", "%edx", "%esi", "%edi", "cc"); + + if(status) return(NULL); + + info = (void *)(BIOS_regs.biosr_es << 4); + + return(info); +} + diff --git a/sys/arch/i386/stand/libsa/libsa.h b/sys/arch/i386/stand/libsa/libsa.h index 298aba48ab6..3e8499f4255 100644 --- a/sys/arch/i386/stand/libsa/libsa.h +++ b/sys/arch/i386/stand/libsa/libsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: libsa.h,v 1.34 2002/03/14 01:26:34 millert Exp $ */ +/* $OpenBSD: libsa.h,v 1.35 2002/06/20 20:22:58 weingart Exp $ */ /* * Copyright (c) 1996-1999 Michael Shalayeff @@ -45,7 +45,7 @@ void pciprobe(void); void memprobe(void); void diskprobe(void); void apmprobe(void); -void apmcheck(void); +void apmfixmem(void); void dump_biosmem(bios_memmap_t *); int mem_add(long, long); int mem_delete(long, long); @@ -54,6 +54,9 @@ void mem_pass(void); void devboot(dev_t, char *); void machdep(void); +void *getSYSCONFaddr(void); +void *getEBDAaddr(void); + extern const char bdevs[][4]; extern const int nbdevs; extern u_int cnvmem, extmem; /* XXX global pass memprobe()->machdep_start() */ diff --git a/sys/arch/i386/stand/libsa/memprobe.c b/sys/arch/i386/stand/libsa/memprobe.c index e987c284262..29853aaf4f2 100644 --- a/sys/arch/i386/stand/libsa/memprobe.c +++ b/sys/arch/i386/stand/libsa/memprobe.c @@ -1,8 +1,8 @@ -/* $OpenBSD: memprobe.c,v 1.36 2002/05/03 13:58:11 espie Exp $ */ +/* $OpenBSD: memprobe.c,v 1.37 2002/06/20 20:22:58 weingart Exp $ */ /* * Copyright (c) 1997-1999 Michael Shalayeff - * Copyright (c) 1997 Tobias Weingartner + * Copyright (c) 1997-1999 Tobias Weingartner * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,7 +73,9 @@ static __inline bios_memmap_t * bios_E820(mp) register bios_memmap_t *mp; { + void *info; int rc, off = 0, sig, gotcha = 0; + info = getEBDAaddr(); do { BIOS_regs.biosr_es = ((u_int)(mp) >> 4); @@ -100,29 +102,46 @@ bios_E820(mp) return (mp); } -/* XXX Disabled until it is shown it is needed, and a version that does not - * confuse the AT&T Globalyst 580 comes up. Ask niklas@openbsd.org if you - * want to know details. - */ #if 0 /* BIOS int 15, AX=E801 * * Only used if int 15, AX=E820 does not work. - * This should work for more than 64MB. + * This should work for more than 64MB on most + * modern machines. However, there is always + * an exception, the older IBM machine do not + * like this call. */ static __inline bios_memmap_t * bios_E801(mp) register bios_memmap_t *mp; { - int rc, m1, m2; + int rc, m1, m2, m3, m4; + u_int8_t *info; + + /* Test for possibility of 0xE801 */ + info = getSYSCONFaddr(); + if(!info) return(NULL); + /* XXX - Should test model/submodel/rev here */ + printf("model(%d,%d,%d)", info[2], info[3], info[4]); - /* Test for 0xE801 */ - __asm __volatile(DOINT(0x15) "; setc %b1" - : "=a" (m1), "=b" (m2), "=c" (rc) : "0" (0xE801)); + /* Check for 94 or later bios */ + info = (void *)0xFFFFB; + if(info[0] == '9' && info[1] <= '3') return(NULL); - /* Make a memory map from info */ + /* We might have this call */ + __asm __volatile(DOINT(0x15) "; mov %%ax, %%si; setc %b0" + : "=a" (rc), "=S" (m1), "=b" (m2), "=c" (m3), "=d" (m4) + : "0" (0xE801)); + + /* Test for failure */ if(rc & 0xff) return (NULL); + + /* Fixup for screwed up machines */ + if(m1 == 0){ + m1 = m3; + m2 = m4; + } #ifdef DEBUG printf("0x15[E801] "); #endif @@ -306,11 +325,12 @@ memprobe() pm = im; } } - pm->type = BIOS_MAP_END; - /* gotta peephole optimize the list */ - apmcheck(); + /* XXX - gotta peephole optimize the list */ + + /* Remove APM needed RAM */ + apmfixmem(); #ifdef DEBUG printf(")["); @@ -359,9 +379,14 @@ dump_biosmem(tm) if (!tm) tm = bios_memmap; + /* libsa printf does not handle quad args, so we use long + * instead. Note, since we're unlikely to support more than + * 4G of RAM on a x86 box, this not likely to cause a problem. + * If/when we do, libsa may need to be updated some... + */ for(p = tm; p->type != BIOS_MAP_END; p++) { printf("Region %ld: type %u at 0x%x for %uKB\n", - (long)(p - tm), p->type, (u_int)p->addr, + (long)(p - tm), p->type, (u_int)p->addr, (u_int)(p->size / 1024)); if(p->type == BIOS_MAP_FREE) @@ -380,7 +405,7 @@ mem_delete(sa, ea) for (p = bios_memmap; p->type != BIOS_MAP_END; p++) { if (p->type == BIOS_MAP_FREE) { - register int32_t sp = p->addr, ep = p->addr + p->size; + register int64_t sp = p->addr, ep = p->addr + p->size; /* can we eat it as a whole? */ if ((sa - sp) <= NBPG && (ep - ea) <= NBPG) { @@ -418,7 +443,7 @@ mem_add(sa, ea) for (p = bios_memmap; p->type != BIOS_MAP_END; p++) { if (p->type == BIOS_MAP_FREE) { - register int32_t sp = p->addr, ep = p->addr + p->size; + register int64_t sp = p->addr, ep = p->addr + p->size; /* is it already there? */ if (sp <= sa && ea <= ep) { |