Sync with trunk rev.61910 to get latest improvements and bugfixes.
[reactos.git] / win32ss / drivers / videoprt / int10.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "videoprt.h"
23
24 /* PRIVATE FUNCTIONS **********************************************************/
25
26 #if defined(_M_IX86) || defined(_M_AMD64)
27 NTSTATUS
28 NTAPI
29 IntInitializeVideoAddressSpace(VOID)
30 {
31 OBJECT_ATTRIBUTES ObjectAttributes;
32 UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
33 NTSTATUS Status;
34 HANDLE PhysMemHandle;
35 PVOID BaseAddress;
36 LARGE_INTEGER Offset;
37 SIZE_T ViewSize;
38 CHAR IVTAndBda[1024+256];
39
40 /* Free the 1MB pre-reserved region. In reality, ReactOS should simply support us mapping the view into the reserved area, but it doesn't. */
41 BaseAddress = 0;
42 ViewSize = 1024 * 1024;
43 Status = ZwFreeVirtualMemory(NtCurrentProcess(),
44 &BaseAddress,
45 &ViewSize,
46 MEM_RELEASE);
47 if (!NT_SUCCESS(Status))
48 {
49 DPRINT1("Couldn't unmap reserved memory (%x)\n", Status);
50 return 0;
51 }
52
53 /* Open the physical memory section */
54 InitializeObjectAttributes(&ObjectAttributes,
55 &PhysMemName,
56 0,
57 NULL,
58 NULL);
59 Status = ZwOpenSection(&PhysMemHandle,
60 SECTION_ALL_ACCESS,
61 &ObjectAttributes);
62 if (!NT_SUCCESS(Status))
63 {
64 DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
65 return Status;
66 }
67
68 /* Map the BIOS and device registers into the address space */
69 Offset.QuadPart = 0xa0000;
70 ViewSize = 0x100000 - 0xa0000;
71 BaseAddress = (PVOID)0xa0000;
72 Status = ZwMapViewOfSection(PhysMemHandle,
73 NtCurrentProcess(),
74 &BaseAddress,
75 0,
76 ViewSize,
77 &Offset,
78 &ViewSize,
79 ViewUnmap,
80 0,
81 PAGE_EXECUTE_READWRITE);
82 if (!NT_SUCCESS(Status))
83 {
84 DPRINT1("Couldn't map physical memory (%x)\n", Status);
85 ZwClose(PhysMemHandle);
86 return Status;
87 }
88
89 /* Close physical memory section handle */
90 ZwClose(PhysMemHandle);
91
92 if (BaseAddress != (PVOID)0xa0000)
93 {
94 DPRINT1("Couldn't map physical memory at the right address (was %x)\n",
95 BaseAddress);
96 return STATUS_UNSUCCESSFUL;
97 }
98
99 /* Allocate some low memory to use for the non-BIOS
100 * parts of the v86 mode address space
101 */
102 BaseAddress = (PVOID)0x1;
103 ViewSize = 0xa0000 - 0x1000;
104 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
105 &BaseAddress,
106 0,
107 &ViewSize,
108 MEM_RESERVE | MEM_COMMIT,
109 PAGE_EXECUTE_READWRITE);
110 if (!NT_SUCCESS(Status))
111 {
112 DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status);
113 return Status;
114 }
115 if (BaseAddress != (PVOID)0x0)
116 {
117 DPRINT1("Failed to allocate virtual memory at right address (was %x)\n",
118 BaseAddress);
119 return 0;
120 }
121
122 /* Get the real mode IVT and BDA from the kernel */
123 Status = NtVdmControl(VdmInitialize, IVTAndBda);
124 if (!NT_SUCCESS(Status))
125 {
126 DPRINT1("NtVdmControl failed (status %x)\n", Status);
127 return Status;
128 }
129
130 /* Return success */
131 return STATUS_SUCCESS;
132 }
133 #endif
134
135 #if defined(_M_IX86)
136 VP_STATUS NTAPI
137 IntInt10AllocateBuffer(
138 IN PVOID Context,
139 OUT PUSHORT Seg,
140 OUT PUSHORT Off,
141 IN OUT PULONG Length)
142 {
143 PVOID MemoryAddress;
144 NTSTATUS Status;
145 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
146 KAPC_STATE ApcState;
147
148 TRACE_(VIDEOPRT, "IntInt10AllocateBuffer\n");
149
150 IntAttachToCSRSS(&CallingProcess, &ApcState);
151
152 MemoryAddress = (PVOID)0x20000;
153 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &MemoryAddress, 0,
154 Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
155
156 if (!NT_SUCCESS(Status))
157 {
158 WARN_(VIDEOPRT, "- ZwAllocateVirtualMemory failed\n");
159 IntDetachFromCSRSS(&CallingProcess, &ApcState);
160 return ERROR_NOT_ENOUGH_MEMORY;
161 }
162
163 if (MemoryAddress > (PVOID)(0x100000 - *Length))
164 {
165 ZwFreeVirtualMemory(NtCurrentProcess(), &MemoryAddress, Length,
166 MEM_RELEASE);
167 WARN_(VIDEOPRT, "- Unacceptable memory allocated\n");
168 IntDetachFromCSRSS(&CallingProcess, &ApcState);
169 return ERROR_NOT_ENOUGH_MEMORY;
170 }
171
172 *Seg = (USHORT)((ULONG)MemoryAddress >> 4);
173 *Off = (USHORT)((ULONG)MemoryAddress & 0xF);
174
175 INFO_(VIDEOPRT, "- Segment: %x\n", (ULONG)MemoryAddress >> 4);
176 INFO_(VIDEOPRT, "- Offset: %x\n", (ULONG)MemoryAddress & 0xF);
177 INFO_(VIDEOPRT, "- Length: %x\n", *Length);
178
179 IntDetachFromCSRSS(&CallingProcess, &ApcState);
180
181 return NO_ERROR;
182 }
183
184 VP_STATUS NTAPI
185 IntInt10FreeBuffer(
186 IN PVOID Context,
187 IN USHORT Seg,
188 IN USHORT Off)
189 {
190 PVOID MemoryAddress = (PVOID)((Seg << 4) | Off);
191 NTSTATUS Status;
192 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
193 KAPC_STATE ApcState;
194 SIZE_T Size = 0;
195
196 TRACE_(VIDEOPRT, "IntInt10FreeBuffer\n");
197 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
198 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
199
200 IntAttachToCSRSS(&CallingProcess, &ApcState);
201 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &MemoryAddress, &Size,
202 MEM_RELEASE);
203 IntDetachFromCSRSS(&CallingProcess, &ApcState);
204
205 return Status;
206 }
207
208 VP_STATUS NTAPI
209 IntInt10ReadMemory(
210 IN PVOID Context,
211 IN USHORT Seg,
212 IN USHORT Off,
213 OUT PVOID Buffer,
214 IN ULONG Length)
215 {
216 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
217 KAPC_STATE ApcState;
218
219 TRACE_(VIDEOPRT, "IntInt10ReadMemory\n");
220 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
221 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
222 INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
223 INFO_(VIDEOPRT, "- Length: %x\n", Length);
224
225 IntAttachToCSRSS(&CallingProcess, &ApcState);
226 RtlCopyMemory(Buffer, (PVOID)((Seg << 4) | Off), Length);
227 IntDetachFromCSRSS(&CallingProcess, &ApcState);
228
229 return NO_ERROR;
230 }
231
232 VP_STATUS NTAPI
233 IntInt10WriteMemory(
234 IN PVOID Context,
235 IN USHORT Seg,
236 IN USHORT Off,
237 IN PVOID Buffer,
238 IN ULONG Length)
239 {
240 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
241 KAPC_STATE ApcState;
242
243 TRACE_(VIDEOPRT, "IntInt10WriteMemory\n");
244 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
245 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
246 INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
247 INFO_(VIDEOPRT, "- Length: %x\n", Length);
248
249 IntAttachToCSRSS(&CallingProcess, &ApcState);
250 RtlCopyMemory((PVOID)((Seg << 4) | Off), Buffer, Length);
251 IntDetachFromCSRSS(&CallingProcess, &ApcState);
252
253 return NO_ERROR;
254 }
255
256 VP_STATUS
257 NTAPI
258 IntInt10CallBios(
259 IN PVOID Context,
260 IN OUT PINT10_BIOS_ARGUMENTS BiosArguments)
261 {
262 CONTEXT BiosContext;
263 NTSTATUS Status;
264 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
265 KAPC_STATE ApcState;
266
267 /* Attach to CSRSS */
268 IntAttachToCSRSS(&CallingProcess, &ApcState);
269
270 /* Clear the context */
271 RtlZeroMemory(&BiosContext, sizeof(CONTEXT));
272
273 /* Fill out the bios arguments */
274 BiosContext.Eax = BiosArguments->Eax;
275 BiosContext.Ebx = BiosArguments->Ebx;
276 BiosContext.Ecx = BiosArguments->Ecx;
277 BiosContext.Edx = BiosArguments->Edx;
278 BiosContext.Esi = BiosArguments->Esi;
279 BiosContext.Edi = BiosArguments->Edi;
280 BiosContext.Ebp = BiosArguments->Ebp;
281 BiosContext.SegDs = BiosArguments->SegDs;
282 BiosContext.SegEs = BiosArguments->SegEs;
283
284 /* Do the ROM BIOS call */
285 Status = Ke386CallBios(0x10, &BiosContext);
286
287 /* Return the arguments */
288 BiosArguments->Eax = BiosContext.Eax;
289 BiosArguments->Ebx = BiosContext.Ebx;
290 BiosArguments->Ecx = BiosContext.Ecx;
291 BiosArguments->Edx = BiosContext.Edx;
292 BiosArguments->Esi = BiosContext.Esi;
293 BiosArguments->Edi = BiosContext.Edi;
294 BiosArguments->Ebp = BiosContext.Ebp;
295 BiosArguments->SegDs = (USHORT)BiosContext.SegDs;
296 BiosArguments->SegEs = (USHORT)BiosContext.SegEs;
297
298 /* Detach and return status */
299 IntDetachFromCSRSS(&CallingProcess, &ApcState);
300 if (NT_SUCCESS(Status)) return NO_ERROR;
301 return ERROR_INVALID_PARAMETER;
302 }
303 #endif
304
305 /* PUBLIC FUNCTIONS ***********************************************************/
306
307 /*
308 * @implemented
309 */
310
311 VP_STATUS NTAPI
312 VideoPortInt10(
313 IN PVOID HwDeviceExtension,
314 IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
315 {
316 #if defined(_M_IX86)
317 CONTEXT BiosContext;
318 NTSTATUS Status;
319 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
320 KAPC_STATE ApcState;
321
322 if (!CsrssInitialized)
323 {
324 return ERROR_INVALID_PARAMETER;
325 }
326
327 /* Attach to CSRSS */
328 IntAttachToCSRSS(&CallingProcess, &ApcState);
329
330 /* Clear the context */
331 RtlZeroMemory(&BiosContext, sizeof(CONTEXT));
332
333 /* Fill out the bios arguments */
334 BiosContext.Eax = BiosArguments->Eax;
335 BiosContext.Ebx = BiosArguments->Ebx;
336 BiosContext.Ecx = BiosArguments->Ecx;
337 BiosContext.Edx = BiosArguments->Edx;
338 BiosContext.Esi = BiosArguments->Esi;
339 BiosContext.Edi = BiosArguments->Edi;
340 BiosContext.Ebp = BiosArguments->Ebp;
341
342 /* Do the ROM BIOS call */
343 Status = Ke386CallBios(0x10, &BiosContext);
344
345 /* Return the arguments */
346 BiosArguments->Eax = BiosContext.Eax;
347 BiosArguments->Ebx = BiosContext.Ebx;
348 BiosArguments->Ecx = BiosContext.Ecx;
349 BiosArguments->Edx = BiosContext.Edx;
350 BiosArguments->Esi = BiosContext.Esi;
351 BiosArguments->Edi = BiosContext.Edi;
352 BiosArguments->Ebp = BiosContext.Ebp;
353
354 /* Detach from CSRSS */
355 IntDetachFromCSRSS(&CallingProcess, &ApcState);
356 if (NT_SUCCESS(Status)) return NO_ERROR;
357 return ERROR_INVALID_PARAMETER;
358 #else
359 /* Not implemented for anything else than X86*/
360 DPRINT1("Int10 not available on non-x86!\n");
361 return ERROR_INVALID_FUNCTION;
362 #endif
363 }