3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 U32
GetExtendedMemorySize(VOID
)
34 DbgPrint((DPRINT_MEMORY
, "GetExtendedMemorySize()\n"));
37 // Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
41 // CF clear if successful
42 // AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
43 // BX = extended memory above 16M, in 64K blocks
44 // CX = configured memory 1M to 16M, in K
45 // DX = configured memory above 16M, in 64K blocks
48 Int386(0x15, &RegsIn
, &RegsOut
);
50 DbgPrint((DPRINT_MEMORY
, "Int15h AX=E801h\n"));
51 DbgPrint((DPRINT_MEMORY
, "AX = 0x%x\n", RegsOut
.w
.ax
));
52 DbgPrint((DPRINT_MEMORY
, "BX = 0x%x\n", RegsOut
.w
.bx
));
53 DbgPrint((DPRINT_MEMORY
, "CX = 0x%x\n", RegsOut
.w
.cx
));
54 DbgPrint((DPRINT_MEMORY
, "DX = 0x%x\n", RegsOut
.w
.dx
));
55 DbgPrint((DPRINT_MEMORY
, "CF set = %s\n\n", (RegsOut
.x
.eflags
& I386FLAG_CF
) ? "TRUE" : "FALSE"));
57 if (INT386_SUCCESS(RegsOut
))
59 // If AX=BX=0000h the use CX and DX
60 if (RegsOut
.w
.ax
== 0)
62 // Return extended memory size in K
63 MemorySize
= RegsOut
.w
.dx
* 64;
64 MemorySize
+= RegsOut
.w
.cx
;
69 // Return extended memory size in K
70 MemorySize
= RegsOut
.w
.bx
* 64;
71 MemorySize
+= RegsOut
.w
.ax
;
76 // If we get here then Int15 Func E801h didn't work
77 // So try Int15 Func 88h
80 // SYSTEM - GET EXTENDED MEMORY SIZE (286+)
84 // CF clear if successful
85 // AX = number of contiguous KB starting at absolute address 100000h
88 // 80h invalid command (PC,PCjr)
89 // 86h unsupported function (XT,PS30)
91 Int386(0x15, &RegsIn
, &RegsOut
);
93 DbgPrint((DPRINT_MEMORY
, "Int15h AH=88h\n"));
94 DbgPrint((DPRINT_MEMORY
, "AX = 0x%x\n", RegsOut
.w
.ax
));
95 DbgPrint((DPRINT_MEMORY
, "CF set = %s\n\n", (RegsOut
.x
.eflags
& I386FLAG_CF
) ? "TRUE" : "FALSE"));
97 if (INT386_SUCCESS(RegsOut
) && RegsOut
.w
.ax
!= 0)
99 MemorySize
= RegsOut
.w
.ax
;
103 // If we get here then Int15 Func 88h didn't work
104 // So try reading the CMOS
105 WRITE_PORT_UCHAR((PUCHAR
)0x70, 0x31);
106 MemorySize
= READ_PORT_UCHAR((PUCHAR
)0x71);
107 MemorySize
= (MemorySize
& 0xFFFF);
108 MemorySize
= (MemorySize
<< 8);
110 DbgPrint((DPRINT_MEMORY
, "Int15h Failed\n"));
111 DbgPrint((DPRINT_MEMORY
, "CMOS reports: 0x%x\n", MemorySize
));
116 U32
GetConventionalMemorySize(VOID
)
120 DbgPrint((DPRINT_MEMORY
, "GetConventionalMemorySize()\n"));
123 // BIOS - GET MEMORY SIZE
126 // AX = kilobytes of contiguous memory starting at absolute address 00000h
128 // This call returns the contents of the word at 0040h:0013h;
129 // in PC and XT, this value is set from the switches on the motherboard
131 Int386(0x12, &Regs
, &Regs
);
133 DbgPrint((DPRINT_MEMORY
, "Int12h\n"));
134 DbgPrint((DPRINT_MEMORY
, "AX = 0x%x\n\n", Regs
.w
.ax
));
136 return (U32
)Regs
.w
.ax
;
139 U32
GetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap
, U32 MaxMemoryMapSize
)
144 DbgPrint((DPRINT_MEMORY
, "GetBiosMemoryMap()\n"));
147 // Newer BIOSes - GET SYSTEM MEMORY MAP
151 // EDX = 534D4150h ('SMAP')
152 // EBX = continuation value or 00000000h to start at beginning of map
153 // ECX = size of buffer for result, in bytes (should be >= 20 bytes)
154 // ES:DI -> buffer for result
156 // CF clear if successful
157 // EAX = 534D4150h ('SMAP')
158 // ES:DI buffer filled
159 // EBX = next offset from which to copy or 00000000h if all done
160 // ECX = actual length returned in bytes
162 // AH = error code (86h)
163 Regs
.x
.eax
= 0x0000E820;
164 Regs
.x
.edx
= 0x534D4150; // ('SMAP')
165 Regs
.x
.ebx
= 0x00000000;
166 Regs
.x
.ecx
= sizeof(BIOS_MEMORY_MAP
);
167 Regs
.w
.es
= BIOSCALLBUFSEGMENT
;
168 Regs
.w
.di
= BIOSCALLBUFOFFSET
;
169 for (MapCount
=0; MapCount
<MaxMemoryMapSize
; MapCount
++)
171 Int386(0x15, &Regs
, &Regs
);
173 DbgPrint((DPRINT_MEMORY
, "Memory Map Entry %d\n", MapCount
));
174 DbgPrint((DPRINT_MEMORY
, "Int15h AX=E820h\n"));
175 DbgPrint((DPRINT_MEMORY
, "EAX = 0x%x\n", Regs
.x
.eax
));
176 DbgPrint((DPRINT_MEMORY
, "EBX = 0x%x\n", Regs
.x
.ebx
));
177 DbgPrint((DPRINT_MEMORY
, "ECX = 0x%x\n", Regs
.x
.ecx
));
178 DbgPrint((DPRINT_MEMORY
, "CF set = %s\n", (Regs
.x
.eflags
& I386FLAG_CF
) ? "TRUE" : "FALSE"));
180 // If the BIOS didn't return 'SMAP' in EAX then
181 // it doesn't support this call
182 if (Regs
.x
.eax
!= 0x534D4150)
187 // Copy data to caller's buffer
188 RtlCopyMemory(&BiosMemoryMap
[MapCount
], (PVOID
)BIOSCALLBUFFER
, Regs
.x
.ecx
);
190 DbgPrint((DPRINT_MEMORY
, "BaseAddress: 0x%x%x\n", BiosMemoryMap
[MapCount
].BaseAddress
));
191 DbgPrint((DPRINT_MEMORY
, "Length: 0x%x%x\n", BiosMemoryMap
[MapCount
].Length
));
192 DbgPrint((DPRINT_MEMORY
, "Type: 0x%x\n", BiosMemoryMap
[MapCount
].Type
));
193 DbgPrint((DPRINT_MEMORY
, "Reserved: 0x%x\n", BiosMemoryMap
[MapCount
].Reserved
));
194 DbgPrint((DPRINT_MEMORY
, "\n"));
196 // If the continuation value is zero or the
197 // carry flag is set then this was
198 // the last entry so we're done
199 if (Regs
.x
.ebx
== 0x00000000 || !INT386_SUCCESS(Regs
))
202 DbgPrint((DPRINT_MEMORY
, "End Of System Memory Map!\n\n"));
206 // Setup the registers for the next call
207 Regs
.x
.eax
= 0x0000E820;
208 Regs
.x
.edx
= 0x534D4150; // ('SMAP')
209 //Regs.x.ebx = 0x00000001; // Continuation value already set by the BIOS
210 Regs
.x
.ecx
= sizeof(BIOS_MEMORY_MAP
);
211 Regs
.w
.es
= BIOSCALLBUFSEGMENT
;
212 Regs
.w
.di
= BIOSCALLBUFOFFSET
;