64MB+ detection patch for 2.0.31-pre5

Michael Meskes (meskes@topsystem.de)
Thu, 14 Aug 1997 10:16:20 +0200 (CEST)


Please include this patch. It works fin and more and more people do have
machines with that amount of memory. Since I couldn't find the patch as a
whole on linuxhq I include it with this mail.

--- setup.c Thu Aug 14 10:14:56 1997
+++ /usr/src/linux/arch/i386/kernel/setup.c Wed Aug 13 12:57:43 1997
@@ -87,6 +87,12 @@
#endif
#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
+/* Total memory in 1K blocks */
+#define MEM_K (*(unsigned int *) (PARAM+0x1E0))
+/* Amounted of memory cached in 1K blocks */
+#define MEM_K_CACHED (*(unsigned int *) (PARAM+0x1E4))
+/* Return code from BIOS memory detection routines in setup.S */
+#define MEM_BIOS_RESULTS (*(unsigned char *) (PARAM+0x1E8))
#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
@@ -108,7 +114,7 @@
void setup_arch(char **cmdline_p,
unsigned long * memory_start_p, unsigned long * memory_end_p)
{
- unsigned long memory_start, memory_end;
+ unsigned long memory_start, memory_end, old_style_memory_end;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
static unsigned char smptrap=0;
@@ -126,7 +132,38 @@
apm_bios_info = APM_BIOS_INFO;
#endif
aux_device_present = AUX_DEVICE_INFO;
- memory_end = (1<<20) + (EXT_MEM_K<<10);
+
+ /* Memory detection code added by lma@varesearch.com 4/16/97 */
+ old_style_memory_end = (1<<20) + (EXT_MEM_K << 10);
+ memory_end = MEM_K << 10;
+ if (old_style_memory_end > memory_end) {
+ printk("Old 16-bit EXT_MEM_K parameter shows more memory than new 32-bit\n memory detection code. Please report this to lma@varesearch.com.\n Reverting to old 16-bit memory parameter.\n");
+ memory_end = old_style_memory_end;
+ }
+ printk("BIOS query detected %dKB RAM. Report errors to lma@varesearch.com\n", MEM_K);
+ switch(MEM_BIOS_RESULTS) {
+ case 0x01:
+ printk("Warning: BIOS function int 15h ah=88h used to determine RAM size returned an error code\n indicating failure. The amount of detected RAM may be incorrect.\n");
+ break;
+ case 0x02:
+ printk("Total RAM size was detected using int 15h, ah=88h.\n Your system BIOS does not support detecting more than 64M of RAM.\n");
+ break;
+ case 0x03:
+ printk("Total RAM size was detected using BIOS function int 15h, ax=e801h.\n");
+ break;
+ case 0x04:
+ printk("Total RAM size was detected using BIOS function int 15h, ax=e801h.\n Your BIOS does not support the ah=c0h feature code test.\n");
+ break;
+ case 0x05:
+ printk("BIOS int 15h, ah=c7h reports %dKB of %dKB RAM is cached.\n", MEM_K, MEM_K_CACHED);
+ break;
+ case 0x06:
+ printk("Total RAM size was detected using BIOS function int 15h, ax=e801h.\n A call to ah=c7h did not succeed.\n");
+ break;
+ default:
+ printk("Warning: BIOS based memory detection routine returned unknown result code %x.\n", MEM_BIOS_RESULTS);
+ }
+
memory_end &= PAGE_MASK;
#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
--- setup.S Thu Aug 14 10:14:56 1997
+++ /usr/src/linux/arch/i386/boot/setup.S Wed Aug 13 12:57:43 1997
@@ -26,6 +26,9 @@
!
! Video handling moved to video.S by Martin Mares, March 1996
! <mj@k332.feld.cvut.cz>
+!
+! Modifications to detect > 64M RAM by Larry M. Augustin lma@varesearch.com 4/16/97.
+

! NOTE! These had better be the same as in bootsect.s!
#define __ASSEMBLY__
@@ -230,17 +233,90 @@
db 0

loader_ok:
-! Get memory size (extended mem, kB)

+! Start of memory size detection code
+!
+! int 15h, ah=0x88
+! Returns amount of memory above 1MB in KB in AX
+! 16M == 3C00 (15M extended memory)
+! ...
+! 64M == FC00 (63M extended memory)
+ xor eax,eax ! Clear upper part of EAX
mov ah,#0x88
int 0x15
- mov [2],ax
-
+ pushf ! Save CF error flag
+ mov [0x2], ax ! save result at PARAM+2 offset in kernel parameter page
+ and eax, #0x0000ffff ! Clear upper 16 bits
+ add eax, #0x0400 ! Add 1MB
+ mov [0x1E0], eax ! Save 32-bit result at PARAM+0x220 offset
+ popf ! Restore CF error flag
+ jnc int15_88_good ! CF = 1 indicates error
+ movb [0x1E8], #0x01 ! Return the result code
+ lea cx, end_memdetect ! gas can't do 16-bit offset jumps. very annoying.
+ jmp cx
+int15_88_good:
+ ! int 15h succeeded, but now we should check for more advanced BIOS calls
+try_int15_e801: ! try int 15h, ax=e801
+ mov ax,#0xe801
+ int 0x15
+ jnc int15_e801_good ! CF = 1 indicates error
+ movb [0x1E8], #0x02 ! Only int 15h, ah=88h succeeded. Return the result code.
+ jmp end_memdetect ! Return int 15h, ah=88h result.
+int15_e801_good:
+ and eax, #0x0000ffff ! Clear upper 16 bits
+ and ebx, #0x0000ffff ! Clear upper 16 bits
+ shl ebx, 6 ! Multiply EBX by 64 so we have memory in 1K blocks
+ add eax, ebx
+ add eax, #0x0400 ! Add 1MB
+ mov [0x1E0], eax ! Return 32-bit result
+testfor_int15_c7: ! Test if int 15h ah=c7h is supported using int 15h, ah=c0
+ push es
+ mov ah, #0xc0
+ int 0x15 ! ES:BX points to a configuration table
+ seg es
+ movb al, 6(bx) ! Save byte at ES:BX + 6 for testing
+ pop es
+ or ah,ah ! check return code
+ jnz int15_c7_test_failed ! BIOS call failed, try int 15h, ax=e801
+int15_c0_good: ! int 15, c0 call succeeded
+ and al,#0x10 ! Test bit 4 of byte at ES:BX + 6
+ jnz try_int15_c7 ! int 15h, ah=c7h is supported. call it.
+ movb [0x1E8], #0x03 ! int 15h,ax=e801h succeeded. ah=c7h not supported. Return result.
+ jmp end_memdetect
+int15_c7_test_failed:
+ movb [0x1E8], #0x04 ! int 15h,ax=e801h succeeded. ah=c0h BIOS feature test failed.
+ jmp end_memdetect
+try_int15_c7: ! Try calling int 15 ah=c7
+ push ds
+ push cs
+ pop ds
+ lea si,mem_tbl ! address of memory map table
+ mov ah,#0xc7 !
+ int 0x15 !
+ pop ds
+ jc int15_c7_fail ! CF = 1 indicates an error, fall back to int 15h ax=e801
+int15_c7_good:
+ mov eax, lmlo ! Memory between 1M and 16M in 1K blocks
+ add eax, lmhi ! Memory above 16M in 1K blocks
+ add eax, #0x0400 ! Add 1MB
+ mov [0x1E0], eax ! Return 32-bit result
+ mov eax, cmlo ! Cacheable memory between 1M and 16M in 1K blocks
+ add eax, cmhi ! Cacheable memory above 16M in 1K blocks
+ add eax, #0x0400 ! Add 1MB
+ mov [0x1E4], eax ! Return 32-bit result
+ movb [0x1E8], #0x05 ! Return the result code
+int15_c7_fail:
+ movb [0x1E8], #0x06 ! int 15h,ax=e801h succeeded. ah=c7h call failed.
+end_memdetect:
+
+! LMA 4/15/97 removed setting of keyboard repeat rate. Causes some systems
+! to hang at boot. No need for this in ther kernel anyway. It is probably better done
+! with the kbdrate command.
! Set the keyboard repeat rate to the max

- mov ax,#0x0305
- xor bx,bx ! clear bx
- int 0x16
+! mov ax,#0x0305
+! xor bx,bx ! clear bx
+! int 0x16

! Check for video adapter and its parameters and allow the
! user to browse video modes.
@@ -700,6 +776,19 @@
gdt_48:
.word 0x800 ! gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ! gdt base = 0X9xxxx
+
+mem_tbl:
+ .word 0x0000 ! length of table (excluding this word)
+lmlo: .word 0x0000, 0x0000 ! local memory between 1M and 16M in 1K blocks
+lmhi: .word 0x0000, 0x0000 ! local memory between 16M and 4G in 1K blocks
+smlo: .word 0x0000, 0x0000 ! system memory between 1M and 16M in 1K blocks
+smhi: .word 0x0000, 0x0000 ! system memory between 16M and 4G in 1K blocks
+cmlo: .word 0x0000, 0x0000 ! cacheable memory between 1M and 16M in 1K blocks
+cmhi: .word 0x0000, 0x0000 ! cacheable memory between 16M and 4G in 1K blocks
+ .word 0x0000, 0x0000 ! 1K blocks before start of non-system memory between 1M and 16M
+ .word 0x0000, 0x0000 ! 1K blocks before start of non-system memory between 16M and 4G
+ .word 0x0000, 0x0000 ! reserved
+ .word 0x0000, 0x0000 ! reserved

!
! Include video setup & detection code

Michael

-- 
Dr. Michael Meskes, Project-Manager    | topsystem Systemhaus GmbH
meskes@topsystem.de                    | Europark A2, Adenauerstr. 20
meskes@debian.org                      | 52146 Wuerselen
Go SF49ers! Go Rhein Fire!             | Tel: (+49) 2405/4670-44
Use Debian GNU/Linux!                  | Fax: (+49) 2405/4670-10