2d6890ea78e7fbcffeb17b889210e124ae39242b
[reactos.git] / boot / freeldr / freeldr / arch / i386 / xboxmem.c
1 /*
2 * FreeLoader
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Note: much of this code was based on knowledge and/or code developed
19 * by the Xbox Linux group: http://www.xbox-linux.org
20 */
21
22 #include <freeldr.h>
23 #include <debug.h>
24
25 DBG_DEFAULT_CHANNEL(MEMORY);
26
27 static ULONG InstalledMemoryMb = 0;
28 static ULONG AvailableMemoryMb = 0;
29
30 #define TEST_SIZE 0x200
31 #define TEST_PATTERN1 0xAA
32 #define TEST_PATTERN2 0x55
33
34 extern VOID
35 SetMemory(
36 PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
37 ULONG_PTR BaseAddress,
38 SIZE_T Size,
39 TYPE_OF_MEMORY MemoryType);
40
41 extern ULONG
42 PcMemFinalizeMemoryMap(
43 PFREELDR_MEMORY_DESCRIPTOR MemoryMap);
44
45 VOID
46 XboxMemInit(VOID)
47 {
48 UCHAR ControlRegion[TEST_SIZE];
49 PVOID MembaseTop = (PVOID)(64 * 1024 * 1024);
50 PVOID MembaseLow = (PVOID)0;
51
52 (*(PULONG)(0xfd000000 + 0x100200)) = 0x03070103;
53 (*(PULONG)(0xfd000000 + 0x100204)) = 0x11448000;
54
55 WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84));
56 WRITE_PORT_ULONG((ULONG*) 0xcfc, 0x7ffffff); /* Prep hardware for 128 Mb */
57
58 InstalledMemoryMb = 64;
59 memset(ControlRegion, TEST_PATTERN1, TEST_SIZE);
60 memset(MembaseTop, TEST_PATTERN1, TEST_SIZE);
61 __wbinvd();
62
63 if (memcmp(MembaseTop, ControlRegion, TEST_SIZE) == 0)
64 {
65 /* Looks like there is memory .. maybe a 128MB box */
66 memset(ControlRegion, TEST_PATTERN2, TEST_SIZE);
67 memset(MembaseTop, TEST_PATTERN2, TEST_SIZE);
68 __wbinvd();
69 if (memcmp(MembaseTop, ControlRegion, TEST_SIZE) == 0)
70 {
71 /* Definitely looks like there is memory */
72 if (memcmp(MembaseLow, ControlRegion, TEST_SIZE) == 0)
73 {
74 /* Hell, we find the Test-string at 0x0 too! */
75 InstalledMemoryMb = 64;
76 }
77 else
78 {
79 InstalledMemoryMb = 128;
80 }
81 }
82 }
83
84 /* Set hardware for amount of memory detected */
85 WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84));
86 WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1);
87
88 /* 4 MB video framebuffer is reserved later using XboxMemReserveMemory() */
89 AvailableMemoryMb = InstalledMemoryMb;
90 }
91
92 FREELDR_MEMORY_DESCRIPTOR XboxMemoryMap[MAX_BIOS_DESCRIPTORS + 1];
93
94 PFREELDR_MEMORY_DESCRIPTOR
95 XboxMemGetMemoryMap(ULONG *MemoryMapSize)
96 {
97 TRACE("XboxMemGetMemoryMap()\n");
98 /* FIXME: Obtain memory map via multiboot spec */
99
100 /* Synthesize memory map */
101
102 /* Available RAM block */
103 SetMemory(XboxMemoryMap,
104 0,
105 AvailableMemoryMb * 1024 * 1024,
106 LoaderFree);
107
108 /* Video memory */
109 SetMemory(XboxMemoryMap,
110 AvailableMemoryMb * 1024 * 1024,
111 (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024,
112 LoaderFirmwarePermanent);
113
114 *MemoryMapSize = PcMemFinalizeMemoryMap(XboxMemoryMap);
115 return XboxMemoryMap;
116 }
117
118 PVOID
119 XboxMemReserveMemory(ULONG MbToReserve)
120 {
121 /* This function is used to reserve video framebuffer in XboxVideoInit() */
122
123 if (InstalledMemoryMb == 0)
124 {
125 /* Hmm, seems we're not initialized yet */
126 XboxMemInit();
127 }
128
129 if (MbToReserve > AvailableMemoryMb)
130 {
131 /* Can't satisfy the request */
132 return NULL;
133 }
134
135 AvailableMemoryMb -= MbToReserve;
136
137 /* Top of available memory points to the space just reserved */
138 return (PVOID)(AvailableMemoryMb * 1024 * 1024);
139 }
140
141 /* EOF */