[VIDEOPRT] [FORMATTING] No code change
[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 #include <ndk/kefuncs.h>
25
26 #define NDEBUG
27 #include <debug.h>
28
29 /* PRIVATE FUNCTIONS **********************************************************/
30
31 #if defined(_M_IX86) || defined(_M_AMD64)
32 NTSTATUS
33 NTAPI
34 IntInitializeVideoAddressSpace(VOID)
35 {
36 OBJECT_ATTRIBUTES ObjectAttributes;
37 UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
38 NTSTATUS Status;
39 HANDLE PhysMemHandle;
40 PVOID BaseAddress;
41 LARGE_INTEGER Offset;
42 SIZE_T ViewSize;
43 #ifdef _M_IX86
44 CHAR IVTAndBda[1024 + 256];
45 #endif // _M_IX86
46
47 /* Free the 1MB pre-reserved region. In reality, ReactOS should simply support us mapping the view into the reserved area, but it doesn't. */
48 BaseAddress = 0;
49 ViewSize = 1024 * 1024;
50 Status = ZwFreeVirtualMemory(NtCurrentProcess(),
51 &BaseAddress,
52 &ViewSize,
53 MEM_RELEASE);
54 if (!NT_SUCCESS(Status))
55 {
56 DPRINT1("Couldn't unmap reserved memory (%x)\n", Status);
57 return 0;
58 }
59
60 /* Open the physical memory section */
61 InitializeObjectAttributes(&ObjectAttributes,
62 &PhysMemName,
63 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
64 NULL,
65 NULL);
66 Status = ZwOpenSection(&PhysMemHandle,
67 SECTION_ALL_ACCESS,
68 &ObjectAttributes);
69 if (!NT_SUCCESS(Status))
70 {
71 DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
72 return Status;
73 }
74
75 /* Map the BIOS and device registers into the address space */
76 Offset.QuadPart = 0xa0000;
77 ViewSize = 0x100000 - 0xa0000;
78 BaseAddress = (PVOID)0xa0000;
79 Status = ZwMapViewOfSection(PhysMemHandle,
80 NtCurrentProcess(),
81 &BaseAddress,
82 0,
83 ViewSize,
84 &Offset,
85 &ViewSize,
86 ViewUnmap,
87 0,
88 PAGE_EXECUTE_READWRITE);
89 if (!NT_SUCCESS(Status))
90 {
91 DPRINT1("Couldn't map physical memory (%x)\n", Status);
92 ZwClose(PhysMemHandle);
93 return Status;
94 }
95
96 /* Close physical memory section handle */
97 ZwClose(PhysMemHandle);
98
99 if (BaseAddress != (PVOID)0xa0000)
100 {
101 DPRINT1("Couldn't map physical memory at the right address (was %x)\n",
102 BaseAddress);
103 return STATUS_UNSUCCESSFUL;
104 }
105
106 /* Allocate some low memory to use for the non-BIOS
107 * parts of the v86 mode address space
108 */
109 BaseAddress = (PVOID)0x1;
110 ViewSize = 0xa0000 - 0x1000;
111 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
112 &BaseAddress,
113 0,
114 &ViewSize,
115 MEM_RESERVE | MEM_COMMIT,
116 PAGE_EXECUTE_READWRITE);
117 if (!NT_SUCCESS(Status))
118 {
119 DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status);
120 return Status;
121 }
122 if (BaseAddress != (PVOID)0x0)
123 {
124 DPRINT1("Failed to allocate virtual memory at right address (was %x)\n",
125 BaseAddress);
126 return 0;
127 }
128
129 #ifdef _M_IX86
130 /* Get the real mode IVT and BDA from the kernel */
131 Status = NtVdmControl(VdmInitialize, IVTAndBda);
132 if (!NT_SUCCESS(Status))
133 {
134 DPRINT1("NtVdmControl failed (status %x)\n", Status);
135 return Status;
136 }
137 #endif // _M_IX86
138
139 /* Return success */
140 return STATUS_SUCCESS;
141 }
142 #else
143 NTSTATUS
144 NTAPI
145 IntInitializeVideoAddressSpace(VOID)
146 {
147 UNIMPLEMENTED;
148 NT_ASSERT(FALSE);
149 return STATUS_NOT_IMPLEMENTED;
150 }
151 #endif
152
153 #if defined(_M_IX86)
154 VP_STATUS
155 NTAPI
156 IntInt10AllocateBuffer(
157 IN PVOID Context,
158 OUT PUSHORT Seg,
159 OUT PUSHORT Off,
160 IN OUT PULONG Length)
161 {
162 PVOID MemoryAddress;
163 NTSTATUS Status;
164 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
165 KAPC_STATE ApcState;
166
167 TRACE_(VIDEOPRT, "IntInt10AllocateBuffer\n");
168
169 IntAttachToCSRSS(&CallingProcess, &ApcState);
170
171 MemoryAddress = (PVOID)0x20000;
172 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
173 &MemoryAddress,
174 0,
175 Length,
176 MEM_COMMIT,
177 PAGE_EXECUTE_READWRITE);
178 if (!NT_SUCCESS(Status))
179 {
180 WARN_(VIDEOPRT, "- ZwAllocateVirtualMemory failed\n");
181 IntDetachFromCSRSS(&CallingProcess, &ApcState);
182 return ERROR_NOT_ENOUGH_MEMORY;
183 }
184
185 if (MemoryAddress > (PVOID)(0x100000 - *Length))
186 {
187 ZwFreeVirtualMemory(NtCurrentProcess(), &MemoryAddress, Length,
188 MEM_RELEASE);
189 WARN_(VIDEOPRT, "- Unacceptable memory allocated\n");
190 IntDetachFromCSRSS(&CallingProcess, &ApcState);
191 return ERROR_NOT_ENOUGH_MEMORY;
192 }
193
194 *Seg = (USHORT)((ULONG)MemoryAddress >> 4);
195 *Off = (USHORT)((ULONG)MemoryAddress & 0xF);
196
197 INFO_(VIDEOPRT, "- Segment: %x\n", (ULONG)MemoryAddress >> 4);
198 INFO_(VIDEOPRT, "- Offset: %x\n", (ULONG)MemoryAddress & 0xF);
199 INFO_(VIDEOPRT, "- Length: %x\n", *Length);
200
201 IntDetachFromCSRSS(&CallingProcess, &ApcState);
202
203 return NO_ERROR;
204 }
205
206 VP_STATUS
207 NTAPI
208 IntInt10FreeBuffer(
209 IN PVOID Context,
210 IN USHORT Seg,
211 IN USHORT Off)
212 {
213 PVOID MemoryAddress = (PVOID)((Seg << 4) | Off);
214 NTSTATUS Status;
215 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
216 KAPC_STATE ApcState;
217 SIZE_T Size = 0;
218
219 TRACE_(VIDEOPRT, "IntInt10FreeBuffer\n");
220 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
221 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
222
223 IntAttachToCSRSS(&CallingProcess, &ApcState);
224 Status = ZwFreeVirtualMemory(NtCurrentProcess(),
225 &MemoryAddress,
226 &Size,
227 MEM_RELEASE);
228
229 IntDetachFromCSRSS(&CallingProcess, &ApcState);
230
231 return Status;
232 }
233
234 VP_STATUS
235 NTAPI
236 IntInt10ReadMemory(
237 IN PVOID Context,
238 IN USHORT Seg,
239 IN USHORT Off,
240 OUT PVOID Buffer,
241 IN ULONG Length)
242 {
243 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
244 KAPC_STATE ApcState;
245
246 TRACE_(VIDEOPRT, "IntInt10ReadMemory\n");
247 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
248 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
249 INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
250 INFO_(VIDEOPRT, "- Length: %x\n", Length);
251
252 IntAttachToCSRSS(&CallingProcess, &ApcState);
253 RtlCopyMemory(Buffer, (PVOID)((Seg << 4) | Off), Length);
254 IntDetachFromCSRSS(&CallingProcess, &ApcState);
255
256 return NO_ERROR;
257 }
258
259 VP_STATUS
260 NTAPI
261 IntInt10WriteMemory(
262 IN PVOID Context,
263 IN USHORT Seg,
264 IN USHORT Off,
265 IN PVOID Buffer,
266 IN ULONG Length)
267 {
268 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
269 KAPC_STATE ApcState;
270
271 TRACE_(VIDEOPRT, "IntInt10WriteMemory\n");
272 INFO_(VIDEOPRT, "- Segment: %x\n", Seg);
273 INFO_(VIDEOPRT, "- Offset: %x\n", Off);
274 INFO_(VIDEOPRT, "- Buffer: %x\n", Buffer);
275 INFO_(VIDEOPRT, "- Length: %x\n", Length);
276
277 IntAttachToCSRSS(&CallingProcess, &ApcState);
278 RtlCopyMemory((PVOID)((Seg << 4) | Off), Buffer, Length);
279 IntDetachFromCSRSS(&CallingProcess, &ApcState);
280
281 return NO_ERROR;
282 }
283
284 VP_STATUS
285 NTAPI
286 IntInt10CallBios(
287 IN PVOID Context,
288 IN OUT PINT10_BIOS_ARGUMENTS BiosArguments)
289 {
290 CONTEXT BiosContext;
291 NTSTATUS Status;
292 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
293 KAPC_STATE ApcState;
294
295 /* Attach to CSRSS */
296 IntAttachToCSRSS(&CallingProcess, &ApcState);
297
298 /* Clear the context */
299 RtlZeroMemory(&BiosContext, sizeof(BiosContext));
300
301 /* Fill out the bios arguments */
302 BiosContext.Eax = BiosArguments->Eax;
303 BiosContext.Ebx = BiosArguments->Ebx;
304 BiosContext.Ecx = BiosArguments->Ecx;
305 BiosContext.Edx = BiosArguments->Edx;
306 BiosContext.Esi = BiosArguments->Esi;
307 BiosContext.Edi = BiosArguments->Edi;
308 BiosContext.Ebp = BiosArguments->Ebp;
309 BiosContext.SegDs = BiosArguments->SegDs;
310 BiosContext.SegEs = BiosArguments->SegEs;
311
312 /* Do the ROM BIOS call */
313 (void)KeWaitForMutexObject(&VideoPortInt10Mutex,
314 Executive,
315 KernelMode,
316 FALSE,
317 NULL);
318
319 Status = Ke386CallBios(0x10, &BiosContext);
320
321 KeReleaseMutex(&VideoPortInt10Mutex, FALSE);
322
323 /* Return the arguments */
324 BiosArguments->Eax = BiosContext.Eax;
325 BiosArguments->Ebx = BiosContext.Ebx;
326 BiosArguments->Ecx = BiosContext.Ecx;
327 BiosArguments->Edx = BiosContext.Edx;
328 BiosArguments->Esi = BiosContext.Esi;
329 BiosArguments->Edi = BiosContext.Edi;
330 BiosArguments->Ebp = BiosContext.Ebp;
331 BiosArguments->SegDs = (USHORT)BiosContext.SegDs;
332 BiosArguments->SegEs = (USHORT)BiosContext.SegEs;
333
334 /* Detach and return status */
335 IntDetachFromCSRSS(&CallingProcess, &ApcState);
336
337 if (NT_SUCCESS(Status))
338 {
339 return NO_ERROR;
340 }
341
342 return ERROR_INVALID_PARAMETER;
343 }
344 #endif
345
346 /* PUBLIC FUNCTIONS ***********************************************************/
347
348 /*
349 * @implemented
350 */
351
352 VP_STATUS
353 NTAPI
354 VideoPortInt10(
355 IN PVOID HwDeviceExtension,
356 IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments)
357 {
358 #if defined(_M_IX86)
359 CONTEXT BiosContext;
360 NTSTATUS Status;
361 PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess();
362 KAPC_STATE ApcState;
363
364 if (!CsrssInitialized)
365 {
366 return ERROR_INVALID_PARAMETER;
367 }
368
369 /* Attach to CSRSS */
370 IntAttachToCSRSS(&CallingProcess, &ApcState);
371
372 /* Clear the context */
373 RtlZeroMemory(&BiosContext, sizeof(CONTEXT));
374
375 /* Fill out the bios arguments */
376 BiosContext.Eax = BiosArguments->Eax;
377 BiosContext.Ebx = BiosArguments->Ebx;
378 BiosContext.Ecx = BiosArguments->Ecx;
379 BiosContext.Edx = BiosArguments->Edx;
380 BiosContext.Esi = BiosArguments->Esi;
381 BiosContext.Edi = BiosArguments->Edi;
382 BiosContext.Ebp = BiosArguments->Ebp;
383
384 /* Do the ROM BIOS call */
385 (void)KeWaitForMutexObject(&VideoPortInt10Mutex,
386 Executive,
387 KernelMode,
388 FALSE,
389 NULL);
390 Status = Ke386CallBios(0x10, &BiosContext);
391 KeReleaseMutex(&VideoPortInt10Mutex, FALSE);
392
393 /* Return the arguments */
394 BiosArguments->Eax = BiosContext.Eax;
395 BiosArguments->Ebx = BiosContext.Ebx;
396 BiosArguments->Ecx = BiosContext.Ecx;
397 BiosArguments->Edx = BiosContext.Edx;
398 BiosArguments->Esi = BiosContext.Esi;
399 BiosArguments->Edi = BiosContext.Edi;
400 BiosArguments->Ebp = BiosContext.Ebp;
401
402 /* Detach from CSRSS */
403 IntDetachFromCSRSS(&CallingProcess, &ApcState);
404
405 if (NT_SUCCESS(Status))
406 {
407 return NO_ERROR;
408 }
409
410 return ERROR_INVALID_PARAMETER;
411 #else
412 /* Not implemented for anything else than X86*/
413 DPRINT1("Int10 not available on non-x86!\n");
414 return ERROR_INVALID_FUNCTION;
415 #endif
416 }