Replace assert_irql by ASSERT_IRQL.
[reactos.git] / reactos / drivers / video / videoprt / videoprt.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 Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; see the file COPYING.LIB.
18 * If not, write to the Free Software Foundation,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * $Id: videoprt.c,v 1.28 2004/11/24 11:12:19 ekohl Exp $
22 */
23
24 #include "videoprt.h"
25 #include "internal/ps.h"
26
27 /* GLOBAL VARIABLES ***********************************************************/
28
29 ULONG CsrssInitialized = FALSE;
30 PEPROCESS Csrss = NULL;
31
32 /* PRIVATE FUNCTIONS **********************************************************/
33
34 NTSTATUS STDCALL
35 DriverEntry(
36 IN PDRIVER_OBJECT DriverObject,
37 IN PUNICODE_STRING RegistryPath)
38 {
39 return STATUS_SUCCESS;
40 }
41
42 PVOID STDCALL
43 IntVideoPortImageDirectoryEntryToData(
44 PVOID BaseAddress,
45 ULONG Directory)
46 {
47 PIMAGE_NT_HEADERS NtHeader;
48 ULONG Va;
49
50 NtHeader = RtlImageNtHeader(BaseAddress);
51 if (NtHeader == NULL)
52 return NULL;
53
54 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
55 return NULL;
56
57 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
58 if (Va == 0)
59 return NULL;
60
61 return (PVOID)(BaseAddress + Va);
62 }
63
64 PVOID STDCALL
65 IntVideoPortGetProcAddress(
66 IN PVOID HwDeviceExtension,
67 IN PUCHAR FunctionName)
68 {
69 SYSTEM_LOAD_IMAGE GdiDriverInfo;
70 PVOID BaseAddress;
71 PIMAGE_EXPORT_DIRECTORY ExportDir;
72 PUSHORT OrdinalPtr;
73 PULONG NamePtr;
74 PULONG AddressPtr;
75 ULONG i = 0;
76 NTSTATUS Status;
77
78 DPRINT("VideoPortGetProcAddress(%s)\n", FunctionName);
79
80 RtlInitUnicodeString(&GdiDriverInfo.ModuleName, L"videoprt");
81 Status = ZwSetSystemInformation(
82 SystemLoadImage,
83 &GdiDriverInfo,
84 sizeof(SYSTEM_LOAD_IMAGE));
85 if (!NT_SUCCESS(Status))
86 {
87 DPRINT("Couldn't get our own module handle?\n");
88 return NULL;
89 }
90
91 BaseAddress = GdiDriverInfo.ModuleBase;
92
93 /* Get the pointer to the export directory */
94 ExportDir = (PIMAGE_EXPORT_DIRECTORY)IntVideoPortImageDirectoryEntryToData(
95 BaseAddress,
96 IMAGE_DIRECTORY_ENTRY_EXPORT);
97
98 /* Search by name */
99 AddressPtr = (PULONG)
100 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
101 OrdinalPtr = (PUSHORT)
102 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
103 NamePtr = (PULONG)
104 ((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
105 for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
106 {
107 if (!_strnicmp(FunctionName, (char*)(BaseAddress + *NamePtr),
108 strlen(FunctionName)))
109 {
110 return (PVOID)((ULONG_PTR)BaseAddress +
111 (ULONG_PTR)AddressPtr[*OrdinalPtr]);
112 }
113 }
114
115 DPRINT("VideoPortGetProcAddress: Can't resolve symbol %s\n", FunctionName);
116
117 return NULL;
118 }
119
120 VOID STDCALL
121 IntVideoPortDeferredRoutine(
122 IN PKDPC Dpc,
123 IN PVOID DeferredContext,
124 IN PVOID SystemArgument1,
125 IN PVOID SystemArgument2)
126 {
127 PVOID HwDeviceExtension =
128 &((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
129 ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
130 }
131
132 ULONG STDCALL
133 IntVideoPortAllocateDeviceNumber(VOID)
134 {
135 NTSTATUS Status;
136 ULONG DeviceNumber;
137 WCHAR SymlinkBuffer[20];
138 UNICODE_STRING SymlinkName;
139
140 for (DeviceNumber = 0;;)
141 {
142 OBJECT_ATTRIBUTES Obj;
143 HANDLE ObjHandle;
144
145 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
146 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
147 InitializeObjectAttributes(&Obj, &SymlinkName, 0, NULL, NULL);
148 Status = ZwOpenSymbolicLinkObject(&ObjHandle, GENERIC_READ, &Obj);
149 if (NT_SUCCESS(Status))
150 {
151 ZwClose(ObjHandle);
152 DeviceNumber++;
153 continue;
154 }
155 else if (Status == STATUS_NOT_FOUND || Status == STATUS_UNSUCCESSFUL)
156 break;
157 else
158 return 0xFFFFFFFF;
159 }
160
161 return DeviceNumber;
162 }
163
164 NTSTATUS STDCALL
165 IntVideoPortFindAdapter(
166 IN PDRIVER_OBJECT DriverObject,
167 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
168 IN PDEVICE_OBJECT PhysicalDeviceObject)
169 {
170 WCHAR DeviceVideoBuffer[20];
171 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
172 ULONG DeviceNumber;
173 ULONG Size;
174 NTSTATUS Status;
175 VIDEO_PORT_CONFIG_INFO ConfigInfo;
176 SYSTEM_BASIC_INFORMATION SystemBasicInfo;
177 UCHAR Again = FALSE;
178 WCHAR DeviceBuffer[20];
179 UNICODE_STRING DeviceName;
180 WCHAR SymlinkBuffer[20];
181 UNICODE_STRING SymlinkName;
182 PDEVICE_OBJECT DeviceObject;
183 BOOL LegacyDetection = FALSE;
184
185 /*
186 * Find the first free device number that can be used for video device
187 * object names and symlinks.
188 */
189
190 DeviceNumber = IntVideoPortAllocateDeviceNumber();
191 if (DeviceNumber == 0xFFFFFFFF)
192 {
193 DPRINT("Can't find free device number\n");
194 return STATUS_UNSUCCESSFUL;
195 }
196
197 /*
198 * Create the device object, we need it even for calling HwFindAdapter :(
199 */
200
201 /* Create a unicode device name. */
202 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
203 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
204
205 /* Create the device object. */
206 Status = IoCreateDevice(
207 DriverObject,
208 sizeof(VIDEO_PORT_DEVICE_EXTENSION) +
209 DriverExtension->InitializationData.HwDeviceExtensionSize,
210 &DeviceName,
211 FILE_DEVICE_VIDEO,
212 0,
213 TRUE,
214 &DeviceObject);
215
216 if (!NT_SUCCESS(Status))
217 {
218 DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
219 return Status;
220 }
221
222 /*
223 * Set the buffering strategy here. If you change this, remember
224 * to change VidDispatchDeviceControl too.
225 */
226
227 DeviceObject->Flags |= DO_BUFFERED_IO;
228
229 /*
230 * Initialize device extension.
231 */
232
233 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
234 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
235 DeviceExtension->FunctionalDeviceObject = DeviceObject;
236 DeviceExtension->DriverExtension = DriverExtension;
237
238 DeviceExtension->RegistryPath.Length =
239 DeviceExtension->RegistryPath.MaximumLength =
240 DriverExtension->RegistryPath.Length + (9 * sizeof(WCHAR));
241 DeviceExtension->RegistryPath.Length -= sizeof(WCHAR);
242 DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(
243 NonPagedPool,
244 DeviceExtension->RegistryPath.MaximumLength,
245 TAG_VIDEO_PORT);
246 swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
247 DriverExtension->RegistryPath.Buffer);
248
249 if (PhysicalDeviceObject == NULL)
250 {
251 LegacyDetection = TRUE;
252 }
253 else
254 {
255 /* Get bus number from the upper level bus driver. */
256 Size = sizeof(ULONG);
257 Status = IoGetDeviceProperty(
258 PhysicalDeviceObject,
259 DevicePropertyBusNumber,
260 Size,
261 &DeviceExtension->SystemIoBusNumber,
262 &Size);
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT("Couldn't get an information from bus driver. We will try to\n"
266 "use legacy detection method, but even that doesn't mean that\n"
267 "it will work.\n");
268 DeviceExtension->PhysicalDeviceObject = NULL;
269 LegacyDetection = TRUE;
270 }
271 }
272
273 DeviceExtension->AdapterInterfaceType =
274 DriverExtension->InitializationData.AdapterInterfaceType;
275
276 if (PhysicalDeviceObject != NULL)
277 {
278 /* Get bus type from the upper level bus driver. */
279 Size = sizeof(ULONG);
280 IoGetDeviceProperty(
281 PhysicalDeviceObject,
282 DevicePropertyLegacyBusType,
283 Size,
284 &DeviceExtension->AdapterInterfaceType,
285 &Size);
286
287 /* Get bus device address from the upper level bus driver. */
288 Size = sizeof(ULONG);
289 IoGetDeviceProperty(
290 PhysicalDeviceObject,
291 DevicePropertyAddress,
292 Size,
293 &DeviceExtension->SystemIoSlotNumber,
294 &Size);
295 }
296
297 InitializeListHead(&DeviceExtension->AddressMappingListHead);
298 KeInitializeDpc(
299 &DeviceExtension->DpcObject,
300 IntVideoPortDeferredRoutine,
301 DeviceExtension);
302
303 /*
304 * Uff, the DeviceExtension is setup. Now it's needed to setup
305 * a ConfigInfo structure that we will pass to HwFindAdapter.
306 */
307
308 RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
309 ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
310 ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
311 if (ConfigInfo.AdapterInterfaceType == PCIBus)
312 ConfigInfo.InterruptMode = LevelSensitive;
313 else
314 ConfigInfo.InterruptMode = Latched;
315 ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer;
316 ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress;
317 ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
318
319 Size = sizeof(SystemBasicInfo);
320 Status = ZwQuerySystemInformation(
321 SystemBasicInformation,
322 &SystemBasicInfo,
323 Size,
324 &Size);
325
326 if (NT_SUCCESS(Status))
327 {
328 ConfigInfo.SystemMemorySize =
329 SystemBasicInfo.NumberOfPhysicalPages *
330 SystemBasicInfo.PhysicalPageSize;
331 }
332
333 /*
334 * Call miniport HwVidFindAdapter entry point to detect if
335 * particular device is present. There are two possible code
336 * paths. The first one is for Legacy drivers (NT4) and cases
337 * when we don't have information about what bus we're on. The
338 * second case is the standard one for Plug & Play drivers.
339 */
340
341 if (LegacyDetection)
342 {
343 ULONG BusNumber, MaxBuses;
344
345 MaxBuses = DeviceExtension->AdapterInterfaceType == PCIBus ? 8 : 1;
346
347 for (BusNumber = 0; BusNumber < MaxBuses; BusNumber++)
348 {
349 DeviceExtension->SystemIoBusNumber =
350 ConfigInfo.SystemIoBusNumber = BusNumber;
351
352 RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
353 DriverExtension->InitializationData.HwDeviceExtensionSize);
354
355 /* FIXME: Need to figure out what string to pass as param 3. */
356 Status = DriverExtension->InitializationData.HwFindAdapter(
357 &DeviceExtension->MiniPortDeviceExtension,
358 DriverExtension->HwContext,
359 NULL,
360 &ConfigInfo,
361 &Again);
362
363 if (Status == ERROR_DEV_NOT_EXIST)
364 {
365 continue;
366 }
367 else if (Status == NO_ERROR)
368 {
369 break;
370 }
371 else
372 {
373 DPRINT("HwFindAdapter call failed with error %X\n", Status);
374 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
375 IoDeleteDevice(DeviceObject);
376
377 return Status;
378 }
379 }
380 }
381 else
382 {
383 /* FIXME: Need to figure out what string to pass as param 3. */
384 Status = DriverExtension->InitializationData.HwFindAdapter(
385 &DeviceExtension->MiniPortDeviceExtension,
386 DriverExtension->HwContext,
387 NULL,
388 &ConfigInfo,
389 &Again);
390 }
391
392 if (Status != NO_ERROR)
393 {
394 DPRINT("HwFindAdapter call failed with error %X\n", Status);
395 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
396 IoDeleteDevice(DeviceObject);
397 return Status;
398 }
399
400 /*
401 * Now we know the device is present, so let's do all additional tasks
402 * such as creating symlinks or setting up interrupts and timer.
403 */
404
405 /* Create symbolic link "\??\DISPLAYx" */
406 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
407 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
408 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
409
410 /* Add entry to DEVICEMAP\VIDEO key in registry. */
411 swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DeviceNumber);
412 RtlWriteRegistryValue(
413 RTL_REGISTRY_DEVICEMAP,
414 L"VIDEO",
415 DeviceVideoBuffer,
416 REG_SZ,
417 DeviceExtension->RegistryPath.Buffer,
418 DeviceExtension->RegistryPath.MaximumLength);
419
420 /* FIXME: Allocate hardware resources for device. */
421
422 /*
423 * Allocate interrupt for device.
424 */
425
426 if (!IntVideoPortSetupInterrupt(DeviceObject, DriverExtension, &ConfigInfo))
427 {
428 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
429 IoDeleteDevice(DeviceObject);
430 return STATUS_INSUFFICIENT_RESOURCES;
431 }
432
433 /*
434 * Allocate timer for device.
435 */
436
437 if (!IntVideoPortSetupTimer(DeviceObject, DriverExtension))
438 {
439 if (DeviceExtension->InterruptObject != NULL)
440 IoDisconnectInterrupt(DeviceExtension->InterruptObject);
441 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
442 IoDeleteDevice(DeviceObject);
443 DPRINT("STATUS_INSUFFICIENT_RESOURCES\n");
444 return STATUS_INSUFFICIENT_RESOURCES;
445 }
446
447 if (PhysicalDeviceObject != NULL)
448 IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
449
450 DPRINT("STATUS_SUCCESS\n");
451 return STATUS_SUCCESS;
452 }
453
454 VOID FASTCALL
455 IntAttachToCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess)
456 {
457 *CallingProcess = PsGetCurrentProcess();
458 if (*CallingProcess != Csrss)
459 {
460 if (PsGetCurrentThread()->ThreadsProcess != *CallingProcess)
461 {
462 *PrevAttachedProcess = *CallingProcess;
463 KeDetachProcess();
464 }
465 else
466 {
467 *PrevAttachedProcess = NULL;
468 }
469 KeAttachProcess(Csrss);
470 }
471 }
472
473 VOID FASTCALL
474 IntDetachFromCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess)
475 {
476 if (*CallingProcess != Csrss)
477 {
478 KeDetachProcess();
479 if (NULL != *PrevAttachedProcess)
480 {
481 KeAttachProcess(*PrevAttachedProcess);
482 }
483 }
484 }
485
486 /* PUBLIC FUNCTIONS ***********************************************************/
487
488 /*
489 * @implemented
490 */
491
492 ULONG STDCALL
493 VideoPortInitialize(
494 IN PVOID Context1,
495 IN PVOID Context2,
496 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
497 IN PVOID HwContext)
498 {
499 PDRIVER_OBJECT DriverObject = Context1;
500 PUNICODE_STRING RegistryPath = Context2;
501 NTSTATUS Status;
502 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
503 BOOL LegacyDetection = FALSE;
504
505 DPRINT("VideoPortInitialize\n");
506
507 /*
508 * NOTE:
509 * The driver extension can be already allocated in case that we were
510 * called by legacy driver and failed detecting device. Some miniport
511 * drivers in that case adjust parameters and calls VideoPortInitialize
512 * again.
513 */
514
515 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
516 if (DriverExtension == NULL)
517 {
518 Status = IoAllocateDriverObjectExtension(
519 DriverObject,
520 DriverObject,
521 sizeof(VIDEO_PORT_DRIVER_EXTENSION),
522 (PVOID *)&DriverExtension);
523
524 if (!NT_SUCCESS(Status))
525 {
526 return Status;
527 }
528 }
529
530 /*
531 * Copy the correct miniport initializtation data to the device extension.
532 */
533
534 RtlCopyMemory(
535 &DriverExtension->InitializationData,
536 HwInitializationData,
537 min(sizeof(VIDEO_HW_INITIALIZATION_DATA),
538 HwInitializationData->HwInitDataSize));
539 DriverExtension->HwContext = HwContext;
540
541 RtlCopyMemory(&DriverExtension->RegistryPath, RegistryPath, sizeof(UNICODE_STRING));
542
543 switch (HwInitializationData->HwInitDataSize)
544 {
545 /*
546 * NT4 drivers are special case, because we must use legacy method
547 * of detection instead of the Plug & Play one.
548 */
549
550 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA:
551 DPRINT("We were loaded by a Windows NT miniport driver.\n");
552 LegacyDetection = TRUE;
553 break;
554
555 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA:
556 DPRINT("We were loaded by a Windows 2000 miniport driver.\n");
557 break;
558
559 case sizeof(VIDEO_HW_INITIALIZATION_DATA):
560 DPRINT("We were loaded by a Windows XP or later miniport driver.\n");
561 break;
562
563 default:
564 DPRINT("Invalid HwInitializationData size.\n");
565 return STATUS_UNSUCCESSFUL;
566 }
567
568 DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
569 DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
570 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IntVideoPortDispatchDeviceControl;
571 DriverObject->DriverUnload = IntVideoPortUnload;
572
573 /*
574 * Plug & Play drivers registers the device in AddDevice routine. For
575 * legacy drivers we must do it now.
576 */
577
578 if (LegacyDetection)
579 {
580 Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, NULL);
581 DPRINT("IntVideoPortFindAdapter returned 0x%x\n", Status);
582 return Status;
583 }
584 else
585 {
586 DriverObject->DriverExtension->AddDevice = IntVideoPortAddDevice;
587 DriverObject->MajorFunction[IRP_MJ_PNP] = IntVideoPortDispatchPnp;
588 DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
589
590 return STATUS_SUCCESS;
591 }
592 }
593
594 /*
595 * @implemented
596 */
597
598 VOID
599 VideoPortDebugPrint(
600 IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
601 IN PCHAR DebugMessage, ...)
602 {
603 char Buffer[256];
604 va_list ap;
605
606 va_start(ap, DebugMessage);
607 vsprintf(Buffer, DebugMessage, ap);
608 va_end(ap);
609
610 DbgPrint(Buffer);
611 }
612
613 /*
614 * @unimplemented
615 */
616
617 VOID STDCALL
618 VideoPortLogError(
619 IN PVOID HwDeviceExtension,
620 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
621 IN VP_STATUS ErrorCode,
622 IN ULONG UniqueId)
623 {
624 DPRINT1("VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
625 ErrorCode, ErrorCode, UniqueId, UniqueId);
626 if (NULL != Vrp)
627 {
628 DPRINT1("Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
629 }
630 }
631
632 /*
633 * @implemented
634 */
635
636 UCHAR STDCALL
637 VideoPortGetCurrentIrql(VOID)
638 {
639 return KeGetCurrentIrql();
640 }
641
642 typedef struct QueryRegistryCallbackContext
643 {
644 PVOID HwDeviceExtension;
645 PVOID HwContext;
646 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
647 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
648
649 static NTSTATUS STDCALL
650 QueryRegistryCallback(
651 IN PWSTR ValueName,
652 IN ULONG ValueType,
653 IN PVOID ValueData,
654 IN ULONG ValueLength,
655 IN PVOID Context,
656 IN PVOID EntryContext)
657 {
658 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
659
660 DPRINT("Found registry value for name %S: type %d, length %d\n",
661 ValueName, ValueType, ValueLength);
662 return (*(CallbackContext->HwGetRegistryRoutine))(
663 CallbackContext->HwDeviceExtension,
664 CallbackContext->HwContext,
665 ValueName,
666 ValueData,
667 ValueLength);
668 }
669
670 /*
671 * @unimplemented
672 */
673
674 VP_STATUS STDCALL
675 VideoPortGetRegistryParameters(
676 IN PVOID HwDeviceExtension,
677 IN PWSTR ParameterName,
678 IN UCHAR IsParameterFileName,
679 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
680 IN PVOID HwContext)
681 {
682 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
683 QUERY_REGISTRY_CALLBACK_CONTEXT Context;
684 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
685
686 DPRINT("VideoPortGetRegistryParameters ParameterName %S\n", ParameterName);
687
688 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
689
690 if (IsParameterFileName)
691 {
692 UNIMPLEMENTED;
693 }
694
695 Context.HwDeviceExtension = HwDeviceExtension;
696 Context.HwContext = HwContext;
697 Context.HwGetRegistryRoutine = GetRegistryRoutine;
698
699 QueryTable[0].QueryRoutine = QueryRegistryCallback;
700 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
701 QueryTable[0].Name = ParameterName;
702 QueryTable[0].EntryContext = NULL;
703 QueryTable[0].DefaultType = REG_NONE;
704 QueryTable[0].DefaultData = NULL;
705 QueryTable[0].DefaultLength = 0;
706
707 QueryTable[1].QueryRoutine = NULL;
708 QueryTable[1].Name = NULL;
709
710 return NT_SUCCESS(RtlQueryRegistryValues(
711 RTL_REGISTRY_ABSOLUTE,
712 DeviceExtension->RegistryPath.Buffer,
713 QueryTable,
714 &Context,
715 NULL)) ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
716 }
717
718 /*
719 * @implemented
720 */
721
722 VP_STATUS STDCALL
723 VideoPortSetRegistryParameters(
724 IN PVOID HwDeviceExtension,
725 IN PWSTR ValueName,
726 IN PVOID ValueData,
727 IN ULONG ValueLength)
728 {
729 DPRINT("VideoPortSetRegistryParameters\n");
730 ASSERT_IRQL(PASSIVE_LEVEL);
731 return RtlWriteRegistryValue(
732 RTL_REGISTRY_ABSOLUTE,
733 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->RegistryPath.Buffer,
734 ValueName,
735 REG_BINARY,
736 ValueData,
737 ValueLength);
738 }
739
740 /*
741 * @implemented
742 */
743
744 VP_STATUS STDCALL
745 VideoPortGetVgaStatus(
746 IN PVOID HwDeviceExtension,
747 OUT PULONG VgaStatus)
748 {
749 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
750
751 DPRINT("VideoPortGetVgaStatus\n");
752
753 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
754 if (KeGetCurrentIrql() == PASSIVE_LEVEL)
755 {
756 if (DeviceExtension->AdapterInterfaceType == PCIBus)
757 {
758 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
759 /* Assumed for now */
760 *VgaStatus = 1;
761 return NO_ERROR;
762 }
763 }
764
765 return ERROR_INVALID_FUNCTION;
766 }
767
768 /*
769 * @implemented
770 */
771
772 PVOID STDCALL
773 VideoPortGetRomImage(
774 IN PVOID HwDeviceExtension,
775 IN PVOID Unused1,
776 IN ULONG Unused2,
777 IN ULONG Length)
778 {
779 static PVOID RomImageBuffer = NULL;
780 PEPROCESS CallingProcess;
781 PEPROCESS PrevAttachedProcess;
782
783 DPRINT("VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
784 HwDeviceExtension, Length);
785
786 /* If the length is zero then free the existing buffer. */
787 if (Length == 0)
788 {
789 if (RomImageBuffer != NULL)
790 {
791 ExFreePool(RomImageBuffer);
792 RomImageBuffer = NULL;
793 }
794 return NULL;
795 }
796 else
797 {
798 /*
799 * The DDK says we shouldn't use the legacy C0000 method but get the
800 * rom base address from the corresponding pci or acpi register but
801 * lets ignore that and use C0000 anyway. We have already mapped the
802 * bios area into memory so we'll copy from there.
803 */
804
805 /* Copy the bios. */
806 Length = min(Length, 0x10000);
807 if (RomImageBuffer != NULL)
808 {
809 ExFreePool(RomImageBuffer);
810 }
811
812 RomImageBuffer = ExAllocatePool(PagedPool, Length);
813 if (RomImageBuffer == NULL)
814 {
815 return NULL;
816 }
817
818 IntAttachToCSRSS(&CallingProcess, &PrevAttachedProcess);
819 RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
820 IntDetachFromCSRSS(&CallingProcess, &PrevAttachedProcess);
821
822 return RomImageBuffer;
823 }
824 }
825
826 /*
827 * @implemented
828 */
829
830 BOOLEAN STDCALL
831 VideoPortScanRom(
832 IN PVOID HwDeviceExtension,
833 IN PUCHAR RomBase,
834 IN ULONG RomLength,
835 IN PUCHAR String)
836 {
837 ULONG StringLength;
838 BOOLEAN Found;
839 PUCHAR SearchLocation;
840
841 DPRINT("VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String);
842
843 StringLength = strlen(String);
844 Found = FALSE;
845 SearchLocation = RomBase;
846 for (SearchLocation = RomBase;
847 !Found && SearchLocation < RomBase + RomLength - StringLength;
848 SearchLocation++)
849 {
850 Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength);
851 if (Found)
852 {
853 DPRINT("Match found at %p\n", SearchLocation);
854 }
855 }
856
857 return Found;
858 }
859
860 /*
861 * @implemented
862 */
863
864 BOOLEAN STDCALL
865 VideoPortSynchronizeExecution(
866 IN PVOID HwDeviceExtension,
867 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
868 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
869 OUT PVOID Context)
870 {
871 BOOLEAN Ret;
872 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
873 KIRQL OldIrql;
874
875 switch (Priority)
876 {
877 case VpLowPriority:
878 Ret = (*SynchronizeRoutine)(Context);
879 break;
880
881 case VpMediumPriority:
882 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
883 if (DeviceExtension->InterruptObject == NULL)
884 Ret = (*SynchronizeRoutine)(Context);
885 else
886 Ret = KeSynchronizeExecution(
887 DeviceExtension->InterruptObject,
888 SynchronizeRoutine,
889 Context);
890 break;
891
892 case VpHighPriority:
893 OldIrql = KeGetCurrentIrql();
894 if (OldIrql < SYNCH_LEVEL)
895 OldIrql = KfRaiseIrql(SYNCH_LEVEL);
896
897 Ret = (*SynchronizeRoutine)(Context);
898
899 if (OldIrql < SYNCH_LEVEL)
900 KfLowerIrql(OldIrql);
901 break;
902
903 default:
904 Ret = FALSE;
905 }
906
907 return Ret;
908 }
909
910 /*
911 * @unimplemented
912 */
913
914 BOOLEAN STDCALL
915 VideoPortDDCMonitorHelper(
916 PVOID HwDeviceExtension,
917 /*PI2C_FNC_TABLE*/PVOID I2CFunctions,
918 PUCHAR pEdidBuffer,
919 ULONG EdidBufferSize
920 )
921 {
922 DPRINT1("VideoPortDDCMonitorHelper() - Unimplemented.\n");
923 return FALSE;
924 }
925
926 /*
927 * @unimplemented
928 */
929
930 VP_STATUS STDCALL
931 VideoPortEnumerateChildren(
932 IN PVOID HwDeviceExtension,
933 IN PVOID Reserved)
934 {
935 DPRINT1("VideoPortEnumerateChildren(): Unimplemented.\n");
936 return NO_ERROR;
937 }
938
939 /*
940 * @unimplemented
941 */
942
943 VP_STATUS STDCALL
944 VideoPortCreateSecondaryDisplay(
945 IN PVOID HwDeviceExtension,
946 IN OUT PVOID *SecondaryDeviceExtension,
947 IN ULONG Flag)
948 {
949 DPRINT1("VideoPortCreateSecondaryDisplay: Unimplemented.\n");
950 return NO_ERROR;
951 }
952
953 /*
954 * @implemented
955 */
956
957 BOOLEAN STDCALL
958 VideoPortQueueDpc(
959 IN PVOID HwDeviceExtension,
960 IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
961 IN PVOID Context)
962 {
963 return KeInsertQueueDpc(
964 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject,
965 (PVOID)CallbackRoutine,
966 (PVOID)Context);
967 }
968
969 /*
970 * @unimplemented
971 */
972
973 PVOID STDCALL
974 VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject)
975 {
976 DPRINT1("VideoPortGetAssociatedDeviceExtension: Unimplemented.\n");
977 return NULL;
978 }
979
980 /*
981 * @implemented
982 */
983
984 VP_STATUS STDCALL
985 VideoPortGetVersion(
986 IN PVOID HwDeviceExtension,
987 IN OUT PVPOSVERSIONINFO VpOsVersionInfo)
988 {
989 RTL_OSVERSIONINFOEXW Version;
990
991 Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
992 if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO))
993 {
994 #if 1
995 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version)))
996 {
997 VpOsVersionInfo->MajorVersion = Version.dwMajorVersion;
998 VpOsVersionInfo->MinorVersion = Version.dwMinorVersion;
999 VpOsVersionInfo->BuildNumber = Version.dwBuildNumber;
1000 VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor;
1001 VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor;
1002 return NO_ERROR;
1003 }
1004 return ERROR_INVALID_PARAMETER;
1005 #else
1006 VpOsVersionInfo->MajorVersion = 5;
1007 VpOsVersionInfo->MinorVersion = 0;
1008 VpOsVersionInfo->BuildNumber = 2195;
1009 VpOsVersionInfo->ServicePackMajor = 4;
1010 VpOsVersionInfo->ServicePackMinor = 0;
1011 return NO_ERROR;
1012 #endif
1013 }
1014
1015 return ERROR_INVALID_PARAMETER;
1016 }
1017
1018 /*
1019 * @unimplemented
1020 */
1021
1022 BOOLEAN STDCALL
1023 VideoPortCheckForDeviceExistence(
1024 IN PVOID HwDeviceExtension,
1025 IN USHORT VendorId,
1026 IN USHORT DeviceId,
1027 IN UCHAR RevisionId,
1028 IN USHORT SubVendorId,
1029 IN USHORT SubSystemId,
1030 IN ULONG Flags)
1031 {
1032 DPRINT1("VideoPortCheckForDeviceExistence: Unimplemented.\n");
1033 return TRUE;
1034 }
1035
1036 /*
1037 * @unimplemented
1038 */
1039
1040 VP_STATUS STDCALL
1041 VideoPortRegisterBugcheckCallback(
1042 IN PVOID HwDeviceExtension,
1043 IN ULONG BugcheckCode,
1044 IN PVOID Callback,
1045 IN ULONG BugcheckDataSize)
1046 {
1047 DPRINT1("VideoPortRegisterBugcheckCallback(): Unimplemented.\n");
1048 return NO_ERROR;
1049 }
1050
1051 /*
1052 * @implemented
1053 */
1054
1055 LONGLONG STDCALL
1056 VideoPortQueryPerformanceCounter(
1057 IN PVOID HwDeviceExtension,
1058 OUT PLONGLONG PerformanceFrequency OPTIONAL)
1059 {
1060 LARGE_INTEGER Result;
1061
1062 DPRINT("VideoPortQueryPerformanceCounter\n");
1063 Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
1064 return Result.QuadPart;
1065 }